-
New Feature
-
Resolution: Duplicate
-
Minor
-
None
-
None
-
None
I am currently trying to check in a plugin if an item contains specific metadata, which a player or admin can specify by providing an ItemStack, similar to minecraft's testFor command: In minecraft they parse the nbt data from the command and then check if the data of entities contains the same data. (their implementation can be found here: GameProfileSerializer.a(NBTBase paramNBTBase1, NBTBase paramNBTBase2, boolean paramBoolean))
This is different to ItemStack.isSimilar or MetaData.equals because those check for equality, while I am interested in checking if an item has certain data, specified by a player or admin. Matching items are however allowed to additionally have other data. Example: If the specified MetaData contains enchantments, then it checks if the MetaData of other items contains those enchantments, without checking if all their enchantments are the same.
One could write and maintain the code which checks for all the different meta data attributes (for all the different item types, etc.). I am trying to avoid doing that in my plugin. It would be nice to have that directly in craftbukkit instead, where it could be easily maintained whenever new metadata is added.
Currently I am using MetaData.serialize to get a Map representation of the ItemStack's metadata and then go through that map similar to how GameProfileSerializer.a(NBTBase paramNBTBase1, NBTBase paramNBTBase2, boolean paramBoolean) works.
This however has a few drawbacks as well:
- It relies on the serialization only using Maps and Lists as container objects (doesn't seem to be a problem for MetaData though). However, in principal any other ConfigurationSerializable object could be used here as well in the future. ItemStack for example inserts the MetaData object directly into its serialization.
- Serialization requires copying (and compressing) of all the data, while the actual check, if certain data is there, would not require that.
- Serialization puts all the 'internal' (custom) item data into one compressed String. So checking if the MetaData contains the same custom data of the given MetaData is not possible. If MetaData had a dedicated 'contains' method, it could directly check in the unhandledTags map and not have this problem.
Now, I am proposing a method MetaData#contains(MetaData otherData, boolean checkListsContain) which checks if the MetaData contains the given other MetaData. With the additional boolean parameter one can decide whether to check if lists (ex. lore, ..) are completely equal, or whether it checks if the lists contain the entries which can be found in the corresponding lists of the given other MetaData. (Similar to the boolean parameter in GameProfileSerializer.a(NBTBase paramNBTBase1, NBTBase paramNBTBase2, boolean paramBoolean)).
The implementation would then check for every data in the given otherData, if the MetaData contains the data.
Example: if (otherData.hasDisplayName()) return this.hasDisplayName() && this.getDisplayName().equals(otherData.getDisplayName())
Example for lore: if (otherData.hasLore()) return this.hasLore() && checkListContains ? this.getLore().containsAll(otherData.getLore()) : this.getLore().equals(otherData.getLore())
The unhandledTags could be compared by using minecraft's GameProfileSerializer.a(NBTBase paramNBTBase1, NBTBase paramNBTBase2, boolean paramBoolean) method.
I would be willing to create a pull request for this if you would be willing to accept such an addition.
- duplicates
-
SPIGOT-7828 MC 1.20.5+: Item component predicate API + use for Merchant trades
- Open