-
Notifications
You must be signed in to change notification settings - Fork 434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Data Attachment API #3476
Data Attachment API #3476
Conversation
...ttachment-api-v1/src/main/java/net/fabricmc/fabric/api/attachment/v1/AttachmentRegistry.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like a reasonable start, it should be nice and easy to write some good unit tests for this, alongside a testmod.
...-attachment-api-v1/src/main/java/net/fabricmc/fabric/api/attachment/v1/AttachmentTarget.java
Outdated
Show resolved
Hide resolved
...c-data-attachment-api-v1/src/main/java/net/fabricmc/fabric/api/attachment/v1/Attachment.java
Outdated
Show resolved
Hide resolved
...c-data-attachment-api-v1/src/main/java/net/fabricmc/fabric/api/attachment/v1/Attachment.java
Outdated
Show resolved
Hide resolved
- 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
...achment-api-v1/src/main/java/net/fabricmc/fabric/impl/attachment/AttachmentRegistryImpl.java
Outdated
Show resolved
Hide resolved
- changed logger name
We need to figure out a couple things regarding how the API of
Naturally, many of these cons can be solved or at least alleviated with suitable helper methods. In 1, a An in-between may be to provide partial/optional auto-initialization capability. For example, an optional initializer that, if given, is called when there is no attached data as in 1. Or, for a less intrusive alternative, an optional 'default' initializer that is used as the parameter of In any case, the choice should be guided by which paradigm will cause the least boilerplate in the majority of cases. Whatever behavior |
After some discussion, I have implemented the following compromise: By default, As a result, whether the attachment automatically initializes or not, the call site looks like |
What if I registered my I can suggest the following:
For now I prefer option 2, but it's not ideal, so I'd like to think more... |
I mentioned this potential pitfall, and if you check, the (normal) getAttached implementation issues a warning and auto-inits if you pass a defaulted one. But you're right about bad extensibility, the cursory amount of thought I've given syncing tells me that is quickly going to be unsustainable, so back to the drawing board. That being said, the issue with 2 is that static checkers will complain about nullability even for defaulted attachments (could be solved with a getAttachedOrThrow). The problem with 3 is overarching, and it's that I'm unsure how common defaulted will be vs non-defaulted, and I don't want to have a longer method name be used for the most common case. |
fabric-data-attachment-api-v1/src/testmod/resources/fabric.mod.json
Outdated
Show resolved
Hide resolved
...nt-api-v1/src/testmod/java/net/fabricmc/fabric/test/attachment/PersistentAttachmentTest.java
Outdated
Show resolved
Hide resolved
...tachment-api-v1/src/test/java/net/fabricmc/fabric/test/attachment/CommonAttachmentTests.java
Show resolved
Hide resolved
fabric-data-attachment-api-v1/src/main/resources/fabric.mod.json
Outdated
Show resolved
Hide resolved
fabric-data-attachment-api-v1/src/main/resources/fabric-data-attachment-api-v1.mixins.json
Outdated
Show resolved
Hide resolved
...chment-api-v1/src/main/java/net/fabricmc/fabric/mixin/attachment/AttachmentTargetsMixin.java
Outdated
Show resolved
Hide resolved
...chment-api-v1/src/main/java/net/fabricmc/fabric/mixin/attachment/AttachmentTargetsMixin.java
Outdated
Show resolved
Hide resolved
...ttachment-api-v1/src/main/java/net/fabricmc/fabric/impl/attachment/AttachmentTargetImpl.java
Outdated
Show resolved
Hide resolved
...ment-api-v1/src/main/java/net/fabricmc/fabric/impl/attachment/AttachmentSerializingImpl.java
Outdated
Show resolved
Hide resolved
...ment-api-v1/src/main/java/net/fabricmc/fabric/impl/attachment/AttachmentPersistentState.java
Outdated
Show resolved
Hide resolved
...a-attachment-api-v1/src/main/java/net/fabricmc/fabric/mixin/attachment/BlockEntityMixin.java
Outdated
Show resolved
Hide resolved
...a-attachment-api-v1/src/main/java/net/fabricmc/fabric/mixin/attachment/ServerWorldMixin.java
Outdated
Show resolved
Hide resolved
...chment-api-v1/src/main/java/net/fabricmc/fabric/mixin/attachment/AttachmentTargetsMixin.java
Show resolved
Hide resolved
...a-attachment-api-v1/src/main/java/net/fabricmc/fabric/mixin/attachment/BlockEntityMixin.java
Outdated
Show resolved
Hide resolved
...ment-api-v1/src/main/java/net/fabricmc/fabric/impl/attachment/AttachmentPersistentState.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Glad this wasn't merged yet. Sorry for late review.
...ttachment-api-v1/src/main/java/net/fabricmc/fabric/api/attachment/v1/AttachmentRegistry.java
Show resolved
Hide resolved
...-attachment-api-v1/src/main/java/net/fabricmc/fabric/api/attachment/v1/AttachmentTarget.java
Outdated
Show resolved
Hide resolved
...-attachment-api-v1/src/main/java/net/fabricmc/fabric/api/attachment/v1/AttachmentTarget.java
Outdated
Show resolved
Hide resolved
...-attachment-api-v1/src/main/java/net/fabricmc/fabric/api/attachment/v1/AttachmentTarget.java
Outdated
Show resolved
Hide resolved
...-attachment-api-v1/src/main/java/net/fabricmc/fabric/api/attachment/v1/AttachmentTarget.java
Outdated
Show resolved
Hide resolved
...-attachment-api-v1/src/main/java/net/fabricmc/fabric/api/attachment/v1/AttachmentTarget.java
Outdated
Show resolved
Hide resolved
...-attachment-api-v1/src/main/java/net/fabricmc/fabric/api/attachment/v1/AttachmentTarget.java
Outdated
Show resolved
Hide resolved
...achment-api-v1/src/main/java/net/fabricmc/fabric/impl/attachment/AttachmentRegistryImpl.java
Outdated
Show resolved
Hide resolved
...a-attachment-api-v1/src/main/java/net/fabricmc/fabric/mixin/attachment/BlockEntityMixin.java
Show resolved
Hide resolved
...a-attachment-api-v1/src/main/java/net/fabricmc/fabric/mixin/attachment/ServerWorldMixin.java
Outdated
Show resolved
Hide resolved
...a-attachment-api-v1/src/main/java/net/fabricmc/fabric/mixin/attachment/BlockEntityMixin.java
Outdated
Show resolved
Hide resolved
Two notes:
|
* 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 3f53b55. * 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 25e1b47)
Trying to revive #2172, with some ideas from @Technici4n's NF implementation.
The Data Attachment API provides a unified and convenient way for modders to attach arbitrary pieces of data to various game objects (as of writing: entities, block entities, worlds and chunks). Importantly, all of the logic specific to each game object type is abstracted away behind an interface and is not the modder's concern.
Additionally, attached data can optionally be made to persist across server restarts. A subsequent PR should work to implement a robust and flexible client-server syncing mechanism, staying true to the API's "target type should not matter in the API" philosophy.
API Overview
The API contains three classes:
AttachmentType
,AttachmentRegistry
andAttachmentTarget
.An
AttachmentType<A>
is a type of way to attach objects of typeA
to game objects. It specifies whether the attachments are persistent and/or synced, and if one of these is enabled, provides aCodec<A>
for convenient encoding/decoding. The API assumes the objects of typeA
are immutable or, more generally, do not share any state with other objects used in separate attachments.Attachment types are created and registered using
AttachmentRegistry
. This class provides simplecreate
,createDefaulted
andcreatePersistent
methods for quick creation and registration of attachments, but when finer control is needed, provides anAttachmentRegistry.Builder
to set each desired property separately.Finally,
AttachmentTarget
defines the game objects to which data can be attached. Currently,Entity
,BlockEntity
,ServerWorld
andWorldChunk
are made to implement it using interface injection and mixin. It provides methods for getting, setting, modifying and removing attachments, as well ashasAttached
for check if an attachment exists.Example use
Attachment types are created and registered using methods in
AttachmentRegistry
, and should be stored instatic final
fields, like so:Once attachments have been registered, they can be used on all
AttachmentTarget
s. In this example, we assume all of the relevant targets start with no attachments.Future enhancements
Client-server syncing would be a great feature to have, but has been left out of this PR on account of being a lot trickier than the rest, and not as essential. It should instead be the subject of a future PR. However, this feature is important because syncing rendering data with the client seems like a very obvious addition to this API. I'll outline a couple of the constraints any potential addition should try to fit into:
AttachmentTarget
.Maintainer note: the unit tests test persistence for entities and blockentities as those can be mocked without too much effort, but mocking worlds and chunks is such a pain that I opted to make those into a separate testmod. It works by launching a server (on the same world) twice from the client to check the saving/loading.
TODO:
Implement server-client syncingScrapped in favor of future PR