Ender IO Zoo

Ender IO Zoo

962k Downloads

EnderIO causes GSON to throw an exception when certain loot tables are serialised

Daomephsta opened this issue ยท 16 comments

commented

Issue Description:

When LootTweaker attempts to serialise certain loot tables(to dump them to a folder), GSON throws an error. This error is not caused by LootTweaker or CraftTweaker, as it only occurs with EnderIO installed. EnderCore is not the cause of the problem. LootTweaker successfully dumps loot tables modified by other mods, such as Actually Additions and BetterBeginnings.

What happens:

When LootTweaker attempts to serialise certain loot tables with EnderIO installed, GSON throws an error.

What you expected to happen:

LootTweaker to successfully dump all loot tables.

Steps to reproduce:

  1. Install this build of LootTweaker, also install CraftTweaker(I reproduced this issue with CT 1.10.2-3.0.15, but any 1.10.2 build should do). Any build of LootTweaker will reveal the issue, but the linked one has been tweaked to give a more useful error.
  2. Launch Minecraft and open a world.
  3. Run the command /mt loottables all. There will be no errors in the log
  4. Install EnderIO and EnderCore.
  5. Repeat step 3. Errors will now occur.

Affected Versions (Do not use "latest"):

  • CraftTweaker: 1.10.2-3.0.15
  • EnderIO: 1.10.2-3.0.1.142_beta
  • EnderCore: 1.10.2-0.4.1.61-beta
  • Minecraft: 1.10.2
  • Forge: 1.10.2-12.18.2.2134

Your most recent log file where the issue was present:

https://paste.ee/p/TNh8M

commented

It looks like LootTweaker tries to convert some Ender IO objects into GSON that were not build to be serialized to disk---and are not serialized by vanilla...

commented

@HenryLoenwind
LootTweaker serialises the loot tables here. As far as I'm aware, this is the proper way to serialise a JSON object, I don't do anything odd. Yes, vanilla does not serialise these loot tables, but they are nevertheless serialisable objects. Since they are serialisable objects, you should expect that someone may want to serialise them.

I'm quite sure that LootTweaker is not at fault, I have tried dumping loot tables with other loot adding mods installed. LootTweaker threw no errors, the tables were successfully dumped. While LootTweaker is capable of modifying loot tables, this issue was produced with no CraftTweaker scripts in the MC instance. LootTweaker does not modify loot tables unless instructed to by a CraftTweaker script.

commented

Vanilla uses GSON to load the json loot tables from its resource pack. It never serializes them again as far as I can find. That LootTableManager.GSON_INSTANCE is only used for reading json, it is private and has no hooks to register custom serializers. So I have no way to actually make our objects serializable with it.

commented

LootFunction serialisers can be registered with LootFunctionManager#registerFunction()
LootCondition serialisers can be registered with LootConditionManager#registerCondition()
Other loot objects have serialise and deserialise methods that can be overriden.

commented

LootPool doesn't. And there's no way to add custom classes that are not of those types you named.

commented

LootPool doesn't. And there's no way to add custom classes that are not of those types you named.

Where do you extend LootPool?

commented

Thank you. What does that do that LootPool doesn't? (I'm trying to figure out if a case for a forge hook could be made)

commented

I'm not sure. I only know that CrazyPants made it when we got too many bug reports about overflowing chests...

commented

Could you please ask him?
If it's a significant part of your loot code, I think a case for a Forge hook could be made. If Forge isn't interested, I'd be open to writing a way for you to tell LootTweaker how to serialise that.

commented

Crazy's not generally available atm for health reasons. :(

On the other hand, you seem to actually know what you're doing in regards to loot tables. So I'd be more than happy if you'd have an extended look at that loot manager and, if that custom impl isn't really needed, to redo it in a standard way...

commented

I'll take a look. Thank you for your assistance.

commented

I added two new LootFunctions, could you test if it still works

You've registered serialisers for them, so there should be no problems. I'll test anyway though.

if it really is possible to feed it to the game again and get my LootFunctions back

