# Events



# List of Events

This is a list of all events. It's possible that not all events are listed here, but this list will be updated regularly.

Click on event ID to open its class and see information, fields, and methods.

Type descriptions:

- <span style="color: rgb(45, 194, 107);">**Startup**</span>: scripts go into the <span style="color: rgb(45, 194, 107);">`/kubejs/startup_scripts/`</span> folder. Startup scripts run once, at startup, on both the client and server. Most events that require registering or modifying something at game start (like custom blocks, items, and fluids) will be Startup events.
- <span style="color: rgb(185, 106, 217);">**Server**</span>: scripts go into the <span style="color: rgb(185, 106, 217);">`/kubejs/server_scripts/`</span> folder. It will be reloaded when you run `/reload` command. Server events are always accessible, even in single-player worlds. Most events that make changes to the world while the game is running (such as breaking blocks, teleporting players, or adding recipes) will go here.
- <span style="color: rgb(185, 106, 217);">**Server Startup**</span>: same as Server, and the event will be fired at least once when the server loads.
- <span style="color: rgb(230, 126, 35);">**Client**</span>: scripts go into the <span style="color: rgb(230, 126, 35);">`/kubejs/client_scripts/`</span> folder. Will be reloaded when you press `F3+T`. Most changes that are per-client (such as resource packs, Painter, and JEI) are client events.
- <span style="color: rgb(230, 126, 35);">**Client Startup**:</span> Same as Client, and the event will be fired at least once when the client loads.

### Base KubeJS Events

<table border="1" id="bkmrk-folder-method-cancel" style="border-collapse: collapse; width: 100%; height: 2976.14px;"><thead><tr style="height: 29.7017px;"><td style="width: 18.2921%; height: 29.7017px;">**Folder**</td><td style="width: 63.8989%; height: 29.7017px;">**Method**</td><td style="width: 17.7978%; height: 29.7017px;">**Cancellable**</td></tr></thead><tbody><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(45, 194, 107);">`/startup_scripts/`</span></td><td style="width: 63.8989%; height: 30.6392px;">`StartupEvents.init` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(45, 194, 107);">`/startup_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`StartupEvents.postInit` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 349.929px;"><td style="width: 18.2921%; height: 349.929px;"><span style="color: rgb(45, 194, 107);">`/startup_scripts/`</span></td><td style="height: 349.929px; width: 63.8989%;">`StartupEvents.registry` (fluid)

`StartupEvents.registry` ([block](https://wiki.latvian.dev/books/kubejs/page/custom-blocks "Custom Blocks"))

`StartupEvents.registry` ([item](https://mods.latvian.dev/books/kubejs/page/custom-items))

`StartupEvents.registry` (enchantment)

`StartupEvents.registry` (mob effects)

`StartupEvents.registry` (sound event)

`StartupEvents.registry` (block entity type)

`StartupEvents.registry` (potion)

`StartupEvents.registry` (particle type)

`StartupEvents.registry` (painting variant)

`StartupEvents.registry` (custom stat)

`StartupEvents.registry` (point of interest type)

`StartupEvents.registry` (villager type)

`StartupEvents.registry` (villager profession)

</td><td style="width: 17.7978%; height: 349.929px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ClientEvents.highPriorityAssets` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ClientEvents.init` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ClientEvents.loggedIn` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ClientEvents.loggedOut` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ClientEvents.tick` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ClientEvents.painterUpdated` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ClientEvents.leftDebugInfo` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ClientEvents.rightDebugInfo` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ClientEvents.paintScreen` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ServerEvents.lowPriorityData` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ServerEvents.highPriorityData` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ServerEvents.loaded` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ServerEvents.unloaded` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ServerEvents.tick` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ServerEvents.tags` ([link](https://mods.latvian.dev/books/kubejs/page/tags))

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ServerEvents.commandRegistry` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">❌</td></tr><tr style="height: 35.3125px;"><td style="width: 18.2921%; height: 35.3125px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 35.3125px; width: 63.8989%;">`ServerEvents.command` (link)

</td><td style="width: 17.7978%; height: 35.3125px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ServerEvents.customCommand` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ServerEvents.recipes` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ServerEvents.afterRecipes` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ServerEvents.specialRecipeSerializers` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ServerEvents.compostableRecipes` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ServerEvents.recipeTypeRegistry` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ServerEvents.genericLootTables` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ServerEvents.blockLootTables` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ServerEvents.entityLootTables` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ServerEvents.giftLootTables` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ServerEvents.fishingLootTables` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ServerEvents.chestLootTables` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`LevelEvents.loaded` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`LevelEvents.unloaded` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`LevelEvents.tick` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`LevelEvents.beforeExplosion` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`LevelEvents.afterExplosion` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(45, 194, 107);">`/startup_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`WorldgenEvents.add` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(45, 194, 107);">`/startup_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`WorldgenEvents.remove` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`NetworkEvents.fromServer` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`NetworkEvents.fromClient` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(45, 194, 107);">`/startup_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.modification` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 35.2983px;"><td style="width: 18.2921%; height: 35.2983px;"><span style="color: rgb(45, 194, 107);">`/startup_scripts/`</span></td><td style="height: 35.2983px; width: 63.8989%;">`ItemEvents.toolTierRegistry` ([link](https://wiki.latvian.dev/books/kubejs/page/custom-tiers#bkmrk-tool-tiers))</td><td style="width: 17.7978%; height: 35.2983px;">❌</td></tr><tr style="height: 35.2983px;"><td style="width: 18.2921%; height: 35.2983px;"><span style="color: rgb(45, 194, 107);">`/startup_scripts/`</span></td><td style="height: 35.2983px; width: 63.8989%;">`ItemEvents.armorTierRegistry` ([link](https://wiki.latvian.dev/books/kubejs/page/custom-tiers#bkmrk-armour-tiers))</td><td style="width: 17.7978%; height: 35.2983px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.rightClicked` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.canPickUp` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.pickedUp` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.dropped` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.entityInteracted` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.crafted` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.smelted` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.foodEaten` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.tooltip` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(45, 194, 107);">`/startup_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.modelProperties` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.clientRightClicked` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.clientLeftClicked` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.firstRightClicked` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`ItemEvents.firstLeftClicked` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(45, 194, 107);">`/startup_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`BlockEvents.modification` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`BlockEvents.rightClicked` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`BlockEvents.leftClicked` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`BlockEvents.placed` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`BlockEvents.broken` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`BlockEvents.detectorChanged` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`BlockEvents.detectorPowered` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`BlockEvents.detectorUnpowered` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`BlockEvents.farmlandTrampled` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`EntityEvents.death` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`EntityEvents.hurt` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`EntityEvents.checkSpawn` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`EntityEvents.spawned` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`PlayerEvents.loggedIn` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`PlayerEvents.loggedOut` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`PlayerEvents.respawned` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`PlayerEvents.tick` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`PlayerEvents.chat` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`PlayerEvents.decorateChat` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`PlayerEvents.advancement` (link)</td><td style="width: 17.7978%; height: 30.6392px;">✅</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`PlayerEvents.inventoryOpened` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`PlayerEvents.inventoryClosed` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`PlayerEvents.inventoryChanged` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`PlayerEvents.chestOpened` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2921%; height: 30.6392px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.6392px; width: 63.8989%;">`PlayerEvents.chestClosed` (link)</td><td style="width: 17.7978%; height: 30.6392px;">❌</td></tr></tbody></table>

### Mod Compatibility

<p class="callout info">These events are enabled when certain other mods are present.</p>

##### **Just Enough Items (JEI)**

<table border="1" id="bkmrk-folder-method-cancel-0" style="border-collapse: collapse; width: 100%; height: 310.199px;"><colgroup><col style="width: 18.1685%;"></col><col style="width: 67.4791%;"></col><col style="width: 14.3411%;"></col></colgroup><tbody><tr style="height: 29.7017px;"><td style="width: 18.2942%; height: 29.7017px;">**Folder**</td><td style="width: 63.9061%; height: 29.7017px;">**Method**</td><td style="width: 17.7998%; height: 29.7017px;">**Cancellable**</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2942%; height: 30.6392px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.6392px; width: 63.9061%;">`JEIEvents.subtypes` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/forge/src/main/java/dev/latvian/mods/kubejs/integration/forge/jei/JEISubtypesEventJS.java))  
</td><td style="width: 17.7998%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2942%; height: 30.6392px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.6392px; width: 63.9061%;">`JEIEvents.hideItems` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/forge/src/main/java/dev/latvian/mods/kubejs/integration/forge/jei/HideJEIEventJS.java))  
</td><td style="width: 17.7998%; height: 30.6392px;">❌</td></tr><tr style="height: 35.3835px;"><td style="width: 18.2942%; height: 35.3835px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 35.3835px; width: 63.9061%;">`JEIEvents.hideFluids` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/forge/src/main/java/dev/latvian/mods/kubejs/integration/forge/jei/HideJEIEventJS.java))

