Skip to content

Instantly share code, notes, and snippets.

@LexManos
Last active September 30, 2018 13:45
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LexManos/2a11d4f7aa9d680d861dae4faf9dcfa6 to your computer and use it in GitHub Desktop.
Save LexManos/2a11d4f7aa9d680d861dae4faf9dcfa6 to your computer and use it in GitHub Desktop.
1.12 Recipe enhancements
Basic loading.
To be done on ServerInit. This means things will load multiple times on the client.
Benifits:
Allows us to just nuke the custom recipes every server init
Allows us to have save leve overrides.
Primes us for syncing recipe types/contents S->C {Not gunna happen in 1.12, but I expect Mojang to work twards this in 1.13+}
Cons:
Increases single player server load time. No known stats at the moment but shouldn't be TO bad
Loading Process:
BootStrap: Vanilla loads their internal recipes, we'll freeze this registry and revert to it at the beginning of ServerInit
Gather Factories:
Gather a list of IRecipe, and Ingredient factories.
Loop through all mod jars/directories and load /assets/MODID/recipes/_factories.json
Names will automatically be prefixed with modid domains. Error if name contains : to dissallow overriding other's factories
Gather Constants:
Done as a second pass to allow modders to depend on other mods ingredient factories
Loop through all mods, loading /assets/MODID/recipes/_constants.json
Add to a central dictionary as modid:name, so mods can't overlap eachother. Again, error if people try to overwrite other's
Load jsons from Mod Jars:
Loop through all mods, loading /assets/MODID/recipes/[!_factories && !_constants].json
Register to central regirsty as modid:jsonFileName like vanilla does
Fire RegistryEvent.Register<IRecipe>:
Fire code event to allow people to create recipes in code?
Loading from modpack/config folder?
Check Forge config for a 'recipes_folder', or explicitly check GameDir/custom_recipes and load all recipes there.
Loads from all asset domains, automatically skipping the ones that do not match a loaded modid.
This should behave the same as loading from a single jar file.
Should we add a global FACTORIES/CONSTANTS json?
Loading from world folder?
Same as loading from modpacks folder but happens afterwords so that worlds override both modpacks and jars.
Conditions:
Simple conditions to determine if we should load the recipe, or set the constant.
All entries must return true.
Allow custom condition types defined in FACTORIES?
Types to add:
mod_loaded: modid
item_exists: itemname
not: [conditions] -- Inverts a condition, can be nested
or: condition1, condition2
[
{
"conditions": [
{
"type": "mod_loaded",
"mod": "minecraft"
}
],
"name" : "PLANKS",
"ingredient" : {
"type" : "ore_dict",
"ore" : "planks"
}
},
{
"conditions": [
{
"type": "mod_loaded",
"mod": "xycraft"
}
],
"name": "PLANKS",
"ingredient" : {
"item" : "xycraft:planks"
}
},
{
"name": "OAK_OR_SPRUCE",
"ingredient": [
{
"item": "minecraft:log",
"data" : 0
},
{
"item": "minecraft:log",
"data" : 2
}
],
},
{
"name": "MIXED",
"ingredient": [
{
"type": "ore_dict",
"ore": "stick"
},
{
"item": "minecraft:torch"
}
]
},
{
"name": "PigEgg",
"ingredient": {
"type": "itemstack_nbt",
"item": "minecraft:mobegg",
"nbt": {
"entityId": "pig"
}
}
}
]
{
"ingredients" : {
"ore_dict": "net.minecraftforge.oredict.OreIngredientFactory",
"itemstack_nbt": "net.minecraftforge.util.NBTIngredientFactory",
},
"recipes" : {
"shapeless_ore" : "net.minecraftforge.oredict.ShapelessOreRecipeFactory",
"shaped_ore" : "net.minecraftforge.oredict.ShapedOreRecipeFactory"
}
}
{
"conditions": [
{
"type": "mod_loaded",
"mod": "minecraft"
}
],
"type": "minecraft:crafting_shaped",
"group": "random_things",
"pattern": [
"###",
"XXX"
],
"key": {
"#": {
"item": "#PLANKS"
},
"X": [
{
"item": "#PLANKS"
},
{
"item": "#MIXED",
},
{
"item": "minecraft:planks",
"data": 2
}
]
},
"result": {
"item": "minecraft:bed",
"data": 15
}
}
@Vectrobe
Copy link

Not sure if this was already covered, but there most definitely should be a recipe craft event to allow special conditions, such as blocking a craft with a certain variable or firing other events such as achievements...

@LexManos
Copy link
Author

THere is already an event like we've always had in Forge. This has nothing to do with that.

@darkevilmac
Copy link

Alright, thanks for the clarification.

@mcenderdragon
Copy link

The _constands do they only work for items or also for meta/data ? And is it possible to inject constands from code? I am aking because I have an item with many metas so typing #green_jar is better readable than 23.

@asiekierka
Copy link

asiekierka commented Jun 13, 2017

Looks reasonable and customizable. (Especially if in-code recipes are kept, though custom recipe factories should do the trick and give modpack creators more to play with.)

I'd honestly miss the ability to reload recipes - I used that feature with MineTweaker 3 a lot when developing a modpack, because it allowed me to very quickly push changes and get feedback from players. Do recipes need numeric IDs? Wouldn't ResourceLocation IDs avoid desyncing all of them on reload?

