Shopkeepers / Shopkeepers

A Bukkit plugin to create custom villager shopkeepers.
https://dev.bukkit.org/projects/shopkeepers
GNU General Public License v3.0
99 stars 54 forks source link

Unable to load shop data after update to 2.22.3: "The name of the profile contains invalid characters" #907

Open BigScary opened 1 month ago

BigScary commented 1 month ago

Preliminaries:

Reproduction on a fresh and up-to-date Spigot server:

This doesn't apply to my case because my repro is about specific shopkeepers data that can't be loaded. An entirely fresh server wouldn't repro because it wouldn't have the needed data state.

The issue:

Have been using Shopkeepers for several years on my Paper server. We were on 1.20.4 before we finally updated to a recommended build of Paper 1.21 last week. For a few days, we ran without Shopkeepers because there wasn't a Shopkeepers 1.21 update out yet. When I first tried booting my server with the latest Shopkeepers with 1.21 support, it failed to load with an error message about loading shop data, which I have pasted below in full. In brief: "Caused by: java.lang.IllegalArgumentException: The name of the profile contains invalid characters: Warden Head"

We had no data load issues when we last ran the plugin, and our server was at 1.20.4. I have not downgraded the version of the server or Shopkeepers.

[10:02:11] [Server thread/ERROR]: [Shopkeepers] Failed to load the save file! Note: Server downgrades or manually editing the save file are not supported! com.nisovin.shopkeepers.util.data.persistence.InvalidDataFormatException: Failed to load data as Bukkit config! at Shopkeepers.jar/com.nisovin.shopkeepers.util.data.persistence.bukkit.BukkitConfigDataStore.loadFromString(BukkitConfigDataStore.java:63) ~[Shopkeepers.jar:?] at Shopkeepers.jar/com.nisovin.shopkeepers.util.data.persistence.DataStoreBase.load(DataStoreBase.java:57) ~[Shopkeepers.jar:?] at Shopkeepers.jar/com.nisovin.shopkeepers.storage.SKShopkeeperStorage.doReload(SKShopkeeperStorage.java:456) ~[Shopkeepers.jar:?] at Shopkeepers.jar/com.nisovin.shopkeepers.storage.SKShopkeeperStorage.reload(SKShopkeeperStorage.java:408) ~[Shopkeepers.jar:?] at Shopkeepers.jar/com.nisovin.shopkeepers.SKShopkeepersPlugin.onEnable(SKShopkeepersPlugin.java:423) ~[Shopkeepers.jar:?] at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:288) ~[paper-api-1.21-R0.1-SNAPSHOT.jar:?] at io.papermc.paper.plugin.manager.PaperPluginInstanceManager.enablePlugin(PaperPluginInstanceManager.java:202) ~[paper-1.21.jar:1.21-108-73a863b] at io.papermc.paper.plugin.manager.PaperPluginManagerImpl.enablePlugin(PaperPluginManagerImpl.java:109) ~[paper-1.21.jar:1.21-108-73a863b] at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:520) ~[paper-api-1.21-R0.1-SNAPSHOT.jar:?] at org.bukkit.craftbukkit.CraftServer.enablePlugin(CraftServer.java:640) ~[paper-1.21.jar:1.21-108-73a863b] at org.bukkit.craftbukkit.CraftServer.enablePlugins(CraftServer.java:589) ~[paper-1.21.jar:1.21-108-73a863b] at net.minecraft.server.MinecraftServer.loadWorld0(MinecraftServer.java:753) ~[paper-1.21.jar:1.21-108-73a863b] at net.minecraft.server.MinecraftServer.loadLevel(MinecraftServer.java:515) ~[paper-1.21.jar:1.21-108-73a863b] at net.minecraft.server.dedicated.DedicatedServer.initServer(DedicatedServer.java:329) ~[paper-1.21.jar:1.21-108-73a863b] at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1214) ~[paper-1.21.jar:1.21-108-73a863b] at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:330) ~[paper-1.21.jar:1.21-108-73a863b] at java.base/java.lang.Thread.run(Thread.java:1583) ~[?:?] Caused by: org.bukkit.configuration.InvalidConfigurationException: Could not call method 'public static com.destroystokyo.paper.profile.CraftPlayerProfile com.destroystokyo.paper.profile.CraftPlayerProfile.deserialize(java.util.Map)' of class com.destroystokyo.paper.profile.CraftPlayerProfile for deserialization at Shopkeepers.jar/com.nisovin.shopkeepers.util.bukkit.ConfigUtils.loadConfigSafely(ConfigUtils.java:246) ~[Shopkeepers.jar:?] at Shopkeepers.jar/com.nisovin.shopkeepers.util.data.persistence.bukkit.BukkitConfigDataStore.loadFromString(BukkitConfigDataStore.java:61) ~[Shopkeepers.jar:?] ... 16 more Caused by: java.lang.IllegalArgumentException: The name of the profile contains invalid characters: Warden Head at com.google.common.base.Preconditions.checkArgument(Preconditions.java:218) ~[guava-32.1.2-jre.jar:?] at com.destroystokyo.paper.profile.CraftPlayerProfile.createAuthLibProfile(CraftPlayerProfile.java:274) ~[paper-1.21.jar:1.21-108-73a863b] at com.destroystokyo.paper.profile.CraftPlayerProfile.(CraftPlayerProfile.java:41) ~[paper-1.21.jar:1.21-108-73a863b] at com.destroystokyo.paper.profile.CraftPlayerProfile.deserialize(CraftPlayerProfile.java:333) ~[paper-1.21.jar:1.21-108-73a863b] at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] at org.bukkit.configuration.serialization.ConfigurationSerialization.deserializeViaMethod(ConfigurationSerialization.java:87) ~[paper-api-1.21-R0.1-SNAPSHOT.jar:?] at org.bukkit.configuration.serialization.ConfigurationSerialization.deserialize(ConfigurationSerialization.java:129) ~[paper-api-1.21-R0.1-SNAPSHOT.jar:?] at org.bukkit.configuration.serialization.ConfigurationSerialization.deserializeObject(ConfigurationSerialization.java:209) ~[paper-api-1.21-R0.1-SNAPSHOT.jar:?] at org.bukkit.configuration.file.YamlConstructor$ConstructCustomObject.construct(YamlConstructor.java:58) ~[paper-api-1.21-R0.1-SNAPSHOT.jar:?] at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:264) ~[snakeyaml-2.2.jar:?] at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:247) ~[snakeyaml-2.2.jar:?] at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping2ndStep(BaseConstructor.java:576) ~[snakeyaml-2.2.jar:?] at org.yaml.snakeyaml.constructor.SafeConstructor.constructMapping2ndStep(SafeConstructor.java:210) ~[snakeyaml-2.2.jar:?] at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping(BaseConstructor.java:552) ~[snakeyaml-2.2.jar:?] at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlMap.construct(SafeConstructor.java:597) ~[snakeyaml-2.2.jar:?] at org.bukkit.configuration.file.YamlConstructor$ConstructCustomObject.construct(YamlConstructor.java:49) ~[paper-api-1.21-R0.1-SNAPSHOT.jar:?] at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:264) ~[snakeyaml-2.2.jar:?] at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:247) ~[snakeyaml-2.2.jar:?] at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping2ndStep(BaseConstructor.java:576) ~[snakeyaml-2.2.jar:?] at org.yaml.snakeyaml.constructor.SafeConstructor.constructMapping2ndStep(SafeConstructor.java:210) ~[snakeyaml-2.2.jar:?] at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping(BaseConstructor.java:552) ~[snakeyaml-2.2.jar:?] at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlMap.construct(SafeConstructor.java:597) ~[snakeyaml-2.2.jar:?] at org.bukkit.configuration.file.YamlConstructor$ConstructCustomObject.construct(YamlConstructor.java:49) ~[paper-api-1.21-R0.1-SNAPSHOT.jar:?] at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:264) ~[snakeyaml-2.2.jar:?] at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:247) ~[snakeyaml-2.2.jar:?] at org.bukkit.configuration.file.YamlConstructor.construct(YamlConstructor.java:37) ~[paper-api-1.21-R0.1-SNAPSHOT.jar:?] at org.bukkit.configuration.file.YamlConfiguration.fromNodeTree(YamlConfiguration.java:163) ~[paper-api-1.21-R0.1-SNAPSHOT.jar:?] at org.bukkit.configuration.file.YamlConfiguration.fromNodeTree(YamlConfiguration.java:161) ~[paper-api-1.21-R0.1-SNAPSHOT.jar:?] at org.bukkit.configuration.file.YamlConfiguration.fromNodeTree(YamlConfiguration.java:161) ~[paper-api-1.21-R0.1-SNAPSHOT.jar:?] at org.bukkit.configuration.file.YamlConfiguration.fromNodeTree(YamlConfiguration.java:161) ~[paper-api-1.21-R0.1-SNAPSHOT.jar:?] at org.bukkit.configuration.file.YamlConfiguration.loadFromString(YamlConfiguration.java:120) ~[paper-api-1.21-R0.1-SNAPSHOT.jar:?] at Shopkeepers.jar/com.nisovin.shopkeepers.util.bukkit.ConfigUtils.loadConfigSafely(ConfigUtils.java:239) ~[Shopkeepers.jar:?] at Shopkeepers.jar/com.nisovin.shopkeepers.util.data.persistence.bukkit.BukkitConfigDataStore.loadFromString(BukkitConfigDataStore.java:61) ~[Shopkeepers.jar:?] ... 16 more [10:02:11] [Server thread/ERROR]: [Shopkeepers] Detected an issue during the loading of the saved shopkeepers data! Disabling the plugin! [10:02:11] [Server thread/INFO]: [Shopkeepers] Disabling Shopkeepers v2.22.3

blablubbabc commented 1 month ago

Minecraft and also the Paper server are more strict now regarding custom profile data on head items. The profile name has to adhere to the requirements of Minecraft usernames now (limited length and limited set of allowed characters). On Paper, the item fails to load, on Spigot, it currently loads but then crashes players when they open the shop. The usual approach of loading the item and then passing it through Minecraft's data migrations doesn't seem to work, neither on Paper nor on Spigot currently. I still need to further investigate this.

There is no automatic migration path for this currently. The quickest solution would be to match the profile name property via a regex and replace all names, e.g. with an empty string. I think this is also how Minecraft itself has migrated previous custom head items. See also my comment here: https://www.spigotmc.org/threads/shopkeepers.447969/page-18#post-4759335 If you want to migrate these items to something nicer, e.g. preserve the name in some form, you would need to be more sophisticated.

Edit: I looked into this a bit more: