[SPIGOT-1066] Serialization of custom player skull items Created: 22/Jul/15  Updated: 03/Feb/16  Resolved: 03/Feb/16

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: 11
Labels: None


 Description   

The issue: Skull items with a skull owner profile containing a custom texture, no owner name (and usually a random uuid), which can for example be created with the vanilla give command as shown below, are not properly serialized and deserialized to/from configuration files.

This ticket is probably related to SPIGOT-583. The linked ticket did only mention skull items without attached profile (and was marked as fixed).
This ticket however is about config serialization of skull items with 'custom/modified/unusual' profile, which people seem to use for creating skull items with custom textures. (This is probably what was intended by the linked ticket in the first place).

I did test this issue by using the example skull item created by the following command. Similar commands are also created by this online tool: http://www.dragnoz.com/custom-head-block-generator/

Custom skull item command

/give @p skull 1 3
{display:

Unknown macro: {Name}

,
SkullOwner:{
Id:"60dbfcd2-4f2e-49ff-91ed-e8e6242dd0b2",
Properties:{
textures:
[

Unknown macro: { Value}

]
}
}
}

Some plugin trying to store this skull item in a configuration file will experience a NPE during serialization (example at the end of this ticket).

So the first part of this issue is that craftbukkit is currently trying to store null (the custom profiles don't have an owner name) in the ImmutableMapBuilder here (which doesn't accept null as value) here: https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/browse/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java#159

The second part of this issue would then be to properly store and restore other values of the custom profile, like the uuid and the texture component (which don't get currently stored as far as I can tell from a quick look at the source code).

Error stacktrace of serialization

[15:58:45 WARN]: Exception in thread "Craft Scheduler Thread - 6"
[15:58:45 WARN]: org.apache.commons.lang.UnhandledException: Plugin Shopkeepers v1.63-SNAPSHOT generated an exception while executing task 1650
at org.bukkit.craftbukkit.v1_8_R3.scheduler.CraftAsyncTask.run(CraftAsyn
cTask.java:56)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException: null value in entry: skull-owner=null

at com.google.common.collect.CollectPreconditions.checkEntryNotNull(Coll
ectPreconditions.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_R3.inventory.CraftMetaSkull.serialize(Cra
ftMetaSkull.java:173)
at org.bukkit.craftbukkit.v1_8_R3.inventory.CraftMetaItem.serialize(Craf
tMetaItem.java:850)
at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationS
erializable.representData(YamlRepresenter.java:33)
at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepr
esenter.java:94)
at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseR
epresenter.java:156)
at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.represent
Data(SafeRepresenter.java:304)
at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationS
erializable.representData(YamlRepresenter.java:35)
at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepr
esenter.java:94)
at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseR
epresenter.java:156)
at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.represent
Data(SafeRepresenter.java:304)
at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationS
ection.representData(YamlRepresenter.java:23)
at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepr
esenter.java:94)
at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseR
epresenter.java:156)
at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.represent
Data(SafeRepresenter.java:304)
at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationS
ection.representData(YamlRepresenter.java:23)
at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepr
esenter.java:94)
at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseR
epresenter.java:156)
at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.represent
Data(SafeRepresenter.java:304)
at org.bukkit.configuration.file.YamlRepresenter$RepresentConfigurationS
ection.representData(YamlRepresenter.java:23)
at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepr
esenter.java:94)
at org.yaml.snakeyaml.representer.BaseRepresenter.representMapping(BaseR
epresenter.java:156)
at org.yaml.snakeyaml.representer.SafeRepresenter$RepresentMap.represent
Data(SafeRepresenter.java:304)
at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepr
esenter.java:94)
at org.yaml.snakeyaml.representer.BaseRepresenter.represent(BaseRepresen
ter.java:64)
at org.yaml.snakeyaml.Yaml.dumpAll(Yaml.java:242)
at org.yaml.snakeyaml.Yaml.dumpAll(Yaml.java:206)
at org.yaml.snakeyaml.Yaml.dump(Yaml.java:181)
at org.bukkit.configuration.file.YamlConfiguration.saveToString(YamlConf
iguration.java:40)
at com.nisovin.shopkeepers.ShopkeepersPlugin.saveDataToFile(ShopkeepersP
lugin.java:1392)
at com.nisovin.shopkeepers.ShopkeepersPlugin.access$1200(ShopkeepersPlug
in.java:62)
at com.nisovin.shopkeepers.ShopkeepersPlugin$11.run(ShopkeepersPlugin.ja
va:1302)
at org.bukkit.craftbukkit.v1_8_R3.scheduler.CraftTask.run(CraftTask.java
:71)
at org.bukkit.craftbukkit.v1_8_R3.scheduler.CraftAsyncTask.run(CraftAsyn
cTask.java:53)
... 3 more



 Comments   
