ProgressivePeripherals

ProgressivePeripherals

11.3k Downloads

[Improvement] recipe registry

ralphgod3 opened this issue ยท 2 comments

commented

Describe your idea

changes and additions for the recipe registry

preface

As SirEdvin is aware I have been trying to create an AE like system using purely computercraft,
This includes the autocrafting aspect.
Since I was unaware the recipe registry was a thing and to be honest it might not have been when I started writing the code.
I do some processing of recipes using external scripts to create something similar as the recipe registry tries to accomplish.
Once I was made aware the recipe registry exists i tried to use it but it has some flaws that prevent any normal (normal as in not someone with days or weeks of time to spare) person from using it.
The changes proposed should make the recipe registry more useful whilst simultaneously hopefully making it useful for people that are less advanced programmers or do not wish to invest the amount of time required to make it useful.

tools

As mentioned I have done quite a lot of this work already for my own ae clone whilst this clone uses computercraft and python/ C++ for the external scripts some of the tools might be useful for making design decisions.
git link
At the time of writing there is no documentation yet but the basic idea is that you put all mod jars and the forge jar in the input folder and then run jarextractor.py
This will create a bunch of folders and files in the output folder that can be used to view how certain mods store their recipes and what is needed to convert them.
note: My own recipe converter currently does not output recipes in the recipe format defined below since its mostly a proof of concept. Its the first thing on my todo list when a basic version for the external scripts is fully working.
I will try to update this with any issues I find when implementing my own ae clone.

Current flaws or lack of functionality

  1. Not all mods serialize their recipes in a to put it mildly convenient way. This leads to issues with the current implementation of the recipe registry.
    For example some minor differences like CC:tweaked using nbt tags to differentiate turtle types leads to the registry not returning a valid recipe at all.
    Some more extreme cases like ars_nouveau use a system where recipes have input items defined as named keys like item1, item2.
    Other mods like Immersive engineering and Mekanism add an extra layer to getting ingredients.

  2. For a user it is very hard to determine what recipe type is used to produce an item unless they keep a database.
    however building such a database should not be necessary for basic use of the registry since the block would be too complicated too use for any but the most dedicated computercraft users.

  3. It can be hard to convert a tag returned as an ingredient in a recipe to an item with that tag.

  4. The final issue for now is balance. It is extremely hard to effectively use the registry with the current cooldown value.

Current workarounds for the listed issues

  1. No simple workaround the only way to get around it is to build your own recipe database and converters which most people will not be able or do not want to do.
  2. build and keep a database with known recipe types for items. should this be done than the recipe registry loses some of its attractiveness to be used at all.
  3. Since the recipe registry is intended for people making ae like systems with computercraft it can be safely assumed that there will be no very new users using it.
    This means that it is viable for a user to get all tags of of any new item entering their storage solution and using that as a lookup table for recipes.
    The main disadvantage for doing this is that it makes it much harder to handle crafts that need other crafts for their ingredients at the start of the game.
  4. attach a bunch of registries over a wired network and iterate through them with each request. This idea does sound interesting but the current 5 second time is fairy long for each lookup.

API changes

The current API is rather limited and has problems dealing with certain recipes like computercraft turtle upgrades.

Changes to existing API

The current getRecipeFor is limited in that it will be unable to find recipes that only differ on nbt data.
A extra optional argument with nbt given as a hex string of a md5 hash (cc:tweaked returns them like this) or as just the nbt tags (ap inventory manager does this) would be needed to solve this issue.

Arguments for the changed function:

  • itemId
    itemId as a string ex: minecraft:oak_log
  • nbt
    optional argument given as a string.
    when given will only try to find recipes that match itemId and nbt tag in the result of recipe.
  • type
    recipeTypes to search in given as a table if multiple recipeTypes should be searched in, string for only 1 type or nil if all types should be returned.
    Whilst this might seem overpowered it is extremely hard for a user to determine programmatically without using external scripts or databases what recipetype creates an item.
    As to why this should still be an argument it is to allow the user to filter for recipe types they can create. for the mod this can speed up searching through the recipe types to speed up the function.

Returns:

  • table, nil
    table containing recipe info (check recipe structure definition) or nil when no recipe could be found.
--current api call
table getRecipeFor(string type, string itemId)

