[SPIGOT-583] Custom Player Skull Texture NPE on Serialize Created: 17/Feb/15 Updated: 22/Jul/15 Resolved: 07/Jun/15 |
|
Status: | Closed |
Project: | Spigot |
Component/s: | None |
Affects Version/s: | None |
Fix Version/s: | None |
Type: | Bug | Priority: | Minor |
Reporter: | Nathan Wolf | Assignee: | Thinkofname |
Resolution: | Fixed | Votes: | 3 |
Labels: | None |
Description |
It is possible, with vanilla commands, to give yourself a player skull without a profile attached, that contains a custom texture. See here: http://www.dragnoz.com/custom-head-block-generator/ When serializing such an item, an NPE is thrown. I realize this is kind of a hacky thing to do, but as long as it works it'd be nice if it was supported. |
Comments |
Comment by md_5 [ 22/Jul/15 ] |
Might be best to open a new ticket. |
Comment by blablubbabc [ 22/Jul/15 ] |
Any update on this one? Just wanting to let you know that I am as well still getting reports of users still having this issue. Edit: The issue is probably caused by skull items with a profile which only has an uuid and no name. The second part of the issue would then be to properly store and restore the profile uuid (which doesn't currently get stored as far as I can tell from a quick look at the source code). |
Comment by Nathan Wolf [ 24/Jun/15 ] |
Hmm.. yeah looking at the code, I think the fix for this handled saving the full profile (yay!) but still tries to separately save the owner name, I'm guessing for backwards-compatibility. A simple check for null before adding owner name to the serialization map would probably fix this. |
Comment by Robert Pettit [ 24/Jun/15 ] |
Has this fix been pushed? I still can't save a yml file that has one of these custom heads. I am running the latest version of spigot and have recompiled my plugin with the same spigot. Here is the Stacktrace I get when the plugin tries to save the .yml Stacktrace1 2015-06-24 15:33:24 | [ERROR] Could not pass event InventoryClickEvent to AuctionHouse v1.0 2015-06-24 15:33:24 | [RAW] org.bukkit.event.EventException 2015-06-24 15:33:24 | [RAW] ?at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:310) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:502) [spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:487) [spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at net.minecraft.server.v1_8_R3.PlayerConnection.a(PlayerConnection.java:1603) [spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at net.minecraft.server.v1_8_R3.PacketPlayInWindowClick.a(SourceFile:31) [spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at net.minecraft.server.v1_8_R3.PacketPlayInWindowClick.a(SourceFile:9) [spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at net.minecraft.server.v1_8_R3.PlayerConnectionUtils$1.run(SourceFile:13) [spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_45] 2015-06-24 15:33:24 | [RAW] ?at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_45] 2015-06-24 15:33:24 | [RAW] ?at net.minecraft.server.v1_8_R3.SystemUtils.a(SystemUtils.java:19) [spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:718) [spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:367) [spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:657) [spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:560) [spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at java.lang.Thread.run(Thread.java:745) [?:1.8.0_45] 2015-06-24 15:33:24 | [RAW] Caused by: java.lang.NullPointerException: null value in entry: skull-owner=null 2015-06-24 15:33:24 | [RAW] ?at com.google.common.collect.CollectPreconditions.checkEntryNotNull(CollectPreconditions.java:33) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at com.google.common.collect.ImmutableMap.entryOf(ImmutableMap.java:135) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at com.google.common.collect.ImmutableMap$Builder.put(ImmutableMap.java:206) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.bukkit.craftbukkit.v1_8_R3.inventory.CraftMetaSkull.serialize(CraftMetaSkull.java:173) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.bukkit.craftbukkit.v1_8_R3.inventory.CraftMetaItem.serialize(CraftMetaItem.java:850) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationSerializable.representData(YamlRepresenter.java:33) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepresenter.java:94) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseRepresenter.java:156) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.representData(SafeRepresenter.java:304) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationSerializable.representData(YamlRepresenter.java:35) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepresenter.java:94) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseRepresenter.java:156) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.representData(SafeRepresenter.java:304) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationSection.representData(YamlRepresenter.java:23) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepresenter.java:94) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseRepresenter.java:156) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.representData(SafeRepresenter.java:304) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationSection.representData(YamlRepresenter.java:23) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepresenter.java:94) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseRepresenter.java:156) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.representData(SafeRepresenter.java:304) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepresenter.java:94) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.representer.BaseRepresenter.represent(BaseRepresenter.java:64) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.Yaml.dumpAll(Yaml.java:242) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.Yaml.dumpAll(Yaml.java:206) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.yaml.snakeyaml.Yaml.dump(Yaml.java:181) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.bukkit.configuration.file.YamlConfiguration.saveToString(YamlConfiguration.java:40) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at org.bukkit.configuration.file.FileConfiguration.save(FileConfiguration.java:103) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?at me.surfdudeboy.auctionhouse.YMLIO.save(YMLIO.java:904) ~[?:?] 2015-06-24 15:33:24 | [RAW] ?at me.surfdudeboy.auctionhouse.objects.AuctionListing.<init>(AuctionListing.java:68) ~[?:?] 2015-06-24 15:33:24 | [RAW] ?at me.surfdudeboy.auctionhouse.GUI.SellDialogue.createListing(SellDialogue.java:63) ~[?:?] 2015-06-24 15:33:24 | [RAW] ?at me.surfdudeboy.auctionhouse.GUI.Listeners.Execute.manipulateNewListingPage(Execute.java:183) ~[?:?] 2015-06-24 15:33:24 | [RAW] ?at me.surfdudeboy.auctionhouse.GUI.Listeners.AuctionListeners.onGUIInteract(AuctionListeners.java:89) ~[?:?] 2015-06-24 15:33:24 | [RAW] ?at sun.reflect.GeneratedMethodAccessor63.invoke(Unknown Source) ~[?:?] 2015-06-24 15:33:24 | [RAW] ?at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_45] 2015-06-24 15:33:24 | [RAW] ?at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_45] 2015-06-24 15:33:24 | [RAW] ?at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:306) ~[spigot.jar:git-Spigot-f928e7a-994b2aa] 2015-06-24 15:33:24 | [RAW] ?... 15 more There is also sometimes a stacktrace printed when moving the head around inside of a chest. stacktrace2 2015-06-24 15:52:11 | [WARN] java.lang.NullPointerException: null value in entry: skull-owner=null 2015-06-24 15:52:11 | [WARN] ?at com.google.common.collect.CollectPreconditions.checkEntryNotNull(CollectPreconditions.java:33) 2015-06-24 15:52:11 | [WARN] ?at com.google.common.collect.ImmutableMap.entryOf(ImmutableMap.java:135) 2015-06-24 15:52:11 | [WARN] ?at com.google.common.collect.ImmutableMap$Builder.put(ImmutableMap.java:206) 2015-06-24 15:52:11 | [WARN] ?at org.bukkit.craftbukkit.v1_8_R3.inventory.CraftMetaSkull.serialize(CraftMetaSkull.java:173) 2015-06-24 15:52:11 | [WARN] ?at org.bukkit.craftbukkit.v1_8_R3.inventory.CraftMetaItem.serialize(CraftMetaItem.java:850) 2015-06-24 15:52:11 | [WARN] ?at net.coreprotect.database.Logger.container_logger(Logger.java:498) 2015-06-24 15:52:11 | [WARN] ?at net.coreprotect.database.Logger.log_container(Logger.java:413) 2015-06-24 15:52:11 | [WARN] ?at net.coreprotect.consumer.Process.processContainerTransaction(Process.java:251) 2015-06-24 15:52:11 | [WARN] ?at net.coreprotect.consumer.Process.processConsumer(Process.java:91) 2015-06-24 15:52:11 | [WARN] ?at net.coreprotect.consumer.Consumer.run(Consumer.java:49) 2015-06-24 15:52:11 | [WARN] ?at java.lang.Thread.run(Thread.java:745) The skull is obtained through the following command via command block: Note that The SkullOwner was assigned to an arbitrary, random UUID. This is done to prevent new custom skulls from overwriting the texture of others. command /give @p skull 1 3 {display:{Name:"Dallas Mask"}, SkullOwner:{ Id:"60dbfcd2-4f2e-49ff-91ed-e8e6242dd0b2", Properties:{ textures: [{ Value: "eyJ0aW1lc3RhbXAiOjE0MzA2MTYwMTM2ODMsInByb2ZpbGVJZCI6IjNjZTY4YzY0OTg3NDQ4ZmRiOGIyMjZhOTk2M2M1ZjcyIiwicHJvZmlsZU5hbWUiOiJTdXJmZHVkZWJveSIsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9lNzM3ZWU1NTcwNGE2ZjRlYWMxOGJmZWVlMjIyZDc2Zjc5OWQyNGQ3MzAzNjc3NzRhNTFiZjkxYWQzYzJjIn19fQ==" }] } } } |
Comment by Nathan Wolf [ 07/Jun/15 ] |
Did this get fixed by saving the full player profile? I'm guessing not ... But hopefully asking anyway |
Comment by Nathan Wolf [ 19/Feb/15 ] |
No problem! I could've been more clear about the specific part that was broken. For the most part, the custom skulls seem to work- but if you think "oh, these are awesome, players would love to buy them", and try to put one in a shopkeeper- it will blow up on save and delete all your Shopkeepers. Same with StarterKit, or I imagine any other plugin that tries to serialize items when it saves data. |
Comment by Nathan Wolf [ 19/Feb/15 ] |
I guess I should also mention I have a PR submitted to fix this. It relies on one of my other PR's though (for general serialization of NBT data) |
Comment by Nathan Wolf [ 19/Feb/15 ] |
Here's an example stack trace of this in action, something I should have provided originally! [10:18:47] [Craft Scheduler Thread - 8/WARN]: org.apache.commons.lang.UnhandledException: Plugin Shopkeepers v1.43 generated an exception while executing task 10138 at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:56) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.NullPointerException: null value in entry: skull-owner=null at com.google.common.collect.CollectPreconditions.checkEntryNotNull(CollectPreconditions.java:33) at com.google.common.collect.ImmutableMap.entryOf(ImmutableMap.java:135) at com.google.common.collect.ImmutableMap$Builder.put(ImmutableMap.java:206) at org.bukkit.craftbukkit.v1_8_R1.inventory.CraftMetaSkull.serialize(CraftMetaSkull.java:150) at org.bukkit.craftbukkit.v1_8_R1.inventory.CraftMetaItem.serialize(CraftMetaItem.java:810) at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationSerializable.representData(YamlRepresenter.java:33) at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepresenter.java:95) at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseRepresenter.java:157) at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.representData(SafeRepresenter.java:320) at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationSerializable.representData(YamlRepresenter.java:35) at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepresenter.java:95) at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseRepresenter.java:157) at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.representData(SafeRepresenter.java:320) at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationSection.representData(YamlRepresenter.java:23) at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepresenter.java:95) at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseRepresenter.java:157) at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.representData(SafeRepresenter.java:320) at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationSection.representData(YamlRepresenter.java:23) at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepresenter.java:95) at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseRepresenter.java:157) at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.representData(SafeRepresenter.java:320) at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationSection.representData(YamlRepresenter.java:23) at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepresenter.java:95) at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseRepresenter.java:157) at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.representData(SafeRepresenter.java:320) at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationSection.representData(YamlRepresenter.java:23) at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepresenter.java:95) at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseRepresenter.java:157) at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.representData(SafeRepresenter.java:320) at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepresenter.java:95) at org.yaml.snakeyaml.representer.BaseRepresenter.represent(BaseRepresenter.java:65) at org.yaml.snakeyaml.Yaml.dumpAll(Yaml.java:271) at org.yaml.snakeyaml.Yaml.dumpAll(Yaml.java:262) at org.yaml.snakeyaml.Yaml.dumpAll(Yaml.java:234) at org.yaml.snakeyaml.Yaml.dump(Yaml.java:209) at org.bukkit.configuration.file.YamlConfiguration.saveToString(YamlConfiguration.java:40) at com.nisovin.shopkeepers.ShopkeepersPlugin.saveDataToFile(ShopkeepersPlugin.java:1128) at com.nisovin.shopkeepers.ShopkeepersPlugin.access$900(ShopkeepersPlugin.java:54) at com.nisovin.shopkeepers.ShopkeepersPlugin$10.run(ShopkeepersPlugin.java:1087) at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftTask.run(CraftTask.java:71) at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:53) ... 3 more |
Comment by Nathan Wolf [ 19/Feb/15 ] |
The NPE arises when you serialize the items. This is because they are lacking a "Name" NBT tag, and CraftMetaSkull assumes it's there. This can be worked around by just putting some random name in there, but the skull will then revert to that player's skull after serializing + deserializing. |
Comment by David McKenna [ 19/Feb/15 ] |
Using the default one they provided in the video ( https://i.imgur.com/ggXlehE.png ) with that tool, I cannot replicate your NPE and the skeleton spawns fine / item is given to me textured on git-Bukkit-3fc97ff http://i.suddenly.coffee/2015-02-19_15.13.55.png EDIT: Misread, sorry. |