RyanHub – file viewer
filename: fabricdatagen/src/main/java/rearth/oritech/fabricgen/datagen/RecipeGenerator.java
branch: 1.21
back to repo
package rearth.oritech.fabricgen.datagen;

import java.util.List;
import java.util.concurrent.CompletableFuture;

import dev.architectury.fluid.FluidStack;
import me.jddev0.ep.api.EPAPI;
import net.emilsg.clutter.Clutter;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.fabricmc.fabric.api.tag.convention.v2.ConventionalItemTags;
import net.fabricmc.fabric.impl.resource.conditions.conditions.AllModsLoadedResourceCondition;
import net.fabricmc.fabric.impl.resource.conditions.conditions.TagsPopulatedResourceCondition;
import net.minecraft.block.Blocks;
import net.minecraft.data.server.recipe.CraftingRecipeJsonBuilder;
import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.RecipeProvider;
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.Item;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.recipe.Ingredient;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.registry.Registries;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.util.Identifier;
import nourl.mythicmetals.MythicMetals;
import rearth.oritech.Oritech;
import rearth.oritech.api.recipe.AssemblerRecipeBuilder;
import rearth.oritech.api.recipe.AtomicForgeRecipeBuilder;
import rearth.oritech.api.recipe.AugmentRecipeBuilder;
import rearth.oritech.api.recipe.BioGeneratorRecipeBuilder;
import rearth.oritech.api.recipe.CentrifugeFluidRecipeBuilder;
import rearth.oritech.api.recipe.CentrifugeRecipeBuilder;
import rearth.oritech.api.recipe.CoolerRecipeBuilder;
import rearth.oritech.api.recipe.DeepDrillRecipeBuilder;
import rearth.oritech.api.recipe.FoundryRecipeBuilder;
import rearth.oritech.api.recipe.FuelGeneratorRecipeBuilder;
import rearth.oritech.api.recipe.GrinderRecipeBuilder;
import rearth.oritech.api.recipe.LaserRecipeBuilder;
import rearth.oritech.api.recipe.LavaGeneratorRecipeBuilder;
import rearth.oritech.api.recipe.ParticleCollisionRecipeBuilder;
import rearth.oritech.api.recipe.PulverizerRecipeBuilder;
import rearth.oritech.api.recipe.ReactorGeneratorRecipeBuilder;
import rearth.oritech.api.recipe.SteamGeneratorRecipeBuilder;
import rearth.oritech.api.recipe.util.MetalProcessingChainBuilder;
import rearth.oritech.fabricgen.datagen.compat.AlloyForgeryRecipeGenerator;
import rearth.oritech.fabricgen.datagen.compat.ClutterRecipeGenerator;
import rearth.oritech.fabricgen.datagen.compat.EnergizedPowerRecipeGenerator;
import rearth.oritech.fabricgen.datagen.compat.MythicMetalsRecipeGenerator;
import rearth.oritech.fabricgen.datagen.compat.TechRebornRecipeGenerator;
import rearth.oritech.init.BlockContent;
import rearth.oritech.init.FluidContent;
import rearth.oritech.init.ItemContent;
import rearth.oritech.init.TagContent;
import rearth.oritech.init.ToolsContent;
import techreborn.TechReborn;
import wraith.alloyforgery.AlloyForgery;

import static rearth.oritech.api.recipe.util.RecipeHelpers.*;
import static rearth.oritech.init.TagContent.cItemTag;

public class RecipeGenerator extends FabricRecipeProvider {
    
    public RecipeGenerator(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) {
        super(output, registriesFuture);
    }
    
    @Override
    public void generate(RecipeExporter exporter) {
        
        addDeepDrillOres(exporter);
        addFuels(exporter);
        addBiomass(exporter);
        addEquipment(exporter);
        addMachines(exporter);
        addComponents(exporter);
        addOreChains(exporter);
        addAlloys(exporter);
        addParticleCollisions(exporter);
        addDusts(exporter);
        addDecorative(exporter);
        addVanillaAdditions(exporter);
        addDyes(exporter);
        addCompactingRecipes(exporter);
        addReactorFuels(exporter);
        addLaserTransformations(exporter);
        addUraniumProcessing(exporter);
        addReactorBlocks(exporter);
        addAugmentRecipes(exporter);
        
        AlloyForgeryRecipeGenerator.generateRecipes(this.withConditions(exporter, new AllModsLoadedResourceCondition(List.of(AlloyForgery.MOD_ID))));
        ClutterRecipeGenerator.generateRecipes(this.withConditions(exporter, new AllModsLoadedResourceCondition(List.of(Clutter.MOD_ID))));
        EnergizedPowerRecipeGenerator.generateRecipes(this.withConditions(exporter, new AllModsLoadedResourceCondition(List.of(EPAPI.MOD_ID))));
        MythicMetalsRecipeGenerator.generateRecipes(this.withConditions(exporter, new AllModsLoadedResourceCondition(List.of(MythicMetals.MOD_ID))));
        TechRebornRecipeGenerator.generateRecipes(this.withConditions(exporter, new AllModsLoadedResourceCondition(List.of(TechReborn.MOD_ID))));
    }
    