--proposed
--when nbt is nil then only recipes that do not give an item with nbt data as a result will be returned.
table getRecipesFor(string itemId, string | nil nbt, table | string | nil type)

New functions for the API

Some functionality to make the block easier in use should be considered.

This is not strictly necessary and might not even fit with what this peripheral does.
If the user wants to do sub component crafting for the recipe they actually want to create then this would be a very useful function to have.

Arguments for function:

  • tag
    string the tag that should be checked

Returns:

  • table, nil
    Table of items that have the given tag or nil if no item has the tag.
    table GetItemsForTag(string tag)

Recipe structure definition.

Preface

Whilst I obviously have a benefit into the recipe structure changing to this structure.
I genuinely believe that a standard format is needed and from my current experience with writing converters this format should be able to deal with most if not all mod recipes and should be relatively easy for the user to parse.

Proposed structure

Since a lot of mods serialize recipes in interesting ways it would make sense to return a standardized format to the user.
The format defined below should captures all information from every recipe type I have encountered thus far and should be easy enough for a user to parse and use.

this recipe format is also capable of accurately describing information about recipes crafted in machines as long as the converter to produce this format is consistent.
for example an ae2 inscriber might not have slot 1, 2, and 3 assigned the same way as the recipe format does but as long as the recipes are consistent in serialization the user can make a lookup table for this. This is also vastly preferred too having to parse roughly 80 different formats in ~200 mods that I tested with.

recipe = {
    --the minecraft way of item and tag doesn't work with all the mods. This is because of fluids, slurries, gasses and block based crafting. so separate it into a type
    --current options I found with my recipe converter that should cover most mods:
    --item, tag, fluid, block, fluidBlock, gass, slurry, infusion and fluidTag. I am not entirely sure fluidTag is needed. This needs more testing.
    --as to why it is needed on the result or output that is because some mods like immersive engineering can have tags as a result.
    type = "item",
    --optional nbt tag on return so user can get the exact required recipe using the api. this will have to be the hash of the nbt tags like cc does it.
    nbt = {},
    --name of the produced result
    result = "minecraft:diamond_pickaxe",
    --recipes to create this item, fluid, gas, slurry
    recipes = {
        {
            --recipe type
            type = "minecraft:crafting",
            --optional count tag if more than 1 is returned
            count = 1,
            --optional tags that define crafting table or input size, only given when size is non standard crafting size (not 3x3) and not just machine inputs.
            --progressive peripherals automata crafting and mechanical crafters from create will need this
            --this could also be left to the user to figure out based on the type of craft being performed
            width = 3,
            height = 3,
            recipe = {
                --recipe is always given as a shaped recipe since converting from unshaped to shaped is easy and it eliminates complexity on user side
                [1] = {
                    type = "tag",
                    name = "forge:gems/diamond",
                    --nbt and count tag are optional since user can check for it and if there isnt a tag it means item shouldnt have nbt and count = 1
                    count = 1,
                    --nbt can be given as the actual nbt or the md5 hash as cc does it.
                    nbt = {},
                },
                [2] = {
                    type = "tag",
                    name = "forge:gems/diamond",
                },
                [3] = {
                    type = "tag",
                    name = "forge:gems/diamond",
                },
                [5] = {

                    type = "tag",
                    name = "forge:rods/wooden",
                },
                [8] = {
                    type = "tag",
                    name = "forge:rods/wooden",
                },
            },
        },
        {
            --example of a machine recipe with 1 input
            type = "thermal:smelter",
            recipe = {
                --recipe is always given as a shaped recipe since converting from unshaped to shaped is easy and it eliminates complexity on user side
                [1] = {
                    type = "tag",
                    name = "forge:gems/diamond",
                    --nbt and count tag are optional since user can check for it and if there isnt a tag it means item shouldnt have nbt and count = 1
                    count = 5
                },
            },
        },
        {
            --example of a fluid machine recipe with 1 input
            type = "thermal:refinery",
            recipe = {
                [1] = {
                    type = "fluid",
                    name = "minecraft:water",
                    --for fluids count tag is the amount of mb needed or returned as a result, i propose stil naming it count or renaming count everywhere to amount to make parsing easier
                    count = 10000
                },
            },
        },
        {
            --example of a fluid machine recipe with 1 input
            type = "minecraft:crafting",
            --this recipe also returns or has the ability to return extra items
            optionalOutputs = 
            {
                {
                    --just as with the inputs and result the count and nbt tags are optional
                    type = "item",
                    name = "bloodmagic:blood_orb",
                },
                {
                    type = "item",
                    name = "minecraft:dirt",
                    -- a count that is not an integer indicates the recipe has chance to return the item but it is not guaranteed
                    --this would need some logic in the function to convert the various methods mods use to represent this but this should be the easiest for a user to handle
                    count = 0.5
                },
            },
            recipe = {
                [1] = {
                    --some mods like blood magic, mantle, tinkers construct and tetra modify some of the default assumptions made for recipes and need extra info.
                    --for these mods I propose simply serializing the extra info in the slotInfo for the recipe and having the user deal with it.
                    --there is as far as I could gather from testing no good standardized way of presenting this info to the user
                    type = "item",
                    name = "bloodmagic:blood_orb",
                    orb_tier = 3
                },
            },
        },
    },
}

