How to add an Item to dungeon loot or other chests
To add an item to a LootTable you have to use the new LootTableLoadEvent. This event is actually very straight forward, and allows for some seriously cool things. The first thing you need to do after you have the basic event set up, is to decide what loot table you want to edit. Because the event is fired for every single loot table, you need to check if the name of the loot table is the right one. For this section of the tutorial we will be editing minecraft:chests/simple_dungeon which is the loot table for the basic monster spawner dungeons. If you plan to edit a different table, you can look at the LootTableList class from vanilla which gives you all the vanilla table names.
@SubscribeEvent public void onLootTablesLoaded(LootTableLoadEvent event) { if (event.getName().equals(LootTableList.CHESTS_SIMPLE_DUNGEON)) { } }
Now that we have this check in place, we can be confident that the table we are about to edit is the right one. The next step is to figure out which pool you are going to edit, some tables such as the simple dungeon have multiple pools where each pool represents a different tier of loot. pool2 is used for common loot like gunpowder or rotten flesh, pool1 is used for uncommon loot like redstone or buckets and main is used for the rare loot such as name tags or horse armor. Each table has different pools and uses them in different ways, so you may have to do some research into the pool before editing it. A full list of the vanilla loot table data can be found here. For this example I will be editing pool2 which is the common pool. It is possible for other mods to delete pools, so make sure the pool exists before editing it!
@SubscribeEvent public void onLootTablesLoaded(LootTableLoadEvent event) { if (event.getName().equals(LootTableList.CHESTS_SIMPLE_DUNGEON)) { final LootPool pool2 = event.getTable().getPool("pool2"); if (pool2 != null) { } } }
At this point we can be fairly confident that pool2 is still there, and we can begin editing it. For this example we will be adding in cookies as an example loot item. To do this, we must create a new LootEntryItem instance. LootEntryItem requires a few pieces of information, the first is the item to add. The second piece of information is the weight for the entry. In a weighted system, entries with higher weights have a higher likelihood to be selected. The vanilla pool has four entries, each with 10 for their weight. In this example I will also be using 10. The third value is the quality of the entry, this is used as a modifier to increase or decrease the odds of the entry, almost everything uses 0 for this. The fourth and fifth values are for functions and conditions, which we will be temporarily ignoring, you can safely pass empty arrays for both. The final variable is the name for your entry. The convention for entry names is the mod id followed by a colon (:) and then a relevant name that uses snake case. (Snake case is when words are separated using an _). For this example I will be using loottable:cookie as my name.
@SubscribeEvent public void onLootTablesLoaded(LootTableLoadEvent event) { if (event.getName().equals(LootTableList.CHESTS_SIMPLE_DUNGEON)) { final LootPool pool2 = event.getTable().getPool("pool2"); if (pool2 != null) { // pool2.addEntry(new LootEntryItem(ITEM, WEIGHT, QUALITY, FUNCTIONS, CONDITIONS, NAME)); pool2.addEntry(new LootEntryItem(Items.COOKIE, 10, 0, new LootFunction[0], new LootCondition[0], "loottable:cookie")); } } }
And that's it. Now there is a chance that a single cookie will spawn in a dungeon chest. But what if we want to use an item with metadata, or give more than one item? This is where loot functions come in. A loot function is a bit of code that is applied to the item when the entry is selected. Vanilla provides some nice functions in the net.minecraft.world.storage.loot.functions package, and you can write your own if you can't find what you need. You can replace the empty LootFunction array from before with a new one that contains the functions you want to apply. For example, you can create a new instance of SetCount to increase the stack size of the item. The parameters for SetCount are a LootCondition array, which we will be ignoring for now, just use an empty one. The second parameter is a RandomValueRange object, which is constructed using a min float and a max float. The RandomValueRange object is used to get the stack size for the item. In the next code snip I change it so cookies will spawn in a stack of 1 to 5.
@SubscribeEvent public void onLootTablesLoaded(LootTableLoadEvent event) { if (event.getName().equals(LootTableList.CHESTS_SIMPLE_DUNGEON)) { final LootPool pool2 = event.getTable().getPool("pool2"); if (pool2 != null) { // pool2.addEntry(new LootEntryItem(ITEM, WEIGHT, QUALITY, FUNCTIONS, CONDITIONS, NAME)); pool2.addEntry(new LootEntryItem(Items.COOKIE, 10, 0, new LootFunction[] {new SetCount(new LootCondition[0], new RandomValueRange(1, 5))}, new LootCondition[0], "loottable:cookie")); } } }
So what about metadata then? There is another function called SetDamage which allows you to set the metadata value of the item. Since cookies don't use metadata, this next example will use lime green dye, which has a meta value of 10. The constructor for SetDamage is the same as SetCount. The key difference is that the RandomValueRange for this one sets the meta of the itemstack instead of the count. We could use 0 and 16 to let it randomly chose a dye, however we want specifically lime green dye so we use 10 for both.
@SubscribeEvent public void onLootTablesLoaded(LootTableLoadEvent event) { if (event.getName().equals(LootTableList.CHESTS_SIMPLE_DUNGEON)) { final LootPool pool2 = event.getTable().getPool("pool2"); if (pool2 != null) { // pool2.addEntry(new LootEntryItem(ITEM, WEIGHT, QUALITY, FUNCTIONS, CONDITIONS, NAME)); pool2.addEntry(new LootEntryItem(Items.DYE, 10, 0, new LootFunction[] {new SetDamage(new LootCondition[0], new RandomValueRange(10, 10))}, new LootCondition[0], "loottable:dyes")); } } }
And that's basically everything you need to know to add dungeon loot. As for the LootCondition arrays that we have been ignoring, they allow you to add specific conditional requirements to the entry to be selected. This is not really useful for dungeon loot, however it can be useful when it comes to adding in more mob drops. Since it is also possible to add your own conditions, you may be able to create some cool things with them. I cover them in more detail in my tutorial on adding loot to existing mobs.