wisp-forest / alloy-forgery

Alloy smelter mod for Fabric
MIT License
43 stars 18 forks source link

Codec Error when calling the recipe serializer codec directly #129

Closed kindlich closed 3 months ago

kindlich commented 6 months ago

Hey there,

this issue came up in the CraftTweaker discord and I just wanted to forward it here.

Background: CraftTweaker allows modpack developers to specify their own recipes using a builtin scripting language. Mods either provide explicit support inside their mod (or an addon mod). If a mod does not provide explicit support, we can fall back to using the recipe serializer system and allow users to provide JSON recipes which are then passed to the serializer's codec.

Issue description and Steps to reproduce: When trying to add a recipe to the alloy_forgery:forging serializer, the ingredients cannot be parsed properly. I assume this has to do with the Endecs that this mod uses, but I cannot see if the issue lies in this mod or in uwu-lib.

  1. Have CraftTweaker and alloy-forgery installed. Versions I used:
    • Minecraft 1.20.4 with Fabric Loader 0.15.7
    • CraftTweaker-fabric-1.20.4-17.0.12
    • fabric-api-0.96.4+1.20.4
    • owo-lib-0.12.5+1.20.3
  2. Create a script .../.minecraft/scripts/test.zs
    <recipetype:alloy_forgery:forging>.addJsonRecipe("forging.testing", {
      "type": "alloy_forgery:forging",
      "fuel_per_tick": 90,
      "inputs": [
        {
          "count": 2,
          "tag": "c:raw_adamantite_blocks"
        }
      ],
      "min_forge_tier": 2,
      "output": {
        "count": 2,
        "default": "c:adamantite_blocks",
        "priority": [
          "mythicmetals:adamantite_block"
        ]
      },
      "overrides": {
        "3+": {
          "count": 3
        }
      }
    });
  3. Join any world (or run /reload if you are already in one)
  4. Check the error in the chat (or in the .../.minecraft/logs/crafttweaker.log file)
    [10:36:30.326][ERROR][CraftTweaker-ZenCode]: Error while running scripts:
    java.lang.IllegalArgumentException: 
        No key tag in MapLike[{E(STRING, "count")=E(INT, 2), E(STRING, "tag")=E(STRING, "c:raw_adamantite_blocks")}]; 
        No key item in MapLike[{E(STRING, "count")=E(INT, 2), E(STRING, "tag")=E(STRING, "c:raw_adamantite_blocks")}]; 
        Not a sequence: E(MAP, {"count"=E(INT, 2), "tag"=E(STRING, "c:raw_adamantite_blocks")}); 
        Input does not contain a key [fabric:type]: MapLike[{E(STRING, "count")=E(INT, 2), E(STRING, "tag")=E(STRING, "c:raw_adamantite_blocks")}]

Analysis: To me, this looks like some part of the system serializes our input into the uwu-lib's endec format and then passes that to the recipe serializer instead of the "raw" MapLike structure. It goes without saying that a Map with EDM-Elements as keys and values does not contain a String called "tag". Since CraftTweaker only calls serializer.codec().parse(...) with the normal Minecraft Codec class, we assume the issue lies in either AlloyForgery or in uwu-lib.

Possible Workarounds/Alternative Fixes:

Additional Files:

gliscowo commented 6 months ago

I must admit, I am rather bewildered as to how this issue would occur - granted, I also did not implement the current recipe system. Did you test this exact recipe in a datapack?

You are indeed correct in assuming that data is encoded to EDM before being passed to a codec, however, said codec then uses a special DynamicOps implementation which knows how to deal with this format. I believe (this could be incorrect) that the MapLike displaying EDM data is normal since the DynamicOps implementation is used to actually interact with and get data from it.

Anyways, @Dragon-Seeker will need to look more into this

Also, don't get confused, I fat-fingered the close with comment button

Cheers

kindlich commented 6 months ago

Well, I basically copied over what was written here and removed a few blocks.

Putting it into a datapack seems to load properly. I did change the recipe a bit since in my test instance there's no adamantite:

// saves/Test World/datapacks/test_alloy/data/crafttweaker/recipes/forging.testing.json

{
  "type": "alloy_forgery:forging",
  "fuel_per_tick": 45,
  "inputs": [
    {
      "count": 10,
      "item": "minecraft:bedrock"
    }
  ],
  "min_forge_tier": 1,
  "output": {
    "count": 3,
    "id": "minecraft:gold_block"
  },
  "overrides": {
    "2+": {
      "count": 4
    }
  }
}

Works fine inside a datapack, but breaks inside a CraftTweaker script:

// scripts/test.zs
<recipetype:alloy_forgery:forging>.addJsonRecipe("forging.testing.2", {
  "type": "alloy_forgery:forging",
  "fuel_per_tick": 45,
  "inputs": [
    {
      "count": 10,
      "item": "minecraft:bedrock"
    }
  ],
  "min_forge_tier": 1,
  "output": {
    "count": 3,
    "id": "minecraft:gold_block"
  },
  "overrides": {
    "2+": {
      "count": 4
    }
  }
});
[15:03:39.083][ERROR][CraftTweaker-ZenCode]: Error while running scripts:
java.lang.IllegalArgumentException: 
No key tag in MapLike[{E(STRING, "item")=E(STRING, "minecraft:bedrock"), E(STRING, "count")=E(INT, 10)}]; 
No key item in MapLike[{E(STRING, "item")=E(STRING, "minecraft:bedrock"), E(STRING, "count")=E(INT, 10)}];
Not a sequence: E(MAP, {"count"=E(INT, 10), "item"=E(STRING, "minecraft:bedrock")});
Input does not contain a key [fabric:type]: MapLike[{E(STRING, "item")=E(STRING, "minecraft:bedrock"), E(STRING, "count")=E(INT, 10)}]
Dragon-Seeker commented 6 months ago

Will dive further into this issue coming up when I find time.