</td><td style="width: 17.7998%; height: 35.3835px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2942%; height: 30.6392px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.6392px; width: 63.9061%;">`JEIEvents.hideCustom` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/forge/src/main/java/dev/latvian/mods/kubejs/integration/forge/jei/HideCustomJEIEventJS.java))  
</td><td style="width: 17.7998%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2942%; height: 30.6392px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.6392px; width: 63.9061%;">`JEIEvents.removeCategories` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/forge/src/main/java/dev/latvian/mods/kubejs/integration/forge/jei/RemoveJEICategoriesEvent.java))  
</td><td style="width: 17.7998%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2942%; height: 30.6392px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.6392px; width: 63.9061%;">`JEIEvents.removeRecipes` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/forge/src/main/java/dev/latvian/mods/kubejs/integration/forge/jei/RemoveJEIRecipesEvent.java))  
</td><td style="width: 17.7998%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2942%; height: 30.6392px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.6392px; width: 63.9061%;">`JEIEvents.addItems` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/forge/src/main/java/dev/latvian/mods/kubejs/integration/forge/jei/AddJEIEventJS.java))  
</td><td style="width: 17.7998%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2942%; height: 30.6392px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.6392px; width: 63.9061%;">`JEIEvents.addFluids` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/forge/src/main/java/dev/latvian/mods/kubejs/integration/forge/jei/AddJEIEventJS.java))  
</td><td style="width: 17.7998%; height: 30.6392px;">❌</td></tr><tr style="height: 30.6392px;"><td style="width: 18.2942%; height: 30.6392px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.6392px; width: 63.9061%;">`JEIEvents.information` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/forge/src/main/java/dev/latvian/mods/kubejs/integration/forge/jei/InformationJEIEventJS.java))  
</td><td style="width: 17.7998%; height: 30.6392px;">❌</td></tr></tbody></table>

##### **Roughly Enough Items (REI)**

<table border="1" id="bkmrk-folder-method-cancel-1" style="border-collapse: collapse; width: 100%; height: 180.344px;"><colgroup><col style="width: 18.4178%;"></col><col style="width: 63.288%;"></col><col style="width: 18.4178%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="width: 18.2942%; height: 29.7969px;">**Folder**</td><td style="width: 63.9061%; height: 29.7969px;">**Method**</td><td style="width: 17.7998%; height: 29.7969px;">**Cancellable**</td></tr><tr style="height: 30.1094px;"><td style="width: 18.2942%; height: 30.1094px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.1094px; width: 63.9061%;">`REIEvents.hide` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/common/src/main/java/dev/latvian/mods/kubejs/integration/rei/HideREIEventJS.java))  
</td><td style="width: 17.7998%; height: 30.1094px;">❌</td></tr><tr style="height: 30.1094px;"><td style="width: 18.2942%; height: 30.1094px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.1094px; width: 63.9061%;">`REIEvents.add` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/common/src/main/java/dev/latvian/mods/kubejs/integration/rei/AddREIEventJS.java))  
</td><td style="width: 17.7998%; height: 30.1094px;">❌</td></tr><tr style="height: 30.1094px;"><td style="width: 18.2942%; height: 30.1094px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.1094px; width: 63.9061%;">`REIEvents.information` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/common/src/main/java/dev/latvian/mods/kubejs/integration/rei/InformationREIEventJS.java))  
</td><td style="width: 17.7998%; height: 30.1094px;">❌</td></tr><tr style="height: 30.1094px;"><td style="width: 18.2942%; height: 30.1094px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.1094px; width: 63.9061%;">`REIEvents.removeCategories` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/common/src/main/java/dev/latvian/mods/kubejs/integration/rei/RemoveREICategoryEventJS.java))  
</td><td style="width: 17.7998%; height: 30.1094px;">❌</td></tr><tr style="height: 30.1094px;"><td style="width: 18.2942%; height: 30.1094px;"><span style="color: rgb(230, 126, 35);">`/client_scripts/`</span></td><td style="height: 30.1094px; width: 63.9061%;">`REIEvents.groupEntries` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/common/src/main/java/dev/latvian/mods/kubejs/integration/rei/GroupREIEntriesEventJS.java))  
</td><td style="width: 17.7998%; height: 30.1094px;">❌</td></tr></tbody></table>

##### **GameStages**