Closing remarks

The things mentioned are from my own current experiences writing a recipe converter.
The recipe registry seems like a very interesting and powerful block it is however difficult to use effectively at the moment which may lead to people not using it at all.

Additional context

No response

Linked Issues

No response

commented
  • thermal:tree_extractor
  • thermal:tree_extractor_boost
  • thermal:rock_gen
  • thermal:potion_diffuser_boost
  • immersiveengineering:alloy
  • immersiveengineering:blast_furnace
  • immersiveengineering:blast_furnace_fuel #maybe doesnt need working recipes
  • immersiveengineering:coke_oven
  • immersiveengineering:cloche #cant setup plants automaticly i think but still no input is weird
  • immersiveengineering:fertilizer #no inputs, may not be needed
  • immersiveengineering:blueprint #no inputs, may not be needed
  • immersiveengineering:metal_press #no inputs
  • immersiveengineering:arc_furnace #no inputs
  • immersiveengineering:bottling #no inputs
  • immersiveengineering:crusher #no inputs
  • immersiveengineering:sawmill #no inputs
  • immersiveengineering:fermenter #no inputs, air as output
  • immersiveengineering:squeezer #no inputs, air as output
  • immersiveengineering:refinery #no inputs, air as output
  • immersiveengineering:mixer #no inputs, air as output
  • immersiveengineering:mineral_mix #should not be exported i think, also no inputs and air as output
  • integrateddynamics:drying_basin #no inputs
  • integrateddynamics:mechanical_drying_basin #no inputs
  • integrateddynamics:squeezer #no inputs
  • integrateddynamics:mechanical_squeezer #no inputs
  • botanypots:soil #should not be exported
  • botanypots:crop #no inputs, air as output, should not be exported
  • botanypots:fertilizer #no inputs
  • thermal:furnace #no inputs, output is air
  • thermal:sawmill #no inputs, output is air
  • thermal:pulverizer #no inputs, output is air
  • thermal:smeter #no inputs, output is air
  • thermal:insolator #no inputs, output is air
  • thermal:centrifuge #no inputs, output is air
  • thermal:press #no inputs, output is air
  • thermal:crucible #no inputs, output is air
  • thermal:chiller #no inputs, output is air
  • thermal:refinery #no inputs, output is air
  • thermal:bottler #no inputs, output is air
  • thermal:brewer #no recipes (should get minecraft:brewing or blacklisted from showing up)
  • thermal:pulverizer_catalyst #no inputs, output is air
  • thermal:smelter_catalyst #no inputs, output is air
  • thermal:insolator_catalyst #no inputs, output is air
  • thermal:stirling_fuel #no inputs, output is air shouldnt show as recipe
  • thermal:compression_fuel #no inputs, output is air shouldnt show as recipe
  • thermal:magmatic_fuel #no inputs, output is air shouldnt show as recipe
  • thermal:numismatic_fuel #no inputs, output is air shouldnt show as recipe
  • thermal:lapidary_fuel #no inputs, output is air shouldnt show as recipe
  • rftoolsutility:spawner #shouldnt show as recipe
  • titanium:test_serializer #shouldnt show up
  • minecraft:infusion #mythic botany, recipes are correct but it seems like a weird recipe handler name, comparing with my own should be mythicbotany:infusion, also has extra tag called mana
  • minecraft:rune_ritual #mythicbotany:rune_ritual and recipes show up wrong
  • astralsorcery:well #no inputs, output is air
  • astralsorcery:infusion #no inputs, output is air
  • astralsorcery:block_transmutaion #no inputs, output is air
  • astralsorcery:simple_altar #no inputs, output is air
  • astralsorcery:liquid_interaction #no inputs, output is air
  • industrialforegoing:fluid_extractor #inputs shown as output and output not shown
  • industrialforegoing:dissolution_chamber #no inputs
  • industrialforegoing:laser_drill_ore #shouldnt be shown, but if shown shouldnt produce air
  • industrialforegoing:laser_drill_fluid #shouldnt be shown, but if shown shouldnt produce air
  • industrialforegoing:stonework_generate #no inputs, output is air
  • industrialforegoing:crusher #no inputs, output is air
  • botania:elven_trade #output is minecraft:air
  • botania:pure_daisy #no inputs, output is air
  • botania:brew #inputs correct, output is air
  • naturesaura:altar #no inputs
  • naturesaura:animal_spawner #no inputs, output is air
  • naturesaura:offering #no inputs
  • naturesaura:tree_ritual #no inputs
  • mekanism:smelting #no recipes
  • pneumaticcraft:amadron #no inputs, output is air
  • pneumaticcraft:assembly_laser #no inputs, output is air
  • pneumaticcraft:assembly_drill #no inputs, output is air
  • pneumaticcraft:assembly_drill_laser #no recipes ?
  • pneumaticcraft:explosion_crafting #no inputs, output is air
  • pneumaticcraft:heat_frame_cooling #shouldnt show
  • pneumaticcraft:pressure_chamber #no inputs, output is air
  • pneumaticcraft:refinery #no inputs, output is air
  • pneumaticcraft:thermo_plant #no inputs, output is air
  • pneumaticcraft:fluid_mixer #no inputs, output is air
  • pneumaticcraft:fuel_quality #no inputs, output is air, should show fuel power outputs
  • pneumaticcraft:heat_properties #shouldnt show or show heat values
  • ars_nouveau:glyph_recipe #no inputs
  • ars_nouveau:enchanting_apparatus #no inputs
  • ars_nouveau:enchantment #shouldnt show ?
  • cyclic:melter #no outputs
  • create:conversion #no recipes ?
  • create:basin #no recipes ?
  • create:mixing #output is air
  • appliedenergistics2:entropy #no inputs, output is air
  • woot:factory #no inputs, output is air
  • mana-and-artifice:ritual-type #no inputs, output is air
  • mana-and-artifice:weaving-pattern-type #no inputs, output is air
  • mana-and-artifice:runescribing-type #no inputs, output is air
  • mana-and-artifice:runeforging-type #no inputs, output is air
  • mana-and-artifice:manaweaving-recipe-type #might not be broken but has no inputs, seems like an enchanting recipe
  • mana-and-artifice:shape-recipe-type #no inputs, output is air
  • mana-and-artifice:component-recipe-type #no inputs, output is air
  • mana-and-artifice:modifier-recipe-type #no inputs, output is air
  • mana-and-artifice:arcane-furnace-type #no inputs
  • tconstruct:part_builder #shouldnt show
  • tconstruct:material #shouldnt show
  • tconstruct:tinker_station #no inputs, output is air, shouldnt show
  • tconstruct:melting #output is air
  • tconstruct:entity_melting #no inputs, output is air
  • tconstruct:fuel #no inputs, output is air, should show fuel values
  • tconstruct:allooying #no inputs, output is air
  • tconstruct:severing #no inputs, output is air, shouldnt show ?
  • tconstruct:data #no inputs, output is air, shouldnt show
  • woot:dyesqueezer #no inputs, output is air
  • woot:infuser #no inputs, output is air
  • woot:anvil #output is air
  • woot:fluidconverter #no inputs, output is air
  • bloodmagic:altar #output is air, missing fluid input, missing altar tier
  • bloodmagic:array #output is air
  • bloodmagic:soulforge #no inputs, output is air, shoultn show ?
  • bloodmagic:arc #output is air
  • bloodmagic:alchemytable #no inputs, output is air
commented

So, I have finish with it. I will continue to add compact logic for mod that I like and this mod is big enough, but for rest mod of the list I just add examples of lua-side parsing.
You can track progress here #39