Minecraft Modding: IExtendedEntityProperties

Background


In 1.8 and earlier, if you wanted to add extra information to an Entity it was recommended to use the IExtendedEntityProperties interface. This tutorial explains how to do that.

In 1.9+ this interface was no longer available and instead the Capability interface was implemented. See Jabelar's Capability Modding Tips.

The IExtendedEntityProperties Approach


You may want to check out CoolAlias' tutorial on this subject, as he has interesting example where he uses it to add custom properties to the EntityPlayer.

To summarize, you use IExtendedEntityProperties if: 
  • You want to add data to a vanilla entity, and
  • The data may change during the game.
Warning: If you're using IEEP for players, be aware that every time a player re-spawns or travels to another dimension, technically it is a new instance of the player object. (The UUID will remain the same, but that isn't relevant to IEEP.) So it means that the loading of the IEEP won't persist if the player re-spawns or changes dimension. To solve this (thanks to coolalias for this tip):
  • Subscribe to PlayerEvent.Clone and copy the IEEP data to the new player instance's IEEP.
  • There should also be a class field from the event that tells you whether the player died or is simply re-spawning due to dimensional travel.
There are two steps to using IExtendedEntityProperties:
  1. Create a class that implements the interface.
  2. Register the class in your onEntityConstructing event handler.

Step 1. Create A Class That Implements IExtendedEntityProperties


In that class, create protected fields for the entity and the world. Eclipse should give you a warning about unimplemented methods, so accept its suggested fix to create those methods for your.
In the init() method copy the entity and world parameters to the associated fields. In the saveNBTData() method, use the compound.setxxx() type methods (where xxx should be replaced with the data type) to take each entity field getter and store it in NBT tag of similar name. In the loadNBTData() method, use the entity’s setter methods and grab the compound.getxxx() methods (where xxx should be replaced with the data type) to retrieve each tagged data.

Example:

public class ExtendedPropertiesHerdAnimal implements IExtendedEntityProperties
{
    public final static String extendedPropertiesName = "extendedPropertiesWildAnimal";
    protected EntityHerdAnimal theEntity;
    protected World theWorld;

    @Override
    public void saveNBTData(NBTTagCompound parCompound)
    {
       // DEBUG
       System.out.println("ExtendedPropertiesHerdAnimal saveNBTData()");

       // good idea to keep your extended properties in a sub-compound to 
       // avoid conflicts with other possible extended properties,
       // even from other mods (like if a mod extends all EntityAnimal)

        NBTTagCompound compound = new NBTTagCompound();
        parCompound.setTag(extendedPropertiesName, compound); // set as a sub-compound
        compound.setFloat("scaleFactor", theEntity.getScaleFactor())
        compound.setInteger("rearingCounter", theEntity.getRearingCounter());
        compound.setInteger("rearingTicksMax", theEntity.getRearingTicksMax());
        compound.setBoolean("isRearing", theEntity.isRearing());
    }

@Override
    public void loadNBTData(NBTTagCompound parCompound)
{
        // DEBUG
        System.out.println("ExtendedPropertiesHerdAnimal loadNBTData()");

        // Get the sub-compound
        NBTTagCompound compound = (NBTTagCompound) 
        parCompound.getTag(extendedPropertiesName);

        theEntity.setScaleFactor(compound.getFloat("scaleFactor"));
        theEntity.setRearingCounter(compound.getInteger("rearingCounter"));
        theEntity.setRearingTicksMax(compound.getInteger("rearingTicksMax"));
        theEntity.setRearing(compound.getBoolean("isRearing"));
   }

   @Override
   public void init(Entity entity, World world)
   {
        // DEBUG
        System.out.println("ExtendedPropertiesHerdAnimal init()");
        theEntity = (EntityElephant)entity;
        theWorld = world;
    }
}

Step 2. Register Entity Extended Properties


To ensure that the extended properties are activated, you need to register them.  In your mod’s custom event handler class (the one that is subscribed to the EVENT_BUS) subscribe to the onEntityConstructing() event.

Inside the method subscribed to the event, for each entity that you want to have extended properties check that the entity is of the type you want to register, then register the associated extended properties class.

Example:

@SubscribeEvent
public void onEntityConstructing(EntityConstructing event)
{
    // Register extended entity properties
    // Herd animals

    if (event.entity instanceof EntityHorse)
    {
        // DEBUG
        System.out.println("OnEntityConstructing register EntityHorse
              extended properties");

         event.entity.registerExtendedProperties("ExtendedPropertiesHerdAnimal", 
               new ExtendedPropertiesHerdAnimal());
         }
    }
}

No comments:

Post a Comment