Modify Existing Content
Modifying vanilla (or modded) game content is just as important as adding new content. Katton provides a suite of modify* functions that let you change item properties, block behavior, entity attributes, recipes, loot tables, and villager trades — all from Kotlin scripts, all hot-reloadable.
NOTE
All modify functions live in top.katton.api.mod and are annotated @ApiStatus.Experimental. They are available on the currently supported Minecraft versions: 26.1.2 and 26.2.
Import
import top.katton.api.mod.*Run modifications from a ServerPhase.READY entrypoint, as shown in every example below. This gives server-dependent APIs a valid server and lets world packs replay staged changes during reload. Avoid executable modification calls at Kotlin class-load time because they bypass Katton's phase and ownership context.
Reload Behavior
Modify APIs fall into two categories based on how they interact with Minecraft's internal state:
| Mechanism | APIs | Reload Cleanup |
|---|---|---|
| Live mutation — writes directly to Minecraft's internal fields | modifyItem, modifyBlock, modifyEntityType | Changes persist until JVM restart. Removing a modify* call from a script and reloading does not revert the change. |
| Staged mutation — defers writes to the datapack apply phase | modifyRecipe, removeRecipe, modifyLootTable, addVillagerTrade | Changes are cleared and re-applied on every reload. Removing a call from a script and reloading cleanly drops the mutation. |
1. Modify Items
Change data components on any existing item: max stack size, durability, rarity, food properties, fire resistance, crafting remainder, and attack stats.
import net.minecraft.network.chat.Component
import net.minecraft.world.food.FoodProperties
import net.minecraft.world.item.Rarity
import top.katton.api.ServerPhase
import top.katton.api.ServerScriptEntrypoint
import top.katton.api.mod.*
@ServerScriptEntrypoint(ServerPhase.READY)
fun modifyItems() {
// Make ender pearls stack to 64, add fire resistance, and set epic rarity
modifyItem("minecraft:ender_pearl") {
maxStackSize = 64
rarity = Rarity.EPIC
fireResistant = true
}
// Turn diamond into an edible food item
modifyItem("minecraft:diamond") {
name = Component.literal("Candy Diamond")
foodProperties = FoodProperties.Builder()
.nutrition(8)
.saturationModifier(1.2f)
.alwaysEdible()
.build()
}
// Boost netherite sword attack damage
modifyItem("minecraft:netherite_sword") {
attackDamage = 14.0
attackSpeed = 2.0
}
}Available properties:
| Property | Description |
|---|---|
maxStackSize | Sets max stack. Katton rejects invalid > 1 && maxDamage > 0 combinations. |
maxDamage | Sets durability. |
rarity | Item rarity (COMMON / UNCOMMON / RARE / EPIC). |
name | Display name component. |
foodProperties | Makes the item edible. Katton automatically adds CONSUMABLE alongside FOOD. |
fireResistant | Adds DAMAGE_RESISTANT for fire damage type. Only true is supported. |
craftingRemainder | Container item (e.g., bucket → empty bucket). |
attackDamage | Sets attack damage. Katton adds a default WEAPON component if missing. |
attackSpeed | Sets attack speed. |
2. Modify Blocks
Change block properties: hardness, resistance, friction, speed/jump factor, light emission, collision flags, and sound type.
import net.minecraft.world.level.block.SoundType
import top.katton.api.ServerPhase
import top.katton.api.ServerScriptEntrypoint
import top.katton.api.mod.*
@ServerScriptEntrypoint(ServerPhase.READY)
fun modifyBlocks() {
// Make stone soft and sound like wool
modifyBlock("minecraft:stone") {
strength(0.5f)
soundType = SoundType.WOOL
}
// Make obsidian glow
modifyBlock("minecraft:obsidian") {
lightEmission = 8
}
// Ice with increased friction (less slippery)
modifyBlock("minecraft:ice") {
friction = 0.8f
}
}NOTE
Katton writes changes into three layers: BlockBehaviour.Properties, live BlockBehaviour final fields, and every pre-built BlockStateBase, then calls initCache() to refresh cached shapes. This covers local-player step sounds, mob collision, and lighting.
3. Modify Recipes
Change the result, count, experience, or cooking time of an existing recipe — or remove it entirely.
import top.katton.api.ServerPhase
import top.katton.api.ServerScriptEntrypoint
import top.katton.api.mod.*
@ServerScriptEntrypoint(ServerPhase.READY)
fun modifyRecipes() {
// Change iron smelting to produce 3 gold ingots with bonus experience
modifyRecipe("minecraft:iron_ingot_from_smelting_iron_ore") {
result("minecraft:gold_ingot")
resultCount = 3
experience = 5.0f
cookingTime = 60
}
// Remove the stone pickaxe recipe entirely
removeRecipe("minecraft:stone_pickaxe")
}WARNING
modifyRecipe and removeRecipe require a running server. The recipe being modified must already be registered in the live RecipeManager.
4. Modify Entity Attributes
Override default attribute values for vanilla or modded entity types — max health, attack damage, movement speed, armor, and more.
import top.katton.api.ServerPhase
import top.katton.api.ServerScriptEntrypoint
import top.katton.api.mod.*
@ServerScriptEntrypoint(ServerPhase.READY)
fun modifyEntities() {
// Make zombies stronger
modifyEntityType("minecraft:zombie") {
maxHealth(40.0)
attackDamage(8.0)
movementSpeed(0.32)
followRange(40.0)
}
// Skeleton: faster and tougher
modifyEntityType("minecraft:skeleton") {
maxHealth(30.0)
movementSpeed(0.30)
}
// Creeper with armor
modifyEntityType("minecraft:creeper") {
maxHealth(30.0)
armor(4.0)
}
}Available attributes:
| Method | Attribute |
|---|---|
maxHealth(value) | generic.max_health |
movementSpeed(value) | generic.movement_speed |
knockbackResistance(value) | generic.knockback_resistance |
attackDamage(value) | generic.attack_damage |
attackSpeed(value) | generic.attack_speed |
armor(value) | generic.armor |
armorToughness(value) | generic.armor_toughness |
followRange(value) | generic.follow_range |
luck(value) | generic.luck |
attribute(holder, value) | Any custom attribute |
WARNING
Katton copies all existing attributes from the original supplier before applying overrides. Mob-specific attributes (FOLLOW_RANGE, zombie reinforcement, etc.) are preserved. Starting from LivingEntity.createLivingAttributes() alone would crash mobs.
5. Modify Loot Tables
Read an existing loot table, add or remove pools and entries, and re-register it — all from a Kotlin DSL.
import top.katton.api.ServerPhase
import top.katton.api.ServerScriptEntrypoint
import top.katton.api.mod.*
@ServerScriptEntrypoint(ServerPhase.READY)
fun modifyLootTables() {
// Add a diamond drop to stone blocks
modifyLootTable("minecraft:blocks/stone") {
pool {
rolls = 1
addItem("minecraft:diamond", weight = 1)
}
}
// Add coal to grass block drops
modifyLootTable("minecraft:blocks/grass_block") {
pool {
addItem("minecraft:coal", weight = 3)
}
}
}Operations:
| Method | Effect |
|---|---|
pool { … } | Append a new pool |
rawPool(json) | Append a raw JSON pool |
removePool(index) | Drop a pool at the given index |
removeItem(itemId) | Drop every item entry matching itemId from every pool |
Within a pool { ... } block:
| Member | Description |
|---|---|
rolls = N | Pool roll count (default 1) |
addItem(id, weight, quality) | Add an item entry |
addTag(id, weight, expand) | Add a tag entry |
addEmpty(weight) | Add an empty entry |
6. Modify Villager & Wandering Trader Trades
Append new trades to profession trade sets or wandering trader pools.
import top.katton.api.ServerPhase
import top.katton.api.ServerScriptEntrypoint
import top.katton.api.mod.*
@ServerScriptEntrypoint(ServerPhase.READY)
fun addTrades() {
// Farmer level 1: 1 emerald → 5 apples
addVillagerTrade("minecraft:farmer/level_1") {
cost("minecraft:emerald", count = 1)
result("minecraft:apple", count = 5)
maxUses = 12
xp = 2
priceMultiplier = 0.05f
}
// Weaponsmith level 3: 8 emeralds → 1 diamond sword
addVillagerTrade("minecraft:weaponsmith/level_3") {
cost("minecraft:emerald", count = 8)
result("minecraft:diamond_sword")
maxUses = 3
xp = 15
priceMultiplier = 0.2f
}
// Wandering trader: 5 emeralds → 1 diamond
addVillagerTrade("minecraft:wandering_trader/uncommon") {
cost("minecraft:emerald", count = 5)
result("minecraft:diamond")
maxUses = 3
xp = 0
}
}Configuration:
| Property | Default | Description |
|---|---|---|
cost(itemId, count) | required | Item the merchant wants |
additionalCost(itemId, count) | unset | Optional secondary cost |
result(itemId, count) | required | Item the merchant gives back |
maxUses | 12 | Trade lock-out threshold |
xp | 2 | Villager XP per trade |
priceMultiplier | 0.05f | Vanilla 0.05 for farmers |
NOTE
Trades appear after /katton reload. The manager snapshots every modified TradeSet on first apply and automatically cleans up previous injections on subsequent reloads.
Requirements
| API | Needs server? | Needs reload? |
|---|---|---|
modifyItem / modifyBlock / modifyEntityType | No | No |
modifyRecipe / removeRecipe | Yes | Applied at reload |
modifyLootTable / getLootTable | Yes | Applied at reload |
addVillagerTrade | Yes | Applied at reload |
For complete API signatures, see the Common API docs.
