Fabric API

Fabric API

106M Downloads

Add result NBT and count to crafting and smelting recipes

Technici4n opened this issue ยท 7 comments

commented

I propose the following extensions for vanilla recipe outputs:

  • crafting recipes: allow specifying NBT data of the result stack.
  • smelting recipes: allow specifying NBT data and count of the result stack.

We need 3 kinds of patches: JSON format patches to read the extra data, data generation patches to write the extra data, and possibly patches to fix existing logic: furnaces will need a patch to correctly handle count and NBT.

The main reason I am opening this issue is to discuss what the extended JSON format should be: other format extensions such as process conditions and custom ingredient types have always been prefixed with fabric:.

Current JSON formats

Crafting:

{
  "result": {
    "count": 2, // optional
    "item": "<item id>"
  }
}

Smelting:

{
  "result": "<item id>"
}

Forge JSON format

Forge implements both of these extensions with the following syntax (valid for both crafting and smelting):

{
  "result": {
    "count": 2, // optional
    "nbt": {}, // optional, can either be an object or a string representation, defaults to null
    "item": "<item id>"
  }
}

The old syntax for smelting is still supported.

The main problem with this approach is that there is no way to distinguish vanilla fields and Forge-added fields, however the consistency is nice. In the following I assume that we want a fabric: prefix for any Fabric addition.

Potential JSON format

For crafting recipes it is fairly obvious that we can add a fabric:nbt field to the result. For example:

{
  "result": {
    "count": 2, // optional
    "fabric:nbt": {}, // optional, can either be an object or a string representation, defaults to null
    "item": "<item id>"
  }
}

That would solve the problem nicely. Moving on...

Extended smelting recipes are less clear to me. Here are a few options, but each has drawbacks:

  • Add fabric:result_count and fabric:result_nbt to the top level. Looks a bit weird. Introduces an asymmetry between crafting and smelting.
  • Add fabric:result that supports an object with the same fields as crafting recipes. Replaces vanilla instead of adding to it.
  • Extend result to accept objects, and support the same syntax as crafting recipes. Replaces vanilla instead of adding to it. Either we do "count": 2 (no fabric: tag to mark the extension), or we do "fabric:count": 2 (inconsistent with crafting recipes).

JSON format proposal

Here I will propose a JSON format for these extensions, under the following assumptions:

  • We want to mark any addition with a fabric: prefix.
  • Ideally we want to only be adding to vanilla recipes, not replacing things.
  • Making the crafting and smelting formats identical is not a goal, since they are already different in Vanilla.

I suggest we add fabric:nbt to the result object of crafting recipes, and fabric:result_count + fabric:result_nbt to the top-level object of smelting recipes. This would look like this:
Crafting:

{
  "result": {
    "count": 2, // optional
    "fabric:nbt": {}, // optional, can either be an object or a string representation, defaults to null
    "item": "<item id>"
  }
}

Smelting:

{
  "fabric:result_count": 2, // optional, defaults to null
  "fabric:result_nbt": {}, // optional, can either be an object or a string representation, defaults to null
  "result": "<item id>"
}

What do you all think?

commented

Both the PR and the issue seem to be a bit inactive, hence I'm bumping this just in case
I totally understand if it's not possible to work on this right now, though

commented

I just realized that stonecutting recipes are currently using separate result and count keys for the resulting item stack, so adding fabric:count and fabric:nbt to smelting recipes isn't that far-fetched.

commented

Also, I would like to hear @FabricMC/fabric-triage thoughts on the format.

commented

I would propose the schema that I use for itemstacks and nbt across my mods, which is visible in the first two entries of this document.

That is, for CompoundTag:

"string" // [Mandatory] || Mojangson string representation of a Compound Tag -- See https://github.com/aramperes/Mojangson for spec

OR

Object // [Mandatory] || Object representation of a Compound Tag, which is just write a JSON object that maps to your desired nbt.

// A string representation of CompoundTag implies -> "nbt": "{Data:0}"
// The object representation implies -> "nbt": { "Data": 0 } 
// Either form is valid, and the object form is easier.

And for ItemStack:

{
  "item": "string",       // [Mandatory] || Registry Name of item to load.
  "optional": boolean,    // [Optional, defaults to false] || If False, then the parser will error if the item is not located in the registry.
  "count": integer,       // [Optional, defaults to 1] || Stack Size
  "nbt": CompoundTag,     // [Optional] || Vanilla Item NBT
  "cap_nbt": CompoundTag, // [Optional] || Forge Item Capability NBT
}

I believe having the fabric: prefix in the json keys does not provide any value, and would only make multiplatform development harder.

commented

Pls yes. Much more desirable in 1.20.3 now that recipes are codecs which makes workaround solutions to implement this a bit harder

commented

After checking the code it isn't much harder, might be even bit easier if you know that you are doing

commented

While I agree with Shadows-of-Fire's stance that having the fabric: prefix does not provide enough additional value to be worth restricting multiplatform development, it has been pointed out to me that Fabric already does this in some areas (thanks to maityyy for pointing this out - resource conditions and custom ingredients).
Considering that (and not getting into a further conversation of "should it be changed") I was wondering if the following formatting might be a good idea for cooking recipes:

{
  "fabric:result": {
    "item": (string),        // required
    "count": (integer),      // optional
    "nbt": (to_be_decided)   // optional
  }
}

I have added a PR currently implementing count using the same codec that Vanilla does for crafting recipes, this will likely change to the format above (without nbt). I would like some feedback on what people think.