fabric icon indicating copy to clipboard operation
fabric copied to clipboard

Fabric custom ingredient API

Open Technici4n opened this issue 2 years ago • 2 comments

Note: This PR is still WIP and untested, feel free to ignore it for now.

This API allows modders to define custom Ingredients, with more advanced matching logic than what vanilla allows.

Custom ingredients need to implement the CustomIngredient interface, and also provide and register a CustomIngredientDeserializer. No overriding of Ingredient is needed.

For now, the only example is the OrCondition.

TODO:

  • [ ] The various TODOs in the PR.
  • [ ] Decide on exact API and impl structure.
  • [ ] Write javadoc.

Technici4n avatar Oct 15 '22 21:10 Technici4n

A possible NBT ingredient would also be useful

AlphaMode avatar Oct 15 '22 22:10 AlphaMode

A possible NBT ingredient would also be useful

I have the following ingredients in mind, just haven't written them yet: (matching Forge's)

  • strict and partial NBT ingredient
  • and ingredient
  • difference ingredient

Technici4n avatar Oct 15 '22 22:10 Technici4n

Thanks a lot for your detailed explanation.

I decided to go for the simpler augmenting paths algorithm for the maximum cardinality bipartite matching problem, which should look like this : https://github.com/Technici4n/fabric/blob/custom-ingredient-api/fabric-ingredient-api-v1/src/main/java/net/fabricmc/fabric/impl/ingredient/ShapelessMatch.java. I haven't tested it yet though, but I will definitely add tests similar to what you suggested.

I also renamed matchesStack and getPreviewStacks to test and getMatchingStacks respectively, and provided some javadoc for CustomIngredient. I hope the javadoc is clear enough - there's some tricky details that might not always be obvious. I also borrowed your name for requiresTesting which I like better than ignoresNbt - hopefully you don't mind. :smile:

Technici4n avatar Oct 16 '22 22:10 Technici4n

I just tested the following cases:

  • Server with Fabric ingredient API, vanilla client, no recipe using custom ingredients: can connect fine.
  • Server with Fabric ingredient API, vanilla client, some recipes using custom ingredients: can't connect, with the following error: image Is this fine?
  • Client/server with both Fabric ingredient API and Faux ingredient extension API: packet writing sending works, but I used the 1.19.2 version of the ingredient extension API, so I get a crash due to other reasons. I think the two APIs are compatible. (Though obviously the ingredient extension API won't be needed anymore once this PR is merged, but I want a smooth transition).

This PR is now ready for reviews!

Technici4n avatar Dec 15 '22 01:12 Technici4n

Client/server with both Fabric ingredient API and Faux ingredient extension API: packet writing sending works, but I used the 1.19.2 version of the ingredient extension API, so I get a crash due to other reasons. I think the two APIs are compatible. (Though obviously the ingredient extension API won't be needed anymore once this PR is merged, but I want a smooth transition

We have no intention of continuing development on the Faux Ingredient Extension API once this PR is merged, so even if it wasn't compatible, it shouldn't be an issue since neither APIs should share a version.

jaredlll08 avatar Dec 15 '22 01:12 jaredlll08

My thinking is that you might release a 1.19.3 version of your Extension API before this PR gets merged in 1.19.3. (I have no idea when it will be merged, it's going to require quite a bit of review).

Technici4n avatar Dec 15 '22 01:12 Technici4n

Would it be out of scope to add a way to give these custom ingredients a recipe remainder that overrides the one in their item's settings? So one could, for example, make a "chocolate milk bucket" recipe that takes a milk bucket and cocoa beans, without the milk bucket leaving behind an empty bucket by overriding the milk bucket's remainder in just that recipe.

Shnupbups avatar Dec 15 '22 09:12 Shnupbups

Would it be out of scope to add a way to give these custom ingredients a recipe remainder that overrides the one in their item's settings? So one could, for example, make a "chocolate milk bucket" recipe that takes a milk bucket and cocoa beans, without the milk bucket leaving behind an empty bucket by overriding the milk bucket's remainder in just that recipe.

I think it would be out of scope. Some of the problems:

  • Ingredients are used in many places, so properly supporting this would require a lot of patches.
  • The patches are very invasive as they require all remainder logic to go through the ingredient.
  • For recipes, we don't even know which ingredients were matched where in the getRecipeRemainder method, so we'd need to recompte the match before we apply custom remainders. I think it's best left to other mods (for crafting recipes, it's "easy" to implement on top of this API with a custom recipe type).

Technici4n avatar Dec 15 '22 10:12 Technici4n

I just implemented a graceful fallback mechanism to make this API work nicely for clients that don't support (some or all) custom ingredients. Summary follows:

  • On login, server requests the client's available ingredients.
  • The client answers by listing the serializer IDs it supports.
  • The server stores that where it's relevant.
  • When an ingredient is serialized, we lookup which IDs are supported by the client. If we can lookup and the client doesn't support the ingredient, we send it as a vanilla stack list ingredient instead. Otherwise, we send the custom ingredient as usual.

List of cases to test:

  • [x] Server has ingredient API, client doesn't have the API.
  • [x] Server has ingredient API, client has the API but doesn't support some ingredients.
  • [x] Server has ingredient API, client has the API and all the used ingredients.

Technici4n avatar Dec 16 '22 15:12 Technici4n

After some consideration, this new module will be renamed Fabric Recipe API v1, and the ingredient stuff will be moved to the net.fabricmc.fabric.api.recipe.v1.ingredient package, in preparation for possible other kinds of recipe format extensions.

Technici4n avatar Dec 16 '22 15:12 Technici4n

image

Works fine on vanilla clients now (ignoring the recipe book) !

Technici4n avatar Dec 18 '22 14:12 Technici4n

Partial support on clients also works: (debug output on server, removed some ingredients on client)

[15:28:36] [Server thread/INFO]: Technici4n joined the game
Wrote fabric:nbt as a vanilla ingredient
Wrote fabric:and as a custom ingredient
Wrote fabric:difference as a vanilla ingredient
Wrote fabric:nbt as a vanilla ingredient
Wrote fabric:or as a custom ingredient

Technici4n avatar Dec 18 '22 14:12 Technici4n

Just rebased to fix the gradle.properties conflict, and switched getMatchingStacks to a List<ItemStack>.

Technici4n avatar Dec 24 '22 14:12 Technici4n

I expect out of scope for this PR, but having a condition for a custom ingredient might be useful.

modmuss50 avatar Dec 28 '22 14:12 modmuss50