From 2a76f7740e85beba4f753d3cc773c4c3e73c4a22 Mon Sep 17 00:00:00 2001 From: Mithion Date: Fri, 22 Mar 2013 15:04:00 -0400 Subject: [PATCH] Entity Extended Properties Changes Adds IExtendedEntityProperties interface, which specifies three methods that are needed: Init, Save, and Load. Adds the EntityConstructing event, which is called during the constructor of Entity. It is needed there so that the reference is in place during the ReadNBT call. Adds hooks into Entity that allow registration of IExtendedEntityProperties classes, as well as saving and loading to NBT. --- .../common/IExtendedEntityProperties.java | 31 +++++ .../event/entity/EntityEvent.java | 8 ++ .../net/minecraft/entity/Entity.java.patch | 112 ++++++++++++++++-- 3 files changed, 140 insertions(+), 11 deletions(-) create mode 100644 common/net/minecraftforge/common/IExtendedEntityProperties.java diff --git a/common/net/minecraftforge/common/IExtendedEntityProperties.java b/common/net/minecraftforge/common/IExtendedEntityProperties.java new file mode 100644 index 0000000000..d3f5586f5d --- /dev/null +++ b/common/net/minecraftforge/common/IExtendedEntityProperties.java @@ -0,0 +1,31 @@ +package net.minecraftforge.common; + +import net.minecraft.entity.Entity; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; + +public interface IExtendedEntityProperties { + /** + * Called when the entity that this class is attached to is saved. + * Any custom entity data that needs saving should be saved here. + * @param compound The compound to save to. + */ + public void saveNBTData(NBTTagCompound compound); + + /** + * Called when the entity that this class is attached to is loaded. + * In order to hook into this, you will need to subscribe to the EntityConstructing event. + * Otherwise, you will need to initialize manually. + * @param compound The compound to load from. + */ + public void loadNBTData(NBTTagCompound compound); + + /** + * Used to initialize the extended properties with the entity that this is attached to, as well + * as the world object. + * Called automatically if you register with the EntityConstructing event. + * @param entity The entity that this extended properties is attached to + * @param world The world in which the entity exists + */ + public void init(Entity entity, World world); +} diff --git a/common/net/minecraftforge/event/entity/EntityEvent.java b/common/net/minecraftforge/event/entity/EntityEvent.java index 318c16d422..f7d287dd43 100644 --- a/common/net/minecraftforge/event/entity/EntityEvent.java +++ b/common/net/minecraftforge/event/entity/EntityEvent.java @@ -1,6 +1,7 @@ package net.minecraftforge.event.entity; import net.minecraft.entity.Entity; +import net.minecraft.world.World; import net.minecraftforge.event.Event; public class EntityEvent extends Event @@ -11,6 +12,13 @@ public class EntityEvent extends Event { this.entity = entity; } + + public static class EntityConstructing extends EntityEvent + { + public EntityConstructing(Entity entity){ + super(entity); + } + } public static class CanUpdate extends EntityEvent { diff --git a/patches/minecraft/net/minecraft/entity/Entity.java.patch b/patches/minecraft/net/minecraft/entity/Entity.java.patch index 320de7e312..e427ccf8e1 100644 --- a/patches/minecraft/net/minecraft/entity/Entity.java.patch +++ b/patches/minecraft/net/minecraft/entity/Entity.java.patch @@ -1,14 +1,17 @@ --- ../src_base/minecraft/net/minecraft/entity/Entity.java +++ ../src_work/minecraft/net/minecraft/entity/Entity.java -@@ -2,6 +2,7 @@ +@@ -1,7 +1,10 @@ + package net.minecraft.entity; ++import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import java.util.ArrayList; ++import java.util.HashMap; import java.util.List; import java.util.Random; import java.util.UUID; -@@ -13,8 +14,13 @@ +@@ -13,8 +16,13 @@ import net.minecraft.crash.CrashReportCategory; import net.minecraft.enchantment.EnchantmentProtection; import net.minecraft.entity.effect.EntityLightningBolt; @@ -22,7 +25,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagDouble; -@@ -25,6 +31,7 @@ +@@ -25,12 +33,16 @@ import net.minecraft.util.DamageSource; import net.minecraft.util.Direction; import net.minecraft.util.MathHelper; @@ -30,7 +33,16 @@ import net.minecraft.util.ReportedException; import net.minecraft.util.StatCollector; import net.minecraft.util.Vec3; -@@ -225,6 +232,11 @@ + import net.minecraft.world.Explosion; + import net.minecraft.world.World; + import net.minecraft.world.WorldServer; ++import net.minecraftforge.common.IExtendedEntityProperties; ++import net.minecraftforge.common.MinecraftForge; ++import net.minecraftforge.event.entity.EntityEvent; + + public abstract class Entity + { +@@ -225,6 +237,13 @@ private boolean invulnerable; private UUID entityUniqueID; public EnumEntitySize myEntitySize; @@ -39,10 +51,27 @@ + public boolean captureDrops = false; + public ArrayList capturedDrops = new ArrayList(); + private UUID persistentID; ++ ++ private HashMap extendedProperties; public Entity(World par1World) { -@@ -554,7 +566,7 @@ +@@ -274,6 +293,14 @@ + this.dataWatcher.addObject(0, Byte.valueOf((byte)0)); + this.dataWatcher.addObject(1, Short.valueOf((short)300)); + this.entityInit(); ++ ++ extendedProperties = new HashMap(); ++ ++ MinecraftForge.EVENT_BUS.post(new EntityEvent.EntityConstructing(this)); ++ ++ for (IExtendedEntityProperties props : this.extendedProperties.values()){ ++ props.init(this, par1World); ++ } + } + + protected abstract void entityInit(); +@@ -554,7 +581,7 @@ if (!this.worldObj.isRemote) { this.setFlag(0, this.fire > 0); @@ -51,7 +80,7 @@ } this.firstUpdate = false; -@@ -1534,6 +1546,10 @@ +@@ -1534,6 +1561,21 @@ par1NBTTagCompound.setInteger("PortalCooldown", this.timeUntilPortal); par1NBTTagCompound.setLong("UUIDMost", this.entityUniqueID.getMostSignificantBits()); par1NBTTagCompound.setLong("UUIDLeast", this.entityUniqueID.getLeastSignificantBits()); @@ -59,10 +88,21 @@ + { + par1NBTTagCompound.setCompoundTag("ForgeData", customEntityData); + } ++ ++ for (String identifier : this.extendedProperties.keySet()){ ++ try{ ++ IExtendedEntityProperties props = this.extendedProperties.get(identifier); ++ props.saveNBTData(par1NBTTagCompound); ++ }catch (Throwable t){ ++ FMLLog.severe("Failed to save extended properties for %s. This is a mod issue.", identifier); ++ t.printStackTrace(); ++ } ++ } ++ this.writeEntityToNBT(par1NBTTagCompound); if (this.ridingEntity != null) -@@ -1604,6 +1620,15 @@ +@@ -1604,6 +1646,26 @@ this.setPosition(this.posX, this.posY, this.posZ); this.setRotation(this.rotationYaw, this.rotationPitch); @@ -70,6 +110,17 @@ + { + customEntityData = par1NBTTagCompound.getCompoundTag("ForgeData"); + } ++ ++ for (String identifier : this.extendedProperties.keySet()){ ++ try{ ++ IExtendedEntityProperties props = this.extendedProperties.get(identifier); ++ props.loadNBTData(par1NBTTagCompound); ++ }catch (Throwable t){ ++ FMLLog.severe("Failed to load extended properties for %s. This is a mod issue.", identifier); ++ t.printStackTrace(); ++ } ++ } ++ + //Rawr, legacy code, Vanilla added a UUID, keep this so older maps will convert properly + if (par1NBTTagCompound.hasKey("PersistentIDMSB") && par1NBTTagCompound.hasKey("PersistentIDLSB")) + { @@ -78,7 +129,7 @@ this.readEntityFromNBT(par1NBTTagCompound); } catch (Throwable throwable) -@@ -1698,7 +1723,14 @@ +@@ -1698,7 +1760,14 @@ { EntityItem entityitem = new EntityItem(this.worldObj, this.posX, this.posY + (double)par2, this.posZ, par1ItemStack); entityitem.delayBeforeCanPickup = 10; @@ -94,7 +145,7 @@ return entityitem; } -@@ -2056,7 +2088,7 @@ +@@ -2056,7 +2125,7 @@ */ public boolean isRiding() { @@ -103,7 +154,7 @@ } /** -@@ -2400,7 +2432,7 @@ +@@ -2400,7 +2469,7 @@ public float func_82146_a(Explosion par1Explosion, World par2World, int par3, int par4, int par5, Block par6Block) { @@ -112,7 +163,7 @@ } public boolean func_96091_a(Explosion par1Explosion, World par2World, int par3, int par4, int par5, int par6, float par7) -@@ -2455,4 +2487,100 @@ +@@ -2455,4 +2524,139 @@ { return this.getEntityName(); } @@ -211,5 +262,44 @@ + public boolean isCreatureType(EnumCreatureType type, boolean forSpawnCount) + { + return type.getCreatureClass().isAssignableFrom(this.getClass()); ++ } ++ ++ /** ++ * Register the instance of IExtendedProperties into the entity's collection. ++ * @param identifier The identifier which you can use to retrieve these properties for the entity. ++ * @param properties The instanceof IExtendedProperties to register ++ * @return The identifier that was used to register the extended properties. Empty String indicates an error. If your requested key already existed, this will return a modified one that is unique. ++ */ ++ public String registerExtendedProperties(String identifier, IExtendedEntityProperties properties){ ++ if (identifier == null){ ++ FMLLog.warning("Someone is attempting to register extended properties using a null identifier. This is not allowed. Aborting. This may have caused instability."); ++ return ""; ++ } ++ if (properties == null){ ++ FMLLog.warning("Someone is attempting to register null extended properties. This is not allowed. Aborting. This may have caused instability."); ++ return ""; ++ } ++ ++ String baseIdentifier = identifier; ++ int identifierModCount = 1; ++ while (this.extendedProperties.containsKey(identifier)){ ++ identifier = String.format("%s%d", baseIdentifier, identifierModCount); ++ } ++ ++ if (baseIdentifier != identifier){ ++ FMLLog.info("An attempt was made to register exended properties using an existing key. The duplicate identifier (%s) has been remapped to %s.", baseIdentifier, identifier); ++ } ++ ++ this.extendedProperties.put(identifier, properties); ++ return identifier; ++ } ++ ++ /** ++ * Gets the extended properties identified by the passed in key ++ * @param identifier The key that identifies the extended properties. ++ * @return The instance of IExtendedProperties that was found, or null. ++ */ ++ public IExtendedEntityProperties getExtendedProperties(String identifier){ ++ return this.extendedProperties.get(identifier); + } }