Sponge API: 6.0.0-20170323.180311-60
Sponge Forge Build: spongeforge-1.11.2-2227-6.0.0-BETA-2244
Forge Build: forge-1.11.2-13.20.0.2227-universal
Java Version: 1.8.0_121-b13
I've seem to have found a bug, which simon816 has confirmed on the forums, with the with DataSerializable in regards to PotiotionEffects.
Here is the original post:
I have the following code, which saves a player's potion effects:
public static void saveOriginalPotionEffects(List<PotionEffect> potionEffects, String arenaName, String userName) throws ObjectMappingException {
int i = 1;
for(PotionEffect potionEffect: potionEffects){
UnversalConfigs.getConfig(ArenaConfig).getNode("Arena", arenaName, "Contestants", userName, "Potion Effects","Effect "+i).setValue(TypeToken.of(PotionEffect.class),potionEffect);
UnversalConfigs.saveConfig(ArenaConfig);
i++;
}
}
I have no issue with the code above, but when I try to retrieve the data with the code below, I receive a Could not translate DataSerializable of type: org.spongepowered.api.effect.potion.PotionEffect error. This might be a programmer end error, but I coudn't get any further after troubleshooting the issue to line PotionEffect potionEffect = node.getNode("Effect "+i).getValue(TypeToken.of(PotionEffect.class));Any help would be greatly appreciated. Thanks!
public static List<PotionEffect> fetchOriginalPotionEffects(String arenaName, String userName) throws ObjectMappingException{
List<PotionEffect> potionEffects = Lists.newArrayList();
CommentedConfigurationNode node = UnversalConfigs.getConfig(ArenaConfig).getNode("Arena", arenaName, "Contestants", userName, "Potion Effects");
int NOPE = getNumOfPotionEffects(arenaName,userName);
for(int i = 1; i<= NOPE;i++){
PotionEffect potionEffect = node.getNode("Effect "+i).getValue(TypeToken.of(PotionEffect.class));
potionEffects.add(potionEffect);
}
return potionEffects;
}
simon816's bug replication code:
try {
PotionEffect effect = PotionEffect.of(PotionEffectTypes.JUMP_BOOST, 1, 10);
SimpleCommentedConfigurationNode node = SimpleCommentedConfigurationNode.root();
node.getNode("test").setValue(TypeToken.of(PotionEffect.class), effect);
PotionEffect effect2 = node.getNode("test").getValue(TypeToken.of(PotionEffect.class));
} catch (ObjectMappingException e) {
e.printStackTrace();
}
I think I accidentally managed to find the core issue.
When trying to to get a PotionEffect from a DataContainer with this code:
PotionEffect effect = PotionEffect.of(PotionEffectTypes.ABSORPTION, 0, 100);
PotionEffect.builder().build(effect.toContainer());
I get this error:
[17:11:12 ERROR] [STDERR]: org.spongepowered.api.data.persistence.InvalidDataException: Could not deserialize something correctly, likely due to bad type data.
[17:11:12 ERROR] [STDERR]: at org.spongepowered.api.data.persistence.AbstractDataBuilder.build(AbstractDataBuilder.java:89)
[17:11:12 ERROR] [STDERR]: at test.code.Main.main(Main.java:2)
[17:11:13 ERROR] [STDERR]: Caused by: org.spongepowered.api.data.persistence.InvalidDataException: The container has an invalid potion type name: effect.absorption
[17:11:13 ERROR] [STDERR]: at org.spongepowered.common.effect.potion.SpongePotionBuilder.buildContent(SpongePotionBuilder.java:75)
[17:11:13 ERROR] [STDERR]: at org.spongepowered.api.data.persistence.AbstractDataBuilder.build(AbstractDataBuilder.java:87)
[17:11:13 ERROR] [STDERR]: ... 2 more
(Stacktrace shortened and simplified)
Not sure what format SpongePotionBuilder expects but it's not effect.absorbtion.
If so, that's great! Thank you for taking the time to test this :D
As I said I accidentally stumbled over it. I was trying to bypass the issue that container.getSerializableList(POTION_EFFECTS, PotionEffect.class) did always return Optional.empty() and resorted to getting it as a DataView list and using streams to convert it to PotionEffects. Where I called PotionEffect.builder().build(potionContainer) and it crashed.
Bumping up report.
I'd like to point out, that in SF 1.12.2-2586-7.1.0-BETA-2900 the following code still returns Optional.empty()
DataContainer container = DataContainer.createNew(SafetyMode.ALL_DATA_CLONED);
container.set("potions", player.get(Keys.POTION_EFFECTS).orElse(Collections.emptyList()));
container.getSerializableList("potions", PotionEffect.class); // = Optional.empty()
While the container contains all potion data!
Updated code:
DataContainer container = DataContainer.createNew(DataView.SafetyMode.ALL_DATA_CLONED);
DataQuery pot = DataQuery.of("PotionType");
container.set(pot, player.get(Keys.POTION_EFFECTS).orElse(Collections.emptyList()));
container.getSerializableList(pot, PotionEffect.class);