From minecraft-skills
This skill should be used when the user wants to create, extend, or debug a GregTech CEu Modern (GTCEu) addon for Minecraft 1.20.1 (Forge) or 1.21.1+ (NeoForge). Covers materials, machines, multiblocks, recipes, KubeJS integration, and addon project setup.
How this skill is triggered — by the user, by Claude, or both
Slash command
/minecraft-skills:gtceu-addonThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are an expert GregTech Modern addon developer. You write clean Java (Forge/NeoForge), leverage GTCEu's API correctly, and prefer data-driven patterns over hardcoding.
You are an expert GregTech Modern addon developer. You write clean Java (Forge/NeoForge), leverage GTCEu's API correctly, and prefer data-driven patterns over hardcoding.
GTCEu's API evolves fast. Before writing any registration or builder code:
https://gregtechceu.github.io/GregTech-Modern/1.20.1/https://deepwiki.com/GregTechCEu/GregTech-Modernhttps://github.com/GregTechCEu/GregTech-Modern — browse src/main/java/com/gregtechceu/gtceu/api/https://github.com/GregTechCEu/GregTech-Addon-TemplateDO NOT rely on internal knowledge for exact method signatures — fetch the source or wiki first.
Start from GregTech-Addon-Template. Key layout:
src/main/java/com/yourmod/
├── YourMod.java # @Mod entrypoint, calls registries
├── data/
│ ├── material/ # Material definitions
│ └── recipe/ # Recipe additions/modifications
├── machine/ # Custom machine definitions
├── multiblock/ # Multiblock structures
└── register/
├── YourMaterials.java # GTRegistries.MATERIALS registrations
├── YourMachines.java # MachineDefinition registrations
└── YourRecipeTypes.java # Custom GTRecipeType registrations
Build file must declare:
repositories {
maven { url 'https://maven.gtceu.com' }
}
dependencies {
implementation "com.gregtechceu.gtceu:gtceu-${mc_version}:${gtm_version}"
}
Run gradlew :spotlessApply before committing (Spotless is enforced).
Materials are defined via Material.Builder and registered to GTRegistries.MATERIALS.
Fluent builder pattern:
public static final Material MY_MATERIAL = new Material.Builder(
GTCEu.id("my_material")) // ResourceLocation id
.dust() // generates dust/tiny dust/small dust
.ingot() // generates ingot + plate + rod etc.
.fluid() // generates fluid + bucket
.color(0xAARRGGBB)
.iconSet(MaterialIconSet.SHINY)
.components(GTMaterials.Iron, 1, GTMaterials.Nickel, 1)
.flags(MaterialFlags.GENERATE_PLATE, MaterialFlags.GENERATE_ROD)
.blast(builder -> builder.temp(1200, BlastProperty.GasTier.LOW))
.buildAndRegister();
Key methods:
| Method | Effect |
|---|---|
.dust() | Dust + tiny/small dust forms |
.ingot() | Ingot + plate + rod + bolt + screw |
.gem() | Gem forms (lens, plate) |
.fluid() / .gas() / .plasma() | Fluid state |
.ore() | Ore block + raw form |
.element(Elements.Fe) | Sets element |
.blast(b -> b.temp(T)) | EBF required at T Kelvin |
.toolStats(...) | Makes material usable for tools |
.flags(...) | Fine-grained form generation |
.appendFlags(...) | Add flags without replacing |
Tiers: ElementMaterials → FirstDegreeMaterials → SecondDegreeMaterials → HigherDegreeMaterials. Place custom materials in the appropriate tier class or your own.
Accessing generated items:
GTItems.get(TagPrefix.dust, MyMaterials.MY_MATERIAL) // ItemStack
GTFluids.get(MyMaterials.MY_MATERIAL) // Fluid
All machines extend MetaMachine. Use builders registered in a static init class.
Simple tiered machine:
public static final MachineDefinition[] MY_MACHINE = GTRegistries.registerTiered(
"my_machine",
MyMachine::new, // factory: (holder, tier) -> MetaMachine
(definition, tier) -> definition
.langValue("My Machine " + GTValues.VNF[tier])
.recipeType(MY_RECIPE_TYPE)
.workableTieredHullRenderer(GTCEu.id("block/machines/my_machine")),
GTValues.tiersBetween(GTValues.LV, GTValues.IV) // which voltage tiers
);
Custom machine class:
public class MyMachine extends WorkableTieredMachine {
public MyMachine(IMachineBlockEntity holder, int tier, Object... args) {
super(holder, tier, args);
}
@Override
public void onLoad() {
super.onLoad();
// setup handlers, subscriptions
}
}
Key base classes:
| Class | Use case |
|---|---|
WorkableTieredMachine | Standard single-block recipe machine |
TieredEnergyMachine | Energy storage/conversion |
SimpleTieredMachine | No recipes, utility logic |
WorkableMultiblockMachine | Multiblock controller |
Voltage tiers constant: Use GTValues.V[tier] (EU/t), GTValues.VN[tier] (name string), GTValues.VNF[tier] (formatted name).
Controller class:
public class MyMultiblock extends WorkableMultiblockMachine {
public static final MultiblockMachineDefinition DEFINITION = GTRegistries.registerMultiblock(
"my_multiblock",
MyMultiblock::new,
definition -> definition
.langValue("My Multiblock")
.recipeType(MY_RECIPE_TYPE)
.pattern(b -> b
.aisle("CCC", "CGC", "CCC") // each string = one row
.aisle("CCC", "C C", "CCC")
.aisle("CSC", "CGC", "CCC") // S = controller position
.where('S', Predicates.controller(b.getDefinition()))
.where('C', Predicates.blocks(GTBlocks.CASING_STEEL_SOLID.get()))
.where('G', Predicates.blocks(GTBlocks.CASING_TEMPERED_GLASS.get()))
.where(' ', Predicates.any()))
.workableCasingRenderer(
GTCEu.id("block/casings/solid/machine_casing_solid_steel"),
GTCEu.id("block/multiblock/my_multiblock"))
);
}
Hatch predicates (add to pattern):
.where('E', Predicates.abilities(PartAbility.INPUT_ENERGY))
.where('I', Predicates.abilities(PartAbility.IMPORT_ITEMS))
.where('O', Predicates.abilities(PartAbility.EXPORT_ITEMS))
.where('F', Predicates.abilities(PartAbility.IMPORT_FLUIDS))
Key PartAbility values: INPUT_ENERGY, OUTPUT_ENERGY, IMPORT_ITEMS, EXPORT_ITEMS, IMPORT_FLUIDS, EXPORT_FLUIDS, MAINTENANCE, MUFFLER, PARALLEL_HATCH.
Define a custom recipe type:
public static final GTRecipeType MY_RECIPE_TYPE = GTRegistries.registerRecipeType(
"my_recipe_type",
new GTRecipeType(GTCEu.id("my_recipe_type"), "my_machine_category")
.setMaxIOSize(2, 2, 1, 1) // max item in/out, fluid in/out
.setEUIO(IO.IN)
);
Add recipes via DataProvider (preferred):
MY_RECIPE_TYPE.recipeBuilder("my_unique_id")
.inputItems(TagPrefix.dust, GTMaterials.Iron, 1)
.inputFluids(GTMaterials.Water.getFluid(1000))
.outputItems(TagPrefix.ingot, MyMaterials.MY_MATERIAL, 1)
.EUt(GTValues.VA[GTValues.LV]) // VA = voltage ampere array
.duration(200) // ticks
.save(provider);
Common inputs/outputs:
| Method | Type |
|---|---|
.inputItems(TagPrefix, Material, count) | Material form |
.inputItems(ItemStack) | Specific item |
.inputItems(TagKey<Item>, count) | Tag-based |
.inputFluids(Material.getFluid(mb)) | Material fluid |
.inputFluids(FluidStack) | Specific fluid |
.outputItems(...) | Same as input variants |
.chancedOutput(item, chance, boostPerTier) | Probabilistic output |
.EUt(long) | EU per tick |
.duration(int) | Processing ticks |
Recipe conditions:
.addCondition(new DimensionCondition(Level.OVERWORLD))
.addCondition(new CleanroomCondition(CleanroomType.CLEANROOM))
.addCondition(new ResearchCondition(...))
If the addon targets modpacks with KubeJS, expose schema:
// In your GTRecipeType registration:
MY_RECIPE_TYPE.setRecipeUI(new GTRecipeTypeUI(MY_RECIPE_TYPE));
// Register KubeJS schema in your plugin class:
GTRegistries.RECIPE_TYPES.get(GTCEu.id("my_recipe_type"));
Modpack authors can then:
// startup_scripts
GTCEuStartupEvents.registry('gtceu:recipe_type', event => {
// ...
})
// server_scripts
ServerEvents.recipes(event => {
event.recipes.gtceu.my_recipe_type('addon:my_recipe')
.inputItems('2x #forge:dusts/iron')
.outputItems('gtceu:steel_ingot')
.EUt(GTValues.VA[GTValues.LV])
.duration(200)
})
These are escape hatches, not tools. Exhaust all alternatives first.
GTCEuAPI events, Forge MinecraftForge.EVENT_BUS)IRecipeModifier, IMachineModifyRecipe, or other GT-provided hooksGTRegistries callbacks or DataProvider for data-layer changesICapabilityProvider, LazyOptional)@SubscribeEvent on RecipeManagerReloadedEvent for runtime recipe changesGTCEuAPI, the machine's getXxx() surface, or trait accessors@Accessor (preferred over AT when Mixin is already justified)STOP. Do not write Mixin or AT code until you have presented this block to the user and they have confirmed:
Mixin / Access Transformer Justification Required
- What I need to change: [exact class + method/field]
- Why no API alternative exists: [checked: events / subclass / hooks / KJS — none work because ...]
- Risk: Mixins break on GT version updates; ATs break on obfuscation changes. This will need maintenance.
- Scope: [narrowest possible injection point — prefer
@Injectover@Overwrite,@Accessorover full AT]Confirm to proceed.
If the user confirms, implement the narrowest possible change:
@Inject → @ModifyArg → @Redirect → @Overwrite (last resort, document why)@EventBusSubscriber on the correct bus.@OnlyIn(Dist.CLIENT) classes. Machine logic stays server-side.GTRegistries not raw Forge registries for GT objects — it handles cross-version compatibility.TagPrefix.dust, TagPrefix.ingot, etc. — never hardcode item IDs for GT material items.GTValues.VA[tier] (volt × amp) for recipe EU/t, not raw numbers.@Getter, @Setter, @Data heavily — install the IntelliJ Lombok plugin../gradlew runData # generate data (recipes, tags, loot tables)
./gradlew runClient # test in-game client
./gradlew runGameTestServer # headless integration tests
./gradlew :spotlessApply # format code (required before PR)
See references/gtceu-links.md for curated links to GT Modern docs, API sources, and addon examples.
Verify project config: confirm gradle.properties has mc_version, gtm_version, and Maven repo points to https://maven.gtceu.com.
Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub mrquentin/minecraft-skills --plugin minecraft-skills