<table border="1" id="bkmrk-folder-method-cancel-2" style="border-collapse: collapse; width: 100%; height: 90.0157px;"><colgroup><col style="width: 18.5414%;"></col><col style="width: 62.7754%;"></col><col style="width: 18.6832%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px;">**Folder**</td><td style="height: 29.7969px;">**Method**</td><td style="height: 29.7969px;">**Cancellable**</td></tr><tr style="height: 30.1094px;"><td style="height: 30.1094px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.1094px;">`GameStageEvents.stageAdded` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/forge/src/main/java/dev/latvian/mods/kubejs/integration/forge/gamestages/GameStageEventJS.java))  
</td><td style="height: 30.1094px;">❌</td></tr><tr style="height: 30.1094px;"><td style="height: 30.1094px;"><span style="color: rgb(185, 106, 217);">`/server_scripts/`</span></td><td style="height: 30.1094px;">`GameStageEvents.stageRemoved` ([source](https://github.com/KubeJS-Mods/KubeJS/blob/1.19/main/forge/src/main/java/dev/latvian/mods/kubejs/integration/forge/gamestages/GameStageEventJS.java))</td><td style="height: 30.1094px;">❌</td></tr></tbody></table>

<div id="bkmrk-" style="position: absolute; left: 1144px; top: 2934.08px;"><div class="gtx-trans-icon">  
</div></div>

# Registering Items



# Recipes

<p class="callout warning">This page is still under development. It is not complete, and subject to change at any time.</p>

<p class="callout info">The recipe event is a server event.</p>

### Contents

- [How Recipes &amp; Callbacks Work](#bkmrk-recipes%2C-callbacks%2C-)
- [Adding Recipes](#bkmrk-adding-recipes)
    - [Shaped](#bkmrk-shaped)
    - [Shapeless](#bkmrk-%C2%A0)
    - [Smithing](#bkmrk-smithing)
    - [Smelting &amp; other Cooking](#bkmrk-smelting-%26-cooking)
    - [Stonecutting](#bkmrk-stonecutting)
    - [Custom (JSON)](#bkmrk-custom%2Fmodded-json-r)
- [Removing Recipes](#bkmrk-removing-recipes)
- [Modifying &amp; Replacing Recipes](#bkmrk-modifying-%26-replacin)
- [Helpers, Efficiency and Advanced Ingredients](#bkmrk-%C2%A0-0) (a.k.a. "how to avoid repeating yourself")

### Recipes, Callbacks, and You [↑](#bkmrk-contents)  


The recipe event can be used to add, remove, or replace recipes.

Any script that modifies recipes should be placed in the `kubejs/server_scripts` folder, and can be reloaded at any time with `/reload`.

Any modifications to the recipes should be done within the context of a `recipes` event. This means that we need to register an "event listener" for the `ServerEvents.recipes` event, and give it some code to execute whenever the game is ready to modify recipes. Here's how we tell KubeJS to execute some code whenever it's recipe time:

```javascript
/* 
 * ServerEvents.recipes() is a function that accepts another function,
 * called the "callback", as a parameter. The callback gets run when the 
 * server is working on recipes, and then we can make our own changes.
 * When the callback runs, it is also known as the event "firing". 
*/

ServerEvents.recipes(event => { //listen for the "recipes" server event.
  // You can replace `event` with any name you like, as 
  // long as you change it inside the callback too!
  
  // This part, inside the curly braces, is the callback.
  // You can modify as many recipes as you like in here,
  // without needing to use ServerEvents.recipes() again.
    
  console.log('Hello! The recipe event has fired!')
})
```

In the next sections, you can see what to put inside your callback.

### Adding Recipes [↑](#bkmrk-contents)


The following is all code that should be placed *inside* your recipe callback.

##### Shaped[↑](#bkmrk-contents)

Shaped recipes are added with the `event.shaped()` method. Shaped recipes must have their ingredients in a specific order and shape in order to match the player's input. The arguments to `event.shaped()` are:

1. The output item, which can have a count of 1-64
2. An array (max length 3) of crafting table rows, represented as strings (max length 3). Spaces represent slots with no item, and letters represent items. The letters don't have to mean anything; you explain what they mean in the next argument.
3. An object mapping the letters to Items, like `{letter: item}`. Input items must have a count of 1.

If you want to force strict positions on the crafting grid or disable mirroring, see Methods of Custom Recipes.

```javascript
event.shaped('3x minecraft:stone', [// arg 1: output
    'A B', 
    ' C ', // arg 2: the shape (array of strings)
    'B A'  
  ], {
    A: 'minecraft:andesite', 
    B: 'minecraft:diorite',  //arg 3: the mapping object
    C: 'minecraft:granite'   
  }
)
```

##### Shapeless[↑](#bkmrk-contents)

Shapeless recipes are added with the `event.shapeless()` method. Players can put ingredients of shapeless recipes anywhere on the grid and it will still craft. The arguments to `event.shapeless()` are:

1. The output item
2. An array of input items. The total input items' count must be 9 at most.

```javascript
event.shapeless('3x minecraft:dandelion', [ // arg 1: output
  'minecraft:bone_meal',
  'minecraft:yellow_dye', 	//arg 2: the array of inputs
  '3x minecraft:ender_pearl'
])
```

##### Smithing[↑](#bkmrk-contents)

Smithing recipes have 2 inputs and one output and are added with the `event.smithing()` method. Smithing recipes are crafted in the smithing table.

```javascript
event.smithing(
  'minecraft:netherite',  // arg 1: output
  'minecraft:iron_ingot', // arg 2: the item to be upgraded
  'minecraft:black_dye'   // arg 3: the upgrade item
)
```

##### Smelting &amp; Cooking[↑](#bkmrk-contents)

Cooking recipes are all very similar, accepting one input (a single item) and giving one output (which can be up to 64 of the same item). The fuel cannot be changed in this recipe event and should be done with tags instead.

- Smelting recipes are added with `event.smelting()`, and require the regular Furnace.
- Blasting recipes are added with `event.blasting()`, and require the Blast Furnace.
- Smoking recipes are added with `event.smoking()`, and require the Smoker.
- Campfire cooking recipes are added with `event.campfireCooking()`, and require the Campfire.

```javascript
// Cook 1 stone into 3 gravel in a Furnace:
event.smelting('3x minecraft:gravel', 'minecraft:stone')

// Blast 1 iron ingot into 10 nuggets in a Blast Furnace: 
event.blasting('10x minecraft:iron_nugget', 'minecraft:iron_ingot')

// Smoke glass into tinted glass in the Smoker:
event.smoking('minecraft:tinted_glass', 'minecraft:glass')

// Burn sticks into torches on the Campfire:
event.campfireCooking('minecraft:torch', 'minecraft:stick')
```

##### Stonecutting[↑](#bkmrk-contents)

Like the cooking recipes, stonecutting recipes are very simple, with one input (a single item) and one output (which can be up to 64 of the same item). They are added with the `event.stonecutting()` method.

```javascript
//allow cutting 3 sticks from any plank on the stonecutter
event.stonecutting('3x minecraft:stick', '#minecraft:planks')
```

##### Custom/Modded JSON recipes[↑](#bkmrk-contents)

If a mod supports Datapack recipes, you can add recipes for it without any addon mod support! Unfortunately, we can't give specific advice because every mod's layout is different, but if a mod has a GitHub (most do!) or other source code, you can find the relevant JSON files in `/src/generated/resources/data/<modname>/recipes/`. Otherwise, you may be able to find it by unzipping the mod's `.jar` file.

Here's an example of adding a Farmer's Delight cutting board recipe, which defines an input, output, and tool taken straight from [their GitHub](https://github.com/vectorwing/FarmersDelight/blob/1.18.2/src/generated/resources/data/farmersdelight/recipes/cutting/cake.json). Obviously, you can substitute any of the items here to make your own recipe!

```javascript
// Slice cake on a cutting board!
event.custom({
  type: 'farmersdelight:cutting',
  ingredients: [
    { item: 'minecraft:cake' }
  ],
  tool: { tag: 'forge:tools/knives' },
  result: [
    { item: 'farmersdelight:cake_slice', count: 7 }
  ]
})
```

Here's another example of `event.custom()` for making a Tinkers' Construct alloying recipe, which defines inputs, an output, and a temperature straight from [their GitHub](https://github.com/SlimeKnights/TinkersConstruct/blob/1.18.2/src/generated/resources/data/tconstruct/recipes/smeltery/alloys/molten_electrum.json) (conditions removed):

```javascript
// Adding the Molten Electrum alloying recipe from Tinkers' Construct
event.custom({
  type: 'tconstruct:alloy',
  inputs: [
    { tag: 'forge:molten_gold', amount: 90 },
    { tag: 'forge:molten_silver', amount: 90 }
  ],
  result: { fluid: 'tconstruct:molten_electrum', amount: 180 },
  temperature: 760
})
```

### Removing Recipes[↑](#bkmrk-contents)


Removing recipes can be done with the `event.remove()` method. It accepts 1 argument: a Recipe Filter. A filter is a set of properties that determine which recipe(s) to select. There are many conditions with which you can select a recipe:

- by output item `{output: '<item_id>'}`
- by input item(s) `{input: '<item_id>'}`
- by mod `{mod: '<mod_id>'}`
- by the unique recipe ID `{id: '<recipe_id>'}`
- combinations of the above: 
    - Require ALL conditions to be met: `{condition1: 'value', condition2: 'value2'}`
    - Require ANY of the conditions to be met: `[{condition_a: 'true'}, {condition_b: 'true'}]`
    - Require the condition NOT be met: `{not: {condition: 'requirement'}}`

All of the following can go in your recipe callback, as normal:

```javascript
// A blank condition removes all recipes (obviously not recommended):
event.remove({})

// Remove all recipes where output is stone pickaxe:
event.remove({ output: 'minecraft:stone_pickaxe' })

// Remove all recipes where output has the Wool tag:
event.remove({ output: '#minecraft:wool' })

// Remove all recipes where any input has the Redstone Dust tag:
event.remove({ input: '#forge:dusts/redstone' })

// Remove all recipes from Farmer's Delight:
event.remove({ mod: 'farmersdelight' })

// Remove all campfire cooking recipes:
event.remove({ type: 'minecraft:campfire_cooking' })

// Remove all recipes that grant stone EXCEPT smelting recipes:
event.remove({ not: { type: 'minecraft:smelting' }, output: 'stone' })

// Remove recipes that output cooked chicken AND are cooked on a campfire:
event.remove({ output: 'minecraft:cooked_chicken', type: 'minecraft:campfire_cooking' })

// Remove any blasting OR smelting recipes that output minecraft:iron_ingot:
event.remove([{ type: 'minecraft:smelting', output: 'minecraft:iron_ingot' }, { type: 'minecraft:blasting', output: 'minecraft:iron_ingot' }])

// Remove a recipe by ID. in this case, data/minecraft/recipes/glowstone.json:
// Note: Recipe ID and output are different!
event.remove({ id: 'minecraft:glowstone' })
```

To find a recipe's unique ID, turn on advanced tooltips using the `F3`+`H` keys (you will see an announcement in chat), then hover over the \[+\] symbol (if using [REI](https://www.curseforge.com/minecraft/mc-mods/roughly-enough-items)) or the output (if using [JEI](https://www.curseforge.com/minecraft/mc-mods/jei)).

### Modifying &amp; Replacing Recipes[ ↑](#bkmrk-contents)

You can bulk-modify supported recipes using `event.replaceInput()` and `event.replaceOutput()`. They each take 3 arguments:

1. A filter, similar to the ones used when [removing recipes](#bkmrk-removing-recipes)
2. The ingredient to replace
3. The ingredient to replace it with (can be a tag)

For example, let's say you were removing all sticks and wanted to make people craft things with saplings instead. Inside your [callback](#bkmrk-recipes%2C-callbacks%2C-) you would put:

```javascript
event.replaceInput(
  { input: 'minecraft:stick' }, // Arg 1: the filter
  'minecraft:stick',            // Arg 2: the item to replace
  '#minecraft:saplings'         // Arg 3: the item to replace it with
  // Note: tagged fluid ingredients do not work on Fabric, but tagged items do.
)
```

### Advanced Techniques [↑](#bkmrk-contents)  


##### Helper functions<span class="ILfuVd" lang="en"><span class="hgKElc"> **[↑](#bkmrk-contents)**</span></span>

<span class="ILfuVd" lang="en"><span class="hgKElc">Are you making a lot of similar recipes? Feel like you're typing the same text over and over? Try helper functions! Helper functions will perform repeated actions in much less space by taking in only the parts that are relevant, then doing the repetitive stuff for you!</span></span>

Here's a helper function, which allows you to make items by crafting a flower pot around the item you specify.

```javascript
ServerEvents.recipes(event => {
  let potting = (output, pottedInput) => {
    event.shaped(output, [
      'BIB',
      ' B '
    ], {
      B: 'minecraft:brick',
      I: pottedInput
    })
  }

  //Now we can make many 'potting' recipes without typing that huge block over and over!
  potting('kubejs:potted_snowball', 'minecraft:snowball')
  potting('kubejs:potted_lava', 'minecraft:lava_bucket')
  potting('minecraft:blast_furnace', 'minecraft:furnace')
})
```

##### <span class="ILfuVd" lang="en"><span class="hgKElc">Looping [**↑**](#bkmrk-contents)</span></span>

<span class="ILfuVd" lang="en"><span class="hgKElc">In addition to helper functions, you can also loop through an array to perform an action on every item in the array.  
</span></span>

<div id="bkmrk--0" style="position: absolute; left: 1014px; top: 363.969px;"><div class="gtx-trans-icon">  
</div></div>

# Tags

<p class="callout info">The tag event is a server event.</p>

<p class="callout warning">Tags are per item/block/fluid/entity\_type and as such cannot be added based on things like NBT data!</p>

The tags event takes an extra parameter that determines which registry it's adding tags to. You will generally only need item, block, and fluid tags. However, it does support adding tags to any registry, including other mods ones. For mod ones make sure to include the namespace!

```javascript
// Listen to item tag event
ServerEvents.tags('item', event => {
  // Get the #forge:cobblestone tag collection and add Diamond Ore to it
  event.add('forge:cobblestone', 'minecraft:diamond_ore')
  
  // Get the #forge:cobblestone tag collection and remove Mossy Cobblestone from it
  event.remove('forge:cobblestone', 'minecraft:mossy_cobblestone')
  
  // Get #forge:ingots/copper tag and remove all entries from it
  event.removeAll('forge:ingots/copper')
  
  // Required for FTB Quests to check item NBT
  event.add('itemfilters:check_nbt', 'some_item:that_has_nbt_types')
  
  // You can create new tags the same way you add to existing, just give it a name
  event.add('forge:completely_new_tag', 'minecraft:clay_ball')
  
  // It supports adding tags to tags as well. Just prefix the second tag with #
  event.add('c:stones', '#forge:stone')
  
  // Removes all tags from this entry
  event.removeAllTagsFrom('minecraft:stick')
  
  // Add all items from the forge:stone tag to the c:stone tag, unless the id contains diorite
  const stones = event.get('forge:stone').getObjectIds()
  const blacklist = Ingredient.of(/.*diorite.*/)
  stones.forEach(stone => {
    if (!blacklist.test(stone)) event.add('c:stone', stone)
  })
})
```

<p class="callout warning">Recipes use item tags, not block or fluid tags. Even if items representing those are blocks, like `minecraft:cobblestone`, it still uses an item tag for recipes.</p>

```javascript
// Listen to the block tag event
ServerEvents.tags('block', event => {
  // Add tall grass to the climbable tag. This does make it climbable!
  event.add('minecraft:climbable', 'minecraft:tall_grass')
})
```

# Custom Items

<p class="callout info">The custom item event is a startup event.</p>

Custom items are created in a startup script. They cannot be reloaded without restarting the game. The event is not cancellable.

```javascript
// Listen to item registry event
StartupEvents.registry('item', e => {
  // The texture for this item has to be placed in kubejs/assets/kubejs/textures/item/test_item.png
  // If you want a custom item model, you can create one in Blockbench and put it in kubejs/assets/kubejs/models/item/test_item.json
  e.create('test_item')
  
  // If you want to specify a different texture location you can do that too, like this:
  e.create('test_item_1').texture('mobbo:item/lava') // This texture would be located at kubejs/assets/mobbo/textures/item/lava.png
  
  // You can chain builder methods as much as you like
  e.create('test_item_2').maxStackSize(16).glow(true)
  
  // You can specify item type as 2nd argument in create(), some types have different available methods
  e.create('custom_sword', 'sword').tier('diamond').attackDamageBaseline(10.0)
})
```

Valid item types:

<div class="pointer-container" id="bkmrk-%C2%A0"><div class="pointer anim is-page-editable"><svg class="svg-icon" data-icon="link" role="presentation" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"></svg><div class="input-group inline block"> <button class="button outline icon" data-clipboard-target="#pointer-url" title="Copy Link" type="button"><svg class="svg-icon" data-icon="copy" role="presentation" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"></svg></button></div><svg class="svg-icon" data-icon="edit" role="presentation" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"></svg></div></div>- basic (this is the default)
- sword
- pickaxe
- axe
- shovel
- shears
- hoe
- helmet
- chestplate
- leggings
- boots

Other methods item builder supports: \[you can chain these methods after create()\]

- `maxStackSize(size)`
- `displayName(name)`
- `unstackable()`
- `maxDamage(damage)` This is the item's durability, not actual weapon damage.
- `burnTime(ticks)`
- `containerItem(item_id)`
- `rarity('rarity')`
- `tool(type, level)`
- `glow(true/false)`
- `tooltip(text...)`
- `group('group_id')`
- `color(index, colorHex)`
- `texture(customTextureLocation)`
- `parentModel(customParentModelLocation)`
- `food(foodBuilder => ...)` For full syntax see below

Methods available if you use a tool type (`'sword'`, `'pickaxe'`, `'axe'`, `'shovel'` or `'hoe'`):

- `tier('toolTier')`
- `modifyTier(tier => ...)` Same syntax as custom tool tier, see [Custom Tiers](https://mods.latvian.dev/books/kubejs/page/custom-tiers)
- `attackDamageBaseline(damage)` You only want to modify this if you are creating a custom weapon such as Spear, Battleaxe, etc.
- `attackDamageBonus(damage)`
- `speedBaseline(speed)` Same as attackDamageBaseline, only modify for custom weapon types
- `speed(speed)`

Default available tool tiers:

- wood
- stone
- iron
- gold
- diamond
- netherite

Methods available if you use an armour type ('helmet', 'chestplate', 'leggings' or 'boots'):

<div class="pointer-container" id="bkmrk-%C2%A0-0"><div class="pointer anim is-page-editable"><svg class="svg-icon" data-icon="link" role="presentation" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"></svg><div class="input-group inline block"> <button class="button outline icon" data-clipboard-target="#pointer-url" title="Copy Link" type="button"><svg class="svg-icon" data-icon="copy" role="presentation" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"></svg></button></div><svg class="svg-icon" data-icon="edit" role="presentation" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"></svg></div></div>- `tier('armorTier')`
- `modifyTier(tier => ...)` Same syntax as custom armor tier, see [Custom Tiers](https://mods.latvian.dev/books/kubejs/page/custom-tiers)

Default available armor tiers:

<div class="pointer-container" id="bkmrk-%C2%A0-1"><div class="pointer anim is-page-editable"><svg class="svg-icon" data-icon="link" role="presentation" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"></svg><div class="input-group inline block"> <button class="button outline icon" data-clipboard-target="#pointer-url" title="Copy Link" type="button"><svg class="svg-icon" data-icon="copy" role="presentation" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"></svg></button></div><svg class="svg-icon" data-icon="edit" role="presentation" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"></svg></div></div>- leather
- chainmail
- iron
- gold
- diamond
- turtle
- netherite

Vanilla group/creative tab IDs:

<div class="pointer-container" id="bkmrk-%C2%A0-2"><div class="pointer anim is-page-editable"><svg class="svg-icon" data-icon="link" role="presentation" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"></svg><div class="input-group inline block"> <button class="button outline icon" data-clipboard-target="#pointer-url" title="Copy Link" type="button"><svg class="svg-icon" data-icon="copy" role="presentation" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"></svg></button></div><svg class="svg-icon" data-icon="edit" role="presentation" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"></svg></div></div>- search
- buildingBlocks
- decorations
- redstone
- transportation
- misc
- food
- tools
- combat
- brewing

#### Custom Foods

```javascript
StartupEvents.registry('item', event => {
	event.create('magic_steak').food(food => {
		food
    		.hunger(6)
    		.saturation(6)//This value does not directly translate to saturation points gained
      		//The real value can be assumed to be:
      		//min(hunger * saturation * 2 + saturation, foodAmountAfterEating)
      		.effect('speed', 600, 0, 1)
      		.removeEffect('poison')
      		.alwaysEdible()//Like golden apples
      		.fastToEat()//Like dried kelp
      		.meat()//Dogs are willing to eat it
      		.eaten(ctx => {//runs code upon consumption
        		ctx.player.tell(Text.gold('Yummy Yummy!'))
          		//If you want to modify this code then you need to restart the game.
          		//However, if you make this code call a global startup function
          		//and place the function *outside* of an event handler
          		//then you may use the command:
          		//  /kubejs reload startup_scripts
          		//to reload the function instantly.
          		//See example below
        	})
	})
  
  event.create('magicer_steak').unstackable().food(food => {
    food
      .hunger(7)
      .saturation(7)
      // This references the function below instead of having code directly, so it is reloadable! 
      .eaten(ctx => global.myAwesomeReloadableFunction(ctx))
  })
})

global.myAwesomeReloadableFunction = ctx => {
  ctx.player.tell('Hello there!')
  ctx.player.tell(Text.of('Change me then reload with ').append(Text.red('/kubejs reload startup_scripts')).append(' to see your changes!'))
}
```

# Item modification

<p class="callout info">Item modification is a startup event.</p>

`ItemEvents.modification` is a startup script event used to modify various properties of existing items.

```javascript
ItemEvents.modification(event => {
  event.modify('minecraft:ender_pearl', item => {
    item.maxStackSize = 64
    item.fireResistant = true
    item.rarity = "UNCOMMON"
  })
  event.modify('minecraft:ancient_debris', item => {
    item.rarity = "RARE"
    item.burnTime = 16000
  })
  event.modify('minecraft:turtle_helmet', item => {
    item.rarity = "EPIC"
    item.maxDamage = 481
    item.craftingRemainder = Item.of('minecraft:scute').item
  })
})
```

Available properties:

<table border="1" id="bkmrk-property-value-type-" style="border-collapse: collapse; width: 90.6173%; height: 756.188px;"><colgroup><col style="width: 25.5116%;"></col><col style="width: 27.8299%;"></col><col style="width: 46.6585%;"></col></colgroup><thead><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Property</td><td style="height: 29.7969px;">Value Type</td><td style="height: 29.7969px;">Description</td></tr></thead><tbody><tr style="height: 46.5938px;"><td style="height: 46.5938px;">maxStackSize</td><td style="height: 46.5938px;">int</td><td style="height: 46.5938px;">Sets the maximum stack size for items. Default is 64 for most items.</td></tr><tr style="height: 46.5938px;"><td style="height: 46.5938px;">maxDamage</td><td style="height: 46.5938px;">int</td><td style="height: 46.5938px;">Sets the maximum damage an item can take before it is broken.</td></tr><tr style="height: 80.1875px;"><td style="height: 80.1875px;">craftingRemainder</td><td style="height: 80.1875px;">Item</td><td style="height: 80.1875px;">Sets the item left behind in the crafting grid when this item is used as a crafting ingredient (like milk buckets in the cake recipe). Most items do not have one.</td></tr><tr style="height: 63.3906px;"><td style="height: 63.3906px;">fireResistant</td><td style="height: 63.3906px;">boolean</td><td style="height: 63.3906px;">If this item burns in fire and lava. Most items are false by default, but Ancient Debris and Netherite things are not.</td></tr><tr style="height: 80.1875px;"><td style="height: 80.1875px;">rarity</td><td style="height: 80.1875px;">Rarity</td><td style="height: 80.1875px;">Sets the items rarity. This is mainly used for the name colour. COMMON by default. Nether Stars and Elytra are UNCOMMON, Golden Apples are RARE and Enchanted Golden Apples are EPIC. </td></tr><tr style="height: 63.3906px;"><td style="height: 63.3906px;">burnTime</td><td style="height: 63.3906px;">int</td><td style="height: 63.3906px;">Sets the burn time (in ticks) in a regular furnace for this item. Note that Smokers and Blast Furnaces burn fuel twice as fast. Coal is 1600.</td></tr><tr style="height: 50.6875px;"><td style="height: 50.6875px;">foodProperties</td><td style="height: 50.6875px;">FoodProperties</td><td style="height: 50.6875px;">Sets the items food properties to the provided properties. Can be `null` to remove food properties.</td></tr><tr style="height: 46.5938px;"><td style="height: 46.5938px;">foodProperties</td><td style="height: 46.5938px;"><div>Consumer&lt;FoodBuilder&gt;</div></td><td style="height: 46.5938px;">Sets the properties according to the consumer. See [below for more info](https://wiki.latvian.dev/books/kubejs/page/item-modification#bkmrk-food).</td></tr><tr style="height: 46.5938px;"><td style="height: 46.5938px;">digSpeed</td><td style="height: 46.5938px;">float</td><td style="height: 46.5938px;">Sets the items digging speed to the number provided. See table below for defaults.</td></tr><tr style="height: 46.5938px;"><td style="height: 46.5938px;">tier</td><td style="height: 46.5938px;"><div>Consumer&lt;MutableToolTier&gt;</div></td><td style="height: 46.5938px;">Currently BROKEN! Sets the tools tier according to the consumer. See [below for more info](https://wiki.latvian.dev/books/kubejs/page/item-modification#bkmrk-tier).</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">attackDamage</td><td style="height: 29.7969px;">double</td><td style="height: 29.7969px;">Sets the attack damage of this item.</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">attackSpeed</td><td style="height: 29.7969px;">double</td><td style="height: 29.7969px;">Sets the attack speed of this item</td></tr><tr style="height: 19.5938px;"><td style="height: 19.5938px;">armorProtection</td><td style="height: 19.5938px;">double</td><td style="height: 19.5938px;">Sets the armor protection for this item. 20 is a full armour bar.

</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">armorToughness</td><td style="height: 29.7969px;">double</td><td style="height: 29.7969px;">Adds an armor toughness bonus.</td></tr><tr style="height: 46.5938px;"><td style="height: 46.5938px;"><div>armorKnockbackResistance</div></td><td style="height: 46.5938px;">double</td><td style="height: 46.5938px;">Add an armor knockback resistance bonus. Can be negative. 1 is full knockback resistance.</td></tr></tbody></table>

##### Tool defaults

<table border="1" id="bkmrk-tier-maxdamage-digsp" style="border-collapse: collapse; width: 99.1358%;"><colgroup><col style="width: 10.5985%;"></col><col style="width: 5.86035%;"></col><col style="width: 12.2195%;"></col><col style="width: 9.47631%;"></col><col style="width: 36.1612%;"></col><col style="width: 25.6842%;"></col></colgroup><thead><tr><td>Tier</td><td>level</td><td>maxDamage</td><td>digSpeed</td><td>attackDamage (this is a bonus modified by the tool type value, not the final value)</td><td>enchantmentValue</td></tr></thead><tbody><tr><td>Wood

</td><td>0

</td><td>59</td><td>2</td><td>0</td><td>15</td></tr><tr><td>Stone</td><td>1</td><td>131</td><td>4</td><td>1</td><td>5</td></tr><tr><td>Iron</td><td>2</td><td>250</td><td>6</td><td>2</td><td>14</td></tr><tr><td>Diamond</td><td>3</td><td>1561</td><td>8</td><td>3</td><td>10</td></tr><tr><td>Gold</td><td>0</td><td>32</td><td>12</td><td>0</td><td>22</td></tr><tr><td>Netherite</td><td>4</td><td>2031</td><td>9</td><td>4</td><td>15</td></tr></tbody></table>

##### Armor defaults

All boxes with multiple values are formatted \[head, chest, legs, feet\]. Boxes with single values are the same for every piece.

<table border="1" id="bkmrk-tier-maxdamage%C2%A0-armo" style="border-collapse: collapse; width: 100%; height: 273.766px;"><colgroup><col style="width: 27.6897%;"></col><col style="width: 17.0569%;"></col><col style="width: 16.0692%;"></col><col style="width: 15.5748%;"></col><col style="width: 23.4858%;"></col></colgroup><thead><tr style="height: 35.3906px;"><td style="height: 35.3906px;">Tier</td><td style="height: 35.3906px;">maxDamage

</td><td style="height: 35.3906px;">armourProtection

</td><td style="height: 35.3906px;">armorToughness</td><td style="height: 35.3906px;">armorKnockbackResistance</td></tr></thead><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Leather</td><td style="height: 29.7969px;">\[65, 75, 80, 55\]</td><td style="height: 29.7969px;">\[1, 2, 3, 1\]</td><td style="height: 29.7969px;">0</td><td style="height: 29.7969px;">0</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Chain</td><td style="height: 29.7969px;">\[195, 225, 240, 165\]</td><td style="height: 29.7969px;"><div>[1, 4, 5, 2]</div></td><td style="height: 29.7969px;">0</td><td style="height: 29.7969px;">0</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Iron</td><td style="height: 29.7969px;">\[195, 225, 240, 165\]</td><td style="height: 29.7969px;"><div>[2, 5, 6, 2]</div></td><td style="height: 29.7969px;">0</td><td style="height: 29.7969px;">0</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Gold</td><td style="height: 29.7969px;">\[91 ,105, 112, 77\]</td><td style="height: 29.7969px;"><div>[1, 3, 5, 2]</div></td><td style="height: 29.7969px;">0</td><td style="height: 29.7969px;">0</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Diamond</td><td style="height: 29.7969px;">\[429, 495, 528, 363\]</td><td style="height: 29.7969px;"><div>[3, 6, 8, 3]</div></td><td style="height: 29.7969px;">2</td><td style="height: 29.7969px;">0</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Turtle (only has helmet)</td><td style="height: 29.7969px;">\[325, nil, nil. nil\]</td><td style="height: 29.7969px;"><div>[2, nil, nil, nil]</div></td><td style="height: 29.7969px;">0</td><td style="height: 29.7969px;">0</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Netherite</td><td style="height: 29.7969px;">\[481, 555, 592, 407\]</td><td style="height: 29.7969px;"><div>[3, 6, 8, 3]</div></td><td style="height: 29.7969px;">3</td><td style="height: 29.7969px;">0.1</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Elytra (not actually armor)</td><td style="height: 29.7969px;">\[nil, 432, nil, nil\]</td><td style="height: 29.7969px;">0</td><td style="height: 29.7969px;">0</td><td style="height: 29.7969px;">0</td></tr></tbody></table>

#### Tier

<p class="callout warning">Broken at the moment! [https://github.com/KubeJS-Mods/KubeJS/issues/662](https://github.com/KubeJS-Mods/KubeJS/issues/662). Use the non tier methods instead.</p>

##### Tools

```javascript
ItemEvents.modification(event => {
  event.modify('golden_sword', item => {
    item.tier = tier => {
        tier.speed = 12
        tier.attackDamageBonus = 10
        tier.repairIngredient = '#forge:storage_blocks/gold'
        tier.level = 3
    }
  })
  event.modify('wooden_sword', item => {
    item.tier = tier => {
        tier.enchantmentValue = 30
    }
  })
})
```

<table border="1" id="bkmrk-property-value-type--1" style="border-collapse: collapse; width: 100%; height: 119.188px;"><colgroup><col style="width: 33.3745%;"></col><col style="width: 20.6585%;"></col><col style="width: 46.0906%;"></col></colgroup><thead><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Property</td><td style="height: 29.7969px;">Value Type</td><td style="height: 29.7969px;">Description</td></tr></thead><tbody><tr><td>uses</td><td>int</td><td>The maximum damage before this tool breaks. Identical to maxDamage.</td></tr><tr><td>speed</td><td>float</td><td>The digging speed of this tool.</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">attackDamageBonus</td><td style="height: 29.7969px;">float</td><td style="height: 29.7969px;">The bonus attack damage of this tool.</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">level</td><td style="height: 29.7969px;">int</td><td style="height: 29.7969px;">The mining level of this tool.</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">enchantmentValue</td><td style="height: 29.7969px;">int</td><td style="height: 29.7969px;">The enchanting power of this tool. The higher this is, the better the enchantments at an Enchanting Table are.</td></tr><tr><td>repairIngredient</td><td>Ingredient</td><td>The material used to repair this tool in an anvil.</td></tr></tbody></table>

##### Armor

Doesnt actually exist/work at the moment. Sorry.

#### Food

```javascript
ItemEvents.modification(event => {
  event.modify('minecraft:diamond', item => {
    item.foodProperties = food => {
        food.hunger(2)
        food.saturation(3)
        food.fastToEat(true)
        food.eaten(e => e.player.tell('you ate')) // this is broken, use ItemEvents.foodEaten instead.
    }
  })

  event.modify('pumpkin_pie', item => {
    item.foodProperties = null // make pumpkin pies inedible
  })
})
```

<table border="1" id="bkmrk-method-parameters-de" style="border-collapse: collapse; width: 100%; height: 268.172px;"><colgroup><col style="width: 22.7441%;"></col><col style="width: 37.3381%;"></col><col style="width: 39.9177%;"></col></colgroup><thead><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Method</td><td style="height: 29.7969px;">Parameters</td><td style="height: 29.7969px;">Description</td></tr></thead><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px;">hunger</td><td style="height: 29.7969px;">int h</td><td style="height: 29.7969px;">Sets the hunger restored when this item is eaten</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">saturation</td><td style="height: 29.7969px;">float s</td><td style="height: 29.7969px;">Sets the saturation mulitplier when this food is eaten. This is not the final value, it goes through some complicated maths first</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">meat</td><td style="height: 29.7969px;">boolean flag (optional, true by default)</td><td style="height: 29.7969px;">Sets if this item is considered meat. Meat can be fed to wolves to heal them.</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">alwaysEdible</td><td style="height: 29.7969px;"><div>boolean flag (optional, true by default)</div></td><td style="height: 29.7969px;">If this item can be eaten even if your food bar is full. Chorus Fruit has this true by default.</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">fastToEat</td><td style="height: 29.7969px;"><div>boolean flag (optional, true by default)</div></td><td style="height: 29.7969px;">If this item is fast to eat, like Dried Kelp.</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">effect</td><td style="height: 29.7969px;"><div>ResourceLocation mobEffectId, int duration, int amplifier, float probability</div></td><td style="height: 29.7969px;">Adds an effect to the entity who eats this, like a Golden Apple</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">removeEffect</td><td style="height: 29.7969px;">MobEffect mobEffect</td><td style="height: 29.7969px;">Removes the effect from the entity who eats this, like Honey Bottles (poison).</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">eaten</td><td style="height: 29.7969px;"><div>Consumer&lt;FoodEatenEventJS&gt; e</div></td><td style="height: 29.7969px;">BROKEN! Use ItemEvents.foodEaten in server scripts instead.</td></tr></tbody></table>

# Custom Blocks

<p class="callout info">This is a [startup script](https://wiki.latvian.dev/books/kubejs/page/list-of-events), meaning that you will need to *restart your game* each time you want to make changes to it.</p>

You can register many types of custom blocks in KubeJS. Here's the simplest way:

```javascript
StartupEvents.registry("block", (event) => {
  event.create("example_block") // Create a new block with ID "kubejs:example_block"
})
```

That's it! Launch the game, and assuming you've left KubeJS's auto-generated resources alone, there should be a fully-textured block in the Creative menu under KubeJS (purple dye). KubeJS will also generate the name "Example Block" for you.

To make modifications to this block, we use the **block builder** returned by the `event.create()` call. The block builder allows us to chain together multiple modifications. Let's try making some of the more common modifications:

```javascript
StartupEvents.registry("block", (event) => {
    event.create("example_block") // Create a new block
    .displayName("My Custom Block") // Set a custom name
    .material("wood") // Set a material (affects the sounds and some properties)
    .hardness(1.0) // Set hardness (affects mining time)
    .resistance(1.0) // Set resistance (to explosions, etc)
    .tagBlock("my_custom_tag") // Tag the block with `#minecraft:my_custom_tag` (can have multiple tags)
    .requiresTool(true) // Requires a tool or it won't drop (see tags below)
    .tagBlock("my_namespace:my_other_tag") // Tag the block with `#my_namespace:my_other_tag`
    .tagBlock("mineable/axe") //can be mined faster with an axe
    .tagBlock("mineable/pickaxe") // or a pickaxe
    .tagBlock('minecraft:needs_iron_tool') // the tool tier must be at least iron
})
```

### All Block Builder Methods

In case it wasn't covered above, here's list of each method you can use when building a block.

- `displayName('name')`
    - Sets the item's display name.
- `material('material')` <span style="color: rgb(186, 55, 42);">(No longer supported in 1.20+, see `mapColor` and `soundType` below!)</span>
    - Set the item's material to an available material from the Materials List:

<details id="bkmrk-materials-list-airam"><summary>Materials List</summary>

air  
amethyst  
bamboo  
bamboo\_sapling  
barrier  
bubble\_column  
buildable\_glass  
cactus  
cake  
clay  
cloth\_decoration  
decoration  
dirt  
egg  
explosive  
fire  
froglight  
frogspawn  
glass  
grass  
heavy\_metal  
ice  
ice\_solid  
lava  
leaves  
metal  
moss  
nether\_wood  
piston  
plant  
portal  
powder\_snow  
replaceable\_fireproof\_plant  
replaceable\_plant  
replaceable\_water\_plant  
sand  
sculk  
shulker\_shell  
snow  
sponge  
stone  
structural\_air  
top\_snow  
vegetable  
water  
water\_plant  
web  
wood  
wool

</details>- `mapColor(MapColor)` <span style="color: rgb(186, 55, 42);">(1.20.1+ only)</span>
    - Set block map color, you can [find the entire list here](https://minecraft.fandom.com/wiki/Map_item_format#Base_colors), use ID in lowercase, e.g. `'color_light_green'`.
- `soundType(SoundType)` <span style="color: rgb(186, 55, 42);">(1.20.1+ only)</span>
    - Set block sound type:

<details id="bkmrk-properties-list-bool"><summary>SoundType List</summary>

Instead of using `soundType(SoundType)` you can also use one of these shortcut methods:

- `noSoundType()`
- `woodSoundType()`
- `stoneSoundType()`
- `gravelSoundType()`
- `grassSoundType()`
- `sandSoundType()`
- `cropSoundType()`
- `glassSoundType()`

wood  
gravel  
grass  
lily\_pad  
stone  
metal  
glass  
wool  
sand  
snow  
powder\_snow  
ladder  
anvil  
slime\_block  
honey\_block  
wet\_grass  
coral\_block  
bamboo  
bamboo\_sapling  
scaffolding  
sweet\_berry\_bush  
crop  
hard\_crop  
vine  
nether\_wart  
lantern  
stem  
nylium  
fungus  
roots  
shroomlight  
weeping\_vines  
twisting\_vines  
soul\_sand  
soul\_soil  
basalt  
wart\_block  
netherrack  
nether\_bricks  
nether\_sprouts  
nether\_ore  
bone\_block  
netherite\_block  
ancient\_debris  
lodestone  
chain  
nether\_gold\_ore  
gilded\_blackstone  
candle  
amethyst  
amethyst\_cluster  
small\_amethyst\_bud  
medium\_amethyst\_bud  
large\_amethyst\_bud  
tuff  
calcite  
dripstone\_block  
pointed\_dripstone  
copper  
cave\_vines  
spore\_blossom  
azalea  
flowering\_azalea  
moss\_carpet  
pink\_petals  
moss  
big\_dripleaf  
small\_dripleaf  
rooted\_dirt  
hanging\_roots  
azalea\_leaves  
sculk\_sensor  
sculk\_catalyst  
sculk  
sculk\_vein  
sculk\_shrieker  
glow\_lichen  
deepslate  
deepslate\_bricks  
deepslate\_tiles  
polished\_deepslate  
froglight  
frogspawn  
mangrove\_roots  
muddy\_mangrove\_roots  
mud  
mud\_bricks  
packed\_mud  
hanging\_sign  
nether\_wood\_hanging\_sign  
bamboo\_wood\_hanging\_sign  
bamboo\_wood  
nether\_wood  
cherry\_wood  
cherry\_sapling  
cherry\_leaves  
cherry\_wood\_hanging\_sign  
chiseled\_bookshelf  
suspicious\_sand  
suspicious\_gravel  
decorated\_pot  
decorated\_pot\_cracked

You can construct your own sound type with `new SoundType(volume, pitch, breakSound, stepSound, placeSound, hitSound, fallSound)` where volume and pitch are floats 0.0 - 1.0 (usually leave it as 1.0) and all sounds are SoundEvents.

</details>- `property(BlockProperty)`
    - - Adds more blockstates to the block, like being waterlogged or facing a certain direction. A full list of properties is available in the Properties List:

<details id="bkmrk-properties-list-usag"><summary>Properties List</summary>

Usage: `.property(BlockProperties.PICKLES)`

#### Boolean Properties (true/false):

attached,  
berries,  
bloom,  
bottom,  
can\_summon,  
conditional,  
disarmed,  
down,  
drag,  
east,  
enabled,  
extended,  
eye,  
falling,  
hanging,  
has\_book,  
has\_bottle\_0,  
has\_bottle\_1,  
has\_bottle\_2,  
has\_record,  
inverted,  
in\_wall,  
lit,  
locked,  
north,  
occupied,  
open,  
persistent,  
powered,  
short,  
shrieking,  
signal\_fire,  
snowy,  
south,  
triggered,  
unstable,  
up,  
vine\_end,  
waterlogged,  
west

#### Integer properties:

age\_1,  
age\_2,  
age\_3,  
age\_4,  
age\_5,  
age\_7,  
age\_15,  
age\_25,  
bites,  
candles,  
delay,  
distance,  
eggs,  
hatch,  
layers,  
level,  
level\_cauldron,  
level\_composter,  
level\_flowing,  
level\_honey,  
moisture,  
note,  
pickles,  
power,  
respawn\_anchor\_charges,  
rotation\_16,  
stability\_distance,  
stage

#### Directional Properties:  


facing,  
facing\_hopper,  
horizontal\_facing,  
vertical\_direction

#### Other (`enum`) Properties:  


attach\_face,  
axis,  
bamboo\_leaves,  
bed\_part,  
bell\_attachment,  
chest\_type,  
door\_hinge,  
double\_block\_half,  
dripstone\_thickness,  
east\_redstone,  
east\_wall,  
half,  
horizontal\_axis,  
mode\_comparator,  
north\_redstone,  
north\_wall,  
noteblock\_instrument,  
orientation,  
piston\_type,  
rail\_shape,  
rail\_shape\_straight,  
sculk\_sensor\_phase,  
slab\_type,  
south\_redstone,  
south\_wall,  
stairs\_shape,  
structureblock\_mode,  
tilt,  
west\_redstone,  
west\_wall

</details>- `tagBlock('namespace:tag_name')`
    - adds a tag to the block
- `tagItem('namespace:tag_name')`
    - adds a tag to the block's item, if it has one
- `tagBoth('namespace:tag_name')`
    - adds both block and item tag if possible
- `hardness(float)`  
    
    - Sets the block's Hardness value. Used for calculating the time it takes for the block to be destroyed.
- `resistance(float)`  
    
    - Set's the block's resistance to things like explosions
- `unbreakable()`
    - Shortcut to set the resistance to MAX\_VALUE and hardness to -1 (like bedrock)
- `lightLevel(number)`
    - Sets the block's light level.
    - Passing an integer (0-15) will set the block's light level to that value.
    - Passing a float (0.0-1.0) will multiply that number by 15, then set the block's light level to the nearest integer
- `opaque(boolean)`
    - Sets whether the block is opaque. Full, opaque blocks will not let light through.
- `fullBlock(boolean)`
    - Sets whether the block renders as a full block. Full blocks have certain optimizations applied to them, such as not rendering terrain behind them. If you're using `.box()` to make a custom hitbox, please set this to `false`.
- `requiresTool(boolean)`
    - If `true`, the block will use certain block tags to determine whether it should drop an item when mined. For example, a block tagged with `#minecraft:mineable/axe`, `#minecraft:mineable/pickaxe`, and `#minecraft:needs_iron_tool` would drop nothing unless it was mined with an axe or pickaxe that was at least iron level.
- `renderType('solid'|'cutout'|'translucent')`
    - Sets the render type.  
        
        - `cutout` is required for blocks with texture like glass, where pixels are either transparent or not
        - `translucent` is required for blocks like stained glass, where pixels can be semitransparent
        - otherwise, use `solid` if all pixels in your block are opaque.
- `color(tintindex, color)`
    - Recolors a block to a certain color
- `textureAll('texturepath')`
    - Textures all 6 sides of the block to the same texture.
    - The path must look like `kubejs:block/texture_name` (which would be included under `kubejs/assets/kubejs/textures/block/texture_name.png`).
    - Defaults to `kubejs:block/<block_name>`
- `texture('side', 'texturepath')`  
    
    - Texture one side by itself. Valid sides are `up`, `down`, `north`, `south`, `east`, and `west`.
- `model('modelpath')`
    - Specify a custom model.
    - The path must look like `kubejs:block/texture_name` (which would be included under `kubejs/assets/kubejs/models/block/texture_name.png`).
    - Defaults to `kubejs:block/<block_name>`.
- `noItem()`
    - Removes the associated item. Minecraft does this by default for a few blocks, like nether portal blocks. Use this if the player should never be able to hold or place the block.
- `box(x0, y0, z0, x1, y1, z1, boolean)`
- `box(x0, y0, z0, x1, y1, z1)` // defaults to true 
    - Sets a custom hitbox for the block, affecting collision. You can use this multiple times to define a complex shape composed of multiple boxes.
    - Each box is a rectangular prism with corners at (x0,y0,z0) and (x1,y1,z1)
    - You will probably want to set up a custom block model that matches the shape you define here.
    - The final boolean determines the coordinate scale of the box. Passing in `true` will use the numbers 0-16, while passing in `false` will use coordinates ranging from 0.0 to 1.0
- `noCollision()`
    - Removes the default full-block hitbox, allowing you to fall through the block.
- `notSolid()`
    - Tells the renderer that the block isn't solid.
- `waterlogged()`
    - Allows the block to be waterloggable.
- `noDrops()`
    - The block will not drop itself, even if mined with silk touch.
- `slipperiness(float)`
    - Sets the slipperiness of the block. Affects how much entities slide while moving on it. Almost every block in Vanilla has a slipperiness value of 0.6, except slime (0.8) and ice (0.98).
- `speedFactor(float)`
    - A modifier affecting how quickly players walk on the block.
- `jumpFactor(float)`
    - A modifier affecting how high players can jump off the block.
- `randomTick(consumer<randomTickEvent>)`
    - A function to run when the block recieves a random tick.
- `item(consumer<<a href="https://wiki.latvian.dev/books/kubejs/page/custom-items" title="Custom Items">itemBuilder</a>>)`
    - Modify certain properties of the block's item (see link)
- `setLootTableJson(json)`
    - Pass in a custom loot table JSON directly
- `setBlockstateJson(json)`
    - Pass in a custom blockstate JSON directly
- `setModelJson(json)`
    - Pass in a custom model JSON directly
- `noValidSpawns(boolean)`
    - If `true`, the block is not counted as a valid spawnpoint for entities
- `suffocating(boolean)`
    - Whether the block will suffocate entities that have their head inside it
- `viewBlocking(boolean)`
    - Whether the block counts as blocking a player's view.
- `redstoneConductor(boolean)`
    - Sets whether the block will conduct redstone. True by default.
- `transparent(boolean)`
    - Sets whether the block is transparent or not
- `defaultCutout()`
    - batches a bunch of methods to make blocks such as glass
- `defaultTranslucent()`
    - similar to defaultCutout() but using translucent layer instead

# Block Modification

<p class="callout info">The block modification event is a startup event.</p>

`BlockEvents.modification` event is a startup script event that allows you to change properties of existing blocks.

```JavaScript
BlockEvents.modification(e => {
  e.modify('minecraft:stone', block => {
    block.destroySpeed = 0.1
    block.hasCollision = false
  })
})
```

All available properties:

- `String material`
- `boolean hasCollision`
- `float destroySpeed`
- `float explosionResistance`
- `boolean randomlyTicking`
- `String soundType`
- `float friction`
- `float speedFactor`
- `float jumpFactor`
- `int lightEmission`
- `boolean requiresTool`

# Custom Tiers

<p class="callout info">The custom tier event is a startup event.</p>

You can make custom tiers for armor and tools in a startup script. They are not reloadable without restarting the game. The events are not cancellable.

##### Tool tiers

```javascript
ItemEvents.toolTierRegistry(event => {
  event.add('tier_id', tier => {
    tier.uses = 250
    tier.speed = 6.0
    tier.attackDamageBonus = 2.0
    tier.level = 2
    tier.enchantmentValue = 14
    tier.repairIngredient = '#forge:ingots/iron'
  })
})
```

##### Armor tiers

```javascript
ItemEvents.armorTierRegistry(event => {
  event.add('tier_id', tier => {
    tier.durabilityMultiplier = 15 // Each slot will be multiplied with [13, 15, 16, 11]
    tier.slotProtections = [2, 5, 6, 2] // Slot indicies are [FEET, LEGS, BODY, HEAD] 
    tier.enchantmentValue = 9
    tier.equipSound = 'minecraft:item.armor.equip_iron'
    tier.repairIngredient = '#forge:ingots/iron'
    tier.toughness = 0.0 // diamond has 2.0, netherite 3.0
    tier.knockbackResistance = 0.0
  })
})
```

# Worldgen

## General Notes

#### Biome Filters:

Biome filters work similarly to *recipe filters* and can be used to create complex and exact filters to fine-tune where your features may and may not spawn in the world. They are used for the `biomes` field of a feature and may look something like this:

```JavaScript
WorldgenEvents.add(event => {
  event.addOre(ore => {
    // let's look at all of the 'simple' filters first
    ore.biomes = 'minecraft:plains' 		// only spawn in exactly this biome
    ore.biomes = /^minecraft:.*/			// spawn in all biomes that match the given pattern
    ore.biomes = '#minecraft:is_forest' 	// spawn in all biomes tagged as 'minecraft:is_forest'
    
    // filters can be arbitrarily combined using AND, OR and NOT logic
    ore.biomes = {}							// empty AND filter, always true
    ore.biomes = []							// empty OR filter, always true
    ore.biomes = { not: 'minecraft:ocean' }	// spawn in all biomes that are NOT 'minecraft:ocean'
    
    // since AND filters are expressed as maps and expect string keys,
    // all of the 'primitive' filters can also be expressed as such
    ore.biomes = {					// see above for an explanation of these filters
      id: 'minecraft:plains',
      id: /^minecraft:.*/,			// regex (also technically an ID filter)
      tag: 'minecraft:is_forest',
    }
    // note all of the above syntax may be mixed and matched individually
  })
})
```

#### Rule Tests and Targets:

In 1.18, Minecraft WorldGen has changed to a "target-based" replacement system, meaning you can specify specific blocks to be replaced with specific other blocks within the same feature configuration. (For example, this is used to replace Stone with the normal ore and Deepslate with the Deepslate ore variant).

Each target gets a "rule test" as input (something that checks if a given block state should be replaced or not) and produces a specific output block state. While scripting, both of these concepts are expressed as the same class: `BlockStatePredicate`.

Syntax-wise, `BlockStatePredicate` is pretty similar to biome filters as they too can be combined using `AND` or `OR` filters (which is why we will not be repeating that step here), and can be used to match one of three different things fundamentally:

1. **Blocks:** these are simply parsed as strings, so for example `'minecraft:stone'` to match Stone
2. **Block States:** these are parsed as the block ID followed by an array of properties. You would use something like `'minecraft:furnace[lit=true]'` to match only Furnace blocks that are lit. You can use `F3` to figure out a block's properties, as well as possible values through using the debug stick.
3. **Block Tags**: these are parsed in the "familiar" tag syntax, so you could use `'#minecraft:base_stone_overworld'` to match all types of stone that can be found generating in the ground in the Overworld.

<p class="callout warning">Note that these are **block** tags, not **item** tags. They may (and probably will) be different! (F3 is your friend!)</p>

<p class="callout info">You can also use regular expressions with block filters, so `/^mekanism:.+_ore$/` would match any block from Mekanism whose ID ends with `_ore`. Keep in mind this will *not* match block state properties!</p>

<p class="callout info">When a `RuleTest` is required instead of a `BlockStatePredicate`, you can also supply that rule test directly in the form of a JavaScript object (it will then be parsed the same as vanilla would parse JSON or NBT objects). This can be useful if you want rule tests that have a random chance to match.</p>

**More examples of how targets work can be found in the example script down below.**

#### Height Providers:

Another system that may appear a bit confusing at first is the system of "height providers", which are used to determine at what Y level a given ore should spawn and with what frequency. Used in tandem with this feature are the so-called "vertical anchors", which may be used to get the height of something relative to a specific anchor point (for example the top or bottom of the world).

In KubeJS, this system has been simplified a bit to make it easier to use for script developers. There are two common types of ore placement:

1. **Uniform**: has the same chance to spawn anywhere in between the two anchors
2. **Triangle**: is more likely to spawn in the center of the two anchors than it is to spawn further outwards

 To use these two, you can use the methods `uniformHeight` and `traingleHeight` in `AddOreProperties`, respectively. Vertical anchors have also been simplified, as you can use the `aboveBottom` / `belowTop` helper methods in `AddOreProperties`.

**Once again, see the example script for more information!**

---


#### Example script

```JavaScript
WorldgenEvents.add(event => {
  // use the anchors helper from the event
  const { anchors } = event

  event.addOre(ore => {
    ore.id = 'kubejs:glowstone_test_lmao' // (optional, but recommended) custom id for the feature
    ore.biomes = {
      not: 'minecraft:savanna' // biome filter, see above (technically also optional)
    }

    // examples on how to use targets
    ore.addTarget('#minecraft:stone_ore_replaceables', 'minecraft:glowstone') // replace anything in the vanilla stone_ore_replaceables tag with Glowstone
    ore.addTarget('minecraft:deepslate', 'minecraft:nether_wart_block')       // replace Deepslate with Nether Wart Blocks
    ore.addTarget([
      'minecraft:gravel',     // replace gravel...
      /minecraft:(.*)_dirt/   // or any kind of dirt (including coarse, rooted, etc.)...
    ], 'minecraft:tnt')       // with TNT (trust me, it'll be funny)

    ore.count([15, 50])             // generate between 15 and 50 veins (chosen at random), you could use a single number here for a fixed amount of blocks
      .squared()                    // randomly spreads the ores out across the chunk, instead of generating them in a column
      .triangleHeight(				      // generate the ore with a triangular distribution, this means it will be more likely to be placed closer to the center of the anchors
        anchors.aboveBottom(32),    // the lower bound should be 32 blocks above the bottom of the world, so in this case, Y = -32 since minY = -64
        anchors.absolute(96)	      // the upper bound, meanwhile is set to be just exactly at Y = 96
      )								              // in total, the ore can be found between Y levels -32 and 96, and will be most likely at Y = (96 + -32) / 2 = 32

    // more, optional parameters (default values are shown here)
    ore.size = 9                            // max. vein size
    ore.noSurface = 0.5                     // chance to discard if the ore would be exposed to air
    ore.worldgenLayer = 'underground_ores'  // what generation step the ores should be generated in (see below)
    ore.chance = 0							            // if != 0 and count is unset, the ore has a 1/n chance to generate per chunk
  })

  // oh yeah, and did I mention lakes exist, too?
  // (for now at least, Vanilla is likely to remove them in the future)
  event.addLake(lake => {
    lake.id = 'kubejs:funny_lake' // BlockStatePredicate
    lake.chance = 4
    lake.fluid = 'minecraft:lava'
    lake.barrier = 'minecraft:diamond_block'
  })
})

WorldgenEvents.remove(event => {
  // print all features for a given biome filter
  event.printFeatures('', 'minecraft:plains')

  event.removeOres(props => {
    // much like ADDING ores, this supports filtering by worldgen layer...
    props.worldgenLayer = 'underground_ores'
    // ...and by biome
    props.biomes = [
      { category: 'icy' },
      { category: 'savanna' },
      { category: 'mesa' }
    ]

    // BlockStatePredicate to remove iron and copper ores from the given biomes
    // Note tags may NOT be used here, unfortunately...
    props.blocks = ['minecraft:iron_ore', 'minecraft:copper_ore']
  })

  // remove features by their id (first argument is a generation step)
  event.removeFeatureById('underground_ores', ['minecraft:ore_coal_upper', 'minecraft:ore_coal_lower'])
})
```

#### Generation Steps

<div id="bkmrk-raw_generation-lakes"><div data-jump-section="global"><div aria-label="Messages in " aria-live="off" aria-orientation="vertical" data-list-id="chat-messages"><div data-list-item-id="chat-messages___chat-messages-793143572244201492"><div>1. `raw_generation`
2. `lakes`
3. `local_modifications`
4. `underground_structures`
5. `surface_structures`
6. `strongholds`
7. `underground_ores`
8. `underground_decoration`
9. `fluid_springs`
10. `vegetal_decoration`
11. `top_layer_modification`

</div></div></div></div></div><form class="form-2fGMdU" id="bkmrk-test"><p class="callout warning">It's possible you may not be able to generate some things in their layer, like ores in Dirt, because Dirt hasn't spawned yet. You may have to change the layer to one of the above generation steps by calling `ore.worldgenLayer = 'top_layer_modification'`. However, this is not recommended.</p>

<p class="callout warning">Nether ores are generated in `underground_decoration` step!</p>

</form>