[SPIGOT-6257] Items with boolean-literal-like Strings in PersistentDataContainer are deserialized as booleans Created: 28/Nov/20 Updated: 26/May/24 Resolved: 26/May/24 |
|
Status: | Resolved |
Project: | Spigot |
Component/s: | None |
Affects Version/s: | None |
Fix Version/s: | None |
Type: | Bug | Priority: | Minor |
Reporter: | Dmitry Chankov | Assignee: | Unassigned |
Resolution: | Fixed | Votes: | 2 |
Labels: | ConfigurationSerializable, PersistentDataContainer, deserialization, itemstack |
Attachments: |
![]() |
Version: | This server is running CraftBukkit version git-Spigot-a19903d-e1ebdd9 (MC: 1.16.4) (Implementing API version 1.16.4-R0.1-SNAPSHOT) |
Guidelines Read: | Yes |
Description |
public void onEnable() { File saveFile = new File(getDataFolder(), "test.yml"); try { FileConfiguration configuration = new YamlConfiguration(); ItemStack item = new ItemStack(Material.STONE); ItemMeta meta = item.getItemMeta(); meta.getPersistentDataContainer().set(new NamespacedKey(this, "value"), PersistentDataType.STRING, "TRUE"); item.setItemMeta(meta); configuration.set("item", item); configuration.save(saveFile); // SAVED getLogger().info(configuration.saveToString()); } catch (IOException e) { e.printStackTrace(); } try { FileConfiguration configuration = new YamlConfiguration(); configuration.load(saveFile); // LOADED getLogger().info(configuration.saveToString()); } catch (IOException | InvalidConfigurationException e) { e.printStackTrace(); } }
Output: [20:34:51] [Server thread/INFO]: [TestPlugin] item:
==: org.bukkit.inventory.ItemStack
v: 2584
type: STONE
meta:
==: ItemMeta
meta-type: UNSPECIFIC
PublicBukkitValues:
testplugin:value: 'TRUE'
[20:34:51] [Server thread/INFO]: [TestPlugin] item:
==: org.bukkit.inventory.ItemStack
v: 2584
type: STONE
meta:
==: ItemMeta
meta-type: UNSPECIFIC
PublicBukkitValues:
testplugin:value: 1b
|
Comments |
Comment by Marvin Rieple [ 26/May/24 ] |
Can no longer reproduce in 1.20.6. Got fixed in 1.20.2 with this commit: f0661c3514a |
Comment by PikaMug [ 25/Jul/22 ] |
Still an issue on CraftBukkit version 3553-Spigot-14a2382-ef09464 (MC: 1.19) (Implementing API version 1.19-R0.1-SNAPSHOT) |
Comment by blablubbabc [ 10/Mar/21 ] |
This issue not only affects custom plugin data inside the PersistentDataContainer, but also items with BlockStateTag. For example: ItemStack itemStack = new ItemStack(Material.CAMPFIRE); ItemMeta itemMeta = itemStack.getItemMeta(); BlockData data = Material.CAMPFIRE.createBlockData(); ((Campfire) data).setLit(false); ((BlockDataMeta) itemMeta).setBlockData(data); itemStack.setItemMeta(itemMeta); Serializing this item to a Yaml config will produce: ==: org.bukkit.inventory.ItemStack v: 1976 type: CAMPFIRE meta: ==: ItemMeta meta-type: TILE_ENTITY BlockStateTag: waterlogged: 'false' signal_fire: 'false' lit: 'false' facing: north blockMaterial: CAMPFIRE Deserializing the item from this will produce an ItemStack which then has this data internally (the following is the output of serializing the deserialized item again): v: 1976 type: CAMPFIRE meta: ==: ItemMeta meta-type: TILE_ENTITY BlockStateTag: waterlogged: 0b signal_fire: 0b lit: 0b facing: north blockMaterial: CAMPFIRE These two items will also no longer be considered equal. |
Comment by Bjarne Koll [ 13/Dec/20 ] |
@blablubbabc my first ideas of a fix would look like this: https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/pull-requests/774/overview |
Comment by blablubbabc [ 13/Dec/20 ] |
As far as I understand, boolean nbt values are already 'escaped' in the yaml output due to them being represented as 0b and 1b according to above serialization output. The only thing missing is to check for this explicit boolean representation during deserialization, and then avoid using the result of the Mojang parser if it parses a String as boolean NBT value (similar as for integers). |
Comment by Bjarne Koll [ 13/Dec/20 ] |
Yeah that may actually be the best solution for this issue, similar to how we are serializing doubles and floats right now I believe. Tho maybe simply escaping true and false directly and returning them as a string might be the most useful thing. |
Comment by blablubbabc [ 12/Dec/20 ] |
I believe that the issue is actually in the use of the MojangParser (Mojang's parser for the Json-like SNBT syntax) (ref: https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/browse/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java#84). If I create a quick test plugin which simply writes and reloads the String value "TRUE" from a yaml config, I get back the actual String value (because it is actually escaped with quotes, like you noted). Plugin: https://pastebin.com/MkzDk2Vc Output: [Server thread/INFO]: [TestPlugin2] Enabling TestPlugin2 v1.0 [Server thread/INFO]: [TestPlugin2] Value of 'some key': TRUE , type: java.lang.String Edit: The same issue has already existed in the past for integer values as well (https://hub.spigotmc.org/jira/browse/SPIGOT-4577). The fix has been to escape them when serializing them to yaml (via the "i" suffix) (https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/8059a937eb6a3e160e1421206e46d24cc5b70687). A similar approach could be applied for boolean values ("b" suffix, which it already produces due to that being Mojangs representation). When deserializing the values, we would need to check if the parsed value matches that boolean representation, and otherwise assume that it is actually a String (instead of passing it to the Mojang parser). |
Comment by Airtheon Thesalion [ 12/Dec/20 ] |
This seems more like an issue with YAML itself (and then of course the parser that the API uses). The solution for you is to explicitly write this to YAML using quotes, so '"TRUE"' instead of just 'TRUE'. Or to just use another word that means the same thing, but is not covered by the regex that YAML uses. For example 'Affirmative'. Yes, it might be possible to fix it, by adding a check using this regex, somewhere deep inside the PersistentData Primitives, as String is one of those Primitives, but this would not be worth the effort, for such a niche usecase. |