Skip to content

GroovyScript Multiblocks

iristhepianist edited this page Mar 21, 2025 · 22 revisions

The CRMC wiki is slightly outtdated for this one. So, i will be explaining it here.

First we begin with our actual multiblock code. This is located in classes. The file must be named MetaTileEntityYour-Name.

Here is one example.

package classes

import gregtech.api.metatileentity.MetaTileEntity
import gregtech.api.metatileentity.interfaces.IGregTechTileEntity
import gregtech.api.metatileentity.multiblock.IMultiblockPart
import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController
import gregtech.api.pattern.BlockPattern
import gregtech.api.pattern.FactoryBlockPattern
import gregtech.api.recipes.RecipeMap
import gregtech.api.recipes.builders.SimpleRecipeBuilder
import gregtech.client.renderer.ICubeRenderer

import gregtech.client.renderer.texture.Textures
import gregtech.common.blocks.BlockGlassCasing
import gregtech.common.blocks.BlockMachineCasing
import gregtech.common.blocks.MetaBlocks

import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly

public class MetaTileEntityGreenhouse extends RecipeMapMultiblockController {

    private static final RecipeMap<SimpleRecipeBuilder> GREENHOUSE_RECIPES = new RecipeMap<>("greenhouse", 3, 4, 1, 0, new SimpleRecipeBuilder(), false)


    public MetaTileEntityGreenhouse(ResourceLocation metaTileEntityId) {
        super(metaTileEntityId, GREENHOUSE_RECIPES)
    }

    @Override
    public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) {
        return new MetaTileEntityGreenhouse(metaTileEntityId)
    }

    @Override
    protected BlockPattern createStructurePattern() {
        return FactoryBlockPattern.start()
                .aisle(" CCC ", " CCC ", " CCC ", " CCC ")
                .aisle("CCCCC", "CDDDC", "C###C", "CGGGC")
                .aisle("CCCCC", "CDDDC", "C###C", "CGGGC")
                .aisle("CCCCC", "CDDDC", "C###C", "CGGGC")
                .aisle(" CCC ", " CSC ", " CCC ", " CCC ")
                .where('S' as char, selfPredicate())
                .where('G' as char, states(MetaBlocks.TRANSPARENT_CASING.getState(BlockGlassCasing.CasingType.TEMPERED_GLASS)))
                .where('D' as char, states(Blocks.DIRT.getDefaultState(), Blocks.GRASS.getDefaultState()))
                .where('C' as char, states(MetaBlocks.MACHINE_CASING.getState(BlockMachineCasing.MachineCasingType.ULV))
                        .setMinGlobalLimited(42)
                        .or(autoAbilities()))
                .where('#' as char, air())
                .build()
    }

    @Override
    @SideOnly(Side.CLIENT)
    public ICubeRenderer getBaseTexture(IMultiblockPart sourcePart) {
        return Textures.VOLTAGE_CASINGS[0]
    }
}

First we begin with the actual MetaTileEntity. We make the class using “public class” as you can see; Next, we make its recipe-map.

private static final RecipeMap<SimpleRecipeBuilder> 
GREENHOUSE_RECIPES = new RecipeMap<>("greenhouse", 3, 4, 1, 0, new SimpleRecipeBuilder(), false)

This is the place where this happens. The numbers are item inputs, item outputs, fluid inputs, fluid outputs. The recipemap’s name is given above; GREENHOUSE_RECIPES. Then the “greenhouse” is what will be used in Groovy for the actual recipes.

Then we have the actual multiblock’s definitions. This is in this.

 @Override
    protected BlockPattern createStructurePattern() {
        return FactoryBlockPattern.start()
                .aisle(" CCC ", " CCC ", " CCC ", " CCC ")
                .aisle("CCCCC", "CDDDC", "C###C", "CGGGC")
                .aisle("CCCCC", "CDDDC", "C###C", "CGGGC")
                .aisle("CCCCC", "CDDDC", "C###C", "CGGGC")
                .aisle(" CCC ", " CSC ", " CCC ", " CCC ")
                .where('S' as char, selfPredicate())
                .where('G' as char, states(MetaBlocks.TRANSPARENT_CASING.getState(BlockGlassCasing.CasingType.TEMPERED_GLASS)))
                .where('D' as char, states(Blocks.DIRT.getDefaultState(), Blocks.GRASS.getDefaultState()))
                .where('C' as char, states(MetaBlocks.MACHINE_CASING.getState(BlockMachineCasing.MachineCasingType.ULV))
                        .setMinGlobalLimited(42)
                        .or(autoAbilities()))
                .where('#' as char, air())
                .build()

There is actually no reason to do this weird MetaBlocks stuff. You can also do blockstate.

                .where('D' as char, states(blockstate("minecraft:cobblestone")))

Simple as that.

You also have to register the file itself in runConfig otherwise grs will not read it. Once you are done with this, you can move onto registering it.

import gregtech.common.metatileentities.MetaTileEntities
import classes.MetaTileEntity(Name)

if (!isReloading()) {
MetaTileEntities.registerMetaTileEntity(32001, new MetaTileEntity(Name)(new ResourceLocation("gtaurora", "your-name")))
}

This is in postInit, in here.

Anyway, once you’re done with that, we move onto the last step, that is lang. The simplest way to do this is in here, write

your-modid.machine.your-name.name=Your Name

Our modid is gtaurora. This will add a lang entry which allows you to write the in-game name of the block.

If you’ve done everything correctly, it should boot without issues. I highly suggest you use a test instance with only groovy, JEI, and GregTech to test it quickly.

And that’s all for now. If anyone needs to add something to this please pr or dm me on discord (iristhepianist)

Clone this wiki locally