Minecraft Modding: Changing Drops For Vanilla Entities

Introduction


It seems to be a common interest to change the drops from vanilla entities.  This tutorial explains how to do this.

How Drops Are Controlled In the Code


The good news is that the drops list is a public ArrayList (of items) field in the Entity class and so it can be directly access and modified like any ArrayList.  The field is called capturedDrops.

However, it is not a static field or in a registry and so every instance of an Entity has its own capturedDrops list. So to modify all of an certain entity type, you'll have to ensure that you modify the capturedDrops for each entity instance.

At What Point Should You Change The Drops


If we want to change the drops list we need to find the appropriate event -- something that occurs after the entity has its capturedDrops list populated:
  • The EntityConstructing event isn't a good place for changing the drops because the drops assignment seems to happen after the constructor.  
  • The LivingSpawnEvent is also not a good choice because that can fire before the spawn even happens whether an entity instance is constructed or not.
In fact, the way the the capturedDrops list gets populated is a little bit complex -- because some entities may have a dynamic inventory, the drops list is calculated at the time that the drop occurs (usually entity death/break).  So the only place you should really modify the drops is in the LivingDropsEvent. I know that seems sort of obvious, but I think it is worthwhile to also understand what doesn't work and why.

Note: If you want to inspect the code where the vanilla drops list is populated, it is in the entityDropItem() method in the Entity class (and therefore inherited by all entities in the game), or in an overridden subclass.

Key point: The captureDrops list is populated at the time a drop happens (just before the LivingDropsEvent), so shouldn't be modified earlier.

Handle LivingDropsEvent To Change The Drops


The capturedDrops list is passed as the event.drops field in the LivingDropsEvent.

The drops field is an ArrayList of Item class elements so (like any ArrayList) you can easily clear() it, remove() items, and add() items or use any other regular methods for modifying an ArrayList.

Tip: The LivingDropsEvent has a lootingLevel field that can be used to change drops based on looting bonus.  You can check the value of this field and drop different amounts or different items.

Example 1: Clear All Drops For EntitySheep


Create an event handler for the LivingDropsEvent.  Basically you need a class containing the method example below that is registered to the EVENT_BUS.  To set that up see my tutorial on events: Jabelar's Event Handling Tutorial.  

The event handling method should contain something like this:

@SubscribeEvent(priority=EventPriority.NORMAL, receiveCanceled=true)
public void onEvent(LivingDropsEvent event)
{
    if (event.entity instanceof EntitySheep)
    {
        // DEBUG
        System.out.println("EntitySheep drops event");
        event.drops.clear();
    }
} 

It is that simple.  Just clear the list and that will remove the drops.

Example 2: Change Drop For EntitySheep To Be 5 Apples


In this case, the event handling method should just add items after clearing it.

@SubscribeEvent(priority=EventPriority.NORMAL, receiveCanceled=true)
public void onEvent(LivingDropsEvent event)
{
    if (event.entity instanceof EntitySheep)
    {
        // DEBUG
        System.out.println("EntitySheep drops event");
        event.drops.clear();
        ItemStack itemStackToDrop = new ItemStack(Items.apple, 5);
        event.drops.add(new EntityItem(event.entity.worldObj, event.entity.posX, 
              event.entity.posY, event.entity.posZ, itemStackToDrop));
    }
} 

Conclusion


Events make it easy to intercept vanilla actions and modify them.  To modify drops for vanilla entities, the LivingDropsEvent provides the right hook.  The drops field in that event is simply an ArrayList that can be modified like any other.  Have fun!

As always, if you see have any suggestions for corrections or clarifications to this tutorial let me know!

8 comments:

  1. How would you make it work with rare drops ?

    ReplyDelete
  2. How do you make it so the vanilla mom drops your own costom item from your mod?

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
    2. You do it the same as mentioned above in the tutorial, but instead of Items.apple you put a reference to an instance of your item. (Of course you have to make sure your item is working properly, registered and stuff).

      Delete
  3. Do i have to make another class to paste it in or just put in my mainregistry?

    ReplyDelete
  4. "entity" cannot be resolved or is not a field. Same for "drops"

    ReplyDelete