So are DataProcessors equivalent to keys? @Tzk
A DataProcessor
is the actual implementation to retrieving/setting a DataManipulator
to and from a DataHolder
, since a DataHolder
can be an ItemStack
, an Entity
, a TileEntity
and even a BlockState
. If there isn’t a DataProcessor
implemented and registered (including a ValueProcessor
for each of the Value
s provided by the DataManipulator
), then the DataManipulator
is non-functional. This is true for SpongeAPI provided DataManipulator
s only though, since custom DataManipulator
s are meant to be translated to a DataContainer
and stored customarily to each DataHolder
if possible. BlockState
s will likely not support custom data for the foreseeable future. Location
s however might sometime later this year after the core implementation is done.
Blood just bumped common ref, I can confirm its not working after your velocity implementation commit
[SignData] How to set text in the sign (The sign is in the world)?
Location
is a DataHolder
, so you can just offer a List<Text>
to it using the Keys.SIGN_LINES
key.
The docs page is not yet ready, yet you may refer to the preview for the PR and, if that does not help, consult here again. According to the checklist above the Sign data processors are already implemented
You actually need to get the TileEntity from the location IIRC Location doesn’t forward data queries to the tile entity.
so it would be something like
Location loc = ...;
List<Text> lines = ...;
if (loc.hasTileEntity()) {
loc.getTileEntity().get().offer(Keys.SIGN_LINES, lines);
}
Ah I see, you need to have a ListValue
rather than a List
Either use the list value you get when calling get(Keys.SIGN_LINES)
or create a new ListValue
:
ListValue<Text> signLines = game.getRegistry().createValueBuilder().createListValue(Keys.SIGN_LINES, lines);
then offer the signLines
Complicated. I’ll wait. Let others do.
It would be cool if “location forwards data requests for the TileEntity”.
What? no…
final Text[] text = { Texts.of("foo"), Texts.of("bar") };
ArrayList<Text> list = Lists.newArrayList(text);
dataHolder.offer(Keys.SIGN_LINES, list);
compiles just fine. Ignore that I’m using Lists
, but it should still work just fine.
If I was to store custom data about an item, say an attribute such as “fire resistance”- would you recommend storing it in memory with the data api or separately in memory (ie: my own collection(s)) if I was to have the data persist in a database?
EDIT: @gabizou How would one go about offering custom keys/values to a DataHolder? Would I simply be able to dataHolder.offer(key, value)
? Do I have to implement anything for the values or instantiate them in a certain way? I’m currently going off of the Keys class in SpongeAPI, a little nudge in the right direction would be nice
So, I actually managed to implement the first phase of custom data tonight. Unfortunately, custom keys/values aren’t directly supported unless a DataManipulator
is already provided in the DataHolder
. The reasoning is that a Key
, let a lone a Value
, does not actually know how to serialize/deserialize itself from a DataContainer
, something that a DataManipulator
/ImmutableDataManipulator
knows how to do.
TL;DR: If you want to store a piece of custom data, offer the manipulator first. Then you can query and manipulate using keys.
If you want to store custom data, just make a data manipulator and store it. Just note that when you create custom data on ItemStack
s, you might make it impossible for that item to stack on other items unless the data is exactly the same. Also remember, because custom data is actively being serialized/deserialized you really do need to have registered your DataManipulatorBuilder
s and likewise ImmutableDataManipulatorBuilder
s (for snapshots). This will work almost always because you can’t really keep track of ItemStack
instances between events, let alone over time, unless you’re storing these things as attributes and attribute modifiers, there’s no real way around it.
Will there be an example of how to do this in the docs at some point?
I included it in my Todo List, although I cannot say when it will be finished. Just a friendly reminder to all reading: Contributions to the docs are welcome
Thanks!
Now, I’m curious- is the PR about the Data API v2 (the OP) accurate/current usage/explanation? I am interested in storing “attributes” for items (or anything for that matter) and the data api looks perfect in terms of offering/retrieving. My issue stems from if I would like to implement the same functionality locally (in my classes) would I have to do the whole mile with making manipulators etc and registering etc? (DISCLAIMER: I have not fiddled around with what you mentioned in your previous reply yet)
I want to be able get values the same way as we do with Sponge’s Keys#<some-key>
but with custom ones. What would you recommend?
EDIT 23/09/2015 @ 8:07
In external sites, people keep recommending that I utilize the Visitor pattern but I can’t help but doubt that it will actually solve my problem. Since it doesn’t do return values, only void
operations (if going off the pattern cookie-cutter, unless I’m misunderstanding it).
If you are making custom DataManipulator
s to store and retrieve from entities/items/tileentities, you will always need to have serialization setup. The same is to be said about the vanilla manipulators, all of the vanilla manipulators have their own DataManipulatorBuilder
s to deserialize the manipulator from a DataView
. In order for you to test this out though, you’d likely need to do a lot of mocking or creation of dummy DataHolder
s
You’re understanding it correctly, because the visitor pattern never really has to return anything. Data API can be used with the Visitor pattern, but it’s not really all that much favorable since Data API doesn’t follow that pattern at all.
Okay cool. I am currently designing it around primitives (well, you know the basics String/int/double and obv the primitive’s object counterparts). Although don’t want to limit the types that can be used as I may change this in the future, future proofing would be ideal. Also, I want these “attributes” to be fully optional. You know, an item could have a “soul” attachment of type String, whereas another item might not so it just wouldn’t exist in it. At the same time, I don’t want to limit the system by hard-coding every attribute as the classes would then get huge, also new items may have attributes that weren’t originally thought of. So you can see why I need a dynamic way of setting/getting these attributes (key=String identifier, and a value=some object).
To explain a little more, I would like to do the same system you guys have done where you may not know what type “strength-modifier” is, but the type is stored in a AttributeKeys#STRENGHT_MODIFIER
and of course you know how retrieval works with the data api (it’s just perfect).
If you’re pulling an id BY NAME, then you’re explicitly trying to work with it, and therefore should know the type.
I don’t need them to be applied to an ItemStack or Entity, I was just curious which would be easier to implement. If I could just make an AttributeHolder (implementation of a DataHolder) that would be great. Although for value getting/setting would I have to do anything special per-DataHolder?
Sorry, I’m not hugely familiar with the Data API (reading through right now).
EDIT 28/09/2015 @ 7:45pm EST
@gabizou (mentioning in-case you didn’t see, very interested in your take on the matter)
I was looking through Sponge, and have a question about an alternative to custom DataManipulators (I’m still on my quest to assign custom data to a player). Is it possible to just create a custom key and a value to offer to the player? All I need to do is be able to is do something like this:
Set a value (In the form of a string) for a key (i.e. "MyKey"
).
Be able to retrieve a value by supplying the key.
You first need to implement a custom DataManipulator
that contains that key and offer it, else the Key will not be recognised, if I understood gabizou correctly. Also, if you create a custom key it must implement the Key
interface.
Ok, thanks . This is still kind of confusing to me, so I think I will wait until there is a solid example somewhere before I attempt to implement this.