    private void addVanillaAdditions(RecipeExporter exporter) {
        
        // slimeball from honey and biomass
        AssemblerRecipeBuilder.build().input(Items.HONEYCOMB).input(TagContent.BIOMASS).input(TagContent.BIOMASS).input(TagContent.BIOMASS).result(Items.SLIME_BALL).timeMultiplier(0.8f).export(exporter, "slime");
        // fireball in assembler (gunpowder, blaze powder + coal) = 5 charges
        AssemblerRecipeBuilder.build().input(Items.GUNPOWDER).input(Items.BLAZE_POWDER).input(ItemTags.COALS).input(ItemTags.COALS).result(Items.FIRE_CHARGE, 4).timeMultiplier(0.8f).export(exporter, "fireball");
        // blaze rod (4 powder in assembler)
        AssemblerRecipeBuilder.build().input(Items.BLAZE_POWDER).input(Items.BLAZE_POWDER).input(Items.BLAZE_POWDER).input(Items.BLAZE_POWDER).result(Items.BLAZE_ROD).timeMultiplier(0.8f).export(exporter, "blazerod");
        // enderic compound from sculk
        CentrifugeRecipeBuilder.build().input(Items.SCULK).result(ItemContent.ENDERIC_COMPOUND).timeMultiplier(4f).export(exporter, "endericsculk");
        // budding amethyst (amethyst shard x2, enderic compound, overcharged crystal)
        AssemblerRecipeBuilder.build().input(ConventionalItemTags.AMETHYST_GEMS).input(ConventionalItemTags.AMETHYST_GEMS).input(ItemContent.ENDERIC_COMPOUND).input(ItemContent.OVERCHARGED_CRYSTAL).result(Items.BUDDING_AMETHYST).time(160).export(exporter, "amethystbud");
        // netherite alloying (yes this is pretty OP)
        FoundryRecipeBuilder.build().input(ConventionalItemTags.GOLD_INGOTS).input(Items.NETHERITE_SCRAP).result(Items.NETHERITE_INGOT).export(exporter, "netherite");
        // books
        AssemblerRecipeBuilder.build().input(Items.PAPER).input(Items.PAPER).input(Items.PAPER).input(ConventionalItemTags.LEATHERS).result(Items.BOOK, 2).timeMultiplier(0.8f).export(exporter, "book");
        // reinforced deepslate
        AtomicForgeRecipeBuilder.build().input(Items.DEEPSLATE).input(ItemContent.DURATIUM_INGOT).input(ItemContent.DURATIUM_INGOT).result(Items.REINFORCED_DEEPSLATE).time(100).export(exporter, "reinfdeepslate");
        // cobblestone to gravel
        PulverizerRecipeBuilder.build().input(ConventionalItemTags.COBBLESTONES).result(Items.GRAVEL).addToGrinder().export(exporter, "gravel");
        // gravel to sand
        PulverizerRecipeBuilder.build().input(cItemTag("gravels")).result(Items.SAND).addToGrinder().export(exporter, "sand_from_gravel");
        // sandstone to sand
        PulverizerRecipeBuilder.build().input(ConventionalItemTags.SANDSTONE_BLOCKS).result(Items.SAND).addToGrinder().export(exporter, "sand_from_sandstone");
        // red sandstone to red sand
        PulverizerRecipeBuilder.build().input(ConventionalItemTags.RED_SANDSTONE_BLOCKS).result(Items.RED_SAND).addToGrinder().export(exporter, "red_sand");
        // centrifuge dirt into clay
        CentrifugeFluidRecipeBuilder.build().input(ItemTags.DIRT).result(Items.CLAY).fluidInput(Fluids.WATER, 0.25f).export(exporter, "clay");
        // create dirt from sand + biomass
        ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, Items.DIRT, 2).input('s', ItemTags.SAND).input('b', TagContent.BIOMASS).pattern("sb").pattern("bs").criterion("has_biomass", conditionsFromTag(TagContent.BIOMASS)).offerTo(exporter);
        // dripstone from dripstone block
        PulverizerRecipeBuilder.build().input(Items.DRIPSTONE_BLOCK).result(Items.POINTED_DRIPSTONE, 4).addToGrinder().export(exporter, "dripstone");
        // shroomlight from logs and 3 glowstone
        AssemblerRecipeBuilder.build().input(ItemTags.LOGS).input(Items.GLOWSTONE).input(Items.GLOWSTONE).input(Items.GLOWSTONE).result(Items.SHROOMLIGHT).timeMultiplier(0.8f).export(exporter, "shroomlight");
        // recyclables
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_NETHERITE_SCRAP).result(Items.NETHERITE_SCRAP).addToGrinder().export(exporter, "recycle/netherite_scrap");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_DIAMOND).result(Items.DIAMOND).addToGrinder().export(exporter, "recycle/diamond");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_IRON_DUST).result(ItemContent.IRON_DUST).addToGrinder().export(exporter, "recycle/iron_dust");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_SMALL_IRON_DUST).result(ItemContent.SMALL_IRON_DUST).export(exporter, "recycle/small_iron_dust");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_GOLD_DUST).result(ItemContent.GOLD_DUST).export(exporter, "recycle/gold_dust");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_SMALL_GOLD_DUST).result(ItemContent.SMALL_GOLD_DUST).export(exporter, "recycle/small_gold_dust");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_COPPER_DUST).result(ItemContent.COPPER_DUST).export(exporter, "recycle/copper_dust");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_SMALL_COPPER_DUST).result(ItemContent.SMALL_COPPER_DUST).export(exporter, "recycle/small_copper_dust");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_2_QUARTZ_DUST).result(ItemContent.QUARTZ_DUST, 2).export(exporter, "recycle/2_quartz_dust");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_4_QUARTZ_DUST).result(ItemContent.QUARTZ_DUST, 4).export(exporter, "recycle/4_quartz_dust");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_REDSTONE_DUST).result(Items.REDSTONE).export(exporter, "recycle/redstone_dust");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_GRAVEL).result(Items.GRAVEL).export(exporter, "recycle/gravel");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_SAND).result(Items.SAND).export(exporter, "recycle/sand");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_RED_SAND).result(Items.RED_SAND).export(exporter, "recycle/red_sand");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_STRING).result(Items.STRING, 3).export(exporter, "recycle/string");
        PulverizerRecipeBuilder.build().input(TagContent.RECYCLES_TO_BIOMASS).result(ItemContent.BIOMASS).export(exporter, "recycle/biomass");
    }
    
    private void addDyes(RecipeExporter exporter) {
        PulverizerRecipeBuilder.build().input(TagContent.RAW_WHITE_DYE).result(Items.WHITE_DYE).addToGrinder().export(exporter, "dyes/white");
        PulverizerRecipeBuilder.build().input(TagContent.RAW_LIGHT_GRAY_DYE).result(Items.LIGHT_GRAY_DYE).addToGrinder().export(exporter, "dyes/light_gray");
        PulverizerRecipeBuilder.build().input(TagContent.RAW_BLACK_DYE).result(Items.BLACK_DYE).addToGrinder().export(exporter, "dyes/black");
        PulverizerRecipeBuilder.build().input(TagContent.RAW_RED_DYE).result(Items.RED_DYE).addToGrinder().export(exporter, "dyes/red");
        PulverizerRecipeBuilder.build().input(TagContent.RAW_ORANGE_DYE).result(Items.ORANGE_DYE).addToGrinder().export(exporter, "dyes/orange");
        PulverizerRecipeBuilder.build().input(TagContent.RAW_YELLOW_DYE).result(Items.YELLOW_DYE).addToGrinder().export(exporter, "dyes/yellow");
        PulverizerRecipeBuilder.build().input(TagContent.RAW_CYAN_DYE).result(Items.CYAN_DYE).addToGrinder().export(exporter, "dyes/cyan");
        PulverizerRecipeBuilder.build().input(TagContent.RAW_BLUE_DYE).result(Items.BLUE_DYE).addToGrinder().export(exporter, "dyes/blue");
        PulverizerRecipeBuilder.build().input(TagContent.RAW_MAGENTA_DYE).result(Items.MAGENTA_DYE).addToGrinder().export(exporter, "dyes/magenta");
        PulverizerRecipeBuilder.build().input(TagContent.RAW_PINK_DYE).result(Items.PINK_DYE).addToGrinder().export(exporter, "dyes/pink");
    }
    
    private void addDeepDrillOres(RecipeExporter exporter) {
        DeepDrillRecipeBuilder.build().input(BlockContent.RESOURCE_NODE_REDSTONE).result(Items.REDSTONE).export(exporter, "redstone");
        DeepDrillRecipeBuilder.build().input(BlockContent.RESOURCE_NODE_LAPIS).result(Items.LAPIS_LAZULI).export(exporter, "lapis");
        DeepDrillRecipeBuilder.build().input(BlockContent.RESOURCE_NODE_IRON).result(Items.RAW_IRON).export(exporter, "iron");
        DeepDrillRecipeBuilder.build().input(BlockContent.RESOURCE_NODE_COAL).result(Items.COAL).export(exporter, "coal");
        DeepDrillRecipeBuilder.build().input(BlockContent.RESOURCE_NODE_COPPER).result(Items.RAW_COPPER).export(exporter, "copper");
        DeepDrillRecipeBuilder.build().input(BlockContent.RESOURCE_NODE_GOLD).result(Items.RAW_GOLD).export(exporter, "gold");
        DeepDrillRecipeBuilder.build().input(BlockContent.RESOURCE_NODE_EMERALD).result(Items.EMERALD).export(exporter, "emerald");
        DeepDrillRecipeBuilder.build().input(BlockContent.RESOURCE_NODE_DIAMOND).result(Items.DIAMOND).export(exporter, "diamond");
        DeepDrillRecipeBuilder.build().input(BlockContent.RESOURCE_NODE_NICKEL).result(ItemContent.RAW_NICKEL).export(exporter, "nickel");
        DeepDrillRecipeBuilder.build().input(BlockContent.RESOURCE_NODE_PLATINUM).result(ItemContent.RAW_PLATINUM).export(exporter, "platinum");
        DeepDrillRecipeBuilder.build().input(BlockContent.RESOURCE_NODE_URANIUM).result(ItemContent.RAW_URANIUM).export(exporter, "uranium");
    }
    
    private void addFuels(RecipeExporter exporter) {
        
        // bio
        BioGeneratorRecipeBuilder.build().input(TagContent.BIOMATTER).timeInSeconds(15).export(exporter, "rawbio");
        BioGeneratorRecipeBuilder.build().input(ItemContent.PACKED_WHEAT).timeInSeconds(200).export(exporter, "packedwheat");
        BioGeneratorRecipeBuilder.build().input(TagContent.BIOMASS).timeInSeconds(25).export(exporter, "biomass");
        BioGeneratorRecipeBuilder.build().input(ItemContent.SOLID_BIOFUEL).timeInSeconds(160).export(exporter, "solidbiomass");
        BioGeneratorRecipeBuilder.build().input(TagContent.BIOMASS_BLOCK).timeInSeconds(270).export(exporter, "biomassblock");
        BioGeneratorRecipeBuilder.build().input(ItemContent.RAW_BIOPOLYMER).timeInSeconds(300).export(exporter, "polymer");
        BioGeneratorRecipeBuilder.build().input(ItemContent.UNHOLY_INTELLIGENCE).timeInSeconds(3000).export(exporter, "vex");
        // lava
        LavaGeneratorRecipeBuilder.build().fluidInput(Fluids.LAVA, 0.1f).timeInSeconds(12).export(exporter, "lava");
        // fuel
        FuelGeneratorRecipeBuilder.build().fluidInput(FluidContent.STILL_OIL.get(), 0.1f).timeInSeconds(3).export(exporter, "crude");
        FuelGeneratorRecipeBuilder.build().fluidInput(FluidContent.STILL_FUEL.get(), 0.1f).timeInSeconds(12).export(exporter, "fuel");
        //steam
        SteamGeneratorRecipeBuilder.build().fluidInput(FluidStack.create(FluidContent.STILL_STEAM.get(), 32)).time(1).export(exporter, "steameng");
    }
    
    private void addBiomass(RecipeExporter exporter) {
        // biomass
        PulverizerRecipeBuilder.build().input(TagContent.BIOMATTER).result(ItemContent.BIOMASS).addToGrinder().export(exporter, "biobasic");
        PulverizerRecipeBuilder.build().input(ItemContent.PACKED_WHEAT).result(ItemContent.BIOMASS, 16).addToGrinder().export(exporter, "packagedwheatbio");
        PulverizerRecipeBuilder.build().input(cItemTag("storage_blocks/wheat")).result(ItemContent.BIOMASS, 16).addToGrinder().export(exporter, "hay_block");
        AssemblerRecipeBuilder.build().input(TagContent.BIOMASS).input(TagContent.BIOMASS).input(TagContent.BIOMASS).input(ItemTags.PLANKS).result(ItemContent.SOLID_BIOFUEL).timeMultiplier(0.8f).export(exporter, "solidbiofuel");
    }
    
    private void addEquipment(RecipeExporter exporter) {
        offerDrillRecipe(exporter, ToolsContent.HAND_DRILL, of(TagContent.STEEL_INGOTS), of(ItemContent.MOTOR), of(ItemContent.ENDERIC_COMPOUND), of(ItemContent.ADAMANT_INGOT), "handdrill");
        offerChainsawRecipe(exporter, ToolsContent.CHAINSAW, of(TagContent.STEEL_INGOTS), of(ItemContent.MOTOR), of(ItemContent.ENDERIC_COMPOUND), of(ItemContent.ADAMANT_INGOT), "chainsaw");
        offerAxeRecipe(exporter, ToolsContent.PROMETHIUM_AXE, of(ItemContent.PROMETHEUM_INGOT), of(BlockContent.DESTROYER_BLOCK.asItem()), "promaxe");
        offerPickaxeRecipe(exporter, ToolsContent.PROMETHIUM_PICKAXE, of(ItemContent.PROMETHEUM_INGOT), of(BlockContent.DESTROYER_BLOCK.asItem()), "prompick");
        
        // designator
        offerDrillRecipe(exporter, ItemContent.TARGET_DESIGNATOR, of(TagContent.STEEL_INGOTS), of(TagContent.ELECTRUM_INGOTS), of(ItemContent.PROCESSING_UNIT), of(TagContent.PLASTIC_PLATES), "designator");
        // weed killer
        offerDrillRecipe(exporter, ItemContent.WEED_KILLER, of(ConventionalItemTags.FOOD_POISONING_FOODS), of(ConventionalItemTags.FOOD_POISONING_FOODS), of(ItemContent.RAW_BIOPOLYMER), of(Items.GLASS_BOTTLE), "weedex");
        // wrench
        offerWrenchRecipe(exporter, ItemContent.WRENCH, of(TagContent.STEEL_INGOTS), of(TagContent.NICKEL_INGOTS), "wrench");
        
        // helmet (enderic lens + machine plating)
        offerHelmetRecipe(exporter, ToolsContent.EXO_HELMET, of(TagContent.MACHINE_PLATING), of(ItemContent.ENDERIC_LENS), "exohelm");
        // chestplate (advanced battery + machine plating)
        offerChestplateRecipe(exporter, ToolsContent.EXO_CHESTPLATE, of(TagContent.MACHINE_PLATING), of(ItemContent.ADVANCED_BATTERY), "exochest");
        // legs (motor + plating)
        offerLegsRecipe(exporter, ToolsContent.EXO_LEGGINGS, of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), "exolegs");
        // feet (silicon + plating)
        offerFeetRecipe(exporter, ToolsContent.EXO_BOOTS, of(TagContent.MACHINE_PLATING), of(TagContent.SILICON), "exoboots");
        
        // basic jetpack main
        offerParticleMotorRecipe(exporter, ToolsContent.JETPACK, of(TagContent.STEEL_INGOTS), of(ConventionalItemTags.LEATHERS), of(ItemContent.ADVANCED_BATTERY), of(Items.GUNPOWDER), "basicjetpack");
        // jetpack alt
        offerParticleMotorRecipe(exporter, ToolsContent.JETPACK, of(TagContent.STEEL_INGOTS), of(ConventionalItemTags.LEATHERS), of(Items.REDSTONE_BLOCK), of(Items.BLAZE_POWDER), "basicjetpackalt");
        // exo jetpack
        offerGeneratorRecipe(exporter, ToolsContent.EXO_JETPACK, of(ToolsContent.JETPACK), of(BlockContent.SMALL_TANK_BLOCK), of(ToolsContent.EXO_CHESTPLATE), of(TagContent.PLASTIC_PLATES), "exojetpack");
        // boosted elytra
        offerGeneratorRecipe(exporter, ToolsContent.JETPACK_ELYTRA, of(Items.ELYTRA), of(ItemContent.PROCESSING_UNIT), of(ToolsContent.JETPACK), of(Items.GUNPOWDER), "boostedelytra");
        // exo elytra (exo jetpack + elytra)
        offerGeneratorRecipe(exporter, ToolsContent.JETPACK_EXO_ELYTRA, of(ToolsContent.EXO_JETPACK), of(ItemContent.PROCESSING_UNIT), of(Items.ELYTRA), of(Items.GUNPOWDER), "exoboostedelytra");
        // exo elytra (boosted elytra + exo chestplate)
        offerGeneratorRecipe(exporter, ToolsContent.JETPACK_EXO_ELYTRA, of(ToolsContent.EXO_CHESTPLATE), of(BlockContent.SMALL_TANK_BLOCK), of(ToolsContent.JETPACK_ELYTRA), of(TagContent.PLASTIC_PLATES), "exoboostedelytraalt");
        
    }
    
    private void addDecorative(RecipeExporter exporter) {
        // ceiling light
        offerInsulatedCableRecipe(exporter, new ItemStack(BlockContent.CEILING_LIGHT.asItem(), 6), of(Items.GLOWSTONE_DUST), of(TagContent.STEEL_INGOTS), "ceilightlight");
        // hanging light
        offerTwoComponentRecipe(exporter, BlockContent.CEILING_LIGHT_HANGING.asItem(), of(ConventionalItemTags.CHAINS), of(BlockContent.CEILING_LIGHT.asItem()), "hanginglight");
        // tech button
        offerLeverRecipe(exporter, BlockContent.TECH_BUTTON.asItem(), of(ConventionalItemTags.COPPER_INGOTS), of(TagContent.STEEL_INGOTS), "techbutton");
        // tech lever
        offerLeverRecipe(exporter, BlockContent.TECH_LEVER.asItem(), of(TagContent.CARBON_FIBRE), of(TagContent.STEEL_INGOTS), "techlever");
        // tech door
        offerDoorRecipe(exporter, BlockContent.TECH_DOOR.asItem(), of(TagContent.STEEL_INGOTS), "techdoor");
        // metal beam
        offerInsulatedCableRecipe(exporter, new ItemStack(BlockContent.METAL_BEAM_BLOCK.asItem(), 6), of(TagContent.CARBON_FIBRE), of(TagContent.STEEL_INGOTS), "metalbeams");
        // tech glass
        offerMachinePlatingRecipe(exporter, BlockContent.INDUSTRIAL_GLASS_BLOCK.asItem(), of(TagContent.STEEL_INGOTS), of(ConventionalItemTags.GLASS_BLOCKS), of(TagContent.MACHINE_PLATING), 4, "industrialglass");
        // machine plated stairs, slabs, pressure plates
        offerSlabRecipe(exporter, BlockContent.MACHINE_PLATING_SLAB.asItem(), of(BlockContent.MACHINE_PLATING_BLOCK.asItem()), "machine");
        offerStairsRecipe(exporter, BlockContent.MACHINE_PLATING_STAIRS.asItem(), of(BlockContent.MACHINE_PLATING_BLOCK.asItem()), "machine");
        offerPressurePlateRecipe(exporter, BlockContent.MACHINE_PLATING_PRESSURE_PLATE.asItem(), of(BlockContent.MACHINE_PLATING_BLOCK.asItem()), "machine");
        // iron plated stairs, slabs, pressure plates
        offerSlabRecipe(exporter, BlockContent.IRON_PLATING_SLAB.asItem(), of(BlockContent.IRON_PLATING_BLOCK.asItem()), "iron");
        offerStairsRecipe(exporter, BlockContent.IRON_PLATING_STAIRS.asItem(), of(BlockContent.IRON_PLATING_BLOCK.asItem()), "iron");
        offerPressurePlateRecipe(exporter, BlockContent.IRON_PLATING_PRESSURE_PLATE.asItem(), of(BlockContent.IRON_PLATING_BLOCK.asItem()), "iron");
        // nickel plated stairs, slabs, pressure plates
        offerSlabRecipe(exporter, BlockContent.NICKEL_PLATING_SLAB.asItem(), of(BlockContent.NICKEL_PLATING_BLOCK.asItem()), "nickel");
        offerStairsRecipe(exporter, BlockContent.NICKEL_PLATING_STAIRS.asItem(), of(BlockContent.NICKEL_PLATING_BLOCK.asItem()), "nickel");
        offerPressurePlateRecipe(exporter, BlockContent.NICKEL_PLATING_PRESSURE_PLATE.asItem(), of(BlockContent.NICKEL_PLATING_BLOCK.asItem()), "nickel");
    }
    
    private void addMachines(RecipeExporter exporter) {
        // basic generator
        offerGeneratorRecipe(exporter, BlockContent.BASIC_GENERATOR_BLOCK.asItem(), of(ConventionalItemTags.PLAYER_WORKSTATIONS_FURNACES), of(ItemContent.MAGNETIC_COIL), of(ConventionalItemTags.COPPER_INGOTS), of(TagContent.NICKEL_INGOTS), "basicgen");
        // pulverizer
        offerGeneratorRecipe(exporter, BlockContent.PULVERIZER_BLOCK.asItem(), of(ConventionalItemTags.STORAGE_BLOCKS_IRON), of(ItemContent.MOTOR), of(TagContent.NICKEL_INGOTS), of(TagContent.STEEL_INGOTS), "pulverizer");
        offerGeneratorRecipe(exporter, BlockContent.PULVERIZER_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), of(TagContent.NICKEL_INGOTS), of(TagContent.STEEL_INGOTS), "pulverizeralt");
        // electric furnace
        offerFurnaceRecipe(exporter, BlockContent.POWERED_FURNACE_BLOCK.asItem(), of(ConventionalItemTags.PLAYER_WORKSTATIONS_FURNACES), of(ItemContent.MAGNETIC_COIL), of(TagContent.SILICON), of(TagContent.ELECTRUM_INGOTS), of(ConventionalItemTags.COPPER_INGOTS), "electricfurnace");
        offerFurnaceRecipe(exporter, BlockContent.POWERED_FURNACE_BLOCK.asItem(), of(ConventionalItemTags.PLAYER_WORKSTATIONS_FURNACES), of(ItemContent.MAGNETIC_COIL), of(TagContent.PLATINUM_INGOTS), of(TagContent.ELECTRUM_INGOTS), of(ConventionalItemTags.COPPER_INGOTS), "electricfurnacealt");
        // assembler
        offerFurnaceRecipe(exporter, BlockContent.ASSEMBLER_BLOCK.asItem(), of(Blocks.BLAST_FURNACE.asItem()), of(ItemContent.MOTOR), of(Items.CRAFTER), of(ItemContent.ADAMANT_INGOT), of(ConventionalItemTags.COPPER_INGOTS), "assembler");
        offerFurnaceRecipe(exporter, BlockContent.ASSEMBLER_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), of(Items.CRAFTER), of(ItemContent.ADAMANT_INGOT), of(ConventionalItemTags.COPPER_INGOTS), "assembleralt");
        // foundry
        offerGeneratorRecipe(exporter, BlockContent.FOUNDRY_BLOCK.asItem(), of(Blocks.CAULDRON.asItem()), of(TagContent.ELECTRUM_INGOTS), of(ItemContent.MOTOR), of(ConventionalItemTags.COPPER_INGOTS), "foundry");
        // cooler
        offerGeneratorRecipe(exporter, BlockContent.COOLER_BLOCK.asItem(), of(Blocks.CAULDRON.asItem()), of(Blocks.ICE.asItem()), of(ItemContent.MOTOR), of(ConventionalItemTags.IRON_INGOTS), "cooler");
        // centrifuge
        offerFurnaceRecipe(exporter, BlockContent.CENTRIFUGE_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.PROCESSING_UNIT), of(ItemContent.MOTOR), of(TagContent.STEEL_INGOTS), of(Items.GLASS_BOTTLE), "centrifuge");
        offerFurnaceRecipe(exporter, BlockContent.CENTRIFUGE_BLOCK.asItem(), of(ItemContent.MOTOR), of(ConventionalItemTags.STORAGE_BLOCKS_IRON), of(ConventionalItemTags.COPPER_INGOTS), of(ItemContent.MOTOR), of(Items.GLASS_BOTTLE), "centrifugealt");
        // laser arm
        offerAtomicForgeRecipe(exporter, BlockContent.LASER_ARM_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), of(TagContent.ELECTRUM_INGOTS), of(ItemContent.ENDERIC_LENS), of(TagContent.CARBON_FIBRE), "laserarm");
        // crusher
        offerGeneratorRecipe(exporter, BlockContent.FRAGMENT_FORGE_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), of(ItemContent.FLUX_GATE), of(TagContent.PLASTIC_PLATES), "crusher");
        // atomic forge
        offerAtomicForgeRecipe(exporter, BlockContent.ATOMIC_FORGE_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(TagContent.PLASTIC_PLATES), of(ItemContent.ENDERIC_COMPOUND), of(ItemContent.DURATIUM_INGOT), of(ItemContent.FLUX_GATE), "atomicforge");
        
        // biofuel generator
        offerGeneratorRecipe(exporter, BlockContent.BIO_GENERATOR_BLOCK.asItem(), of(BlockContent.BASIC_GENERATOR_BLOCK.asItem()), of(ItemContent.MAGNETIC_COIL), of(ItemContent.FLUX_GATE), of(ItemContent.BIOSTEEL_INGOT), "biogen");
        // lava generator
        offerGeneratorRecipe(exporter, BlockContent.LAVA_GENERATOR_BLOCK.asItem(), of(BlockContent.BASIC_GENERATOR_BLOCK.asItem()), of(TagContent.MACHINE_PLATING), of(ItemContent.MAGNETIC_COIL), of(TagContent.ELECTRUM_INGOTS), "lavagen");
        // steam engine
        offerGeneratorRecipe(exporter, BlockContent.STEAM_ENGINE_BLOCK.asItem(), of(BlockContent.BASIC_GENERATOR_BLOCK.asItem()), of(ConventionalItemTags.COPPER_INGOTS), of(ItemContent.MAGNETIC_COIL), of(TagContent.ELECTRUM_INGOTS), "steamgen");
        // diesel generator
        offerGeneratorRecipe(exporter, BlockContent.FUEL_GENERATOR_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(BlockContent.BASIC_GENERATOR_BLOCK), of(ItemContent.ENDERIC_LENS), of(TagContent.STEEL_INGOTS), "fuelgen");
        // large solar
        offerGeneratorRecipe(exporter, BlockContent.BIG_SOLAR_PANEL_BLOCK.asItem(), of(BlockContent.BASIC_GENERATOR_BLOCK.asItem()), of(ItemContent.FLUX_GATE), of(ItemContent.ADVANCED_BATTERY), of(ItemContent.FLUXITE), "solar");
        
        // charger
        offerAtomicForgeRecipe(exporter, BlockContent.CHARGER_BLOCK.asItem(), of(ConventionalItemTags.WOODEN_CHESTS), of(BlockContent.ENERGY_PIPE), of(ConventionalItemTags.STORAGE_BLOCKS_REDSTONE), of(Items.DISPENSER), of(TagContent.STEEL_INGOTS), "charger");
        offerAtomicForgeRecipe(exporter, BlockContent.CHARGER_BLOCK.asItem(), of(ConventionalItemTags.WOODEN_CHESTS), of(BlockContent.ENERGY_PIPE), of(ItemContent.PROCESSING_UNIT), of(Items.DISPENSER), of(TagContent.STEEL_INGOTS), "chargeralt");
        
        // small storage
        offerAtomicForgeRecipe(exporter, BlockContent.SMALL_STORAGE_BLOCK.asItem(), of(ItemContent.BASIC_BATTERY), of(TagContent.SILICON), of(ItemContent.MAGNETIC_COIL), of(TagContent.NICKEL_INGOTS), of(TagContent.WIRES), "smallstorage");
        // large storage
        offerAtomicForgeRecipe(exporter, BlockContent.LARGE_STORAGE_BLOCK.asItem(), of(ItemContent.ADVANCED_BATTERY), of(TagContent.STEEL_INGOTS), of(ItemContent.DUBIOS_CONTAINER), of(ItemContent.FLUX_GATE), of(TagContent.WIRES), "bigstorage");
        // unstable container
        offerAtomicForgeRecipe(exporter, ItemContent.UNSTABLE_CONTAINER, of(ItemContent.FLUXITE), of(ItemContent.DURATIUM_INGOT), of(BlockContent.LARGE_STORAGE_BLOCK), of(ItemContent.FLUX_GATE), of(ItemContent.SUPER_AI_CHIP), "unstablecontainer");
        
        // fluid tank
        offerTankRecipe(exporter, BlockContent.SMALL_TANK_BLOCK.asItem(), of(ConventionalItemTags.COPPER_INGOTS), of(ConventionalItemTags.GLASS_BLOCKS), of(BlockContent.FLUID_PIPE.asItem()), "stank");
        // pump
        offerGeneratorRecipe(exporter, BlockContent.PUMP_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(TagContent.SILICON), of(ItemContent.MOTOR), of(ConventionalItemTags.COPPER_INGOTS), "pump");
        // block placer
        offerFurnaceRecipe(exporter, BlockContent.PLACER_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), of(ItemContent.PROCESSING_UNIT), of(BlockContent.MACHINE_FRAME_BLOCK.asItem()), of(ConventionalItemTags.COPPER_INGOTS), "placer");
        // block destroyer
        offerAtomicForgeRecipe(exporter, BlockContent.DESTROYER_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), of(BlockContent.PULVERIZER_BLOCK), of(BlockContent.LASER_ARM_BLOCK), of(ItemContent.MOTOR), "destroyer");
        // fertilizer
        offerFurnaceRecipe(exporter, BlockContent.FERTILIZER_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), of(TagContent.SILICON), of(ItemContent.PROCESSING_UNIT), of(ConventionalItemTags.COPPER_INGOTS), "fertilizer");
        // tree feller
        offerGeneratorRecipe(exporter, BlockContent.TREEFELLER_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(Items.IRON_AXE), of(ItemContent.MOTOR), of(TagContent.ELECTRUM_INGOTS), "treefeller");
        // pipe booster
        offerTankRecipe(exporter, BlockContent.PIPE_BOOSTER_BLOCK.asItem(), of(BlockContent.ITEM_PIPE), of(ItemContent.MOTOR), of(BlockContent.FLUID_PIPE), "booster");
        
        // machine frame
        offerMachineFrameRecipe(exporter, BlockContent.MACHINE_FRAME_BLOCK.asItem(), of(Items.IRON_BARS), of(TagContent.NICKEL_INGOTS), 16, "frame");
        // energy pipe
        offerInsulatedCableRecipe(exporter, new ItemStack(BlockContent.ENERGY_PIPE.asItem(), 6), of(TagContent.ELECTRUM_INGOTS), of(TagContent.WIRES), "energy");
        // item pipe
        offerInsulatedCableRecipe(exporter, new ItemStack(BlockContent.ITEM_PIPE.asItem(), 6), of(TagContent.NICKEL_INGOTS), of(ItemTags.PLANKS), "item");
        // item filter
        offerGeneratorRecipe(exporter, BlockContent.ITEM_FILTER_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(TagContent.WIRES), of(ItemContent.PROCESSING_UNIT), of(TagContent.WIRES), "itemfilter");
        // fluid pipe
        offerInsulatedCableRecipe(exporter, new ItemStack(BlockContent.FLUID_PIPE.asItem(), 6), of(TagContent.SILICON), of(ConventionalItemTags.COPPER_INGOTS), "fluidpipe");
        
        // framed energy pipe
        offerFramedCableRecipe(exporter, new ItemStack(BlockContent.FRAMED_ENERGY_PIPE, 8), of(BlockContent.ENERGY_PIPE), "energy");
        offerCableFromFrameRecipe(exporter, new ItemStack(BlockContent.ENERGY_PIPE, 1), of(BlockContent.FRAMED_ENERGY_PIPE), "energy");
        // framed superconductor
        offerFramedCableRecipe(exporter, new ItemStack(BlockContent.FRAMED_SUPERCONDUCTOR, 8), of(BlockContent.SUPERCONDUCTOR.asItem()), "superconductor");
        offerCableFromFrameRecipe(exporter, new ItemStack(BlockContent.SUPERCONDUCTOR.asItem(), 1), of(BlockContent.FRAMED_SUPERCONDUCTOR), "superconductor");
        // framed fluid pipe
        offerFramedCableRecipe(exporter, new ItemStack(BlockContent.FRAMED_FLUID_PIPE, 8), of(BlockContent.FLUID_PIPE), "fluid");
        offerCableFromFrameRecipe(exporter, new ItemStack(BlockContent.FLUID_PIPE, 1), of(BlockContent.FRAMED_FLUID_PIPE), "fluid");
        // framed item pipe
        offerFramedCableRecipe(exporter, new ItemStack(BlockContent.FRAMED_ITEM_PIPE, 8), of(BlockContent.ITEM_PIPE), "item");
        offerCableFromFrameRecipe(exporter, new ItemStack(BlockContent.ITEM_PIPE, 1), of(BlockContent.FRAMED_ITEM_PIPE), "item");
        
        // transparent pipe
        offerTankRecipe(exporter, BlockContent.TRANSPARENT_ITEM_PIPE.asItem(), 6, of(ItemTags.PLANKS), of(TagContent.NICKEL_INGOTS), of(ConventionalItemTags.GLASS_BLOCKS), "transparentitem");
        offerMachineCoreRecipe(exporter, BlockContent.TRANSPARENT_ITEM_PIPE.asItem(), 8, of(BlockContent.ITEM_PIPE), of(ConventionalItemTags.GLASS_BLOCKS), "totransparent");
        offerMachineCoreRecipe(exporter, BlockContent.ITEM_PIPE.asItem(), 8, of(BlockContent.TRANSPARENT_ITEM_PIPE), of(ItemTags.PLANKS), "fromtransparent");
        
        // energy pipe duct
        offerCableDuctRecipe(exporter, new ItemStack(BlockContent.ENERGY_PIPE_DUCT_BLOCK, 4), of(BlockContent.ENERGY_PIPE), "energy");
        offerCableFromDuctRecipe(exporter, new ItemStack(BlockContent.ENERGY_PIPE, 1), of(BlockContent.ENERGY_PIPE_DUCT_BLOCK), "energy");
        // superconductor duct
        offerCableDuctRecipe(exporter, new ItemStack(BlockContent.SUPERCONDUCTOR_DUCT_BLOCK, 4), of(BlockContent.SUPERCONDUCTOR.asItem()), "superconductor");
        offerCableFromDuctRecipe(exporter, new ItemStack(BlockContent.SUPERCONDUCTOR.asItem(), 1), of(BlockContent.SUPERCONDUCTOR_DUCT_BLOCK), "superconductor");
        // fluid pipe duct
        offerCableDuctRecipe(exporter, new ItemStack(BlockContent.FLUID_PIPE_DUCT_BLOCK, 4), of(BlockContent.FLUID_PIPE), "fluid");
        offerCableFromDuctRecipe(exporter, new ItemStack(BlockContent.FLUID_PIPE, 1), of(BlockContent.FLUID_PIPE_DUCT_BLOCK), "fluid");
        // item pipe duct
        offerCableDuctRecipe(exporter, new ItemStack(BlockContent.ITEM_PIPE_DUCT_BLOCK, 4), of(BlockContent.ITEM_PIPE), "item");
        offerCableFromDuctRecipe(exporter, new ItemStack(BlockContent.ITEM_PIPE, 1), of(BlockContent.ITEM_PIPE_DUCT_BLOCK), "item");
        
        // deep drill
        offerAtomicForgeRecipe(exporter, BlockContent.DEEP_DRILL_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), of(ItemContent.HEISENBERG_COMPENSATOR), of(ItemContent.OVERCHARGED_CRYSTAL), of(ItemContent.DURATIUM_INGOT), "deepdrill");
        // drone port
        offerAtomicForgeRecipe(exporter, BlockContent.DRONE_PORT_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), of(BlockContent.SUPERCONDUCTOR.asItem()), of(ItemContent.UNHOLY_INTELLIGENCE), of(ItemContent.ADVANCED_COMPUTING_ENGINE), "droneport");
        offerAtomicForgeRecipe(exporter, BlockContent.DRONE_PORT_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), of(BlockContent.SUPERCONDUCTOR.asItem()), of(ItemContent.SUPER_AI_CHIP), of(ItemContent.ADVANCED_COMPUTING_ENGINE), "droneportalt");
        
        // arcane catalyst
        offerFurnaceRecipe(exporter, BlockContent.ENCHANTMENT_CATALYST_BLOCK.asItem(), of(Items.ENCHANTING_TABLE), of(ItemContent.ADAMANT_INGOT), of(ConventionalItemTags.NORMAL_OBSIDIANS), of(ItemContent.UNHOLY_INTELLIGENCE), of(ItemContent.FLUXITE), "catalyst");
        offerFurnaceRecipe(exporter, BlockContent.ENCHANTMENT_CATALYST_BLOCK.asItem(), of(Items.ENCHANTING_TABLE), of(ItemContent.ADAMANT_INGOT), of(ConventionalItemTags.NORMAL_OBSIDIANS), of(ItemContent.SUPER_AI_CHIP), of(ItemContent.FLUXITE), "catalyst_alt");
        // enchanter
        offerGeneratorRecipe(exporter, BlockContent.ENCHANTER_BLOCK.asItem(), of(ItemContent.DURATIUM_INGOT), of(ItemContent.ENERGITE_INGOT), of(BlockContent.ENCHANTMENT_CATALYST_BLOCK.asItem()), of(Items.BOOK), "enchanter");
        // spawner
        offerTankRecipe(exporter, BlockContent.SPAWNER_CONTROLLER_BLOCK.asItem(), of(BlockContent.SPAWNER_CAGE_BLOCK), of(Blocks.RESPAWN_ANCHOR), of(BlockContent.ENCHANTMENT_CATALYST_BLOCK), "spawner");
        // spawner cage
        offerInsulatedCableRecipe(exporter, new ItemStack(BlockContent.SPAWNER_CAGE_BLOCK, 2), of(TagContent.PLASTIC_PLATES), of(Items.IRON_BARS), "cage");
        // withered rose
        offerMachineFrameRecipe(exporter, BlockContent.WITHER_CROP_BLOCK.asItem(), of(Items.WITHER_ROSE), of(ItemTags.FLOWERS), 1, "witherrose");
        
        // particle accelerator
        // motor
        offerParticleMotorRecipe(exporter, BlockContent.ACCELERATOR_MOTOR.asItem(), of(TagContent.ELECTRUM_INGOTS), of(BlockContent.SUPERCONDUCTOR.asItem()), of(ItemContent.DURATIUM_INGOT), of(ItemContent.ADVANCED_BATTERY), "particlemotor");
        // ring
        offerDrillRecipe(exporter, BlockContent.ACCELERATOR_RING.asItem(), of(BlockContent.INDUSTRIAL_GLASS_BLOCK.asItem()), of(BlockContent.SUPERCONDUCTOR.asItem()), of(TagContent.STEEL_INGOTS), of(Items.REDSTONE_TORCH), "acceleratorring");
        // controller
        offerGeneratorRecipe(exporter, BlockContent.ACCELERATOR_CONTROLLER.asItem(), of(BlockContent.ACCELERATOR_MOTOR.asItem()), of(ItemContent.FLUX_GATE), of(Items.DROPPER), of(ItemContent.DURATIUM_INGOT), "particlecontroller");
        // sensor
        offerTwoComponentRecipe(exporter, BlockContent.ACCELERATOR_SENSOR.asItem(), of(BlockContent.ACCELERATOR_RING.asItem()), of(Items.OBSERVER), "particlesensor");
        // collector
        offerTankRecipe(exporter, BlockContent.PARTICLE_COLLECTOR_BLOCK.asItem(), of(BlockContent.SUPERCONDUCTOR.asItem()), of(BlockContent.BIG_SOLAR_PANEL_BLOCK.asItem()), of(ItemContent.HEISENBERG_COMPENSATOR), "particlecollector");
        
        
        // addons
        offerGeneratorRecipe(exporter, BlockContent.MACHINE_SPEED_ADDON.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MAGNETIC_COIL), of(ItemContent.BIOSTEEL_INGOT), of(TagContent.PLASTIC_PLATES), "addon/speed");
        offerAtomicForgeRecipe(exporter, BlockContent.MACHINE_PROCESSING_ADDON.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.SUPER_AI_CHIP), of(ItemContent.FLUX_GATE), of(TagContent.PLATINUM_INGOTS), of(ItemContent.MOTOR), "addon/processing");
        offerAtomicForgeRecipe(exporter, BlockContent.MACHINE_PROCESSING_ADDON.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.UNHOLY_INTELLIGENCE), of(Items.COMPARATOR), of(TagContent.ELECTRUM_INGOTS), of(ItemContent.MOTOR), "addon/processingalt");
        offerAtomicForgeRecipe(exporter, BlockContent.MACHINE_ULTIMATE_ADDON.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.HEISENBERG_COMPENSATOR), of(BlockContent.MACHINE_SPEED_ADDON), of(BlockContent.MACHINE_EFFICIENCY_ADDON), of(ItemContent.OVERCHARGED_CRYSTAL), "addon/ultimate");
        offerGeneratorRecipe(exporter, BlockContent.MACHINE_EFFICIENCY_ADDON.asItem(), of(TagContent.MACHINE_PLATING), of(TagContent.CARBON_FIBRE), of(TagContent.ELECTRUM_INGOTS), of(TagContent.PLASTIC_PLATES), "addon/eff");
        offerGeneratorRecipe(exporter, BlockContent.MACHINE_CAPACITOR_ADDON.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.ENERGITE_INGOT), of(ItemContent.MAGNETIC_COIL), of(TagContent.PLASTIC_PLATES), "addon/capacitor");
        offerGeneratorRecipe(exporter, BlockContent.MACHINE_ACCEPTOR_ADDON.asItem(), of(TagContent.MACHINE_PLATING), of(TagContent.ELECTRUM_INGOTS), of(ItemContent.ENERGITE_INGOT), of(TagContent.PLASTIC_PLATES), "addon/acceptor");
        offerGeneratorRecipe(exporter, BlockContent.MACHINE_YIELD_ADDON.asItem(), of(TagContent.MACHINE_PLATING), of(TagContent.ELECTRUM_INGOTS), of(ItemContent.ENDERIC_LENS), of(TagContent.PLASTIC_PLATES), "addon/yield");
        offerGeneratorRecipe(exporter, BlockContent.MACHINE_FLUID_ADDON.asItem(), of(TagContent.SILICON), of(TagContent.ELECTRUM_INGOTS), of(BlockContent.FLUID_PIPE), of(TagContent.CARBON_FIBRE), "addon/fluid");
        offerGeneratorRecipe(exporter, BlockContent.MACHINE_INVENTORY_PROXY_ADDON.asItem(), of(ItemContent.MOTOR), of(ConventionalItemTags.CHESTS), of(ItemContent.PROCESSING_UNIT), of(TagContent.CARBON_FIBRE), "addon/invproxy");
        offerGeneratorRecipe(exporter, BlockContent.CROP_FILTER_ADDON.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), of(ItemContent.PROCESSING_UNIT), of(TagContent.CARBON_FIBRE), "addon/cropfilter");
        offerGeneratorRecipe(exporter, BlockContent.QUARRY_ADDON.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), of(Items.DIAMOND_PICKAXE), of(TagContent.PLASTIC_PLATES), "addon/quarry");
        offerGeneratorRecipe(exporter, BlockContent.MACHINE_HUNTER_ADDON.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), of(Items.IRON_SWORD), of(TagContent.PLASTIC_PLATES), "_hunter");
        offerGeneratorRecipe(exporter, BlockContent.STEAM_BOILER_ADDON.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.ADAMANT_INGOT), of(ConventionalItemTags.COPPER_INGOTS), of(BlockContent.FLUID_PIPE), "addon/steamboiler");
        offerGeneratorRecipe(exporter, BlockContent.STEAM_BOILER_ADDON.asItem(), of(TagContent.SILICON), of(ItemContent.ADAMANT_INGOT), of(BlockContent.FLUID_PIPE), of(TagContent.COAL_DUSTS), "addon/steamboileralt");
        offerGeneratorRecipe(exporter, BlockContent.MACHINE_REDSTONE_ADDON.asItem(), of(TagContent.MACHINE_PLATING), of(Items.REPEATER), of(Items.COMPARATOR), of(ConventionalItemTags.REDSTONE_DUSTS), "addon/redstone");
        offerTwoComponentRecipe(exporter, BlockContent.CAPACITOR_ADDON_EXTENDER.asItem(), of(BlockContent.MACHINE_EXTENDER.asItem()), of(BlockContent.MACHINE_CAPACITOR_ADDON), "addon/capextender");
        
        // cores
        offerMachineCoreRecipe(exporter, BlockContent.MACHINE_CORE_1.asItem(), of(ItemTags.PLANKS), of(Items.CRAFTING_TABLE), "core1");
        offerMachineCoreRecipe(exporter, BlockContent.MACHINE_CORE_2.asItem(), of(ConventionalItemTags.COPPER_INGOTS), of(ConventionalItemTags.LAPIS_GEMS), "core2");
        offerMachineCoreRecipe(exporter, BlockContent.MACHINE_CORE_2.asItem(), of(ConventionalItemTags.IRON_INGOTS), of(ConventionalItemTags.LAPIS_GEMS), "core2alt");
        offerMachineCoreRecipe(exporter, BlockContent.MACHINE_CORE_3.asItem(), of(TagContent.CARBON_FIBRE), of(ConventionalItemTags.REDSTONE_DUSTS), "core3");
        offerMachineCoreRecipe(exporter, BlockContent.MACHINE_CORE_3.asItem(), of(TagContent.NICKEL_INGOTS), of(ConventionalItemTags.REDSTONE_DUSTS), "core3alt");
        offerMachineCoreRecipe(exporter, BlockContent.MACHINE_CORE_4.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.ENDERIC_COMPOUND), "core4");
        offerMachineCoreRecipe(exporter, BlockContent.MACHINE_CORE_5.asItem(), of(ItemContent.ADAMANT_INGOT), of(ItemContent.ADVANCED_COMPUTING_ENGINE), "core5");
        offerMachineCoreRecipe(exporter, BlockContent.MACHINE_CORE_6.asItem(), of(ItemContent.DURATIUM_INGOT), of(ItemContent.DUBIOS_CONTAINER), "core6");
        offerMachineCoreRecipe(exporter, BlockContent.MACHINE_CORE_7.asItem(), of(ItemContent.PROMETHEUM_INGOT), of(BlockContent.SUPERCONDUCTOR.asItem()), "core7");
        
        // machine extender
        offerMachineCoreRecipe(exporter, BlockContent.MACHINE_EXTENDER.asItem(), of(TagContent.MACHINE_PLATING), of(BlockContent.MACHINE_CORE_2.asItem()), "extender");
        
        // augmenter
        // machine itself
        offerAtomicForgeRecipe(exporter, BlockContent.AUGMENT_APPLICATION_BLOCK.asItem(), of(TagContent.MACHINE_PLATING), of(ItemContent.MOTOR), of(BlockContent.LARGE_STORAGE_BLOCK.asItem()), of(TagContent.CARBON_FIBRE), of(ItemContent.DUBIOS_CONTAINER), "augment/applicator");
        // basic station
        offerGeneratorRecipe(exporter, BlockContent.SIMPLE_AUGMENT_STATION.asItem(), of(Items.BREWING_STAND), of(TagContent.MACHINE_PLATING), of(ConventionalItemTags.STORAGE_BLOCKS_REDSTONE), of(TagContent.ELECTRUM_INGOTS), "augment/basic");
        // adv station
        offerGeneratorRecipe(exporter, BlockContent.ADVANCED_AUGMENT_STATION.asItem(), of(BlockContent.CENTRIFUGE_BLOCK), of(TagContent.MACHINE_PLATING), of(ItemContent.FLUX_GATE), of(ItemContent.DURATIUM_INGOT), "augment/advanced");
        // arcane station
        offerGeneratorRecipe(exporter, BlockContent.ARCANE_AUGMENT_STATION.asItem(), of(Items.ENDER_EYE), of(TagContent.MACHINE_PLATING), of(ItemContent.ENDERIC_LENS), of(ItemContent.OVERCHARGED_CRYSTAL), "augment/arcane");
        
    }
    
    private void addComponents(RecipeExporter exporter) {
        // coal stuff (including basic steel)
        CentrifugeRecipeBuilder.build().input(TagContent.COAL_DUSTS).result(ItemContent.CARBON_FIBRE_STRANDS).timeMultiplier(0.5f).export(exporter, "carbon");
        offerManualAlloyRecipe(exporter, ItemContent.STEEL_INGOT, of(ConventionalItemTags.IRON_INGOTS), of(ItemTags.COALS), "steel");
        
        // manual alloys
        offerManualAlloyRecipe(exporter, ItemContent.ELECTRUM_INGOT, of(ConventionalItemTags.GOLD_INGOTS), of(ConventionalItemTags.REDSTONE_DUSTS), "electrum");
        offerManualAlloyRecipe(exporter, ItemContent.ADAMANT_INGOT, of(TagContent.NICKEL_INGOTS), of(ConventionalItemTags.DIAMOND_GEMS), "adamant");
        
        // enderic entry
        PulverizerRecipeBuilder.build().input(ConventionalItemTags.ENDER_PEARLS).result(ItemContent.ENDERIC_COMPOUND, 8).export(exporter, "pearl_enderic");
        GrinderRecipeBuilder.build().input(ConventionalItemTags.ENDER_PEARLS).result(ItemContent.ENDERIC_COMPOUND, 12).export(exporter, "pearl_enderic");
        GrinderRecipeBuilder.build().input(Blocks.END_STONE).result(ItemContent.ENDERIC_COMPOUND).export(exporter, "stone_enderic");
        
        // fine wires
        offerCableRecipe(exporter, new ItemStack(ItemContent.INSULATED_WIRE, 4), of(TagContent.NICKEL_INGOTS), "insulatedwire");
        AssemblerRecipeBuilder.build().input(TagContent.NICKEL_INGOTS).input(TagContent.NICKEL_INGOTS).input(TagContent.NICKEL_INGOTS).input(ConventionalItemTags.COPPER_INGOTS).result(ItemContent.INSULATED_WIRE, 12).timeMultiplier(0.4f).export(exporter, "fwire");
        
        // magnetic coils
        offerInsulatedCableRecipe(exporter, new ItemStack(ItemContent.MAGNETIC_COIL, 2), of(TagContent.STEEL_INGOTS), of(TagContent.WIRES), "magnet");
        AssemblerRecipeBuilder.build().input(TagContent.STEEL_INGOTS).input(TagContent.WIRES).input(TagContent.WIRES).input(TagContent.WIRES).result(ItemContent.MAGNETIC_COIL, 2).timeMultiplier(0.4f).export(exporter, "magnet");
        
        // motor
        offerMotorRecipe(exporter, ItemContent.MOTOR, of(TagContent.NICKEL_INGOTS), of(ItemContent.MAGNETIC_COIL), of(TagContent.STEEL_INGOTS), "motorcraft");
        AssemblerRecipeBuilder.build().input(TagContent.NICKEL_INGOTS).input(TagContent.STEEL_INGOTS).input(ItemContent.MAGNETIC_COIL).input(ItemContent.MAGNETIC_COIL).result(ItemContent.MOTOR, 2).timeMultiplier(0.4f).export(exporter, "motor");
        
        // machine plating variants
        offerMachinePlatingRecipe(exporter, BlockContent.MACHINE_PLATING_BLOCK.asItem(), of(TagContent.STEEL_INGOTS), of(Blocks.STONE.asItem()), of(ConventionalItemTags.COPPER_INGOTS), 2, "plating");
        AssemblerRecipeBuilder.build().input(TagContent.STEEL_INGOTS).input(TagContent.STEEL_INGOTS).input(ConventionalItemTags.COPPER_INGOTS).input(TagContent.PLASTIC_PLATES).result(BlockContent.MACHINE_PLATING_BLOCK.asItem(), 8).timeMultiplier(0.8f).export(exporter, "plating");
        offerMachinePlatingRecipe(exporter, BlockContent.IRON_PLATING_BLOCK.asItem(), of(TagContent.STEEL_INGOTS), of(Blocks.STONE.asItem()), of(ConventionalItemTags.IRON_INGOTS), 2, "iron");
        AssemblerRecipeBuilder.build().input(TagContent.STEEL_INGOTS).input(TagContent.STEEL_INGOTS).input(ConventionalItemTags.IRON_INGOTS).input(TagContent.PLASTIC_PLATES).result(BlockContent.IRON_PLATING_BLOCK.asItem(), 8).timeMultiplier(0.8f).export(exporter, "platingiron");
        offerMachinePlatingRecipe(exporter, BlockContent.NICKEL_PLATING_BLOCK.asItem(), of(TagContent.STEEL_INGOTS), of(Blocks.STONE.asItem()), of(TagContent.NICKEL_INGOTS), 2, "nickel");
        AssemblerRecipeBuilder.build().input(TagContent.STEEL_INGOTS).input(TagContent.STEEL_INGOTS).input(TagContent.NICKEL_INGOTS).input(TagContent.PLASTIC_PLATES).result(BlockContent.NICKEL_PLATING_BLOCK.asItem(), 8).timeMultiplier(0.8f).export(exporter, "platingnickel");
        
        // basic battery
        offerMotorRecipe(exporter, ItemContent.BASIC_BATTERY, of(TagContent.STEEL_INGOTS), of(TagContent.ELECTRUM_INGOTS), of(TagContent.PLASTIC_PLATES), "manualbattery");
        AssemblerRecipeBuilder.build().input(TagContent.PLASTIC_PLATES).input(TagContent.ELECTRUM_INGOTS).input(TagContent.ELECTRUM_INGOTS).input(TagContent.STEEL_INGOTS).result(ItemContent.BASIC_BATTERY).timeMultiplier(0.4f).export(exporter, "battery");
        AssemblerRecipeBuilder.build().input(TagContent.PLASTIC_PLATES).input(ItemContent.FLUXITE).input(ItemContent.FLUXITE).input(TagContent.STEEL_INGOTS).result(ItemContent.BASIC_BATTERY, 2).timeMultiplier(0.8f).export(exporter, "batterybetter");
        
        // silicon
        offerManualAlloyRecipe(exporter, ItemContent.RAW_SILICON, of(TagContent.QUARTZ_DUSTS), of(ItemTags.SAND), 3, "rawsilicon");
        offerSmelting(exporter, List.of(ItemContent.RAW_SILICON), RecipeCategory.MISC, ItemContent.SILICON, 0.5f, 60, "siliconfurnace");
        
        // plastic
        offer2x2CompactingRecipe(exporter, RecipeCategory.MISC, ItemContent.PACKED_WHEAT, Items.WHEAT);
        CentrifugeFluidRecipeBuilder.build().input(ItemContent.PACKED_WHEAT).result(ItemContent.RAW_BIOPOLYMER).fluidInput(Fluids.WATER, 0.25f).export(exporter, "biopolymer");
        CentrifugeFluidRecipeBuilder.build().input(ItemContent.SOLID_BIOFUEL).result(ItemContent.RAW_BIOPOLYMER).fluidInput(Fluids.WATER, 0.25f).export(exporter, "biopolymer_biomass");
        CentrifugeFluidRecipeBuilder.build().input(TagContent.BIOMASS_BLOCK).result(ItemContent.RAW_BIOPOLYMER).fluidInput(Fluids.WATER, 0.25f).export(exporter, "biopolymer_bioblock");
        CentrifugeFluidRecipeBuilder.build().input(ItemTags.SAND).result(ItemContent.POLYMER_RESIN).fluidInput(FluidContent.STILL_OIL.get(), 0.1f).time(100).export(exporter, "polymerresin");
        CentrifugeFluidRecipeBuilder.build().input(ItemContent.RAW_BIOPOLYMER).result(ItemContent.PLASTIC_SHEET).fluidInput(Fluids.WATER, 0.5f).export(exporter, "plasticoil");
        CentrifugeFluidRecipeBuilder.build().input(ItemContent.POLYMER_RESIN).result(ItemContent.PLASTIC_SHEET).fluidInput(Fluids.WATER, 0.5f).time(66).export(exporter, "plasticbio");
        
        // processing unit
        AssemblerRecipeBuilder.build().input(TagContent.PLASTIC_PLATES).input(TagContent.CARBON_FIBRE).input(TagContent.ELECTRUM_INGOTS).input(ConventionalItemTags.REDSTONE_DUSTS).result(ItemContent.PROCESSING_UNIT).timeMultiplier(0.8f).export(exporter, "processingunit");
        // enderic lens
        AssemblerRecipeBuilder.build().input(ItemContent.ADAMANT_INGOT).input(TagContent.CARBON_FIBRE).input(ItemContent.ENDERIC_COMPOUND).input(ItemContent.ENDERIC_COMPOUND).result(ItemContent.ENDERIC_LENS).timeMultiplier(1.2f).export(exporter, "enderlens");
        // flux gate
        AssemblerRecipeBuilder.build().input(ItemContent.PROCESSING_UNIT).input(ItemContent.FLUXITE).input(ItemContent.FLUXITE).input(TagContent.PLATINUM_INGOTS).result(ItemContent.FLUX_GATE).timeMultiplier(1.2f).export(exporter, "fluxgate");
        
        // ai processor tree
        AtomicForgeRecipeBuilder.build().input(TagContent.CARBON_FIBRE).input(TagContent.SILICON).input(TagContent.SILICON).result(ItemContent.SILICON_WAFER).time(5).export(exporter, "wafer");
        AtomicForgeRecipeBuilder.build().input(ItemContent.PROCESSING_UNIT).input(ItemContent.SILICON_WAFER).input(ItemContent.SILICON_WAFER).result(ItemContent.ADVANCED_COMPUTING_ENGINE).time(5).export(exporter, "advcomputer");
        AtomicForgeRecipeBuilder.build().input(ItemContent.DURATIUM_INGOT).input(ItemContent.ADVANCED_COMPUTING_ENGINE).input(ItemContent.ADVANCED_COMPUTING_ENGINE).result(ItemContent.SUPER_AI_CHIP).time(50).export(exporter, "aicomputer");
        
        // dubios container
        offerMotorRecipe(exporter, ItemContent.DUBIOS_CONTAINER, of(TagContent.PLASTIC_PLATES), of(ItemContent.ADAMANT_INGOT), of(ItemContent.ENDERIC_COMPOUND), "dubios");
        // adv battery
        offerMotorRecipe(exporter, ItemContent.ADVANCED_BATTERY, of(TagContent.ELECTRUM_INGOTS), of(ItemContent.ENERGITE_INGOT), of(TagContent.STEEL_INGOTS), "advbattery");
        
        // fuel
        CentrifugeFluidRecipeBuilder.build().input(ItemContent.FLUXITE).fluidInput(FluidContent.STILL_OIL.get()).fluidOutput(FluidContent.STILL_FUEL.get()).export(exporter, "fuel");
        CentrifugeFluidRecipeBuilder.build().input(ItemContent.FLUXITE).fluidInput(FluidContent.STILL_BIOFUEL.get()).fluidOutput(FluidContent.STILL_FUEL.get()).export(exporter, "fuel_from_biofuel");
        CentrifugeFluidRecipeBuilder.build().input(TagContent.BIOMASS).fluidInput(Fluids.WATER, 0.25f).fluidOutput(FluidContent.STILL_BIOFUEL.get(), 0.1f).timeMultiplier(0.2f).export(exporter, "biofuel");
        
        // biosteel
        FoundryRecipeBuilder.build().input(ItemContent.RAW_BIOPOLYMER).input(ConventionalItemTags.IRON_INGOTS).result(ItemContent.BIOSTEEL_INGOT).export(exporter, "biosteel");
        
        // endgame components
        AtomicForgeRecipeBuilder.build().input(ItemContent.SUPER_AI_CHIP).input(ItemContent.ADAMANT_INGOT).input(ItemContent.ADAMANT_INGOT).result(ItemContent.HEISENBERG_COMPENSATOR).time(60).export(exporter, "compensator");
        AtomicForgeRecipeBuilder.build().input(ItemContent.UNHOLY_INTELLIGENCE).input(ItemContent.ADAMANT_INGOT).input(ItemContent.ADAMANT_INGOT).result(ItemContent.HEISENBERG_COMPENSATOR).time(60).export(exporter, "compensatoralt");
        offerMotorRecipe(exporter, ItemContent.OVERCHARGED_CRYSTAL, of(Items.AMETHYST_BLOCK), of(ItemContent.ADVANCED_BATTERY), of(BlockContent.SUPERCONDUCTOR.asItem()), "overchargedcrystal");
        AssemblerRecipeBuilder.build().input(ItemContent.FLUX_GATE).input(TagContent.WIRES).input(ItemContent.DUBIOS_CONTAINER).input(ItemContent.ENERGITE_INGOT).result(BlockContent.SUPERCONDUCTOR.asItem(), 3).timeMultiplier(1.6f).export(exporter, "superconductor");
        AtomicForgeRecipeBuilder.build().input(ItemContent.HEISENBERG_COMPENSATOR).input(ItemContent.OVERCHARGED_CRYSTAL).input(ItemContent.OVERCHARGED_CRYSTAL).result(ItemContent.PROMETHEUM_INGOT).time(240).export(exporter, "prometheum");
        
        // ice in cooler
        CoolerRecipeBuilder.build().fluidInput(Fluids.WATER).result(Items.ICE, 3).export(exporter, "ice");
        
        // snow from steam in cooler
        CoolerRecipeBuilder.build().fluidInput(FluidContent.STILL_STEAM.get()).result(Items.SNOW_BLOCK, 3).export(exporter, "snow");

        // obsidian from lava
        CoolerRecipeBuilder.build().fluidInput(Fluids.LAVA).result(Items.OBSIDIAN, 2).export(exporter, "obsidian");        
    }
    
    private void addCompactingRecipes(RecipeExporter exporter) {
        addCompactingRecipe(exporter, BlockContent.STEEL_BLOCK, ItemContent.STEEL_INGOT, of(ItemTagGenerator.getIngotTag("steel")), of(ItemTagGenerator.getStorageBlockTag("steel")));
        addCompactingRecipe(exporter, BlockContent.ENERGITE_BLOCK, ItemContent.ENERGITE_INGOT, of(ItemTagGenerator.getIngotTag("energite")), of(ItemTagGenerator.getStorageBlockTag("energite")));
        addCompactingRecipe(exporter, BlockContent.NICKEL_BLOCK, ItemContent.NICKEL_INGOT, of(ItemTagGenerator.getIngotTag("nickel")), of(ItemTagGenerator.getStorageBlockTag("nickel")));
        addCompactingRecipe(exporter, BlockContent.BIOSTEEL_BLOCK, ItemContent.BIOSTEEL_INGOT, of(ItemContent.BIOSTEEL_INGOT), of(ItemTagGenerator.getStorageBlockTag("biosteel")));
        addCompactingRecipe(exporter, BlockContent.PLATINUM_BLOCK, ItemContent.PLATINUM_INGOT, of(ItemTagGenerator.getIngotTag("platinum")), of(ItemTagGenerator.getStorageBlockTag("platinum")));
        addCompactingRecipe(exporter, BlockContent.ADAMANT_BLOCK, ItemContent.ADAMANT_INGOT, of(ItemTagGenerator.getIngotTag("adamant")), of(ItemTagGenerator.getStorageBlockTag("adamant")));
        addCompactingRecipe(exporter, BlockContent.ELECTRUM_BLOCK, ItemContent.ELECTRUM_INGOT, of(ItemTagGenerator.getIngotTag("electrum")), of(ItemTagGenerator.getStorageBlockTag("electrum")));
        addCompactingRecipe(exporter, BlockContent.DURATIUM_BLOCK, ItemContent.DURATIUM_INGOT, of(ItemTagGenerator.getIngotTag("duratium")), of(ItemTagGenerator.getStorageBlockTag("duratium")));
        addCompactingRecipe(exporter, BlockContent.BIOMASS_BLOCK, ItemContent.BIOMASS, of(ItemContent.BIOMASS), of(ItemTagGenerator.getStorageBlockTag("biomass")));
        addCompactingRecipe(exporter, BlockContent.PLASTIC_BLOCK, ItemContent.PLASTIC_SHEET, of(TagContent.PLASTIC_PLATES), of(ItemTagGenerator.getStorageBlockTag("plastic")));
        addCompactingRecipe(exporter, BlockContent.FLUXITE_BLOCK, ItemContent.FLUXITE, of(ItemContent.FLUXITE), of(ItemTagGenerator.getStorageBlockTag("fluxite")));
        addCompactingRecipe(exporter, BlockContent.SILICON_BLOCK, ItemContent.SILICON, of(TagContent.SILICON), of(ItemTagGenerator.getStorageBlockTag("silicon")));
        addCompactingRecipe(exporter, BlockContent.RAW_NICKEL_BLOCK, ItemContent.RAW_NICKEL, of(TagContent.NICKEL_RAW_MATERIALS), of(ItemTagGenerator.getStorageBlockTag("raw_nickel")));
        addCompactingRecipe(exporter, BlockContent.RAW_PLATINUM_BLOCK, ItemContent.RAW_PLATINUM, of(TagContent.PLATINUM_RAW_MATERIALS), of(ItemTagGenerator.getStorageBlockTag("raw_platinum")));
        
    }
    
    private void addOreChains(RecipeExporter exporter) {
        
        // basic smelting for nickel + platinum
        offerSmelting(exporter, List.of(ItemContent.RAW_NICKEL), RecipeCategory.MISC, ItemContent.NICKEL_INGOT, 1f, 200, "nickelsmelting");
        offerSmelting(exporter, List.of(ItemContent.RAW_PLATINUM), RecipeCategory.MISC, ItemContent.PLATINUM_INGOT, 1f, 200, "platinumsmelting");
        offerBlasting(exporter, List.of(ItemContent.RAW_NICKEL), RecipeCategory.MISC, ItemContent.NICKEL_INGOT, 1f, 100, "nickelblasting");
        offerBlasting(exporter, List.of(ItemContent.RAW_PLATINUM), RecipeCategory.MISC, ItemContent.PLATINUM_INGOT, 1f, 100, "platinumblasting");
        
        // iron chain
        MetalProcessingChainBuilder.build("iron")
            .ore(ItemTags.IRON_ORES)
            .rawOre(ConventionalItemTags.IRON_RAW_MATERIALS, Items.RAW_IRON)
            .rawOreByproduct(ItemContent.RAW_NICKEL)
            .ingot(ConventionalItemTags.IRON_INGOTS, Items.IRON_INGOT).nugget(ConventionalItemTags.IRON_NUGGETS, Items.IRON_NUGGET)
            .clump(TagContent.IRON_CLUMPS, ItemContent.IRON_CLUMP).smallClump(ItemContent.SMALL_IRON_CLUMP).clumpByproduct(ItemContent.SMALL_NICKEL_CLUMP)
            .dust(ItemContent.IRON_DUST).smallDust(ItemContent.SMALL_IRON_DUST).dustByproduct(ItemContent.SMALL_NICKEL_DUST)
            .gem(ItemContent.IRON_GEM).gemCatalyst(ItemContent.FLUXITE)
            .vanillaProcessing()
            .export(exporter);
        // copper chain
        MetalProcessingChainBuilder.build("copper")
            .ore(ItemTags.COPPER_ORES)
            .rawOre(ConventionalItemTags.COPPER_RAW_MATERIALS, Items.RAW_COPPER).rawOreByproduct(Items.RAW_GOLD)
            .ingot(ConventionalItemTags.COPPER_INGOTS, Items.COPPER_INGOT).nugget(TagContent.COPPER_NUGGETS, ItemContent.COPPER_NUGGET)
            .clump(TagContent.COPPER_CLUMPS, ItemContent.COPPER_CLUMP).smallClump(ItemContent.SMALL_COPPER_CLUMP).clumpByproduct(ItemContent.SMALL_GOLD_CLUMP)
            .dust(ItemContent.COPPER_DUST).smallDust(ItemContent.SMALL_COPPER_DUST).dustByproduct(ItemContent.SMALL_GOLD_DUST)
            .gem(ItemContent.COPPER_GEM).gemCatalyst(ItemContent.FLUXITE)
            .vanillaProcessing()
            .export(exporter);
        // gold chain
        MetalProcessingChainBuilder.build("gold")
            .ore(ItemTags.GOLD_ORES)
            .rawOre(ConventionalItemTags.GOLD_RAW_MATERIALS, Items.RAW_GOLD).rawOreByproduct(Items.RAW_COPPER)
            .ingot(ConventionalItemTags.GOLD_INGOTS, Items.GOLD_INGOT).nugget(ConventionalItemTags.GOLD_NUGGETS, Items.GOLD_NUGGET)
            .clump(TagContent.GOLD_CLUMPS, ItemContent.GOLD_CLUMP).smallClump(ItemContent.SMALL_GOLD_CLUMP).clumpByproduct(ItemContent.SMALL_COPPER_CLUMP)
            .dust(ItemContent.GOLD_DUST).smallDust(ItemContent.SMALL_GOLD_DUST).dustByproduct(ItemContent.SMALL_COPPER_DUST)
            .gem(ItemContent.GOLD_GEM).gemCatalyst(ItemContent.FLUXITE)
            .vanillaProcessing()
            .export(exporter);
        // nickel chain
        MetalProcessingChainBuilder.build("nickel")
            .ore(TagContent.NICKEL_ORES)
            .rawOre(TagContent.NICKEL_RAW_MATERIALS, ItemContent.RAW_NICKEL).rawOreByproduct(ItemContent.RAW_PLATINUM)
            .ingot(TagContent.NICKEL_INGOTS, ItemContent.NICKEL_INGOT).nugget(TagContent.NICKEL_NUGGETS, ItemContent.NICKEL_NUGGET)
            .clump(TagContent.NICKEL_CLUMPS, ItemContent.NICKEL_CLUMP).smallClump(ItemContent.SMALL_NICKEL_CLUMP).clumpByproduct(ItemContent.SMALL_PLATINUM_CLUMP)
            .dust(ItemContent.NICKEL_DUST).smallDust(ItemContent.SMALL_NICKEL_DUST).dustByproduct(ItemContent.SMALL_PLATINUM_DUST)
            .byproductAmount(2)
            .gem(ItemContent.NICKEL_GEM).gemCatalyst(ItemContent.FLUXITE)
            .vanillaProcessing()
            .export(exporter);
        // platinum chain
        MetalProcessingChainBuilder.build("platinum")
            .ore(TagContent.PLATINUM_ORES)
            .rawOre(TagContent.PLATINUM_RAW_MATERIALS, ItemContent.RAW_PLATINUM).rawOreByproduct(ItemContent.FLUXITE)
            .ingot(TagContent.PLATINUM_INGOTS, ItemContent.PLATINUM_INGOT).nugget(TagContent.PLATINUM_NUGGETS, ItemContent.PLATINUM_NUGGET)
            .clump(TagContent.PLATINUM_CLUMPS, ItemContent.PLATINUM_CLUMP).smallClump(ItemContent.SMALL_PLATINUM_CLUMP).clumpByproduct(ItemContent.FLUXITE)
            .dust(ItemContent.PLATINUM_DUST).smallDust(ItemContent.SMALL_PLATINUM_DUST).dustByproduct(ItemContent.FLUXITE)
            .byproductAmount(1)
            .gem(ItemContent.PLATINUM_GEM).gemCatalyst(ItemContent.FLUXITE)
            .timeMultiplier(1.5f)
            .vanillaProcessing()
            .export(exporter);

          // Uranium clumps don't exist in Oritech, but Oritech should still be able to do something with them if they're added by another mod (like Create).
          // in the compat space so that the Fabric versions won't go into Neoforge
          CentrifugeRecipeBuilder.build()
            .input(TagContent.URANIUM_CLUMPS).result(ItemContent.URANIUM_DUST, 2).result(ItemContent.SMALL_PLUTONIUM_DUST).timeMultiplier(0.5f)
            .export(this.withConditions(exporter, new TagsPopulatedResourceCondition(TagContent.URANIUM_CLUMPS)), "compat/clump/crushed_uranium");
          CentrifugeFluidRecipeBuilder.build()
            .input(TagContent.URANIUM_CLUMPS).result(ItemContent.URANIUM_DUST, 3).fluidInput(Fluids.WATER).timeMultiplier(0.5f)
            .export(this.withConditions(exporter, new TagsPopulatedResourceCondition(TagContent.URANIUM_CLUMPS)), "compat/clumpwet/crushed_uranium");
    }
    
    private void addAlloys(RecipeExporter exporter) {
        FoundryRecipeBuilder.build().input(TagContent.PLATINUM_INGOTS).input(ConventionalItemTags.NETHERITE_INGOTS).result(ItemContent.DURATIUM_INGOT).export(exporter, "duratium");
        FoundryRecipeBuilder.build().input(ConventionalItemTags.GOLD_INGOTS).input(ConventionalItemTags.REDSTONE_DUSTS).result(ItemContent.ELECTRUM_INGOT).export(exporter, "electrum");
        FoundryRecipeBuilder.build().input(ConventionalItemTags.DIAMOND_GEMS).input(TagContent.NICKEL_INGOTS).result(ItemContent.ADAMANT_INGOT).export(exporter, "adamant");
        FoundryRecipeBuilder.build().input(TagContent.NICKEL_INGOTS).input(ItemContent.FLUXITE).result(ItemContent.ENERGITE_INGOT).export(exporter, "energite");
        FoundryRecipeBuilder.build().input(ConventionalItemTags.IRON_INGOTS).input(TagContent.COAL_DUSTS).result(ItemContent.STEEL_INGOT).timeMultiplier(0.3333f).export(exporter, "steel");
    }
    
    private void addParticleCollisions(RecipeExporter exporter) {
        // diamond from coal dust
        ParticleCollisionRecipeBuilder.build().input(TagContent.COAL_DUSTS).input(TagContent.COAL_DUSTS).result(Items.DIAMOND).time(500).export(exporter, "diamond");
        // overcharged crystal from fluxite and energite dust
        ParticleCollisionRecipeBuilder.build().input(ItemContent.FLUXITE).input(ItemContent.ENERGITE_DUST).result(ItemContent.OVERCHARGED_CRYSTAL).time(5000).export(exporter, "overcharged_crystal");
        // platinum from gold dust
        ParticleCollisionRecipeBuilder.build().input(TagContent.GOLD_DUSTS).input(TagContent.GOLD_DUSTS).result(ItemContent.PLATINUM_DUST).time(500).export(exporter, "platinum_dust");
        // enderic compound from redstone and flesh
        ParticleCollisionRecipeBuilder.build().input(ConventionalItemTags.REDSTONE_DUSTS).input(Items.ROTTEN_FLESH).result(ItemContent.ENDERIC_COMPOUND).time(500).export(exporter, "enderic_compound");
        // fluxite from electrum dust and redstone
        ParticleCollisionRecipeBuilder.build().input(TagContent.ELECTRUM_DUSTS).input(ConventionalItemTags.REDSTONE_DUSTS).result(ItemContent.FLUXITE).time(1000).export(exporter, "fluxite");
        // netherite scrap from adamant dust and netherrack
        ParticleCollisionRecipeBuilder.build().input(ItemContent.ADAMANT_DUST).input(Items.NETHERRACK).result(Items.NETHERITE_SCRAP).time(2500).export(exporter, "netherite");
        // elytra from feather and saddle
        ParticleCollisionRecipeBuilder.build().input(cItemTag("feathers")).input(Items.SADDLE).result(Items.ELYTRA).time(10000).export(exporter, "elytra");
        // nether star from overcharged crystal and netherite
        ParticleCollisionRecipeBuilder.build().input(ItemContent.OVERCHARGED_CRYSTAL).input(ConventionalItemTags.NETHERITE_INGOTS).result(Items.NETHER_STAR).time(15000).export(exporter, "nether_star");
        // echo shard from ender pearl and amethyst shard
        ParticleCollisionRecipeBuilder.build().input(ConventionalItemTags.ENDER_PEARLS).input(ConventionalItemTags.AMETHYST_GEMS).result(Items.ECHO_SHARD).time(1000).export(exporter, "echo_shard");
        // heavy core from reinforced deepslate block and duration dust
        ParticleCollisionRecipeBuilder.build().input(Items.REINFORCED_DEEPSLATE).input(ItemContent.DURATIUM_DUST).result(Items.HEAVY_CORE).time(8000).export(exporter, "heavy_core");
    }
    
    private void addDusts(RecipeExporter exporter) {
        addDustRecipe(exporter, of(ItemContent.BIOSTEEL_INGOT), ItemContent.BIOSTEEL_DUST, ItemContent.BIOSTEEL_INGOT, "biosteel");
        addDustRecipe(exporter, of(ItemContent.DURATIUM_INGOT), ItemContent.DURATIUM_DUST, ItemContent.DURATIUM_INGOT, "duratium");
        addDustRecipe(exporter, of(TagContent.ELECTRUM_INGOTS), ItemContent.ELECTRUM_DUST, ItemContent.ELECTRUM_INGOT, "electrum");
        addDustRecipe(exporter, of(ItemContent.ADAMANT_INGOT), ItemContent.ADAMANT_DUST, ItemContent.ADAMANT_INGOT, "adamant");
        addDustRecipe(exporter, of(ItemContent.ENERGITE_INGOT), ItemContent.ENERGITE_DUST, ItemContent.ENERGITE_INGOT, "energite");
        addDustRecipe(exporter, of(TagContent.STEEL_INGOTS), ItemContent.STEEL_DUST, ItemContent.STEEL_INGOT, "steel");
        addDustRecipe(exporter, of(ItemTags.COALS), ItemContent.COAL_DUST, "coal");
        addDustRecipe(exporter, of(ConventionalItemTags.QUARTZ_GEMS), ItemContent.QUARTZ_DUST, "quartz");
        
        // raw ores without processing chains
        // coal
        GrinderRecipeBuilder.build().input(ItemTags.COAL_ORES).result(Items.COAL, 3).export(exporter, "coalore");
        PulverizerRecipeBuilder.build().input(ItemTags.COAL_ORES).result(Items.COAL, 2).export(exporter, "coalore");
        // redstone
        GrinderRecipeBuilder.build().input(ItemTags.REDSTONE_ORES).result(Items.REDSTONE, 12).export(exporter, "redstoneore");
        PulverizerRecipeBuilder.build().input(ItemTags.REDSTONE_ORES).result(Items.REDSTONE, 8).export(exporter, "redstoneore");
        // diamond
        GrinderRecipeBuilder.build().input(ItemTags.DIAMOND_ORES).result(Items.DIAMOND, 2).export(exporter, "diamondore");
        PulverizerRecipeBuilder.build().input(ItemTags.DIAMOND_ORES).result(Items.DIAMOND).export(exporter, "diamondore");
        // quartz
        GrinderRecipeBuilder.build().input(Blocks.NETHER_QUARTZ_ORE).result(Items.QUARTZ, 3).export(exporter, "quartzore");
        PulverizerRecipeBuilder.build().input(Blocks.NETHER_QUARTZ_ORE).result(Items.QUARTZ, 2).export(exporter, "quartzore");
        // glowstone
        GrinderRecipeBuilder.build().input(Blocks.GLOWSTONE).result(Items.GLOWSTONE_DUST, 4).export(exporter, "glowstoneore");
        PulverizerRecipeBuilder.build().input(Blocks.GLOWSTONE).result(Items.GLOWSTONE_DUST, 3).export(exporter, "glowstoneore");
        // lapis
        GrinderRecipeBuilder.build().input(ItemTags.LAPIS_ORES).result(Items.LAPIS_LAZULI, 8).export(exporter, "lapisore");
        PulverizerRecipeBuilder.build().input(ItemTags.LAPIS_ORES).result(Items.LAPIS_LAZULI, 6).export(exporter, "lapisore");
        // bone
        GrinderRecipeBuilder.build().input(Items.BONE).result(Items.BONE_MEAL, 8).export(exporter, "bone");
        PulverizerRecipeBuilder.build().input(Items.BONE).result(Items.BONE_MEAL, 6).export(exporter, "bone");
        // blaze powder
        GrinderRecipeBuilder.build().input(Items.BLAZE_ROD).result(Items.BLAZE_POWDER, 4).export(exporter, "blaze");
        PulverizerRecipeBuilder.build().input(Items.BLAZE_ROD).result(Items.BLAZE_POWDER, 3).export(exporter, "blaze");
        // wool
        GrinderRecipeBuilder.build().input(ItemTags.WOOL).result(Items.STRING, 4).export(exporter, "string");
        PulverizerRecipeBuilder.build().input(ItemTags.WOOL).result(Items.STRING, 3).export(exporter, "string");
        // ancient debris
        GrinderRecipeBuilder.build().input(Items.ANCIENT_DEBRIS).result(Items.NETHERITE_SCRAP, 2).export(exporter, "netheritescrap");
    }
    
    private void addUraniumProcessing(RecipeExporter exporter) {
        // uranium order is:
        // raw ore -> dust/gem, dust -> gem, gem -> pellets
        
        // plutonium can be made via either ender laser on crystals (manually, usually low amount)
        // or via the particle accelerator
        
        // small uranium dust from redstone
        CentrifugeRecipeBuilder.build().input(ConventionalItemTags.REDSTONE_DUSTS).result(ItemContent.SMALL_URANIUM_DUST).export(exporter, "redstoneuran");
        
        // uranium ore blocks
        GrinderRecipeBuilder.build().input(BlockContent.DEEPSLATE_URANIUM_ORE).result(ItemContent.RAW_URANIUM, 3).result(ItemContent.SMALL_PLUTONIUM_DUST).export(exporter, "uraniumore");
        PulverizerRecipeBuilder.build().input(BlockContent.DEEPSLATE_URANIUM_ORE).result(ItemContent.RAW_URANIUM, 2).export(exporter, "uraniumore");
        
        // uranium crystal blocks
        GrinderRecipeBuilder.build().input(BlockContent.URANIUM_CRYSTAL).result(ItemContent.RAW_URANIUM, 5).result(ItemContent.SMALL_PLUTONIUM_DUST).export(exporter, "uraniumcrystal");
        PulverizerRecipeBuilder.build().input(BlockContent.URANIUM_CRYSTAL).result(ItemContent.RAW_URANIUM, 4).export(exporter, "uraniumcrystal");
        
        // raw uranium in grinder
        GrinderRecipeBuilder.build().input(TagContent.URANIUM_RAW_MATERIALS).result(ItemContent.URANIUM_DUST, 2).result(ItemContent.SMALL_PLUTONIUM_DUST).export(exporter, "uranium");
        PulverizerRecipeBuilder.build().input(TagContent.URANIUM_RAW_MATERIALS).result(ItemContent.URANIUM_DUST, 2).export(exporter, "uranium");
        
        // uranium gem from raw uranium / uranium dust in atomic forge
        AtomicForgeRecipeBuilder.build().input(TagContent.COPPER_DUSTS).input(TagContent.URANIUM_RAW_MATERIALS).input(TagContent.URANIUM_RAW_MATERIALS).result(ItemContent.URANIUM_GEM).time(5).export(exporter, "urandust");
        AtomicForgeRecipeBuilder.build().input(TagContent.COPPER_DUSTS).input(TagContent.URANIUM_DUSTS).input(TagContent.URANIUM_DUSTS).result(ItemContent.URANIUM_GEM).time(5).export(exporter, "urandustgem");
        
        // uranium pellets in assembler
        AssemblerRecipeBuilder.build().input(ItemContent.URANIUM_GEM).input(ItemContent.URANIUM_GEM).input(TagContent.PLASTIC_PLATES).input(TagContent.NICKEL_INGOTS).result(ItemContent.URANIUM_PELLET, 2).timeMultiplier(0.8f).export(exporter, "uranpelletbasic");
        AssemblerRecipeBuilder.build().input(ItemContent.URANIUM_GEM).input(ItemContent.URANIUM_GEM).input(TagContent.PLASTIC_PLATES).input(ItemContent.ADAMANT_INGOT).result(ItemContent.URANIUM_PELLET, 3).timeMultiplier(0.8f).export(exporter, "uranpelletbetter");
        AssemblerRecipeBuilder.build().input(ItemContent.URANIUM_GEM).input(ItemContent.URANIUM_GEM).input(TagContent.PLASTIC_PLATES).input(ItemContent.DURATIUM_INGOT).result(ItemContent.URANIUM_PELLET, 4).timeMultiplier(0.8f).export(exporter, "uranpelletult");
        
        // plutonium pellets in assembler
        AssemblerRecipeBuilder.build().input(ItemContent.PLUTONIUM_DUST).input(ItemContent.PLUTONIUM_DUST).input(TagContent.PLASTIC_PLATES).input(TagContent.NICKEL_INGOTS).result(ItemContent.PLUTONIUM_PELLET, 2).timeMultiplier(0.8f).export(exporter, "plutoniumpelletbasic");
        AssemblerRecipeBuilder.build().input(ItemContent.PLUTONIUM_DUST).input(ItemContent.PLUTONIUM_DUST).input(TagContent.PLASTIC_PLATES).input(ItemContent.ADAMANT_INGOT).result(ItemContent.PLUTONIUM_PELLET, 3).timeMultiplier(0.8f).export(exporter, "plutoniumpelletbetter");
        AssemblerRecipeBuilder.build().input(ItemContent.PLUTONIUM_DUST).input(ItemContent.PLUTONIUM_DUST).input(TagContent.PLASTIC_PLATES).input(ItemContent.DURATIUM_INGOT).result(ItemContent.PLUTONIUM_PELLET, 4).timeMultiplier(0.8f).export(exporter, "plutoniumpelletult");
        
        // dust compacting
        addCompactingRecipe(exporter, ItemContent.URANIUM_DUST, ItemContent.SMALL_URANIUM_DUST, of(ItemContent.SMALL_URANIUM_DUST), of(TagContent.URANIUM_DUSTS));
        addCompactingRecipe(exporter, ItemContent.PLUTONIUM_DUST, ItemContent.SMALL_PLUTONIUM_DUST, of(ItemContent.SMALL_PLUTONIUM_DUST), of(TagContent.PLUTONIUM_DUSTS));
        
        // uranium to plutonium
        ParticleCollisionRecipeBuilder.build().input(TagContent.URANIUM_DUSTS).input(ItemContent.FLUXITE).result(ItemContent.PLUTONIUM_DUST).time(2500).export(exporter, "plutonium");
        
        // pellet compacting
        addCompactingRecipe(exporter, ItemContent.URANIUM_PELLET, ItemContent.SMALL_URANIUM_PELLET, of(ItemContent.SMALL_URANIUM_PELLET), of(ItemContent.URANIUM_PELLET));
        addCompactingRecipe(exporter, ItemContent.PLUTONIUM_PELLET, ItemContent.SMALL_PLUTONIUM_PELLET, of(ItemContent.SMALL_PLUTONIUM_PELLET), of(ItemContent.PLUTONIUM_PELLET));
    }
    
    private void addAugmentRecipes(RecipeExporter exporter) {
        
        var SIMPLE_AUGMENT_STATION_ID = Registries.BLOCK.getId(BlockContent.SIMPLE_AUGMENT_STATION);
        var ADVANCED_AUGMENT_STATION_ID = Registries.BLOCK.getId(BlockContent.ADVANCED_AUGMENT_STATION);
        var ARCANE_AUGMENT_STATION_ID = Registries.BLOCK.getId(BlockContent.ARCANE_AUGMENT_STATION);
        
        AugmentRecipeBuilder.build()
            .researchCost(TagContent.MACHINE_PLATING, 64)
            .researchCost(TagContent.COAL_DUSTS, 32)
            .researchCost(ItemContent.BIOSTEEL_INGOT, 8)
            .applyCost(TagContent.STEEL_INGOTS, 8)
            .applyCost(ConventionalItemTags.IRON_INGOTS, 16)
            .requiredStation(SIMPLE_AUGMENT_STATION_ID)
            .uiX(5).uiY(70).time(400).rfCost(10_000_000)
            .export(exporter, "hpboost");

        AugmentRecipeBuilder.build()
            .researchCost(TagContent.CARBON_FIBRE, 32)
            .researchCost(ItemContent.BIOSTEEL_INGOT, 16)
            .researchCost(ConventionalItemTags.DIAMOND_GEMS, 4)
            .applyCost(TagContent.CARBON_FIBRE, 8)
            .applyCost(ItemContent.DURATIUM_INGOT, 4)
            .requirement(Oritech.id("augment/armor"))
            .requiredStation(SIMPLE_AUGMENT_STATION_ID)
            .uiX(80).uiY(70).time(800).rfCost(50_000_000)
            .export(exporter, "hpboostmore");

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.ENERGITE_INGOT, 64)
            .researchCost(ItemContent.DURATIUM_INGOT, 32)
            .researchCost(Items.NETHER_STAR)
            .applyCost(ItemContent.DURATIUM_DUST, 64)
            .applyCost(ConventionalItemTags.STORAGE_BLOCKS_REDSTONE, 64)
            .requirement(Oritech.id("augment/ultimatearmor"))
            .requiredStation(ADVANCED_AUGMENT_STATION_ID)
            .uiX(165).uiY(70).time(1600).rfCost(200_000_000)
            .export(exporter, "hpboostultra");

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.ADAMANT_INGOT, 64)
            .researchCost(Items.NETHER_STAR, 8)
            .researchCost(ItemContent.URANIUM_PELLET, 64)
            .researchCost(BlockContent.FLUXITE_BLOCK, 64)
            .applyCost(ItemContent.ADAMANT_INGOT, 32)
            .applyCost(ItemContent.OVERCHARGED_CRYSTAL)
            .applyCost(ItemContent.FLUXITE, 64)
            .requirement(Oritech.id("augment/hpboostultra"))
            .requirement(Oritech.id("augment/gravity"))
            .requiredStation(ADVANCED_AUGMENT_STATION_ID)
            .uiX(205).uiY(40).time(2400).rfCost(500_000_000)
            .export(exporter, "hpboostultimate");

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.MOTOR, 32)
            .researchCost(ItemContent.BIOSTEEL_INGOT, 64)
            .researchCost(ConventionalItemTags.REDSTONE_DUSTS, 32)
            .applyCost(ItemContent.MOTOR, 16)
            .applyCost(ConventionalItemTags.IRON_INGOTS, 32)
            .requiredStation(SIMPLE_AUGMENT_STATION_ID)
            .uiX(5).uiY(30).time(600).rfCost(30_000_000)
            .export(exporter, "speedboost");

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.ENERGITE_INGOT, 64)
            .researchCost(ItemContent.MAGNETIC_COIL, 32)
            .researchCost(ItemContent.FLUX_GATE, 16)
            .applyCost(ItemContent.MAGNETIC_COIL, 32)
            .applyCost(ItemContent.OVERCHARGED_CRYSTAL)
            .applyCost(TagContent.ELECTRUM_DUSTS, 64)
            .requirement(Oritech.id("augment/speedboost"))
            .requirement(Oritech.id("augment/armor"))
            .requiredStation(ADVANCED_AUGMENT_STATION_ID)
            .uiX(55).uiY(50).time(1800).rfCost(350_000_000)
            .export(exporter, "superspeedboost");

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.MOTOR, 32)
            .researchCost(TagContent.STEEL_INGOTS, 64)
            .researchCost(ConventionalItemTags.STORAGE_BLOCKS_IRON, 16)
            .applyCost(ItemContent.MOTOR, 16)
            .applyCost(ConventionalItemTags.IRON_INGOTS, 64)
            .requirement(Oritech.id("augment/superspeedboost"))
            .requiredStation(SIMPLE_AUGMENT_STATION_ID)
            .uiX(80).uiY(50).time(800).rfCost(75_000_000)
            .export(exporter, "stepassist");

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.SILICON_WAFER, 64)
            .researchCost(ItemContent.PROCESSING_UNIT, 32)
            .researchCost(ConventionalItemTags.STORAGE_BLOCKS_GOLD, 16)
            .applyCost(TagContent.SILICON, 32)
            .applyCost(ConventionalItemTags.STORAGE_BLOCKS_REDSTONE, 32)
            .requirement(Oritech.id("augment/hpboost"))
            .requiredStation(SIMPLE_AUGMENT_STATION_ID)
            .uiX(30).uiY(90).time(400).rfCost(50_000_000)
            .export(exporter, "dwarf");

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.RAW_BIOPOLYMER, 64)
            .researchCost(ItemContent.SMALL_URANIUM_DUST, 32)
            .researchCost(TagContent.BIOMATTER, 64)
            .applyCost(ItemContent.RAW_BIOPOLYMER, 32)
            .applyCost(ConventionalItemTags.IRON_INGOTS, 64)
            .requirement(Oritech.id("augment/dwarf"))
            .requirement(Oritech.id("augment/armor"))
            .requiredStation(SIMPLE_AUGMENT_STATION_ID)
            .uiX(55).uiY(90).time(1600).rfCost(300_000_000)
            .export(exporter, "giant");

        AugmentRecipeBuilder.build()
            .researchCost(TagContent.STEEL_INGOTS, 64)
            .researchCost(ItemContent.DURATIUM_INGOT, 8)
            .researchCost(ConventionalItemTags.DIAMOND_GEMS, 16)
            .applyCost(ItemContent.DURATIUM_INGOT, 4)
            .applyCost(ConventionalItemTags.IRON_INGOTS, 32)
            .requiredStation(SIMPLE_AUGMENT_STATION_ID)
            .uiX(30).uiY(50).time(800).rfCost(80_000_000)
            .export(exporter, "armor");

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.ENERGITE_INGOT, 64)
            .researchCost(ItemContent.MAGNETIC_COIL, 32)
            .researchCost(ConventionalItemTags.DIAMOND_GEMS, 32)
            .applyCost(ItemContent.MAGNETIC_COIL, 16)
            .applyCost(ItemContent.OVERCHARGED_CRYSTAL)
            .applyCost(ItemContent.DURATIUM_INGOT, 8)
            .requirement(Oritech.id("augment/autofeeder"))
            .requiredStation(SIMPLE_AUGMENT_STATION_ID)
            .uiX(105).uiY(50).time(1600).rfCost(280_000_000)
            .export(exporter, "betterarmor");

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.FLUXITE, 64)
            .researchCost(ItemContent.HEISENBERG_COMPENSATOR, 32)
            .researchCost(ItemContent.PLUTONIUM_PELLET, 64)
            .researchCost(Items.NETHER_STAR, 8)
            .applyCost(BlockContent.FLUXITE_BLOCK, 32)
            .applyCost(ItemContent.OVERCHARGED_CRYSTAL)
            .applyCost(ConventionalItemTags.NORMAL_OBSIDIANS, 16)
            .requirement(Oritech.id("augment/betterarmor"))
            .requiredStation(ADVANCED_AUGMENT_STATION_ID)
            .uiX(155).uiY(50).time(2400).rfCost(500_000_000)
            .export(exporter, "ultimatearmor");

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.MAGNETIC_COIL, 64)
            .researchCost(TagContent.ELECTRUM_INGOTS, 48)
            .researchCost(ConventionalItemTags.STORAGE_BLOCKS_REDSTONE, 32)
            .applyCost(ItemContent.MAGNETIC_COIL, 32)
            .applyCost(ConventionalItemTags.STORAGE_BLOCKS_IRON, 64)
            .requirement(Oritech.id("augment/blockreach"))
            .requiredStation(ADVANCED_AUGMENT_STATION_ID)
            .uiX(140).uiY(70).time(1600).rfCost(150_000_000)
            .export(exporter, "weaponreach");       

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.MOTOR, 64)
            .researchCost(TagContent.STEEL_INGOTS, 48)
            .researchCost(ConventionalItemTags.STORAGE_BLOCKS_COPPER, 32)
            .applyCost(ItemContent.MOTOR, 32)
            .applyCost(ConventionalItemTags.COPPER_INGOTS, 64)
            .requiredStation(SIMPLE_AUGMENT_STATION_ID)
            .uiX(115).uiY(90).time(900).rfCost(100_000_000)
            .export(exporter, "blockreach");

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.ENDERIC_LENS, 64)
            .researchCost(ConventionalItemTags.ENDER_PEARLS, 16)
            .researchCost(ConventionalItemTags.STORAGE_BLOCKS_DIAMOND, 16)
            .applyCost(ItemContent.ENDERIC_LENS, 32)
            .applyCost(ConventionalItemTags.NORMAL_OBSIDIANS, 64)
            .requirement(Oritech.id("augment/blockreach"))
            .requiredStation(ADVANCED_AUGMENT_STATION_ID)
            .uiX(140).uiY(90).time(800).rfCost(200_000_000)
            .export(exporter, "farblockreach");

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.MAGNETIC_COIL, 48)
            .researchCost(Items.QUARTZ_BLOCK, 64)
            .researchCost(ItemContent.BASIC_BATTERY, 32)
            .applyCost(Items.QUARTZ_BLOCK, 16)
            .applyCost(ConventionalItemTags.IRON_INGOTS, 32)
            .requirement(Oritech.id("augment/attackdamage"))
            .requirement(Oritech.id("augment/speedboost"))
            .requiredStation(SIMPLE_AUGMENT_STATION_ID)
            .uiX(30).uiY(10).time(1200).rfCost(100_000_000)
            .export(exporter, "miningspeed");

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.ENERGITE_INGOT, 64)
            .researchCost(ItemContent.FLUX_GATE, 48)
            .researchCost(ItemContent.DURATIUM_INGOT, 64)
            .applyCost(ItemContent.ENERGITE_INGOT, 32)
            .applyCost(ConventionalItemTags.STORAGE_BLOCKS_REDSTONE, 64)
            .requirement(Oritech.id("augment/miningspeed"))
            .requirement(Oritech.id("augment/superspeedboost"))
            .requiredStation(ADVANCED_AUGMENT_STATION_ID)
            .uiX(80).uiY(10).time(2400).rfCost(450_000_000)
            .export(exporter, "superminingspeed");

        AugmentRecipeBuilder.build()
            .researchCost(TagContent.STEEL_INGOTS, 64)
            .researchCost(ConventionalItemTags.DIAMOND_GEMS, 48)
            .researchCost(ItemContent.FLUXITE, 32)
            .applyCost(TagContent.STEEL_INGOTS, 16)
            .applyCost(ItemContent.DURATIUM_INGOT, 4)
            .requiredStation(SIMPLE_AUGMENT_STATION_ID)
            .uiX(5).uiY(10).time(1600).rfCost(150_000_000)
            .export(exporter, "attackdamage");

        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.ENDERIC_COMPOUND, 64)
            .researchCost(ItemContent.FLUXITE, 64)
            .researchCost(ConventionalItemTags.BLAZE_RODS, 64)
            .applyCost(ItemContent.ENDERIC_COMPOUND, 32)
            .applyCost(ConventionalItemTags.STORAGE_BLOCKS_GOLD, 64)
            .requirement(Oritech.id("augment/hpboostultra"))
            .requirement(Oritech.id("augment/ultimatearmor"))
            .requiredStation(ARCANE_AUGMENT_STATION_ID)
            .uiX(180).uiY(50).time(2800).rfCost(500_000_000)
            .export(exporter, "superattackdamage");
        
        AugmentRecipeBuilder.build()
            .researchCost(TagContent.ELECTRUM_INGOTS, 64)
            .researchCost(ConventionalItemTags.STORAGE_BLOCKS_LAPIS, 48)
            .researchCost(ConventionalItemTags.STORAGE_BLOCKS_GOLD, 32)
            .applyCost(ConventionalItemTags.STORAGE_BLOCKS_LAPIS, 32)
            .applyCost(ConventionalItemTags.STORAGE_BLOCKS_REDSTONE, 64)
            .requiredStation(ARCANE_AUGMENT_STATION_ID)
            .uiX(55).uiY(30).time(1800).rfCost(200_000_000)
            .export(exporter, "luck");
        
        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.MAGNETIC_COIL, 64)
            .researchCost(ItemContent.FLUXITE, 48)
            .researchCost(Items.PHANTOM_MEMBRANE, 8)
            .applyCost(ItemContent.MAGNETIC_COIL, 32)
            .applyCost(ConventionalItemTags.STORAGE_BLOCKS_IRON, 16)
            .requirement(Oritech.id("augment/flight"))
            .requiredStation(ARCANE_AUGMENT_STATION_ID)
            .uiX(180).uiY(10).time(2200).rfCost(400_000_000)
            .export(exporter, "gravity");
        
        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.FLUX_GATE, 64)
            .researchCost(Items.WIND_CHARGE, 16)
            .researchCost(ItemContent.PROMETHEUM_INGOT, 16)
            .researchCost(ItemContent.PLUTONIUM_PELLET, 32)
            .applyCost(ItemContent.FLUX_GATE, 32)
            .applyCost(ItemContent.PLUTONIUM_PELLET, 8)
            .requirement(Oritech.id("augment/betterarmor"))
            .requirement(Oritech.id("augment/portal"))
            .requiredStation(ARCANE_AUGMENT_STATION_ID)
            .uiX(155).uiY(30).time(3600).rfCost(500_000_000)
            .export(exporter, "flight");
        
        AugmentRecipeBuilder.build()
            .researchCost(Items.ENDER_EYE, 64)
            .researchCost(ItemContent.ENDERIC_LENS, 48)
            .researchCost(ConventionalItemTags.DIAMOND_GEMS, 8)
            .applyCost(ItemContent.ENDERIC_LENS, 32)
            .applyCost(Items.GLOWSTONE, 64)
            .requirement(Oritech.id("augment/orefinder"))
            .requiredStation(ARCANE_AUGMENT_STATION_ID)
            .uiX(155).uiY(10).time(3200).rfCost(100_000_000)
            .export(exporter, "cloak");
        
        AugmentRecipeBuilder.build()
            .researchCost(ConventionalItemTags.ENDER_PEARLS, 16)
            .researchCost(ConventionalItemTags.NORMAL_OBSIDIANS, 48)
            .researchCost(ItemContent.UNHOLY_INTELLIGENCE)
            .researchCost(ItemContent.ADAMANT_INGOT, 32)
            .applyCost(ConventionalItemTags.ENDER_PEARLS, 8)
            .applyCost(ConventionalItemTags.CRYING_OBSIDIANS, 32)
            .requiredStation(ARCANE_AUGMENT_STATION_ID)
            .uiX(130).uiY(30).time(3000).rfCost(250_000_000)
            .export(exporter, "portal");
        
        AugmentRecipeBuilder.build()
            .researchCost(ConventionalItemTags.GOLD_INGOTS, 64)
            .researchCost(ItemContent.ENDERIC_LENS, 48)
            .researchCost(Items.GLOWSTONE, 64)
            .applyCost(ItemContent.ENDERIC_LENS, 4)
            .applyCost(Items.GLOWSTONE, 8)
            .applyCost(Items.REDSTONE_LAMP, 8)
            .requiredStation(ADVANCED_AUGMENT_STATION_ID)
            .uiX(105).uiY(30).time(2400).rfCost(50_000_000)
            .export(exporter, "nightvision");
        
        AugmentRecipeBuilder.build()
            .researchCost(Items.PRISMARINE_CRYSTALS, 64)
            .researchCost(ItemContent.BIOSTEEL_INGOT, 48)
            .researchCost(Items.HEART_OF_THE_SEA)
            .applyCost(ItemContent.BIOSTEEL_INGOT, 32)
            .applyCost(Items.CONDUIT)
            .requiredStation(SIMPLE_AUGMENT_STATION_ID)
            .uiX(5).uiY(90).time(800).rfCost(50_000_000)
            .export(exporter, "waterbreath");
        
        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.PROCESSING_UNIT, 64)
            .researchCost(TagContent.BIOMATTER, 48)
            .researchCost(Items.GOLDEN_CARROT, 64)
            .applyCost(TagContent.BIOMATTER, 32)
            .applyCost(BlockContent.ITEM_PIPE, 64)
            .applyCost(Items.HOPPER, 8)
            .requirement(Oritech.id("augment/armor"))
            .requirement(Oritech.id("augment/hpboostmore"))
            .requiredStation(SIMPLE_AUGMENT_STATION_ID)
            .uiX(90).uiY(90).time(500).rfCost(30_000_000)
            .export(exporter, "autofeeder");
        
        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.MAGNETIC_COIL, 64)
            .researchCost(ItemContent.ENERGITE_INGOT, 48)
            .researchCost(Items.LODESTONE, 2)
            .applyCost(ItemContent.MAGNETIC_COIL, 32)
            .applyCost(ConventionalItemTags.COPPER_INGOTS, 64)
            .requirement(Oritech.id("augment/superminingspeed"))
            .requiredStation(SIMPLE_AUGMENT_STATION_ID)
            .uiX(105).uiY(10).time(2400).rfCost(400_000_000)
            .export(exporter, "magnet");
        
        AugmentRecipeBuilder.build()
            .researchCost(ItemContent.ENDERIC_LENS, 64)
            .researchCost(Items.AMETHYST_BLOCK, 48)
            .researchCost(ItemContent.OVERCHARGED_CRYSTAL)
            .researchCost(ItemContent.PROMETHEUM_INGOT, 8)
            .researchCost(Items.SCULK_SENSOR, 4)
            .applyCost(ItemContent.ENDERIC_LENS, 32)
            .applyCost(Items.REDSTONE_TORCH, 64)
            .requirement(Oritech.id("augment/nightvision"))
            .requirement(Oritech.id("augment/magnet"))
            .requiredStation(ARCANE_AUGMENT_STATION_ID)
            .uiX(130).uiY(10).time(3200).rfCost(200_000_000)
            .export(exporter, "orefinder");
    }
    
    private void addReactorBlocks(RecipeExporter exporter) {
        
        // single rod
        offerRodRecipe(exporter, BlockContent.REACTOR_ROD.asItem(), of(TagContent.PLASTIC_PLATES), of(ItemContent.ENERGITE_INGOT), "singlerod");
        // dual rod
        offerRodCombinationRecipe(exporter, BlockContent.REACTOR_DOUBLE_ROD.asItem(), of(BlockContent.REACTOR_REFLECTOR), of(BlockContent.REACTOR_ROD), "doublerod");
        // quad rod
        offerRodCombinationRecipe(exporter, BlockContent.REACTOR_QUAD_ROD.asItem(), of(BlockContent.REACTOR_REFLECTOR), of(BlockContent.REACTOR_DOUBLE_ROD), "quadrod");
        
        // reactor plating: steel and machine plating in crafting table / assembler
        offerMachinePlatingRecipe(exporter, BlockContent.REACTOR_WALL.asItem(), of(TagContent.MACHINE_PLATING), of(TagContent.STEEL_INGOTS), of(TagContent.NICKEL_INGOTS), 4, "reactorplatingcrafting");
        AssemblerRecipeBuilder.build().input(TagContent.MACHINE_PLATING).input(TagContent.MACHINE_PLATING).input(TagContent.STEEL_INGOTS).input(TagContent.NICKEL_INGOTS).result(BlockContent.REACTOR_WALL.asItem(), 3).timeMultiplier(0.8f).export(exporter, "reactorplatingalt");
        
        // neutron reflectors: expensive, needs duratium core, adamant frame and reactor walls
        offerMachinePlatingRecipe(exporter, BlockContent.REACTOR_REFLECTOR.asItem(), of(BlockContent.REACTOR_WALL), of(ItemContent.ADAMANT_INGOT), of(ItemContent.DURATIUM_INGOT), 1, "reflector");
        
        // reactor controller: reactor wall, processing unit
        offerRodCombinationRecipe(exporter, BlockContent.REACTOR_CONTROLLER.asItem(), of(BlockContent.REACTOR_WALL), of(ItemContent.PROCESSING_UNIT), "controller");
        
        // reactor energy port: reactor wall, storage unit, electrum
        offerParticleMotorRecipe(exporter, BlockContent.REACTOR_ENERGY_PORT.asItem(), of(TagContent.ELECTRUM_INGOTS), of(BlockContent.ENERGY_PIPE), of(BlockContent.REACTOR_WALL), of(ConventionalItemTags.IRON_INGOTS), "energyport");
        
        // reactor redstone port: wall, processing unit, repeater, torch
        offerParticleMotorRecipe(exporter, BlockContent.REACTOR_REDSTONE_PORT.asItem(), of(ItemContent.PROCESSING_UNIT), of(Items.REPEATER), of(BlockContent.REACTOR_WALL), of(Items.REDSTONE_TORCH), "redstoneport");
        
        // reactor fuel port: wall, hopper, motor, item pipe
        offerParticleMotorRecipe(exporter, BlockContent.REACTOR_FUEL_PORT.asItem(), of(BlockContent.ITEM_PIPE), of(Items.HOPPER), of(BlockContent.REACTOR_WALL), of(ConventionalItemTags.CHESTS), "fuelport");
        
        // reactor absorber port: wall, ice, motor, item pipe
        offerParticleMotorRecipe(exporter, BlockContent.REACTOR_ABSORBER_PORT.asItem(), of(BlockContent.ITEM_PIPE), of(Items.HOPPER), of(BlockContent.REACTOR_WALL), of(Blocks.ICE), "absorberport");
        
        // reactor absorber : wall, steel, ice
        offerBatteryRecipe(exporter, BlockContent.REACTOR_CONDENSER.asItem(), of(Items.ICE), of(ConventionalItemTags.GLASS_BLOCKS), of(TagContent.STEEL_INGOTS), "condenser");
        
        // reactor vent: motor, carbon fibre
        offerStarRecipe(exporter, BlockContent.REACTOR_VENT.asItem(), of(ItemContent.MOTOR), of(TagContent.CARBON_FIBRE), "reactorvent");
        
        // reactor heat pipe: electrum, gold
        offerStarRecipe(exporter, BlockContent.REACTOR_HEAT_PIPE.asItem(), of(TagContent.ELECTRUM_INGOTS), of(ConventionalItemTags.GOLD_INGOTS), "reactorheatpipe");
        
        // explosives
        offerMachinePlatingRecipe(exporter, BlockContent.LOW_YIELD_NUKE.asItem(), of(ItemContent.DUBIOS_CONTAINER), of(ItemContent.URANIUM_PELLET), of(Items.TNT), 1, "nuke");
        offerMachinePlatingRecipe(exporter, BlockContent.NUKE.asItem(), of(ItemContent.HEISENBERG_COMPENSATOR), of(ItemContent.PLUTONIUM_PELLET), of(Items.TNT), 1, "nukebetter");
    }
    
    private void addReactorFuels(RecipeExporter exporter) {
        ReactorGeneratorRecipeBuilder.build().input(ItemContent.SMALL_URANIUM_PELLET).time(400).export(exporter, "smallpellet");
        ReactorGeneratorRecipeBuilder.build().input(ItemContent.URANIUM_PELLET).time(4000).export(exporter, "pellet");
        ReactorGeneratorRecipeBuilder.build().input(ItemContent.SMALL_PLUTONIUM_PELLET).time(4000).export(exporter, "smallplutoniumpellet");
        ReactorGeneratorRecipeBuilder.build().input(ItemContent.PLUTONIUM_PELLET).time(40000).export(exporter, "plutoniumpellet");
    }
    
    private void addLaserTransformations(RecipeExporter exporter) {
        LaserRecipeBuilder.build().input(Items.AMETHYST_CLUSTER).result(ItemContent.FLUXITE).export(exporter, "fluxite");
        LaserRecipeBuilder.build().input(BlockContent.URANIUM_CRYSTAL).result(ItemContent.PLUTONIUM_DUST).export(exporter, "plutoniumdust");
    }

    private void addCompactingRecipe(RecipeExporter exporter, ItemConvertible resBlock, ItemConvertible resItem, Ingredient itemIng, Ingredient blockIng) {
        ShapelessRecipeJsonBuilder
          .create(RecipeCategory.MISC, resItem, 9)
          .input(blockIng)
          .criterion(hasItem(resBlock), conditionsFromItem(resBlock))
          .offerTo(exporter, Identifier.of(RecipeProvider.getRecipeName(resBlock) + "blockinv"));
        ShapedRecipeJsonBuilder
          .create(RecipeCategory.MISC, resBlock)
          .input('#', itemIng)
          .pattern("###")
          .pattern("###")
          .pattern("###")
          .criterion(hasItem(resItem), conditionsFromItem(resItem))
          .offerTo(exporter, Identifier.of(RecipeProvider.getRecipeName(resBlock) + "block"));
    }
    
    // crafting shapes
    public void offerCableRecipe(RecipeExporter exporter, ItemStack output, Ingredient input, String suffix) {
        var item = output.getItem();
        createCableRecipe(RecipeCategory.MISC, output.getItem(), output.getCount(), input).criterion(hasItem(item), conditionsFromItem(item)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerInsulatedCableRecipe(RecipeExporter exporter, ItemStack output, Ingredient input, Ingredient insulation, String suffix) {
        var item = output.getItem();
        createInsulatedCableRecipe(RecipeCategory.MISC, output.getItem(), output.getCount(), input, insulation).criterion(hasItem(item), conditionsFromItem(item)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerFramedCableRecipe(RecipeExporter exporter, ItemStack output, Ingredient input, String suffix) {
        var item = output.getItem();
        createFramedCableRecipe(RecipeCategory.MISC, output.getItem(), output.getCount(), input).criterion(hasItem(item), conditionsFromItem(item)).offerTo(exporter, "crafting/frame_" + suffix);
    }
    
    public void offerCableFromFrameRecipe(RecipeExporter exporter, ItemStack output, Ingredient frame, String suffix) {
        var item = output.getItem();
        ShapelessRecipeJsonBuilder.create(RecipeCategory.MISC, item, output.getCount()).input(frame).criterion(hasItem(item), conditionsFromItem(item)).offerTo(exporter, "crafting/unframe_" + suffix);
    }
    
    public void offerCableDuctRecipe(RecipeExporter exporter, ItemStack output, Ingredient input, String suffix) {
        var item = output.getItem();
        createCableDuctRecipe(RecipeCategory.MISC, item, output.getCount(), input).criterion(hasItem(item), conditionsFromItem(item)).offerTo(exporter, "crafting/duct_" + suffix);
    }
    
    public void offerCableFromDuctRecipe(RecipeExporter exporter, ItemStack output, Ingredient duct, String suffix) {
        var item = output.getItem();
        ShapelessRecipeJsonBuilder.create(RecipeCategory.MISC, item, output.getCount()).input(duct).criterion(hasItem(item), conditionsFromItem(item)).offerTo(exporter, "crafting/unduct_" + suffix);
    }
    
    public CraftingRecipeJsonBuilder createCableRecipe(RecipeCategory category, Item output, int count, Ingredient input) {
        return ShapedRecipeJsonBuilder.create(category, output, count).input('#', input).pattern("   ").pattern("###");
    }
    
    public CraftingRecipeJsonBuilder createFramedCableRecipe(RecipeCategory category, Item output, int count, Ingredient input) {
        return ShapedRecipeJsonBuilder.create(category, output, count).input('c', input).input('p', Ingredient.fromTag(TagContent.MACHINE_PLATING)).pattern("ccc").pattern("cpc").pattern("ccc");
    }
    
    public CraftingRecipeJsonBuilder createCableDuctRecipe(RecipeCategory category, Item output, int count, Ingredient input) {
        return ShapedRecipeJsonBuilder.create(category, output, count).input('c', input).input('p', Ingredient.fromTag(TagContent.MACHINE_PLATING)).input('s', of(Blocks.STONE)).pattern("csc").pattern("sps").pattern("csc");
    }
    
    public void offerMotorRecipe(RecipeExporter exporter, Item output, Ingredient shaft, Ingredient core, Ingredient wall, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('s', shaft).input('c', core).input('w', wall).pattern(" s ").pattern("wcw").pattern("wcw");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "motor/" + suffix);
    }
    
    public void offerManualAlloyRecipe(RecipeExporter exporter, Item output, Ingredient A, Ingredient B, String suffix) {
        offerManualAlloyRecipe(exporter, output, A, B, 1, suffix);
    }
    
    public void offerManualAlloyRecipe(RecipeExporter exporter, Item output, Ingredient A, Ingredient B, int count, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, count).input('a', A).input('b', B).pattern("aa ").pattern("bb ");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/alloy/" + suffix);
    }
    
    public void offerGeneratorRecipe(RecipeExporter exporter, Item output, Ingredient base, Ingredient sides, Ingredient core, Ingredient frame, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('s', sides).input('c', core).input('f', frame).input('b', base)
                        .pattern("fff")
                        .pattern("fcf")
                        .pattern("sbs");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerFurnaceRecipe(RecipeExporter exporter, Item output, Ingredient bottom, Ingredient botSides, Ingredient middleSides, Ingredient core, Ingredient top, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('s', botSides).input('c', core).input('f', top).input('b', bottom).input('m', middleSides)
                        .pattern("fff")
                        .pattern("mcm")
                        .pattern("sbs");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerAtomicForgeRecipe(RecipeExporter exporter, Item output, Ingredient base, Ingredient middleSides, Ingredient core, Ingredient top, Ingredient frame, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('s', top).input('c', core).input('f', frame).input('b', base).input('m', middleSides)
                        .pattern("fsf")
                        .pattern("mcm")
                        .pattern("bbb");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerBatteryRecipe(RecipeExporter exporter, Item output, Ingredient inner, Ingredient sides, Ingredient top, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('t', top).input('c', inner).input('f', sides)
                        .pattern(" t ")
                        .pattern("fcf")
                        .pattern("fcf");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerMachineFrameRecipe(RecipeExporter exporter, Item output, Ingredient base, Ingredient alt, int count, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, count).input('s', base).input('c', alt)
                        .pattern(" s ")
                        .pattern("csc")
                        .pattern(" s ");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerMachineCoreRecipe(RecipeExporter exporter, Item output, Ingredient base, Ingredient alt, String suffix) {
        offerMachineCoreRecipe(exporter, output, 1, base, alt, suffix);
    }
    
    public void offerMachineCoreRecipe(RecipeExporter exporter, Item output, int count, Ingredient base, Ingredient alt, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, count).input('s', base).input('c', alt)
                        .pattern("sss")
                        .pattern("scs")
                        .pattern("sss");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerDrillRecipe(RecipeExporter exporter, Item output, Ingredient core, Ingredient motor, Ingredient center, Ingredient head, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('s', core).input('m', motor).input('a', center).input('e', head)
                        .pattern(" a ")
                        .pattern("aea")
                        .pattern("mss");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerWrenchRecipe(RecipeExporter exporter, Item output, Ingredient A, Ingredient B, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('a', A).input('b', B)
                        .pattern(" a ")
                        .pattern(" ba")
                        .pattern("a  ");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerChainsawRecipe(RecipeExporter exporter, Item output, Ingredient core, Ingredient motor, Ingredient center, Ingredient head, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('s', core).input('m', motor).input('a', center).input('e', head)
                        .pattern("aa ")
                        .pattern("ae ")
                        .pattern("mss");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerAxeRecipe(RecipeExporter exporter, Item output, Ingredient plating, Ingredient core, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('p', plating).input('c', core)
                        .pattern("pp ")
                        .pattern("pc ")
                        .pattern(" c ");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerPickaxeRecipe(RecipeExporter exporter, Item output, Ingredient plating, Ingredient core, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('p', plating).input('c', core)
                        .pattern("ppp")
                        .pattern(" c ")
                        .pattern(" c ");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerHelmetRecipe(RecipeExporter exporter, Item output, Ingredient plating, Ingredient core, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('p', plating).input('c', core)
                        .pattern("ppp")
                        .pattern("pcp")
                        .pattern("   ");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerChestplateRecipe(RecipeExporter exporter, Item output, Ingredient plating, Ingredient core, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('p', plating).input('c', core)
                        .pattern("p p")
                        .pattern("ppp")
                        .pattern("pcp");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerLegsRecipe(RecipeExporter exporter, Item output, Ingredient plating, Ingredient core, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('p', plating).input('c', core)
                        .pattern("ppp")
                        .pattern("pcp")
                        .pattern("p p");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerFeetRecipe(RecipeExporter exporter, Item output, Ingredient plating, Ingredient core, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('p', plating).input('c', core)
                        .pattern("   ")
                        .pattern("p p")
                        .pattern("c c");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerRodRecipe(RecipeExporter exporter, Item output, Ingredient cap, Ingredient rod, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('c', cap).input('r', rod)
                        .pattern(" c ")
                        .pattern(" r ")
                        .pattern(" r ");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerRodCombinationRecipe(RecipeExporter exporter, Item output, Ingredient cap, Ingredient rod, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('c', cap).input('r', rod)
                        .pattern("   ")
                        .pattern("rcr")
                        .pattern("   ");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerStarRecipe(RecipeExporter exporter, Item output, Ingredient inner, Ingredient outer, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('c', inner).input('o', outer)
                        .pattern(" o ")
                        .pattern("oco")
                        .pattern(" o ");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerTankRecipe(RecipeExporter exporter, Item output, Ingredient plating, Ingredient core, Ingredient sides, String suffix) {
        offerTankRecipe(exporter, output, 1, plating, core, sides, suffix);
    }
    
    public void offerTankRecipe(RecipeExporter exporter, Item output, int count, Ingredient plating, Ingredient core, Ingredient sides, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, count).input('p', plating).input('s', sides).input('c', core)
                        .pattern("ppp")
                        .pattern("scs")
                        .pattern("ppp");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerTwoComponentRecipe(RecipeExporter exporter, Item output, Ingredient A, Ingredient B, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('a', A).input('b', B)
                        .pattern("ab ");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerLeverRecipe(RecipeExporter exporter, Item output, Ingredient A, Ingredient B, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('a', A).input('b', B)
                        .pattern("a  ")
                        .pattern("b  ");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerParticleMotorRecipe(RecipeExporter exporter, Item output, Ingredient rail, Ingredient top, Ingredient baseInner, Ingredient baseOuter, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, output, 1).input('r', rail).input('t', top).input('i', baseInner).input('o', baseOuter)
                        .pattern(" t ")
                        .pattern("rrr")
                        .pattern("oio");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerMachinePlatingRecipe(RecipeExporter exporter, Item output, Ingredient side, Ingredient edge, Ingredient core, int count, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.REDSTONE, output, count).input('a', side).input('e', edge).input('c', core)
                        .pattern("eae")
                        .pattern("aca")
                        .pattern("eae");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerDoorRecipe(RecipeExporter exporter, Item output, Ingredient A, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.REDSTONE, output, 1).input('a', A)
                        .pattern("aa ")
                        .pattern("aa ")
                        .pattern("aa ");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/" + suffix);
    }
    
    public void offerSlabRecipe(RecipeExporter exporter, Item output, Ingredient A, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.BUILDING_BLOCKS, output, 6).input('a', A)
                        .pattern("aaa");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/slab/" + suffix);
    }
    
    public void offerStairsRecipe(RecipeExporter exporter, Item output, Ingredient A, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.BUILDING_BLOCKS, output, 4).input('a', A)
                        .pattern("a  ")
                        .pattern("aa ")
                        .pattern("aaa");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/stairs/" + suffix);
    }
    
    public void offerPressurePlateRecipe(RecipeExporter exporter, Item output, Ingredient A, String suffix) {
        var builder = ShapedRecipeJsonBuilder.create(RecipeCategory.REDSTONE, output, 1).input('a', A)
                        .pattern("aa");
        builder.criterion(hasItem(output), conditionsFromItem(output)).offerTo(exporter, "crafting/pressureplate/" + suffix);
    }
}