Adding new Loots to existing Mobs
When adding new drops to a mob you will usually want to do this by adding a new entry to the appropriate loot table. Loot tables can be altered through the LootTableLoadEvent in forge. This event is very straight forward and allows for some cool stuff. The first thing you need to do is decide which table you want to edit. The event is fired for every loot table, so need to check if the name of the table is correct. In this tutorial I will be adding new drops to the pig, so I will be checking for the pig's drop table.
@SubscribeEvent public void onLootTablesLoaded(LootTableLoadEvent event) { if (event.getName().equals(LootTableList.ENTITIES_PIG)) { } }
Now that the check is in place, you can be confident that you will only be editing the table you need. The next step is to figure out which loot pool you want to edit. Some mobs have multiple pools, however the majority only have one which is called main. A dump of all vanilla loot table data can be found here. You can use the vanilla data to verify which table you want to edit. Other mods can delete pools so it is always a good idea to check that the pool exists before editing it.
@SubscribeEvent public void onLootTablesLoaded (LootTableLoadEvent event) { if (event.getName().equals(LootTableList.ENTITIES_PIG)) { final LootPool main = event.getTable().getPool("main"); if (main != null) { } } }
Now that we have the pool and we are confident it exists, we can begin adding new entries to it. In this example I will be allowing for pigs to drop carrots just as often as they drop pork chops. Loot pools use a weighted system, so entries with higher weight values tend to be selected more. Vanilla sets the drop rate of pork chops to 1, so if we also use 1 for our new entry both will be equally likely.
@SubscribeEvent public void onLootTablesLoaded (LootTableLoadEvent event) { if (event.getName().equals(LootTableList.ENTITIES_PIG)) { final LootPool main = event.getTable().getPool("main"); if (main != null) { // pool2.addEntry(new LootEntryItem(ITEM, WEIGHT, QUALITY, FUNCTIONS, CONDITIONS, NAME)); main.addEntry(new LootEntryItem(Items.CARROT, 1, 0, new LootFunction[0], new LootCondition[0], "tutorial:carrot")); } } }
At this point you don't need to do anything else for your code to work, however you may be looking for something a bit more nuance. If you want the item dropped to have be in a stack, have a different meta data value, have custom nbt, or anything other than normal, you will want to add new entries to the LootFunction array. A LootFunction is a class from Minecraft that allows you to modify the item via code. Vanilla already provides functions such as SetCount which sets the amount in a stack, SetMetadata which sets the meta value of the stack and SetNBT which sets the NBT data of the stack. There are also others such as Smelt which smelts the item, and EnchantRandomly which applies enchantments to the item. In the example below I change it to allow the pig to drop one to three carrots in a stack.
@SubscribeEvent public void onLootTablesLoaded (LootTableLoadEvent event) { if (event.getName().equals(LootTableList.ENTITIES_PIG)) { final LootPool main = event.getTable().getPool("main"); if (main != null) { // pool2.addEntry(new LootEntryItem(ITEM, WEIGHT, QUALITY, FUNCTIONS, CONDITIONS, NAME)); main.addEntry(new LootEntryItem(Items.CARROT, 1, 0, new LootFunction[] {new SetCount(new LootCondition[0], new RandomValueRange(1,3))}, new LootCondition[0], "tutorial:carrot")); } } }
In addition to LootFunction there is also something called a LootCondition. A LootCondition allows for a check to be made, and if that check fails the item entry can not be selected. Vanilla offers some basic conditions such as KilledByPlayer which can be used to restrict a drop to when a player kills the mob, or RandomChance which is a random roll of the dice. You can add conditions to the drop entry itself and also on functions. For example, vanilla uses the EntityHasProperty condition to apply the Smelt function to the items when the mob dies while on fire. In the example below I restrict the new carrot drop to when a player kills the pig.
@SubscribeEvent public void onLootTablesLoaded (LootTableLoadEvent event) { if (event.getName().equals(LootTableList.ENTITIES_PIG)) { final LootPool main = event.getTable().getPool("main"); if (main != null) { // pool2.addEntry(new LootEntryItem(ITEM, WEIGHT, QUALITY, FUNCTIONS, CONDITIONS, NAME)); main.addEntry(new LootEntryItem(Items.CARROT, 1, 0, new LootFunction[0], new LootCondition[] { new KilledByPlayer(false)}, "tutorial:carrot")); } } }