/**
 * Multiblock Registry.
 * This is the place custom multiblock recipes (Like Discharging) are defined.
 * It is also where the shapes for multis are defined.
 */
const List = Java.loadClass("java.util.List")
const Tags = Java.loadClass("dev.latvian.mods.kubejs.util.Tags")
const LocalizationUtils = Java.loadClass("com.lowdragmc.lowdraglib.utils.LocalizationUtils")
const FusionReactorMachine = Java.loadClass("com.gregtechceu.gtceu.common.machine.multiblock.electric.FusionReactorMachine")
const CoilWorkableElectricMultiblockMachine = Java.loadClass("com.gregtechceu.gtceu.api.machine.multiblock.CoilWorkableElectricMultiblockMachine")
const RecipeLogic = Java.loadClass("com.gregtechceu.gtceu.api.machine.trait.RecipeLogic")
const MoniGuiTextures = Java.loadClass("net.neganote.monilabs.client.gui.MoniGuiTextures");
Java.loadClass("net.neganote.monilabs.client.render.MoniDynamicRenderHelper");
Java.loadClass("net.neganote.monilabs.client.render.HelicalFusionRenderer");

GTCEuStartupEvents.registry("gtceu:recipe_type", event => {

    // Normal mode-exclusive Multis
    if (doHNN) {
        // Simulation Supercomputer
        event.create("simulation_supercomputer")
            .category("multiblock")
            .setEUIO("in")
            .setMaxIOSize(2, 2, 0, 0)
            .setSlotOverlay(false, false, GuiTextures.ARROW_INPUT_OVERLAY)
            .setProgressBar(MoniGuiTextures.PROGRESS_BAR_SIMULATION, FillDirection.LEFT_TO_RIGHT)
            .setSound(GTSoundEntries.COMPUTATION)
            .setSound(GTSoundEntries.ASSEMBLER)

        // Loot Superfabricator
        event.create("loot_superfabricator")
            .category("multiblock")
            .setEUIO("in")
            .setMaxIOSize(2, 1, 0, 0)
            .setSlotOverlay(false, false, GuiTextures.ARROW_INPUT_OVERLAY)
            .setProgressBar(MoniGuiTextures.PROGRESS_BAR_SIMULATION, FillDirection.LEFT_TO_RIGHT)
            .setSound(GTSoundEntries.COMPUTATION)
    }


    // Hard mode-exclusive Multis

    // Actualization Chamber
    event.create("actualization_chamber")
        .category("multiblock")
        .setEUIO("in")
        .setMaxIOSize(2, 20, 0, 0)
        .setSlotOverlay(false, false, GuiTextures.ARROW_INPUT_OVERLAY)
        .setProgressBar(GuiTextures.PROGRESS_BAR_ARROW, FillDirection.LEFT_TO_RIGHT)
        .setSound(GTSoundEntries.COOLING)

    // Naquadah Reactor I Recipe type
    event.create("naquadah_reactor")
        .category("multiblock")
        .setEUIO("out")
        .setMaxIOSize(2, 2, 0, 0)
        .setSlotOverlay(false, false, GuiTextures.ARROW_INPUT_OVERLAY)
        .setProgressBar(GuiTextures.PROGRESS_BAR_ARROW, FillDirection.LEFT_TO_RIGHT)
        .setSound(GTSoundEntries.ARC);

    // Large Naquadah Reactor Recipe Type
    event.create("large_naquadah_reactor")
        .category("multiblock")
        .setEUIO("out")
        .setMaxIOSize(0, 0, 1, 0)
        .setSlotOverlay(false, false, GuiTextures.ARROW_INPUT_OVERLAY)
        .setProgressBar(GuiTextures.PROGRESS_BAR_ARROW, FillDirection.LEFT_TO_RIGHT)
        .setSound(GTSoundEntries.ARC)

    // Naquadah Fuel Refinery
    event.create("naquadah_refinery")
        .category("multiblock")
        .setEUIO("in")
        .setMaxIOSize(6, 0, 5, 1)
        .setSlotOverlay(false, false, GuiTextures.ARROW_INPUT_OVERLAY)
        .setProgressBar(GuiTextures.PROGRESS_BAR_ARROW, FillDirection.LEFT_TO_RIGHT)
        .setSound(GTSoundEntries.COOLING)

    // Greenhouse
    event.create("greenhouse")
        .category("multiblock")
        .setEUIO("in")
        .setMaxIOSize(3, 6, 1, 0)
        .setSlotOverlay(false, false, GuiTextures.ARROW_INPUT_OVERLAY)
        .setProgressBar(GuiTextures.PROGRESS_BAR_ARROW, FillDirection.LEFT_TO_RIGHT)
        .setSound(GTSoundEntries.TURBINE)

    // Quintessence Infuser
    event.create("quintessence_infuser")
        .category("multiblock")
        .setEUIO("in")
        .setMaxIOSize(2, 2, 1, 0)
        .setSlotOverlay(false, false, GuiTextures.ARROW_INPUT_OVERLAY)
        .setProgressBar(MoniGuiTextures.PROGRESS_BAR_XP, FillDirection.DOWN_TO_UP)
        .setSound(GTSoundEntries.CENTRIFUGE)

    // Rock Cycle Simulator
    event.create("rock_cycle_simulator")
        .category("multiblock")
        .setEUIO("in")
        .setMaxIOSize(1, 1, 0, 0)
        .setSlotOverlay(false, false, GuiTextures.ARROW_INPUT_OVERLAY)
        .setProgressBar(GuiTextures.PROGRESS_BAR_MACERATE, FillDirection.LEFT_TO_RIGHT)
        .setSound(GTSoundEntries.MINER)

    // Discharger
    event.create("discharger")
        .category("multiblock")
        .setEUIO("in")
        .setMaxIOSize(9, 1, 1, 0)
        .setSlotOverlay(false, false, GuiTextures.ARROW_INPUT_OVERLAY)
        .setProgressBar(GuiTextures.PROGRESS_BAR_ARROW, FillDirection.LEFT_TO_RIGHT)
        .setSound(GTSoundEntries.ELECTROLYZER)

    event.create("antimatter_manipulation")
        .category("multiblock")
        .setEUIO("in")
        .setMaxIOSize(1, 1, 3, 1)
        .setSlotOverlay(false, false, GuiTextures.ARROW_INPUT_OVERLAY)
        .setProgressBar(GuiTextures.PROGRESS_BAR_ARROW, FillDirection.LEFT_TO_RIGHT)
        .setSound(GTSoundEntries.CHEMICAL)

    // Recipe types for coremod multis
    // MoniRecipeTypes.createPrismaCRecipeType("chromatic_processing")
    // MoniRecipeTypes.createPrismaCRecipeType("chromatic_transcendence")

    event.create("omnic_synthesis")
        .category("multiblock")
        .setEUIO("in")
        .setMaxIOSize(1, 1, 0, 0)
        .setProgressBar(GuiTextures.PROGRESS_BAR_ARROW, FillDirection.LEFT_TO_RIGHT)
        .setSound(GTSoundEntries.CHEMICAL)
})