Comment by Jakob Pfeiffer [ 03/Feb/16 ]

Please fix this issue. I need this feature to keep my server going.

Comment by Henry Daeche [ 23/Jan/16 ]

I have been having issues with many plugins lately due to this issue, primarily ProRecipes, MythicMobs, HeadDatabase, LimitedCreative and CreativeControl. It seems the issues I'm facing can all be fixed with this one resolution.

I'd be extremely grateful if this could be looked into.

Comment by Andrew Epifano [ 13/Jan/16 ]

I pushed some code for this and submitted a pull request.

https://hub.spigotmc.org/stash/projects/SPIGOT/repos/spigot/pull-requests/55/overview

Comment by Andrew Epifano [ 13/Jan/16 ]

I think here may lie the issue. When serializing it checks if there is an owner using hasOwner(). However, hasOwner() is as follows:

 public boolean hasOwner() {
        return profile != null;
    }

The profile can not have an owner even if it's not null. hasOwner() returns true although there is no owner because the profile is not null.

Am I correct in assuming this ? This could fix the error on save and possibly the saving of game profile data (which I assume stores texture data) when there is no owner.

A better alternative for this method is perhaps:

 public boolean hasOwner() {
        return profile != null && profile.getName() != null;
    }

I have never submitted a PR to spigot before, would this be acceptable to submit ?

Comment by Andrew Epifano [ 12/Jan/16 ]

There must be so many things to get to and I understand it's impossible to get to all of them at once. A fix for this would be extremely amazing. Thank you anyway for an awesome API.

Comment by BillyGalbreath [ 14/Dec/15 ]

From my understanding thete have been a few pull request that fix this issue already. None have been accepted as of yet, though.

Comment by md_5 [ 23/Nov/15 ]

You are equally as well placed to fix it as we are.
The only thing shit around here is your attitude towards free software developed in the spare time of others.

Comment by _Leo [ 22/Nov/15 ]

Please fix this shit. This is disgusting, i cant save some skulls in a .yml file.

Comment by maker56 [ 19/Nov/15 ]

Skulls with custom texture tags become more and more popular. It would be a restriction for many plugins when the itemstack serialization method doesn't work correctly any more. Please fix this problem. Thanks in advance

Comment by SirPsp [ 14/Nov/15 ]

Been wanting a fix for this since early in the year. Still not working with the latest build - CraftBukkit version git-Spigot-5f38d38-18fbb24 (MC: 1.8.8) (Implementing API version 1.8.8-R0.1-SNAPSHOT)

Comment by blablubbabc [ 22/Jul/15 ]

My console inserted some line breaks into the stacktrace. Here is the same stacktrace again, but better formatted: http://pastebin.com/eEa8qQHY

And the command seems to have lost its intended format as well :/ http://pastebin.com/cnbjdQje

Generated at Thu Mar 28 22:17:13 UTC 2024 using Jira 9.12.4#9120004-sha1:625303b708afdb767e17cb2838290c41888e9ff0.