Could some of this system be generalized to apply to non-vanilla recipes? (Let's say, a custom crafting table, or even custom mod machines) It could potentially replace a huge chunk of what MineTweaker/ModTweaker were used for with proper compatibility across the board.

Singleplayer server load times would probably scale pretty quickly. Large modpacks can easily get to dozens of thousands of recipes. Since the registry is being frozen after vanilla's recipes are loaded, couldn't - similarly - mod/modpack recipes be loaded and frozen on postInit, at which point only world/server-specific recipes (and recipe deletions) would have to be reloaded?

EDIT: Could one use other mods' factories?

@marvin-roesch
Copy link

@mcenderdragon: As far as I understand it, you can specify any ingredient as a constant, so metadata or wholly custom data (through a custom factory) should be allowed.

@Alpvax
Copy link

Alpvax commented Jun 13, 2017

Am I missing something or is there a way to add custom conditions for general recipes? For example making beds only craftable based on a property of the player's capability. Is the only way to add a custom IRecipe implementation?

@marvin-roesch
Copy link

@Alpvax: There's no access to players in a generic crafting context (think automation, like Lex said). The only way to do it 'reliably' right now is a custom recipe implementation that checks the container, so a general purpose system can't really do this. The condition system as it is proposed here also is about loading a recipe, not whether it may be used on a case-to-case basis.

@Alpvax
Copy link

Alpvax commented Jun 13, 2017

@PaleoCrafter My mistake, I thought this was a way of adding conditions to recipes. Could the condition be registered as an ingredient or will ingredient be limited to items? My current approach has been to write wrappers every time I want to be able to use a custom condition, it would be really helpful if that could be done in the json files. I understand it would mean a re-write of the current 'AdvancedRecipe' implementation, but this seems to be a good time to do it. Then this system could be extended to custom recipe types (i.e. furnace, modded machines etc.).
Machines could then implement an IRecipeHandler interface, which could expose the required ingredients that the recipe would then check.

However, this seems more in-depth than currently required, and would need more thorough fleshing out, so I suggest leaving it for later (see what Mojang do for their customisable recipes implementation).

@LexManos
Copy link
Author

I've played around with the idea of freezing the registry after jar/code runs. And then causing the ServerInit load to just be mods folder/world folder. If we add those. However this would need to be on cpw as he's the one deeply familiar with the registry freezing system.

Again there is no plans on by default allowing a reload system. It uses numeric IDs for the recipe book and management of enabled recipes on both the server and the client. The GOOD thing is thats all encapsulated in one class. So we don't have to sync ids in world. But I see things like the client thinking you have a recipe unlocked but really the server says you have another one. It something we can address in the second pass once we see all the caveats of the current system, It would however require us to write custom registry syncing code that is done post-handshake.

As for custom recipe registries {Things that don't extend IRecipe} This system is fiarly generic, it really only hardcodes IRecipe in two places. The idea is that it might be able to be copy/pasted into a new registry for say.. macerators, or something. But im not sure how the recipe book would deal with that. So the goal is getting IRecipes working first, then see what we can do for custom stuff.

Yes you can use other mod's factories. The factories will be loaded in one global pass, then it'll do a single pass of constants+recipes.
You can NOT use other mod's constants. I see no reason to hard dep on that you can re-make the constant yourself using the mod its with a few conditionals.

No, these conditions are LOAD TIME. So specifying things like player cap checks in the json will not work. However, you're allowed to use your own custom IRecipeFactory which allows you runtime access, so you can go that way.

@Nuchaz
Copy link

Nuchaz commented Jun 13, 2017

Could we have a way to specify multiple result variants based on input ingredients in a single json? For example, I have a number of recipes that are identical with the exception of the wood type used so I get a different output for each wood type. The only thing really changing in that scenario is the meta data on each input/output. It would be nice if I could handle that in a single json. What if there was a sort of "output" tag that could be assigned to ingredients and that same tag could also be assigned to results. So we could have multiple results and each result would only use ingredients that either have a matching "output" tag or no tag at all. It would possibly look something like this: https://pastebin.com/J67vZ1u7

@Gaelan
Copy link

Gaelan commented Jun 14, 2017

The new constant system feels kind of redundant with oredict. Would it be possible to replace oredict with a "global" namespace for constants? Then mods could just add their wood blocks to global:LogWood in their constants.json.

@Alpvax
Copy link

Alpvax commented Jun 14, 2017

@Gaelan That just results in a json configurable oredict. I'm not sure that is beneficial.

Having runtime condition factories would be useful, they could be added as ingredients in json for more advanced modpack configuration.

@TechnicianLP
Copy link

TechnicianLP commented Jun 15, 2017

can it be made possible to specify multiple Recipes in one json? ie replace the top JsonObject witn an JsonArray, which then in return contains multiple JsonObjects (which have to be given a individual name manually)

@Dhranios
Copy link

I actually made a different recipes format as well; perhaps you could look into it, it may be of use to you too.
https://github.com/FVbico/MinecraftData/tree/master/minecraft/assets/server/recipes

@KitsuneAlex
Copy link

alright, RegistryEvent you are my friend

@TehenoPengin
Copy link

Thanks for leaving RegistryEvent option :P

@LexManos
Copy link
Author

Don't expect it as of 1.13, Its only in because I know people will bitch if its removed directly.
This is a first round of the json format. Its not perfect but its functional for 99% of use cases.

@MCOfficer
Copy link

MCOfficer commented Nov 5, 2017

i might be a bit late, but is there a way to set the amount of results? (e.g pumpkin -> pumpkin seeds)

@SkyBlade1978
Copy link

Is there any update on the correct procedure for removing a vanilla recipe in 1.12?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment