Repository navigation
API Loot Tables
Lua API / World systems / Loot tables
Loot tables are reusable weighted item distributions. They are a shared world-system resource rather than a
structure-only feature. A single table can be used by block drops,
entity drops, and structure
loot elements.
The public API registers and references loot tables. It does not currently provide a general roll() function for
arbitrary gameplay Lua code.
| Consumer | How the table is used | Randomness |
|---|---|---|
| Block drop | Produces the stacks dropped for one block-drop request. | Fresh runtime sample for every request. |
| Entity drop | Produces the stacks dropped by a death or explicit entity:dropLoot() call. |
Fresh runtime sample for every event. |
Structure loot element |
Produces contents for an inventory placed by a structure. | Deterministic sample derived from world generation. |
Registers one table and returns a typed reference. Define pools inline, provide a custom path, or omit both to use
the default packaged asset at assets/<namespace>/loot_tables/<key-path>.json.
local materialDrops = betamoon.lootTables:add {
key = "mymod:material_drops",
pools = {
{
key = "supplies",
rolls = { min = 3, max = 6 },
entries = {
{
type = "item",
weight = 4,
stack = {
item = "minecraft:item/ingot_iron",
count = { min = 1, max = 4 }
}
},
{ type = "item", weight = 2, stack = { item = "minecraft:item/bread" } },
{ type = "empty", weight = 1 }
}
}
}
}
assert(materialDrops.key == "mymod:material_drops")| Field | Behavior |
|---|---|
key |
Required canonical namespace:path key. It must be unique among loot tables. |
path |
Optional mod-package path beginning with assets/, for example assets/mymod/loot_tables/special.json. Mutually exclusive with pools. |
pools |
Optional inline pool list. Mutually exclusive with path. |
betamoon.lootTables:get(key) returns a reference or nil; getRequired(key) raises an error when absent. References
provide a readable key field and can be used anywhere a loot table field is accepted.
Use the same registered table reference for any number of block and entity declarations:
local commonLoot = betamoon.lootTables:add {
key = "mymod:common_drops",
pools = {
{
key = "main",
rolls = 1,
entries = {
{ type = "item", weight = 3, stack = { item = 265 } },
{ type = "empty", weight = 1 }
}
}
}
}
local blockDrops = { table = commonLoot }
local entityDrops = { table = commonLoot }The drops field also accepts { pools = { ... } } to declare the same pool syntax inline. pools and table are
mutually exclusive. Block and entity drops do not use structure placement seeds: every block-drop request, entity
death, and explicit entity:dropLoot() call takes a fresh sample from the world's runtime random stream.
The older list of { item, min, max, chance, damage } entries remains available as a compact shorthand. It samples
every listed entry independently rather than selecting weighted entries from pools.
A structure loot element can use the same registered tables and inline pools. Structures additionally control the
destination inventory, slot selection, handling of existing contents, and overflow behavior. Those placement-specific
fields belong to the structure element rather than to the reusable loot table.
See structure inventory loot for the structure syntax and its inventory policies.
JSON and Lua declarations produce the same validated model.
{
"format": "betamoon_loot_table",
"pools": [
{
"key": "main",
"rolls": 2,
"entries": [
{
"type": "item",
"weight": 3,
"stack": { "item": "minecraft:item/coal", "count": { "min": 1, "max": 4 } }
},
{ "type": "empty", "weight": 1 }
]
}
]
}Register a default-path asset with only its key:
local materialDrops = betamoon.lootTables:add { key = "mymod:material_drops" }Files must be strict UTF-8 JSON, are limited to 1 MiB, and reject unknown fields. A malformed or missing asset rejects the declaration when the mod loads.
| Field | Behavior |
|---|---|
key |
Required stable lowercase identifier, unique within this table. |
rolls |
Nonnegative integer or inclusive { min, max }; defaults to 1. Both range fields are required. |
entries |
Required nonempty weighted entry list. |
Every pool runs in declaration order. For each pool, BetaMoon samples rolls once and then performs that many
independent weighted selections with replacement. An entry's probability is its weight divided by the sum of all
weights in that pool.
For example, if pool supplies samples two rolls, it makes two selections and may select the same entry twice. A
second pool then runs and appends its results. An item appends one stack, an empty entry appends nothing, and a
table entry runs the complete referenced table once and appends every stack it emits. One parent roll can therefore
produce several stacks.
| Type | Fields | Behavior |
|---|---|---|
item |
stack, optional weight
|
Emits one sampled stack. |
empty |
Optional weight
|
Emits nothing for that roll. |
table |
table, optional weight
|
Runs another registered table. Lua accepts its key or typed reference. |
weight defaults to 1 and must be positive. Missing nested references, cycles, excessive nesting, and excessive
worst-case output reject the declarations when mods load.
stack = {
item = 265,
count = { min = 1, max = 4 },
damage = 0
}| Field | Behavior |
|---|---|
item |
Required numeric item/block-item ID or supported item name. Numeric IDs are unambiguous. |
count |
Positive integer or inclusive { min, max }; defaults to 1. It may not exceed that item's own stack limit. |
damage |
Nonnegative integer or inclusive { min, max }; defaults to 0. Represents durability or subtype metadata. |
Count and damage are sampled independently. Only identity, count, and damage are supported; arbitrary item NBT, enchantments, custom names, and Lua callbacks are not part of this format. A string currently resolves through Minecraft's available item names after optional namespace/type-prefix normalization. The namespace does not disambiguate two items with the same name; use numeric IDs when names could collide.
The consumer determines how a loot table receives randomness:
- Block and entity drops start every evaluation with a fresh value from the world's runtime random stream. Repeated
block breaks, deaths, and
entity:dropLoot()calls therefore resample the table. - Structure loot derives its sample from the world seed and stable placement information. Regenerating the same structure with the same definitions and seed produces the same result.
The shared table definition does not change between these uses. Only the source of randomness differs.
For structure loot, the deterministic inputs also include the loot-element key and position, table definition, pool key, and roll number. Stable pool and element keys keep unrelated structure-generation random streams independent. Pools append results in declaration order; a structure pairs that order with its destination slot order.
Changing a table used by an unfinished saved regional structure prevents that structure from mixing old and new definitions. Restore the matching declaration to complete it. This saved-plan protection is specific to regional structure generation and does not apply to runtime block or entity drops.
| Limit | Maximum |
|---|---|
| Pools per table | 16 |
| Entries per pool | 64 |
| Sum of every pool's maximum direct rolls | 64 |
| Nested table-reference levels | 8 |
| Worst-case emitted stacks after expanding nested references | 128 |
Worst-case output is validated instead of average output so every legal random result remains bounded. These limits apply equally when a table is consumed by a block, entity, or structure. Structure-only inventory controls are documented under structure inventory loot.
- Installation
- Install scripts
- Getting started
- VS Code and LuaLS
- Examples
- Reload and compatibility
- Troubleshooting
- Changelog
Scripts and shared values
- Script lifecycle
- Packaged Lua mods
- Modules
- References and stacks
- Queries
- Overrides
- Minecraft constants
- Chat and positions
- Structured data
- Script configuration
- Particles
Blocks and items
- Multiblocks
- Blocks
- Block state and placement
- Block shapes and rendering
- Block callbacks
- Block ticks and redstone
- Items
- Fluids
- Item callbacks
- Tools and armor
- Materials
- Textures
Entities
- Entities
- Entity access and movement
- Entity lifecycle and data
- Entity health and loot
- Entity inventories and relationships
- Projectiles and pickups
- Entity presentation and sounds
- Living entities and AI
- Entity parts and sensors
Assets and audio
- Assets
- Models and animations
- Built-in Minecraft models
- Model appearances
- Blockbench workflow
- Audio
- Texture-pack overrides
Events and world actions
World generation
World systems
Inventories and screens
Recipes