[SPIGOT-4028] Legacy items with data values not being converted correctly Created: 16/Jul/18 Updated: 18/Jul/18 Resolved: 18/Jul/18 |
|
| Status: | Resolved |
| Project: | Spigot |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Minor |
| Reporter: | blablubbabc | Assignee: | Unassigned |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | Material, MaterialData, serialization | ||
| Version: | This server is running CraftBukkit version git-Spigot-4520628-84676f3 (MC: 1.13-pre7) (Implementing API version 1.13-pre7-R0.1-SNAPSHOT) |
| Description |
|
Items that have beend defined by material+data value (example colored wool) in the past, are not getting converted correctly in various situations. I have tested this for the case of bukkit's ItemStack serialization, but this should also affect any items that get created via new ItemStack(type, amount, dataValue) and any items created via the MaterialData classes. Edit: I did some more testing: It seems that the items get 'lazily' converted once they are converted to a corresponding nms ItemStack (see CraftItemStack#asNMSCopy). I have update the below example accodingly. However, this lazy conversion doesn't work for deserialized items. I will outline what I think is the cause of the issue and possible solutions at the end of this ticket. Test plugin: package de.blablubbabc.test2; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; public class Test extends JavaPlugin implements Listener { public static Test INSTANCE = null; @Override public void onEnable() { INSTANCE = this; Bukkit.getPluginManager().registerEvents(this, this); if (Bukkit.getVersion().contains("1.12")) { this.getLogger().info("Saving .."); ItemStack saved = new ItemStack(Material.WOOL, 1, (byte) 14); this.getLogger().info("" + saved); this.getConfig().set("test", saved); this.saveConfig(); } else { this.getLogger().info("Loading .."); ItemStack loaded = this.getConfig().getItemStack("test"); this.getLogger().info("" + loaded); this.getLogger().info("Saving loaded itemstack.."); this.getConfig().set("test", loaded); this.saveConfig(); } } @Override public void onDisable() { INSTANCE = null; } @EventHandler void onPlayerJoin(PlayerJoinEvent event) { Bukkit.getScheduler().runTaskLater(this, () -> { event.getPlayer().getInventory().addItem(new ItemStack(Material.WOOL, 1, DyeColor.BLUE.getWoolData())); // works event.getPlayer().getInventory().addItem(new Wool(DyeColor.PINK).toItemStack(1)); // works event.getPlayer().getInventory().addItem(this.getConfig().getItemStack("test")); }, 1L); } } name: Test
version: '1.0'
description: Testing some stuff
main: de.blablubbabc.test2.Test
This is meant to simulate a plugin that uses bukkit's ItemStack serialization to save and load items. To simulate the updating to 1.13, this first gets run on a 1.12.2 spigot server: There it will create and save a red wool item. Any other items that have been defined via data value and split into separate items in 1.13 should be affected by this as well. test: ==: org.bukkit.inventory.ItemStack type: WOOL damage: 14 And a joining player will receive a red wool item as expected. Now consider the server being updated to 1.13. The plugin gets run as is (assuming forward compatibility) and attempts to load the previously saved red wool ItemStack from the config. test:
==: org.bukkit.inventory.ItemStack
v: 1513
type: WHITE_WOOL
meta:
==: ItemMeta
meta-type: UNSPECIFIC
Damage: 14
And the item given to a joining player will be a white wool item. Expected behavior: The ItemStack should probably get converted at some point to a RED_WOOL item. Currently it seems to interpret those legacy data values as damage values (even though the item is not considered damageable in MC 1.13), and not convert them. Related to this, but more of a 'feature request': Edit: Possible cause of the issue: So possible solutions might be:
Edit2: Actually, if I think about this a bit more, and if I understand the effect of the bytecode conversion stuff correctly, there might still be potential of old plugins breaking with this, if deserialized itemstacks get converted..: Bug reports which do not 1) contain a declaration of testing in Vanilla and without plugins, or 2) in the case of plugin API bugs, contain a minimal reproduction case (source + jar please) will be closed. Bug reports must contain step by step instructions to reproduce the bug from a clean server install with no assumptions or prior knowledge. Also make sure you include the full output of /version in your report. Please copy and paste this statement to the bottom of your report to indicate that you have read and understood it. |
| Comments |
| Comment by blablubbabc [ 18/Jul/18 ] |
|
Thanks |
| Comment by md_5 [ 18/Jul/18 ] |
|
The system is not going to be entirely rewritten. >Not having to deal with mixture of legacy and modern items inside bukkit and inside plugins (simpler implementations and less prone to issues overall). Plugins don't have to deal with this, and Bukkit barely has to deal with it (serialization is literally it). |
| Comment by blablubbabc [ 18/Jul/18 ] |
|
Since the discussion of the various alternatives seems to be around which behavior of old plugins to break and which to preserve, I ended up doing some brain storming: If this were possible and there are no other big issues I am currently missing (which I guess there are..), this would have the following advantages:
Remaining issues I can think of right now:
Am I missing something? |
| Comment by md_5 [ 18/Jul/18 ] |
|
Option 3 is closest to what I would implement, but it needs some additional testing regarding other things (namely spawn eggs and actual durable items) |
| Comment by blablubbabc [ 16/Jul/18 ] |
|
> Pull request welcome Sadly I don't have any time to look into this right now > See UnsafeValues, already exists Oh, nice. Didn't see that this was already available from within the API. Thanks! |
| Comment by md_5 [ 16/Jul/18 ] |
|
Related to this, but more of a 'feature request': See UnsafeValues, already exists |
| Comment by md_5 [ 16/Jul/18 ] |
|
Pull request welcome |