Modding Guide
Full public API reference for addon mod developers — weapons, equipment, trims, events, enchantments, biomes, and AI.
Overview
Craftics exposes a comprehensive Java API through the CrafticsAPI class that lets addon mods extend every major system. All registration methods are static and should be called during your mod's onInitialize().
The following registry types are available:
| Registry | Method | Purpose |
|---|---|---|
| Weapons | registerWeapon() |
Add items as Craftics weapons with damage types, abilities, and stats |
| Equipment Scanners | registerEquipmentScanner() |
Read stat bonuses from non-standard inventory slots (custom equipment slots) |
| Armor Sets | registerArmorSet() |
Define full-set bonuses for custom armor materials |
| Trim Patterns | registerTrimPattern() |
Add per-piece and set bonuses for custom trim patterns |
| Trim Materials | registerTrimMaterial() |
Add stat bonuses for custom trim materials |
| Events | registerEvent() |
Create between-level events (gambling, traders, ambushes, etc.) |
| Enchantments | registerEnchantment() |
Map enchantments to passive combat stat bonuses |
| Biomes | registerBiome() |
Add biomes programmatically (also supports JSON datapacks) |
| Enemy AI | registerAI() |
Define AI strategies for custom mob types |
Craftics also supports no-code modding via JSON datapacks for biomes and .nbt/.schem files for arena maps. See the Biomes and Arena Maps sections below.
Getting Started
To create a Craftics addon mod you need a standard Fabric mod that declares Craftics as a dependency. All API calls go in your mod initializer.
Step 1: Declare the Dependency
In your fabric.mod.json, add Craftics as a dependency so Fabric loads it before your mod:
{
"schemaVersion": 1,
"id": "mymod-craftics-compat",
"version": "1.0.0",
"name": "MyMod Craftics Compat",
"environment": "*",
"entrypoints": {
"main": ["com.example.mymod.CrafticsCompat"]
},
"depends": {
"fabricloader": ">=0.16.0",
"craftics": ">=1.0.0"
}
}
Step 2: Register from onInitialize()
All CrafticsAPI.registerXxx() calls must happen during mod initialization. The API is thread-safe and order-independent.
import com.crackedgames.craftics.api.CrafticsAPI;
import net.fabricmc.api.ModInitializer;
public class CrafticsCompat implements ModInitializer {
@Override
public void onInitialize() {
// Register weapons, scanners, armor sets, etc.
CrafticsAPI.registerWeapon(myItem, myWeaponEntry);
CrafticsAPI.registerEquipmentScanner("mymod", myScanner);
CrafticsAPI.registerArmorSet(myArmorSetEntry);
// ... more registrations
}
}
API Package Structure
All public API types live under these packages:
com.crackedgames.craftics.api—CrafticsAPI, interfaces (WeaponAbilityHandler,EquipmentScanner,EventHandler,EnchantmentEffectHandler), helpers (Abilities,EventTemplates,StatModifiers,EnchantmentContext)com.crackedgames.craftics.api.registry— Data records (WeaponEntry,ArmorSetEntry,TrimPatternEntry,TrimMaterialEntry,EventEntry)com.crackedgames.craftics.combat— Enums referenced by the API (DamageType,TrimEffects.Bonus,TrimEffects.SetBonus)
Weapon Registration
Register any Item as a usable weapon in Craftics combat with CrafticsAPI.registerWeapon(). Each weapon needs a WeaponEntry that defines its damage type, stats, and optional ability.
WeaponEntry Builder
Use the fluent builder API to construct a WeaponEntry:
WeaponEntry entry = WeaponEntry.builder(myItem)
.damageType(DamageType.SLASHING) // damage category
.attackPower(8) // flat attack value
.apCost(1) // action points per attack
.range(1) // attack range in tiles
.ranged(false) // true for projectile weapons
.breakChance(0.0) // probability of breaking per use (0.0 - 1.0)
.ability(myAbilityHandler) // optional on-hit ability
.build();
CrafticsAPI.registerWeapon(myItem, entry);
| Builder Method | Type | Default | Description |
|---|---|---|---|
damageType(DamageType) | enum | PHYSICAL | Weapon's damage category |
attackPower(int) | int | 1 | Base attack power |
attackPower(IntSupplier) | supplier | — | Dynamic attack power (called each attack) |
apCost(int) | int | 1 | Action point cost per attack |
range(int) | int | 1 | Attack range in tiles |
ranged(boolean) | bool | false | Whether this is a ranged weapon |
breakChance(double) | double | 0.0 | Chance to break on use (0.0–1.0) |
ability(WeaponAbilityHandler) | handler | null | On-hit ability (see below) |
DamageType Enum
Every weapon belongs to one of eight damage types. Armor sets, trims, and player affinity points can grant bonuses to specific types.
| Value | Display Name | Typical Weapons |
|---|---|---|
SLASHING | Slashing | Swords |
CLEAVING | Cleaving | Axes |
BLUNT | Blunt | Maces, shovels |
WATER | Water | Tridents, corals |
SPECIAL | Special | Blaze rods, end rods, breeze rods |
PET | Pet | Pet attacks |
RANGED | Ranged | Bows, crossbows |
PHYSICAL | Physical | Default / untyped |
Abilities (Built-in Ability Factories)
The Abilities class provides static factory methods that return WeaponAbilityHandler instances. These are composable — chain them with .and() to combine multiple effects on one weapon.
// Compose two abilities: bleed + sweep
WeaponAbilityHandler handler = Abilities.bleed()
.and(Abilities.sweepAdjacent(0.10, 0.05));
| Factory Method | Description |
|---|---|
bleed() | Applies bleed stacks equal to the weapon's Sharpness enchant level |
sweepAdjacent(baseChance, bonusPerPoint) | Chance to hit one adjacent enemy for half damage (scales with SLASHING affinity) |
armorIgnore(baseChance, bonusPerPoint) | Chance to deal bonus damage equal to target's defense (scales with CLEAVING affinity) |
stun(baseChance, bonusPerPoint) | Chance to stun target for one turn (scales with BLUNT affinity) |
knockbackDirection(distance) | Pushes target away from player by up to N tiles |
aoe(radius, damageMultiplier) | Hits all enemies within radius (Manhattan distance) of target |
applyEffect(type, turns, amplifier) | Applies a status effect (POISON, BURNING, SOAKED, SLOWNESS, CONFUSION) |
pierce() | Hits the first enemy behind the target in the attack direction |
fireDamage(bonusDmg) | Sets target on fire and deals flat bonus fire damage |
Custom Ability Handler
WeaponAbilityHandler is a @FunctionalInterface. Implement it for fully custom on-hit logic:
@FunctionalInterface
public interface WeaponAbilityHandler {
WeaponAbility.AttackResult apply(
ServerPlayerEntity player,
CombatEntity target,
GridArena arena,
int baseDamage,
PlayerProgression.PlayerStats stats,
int luckPoints
);
// Compose with another handler:
default WeaponAbilityHandler and(WeaponAbilityHandler next);
}
Return a WeaponAbility.AttackResult(totalDamage, messages, extraTargets) where messages is a list of combat log strings and extraTargets is a list of additional entities hit by the ability.
Example: Custom Weapon
import com.crackedgames.craftics.api.CrafticsAPI;
import com.crackedgames.craftics.api.Abilities;
import com.crackedgames.craftics.api.registry.WeaponEntry;
import com.crackedgames.craftics.combat.DamageType;
// Heavy Claymore: cleaving type, armor ignore + knockback
Item myItem = net.minecraft.registry.Registries.ITEM
.get(net.minecraft.util.Identifier.of("mymod", "heavy_claymore"));
CrafticsAPI.registerWeapon(myItem, WeaponEntry.builder(myItem)
.damageType(DamageType.CLEAVING)
.attackPower(7)
.apCost(2)
.range(1)
.ability(Abilities.armorIgnore(0.15, 0.03)
.and(Abilities.knockbackDirection(2)))
.build());
Equipment Scanners
Equipment scanners let addon mods contribute stat bonuses from non-standard inventory slots. This is how addon mods with custom equipment slots integrate with Craftics combat stats. Register one with CrafticsAPI.registerEquipmentScanner().
EquipmentScanner Interface
@FunctionalInterface
public interface EquipmentScanner {
StatModifiers scan(ServerPlayerEntity player);
}
The scanner is called during combat stat calculation. It receives the player and returns a StatModifiers object containing all bonuses from that mod's equipment.
StatModifiers Class
Accumulates bonuses using the TrimEffects.Bonus enum as keys:
StatModifiers mods = new StatModifiers();
mods.add(TrimEffects.Bonus.DEFENSE, 2); // +2 defense
mods.add(TrimEffects.Bonus.SPEED, 1); // +1 speed
mods.add(TrimEffects.Bonus.MAX_HP, 4); // +4 max HP
mods.addSetBonus(TrimEffects.SetBonus.FERAL, "Feral Ring Set"); // optional set bonus
Available Bonus Types
RANGED_POWER, MELEE_POWER, SPEED, AP, DEFENSE, LUCK,
ATTACK_RANGE, MAX_HP, ARMOR_PEN, REGEN, ALLY_DAMAGE, STEALTH_RANGE,
SWORD_POWER, CLEAVING_POWER, BLUNT_POWER, WATER_POWER, SPECIAL_POWER
Example: Equipment Scanner
import com.crackedgames.craftics.api.CrafticsAPI;
import com.crackedgames.craftics.api.EquipmentScanner;
import com.crackedgames.craftics.api.StatModifiers;
import com.crackedgames.craftics.combat.TrimEffects;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.Registries;
import net.minecraft.util.Identifier;
CrafticsAPI.registerEquipmentScanner("mymod", (player) -> {
StatModifiers mods = new StatModifiers();
// Read items from your addon's custom equipment slots
// and map them to Craftics stat bonuses
ItemStack belt = getCustomSlot(player, "belt");
if (!belt.isEmpty()) {
if (belt.isOf(Registries.ITEM.get(Identifier.of("mymod", "swift_belt")))) {
mods.add(TrimEffects.Bonus.SPEED, 1);
} else if (belt.isOf(Registries.ITEM.get(Identifier.of("mymod", "iron_belt")))) {
mods.add(TrimEffects.Bonus.DEFENSE, 2);
}
}
ItemStack amulet = getCustomSlot(player, "amulet");
if (!amulet.isEmpty() && amulet.isOf(Registries.ITEM.get(Identifier.of("mymod", "lucky_charm")))) {
mods.add(TrimEffects.Bonus.LUCK, 3);
}
return mods;
});
Combat Effects
Overview
Combat effects are custom lifecycle callbacks that fire during combat. Unlike flat stat bonuses, they can react to events — taking damage, killing enemies, moving — and modify combat behavior dynamically. They are registered by calling StatModifiers.addCombatEffect() inside an EquipmentScanner.
CombatEffectHandler Interface
CombatEffectHandler is an interface with 24 default no-op methods. Override only the callbacks your effect needs. The 15 currently wired callbacks are:
| Callback | Returns | When it fires |
|---|---|---|
onCombatStart(ctx) |
void | Combat begins |
onTurnStart(ctx) |
void | Player's turn starts |
onTurnEnd(ctx) |
void | Player's turn ends |
onCombatEnd(ctx) |
void | Combat finishes |
onDealKillingBlow(ctx, killed) |
void | Player kills an enemy |
onTakeDamage(ctx, attacker, damage) |
CombatResult | Player takes damage |
onLethalDamage(ctx, attacker, damage) |
CombatResult | Damage would kill player |
onDodge(ctx, attacker) |
void | Player dodges an attack |
onMove(ctx, from, to, distance) |
void | Player moves on grid |
onEmeraldGain(ctx, amount) |
CombatResult | Emeralds awarded |
onLootRoll(ctx, loot) |
void | Loot generated (mutable list) |
onEnemySpawn(ctx, enemy) |
void | Enemy enters arena |
onEffectExpired(ctx, effect) |
void | Status effect wears off |
onCrit(ctx, target, damage) (planned) |
void | Critical hit (future) |
onMiss(ctx, target) (planned) |
void | Attack misses (future) |
CombatResult
Callbacks that return CombatResult can intercept and modify the value in question. Three factory methods are available:
CombatResult.unchanged(damage) // pass through unchanged
CombatResult.modify(newValue, "message") // change the value, display a message
CombatResult.cancel("message") // cancel the action entirely (e.g., prevent death)
CombatEffectContext
All callbacks receive a CombatEffectContext as their first argument. It exposes the following getters:
ctx.getPlayer() // ServerPlayerEntity — the combatant
ctx.getArena() // CombatArena — the active arena
ctx.getPlayerEffects() // List of active status effects on the player
ctx.getTrimScan() // TrimScan — the player's trim data
ctx.getAllEnemies() // List<CombatEntity> — all current enemies
ctx.getAllAllies() // List<CombatEntity> — all current allies
Statefulness
Handlers are per-combat instances — a fresh instance is created at combat start each time the scanner runs. This means you can safely use instance fields to track state within a single fight:
mods.addCombatEffect("One-Shot Shield", new CombatEffectHandler() {
private boolean used = false; // resets each combat
@Override
public CombatResult onLethalDamage(CombatEffectContext ctx, CombatEntity attacker, int damage) {
if (!used) {
used = true;
// ...
}
return CombatResult.unchanged(damage);
}
});
Registration
Call mods.addCombatEffect(name, handler) inside your EquipmentScanner. Multiple effects per item are allowed — each registered independently with its own name and instance.
CrafticsAPI.registerEquipmentScanner("mymod", (player) -> {
StatModifiers mods = new StatModifiers();
ItemStack ring = getCustomSlot(player, "ring");
if (ring.isOf(MY_THORNS_RING)) {
mods.addCombatEffect("Thorns Ring", new ThornsCombatEffect());
}
return mods;
});
Examples
Thorns Effect (reflect damage)
mods.addCombatEffect("Thorns Ring", new CombatEffectHandler() {
@Override
public CombatResult onTakeDamage(CombatEffectContext ctx, CombatEntity attacker, int damage) {
if (attacker != null) attacker.takeDamage(Math.max(1, damage / 4));
return CombatResult.modify(damage, "§6Thorns Ring reflects damage!");
}
});
Death Prevention (once per combat)
mods.addCombatEffect("Lucky Charm", new CombatEffectHandler() {
private boolean used = false;
@Override
public CombatResult onLethalDamage(CombatEffectContext ctx, CombatEntity attacker, int damage) {
if (!used) {
used = true;
ctx.getPlayer().heal(10);
return CombatResult.cancel("§d❦ Lucky Charm saves you from death!");
}
return CombatResult.unchanged(damage);
}
});
Bonus Emeralds
mods.addCombatEffect("Fortune Amulet", new CombatEffectHandler() {
@Override
public CombatResult onEmeraldGain(CombatEffectContext ctx, int amount) {
return CombatResult.modify(amount + 2, "§6Fortune Amulet: +2 bonus emeralds!");
}
});
Armor Sets
Register custom armor set bonuses that activate when a player wears a full set of matching armor. The armor set ID must match what the game detects for your armor material.
ArmorSetEntry Builder
ArmorSetEntry entry = ArmorSetEntry.builder("mymod:mythril")
.damageBonus(DamageType.SLASHING, 2) // +2 slashing damage
.damageBonus(DamageType.CLEAVING, 1) // +1 cleaving damage
.speedBonus(1) // +1 speed
.apBonus(0) // +0 action points
.defenseBonus(3) // +3 defense
.attackBonus(1) // +1 attack
.apCostReduction(0) // -0 AP cost
.description("Mythril Armor: light and sharp")
.build();
CrafticsAPI.registerArmorSet(entry);
| Builder Method | Type | Default | Description |
|---|---|---|---|
damageBonus(DamageType, int) | per-type | 0 | Bonus damage for a specific damage type |
allDamageBonus(int) | all types | — | Sets the same bonus for every damage type |
speedBonus(int) | int | 0 | Movement speed bonus |
apBonus(int) | int | 0 | Extra action points per turn |
defenseBonus(int) | int | 0 | Defense stat bonus |
attackBonus(int) | int | 0 | Base attack bonus |
apCostReduction(int) | int | 0 | Reduction in AP cost per attack |
description(String) | string | "" | Tooltip description shown in combat HUD |
Trim Effects
Craftics gives armor trims gameplay effects. Each trim pattern grants a per-piece stat bonus and a full-set bonus (when all 4 armor pieces share the same pattern). Each trim material grants its own per-piece stat bonus. Register custom patterns and materials for modded trims.
Trim Pattern Registration
CrafticsAPI.registerTrimPattern(new TrimPatternEntry(
"mymod:dragon", // pattern ID
TrimEffects.Bonus.MELEE_POWER, // per-piece stat
"+1 Melee Power per piece", // per-piece description
TrimEffects.SetBonus.FERAL, // full-set bonus
"Dragon's Fury", // set bonus display name
"First attack each turn costs 0 AP" // set bonus description
));
TrimPatternEntry Fields
| Field | Type | Description |
|---|---|---|
patternId | String | Registry ID of the trim pattern (e.g., "mymod:dragon") |
perPieceStat | TrimEffects.Bonus | Stat bonus granted per armor piece with this pattern |
perPieceDescription | String | Human-readable description of the per-piece bonus |
setBonus | TrimEffects.SetBonus | Bonus activated when all 4 pieces use this pattern |
setBonusName | String | Display name for the set bonus |
setBonusDescription | String | Human-readable description of the set bonus |
Trim Material Registration
CrafticsAPI.registerTrimMaterial(new TrimMaterialEntry(
"mymod:orichalcum", // material ID
TrimEffects.Bonus.ARMOR_PEN, // stat bonus type
2, // value per armor piece
"+2 Armor Penetration per piece"
));
TrimMaterialEntry Fields
| Field | Type | Description |
|---|---|---|
materialId | String | Registry ID of the trim material |
stat | TrimEffects.Bonus | Stat bonus type |
valuePerPiece | int | Bonus value per armor piece with this material |
description | String | Human-readable description |
Bonus Enum Values
| TrimEffects.Bonus | Effect |
|---|---|
RANGED_POWER | Bonus ranged attack damage |
MELEE_POWER | Bonus melee attack damage (all melee types) |
SPEED | Movement speed (tiles per turn) |
AP | Extra action points per turn |
DEFENSE | Damage reduction |
LUCK | Affects loot rolls and ability proc chances |
ATTACK_RANGE | Extra attack range in tiles |
MAX_HP | Bonus maximum hit points |
ARMOR_PEN | Ignore portion of enemy defense |
REGEN | HP regeneration per turn |
ALLY_DAMAGE | Bonus damage for pet/ally attacks |
STEALTH_RANGE | Reduced enemy detection range |
SWORD_POWER | Bonus SLASHING damage specifically |
CLEAVING_POWER | Bonus CLEAVING damage specifically |
BLUNT_POWER | Bonus BLUNT damage specifically |
WATER_POWER | Bonus WATER damage specifically |
SPECIAL_POWER | Bonus SPECIAL damage specifically |
SetBonus Enum Values
| TrimEffects.SetBonus | Name | Effect |
|---|---|---|
NONE | — | No set bonus |
OVERWATCH | Sentry | Counter-attack at range |
SANDSTORM | Dune | Enemy speed reduction aura |
TIDAL | Coast | Water heals the player |
FERAL | Wild | First attack each turn is free |
FORTRESS | Ward | Halve damage when stationary |
ALL_SEEING | Eye | Ranged critical hit bonus |
ETHEREAL | Vex | Dodge chance |
OCEAN_BLESSING | Tide | Emergency heal at low HP |
BRUTE_FORCE | Snout | Attacks deal splash damage |
INFERNAL | Rib | Fire attacks deal bonus damage |
FORTUNE_PEAK | Spire | Double emerald rewards |
PATHFINDER | Wayfinder | Ignore obstacles when moving |
TERRAFORMER | Shaper | Movement deals AoE damage |
PHANTOM | Silence | Start combat invisible |
RALLY | Raiser | Buff allies at start of turn |
SYMBIOTE | Host | Heal on kill |
CURRENT | Flow | Kills refund AP |
THUNDERSTRIKE | Bolt | Critical hits stun the target |
Events
Between-level events fire after completing a combat level. Register custom events with CrafticsAPI.registerEvent(). Events are selected randomly based on probability after each level.
EventEntry Fields
CrafticsAPI.registerEvent(new EventEntry(
"mymod:treasure_chest", // unique event ID
"Treasure Chest", // display name
0.15f, // probability (0.0 - 1.0)
2, // minimum biome ordinal (0-indexed) to appear
true, // isChoiceEvent: player picks from options
myEventHandler // EventHandler implementation
));
| Field | Type | Description |
|---|---|---|
id | String | Unique event identifier |
displayName | String | Name shown in the event popup |
probability | float | Chance to trigger after each level (0.0–1.0) |
minBiomeOrdinal | int | Earliest biome where this event can appear (0 = first biome) |
isChoiceEvent | boolean | Whether the player gets to choose between options |
handler | EventHandler | Logic executed when the event fires |
EventHandler Interface
@FunctionalInterface
public interface EventHandler {
void execute(List<ServerPlayerEntity> participants,
ServerWorld world,
EventManager eventManager);
}
The EventManager provides helper methods for showing UI popups, giving items, applying effects, and managing event state.
EventTemplates
The EventTemplates class will provide pre-built patterns for common event types. Planned templates include:
EventTemplates.gamble()— Risk-reward gambling eventEventTemplates.giveReward()— Simple item/stat rewardEventTemplates.ambush()— Surprise enemy encounterEventTemplates.spawnTrader()— Shop/trade event
EventTemplates are currently under development. For now, implement EventHandler directly.
Example: Custom Event
CrafticsAPI.registerEvent(new EventEntry(
"mymod:healing_spring",
"Healing Spring",
0.10f,
1, // available from biome index 1 onwards
false, // not a choice event - just happens
(participants, world, eventManager) -> {
for (ServerPlayerEntity player : participants) {
// Heal each player by 4 HP
player.heal(4.0f);
}
}
));
Enchantments
Register enchantments that grant passive stat bonuses during Craftics combat. The handler receives an EnchantmentContext with the enchantment level, the player, and a StatModifiers accumulator.
EnchantmentEffectHandler and EnchantmentContext
@FunctionalInterface
public interface EnchantmentEffectHandler {
void apply(EnchantmentContext ctx);
}
public class EnchantmentContext {
public int getLevel(); // enchantment level (1, 2, 3...)
public ServerPlayerEntity getPlayer(); // the player
public StatModifiers getModifiers(); // accumulator to add bonuses to
}
Example: Custom Enchantment
// Holy Blessing: +1 defense and +1 regen per enchantment level
CrafticsAPI.registerEnchantment("mymod:holy_blessing", (ctx) -> {
ctx.getModifiers().add(TrimEffects.Bonus.DEFENSE, ctx.getLevel());
ctx.getModifiers().add(TrimEffects.Bonus.REGEN, ctx.getLevel());
});
// Swiftness: +1 speed at any level
CrafticsAPI.registerEnchantment("mymod:swiftness", (ctx) -> {
ctx.getModifiers().add(TrimEffects.Bonus.SPEED, 1);
});
Biomes
Biomes can be added via JSON datapacks (no code required) or programmatically through CrafticsAPI.registerBiome().
JSON Datapacks (No Code)
Place biome JSON files at data/<namespace>/craftics/biomes/my_biome.json. The full JSON schema:
{
"id": "my_biome",
"name": "My Custom Biome",
"order": 20,
"levels": 5,
"grid": {
"base_width": 10,
"base_height": 10,
"width_growth": 1,
"height_growth": 1
},
"floor_blocks": ["minecraft:stone_bricks", "minecraft:mossy_stone_bricks"],
"obstacle_blocks": ["minecraft:cobblestone_wall"],
"obstacle_density": 0.1,
"obstacle_density_growth": 0.02,
"environment": "cave",
"night": true,
"enemies": {
"passive": [
{"type": "minecraft:bat", "weight": 3, "hp": 2, "attack": 0, "defense": 0, "range": 1}
],
"hostile": [
{"type": "minecraft:skeleton", "weight": 8, "hp": 10, "attack": 3, "defense": 0, "range": 3},
{"type": "minecraft:spider", "weight": 6, "hp": 8, "attack": 3, "defense": 0, "range": 1}
],
"boss": {"type": "minecraft:warden", "hp": 50, "attack": 8, "defense": 4, "range": 2}
},
"loot": [
{"item": "minecraft:diamond", "weight": 5},
{"item": "minecraft:iron_ingot", "weight": 15}
]
}
Field Reference
| Field | Type | Description |
|---|---|---|
id | string | Required. Unique identifier. |
name | string | Display name in HUD and level select. |
order | int | Sort position. Lower = earlier in progression. |
levels | int | Number of levels (typically 5). Last level = boss. |
grid.base_width | int | Starting grid width. |
grid.base_height | int | Starting grid height. |
grid.width_growth | int | Width increase per level. |
grid.height_growth | int | Height increase per level. |
floor_blocks | string[] | Floor tile blocks (checkerboard pattern). |
obstacle_blocks | string[] | Obstacle blocks placed on the grid. |
obstacle_density | float | Base obstacle probability (0.0–1.0). |
obstacle_density_growth | float | Density increase per level. |
environment | string | Visual style: plains, forest, desert, jungle, river, mountain, snowy, cave, nether_wastes, end, deep_dark |
night | bool | Night mode (prevents undead burning). |
enemies.passive | array | Passive mob pool (weighted random). |
enemies.hostile | array | Hostile mob pool (weighted random). |
enemies.boss | object | Boss for the final level. |
loot | array | Weighted loot table (1–3 items rolled per level). |
Programmatic Registration
CrafticsAPI.registerBiome(myBiomeTemplate);
int totalLevels = CrafticsAPI.getTotalLevels();
Use the same id as a built-in biome to override its settings. Use /reload to hot-reload biome JSONs without restarting.
Enemy AI
Register custom AI strategies for mob types that Craftics does not support natively. The AI controls what action an enemy takes each turn.
AI Registration
CrafticsAPI.registerAI("mymod:custom_zombie", (self, arena, playerPos) -> {
// Your AI logic: decide what to do this turn
return new EnemyAction.Attack(self.getAttackPower());
});
Available Action Types
27 action types are available for custom AI. Return any of these from your AI strategy:
Move, Attack, MoveAndAttack, Flee, Teleport, TeleportAndAttack, Pounce, Explode, RangedAttack, Swoop, StartFuse, Detonate, Idle, AttackMob, MoveAndAttackMob, AttackWithKnockback, MoveAndAttackWithKnockback, SummonMinions, AreaAttack, CreateTerrain, LineAttack, ModifySelf, ForcedMovement, BossAbility, CeilingAscend, CeilingDrop, CompositeAction
Supported Mob Types (Built-in)
The following mobs already have registered AI and can be used in custom biomes without additional code:
- Passive:
minecraft:cow,minecraft:pig,minecraft:sheep,minecraft:chicken,minecraft:horse,minecraft:donkey,minecraft:panda,minecraft:parrot,minecraft:rabbit,minecraft:bat,minecraft:cod,minecraft:salmon,minecraft:axolotl,minecraft:cat,minecraft:ocelot,minecraft:fox,minecraft:bee,minecraft:wolf,minecraft:goat,minecraft:polar_bear,minecraft:llama - Hostile:
minecraft:zombie,minecraft:zombie_villager,minecraft:husk,minecraft:drowned,minecraft:zombified_piglin,minecraft:skeleton,minecraft:stray,minecraft:bogged,minecraft:spider,minecraft:cave_spider,minecraft:creeper,minecraft:vindicator,minecraft:evoker,minecraft:pillager,minecraft:ravager,minecraft:witch,minecraft:enderman,minecraft:endermite,minecraft:phantom,minecraft:silverfish,minecraft:slime,minecraft:hoglin,minecraft:piglin,minecraft:blaze,minecraft:ghast,minecraft:shulker,minecraft:breeze,minecraft:magma_cube,minecraft:wither_skeleton - Boss:
minecraft:warden,minecraft:ender_dragon
Complete Example
A full addon mod skeleton registering custom weapons, an equipment scanner, an armor set, and an event with Craftics.
fabric.mod.json
{
"schemaVersion": 1,
"id": "mymod-craftics-addon",
"version": "1.0.0",
"name": "MyMod Craftics Addon",
"description": "Adds MyMod weapons, equipment, armor sets, and events to Craftics combat.",
"environment": "*",
"entrypoints": {
"main": ["com.example.mymod.CrafticsAddon"]
},
"depends": {
"fabricloader": ">=0.16.0",
"craftics": ">=1.0.0",
"mymod": ">=1.0.0"
}
}
CrafticsAddon.java
package com.example.mymod;
import com.crackedgames.craftics.api.*;
import com.crackedgames.craftics.api.registry.*;
import com.crackedgames.craftics.combat.DamageType;
import com.crackedgames.craftics.combat.TrimEffects;
import net.fabricmc.api.ModInitializer;
import net.minecraft.item.Item;
import net.minecraft.registry.Registries;
import net.minecraft.util.Identifier;
public class CrafticsAddon implements ModInitializer {
@Override
public void onInitialize() {
registerWeapons();
registerEquipmentScanner();
registerArmorSet();
registerEvent();
}
private void registerWeapons() {
// --- Heavy Claymore: cleaving weapon with armor ignore + knockback ---
Item claymore = getItem("mymod", "heavy_claymore");
CrafticsAPI.registerWeapon(claymore, WeaponEntry.builder(claymore)
.damageType(DamageType.CLEAVING)
.attackPower(7)
.apCost(2)
.range(1)
.ability(Abilities.armorIgnore(0.15, 0.03)
.and(Abilities.knockbackDirection(1)))
.build());
// --- Swift Rapier: fast slashing weapon with bleed + pierce ---
Item rapier = getItem("mymod", "swift_rapier");
CrafticsAPI.registerWeapon(rapier, WeaponEntry.builder(rapier)
.damageType(DamageType.SLASHING)
.attackPower(4)
.apCost(1)
.range(1)
.ability(Abilities.bleed()
.and(Abilities.pierce()))
.build());
// --- Longreach Glaive: slashing weapon with extended range + sweep ---
Item glaive = getItem("mymod", "longreach_glaive");
CrafticsAPI.registerWeapon(glaive, WeaponEntry.builder(glaive)
.damageType(DamageType.SLASHING)
.attackPower(5)
.apCost(1)
.range(2)
.ability(Abilities.sweepAdjacent(0.20, 0.04))
.build());
}
private void registerEquipmentScanner() {
// Scan mymod's custom equipment slots and contribute stats to Craftics
CrafticsAPI.registerEquipmentScanner("mymod", (player) -> {
StatModifiers mods = new StatModifiers();
// Read items from your addon's custom equipment slots
// and map them to Craftics stat bonuses
Item swiftBelt = getItem("mymod", "swift_belt");
Item ironBelt = getItem("mymod", "iron_belt");
Item luckCharm = getItem("mymod", "lucky_charm");
ItemStack belt = getCustomSlot(player, "belt");
if (!belt.isEmpty()) {
if (belt.isOf(swiftBelt)) mods.add(TrimEffects.Bonus.SPEED, 1);
else if (belt.isOf(ironBelt)) mods.add(TrimEffects.Bonus.DEFENSE, 2);
}
ItemStack amulet = getCustomSlot(player, "amulet");
if (!amulet.isEmpty() && amulet.isOf(luckCharm)) {
mods.add(TrimEffects.Bonus.LUCK, 3);
}
return mods;
});
}
private void registerArmorSet() {
// Full-set bonus for mymod:mythril armor
CrafticsAPI.registerArmorSet(ArmorSetEntry.builder("mymod:mythril")
.damageBonus(DamageType.SLASHING, 2)
.damageBonus(DamageType.CLEAVING, 1)
.speedBonus(1)
.defenseBonus(2)
.description("Mythril Armor: light and sharp")
.build());
}
private void registerEvent() {
// A healing spring event available from biome index 1 onwards
CrafticsAPI.registerEvent(new EventEntry(
"mymod:healing_spring",
"Healing Spring",
0.12f,
1,
false,
(participants, world, eventManager) -> {
for (ServerPlayerEntity player : participants) {
player.heal(5.0f);
}
}
));
}
private static Item getItem(String namespace, String path) {
return Registries.ITEM.get(Identifier.of(namespace, path));
}
}
Custom Arena Maps
Step 1: Build Your Arena
Create the full scene in creative mode including a flat area for the grid, surrounding decorations (trees, ruins, water, cliffs), and any blocks you want. The area outside the grid is purely cosmetic. The game only reads the grid boundaries and spawn markers.
Step 2: Place Marker Blocks
Place special marker blocks to define the playable grid and spawn positions. The game scans for these blocks when loading the arena.
Marker Block Reference
| Block | Purpose |
|---|---|
| Diamond Block | Camera corner. Place on one corner outside the grid (required). |
| Emerald Block | Opposite corner. Place on the corner diagonally opposite the Diamond Block (required). |
| Gold Block | Player 1 spawn (primary) |
| Iron Block | Player 2 spawn (multiplayer) |
| Copper Block | Player 3 spawn |
| Coal Block | Player 4 spawn |
All markers must be at the same Y level.
Step 3: Export
Option A: WorldEdit (recommended)
- Select:
//pos1and//pos2 - Copy:
//copy - Save:
//schem save <name> - Find in
config/worldedit/schematics/ - Copy to
craftics_arenas/<biome>/<number>.schem
Option B: Vanilla Structure Block (48×48×48 limit)
/give @s structure_block- Set to Save mode, define box, name it, click SAVE
- Find in
<world>/generated/minecraft/structures/ - Copy to datapack at
data/craftics/structures/arenas/<biome>/<number>.nbt
File Naming
craftics_arenas/ (in game run directory, for .schem)
plains/
1.schem
2.schem
boss_1.schem
forest/
1.schem
data/craftics/structures/arenas/ (in datapack, for .nbt)
plains/
1.nbt
boss_1.nbt
Biome IDs for Arena Folders
| Overworld | Nether | End |
|---|---|---|
| plains | nether_wastes | outer_end_islands |
| forest | soul_sand_valley | end_city |
| desert | crimson_forest | chorus_grove |
| jungle | warped_forest | dragons_nest |
| river | basalt_deltas | |
| mountain | ||
| snowy | ||
| cave | ||
| deep_dark |
Tips
- Size your grid for the biome's growth range (e.g., Plains starts 8×8, grows +1 per level).
- The isometric camera looks from the southwest at ~55°. Tall structures on the north/east edges may block the view.
- Floor level = marker Y level.
- Obstacles are overlaid by the game, so your arena provides the base terrain only.
- Add atmosphere outside the grid (lanterns, campfires, particle-emitting blocks, etc.).
- Under-floor lighting is automatic (glowstone every 3 blocks).
Mob Head Textures
The combat HUD displays a small head icon for every enemy and ally in the arena. Craftics ships 80+ vanilla mob heads and auto-discovers textures for modded mobs at runtime, so no code changes are needed to add heads for new mobs.
Resolution Order
When the HUD requests a head for entity type somemod:bigwolf, MobHeadTextures.get() checks three sources in order:
- Hardcoded vanilla map — ~80 built-in entries for all vanilla mobs. Always checked first.
- Runtime registration — entries added via the Java API (see below). Checked second.
- Resource auto-discovery — probes the loaded resource manager for a PNG at two path conventions (see below). Results are cached until
/reload.
If none of the three sources return a texture, the HUD falls back to a colored square with the mob’s first initial.
Resource Pack Method (No Code)
Drop a 16×16 PNG at one of these two paths inside any resource pack:
| Convention | Path | Use Case |
|---|---|---|
| Craftics namespace | assets/craftics/textures/mob_heads/{modid}/{mobname}.png |
Resource packs shipping heads for any modded mob under Craftics’ namespace |
| Mod namespace | assets/{modid}/textures/mob_heads/{mobname}.png |
A mod shipping its own head texture in its own namespace |
For a mob with entity type alexsmobs:bone_serpent, the auto-discovery probes:
assets/craftics/textures/mob_heads/alexsmobs/bone_serpent.png (Craftics namespace)
assets/alexsmobs/textures/mob_heads/bone_serpent.png (mod namespace)
Run /reload or toggle the resource pack and the head appears on the combat HUD immediately — no client restart required.
Java API Method (Mod Code)
Addon mods can register head textures explicitly during client initialization:
import com.crackedgames.craftics.client.MobHeadTextures;
import net.minecraft.util.Identifier;
// In your ClientModInitializer.onInitializeClient():
MobHeadTextures.register(
"somemod:bigwolf",
Identifier.of("somemod", "textures/hud/bigwolf_head.png")
);
Runtime-registered entries take priority over auto-discovery but not over the built-in vanilla map.
Cache & Reload
Auto-discovered textures are cached after the first lookup. The cache is cleared automatically whenever /reload runs or resource packs change (via a SimpleSynchronousResourceReloadListener registered in CrafticsClient), so new or updated PNGs are picked up without restarting the client.
Addon Policy
Allowed
- Addons via API (weapons, equipment, armor sets, trims, events, enchantments, biomes, enemies, AI)
- Datapacks (arenas, loot, biome configs)
- Resource packs retexturing Craftics content
- Modpacks on CurseForge/Modrinth with credit
- Videos, streams, reviews (no permission needed)
Not Allowed
- Redistributing Craftics outside modpack launchers
- Copying source code into your projects
- Re-uploading without permission