GTCEuStartupEvents.registry("gtceu:machine", event => {

    // EMI displays for various multis
    GTRecipeTypes.get("omnic_synthesis")
        .addDataInfo((data) => LocalizationUtils.format("gtceu.multiblock.omnic_synthesizer.emi_info.0"))
        .addDataInfo((data) => LocalizationUtils.format("gtceu.multiblock.omnic_synthesizer.emi_info.1"))
        .addDataInfo((data) => LocalizationUtils.format("gtceu.multiblock.omnic_synthesizer.emi_info.2"))
        .addDataInfo((data) => LocalizationUtils.format("gtceu.multiblock.omnic_synthesizer.emi_info.3"))

    // Normal mode-exclusive multis
    if (doHNN) {

        // Simulation Supercomputer
        event.create("simulation_supercomputer", "multiblock")
            .rotationState(RotationState.NON_Y_AXIS)
            .recipeTypes("simulation_supercomputer")
            .recipeModifiers([GTRecipeModifiers.OC_NON_PERFECT, GTRecipeModifiers.BATCH_MODE])
            .appearanceBlock(() => new Block.getBlock("kubejs:dark_steel_casing"))
            .pattern(definition => FactoryBlockPattern.start()
                .aisle("CCC", "CEC", "CCC")
                .aisle("CCC", "EME", "CCC")
                .aisle("C@C", "CEC", "CCC")
                .where("@", Predicates.controller(Predicates.blocks(definition.get())))
                .where("E", Predicates.blocks("gtceu:pulsating_alloy_block"))
                .where("M", Predicates.blocks("gtceu:mythril_block"))
                .where("C", Predicates.blocks("kubejs:dark_steel_casing").setMinGlobalLimited(15)
                    .or(Predicates.autoAbilities(definition.getRecipeTypes()))
                    .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1)))
                .where(" ", Predicates.air())
                .build())
            .workableCasingModel("kubejs:block/casing/dark_steel/casing",
                "gtceu:block/multiblock/simulation_chamber")

        // Loot Superfabricator
        event.create("loot_superfabricator", "multiblock")
            .rotationState(RotationState.NON_Y_AXIS)
            .recipeTypes("loot_superfabricator")
            .recipeModifiers([GTRecipeModifiers.OC_NON_PERFECT])
            .appearanceBlock(() => new Block.getBlock("kubejs:dark_steel_casing"))
            .pattern(definition => FactoryBlockPattern.start()
                .aisle("CCC", "CEC", "CCC")
                .aisle("CCC", "EME", "CCC")
                .aisle("C@C", "CEC", "CCC")
                .where("@", Predicates.controller(Predicates.blocks(definition.get())))
                .where("E", Predicates.blocks("gtceu:energetic_alloy_block"))
                .where("M", Predicates.blocks("gtceu:mythril_block"))
                .where("C", Predicates.blocks("kubejs:dark_steel_casing").setMinGlobalLimited(15)
                    .or(Predicates.autoAbilities(definition.getRecipeTypes()))
                    .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1)))
                .where(" ", Predicates.air())
                .build())
            .workableCasingModel("kubejs:block/casing/dark_steel/casing",
                "gtceu:block/multiblock/loot_fabricator")


        // Simulation Quantumcomputer
        event.create("simulation_quantumcomputer", "multiblock")
            .rotationState(RotationState.NON_Y_AXIS)
            .recipeTypes("simulation_supercomputer")
            .recipeModifiers([GTRecipeModifiers.PARALLEL_HATCH, GTRecipeModifiers.OC_NON_PERFECT, GTRecipeModifiers.BATCH_MODE])
            .appearanceBlock(() => new Block.getBlock("kubejs:dark_steel_casing"))
            .pattern(definition => FactoryBlockPattern.start()
                .aisle("CCCCC", "VEEEV", "VEEEV", "VEEEV", "CCCCC")
                .aisle("CCCCC", "QOOOQ", "VOOOV", "QOOOQ", "CCCCC")
                .aisle("CCCCC", "QOOOQ", "VO OV", "QOOOQ", "CCCCC")
                .aisle("CCCCC", "QOOOQ", "VOOOV", "QOOOQ", "CCCCC")
                .aisle("CC@CC", "VEQEV", "VQQQV", "VEQEV", "CCCCC")
                .where("@", Predicates.controller(Predicates.blocks(definition.get())))
                .where("V", Predicates.blocks(GCYMBlocks.CASING_VIBRATION_SAFE.get()))
                .where("E", Predicates.blocks("gtceu:enderium_block"))
                .where("O", Predicates.blocks("gtceu:omnium_block"))
                .where("Q", Predicates.blocks("ae2:quartz_vibrant_glass"))
                .where("G", Predicates.blocks(GTBlocks.CASING_TEMPERED_GLASS.get()))
                .where("C", Predicates.blocks("kubejs:dark_steel_casing").setMinGlobalLimited(40)
                    .or(Predicates.autoAbilities(definition.getRecipeTypes()))
                    .or(Predicates.abilities(PartAbility.PARALLEL_HATCH).setMaxGlobalLimited(1))
                    .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1)))
                .where(" ", Predicates.air())
                .build())
            .workableCasingModel("kubejs:block/casing/dark_steel/casing",
                "gtceu:block/multiblock/simulation_chamber")

        // Loot Quantumfabricator
        event.create("loot_quantumfabricator", "multiblock")
            .rotationState(RotationState.NON_Y_AXIS)
            .recipeTypes("loot_superfabricator")
            .recipeModifiers([GTRecipeModifiers.PARALLEL_HATCH, GTRecipeModifiers.OC_NON_PERFECT, GTRecipeModifiers.BATCH_MODE])
            .appearanceBlock(() => new Block.getBlock("kubejs:dark_steel_casing"))
            .pattern(definition => FactoryBlockPattern.start()
                .aisle("CCCCC", "VEEEV", "VEEEV", "VEEEV", "CCCCC")
                .aisle("CCCCC", "QOOOQ", "VOOOV", "QOOOQ", "CCCCC")
                .aisle("CCCCC", "QOOOQ", "VO OV", "QOOOQ", "CCCCC")
                .aisle("CCCCC", "QOOOQ", "VOOOV", "QOOOQ", "CCCCC")
                .aisle("CC@CC", "VEQEV", "VQQQV", "VEQEV", "CCCCC")
                .where("@", Predicates.controller(Predicates.blocks(definition.get())))
                .where("V", Predicates.blocks(GCYMBlocks.CASING_SHOCK_PROOF.get()))
                .where("E", Predicates.blocks("gtceu:energetic_alloy_block"))
                .where("O", Predicates.blocks("gtceu:omnium_block"))
                .where("Q", Predicates.blocks("ae2:quartz_vibrant_glass"))
                .where("G", Predicates.blocks(GTBlocks.CASING_TEMPERED_GLASS.get()))
                .where("C", Predicates.blocks("kubejs:dark_steel_casing").setMinGlobalLimited(40)
                    .or(Predicates.autoAbilities(definition.getRecipeTypes()))
                    .or(Predicates.abilities(PartAbility.PARALLEL_HATCH).setMaxGlobalLimited(1))
                    .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1)))
                .where(" ", Predicates.air())
                .build())
            .workableCasingModel("kubejs:block/casing/dark_steel/casing",
                "gtceu:block/multiblock/loot_fabricator")
    }

    // Helical Fusion Reactor
    FusionReactorMachine.registerFusionTier(GTValues.UHV, " (Helical)")
    event.create("helical_fusion_reactor", "multiblock")
        .machine((holder) => new FusionReactorMachine(holder, GTValues.UEV))
        .rotationState(RotationState.ALL)
        .recipeTypes(GTRecipeTypes.FUSION_RECIPES)
        .recipeModifiers([GTRecipeModifiers.PARALLEL_HATCH, MachineModifiers.FUSION_REACTOR, GTRecipeModifiers.BATCH_MODE])
        .appearanceBlock(GCYMBlocks.CASING_ATOMIC)
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("#######################", "#######################", "#######################", "###F##F#N#####N#F##F###", "###FNNFNN#####NNFNNF###", "###F##F#N#####N#F##F###", "#######################", "#######################", "#######################")
            .aisle("#######################", "###F##F###NNN###F##F###", "###F##F##N###N##F##F###", "###ECCBC#######CBCCE###", "###BBBBC#######CBBBB###", "###ECCBC#######CBCCE###", "###F##F##N###N##F##F###", "###F##F###NNN###F##F###", "#######################")
            .aisle("#######################", "###F##F##N###N##F##F###", "##DDDDDDD#####DDDDDDD##", "#CDTTTTTDCCCCCDTTTTTDC#", "#CDTTTTTDCGGGCDTTTTTDC#", "#CDTTTTTDCCCCCDTTTTTDC#", "##DDDDDDD#####DDDDDDD##", "###F##F##N###N##F##F###", "#######################")
            .aisle("###F##F#N#####N#F##F###", "###ECCBC#######CBCCE###", "#CDTTTTTDCCCCCDTTTTTDC#", "C                     C", "C                     C", "C                     C", "#CDTTTTTDCCCCCDTTTTTDC#", "###ECCBC#######CBCCE###", "###F##F#N#####N#F##F###")
            .aisle("###FNNFNN#####NNFNNF###", "###BBBBC#######CBBBB###", "#CDTTTTTDCGGGCDTTTTTDC#", "C                     C", "G                     G", "C                     C", "#CDTTTTTDCGGGCDTTTTTDC#", "###BBBBC#######CBBBB###", "###FNNFNN#####NNFNNF###")
            .aisle("###F##F#N#####N#F##F###", "###ECCBC#######CBCCE###", "#CDTTTTTDCCCCCDTTTTTDC#", "C                     C", "C                     C", "C                     C", "#CDTTTTTDCCCCCDTTTTTDC#", "###ECCBC#######CBCCE###", "###F##F#N#####N#F##F###")
            .aisle("#######################", "###F##F##N###N##F##F###", "##DDDDDDD#####DDDDDDD##", "#CDTTTTTDCC@CCDTTTTTDC#", "#CDTTTTTDCGGGCDTTTTTDC#", "#CDTTTTTDCCCCCDTTTTTDC#", "##DDDDDDD#####DDDDDDD##", "###F##F##N###N##F##F###", "#######################")
            .aisle("#######################", "###F##F###NNN###F##F###", "###F##F##N###N##F##F###", "###ECCBC#######CBCCE###", "###BBBBC#######CBBBB###", "###ECCBC#######CBCCE###", "###F##F##N###N##F##F###", "###F##F###NNN###F##F###", "#######################")
            .aisle("#######################", "#######################", "#######################", "###F##F#N#####N#F##F###", "###FNNFNN#####NNFNNF###", "###F##F#N#####N#F##F###", "#######################", "#######################", "#######################")
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("B", Predicates.blocks(GCYMBlocks.CASING_ATOMIC.get()))
            .where("G", Predicates.blocks(GTBlocks.FUSION_GLASS.get())
                .or(Predicates.blocks(GCYMBlocks.CASING_ATOMIC.get())))
            .where("E", Predicates.abilities(PartAbility.INPUT_ENERGY)
                .setMinGlobalLimited(1)
                .setMaxGlobalLimited(16)
                .setPreviewCount(16)
                .or(Predicates.blocks(GCYMBlocks.CASING_ATOMIC.get())))
            .where("C", Predicates.blocks(GCYMBlocks.CASING_ATOMIC.get()).setMinGlobalLimited(130)
                .or(Predicates.abilities(PartAbility.IMPORT_FLUIDS).setMinGlobalLimited(2))
                .or(Predicates.abilities(PartAbility.EXPORT_FLUIDS).setMinGlobalLimited(1))
                .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1))
                .or(Predicates.abilities(PartAbility.PARALLEL_HATCH).setMaxGlobalLimited(1)))
            .where("D", Predicates.blocks("monilabs:bioalloy_fusion_casing"))
            .where("F", Predicates.blocks("kubejs:omnic_matrix_coil_block"))
            .where("T", Predicates.blocks(GTBlocks.COIL_TRITANIUM.get()))
            .where("N", Predicates.frames(GTMaterials.get("activated_netherite")))
            .where(" ", Predicates.air())
            .where("#", Predicates.any())
            .build())
        .model(GTMachineModels.createWorkableCasingMachineModel(GTCEu.id("block/casings/gcym/atomic_casing"), GTCEu.id("block/multiblock/fusion_reactor"))
            ["andThen(java.util.function.Consumer)"](b => b.addDynamicRenderer(() => MoniDynamicRenderHelper.createHelicalFusionRenderer()))
        )

    // Greenhouse
    event.create("greenhouse", "multiblock")
        .rotationState(RotationState.NON_Y_AXIS)
        .recipeTypes("greenhouse")
        .appearanceBlock(GTBlocks.CASING_STEEL_SOLID)
        .recipeModifiers([GTRecipeModifiers.OC_NON_PERFECT, GTRecipeModifiers.BATCH_MODE])
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("SSSSS", "UDDDU", "UDDDU", "UUGUU", "#UUU#")
            .aisle("SFFFS", "D###D", "D###D", "GO#OG", "#GEG#")
            .aisle("SFFFS", "D###D", "D###D", "GO#OG", "#GEG#")
            .aisle("SFFFS", "D###D", "D###D", "GO#OG", "#GEG#")
            .aisle("SFFFS", "D###D", "D###D", "GO#OG", "#GEG#")
            .aisle("SFFFS", "D###D", "D###D", "GO#OG", "#GEG#")
            .aisle("SS@SS", "UDDDU", "UDDDU", "UUGUU", "#UUU#")
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("S", Predicates.blocks(GTBlocks.CASING_STEEL_SOLID.get()).setMinGlobalLimited(8)
                .or(Predicates.autoAbilities(definition.getRecipeTypes())))
            .where("U", Predicates.blocks(GTBlocks.CASING_STEEL_SOLID.get()))
            .where("G", Predicates.blocks(GTBlocks.CASING_TEMPERED_GLASS.get()))
            .where("D", Predicates.blocks(GTBlocks.CASING_TEMPERED_GLASS.get())
                .or(Predicates.blockTag(Tags.block("minecraft:doors")).setMaxGlobalLimited(4)))
            .where("O", Predicates.blocks(GTBlocks.CASING_TEMPERED_GLASS.get())
                .or(Predicates.any()))
            .where("F", Predicates.blockTag(Tags.block("minecraft:dirt"))
                .or(Predicates.blocks("minecraft:farmland"))
                .or(Predicates.fluids("minecraft:water")))
            .where("E", Predicates.blocks(GTBlocks.CASING_TEMPERED_GLASS.get())
                .or(Predicates.blocks(GTBlocks.CASING_STEEL_SOLID.get()))
                .or(Predicates.blocks("minecraft:redstone_lamp")))
            .where("#", Predicates.any())
            .build())
        .modelProperty(GTModelProperties.RECIPE_LOGIC_STATUS, RecipeLogic.Status.IDLE)
        .model(GTMachineModels.createWorkableCasingMachineModel(GTCEu.id("block/casings/solid/machine_casing_solid_steel"), GTCEu.id("block/multiblock/implosion_compressor"))
            ["andThen(java.util.function.Consumer)"](b => b.addDynamicRenderer(() => GTDynamicRenders.makeGrowingPlantRender(List.of(
                new Vector3f(-1, 1, -1),
                new Vector3f(1, 1, -1),
                new Vector3f(-1, 1, -3),
                new Vector3f(1, 1, -3),
                new Vector3f(-1, 1, -5),
                new Vector3f(1, 1, -5),
            )))))

    // Rock Cycle Simulator
    event.create("rock_cycle_simulator", "multiblock")
        .rotationState(RotationState.NON_Y_AXIS)
        .recipeTypes("rock_cycle_simulator")
        .recipeModifiers([GTRecipeModifiers.PARALLEL_HATCH, GTRecipeModifiers.OC_NON_PERFECT, GTRecipeModifiers.BATCH_MODE])
        .appearanceBlock(GCYMBlocks.CASING_HIGH_TEMPERATURE_SMELTING)
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("CCCCCCC", "CCCCCCC", "CCCCCCC", "CCCCCCC")
            .aisle("CCCCCCC", "TMMOIIT", "TMCCCIT", "CCCCCCC")
            .aisle("CCC@CCC", "CTTTTTC", "CTCCCTC", "CCCCCCC")
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("I", Predicates.blocks("minecraft:blue_ice"))
            .where("M", Predicates.blocks("minecraft:magma_block"))
            .where("O", Predicates.blocks(GTBlocks.CASING_TITANIUM_PIPE.get()))
            .where("T", Predicates.blocks(GTBlocks.CASING_TEMPERED_GLASS.get()))
            .where("C", Predicates.blocks(GCYMBlocks.CASING_HIGH_TEMPERATURE_SMELTING.get()).setMinGlobalLimited(20)
                .or(Predicates.autoAbilities(definition.getRecipeTypes()))
                .or(Predicates.abilities(PartAbility.PARALLEL_HATCH).setMaxGlobalLimited(1))
                .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1))
            )
            .where("#", Predicates.any())
            .build())
        .workableCasingModel("gtceu:block/casings/gcym/high_temperature_smelting_casing",
            "gtceu:block/machines/rock_crusher")

    // Atmospheric Accumulator
    event.create("atmospheric_accumulator", "multiblock")
        .rotationState(RotationState.NON_Y_AXIS)
        .recipeTypes(GTRecipeTypes.GAS_COLLECTOR_RECIPES)
        .recipeModifiers([GTRecipeModifiers.PARALLEL_HATCH, GTRecipeModifiers.OC_NON_PERFECT, GTRecipeModifiers.BATCH_MODE])
        .appearanceBlock(GCYMBlocks.CASING_CORROSION_PROOF)
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("CCCCC", "C   C", "CCCCC", "C   C", "CCCCC", "C   C", "CCCCC")
            .aisle("CCCCC", " GIG ", "CGGGC", " GIG ", "CCCCC", " GIG ", "CIIIC")
            .aisle("CCCCC", " IOI ", "CGOGC", " IOI ", "CCOCC", " IOI ", "CIOIC")
            .aisle("CCCCC", " GIG ", "CGGGC", " GIG ", "CCCCC", " GIG ", "CIIIC")
            .aisle("CC@CC", "C   C", "CCCCC", "C   C", "CCCCC", "C   C", "CCCCC")
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("I", Predicates.blocks(GTBlocks.CASING_ENGINE_INTAKE.get()))
            .where("G", Predicates.blocks(GTBlocks.CASING_GRATE.get()))
            .where("O", Predicates.blocks(GTBlocks.CASING_TITANIUM_PIPE.get()))
            .where("C", Predicates.blocks(GCYMBlocks.CASING_CORROSION_PROOF.get()).setMinGlobalLimited(70)
                .or(Predicates.autoAbilities(definition.getRecipeTypes()))
                .or(Predicates.abilities(PartAbility.PARALLEL_HATCH).setMaxGlobalLimited(1))
                .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1))
            )
            .where(" ", Predicates.air())
            .build())
        .workableCasingModel("gtceu:block/casings/gcym/corrosion_proof_casing",
            "gtceu:block/machines/gas_collector")

    // Matter Alterator
    event.create("matter_alterator", "multiblock")
        .rotationState(RotationState.NON_Y_AXIS)
        .recipeTypes("atomic_reconstruction")
        .recipeModifiers([GTRecipeModifiers.PARALLEL_HATCH, GTRecipeModifiers.OC_NON_PERFECT_SUBTICK, GTRecipeModifiers.BATCH_MODE])
        .appearanceBlock(GCYMBlocks.CASING_LASER_SAFE_ENGRAVING)
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("#CCC#######", "#CGC#######", "#CGC#######", "#CGC#######", "#CCC#######",)
            .aisle("CCCCC#F###F", "C   CCCCCCC", "C   CGGGGGC", "C   CCCCCCC", "CCCCC######",)
            .aisle("CCCCC######", "G CCCCCCCCC", "G F      PC", "G CCCGGGGGC", "CCCCC######",)
            .aisle("CCCCC#F###F", "C   CCCCCCC", "C   CGGGGGC", "C   CCCCCCC", "CCCCC######",)
            .aisle("#C@C#######", "#CGC#######", "#CGC#######", "#CGC#######", "#CCC#######",)
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("G", Predicates.blocks(GTBlocks.CASING_LAMINATED_GLASS.get()))
            .where("P", Predicates.blocks("gtceu:palis_block"))
            .where("F", Predicates.frames(GTMaterials.HastelloyC276))
            .where("C", Predicates.blocks(GCYMBlocks.CASING_LASER_SAFE_ENGRAVING.get()).setMinGlobalLimited(50)
                .or(Predicates.autoAbilities(definition.getRecipeTypes()))
                .or(Predicates.abilities(PartAbility.PARALLEL_HATCH).setMaxGlobalLimited(1))
                .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1))
            )
            .where(" ", Predicates.air())
            .where("#", Predicates.any())
            .build())
        .workableCasingModel("gtceu:block/casings/gcym/laser_safe_engraving_casing",
            "gtceu:block/machines/reconstructor")

    // Compression Imploder
    event.create("implosion_collider", "multiblock")
        .rotationState(RotationState.NON_Y_AXIS)
        .recipeTypes(GTRecipeTypes.IMPLOSION_RECIPES)
        .recipeModifiers([GTRecipeModifiers.PARALLEL_HATCH, GTRecipeModifiers.OC_NON_PERFECT, GTRecipeModifiers.BATCH_MODE])
        .appearanceBlock(GTBlocks.CASING_STEEL_SOLID)
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("#########", "####E####", "###EEE###", "####E####", "#########", "#########")
            .aisle("#########", "####E####", "###E2E###", "####E####", "#########", "#########")
            .aisle("###SES###", "###SES###", "##SE ES##", "###SES###", "###SES###", "#########")
            .aisle("##SSESS##", "##SOOOS##", "EEEO OEEE", "##SOOOS##", "##SSESS##", "#########")
            .aisle("##EEEEE##", "EEEOOOEEE", "E4     3E", "EEEOOOEEE", "##EEEEE##", "#########")
            .aisle("##SSESS##", "##SOOOS##", "EEEO OEEE", "##SOOOS##", "##SSESS##", "###SSS###")
            .aisle("###SES###", "##SSESS##", "##SE ES##", "##SS SS##", "###S S###", "###SMS###")
            .aisle("##F###F##", "##SSSSS##", "##SE1ES##", "###SSS###", "###SSS###", "###SSS###")
            .aisle("#########", "###SSS###", "###S@S###", "###SSS###", "#########", "#########")
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("S", Predicates.blocks(GTBlocks.CASING_STEEL_SOLID.get())
                .or(Predicates.autoAbilities(definition.getRecipeTypes()))
                .or(Predicates.abilities(PartAbility.PARALLEL_HATCH).setMaxGlobalLimited(1))
                .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1))
            )
            .where("O", Predicates.blocks("enderio:reinforced_obsidian_block"))
            .where("E", Predicates.blocks(GTBlocks.CASING_HSSE_STURDY.get()))
            .where("F", Predicates.frames(GTMaterials.BlackSteel))
            .where("M", Predicates.abilities(PartAbility.MUFFLER))
            .where("1", Predicates.blocks("minecraft:piston"))
            .where("2", Predicates.blocks("minecraft:piston"))
            .where("3", Predicates.blocks("minecraft:piston"))
            .where("4", Predicates.blocks("minecraft:piston"))
            .where(" ", Predicates.air())
            .where("#", Predicates.any())
            .build())
        .workableCasingModel("gtceu:block/casings/solid/machine_casing_solid_steel",
            "gtceu:block/multiblock/implosion_compressor")

    // Quintessence Infuser
    event.create("quintessence_infuser", "multiblock")
        .rotationState(RotationState.NON_Y_AXIS)
        .recipeTypes("quintessence_infuser")
        .recipeModifiers([GTRecipeModifiers.PARALLEL_HATCH, GTRecipeModifiers.OC_NON_PERFECT_SUBTICK, GTRecipeModifiers.BATCH_MODE])
        .appearanceBlock(() => Block.getBlock("kubejs:dark_soularium_casing"))
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("#CCC#", "CCCCC", "HGGGH", "HGGGH", "HGGGH", "CCCCC", "#CCC#")
            .aisle("CCCCC", "COOOC", "G#O#G", "G#O#G", "G#O#G", "C#O#C", "CCCCC")
            .aisle("CCCCC", "COPOC", "GOPOG", "GOPOG", "GOPOG", "COPOC", "CCCCC")
            .aisle("CCCCC", "COOOC", "G#O#G", "G#O#G", "G#O#G", "C#O#C", "CCCCC")
            .aisle("#C@C#", "CCCCC", "HGGGH", "HGGGH", "HGGGH", "CCCCC", "#CCC#")
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("H", Predicates.blocks("enderio:ensouled_chassis"))
            .where("O", Predicates.frames(GTMaterials.Tungsten))
            .where("G", Predicates.blocks(GTBlocks.FUSION_GLASS.get()))
            .where("P", Predicates.blocks(GTBlocks.CASING_TUNGSTENSTEEL_PIPE.get()))
            .where("C", Predicates.blocks("kubejs:dark_soularium_casing").setMinGlobalLimited(40)
                .or(Predicates.autoAbilities(definition.getRecipeTypes()))
                .or(Predicates.abilities(PartAbility.PARALLEL_HATCH).setMaxGlobalLimited(1))
                .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1))
            )
            .where("#", Predicates.any())
            .build())
        .workableCasingModel("kubejs:block/casing/soularium/casing",
            "gtceu:block/multiblock/implosion_compressor")

    // Discharger
    event.create("discharger", "multiblock")
        .rotationState(RotationState.NON_Y_AXIS)
        .recipeTypes("discharger")
        .appearanceBlock(() => Block.getBlock("monilabs:cryolobus_casing"))
        .generator(true)
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("#CCCCC#", "#######", "#######", "#######", "#######", "#######", "#CCCCC#")
            .aisle("CCCCCCC", "#NGGGN#", "#NGGGN#", "#NNNNN#", "#NGGGN#", "#NGGGN#", "CCCCCCC")
            .aisle("CCCCCCC", "#G   G#", "#G   G#", "#NE EN#", "#G   G#", "#G   G#", "CCCCCCC")
            .aisle("CCCCCCC", "#G   G#", "#G   G#", "#N   N#", "#G   G#", "#G   G#", "CCCCCCC")
            .aisle("CCCCCCC", "#G   G#", "#G   G#", "#NE EN#", "#G   G#", "#G   G#", "CCCCCCC")
            .aisle("CCCCCCC", "#NGGGN#", "#NGGGN#", "#NNNNN#", "#NGGGN#", "#NGGGN#", "CCCCCCC")
            .aisle("#CC@CC#", "#######", "#######", "#######", "#######", "#######", "#CCCCC#")


            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("C", Predicates.blocks("monilabs:cryolobus_casing").setMinGlobalLimited(80)
                .or(Predicates.abilities(PartAbility.IMPORT_ITEMS).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.EXPORT_ITEMS).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.IMPORT_FLUIDS).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1))
            )
            .where("c", Predicates.blocks("monilabs:cryolobus_casing"))
            .where("N", Predicates.blocks(GCYMBlocks.CASING_NONCONDUCTING.get()))
            .where("G", Predicates.blocks(GTBlocks.CASING_LAMINATED_GLASS.get()))
            .where("S", Predicates.blocks("minecraft:sculk"))
            .where("T", Predicates.blocks("minecraft:sculk_catalyst"))
            .where("L", Predicates.blocks("gtceu:black_lamp"))
            .where("E", Predicates.blocks(GCYMBlocks.ELECTROLYTIC_CELL.get()))
            .where(" ", Predicates.air())
            .where("#", Predicates.any())
            .build())
        .workableCasingModel("monilabs:block/casing/cryolobus",
            "gtceu:block/machines/electrolyzer")

    let getMicroverseRecipeModifiers = tier => [
        MoniRecipeModifiers.MICROVERSE_OC,
        (machine, recipe) => recipe.data.getLong("projector_tier") > tier ?
            ModifierFunction.NULL : ModifierFunction.IDENTITY
    ]

    // (Small) Naquadah Reactor
    event.create("naquadah_reactor", "multiblock")
        .rotationState(RotationState.NON_Y_AXIS)
        .recipeTypes("naquadah_reactor")
        .recipeModifiers([GTRecipeModifiers.PARALLEL_HATCH])    // Fix for generator "overclocking" as long as the actual hatch invalidates the structure
        .appearanceBlock(GCYMBlocks.CASING_REACTION_SAFE)
        .generator(true)
        .regressWhenWaiting(false)
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("CCC", "PGP", "PGP", "PGP", "PGP", "CCC")
            .aisle("CCC", "GNG", "GNG", "GNG", "GNG", "CCC")
            .aisle("C@C", "PGP", "PGP", "PGP", "PGP", "CCC")
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("G", Predicates.blocks(GTBlocks.FUSION_GLASS.get()))
            .where("C", Predicates.blocks(GCYMBlocks.CASING_REACTION_SAFE.get()).setMinGlobalLimited(12)
                .or(Predicates.autoAbilities(definition.getRecipeTypes())))
            .where("P", Predicates.blocks("ae2:spatial_pylon"))
            .where("N", Predicates.blocks("gtceu:trinium_coil_block"))
            .build())
        .workableCasingModel("gtceu:block/casings/gcym/reaction_safe_mixing_casing",
            "gtceu:block/multiblock/generator/large_steam_turbine")

    // Large Naquadah Reactor
    event.create("large_naquadah_reactor", "multiblock")
        .rotationState(RotationState.NON_Y_AXIS)
        .recipeTypes("large_naquadah_reactor")
        .recipeModifiers([GTRecipeModifiers.PARALLEL_HATCH])    // Fix for generator "overclocking" as long as the actual hatch invalidates the structure
        .regressWhenWaiting(false)
        .appearanceBlock(GCYMBlocks.CASING_ATOMIC)
        .generator(true)
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("##CCCCC##", "##CGGGC##", "##CCCCC##", "#########", "#########", "#########", "#########", "#########", "#########", "#########", "##CCCCC##")
            .aisle("#CCCCCCC#", "#CC   CC#", "#CCCCCCC#", "#A#####A#", "#A#####A#", "#A#####A#", "#A#####A#", "#A#####A#", "#A#####A#", "#A#####A#", "#CCCCCCC#")
            .aisle("CCCHHHCCC", "CCN   NCC", "CCCSSSCCC", "##DGGGD##", "##DGGGD##", "##DGGGD##", "##DGGGD##", "##DGGGD##", "##DGGGD##", "##DGGGD##", "CCCSSSCCC")
            .aisle("CCHCCCHCC", "G  OOO  G", "CCSOOOSCC", "##GOOOG##", "##GOOOG##", "##GOOOG##", "##GOOOG##", "##GOOOG##", "##GOOOG##", "##GOOOG##", "CCSHHHSCC")
            .aisle("CCHCCCHCC", "G  OKO  G", "CCSOKOSCC", "##GOKOG##", "##GOKOG##", "##GOKOG##", "##GOKOG##", "##GOKOG##", "##GOKOG##", "##GOKOG##", "CCSHHHSCC")
            .aisle("CCHCCCHCC", "G  OOO  G", "CCSOOOSCC", "##GOOOG##", "##GOOOG##", "##GOOOG##", "##GOOOG##", "##GOOOG##", "##GOOOG##", "##GOOOG##", "CCSHHHSCC")
            .aisle("CCCHHHCCC", "CCN   NCC", "CCCSSSCCC", "##DGGGD##", "##DGGGD##", "##DGGGD##", "##DGGGD##", "##DGGGD##", "##DGGGD##", "##DGGGD##", "CCCSSSCCC")
            .aisle("#CCCCCCC#", "#CC   CC#", "#CCCCCCC#", "#A#####A#", "#A#####A#", "#A#####A#", "#A#####A#", "#A#####A#", "#A#####A#", "#A#####A#", "#CCCCCCC#")
            .aisle("##CC@CC##", "##CGGGC##", "##CCCCC##", "#########", "#########", "#########", "#########", "#########", "#########", "#########", "##CCCCC##")
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("G", Predicates.blocks(GTBlocks.FUSION_GLASS.get()))
            .where("C", Predicates.blocks("gtceu:atomic_casing").setMinGlobalLimited(150)
                .or(Predicates.autoAbilities(definition.getRecipeTypes()))
                .or(Predicates.abilities(PartAbility.OUTPUT_LASER).setMaxGlobalLimited(2)))
            .where("H", Predicates.blocks("gtceu:heat_vent"))
            .where("K", Predicates.blocks("gtceu:fusion_coil"))
            .where("N", Predicates.blocks("gtceu:tungsten_frame"))
            .where("S", Predicates.blocks("ae2:spatial_pylon"))
            .where("O", Predicates.blocks("gtceu:tritanium_coil_block"))
            .where("D", Predicates.blocks("gtceu:high_temperature_smelting_casing"))
            .where("A", Predicates.blocks("gtceu:naquadah_alloy_frame"))
            .where(" ", Predicates.air())
            .where("#", Predicates.any())
            .build())
        .workableCasingModel("gtceu:block/casings/gcym/atomic_casing",
            "gtceu:block/multiblock/generator/large_steam_turbine")

    // Naquadah Fuel Refinery
    event.create("naquadah_refinery", "multiblock")
        .rotationState(RotationState.NON_Y_AXIS)
        .recipeTypes("naquadah_refinery")
        .appearanceBlock(() => Block.getBlock("gtceu:stress_proof_casing"))
        .recipeModifiers([GTRecipeModifiers.ELECTRIC_OVERCLOCK.apply(OverclockingLogic.NON_PERFECT_OVERCLOCK)])
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("##CCCCC##", "##CCCCC##", "#########", "#########", "#########", "#########", "#########", "#########", "#########", "#########", "#########")
            .aisle("#CCCCCCC#", "#CC#P#CC#", "####P####", "####P####", "###SSS###", "###VVV###", "###GGG###", "###VVV###", "###SSS###", "#########", "#########")
            .aisle("CCCCCCCCC", "CCF###FCC", "##F###F##", "##FSSSF##", "##S   S##", "##V   V##", "##G   G##", "##V   V##", "##S   S##", "###SSS###", "#########")
            .aisle("CCCCCCCCC", "C##III##C", "###SSS###", "##SPPPS##", "#S K K S#", "#V K K V#", "#G K K G#", "#V K K V#", "#S K K S#", "##SPPPS##", "###SSS###")
            .aisle("CCCCCCCCC", "CP#III#PC", "#P#SSS#P#", "#PSPPPSP#", "#S  E  S#", "#V  E  V#", "#G  E  G#", "#V  E  V#", "#S  E  S#", "##SPPPS##", "###SMS###")
            .aisle("CCCCCCCCC", "C##III##C", "###SSS###", "##SPPPS##", "#S K K S#", "#V K K V#", "#G K K G#", "#V K K V#", "#S K K S#", "##SPPPS##", "###SSS###")
            .aisle("CCCCCCCCC", "CCF###FCC", "##F###F##", "##FSSSF##", "##S   S##", "##V   V##", "##G   G##", "##V   V##", "##S   S##", "###SSS###", "#########")
            .aisle("#CCCCCCC#", "#CC#P#CC#", "####P####", "####P####", "###SSS###", "###VVV###", "###GGG###", "###VVV###", "###SSS###", "#########", "#########")
            .aisle("##CC@CC##", "##CCCCC##", "#########", "#########", "#########", "#########", "#########", "#########", "#########", "#########", "#########")
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("C", Predicates.blocks("gtceu:stress_proof_casing").setMinGlobalLimited(85)
                .or(Predicates.autoAbilities(definition.getRecipeTypes()))
                .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1)))
            .where("S", Predicates.blocks("gtceu:high_temperature_smelting_casing"))
            .where("I", Predicates.blocks("gtceu:extreme_engine_intake_casing"))
            .where("P", Predicates.blocks("gtceu:tungstensteel_pipe_casing"))
            .where("K", Predicates.blocks("gtceu:superconducting_coil"))
            .where("V", Predicates.blocks("gtceu:heat_vent"))
            .where("G", Predicates.blocks("gtceu:laminated_glass"))
            .where("E", Predicates.blocks("gtceu:ptfe_pipe_casing"))
            .where("F", Predicates.blocks("gtceu:tungsten_frame"))
            .where("M", Predicates.abilities(PartAbility.MUFFLER))
            .where(" ", Predicates.air())
            .where("#", Predicates.any())
            .build())
        .workableCasingModel("gtceu:block/casings/gcym/stress_proof_casing",
            "gtceu:block/multiblock/fusion_reactor")

    // Advanced Assembly line (Dimensional Superassembler)
    event.create("dimensional_superassembler", "multiblock")
        .rotationState(RotationState.ALL)
        .recipeTypes("assembly_line")
        .recipeModifiers([GTRecipeModifiers.PARALLEL_HATCH, GTRecipeModifiers.OC_NON_PERFECT_SUBTICK, GTRecipeModifiers.BATCH_MODE])
        .appearanceBlock(() => Block.getBlock("monilabs:dimensional_stabilization_netherite_casing"))
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("#########", "###CCC###", "##CCCCC##", "#CCCCCCC#", "#CCCCCCC#", "#CCCCCCC#", "##CCCCC##", "###CCC###", "#########")
            .aisle("##CCCCC##", "#CCCCCCC#", "CCCCCCCCC", "CCCCCCCCC", "CCCCCCCCC", "CCCCCCCCC", "CCCCCCCCC", "#CCCCCCC#", "##CCCCC##")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("#########", "#I#####I#", "##LLOLL##", "##GF FG##", "##GF FG##", "##RLLLR##", "##LM#ML##", "#I#####I#", "#########")
            .aisle("##CCCCC##", "#CCCCCCC#", "CCCCCCCCC", "CCCCCCCCC", "CCCCCCCCC", "CCCCCCCCC", "CCCCCCCCC", "#CCCCCCC#", "##CCCCC##")
            .aisle("#########", "###CCC###", "##CCCCC##", "#CCCCCCC#", "#CCC@CCC#", "#CCCCCCC#", "##CCCCC##", "###CCC###", "#########")
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("C", Predicates.blocks("monilabs:dimensional_stabilization_netherite_casing").setMinGlobalLimited(200)
                .or(Predicates.abilities(PartAbility.INPUT_ENERGY).setMaxGlobalLimited(2).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.IMPORT_ITEMS).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.EXPORT_ITEMS).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.IMPORT_FLUIDS).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.PARALLEL_HATCH).setMaxGlobalLimited(1))
                .or(Predicates.abilities(PartAbility.INPUT_LASER).setMaxGlobalLimited(1))
            )
            .where("G", Predicates.blocks("monilabs:prism_glass"))
            .where("L", Predicates.blocks(GCYMBlocks.CASING_LARGE_SCALE_ASSEMBLING.get()))
            .where("O", Predicates.blocks(GTBlocks.CASING_ASSEMBLY_LINE.get()))
            .where("F", Predicates.blocks("monilabs:bioalloy_fusion_casing"))
            .where("R", Predicates.blocks(GTBlocks.CASING_GRATE.get())
                .or(Predicates.abilities([PartAbility.DATA_ACCESS, PartAbility.OPTICAL_DATA_RECEPTION]).setExactLimit(1)))
            .where("M", Predicates.blocks("monilabs:eltz_casing"))
            .where("I", Predicates.blocks("monilabs:transcendental_matrix_frame"))
            .where(" ", Predicates.air())
            .where("#", Predicates.any())
            .build())
        .workableCasingModel("monilabs:block/casing/netherite",
            "gtceu:block/multiblock/assembly_line")

    // MABS
    const GCYMRecipeTypes = Java.loadClass("com.gregtechceu.gtceu.common.data.GCYMRecipeTypes") // Have to load it here because ALLOY_BLAST_RECIPES is not defined outside of the event
    event.create("mega_alloy_blast_smelter", "multiblock")
        .machine((holder) => new CoilWorkableElectricMultiblockMachine(holder))
        .rotationState(RotationState.ALL)
        .recipeTypes(GCYMRecipeTypes.ALLOY_BLAST_RECIPES)
        .recipeModifiers([GTRecipeModifiers.PARALLEL_HATCH, (machine, recipe) => GTRecipeModifiers.ebfOverclock(machine, recipe), GTRecipeModifiers.BATCH_MODE])
        .appearanceBlock(GCYMBlocks.CASING_HIGH_TEMPERATURE_SMELTING)
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("###IIIII###", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########")
            .aisle("#IIIIIIIII#", "###F###F###", "###F###F###", "###F###F###", "###FIIIF###", "###FIEIF###", "###FIIIF###", "###FFFFF###", "###########", "###########", "###########", "###########", "###########", "###########", "###IIHII###", "###########")
            .aisle("#IIIIIIIII#", "###HHHHH###", "###HVVVH###", "##FHHHHHF##", "##IICCCII##", "##IICECII##", "##IICCCII##", "##FFCCCFF##", "##F#CCC#F##", "##F#CCC#F##", "##F#VVV#F##", "##F#CCC#F##", "##F#CCC#F##", "##F#CCC#F##", "##IIIIIII##", "####IHI####")
            .aisle("IIIIIIIIIII", "#FHHHHHHHF#", "#FHHHPHHHF#", "#FHHPPPHHF#", "#FIC   CIF#", "#FIC   CIF#", "#FIC   CIF#", "#FFC   CFF#", "###C   C###", "###C   C###", "###V   V###", "###C   C###", "###C   C###", "###C   C###", "#IIIHHHIII#", "###IIHII###")
            .aisle("IIIIIIIIIII", "##HHHHHHH##", "##VHHHHHV##", "##HP   PH##", "#IC     CI#", "#IC     CI#", "#IC     CI#", "#FC  P  CF#", "##C     C##", "##C     C##", "##V     V##", "##C  P  C##", "##C     C##", "##C     C##", "#IIH   HII#", "##IIHHHII##")
            .aisle("IIIIIIIIIII", "##HHHGHHH##", "##VPHGHPV##", "##HP P PH##", "#IC  P  CI#", "#EE PPP EE#", "#IC  P  CI#", "#FC  P  CF#", "##C  P  C##", "##C PPP C##", "##V  P  V##", "##C  P  C##", "##C     C##", "##C     C##", "#HIH   HIH#", "##HHHMHHH##")
            .aisle("IIIIIIIIIII", "##HHHHHHH##", "##VHHHHHV##", "##HP   PH##", "#IC     CI#", "#IC     CI#", "#IC     CI#", "#FC  P  CF#", "##C     C##", "##C     C##", "##V     V##", "##C  P  C##", "##C     C##", "##C     C##", "#IIH   HII#", "##IIHHHII##")
            .aisle("IIIIIIIIIII", "#FHHHHHHHF#", "#FHHHPHHHF#", "#FHHPPPHHF#", "#FIC   CIF#", "#FIC   CIF#", "#FIC   CIF#", "#FFC   CFF#", "###C   C###", "###C   C###", "###V   V###", "###C   C###", "###C   C###", "###C   C###", "#IIIHHHIII#", "###IIHII###")
            .aisle("#IIIIIIIII#", "###HHHHH###", "###HH@HH###", "##FHHHHHF##", "##IICCCII##", "##IICECII##", "##IICCCII##", "##FFCCCFF##", "##F#CCC#F##", "##F#CCC#F##", "##F#VVV#F##", "##F#CCC#F##", "##F#CCC#F##", "##F#CCC#F##", "##IIIIIII##", "####IHI####")
            .aisle("#IIIIIIIII#", "###F###F###", "###F###F###", "###F###F###", "###FIIIF###", "###FIEIF###", "###FIIIF###", "###FFFFF###", "###########", "###########", "###########", "###########", "###########", "###########", "###IIHII###", "###########")
            .aisle("###IIIII###", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########")
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("H", Predicates.blocks(GCYMBlocks.CASING_HIGH_TEMPERATURE_SMELTING.get()).setMinGlobalLimited(110)
                .or(Predicates.autoAbilities(definition.getRecipeTypes()))
                .or(Predicates.abilities(PartAbility.PARALLEL_HATCH).setMaxGlobalLimited(1))
                .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1))
            )
            .where("I", Predicates.blocks(GTBlocks.CASING_INVAR_HEATPROOF.get()))
            .where("F", Predicates.frames(GTMaterials.get("cryococcus")))
            .where("V", Predicates.blocks(GCYMBlocks.HEAT_VENT.get()))
            .where("C", Predicates.heatingCoils())
            .where("M", Predicates.abilities(PartAbility.MUFFLER))
            .where("G", Predicates.blocks(GTBlocks.CASING_TUNGSTENSTEEL_GEARBOX.get()))          // Change to Naquadah Gearbox if ICE gets added
            .where("P", Predicates.blocks(GTBlocks.CASING_TUNGSTENSTEEL_PIPE.get()))      // Change to Naquadah Pipe Casing if ICE gets added
            .where("E", Predicates.blocks(GTBlocks.CASING_EXTREME_ENGINE_INTAKE.get()))   // Change to Insane Engine Intake if ICE gets added
            .where(" ", Predicates.air())
            .where("#", Predicates.any())
            .build())
        .workableCasingModel("gtceu:block/casings/gcym/high_temperature_smelting_casing",
            "gtceu:block/multiblock/gcym/blast_alloy_smelter")

    // Coremod multis

    // Omnic Synthesizer
    event.create("omnic_synthesizer", "multiblock")
        .machine((holder) => new OmnicSynthesizerMachine(holder))
        .recipeTypes(["omnic_synthesis"])
        .appearanceBlock(GCYMBlocks.CASING_ATOMIC)
        .recipeModifiers([MoniRecipeModifiers.omnicSynthRecipeModifier(), GTRecipeModifiers.OC_NON_PERFECT])
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("#CCCCC#", "#CCCCC#", "#CGGGC#", "#CGGGC#", "#CGGGC#", "#CGGGC#", "#CGGGC#", "#CCCCC#", "#CCCCC#")
            .aisle("CCCCCCC", "CHMMMHC", "CH###HC", "CH###HC", "CH###HC", "CH###HC", "CH###HC", "CHMMMHC", "CCCCCCC")
            .aisle("CCCCCCC", "CMXYXMC", "G#XYX#G", "G#XYX#G", "G#XYX#G", "G#XYX#G", "G#XYX#G", "CMXYXMC", "CCCCCCC")
            .aisle("CCCCCCC", "CMYYYMC", "G#YYY#G", "G#YYY#G", "G#YYY#G", "G#YYY#G", "G#YYY#G", "CMYYYMC", "CCCCCCC")
            .aisle("CCCCCCC", "CMXYXMC", "G#XYX#G", "G#XYX#G", "G#XYX#G", "G#XYX#G", "G#XYX#G", "CMXYXMC", "CCCCCCC")
            .aisle("CCCCCCC", "CHMMMHC", "CH###HC", "CH###HC", "CH###HC", "CH###HC", "CH###HC", "CHMMMHC", "CCCCCCC")
            .aisle("CCCCCCC", "CCCCCCC", "#CCCCC#", "#CCCCC#", "#CCCCC#", "#CCCCC#", "#CCCCC#", "CCCCCCC", "CCCCCCC")
            .aisle("CCCCCCC", "#CCCCC#", "#CCCCC#", "#CNNNC#", "###N###", "###N###", "###N###", "#CNNNC#", "CCCCCCC")
            .aisle("#CCCCC#", "##C@C##", "##CCC##", "#######", "#######", "#######", "#######", "#######", "#CCCCC#")
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("G", Predicates.blocks(GTBlocks.CLEANROOM_GLASS.get()))
            .where("H", Predicates.blocks(GTBlocks.HIGH_POWER_CASING.get()))
            .where("M", Predicates.blocks("monilabs:crystal_matrix_frame"))
            .where("N", Predicates.frames(GTMaterials.NaquadahAlloy))
            .where("X", Predicates.blocks(GTBlocks.COMPUTER_CASING.get()))
            .where("Y", Predicates.blocks(GTBlocks.ADVANCED_COMPUTER_CASING.get()))
            .where("C", Predicates.blocks(GCYMBlocks.CASING_ATOMIC.get()).setMinGlobalLimited(226)
                .or(Predicates.abilities(PartAbility.INPUT_ENERGY).setMaxGlobalLimited(2).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.IMPORT_ITEMS).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.EXPORT_ITEMS).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1)))
            .where("#", Predicates.any())
            .build())
        .additionalDisplay(MoniMachines.currentDiversityPointsInfo())
        .workableCasingModel("gtceu:block/casings/gcym/atomic_casing",
            "gtceu:block/multiblock/fusion_reactor")

    // Antimatter Manipulator
    event.create("antimatter_manipulator", "multiblock")
        .recipeTypes(["antimatter_manipulation"])
        .recipeModifiers([GTRecipeModifiers.OC_NON_PERFECT])
        .appearanceBlock(() => Block.getBlock("monilabs:dimensional_stabilization_netherite_casing"))
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("#MOM#", "##O##", "#####", "#####", "#####", "#####", "#####", "#####")
            .aisle("MMMMM", "#BOB#", "#BBB#", "##F##", "##F##", "##F##", "##F##", "#BBB#")
            .aisle("OMMMO", "OOSOO", "#BSB#", "#FSF#", "#FSF#", "#FSF#", "#FSF#", "#BCB#")
            .aisle("MMMMM", "#BOB#", "#B@B#", "##F##", "##F##", "##F##", "##F##", "#BBB#")
            .aisle(" MOM ", "##O##", "#####", "#####", "#####", "#####", "#####", "#####")
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("O", Predicates.blocks(GTBlocks.CASING_TUNGSTENSTEEL_PIPE.get()))
            .where("B", Predicates.blocks("monilabs:dimensional_stabilization_netherite_casing")
                .or(Predicates.abilities(PartAbility.INPUT_ENERGY).setMaxGlobalLimited(2).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.IMPORT_FLUIDS).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.EXPORT_FLUIDS).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.IMPORT_ITEMS).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.EXPORT_ITEMS).setPreviewCount(1))
                .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1)))
            .where("S", Predicates.blocks(GTBlocks.SUPERCONDUCTING_COIL.get()))
            .where("F", Predicates.blocks(GTBlocks.FUSION_GLASS.get()))
            .where("C", Predicates.blocks("kubejs:enderium_micro_miner_core"))
            .where("#", Predicates.any())
            .where("M", Predicates.blocks(GTBlocks.CASING_HSSE_STURDY.get()))
            .build())
        .workableCasingModel("monilabs:block/casing/netherite",
            "gtceu:block/multiblock/implosion_compressor")

    // Antimatter Collider
    event.create("antimatter_collider", "multiblock")
        .machine((holder) => new AntimatterGeneratorMachine(holder))
        .appearanceBlock(() => new Block.getBlock("monilabs:dimensional_stabilization_netherite_casing"))
        .recipeTypes(MoniRecipeTypes.ANTIMATTER_COLLIDER_RECIPES)
        .pattern(definition => FactoryBlockPattern.start()
            .aisle("#MMMMMMMMM#", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "#MMMMMMMMM#")
            .aisle("MMMMMMMMMMM", "####AAA####", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "####BBB####", "MMMMMMMMMMM")
            .aisle("MMMMAAAMMMM", "X##ACCCA##X", "X###AAA###X", "X#########X", "X#########X", "X#########X", "X#########X", "X#########X", "X#########X", "X#########X", "X#####CC##X", "X###CC####X", "X###BBB###X", "X##BCCCB##X", "MMMMBBBMMMM")
            .aisle("MMMAMMMAMMM", "##ACAAACA##", "###A###A###", "###########", "###########", "###########", "####OOO####", "####GOG####", "####OOO####", "########C##", "###########", "###########", "###C###B###", "##BCBBBCB##", "MMMBMMMBMMM")
            .aisle("MMAMMMMMAMM", "#ACAX#XACA#", "##A#X#X#A##", "####X#X####", "####X#X####", "####OOO####", "###CC  O###", "###G   G###", "###O   O###", "####OOO#C##", "####X#X####", "####X#X####", "##C#X#X#B##", "#BCBX#XBCB#", "MMBMMMMMBMM")
            .aisle("MMAMMMMMAMM", "#ACA###ACA#", "##A#####A##", "###########", "###########", "####OOO####", "##CO   O###", "###O C O###", "###O   OC##", "####OOO####", "###########", "###########", "##B#####B##", "#BCB###BCB#", "MMBMMMMMBMM")
            .aisle("MMAMMMMMAMM", "#ACAX#XACA#", "##A#X#X#C##", "####X#X####", "####X#X####", "##C#OOO####", "###O   O###", "###G   G###", "###O  CC###", "####OOO####", "####X#X####", "####X#X####", "##B#X#X#B##", "#BCBX#XBCB#", "MMBMMMMMBMM")
            .aisle("MMMAMMMAMMM", "##ACAAACA##", "###A###C###", "###########", "###########", "##C########", "####OOO####", "####G@G####", "####OOO####", "###########", "###########", "###########", "###B###B###", "##BCBBBCB##", "MMMBMMMBMMM")
            .aisle("MMMMAAAMMMM", "X##ACCCA##X", "X###AAA###X", "X####CC###X", "X##CC#####X", "X#########X", "X#########X", "X#########X", "X#########X", "X#########X", "X#########X", "X#########X", "X###BBB###X", "X##BCCCB##X", "MMMMBBBMMMM")
            .aisle("MMMMMMMMMMM", "####AAA####", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "###########", "####BBB####", "MMMMMMMMMMM")
            .aisle("#MMMMMMMMM#", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "##X#####X##", "#MMMMMMMMM#")
            .where("@", Predicates.controller(Predicates.blocks(definition.get())))
            .where("M", Predicates.blocks("gtceu:atomic_casing"))
            .where("A", Predicates.blocks("monilabs:dimensional_stabilization_netherite_casing")
                .or(Predicates.abilities(PartAbility.IMPORT_FLUIDS_1X).setExactLimit(1)))
            .where("B", Predicates.blocks("monilabs:dimensional_stabilization_netherite_casing")
                .or(Predicates.abilities(PartAbility.IMPORT_FLUIDS_1X).setExactLimit(1)))
            .where("O", Predicates.blocks("monilabs:dimensional_stabilization_netherite_casing")
                .or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1))
                .or(Predicates.abilities(PartAbility.OUTPUT_LASER, PartAbility.OUTPUT_ENERGY).setExactLimit(1))
            )
            .where("X", Predicates.blocks("gtceu:hsse_frame"))
            .where("G", Predicates.blocks(GTBlocks.FUSION_GLASS.get()))
            .where("C", Predicates.blocks("gtceu:superconducting_coil"))
            .where(" ", Predicates.air())
            .where("#", Predicates.any())
            .build())
        .workableCasingModel("monilabs:block/casing/netherite",
            "gtceu:block/machines/reconstructor")
})
