Completes the data attachment API with client-server syncing capabilities.
## Motivation
The existing API works great for attaching data to game objects, be they serverside or clientside, but lacks any ability to synchronize between the two.
A mod that wants to add a "thirst" mechanic can easily do so on the server side by attaching an integer to every player. However, the mod may also want to use this information to render additional HUD elements on the client. Currently, informing the client of this data can only be done manually, which is cumbersome, error-prone, and is much better-suited as an API feature.
## API Changes
The API doesn't change a lot (at least compared to the implementation), with a few new methods and one new class.
One new method has been added to `AttachmentRegistry.Builder`, namely `syncWith`. It declares that an attachment type may be synchronized with some clients, and takes a `PacketCodec` to encode attachment data over the network, as well as an element of the new `AttachmentSyncPredicate` interface.
This interface extends `BiPredicate<AttachmentTarget, ServerPlayerEntity>` to allow for user-defined predicates, and provides some common presets:
* `all()`: attachment data will be synchronized with all clients (that track the target).
* `targetOnly()`: attachment data will only be synchronized with the target it is attached to, when it is a player. If the target is not a player, it won't be synchronized with any client.
* `allButTarget()`: reverse of the above. For non-player targets, attachment data will be synchronized with all clients.
**NOTE**: for a user-defined condition, whether attachment data is synchronized with a client can change at runtime (e.g. "sync only with operators" when a player changes operator status). A specialized method to "refresh" data was considered, but in the end discarded due to complexity. It falls to individual mods to handle these edge cases.
AttachmentType also gets one new `isSynced` method to know whether a given attachment type can be synced.
## Usage
Here is how one could register an attachment for a "thirst" meter like mentioned above.
```java
public static final AttachmentType<Integer> THIRST = AttachmentRegistry.<Integer>builder()
.initializer(() -> 20) // start with a default value like hunger
.persistent(Codec.INT) // persist across restarts
.syncWith(PacketCodecs.VAR_INT.cast(), AttachmentSyncPredicate.targetOnly()) // only the player's own client needs the value for rendering
.buildAndRegister(Identifier.of("modid", "thirst"));
```
* allow data-attachment on ProtoChunks
- moved interfaceInjection from WorldChunk to Chunk
- dataAttachment saving on ProtoChunks in ChunkSerializer
- copy attachment from ProtoChunk to WorldChunk on creation.
- make WrapperProtoChunk wrap attachment calls to WorldChunk
* add test for data-attachment on ProtoChunks, and extend testmod.
* code style and license headers
* fix typos in javadoc
* extend testmod to test setting attachment during worldgen.
* code formatting
* fix testmod: don't crash when feature isn't placed (i.e. on GameTest server)
* add warning when adding persistent attachment to chunk with status EMPTY.
* update javadoc
* update javadoc to reference ServerLivingEntityEvents#MOB_CONVERSION
(cherry picked from commit 32782cfdc7)
* Data Attachment API
* javadoc
* Remove AttachmentSerializer & independent syncability and persistence
- removed AttachmentSerializer in favor of codecs
- renamed serializability to "persistence"
- made persistence and syncability independent switches
- reworked convenience registry methods to use Suppliers from the get-go
* Move some serialization-related methods to impl
- changed logger name
* rename Attachment to AttachmentType
* Added DefaultedAttachmentType and reworded Javadoc
* add warning in getAttached
* javadoc
* fix defaulted API
* Add unit tests
* remove DefaultedAttachmentType, add helper methods
bikeshedding inbound
* add more unit tests
* add testmod
it works
* stash syncing for a further PR
* missed license header
* address most reviews
* more reviews
* naming convention
* fix tyop
* fix invalid file name error
* simplify API in the absence of sync
It was established that the presence of a codec might be useful for other things than persistence, and while this seems to couple the two, the API can be changed later in a backward-compatible way if need be.
* couple codec with persistence
committing to the change I mentioned previously
* little fixes
* Fix mixins + requests
- Copy attachments on entity copy,& with a customizable flag in the case of player respawn
- Call relevant change-notifying methods when calling setAttached on BEs and chunks
- Change persistence key
- Fix mixin visibility
* Write tests for entity copy
* replace mixin by COPY_FROM event
* missed license header
* more advanced copy mechanics
- attachments require an EntityCopyHandler to be copied across entities
- a copy handler is automatically derived if there's a codec
- updated javadoc for chunk and BE targets
* Revert "more advanced copy mechanics"
This reverts commit 3f53b554fb.
* replaced complicated API by a stern warning
- also handled cross-world entity teleportation
* add gametest
* fix compilation
* flipped boolean
* forgot some more bools to flip
* requests
* fix FMJ
* fix BE mixin and add gametest
* add client player entity copying
* Use new mob conversion event
---------
Co-authored-by: modmuss <modmuss50@gmail.com>
(cherry picked from commit 25e1b4769d)