As long as your serialise functions are 1:1 with your deserialise functions(All EIO's are), you will get equivalent LootFunctions if you serialise and then deserialise.

commented

Yep, all is fine and dandy.

I'd be interested in how the json looks like

The JSON files look terrible. They are completely unformatted, just serialised and written to a file.
For example, here's the dungeon loot table JSON:
{"pools":[{"name":"main","entries":[{"entryName":"minecraft:saddle","weight":20,"quality":0,"type":"item","name":"minecraft:saddle"},{"entryName":"minecraft:golden_apple","weight":15,"quality":0,"type":"item","name":"minecraft:golden_apple"},{"entryName":"minecraft:golden_apple#0","weight":2,"quality":0,"type":"item","functions":[{"data":1.0,"function":"minecraft:set_data"}],"name":"minecraft:golden_apple"},{"entryName":"minecraft:record_13","weight":15,"quality":0,"type":"item","name":"minecraft:record_13"},{"entryName":"minecraft:record_cat","weight":15,"quality":0,"type":"item","name":"minecraft:record_cat"},{"entryName":"minecraft:name_tag","weight":20,"quality":0,"type":"item","name":"minecraft:name_tag"},{"entryName":"minecraft:golden_horse_armor","weight":10,"quality":0,"type":"item","name":"minecraft:golden_horse_armor"},{"entryName":"minecraft:iron_horse_armor","weight":15,"quality":0,"type":"item","name":"minecraft:iron_horse_armor"},{"entryName":"minecraft:diamond_horse_armor","weight":5,"quality":0,"type":"item","name":"minecraft:diamond_horse_armor"},{"entryName":"minecraft:book","weight":10,"quality":0,"type":"item","functions":[{"function":"minecraft:enchant_randomly"}],"name":"minecraft:book"}],"rolls":{"min":1.0,"max":3.0}},{"name":"pool1","entries":[{"entryName":"minecraft:iron_ingot","weight":10,"quality":0,"type":"item","functions":[{"count":{"min":1.0,"max":4.0},"function":"minecraft:set_count"}],"name":"minecraft:iron_ingot"},{"entryName":"minecraft:gold_ingot","weight":5,"quality":0,"type":"item","functions":[{"count":{"min":1.0,"max":4.0},"function":"minecraft:set_count"}],"name":"minecraft:gold_ingot"},{"entryName":"minecraft:bread","weight":20,"quality":0,"type":"item","name":"minecraft:bread"},{"entryName":"minecraft:wheat","weight":20,"quality":0,"type":"item","functions":[{"count":{"min":1.0,"max":4.0},"function":"minecraft:set_count"}],"name":"minecraft:wheat"},{"entryName":"minecraft:bucket","weight":10,"quality":0,"type":"item","name":"minecraft:bucket"},{"entryName":"minecraft:redstone","weight":15,"quality":0,"type":"item","functions":[{"count":{"min":1.0,"max":4.0},"function":"minecraft:set_count"}],"name":"minecraft:redstone"},{"entryName":"minecraft:coal","weight":15,"quality":0,"type":"item","functions":[{"count":{"min":1.0,"max":4.0},"function":"minecraft:set_count"}],"name":"minecraft:coal"},{"entryName":"minecraft:melon_seeds","weight":10,"quality":0,"type":"item","functions":[{"count":{"min":2.0,"max":4.0},"function":"minecraft:set_count"}],"name":"minecraft:melon_seeds"},{"entryName":"minecraft:pumpkin_seeds","weight":10,"quality":0,"type":"item","functions":[{"count":{"min":2.0,"max":4.0},"function":"minecraft:set_count"}],"name":"minecraft:pumpkin_seeds"},{"entryName":"minecraft:beetroot_seeds","weight":10,"quality":0,"type":"item","functions":[{"count":{"min":2.0,"max":4.0},"function":"minecraft:set_count"}],"name":"minecraft:beetroot_seeds"}],"rolls":{"min":1.0,"max":4.0}},{"name":"pool2","entries":[{"entryName":"minecraft:bone","weight":10,"quality":0,"type":"item","functions":[{"count":{"min":1.0,"max":8.0},"function":"minecraft:set_count"}],"name":"minecraft:bone"},{"entryName":"minecraft:gunpowder","weight":10,"quality":0,"type":"item","functions":[{"count":{"min":1.0,"max":8.0},"function":"minecraft:set_count"}],"name":"minecraft:gunpowder"},{"entryName":"minecraft:rotten_flesh","weight":10,"quality":0,"type":"item","functions":[{"count":{"min":1.0,"max":8.0},"function":"minecraft:set_count"}],"name":"minecraft:rotten_flesh"},{"entryName":"minecraft:string","weight":10,"quality":0,"type":"item","functions":[{"count":{"min":1.0,"max":8.0},"function":"minecraft:set_count"}],"name":"minecraft:string"}],"rolls":3.0},{"name":"Ender IO","entries":[{"entryName":"enderio:itemAlloy:6","weight":1,"quality":1,"conditions":[{"chance":0.25,"condition":"minecraft:random_chance"}],"type":"item","functions":[{"count":1.0,"function":"minecraft:set_count"},{"data":6.0,"function":"minecraft:set_data"}],"name":"enderio:itemAlloy"},{"entryName":"enderio:itemConduitProbe:0","weight":1,"quality":1,"conditions":[{"chance":0.1,"condition":"minecraft:random_chance"}],"type":"item","functions":[{"count":1.0,"function":"minecraft:set_count"},{"data":0.0,"function":"minecraft:set_data"}],"name":"enderio:itemConduitProbe"},{"entryName":"minecraft:quartz:0","weight":1,"quality":1,"conditions":[{"chance":0.25,"condition":"minecraft:random_chance"}],"type":"item","functions":[{"count":3.0,"function":"minecraft:set_count"},{"data":0.0,"function":"minecraft:set_data"}],"name":"minecraft:quartz"},{"entryName":"minecraft:nether_wart:0","weight":1,"quality":1,"conditions":[{"chance":0.2,"condition":"minecraft:random_chance"}],"type":"item","functions":[{"count":1.0,"function":"minecraft:set_count"},{"data":0.0,"function":"minecraft:set_data"}],"name":"minecraft:nether_wart"},{"entryName":"minecraft:ender_pearl:0","weight":1,"quality":1,"conditions":[{"chance":0.3,"condition":"minecraft:random_chance"}],"type":"item","functions":[{"count":1.0,"function":"minecraft:set_count"},{"data":0.0,"function":"minecraft:set_data"}],"name":"minecraft:ender_pearl"},{"entryName":"enderio:darkSteel_sword:0","weight":1,"quality":1,"conditions":[{"chance":0.1,"condition":"minecraft:random_chance"}],"type":"item","functions":[{"count":1.0,"function":"minecraft:set_count"},{"damage":{"min":1.0,"max":2000.0},"function":"minecraft:set_damage"},{"function":"minecraft:set_random_dark_upgrade"},{"function":"minecraft:set_random_energy"}],"name":"enderio:darkSteel_sword"},{"entryName":"enderio:darkSteel_boots:0","weight":1,"quality":1,"conditions":[{"chance":0.1,"condition":"minecraft:random_chance"}],"type":"item","functions":[{"count":1.0,"function":"minecraft:set_count"},{"damage":{"min":1.0,"max":455.0},"function":"minecraft:set_damage"},{"function":"minecraft:set_random_dark_upgrade"},{"function":"minecraft:set_random_energy"}],"name":"enderio:darkSteel_boots"},{"entryName":"enderio:itemBasicCapacitor11","weight":1,"quality":1,"conditions":[{"chance":0.15,"condition":"minecraft:random_chance"}],"type":"item","functions":[{"function":"minecraft:set_capacitor"},{"data":3.0,"function":"minecraft:set_data"}],"name":"enderio:itemBasicCapacitor"},{"entryName":"enderio:itemBasicCapacitor12","weight":1,"quality":1,"conditions":[{"chance":0.15,"condition":"minecraft:random_chance"}],"type":"item","functions":[{"function":"minecraft:set_capacitor"},{"data":3.0,"function":"minecraft:set_data"}],"name":"enderio:itemBasicCapacitor"},{"entryName":"enderio:itemBasicCapacitor13","weight":1,"quality":1,"conditions":[{"chance":0.15,"condition":"minecraft:random_chance"}],"type":"item","functions":[{"function":"minecraft:set_capacitor"},{"data":3.0,"function":"minecraft:set_data"}],"name":"enderio:itemBasicCapacitor"}],"rolls":{"min":1.0,"max":3.0}}]}

Only EnderIO and LootTweaker were installed, and there were no scripts in use. All that loot is from vanilla or EnderIO.

commented

I added two new LootFunctions, could you test if it still works? And I'd be interested in how the json looks like and if it really is possible to feed it to the game again and get my LootFunctions back.

commented

thank you!