-
-
Save LexManos/2a11d4f7aa9d680d861dae4faf9dcfa6 to your computer and use it in GitHub Desktop.
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 | |
} | |
} |
A bit confused about lines 23 and 24.
Does this mean it will still be possible to register IRecipe implementations? And if so, why not just do this in preInit/Init like a lot of mods do already, is it to allow reloading of the recipe registry if needed?
Yes, see the note about why we're doing it in Server init. It is better future proofing to introduce modders to the idea that things should be done at ServerInit not at client load.
I don't think that reloading the registry after server init will be supported as it would mess up all client connections by desyncing all ids.
We'd have to guard everything with kicking everyone from the server. Which honestly might as well just restart the server then.
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...
THere is already an event like we've always had in Forge. This has nothing to do with that.
Alright, thanks for the clarification.
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.
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?
@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.
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?
@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.
@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).
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.
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
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.
@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.
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)
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
alright, RegistryEvent you are my friend
Thanks for leaving RegistryEvent option :P
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.
i might be a bit late, but is there a way to set the amount of results? (e.g pumpkin -> pumpkin seeds)
Is there any update on the correct procedure for removing a vanilla recipe in 1.12?
Factories WILL NOT be able to query and remove other recipes. If you MUST write a wrapper recipe, then wrap the recipe in the json.
Again, The mod specific json will NOT be allowed to modify recipes outside of your modid. So removing another mod's recipe and replacing it with your own via json will NOT be supported. That's the job of the modpack/world jsons/code.