Implemented enchanced EntityLiving events. Thanks Atomic for parts of it.

This commit is contained in:
LexManos 2012-06-18 20:16:48 -07:00
parent 86d7b7b7b8
commit a7ea760097
13 changed files with 691 additions and 40 deletions

View file

@ -9,6 +9,7 @@ import net.minecraft.src.BaseMod;
import net.minecraft.src.Block;
import net.minecraft.src.Chunk;
import net.minecraft.src.ChunkCoordIntPair;
import net.minecraft.src.DamageSource;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityItem;
import net.minecraft.src.EntityLiving;
@ -341,6 +342,7 @@ public class ForgeHooks
}
static LinkedList<IFuelHandler> fuelHandlers = new LinkedList<IFuelHandler>();
@SuppressWarnings("deprecation") //Internal use only, I don't want to see these yet
public static boolean onEntitySpawnSpecial(EntityLiving entity, World world, float x, float y, float z)
{
for (ISpecialMobSpawnHandler handler : specialMobSpawnHandlers)
@ -352,8 +354,109 @@ public class ForgeHooks
}
return false;
}
@SuppressWarnings("deprecation")
static LinkedList<ISpecialMobSpawnHandler> specialMobSpawnHandlers = new LinkedList<ISpecialMobSpawnHandler>();
public static boolean onEntityLivingSpawn(EntityLiving entity, World world, float x, float y, float z)
{
for (IEntityLivingHandler handler : entityLivingHandlers)
{
if (handler.onEntityLivingSpawn(entity, world, x, y, z))
{
return true;
}
}
return false;
}
public static boolean onEntityLivingDeath(EntityLiving entity, DamageSource killer)
{
for (IEntityLivingHandler handler : entityLivingHandlers)
{
if (handler.onEntityLivingDeath(entity, killer))
{
return true;
}
}
return false;
}
public static boolean onEntityLivingUpdate(EntityLiving entity)
{
for (IEntityLivingHandler handler : entityLivingHandlers)
{
if (handler.onEntityLivingUpdate(entity))
{
return true;
}
}
return false;
}
public static void onEntityLivingJump(EntityLiving entity)
{
for (IEntityLivingHandler handler : entityLivingHandlers)
{
handler.onEntityLivingJump(entity);
}
}
public static boolean onEntityLivingFall(EntityLiving entity, float distance)
{
for (IEntityLivingHandler handler : entityLivingHandlers)
{
if (handler.onEntityLivingFall(entity, distance))
{
return true;
}
}
return false;
}
public static boolean onEntityLivingAttacked(EntityLiving entity, DamageSource attack, int damage)
{
for (IEntityLivingHandler handler : entityLivingHandlers)
{
if (handler.onEntityLivingAttacked(entity, attack, damage))
{
return true;
}
}
return false;
}
public static void onEntityLivingSetAttackTarget(EntityLiving entity, EntityLiving target)
{
for (IEntityLivingHandler handler : entityLivingHandlers)
{
handler.onEntityLivingSetAttackTarget(entity, target);
}
}
public static int onEntityLivingHurt(EntityLiving entity, DamageSource source, int damage)
{
for (IEntityLivingHandler handler : entityLivingHandlers)
{
damage = handler.onEntityLivingHurt(entity, source, damage);
if (damage == 0)
{
return 0;
}
}
return damage;
}
public static void onEntityLivingDrops(EntityLiving entity, DamageSource source, ArrayList<EntityItem> drops, int lootingLevel, boolean recentlyHit, int specialDropValue)
{
for (IEntityLivingHandler handler : entityLivingHandlers)
{
handler.onEntityLivingDrops(entity, source, drops, lootingLevel, recentlyHit, specialDropValue);
}
}
static LinkedList<IEntityLivingHandler> entityLivingHandlers = new LinkedList<IEntityLivingHandler>();
// Plant Management
// ------------------------------------------------------------
static class ProbableItem

View file

@ -0,0 +1,127 @@
/**
* This software is provided under the terms of the Minecraft Forge Public
* License v1.0.
*/
package net.minecraft.src.forge;
import java.util.ArrayList;
import net.minecraft.src.EntityItem;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.DamageSource;
import net.minecraft.src.World;
public interface IEntityLivingHandler
{
/**
* Raised when an EntityLiving is spawned into the world from natural means, meaning
* not by command, MobSpawner, cheat, etc.. Just naturally throughout the world.
*
* This allows the mod to create special functionality that runs on a mob natural
* spawn. The Vanilla minecraft mechanic of having 'Spider Jockies', the color of
* sheep's wool, and Ocelot's spawning with babies can be canceled by returning
* true from this function
*
* Returning true will indicate that you have performed your special spawning,
* and no more handling will be done.
*
* @param entity The newly spawned entity
* @param world The world the entity is in
* @param x The Entitie's X Position
* @param y The Entitie's Y Position
* @param z The Entitie's Z Position
* @return True if the event was handled and no more processing should be done, false to continue processing
*/
public boolean onEntityLivingSpawn(EntityLiving entity, World world, float x, float y, float z);
/**
* This is called when any EntityLiving's health reaches 0.
* You can cancel the death here, but you must raise the health or it will die again.
* In multiplayer, this is called by both the client and the server.
*
* @param entity Entity about to die
* @param killer DamageSource instance causing the death
* @return True to continue processing, false to cancel.
*/
public boolean onEntityLivingDeath(EntityLiving entity, DamageSource killer);
/**
* This is called immediately after an EntityLiving receives a new attack target from AI classes.
* eg when a Zombie 'spots' a player. Handles friendly fire (setRevengeTarget) as well.
* In multiplayer, this is called by the server only.
*
* @param entity Entity attacking
* @param target Entity designated as new target
*/
public void onEntityLivingSetAttackTarget(EntityLiving entity, EntityLiving target);
/**
* This is called when any EntityLiving takes damage from any DamageSource.
* In multiplayer, this is called by both the client and the server.
*
* @param entity Entity being attacked
* @param attack DamageSource instance of the attack
* @param damage Unmitigated damage the attack would cause
* @return True if the event was handled and no more processing should be done, false to continue processing
*/
public boolean onEntityLivingAttacked(EntityLiving entity, DamageSource attack, int damage);
/**
* This is called immediately after an EntityLiving started a jump
* Velocity will already be set and can be modified.
*
* @param entity Entity starting the jump
*/
public void onEntityLivingJump(EntityLiving entity);
/**
* This is called when an EntityLiving reconnects with the ground.
* Aborting this would stop both damage and the landing sound.
*
* @param entity Entity which fell
* @param distance absolute height between the last position touching the ground and the current.
* @return True if the event was handled and no more processing should be done, false to continue processing
*/
public boolean onEntityLivingFall(EntityLiving entity, float distance);
/**
* This is called before EntityLiving's Base Update Tick.
* Aborting this process will freeze both Movement and Actions.
*
* @param entity Entity being ticked
* @return True if the event was handled and no more processing should be done, false to continue processing
*/
public boolean onEntityLivingUpdate(EntityLiving entity);
/**
* This is called whenever a EntityLiving is hurt, before any armor calculations are taken into effect.
* Before any blocking, or potions are taken into account.
* Returning 0 from this will stop all processing.
* For the client's entity, this is only called in Single player, or if you are the server.
*
* @param entity The entity being hurt
* @param source The type of damage being dealt
* @param damage The amount of damage being dealt
* @return The amount of damage to let through. Returning 0 will prevent any further processing.
*/
public int onEntityLivingHurt(EntityLiving entity, DamageSource source, int damage);
/**
* This is called after a EntityLiving die, and it spawns it's loot. The drop list should contain any item that the entity spawned at death.
* May not work properly on all Mod entities if they do not use dropFewItems/dropRareDrop/entityDropItem
* This will not contain the special record that creepers drop when they are killed by a Skeleton, or the apple notch drops.
* Or the player's inventory.
*
* If you need to deal with the Player's inventory, do so in onEntityLivingDeath
* In most cases, drops will be empty if the entity was a baby that hadn't reached full size yet.
*
* @param entity The entity that is droping the items
* @param source The damage source that caused the entities death
* @param drops An ArrayList containing all items to drop, AYou must make sure to not cause any concurancy exceptions with this
* @param lootingLevel The Looting enchantment level if the attacker was a player and they had the enchantment, else 0
* @param recentlyHit Signifying if the entity was recently hit by a player.
* @param specialDropValue Random number used to determine if the 'special' loot should be dropped. 0 if the entity was a child
*/
public void onEntityLivingDrops(EntityLiving entity, DamageSource source, ArrayList<EntityItem> drops, int lootingLevel, boolean recentlyHit, int specialDropValue);
}

View file

@ -3,6 +3,7 @@ package net.minecraft.src.forge;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.World;
@Deprecated //See IEntityLivingHandler
public interface ISpecialMobSpawnHandler
{
/**

View file

@ -9,6 +9,7 @@ import net.minecraft.src.Achievement;
import net.minecraft.src.BaseMod;
import net.minecraft.src.Block;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.EntityMinecart;
import net.minecraft.src.Item;
import net.minecraft.src.ItemStack;
@ -159,11 +160,26 @@ public class MinecraftForge
* Register a new Special Mob Spawn handler
* @param handler The handler to be registered
*/
@Deprecated
public static void registerSpecialMobSpawnHandler(ISpecialMobSpawnHandler handler)
{
if (EntityLiving.class.getPackage() != null)
{
throw new RuntimeException("Still using deprecated method/interface MinecraftForge.registerSpecialModSpawnHandler()");
}
ForgeHooks.specialMobSpawnHandlers.add(handler);
}
/**
* Register a new EntityLiving Handler
* @param handler The handler to be registered
*/
public static void registerEnitityLivingHandler(IEntityLivingHandler handler)
{
ForgeHooks.entityLivingHandlers.add(handler);
}
/**
* This is not supposed to be called outside of Minecraft internals.
*/

View file

@ -0,0 +1,64 @@
package net.minecraft.src.forge.adaptors;
import java.util.ArrayList;
import net.minecraft.src.DamageSource;
import net.minecraft.src.EntityItem;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.World;
import net.minecraft.src.forge.IEntityLivingHandler;
public class EntityLivingHandlerAdaptor implements IEntityLivingHandler
{
@Override
public boolean onEntityLivingSpawn(EntityLiving entity, World world, float x, float y, float z)
{
return false;
}
@Override
public boolean onEntityLivingDeath(EntityLiving entity, DamageSource killer)
{
return false;
}
@Override
public void onEntityLivingSetAttackTarget(EntityLiving entity, EntityLiving target)
{
}
@Override
public boolean onEntityLivingAttacked(EntityLiving entity, DamageSource attack, int damage)
{
return false;
}
@Override
public void onEntityLivingJump(EntityLiving entity)
{
}
@Override
public boolean onEntityLivingFall(EntityLiving entity, float distance)
{
return false;
}
@Override
public boolean onEntityLivingUpdate(EntityLiving entity)
{
return false;
}
@Override
public int onEntityLivingHurt(EntityLiving entity, DamageSource source, int damage)
{
return damage;
}
@Override
public void onEntityLivingDrops(EntityLiving entity, DamageSource source, ArrayList<EntityItem> drops, int lootingLevel, boolean recentlyHit, int specialDropValue)
{
}
}

View file

@ -1,16 +1,25 @@
--- ../src_base/minecraft/net/minecraft/src/Entity.java 0000-00-00 00:00:00.000000000 -0000
+++ ../src_work/minecraft/net/minecraft/src/Entity.java 0000-00-00 00:00:00.000000000 -0000
@@ -173,6 +173,9 @@
@@ -1,5 +1,6 @@
package net.minecraft.src;
+import java.util.ArrayList;
import java.util.List;
import java.util.Random;
@@ -173,6 +174,11 @@
*/
public boolean ignoreFrustumCheck;
public boolean isAirBorne;
+
+ /** Forge: Used to store custom data for each entity. */
+ private NBTTagCompound customEntityData;
+ protected boolean captureDrops = false;
+ protected ArrayList<EntityItem> capturedDrops = new ArrayList<EntityItem>();
public Entity(World par1World)
{
@@ -214,6 +217,29 @@
@@ -214,6 +220,29 @@
}
protected abstract void entityInit();
@ -40,7 +49,7 @@
public DataWatcher getDataWatcher()
{
@@ -1318,6 +1344,10 @@
@@ -1318,6 +1347,10 @@
par1NBTTagCompound.setShort("Fire", (short)this.fire);
par1NBTTagCompound.setShort("Air", (short)this.getAir());
par1NBTTagCompound.setBoolean("OnGround", this.onGround);
@ -51,7 +60,7 @@
this.writeEntityToNBT(par1NBTTagCompound);
}
@@ -1359,6 +1389,10 @@
@@ -1359,6 +1392,10 @@
this.onGround = par1NBTTagCompound.getBoolean("OnGround");
this.setPosition(this.posX, this.posY, this.posZ);
this.setRotation(this.rotationYaw, this.rotationPitch);
@ -62,7 +71,23 @@
this.readEntityFromNBT(par1NBTTagCompound);
}
@@ -1717,7 +1751,7 @@
@@ -1444,7 +1481,14 @@
{
EntityItem var3 = new EntityItem(this.worldObj, this.posX, this.posY + (double)par2, this.posZ, par1ItemStack);
var3.delayBeforeCanPickup = 10;
- this.worldObj.spawnEntityInWorld(var3);
+ if (captureDrops)
+ {
+ capturedDrops.add(var3);
+ }
+ else
+ {
+ this.worldObj.spawnEntityInWorld(var3);
+ }
return var3;
}
@@ -1717,7 +1761,7 @@
*/
public boolean isRiding()
{

View file

@ -1,6 +1,15 @@
--- ../src_base/minecraft/net/minecraft/src/EntityLiving.java 0000-00-00 00:00:00.000000000 -0000
+++ ../src_work/minecraft/net/minecraft/src/EntityLiving.java 0000-00-00 00:00:00.000000000 -0000
@@ -59,7 +59,7 @@
@@ -6,6 +6,8 @@
import java.util.List;
import java.util.Random;
+import net.minecraft.src.forge.ForgeHooks;
+
public abstract class EntityLiving extends Entity
{
public int heartsHalvesLife = 20;
@@ -59,7 +61,7 @@
* in each step in the damage calculations, this is set to the 'carryover' that would result if someone was damaged
* .25 hearts (for example), and added to the damage in the next step
*/
@ -9,7 +18,119 @@
/** Number of ticks since this EntityLiving last produced its sound */
private int livingSoundTime;
@@ -1342,7 +1342,7 @@
@@ -303,6 +305,7 @@
public void setAttackTarget(EntityLiving par1EntityLiving)
{
this.attackTarget = par1EntityLiving;
+ ForgeHooks.onEntityLivingSetAttackTarget(this, par1EntityLiving);
}
public boolean func_48100_a(Class par1Class)
@@ -359,6 +362,7 @@
{
this.entityLivingToAttack = par1EntityLiving;
this.revengeTimer = this.entityLivingToAttack != null ? 60 : 0;
+ ForgeHooks.onEntityLivingSetAttackTarget(this, par1EntityLiving);
}
protected void entityInit()
@@ -641,7 +645,12 @@
* Called to update the entity's position/logic.
*/
public void onUpdate()
- {
+ {
+ if (ForgeHooks.onEntityLivingUpdate(this))
+ {
+ return;
+ }
+
super.onUpdate();
if (this.arrowHitTempCounter > 0)
@@ -834,6 +843,11 @@
*/
public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
{
+ if (ForgeHooks.onEntityLivingAttacked(this, par1DamageSource, par2))
+ {
+ return false;
+ }
+
if (this.worldObj.isRemote)
{
return false;
@@ -1012,6 +1026,12 @@
*/
protected void damageEntity(DamageSource par1DamageSource, int par2)
{
+ par2 = ForgeHooks.onEntityLivingHurt(this, par1DamageSource, par2);
+ if (par2 == 0)
+ {
+ return;
+ }
+
par2 = this.applyArmorCalculations(par1DamageSource, par2);
par2 = this.applyPotionDamageCalculations(par1DamageSource, par2);
this.health -= par2;
@@ -1075,6 +1095,11 @@
*/
public void onDeath(DamageSource par1DamageSource)
{
+ if (ForgeHooks.onEntityLivingDeath(this, par1DamageSource))
+ {
+ return;
+ }
+
Entity var2 = par1DamageSource.getEntity();
if (this.scoreValue >= 0 && var2 != null)
@@ -1098,13 +1123,17 @@
var3 = EnchantmentHelper.getLootingModifier(((EntityPlayer)var2).inventory);
}
+ captureDrops = true;
+ capturedDrops.clear();
+ int var4 = 0;
+
if (!this.isChild())
{
this.dropFewItems(this.recentlyHit > 0, var3);
if (this.recentlyHit > 0)
{
- int var4 = this.rand.nextInt(200) - var3;
+ var4 = this.rand.nextInt(200) - var3;
if (var4 < 5)
{
@@ -1112,6 +1141,13 @@
}
}
}
+
+ captureDrops = false;
+ ForgeHooks.onEntityLivingDrops(this, par1DamageSource, capturedDrops, var3, recentlyHit > 0, var4);
+ for (EntityItem item : capturedDrops)
+ {
+ worldObj.spawnEntityInWorld(item);
+ }
}
this.worldObj.setEntityState(this, (byte)3);
@@ -1155,6 +1191,11 @@
*/
protected void fall(float par1)
{
+ if (ForgeHooks.onEntityLivingFall(this, par1))
+ {
+ return;
+ }
+
super.fall(par1);
int var2 = (int)Math.ceil((double)(par1 - 3.0F));
@@ -1342,7 +1383,7 @@
int var2 = MathHelper.floor_double(this.boundingBox.minY);
int var3 = MathHelper.floor_double(this.posZ);
int var4 = this.worldObj.getBlockId(var1, var2, var3);
@ -17,4 +138,13 @@
+ return Block.blocksList[var4] != null && Block.blocksList[var4].isLadder(worldObj, var1, var2, var3);
}
/**
@@ -1613,6 +1654,8 @@
}
this.isAirBorne = true;
+
+ ForgeHooks.onEntityLivingJump(this);
}
/**

View file

@ -60,7 +60,18 @@
{
var3 = var2 + (float)(var4 * var4 + 1);
}
@@ -983,7 +1003,11 @@
@@ -978,12 +998,22 @@
*/
protected void damageEntity(DamageSource par1DamageSource, int par2)
{
+ par2 = ForgeHooks.onEntityLivingHurt(this, par1DamageSource, par2);
+ if (par2 == 0)
+ {
+ return;
+ }
+
if (!par1DamageSource.isUnblockable() && this.isBlocking())
{
par2 = 1 + par2 >> 1;
}
@ -73,7 +84,7 @@
par2 = this.applyPotionDamageCalculations(par1DamageSource, par2);
this.addExhaustion(par1DamageSource.getHungerDamage());
this.health -= par2;
@@ -1014,6 +1038,10 @@
@@ -1014,6 +1044,10 @@
*/
public void useCurrentItemOnEntity(Entity par1Entity)
{
@ -84,7 +95,7 @@
if (!par1Entity.interact(this))
{
ItemStack var2 = this.getCurrentEquippedItem();
@@ -1044,7 +1072,9 @@
@@ -1044,7 +1078,9 @@
*/
public void destroyCurrentEquippedItem()
{
@ -94,7 +105,7 @@
}
/**
@@ -1073,6 +1103,15 @@
@@ -1073,6 +1109,15 @@
*/
public void attackTargetEntityWithCurrentItem(Entity par1Entity)
{
@ -110,7 +121,7 @@
if (par1Entity.canAttackWithItem())
{
int var2 = this.inventory.getDamageVsEntity(par1Entity);
@@ -1215,6 +1254,12 @@
@@ -1215,6 +1260,12 @@
*/
public EnumStatus sleepInBedAt(int par1, int par2, int par3)
{
@ -123,7 +134,7 @@
if (!this.worldObj.isRemote)
{
if (this.isPlayerSleeping() || !this.isEntityAlive())
@@ -1254,6 +1299,11 @@
@@ -1254,6 +1305,11 @@
{
int var9 = this.worldObj.getBlockMetadata(par1, par2, par3);
int var5 = BlockBed.getDirection(var9);
@ -135,7 +146,7 @@
float var10 = 0.5F;
float var7 = 0.5F;
@@ -1323,11 +1373,12 @@
@@ -1323,11 +1379,12 @@
this.resetHeight();
ChunkCoordinates var4 = this.playerLocation;
ChunkCoordinates var5 = this.playerLocation;
@ -151,7 +162,7 @@
if (var5 == null)
{
@@ -1364,7 +1415,9 @@
@@ -1364,7 +1421,9 @@
*/
private boolean isInBed()
{
@ -162,7 +173,7 @@
}
/**
@@ -1379,13 +1432,15 @@
@@ -1379,13 +1438,15 @@
var2.loadChunk(par1ChunkCoordinates.posX - 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4);
var2.loadChunk(par1ChunkCoordinates.posX + 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4);
@ -180,7 +191,7 @@
return var3;
}
}
@@ -1397,8 +1452,11 @@
@@ -1397,8 +1458,11 @@
{
if (this.playerLocation != null)
{
@ -194,7 +205,7 @@
switch (var2)
{
@@ -1688,6 +1746,7 @@
@@ -1688,6 +1752,7 @@
return 101;
}
}
@ -202,7 +213,7 @@
}
return var3;
@@ -1860,4 +1919,30 @@
@@ -1860,4 +1925,30 @@
}
public void func_50009_aI() {}

View file

@ -28,11 +28,16 @@
}
}
@@ -211,6 +214,11 @@
@@ -211,6 +214,16 @@
*/
private static void creatureSpecificInit(EntityLiving par0EntityLiving, World par1World, float par2, float par3, float par4)
{
+ if (ForgeHooks.onEntitySpawnSpecial(par0EntityLiving, par1World, par2, par3, par4))
+ if (ForgeHooks.onEntitySpawnSpecial(par0EntityLiving, par1World, par2, par3, par4)) //Deprecated in 1.2.5, remove in 1.3
+ {
+ return;
+ }
+
+ if (ForgeHooks.onEntityLivingSpawn(par0EntityLiving, par1World, par2, par3, par4))
+ {
+ return;
+ }

View file

@ -1,16 +1,25 @@
--- ../src_base/minecraft_server/net/minecraft/src/Entity.java 0000-00-00 00:00:00.000000000 -0000
+++ ../src_work/minecraft_server/net/minecraft/src/Entity.java 0000-00-00 00:00:00.000000000 -0000
@@ -165,6 +165,9 @@
@@ -1,5 +1,6 @@
package net.minecraft.src;
+import java.util.ArrayList;
import java.util.List;
import java.util.Random;
@@ -165,6 +166,11 @@
public boolean ignoreFrustumCheck;
public boolean isAirBorne;
+ /** Forge: Used to store custom data for each entity. */
+ private NBTTagCompound customEntityData;
+ protected boolean captureDrops = false;
+ protected ArrayList<EntityItem> capturedDrops = new ArrayList<EntityItem>();
+
public Entity(World par1World)
{
this.entityId = nextEntityID++;
@@ -206,6 +209,29 @@
@@ -206,6 +212,29 @@
protected abstract void entityInit();
@ -40,7 +49,7 @@
public DataWatcher getDataWatcher()
{
return this.dataWatcher;
@@ -1215,6 +1241,10 @@
@@ -1215,6 +1244,10 @@
par1NBTTagCompound.setShort("Fire", (short)this.fire);
par1NBTTagCompound.setShort("Air", (short)this.getAir());
par1NBTTagCompound.setBoolean("OnGround", this.onGround);
@ -51,7 +60,7 @@
this.writeEntityToNBT(par1NBTTagCompound);
}
@@ -1256,6 +1286,10 @@
@@ -1256,6 +1289,10 @@
this.onGround = par1NBTTagCompound.getBoolean("OnGround");
this.setPosition(this.posX, this.posY, this.posZ);
this.setRotation(this.rotationYaw, this.rotationPitch);
@ -62,3 +71,19 @@
this.readEntityFromNBT(par1NBTTagCompound);
}
@@ -1336,7 +1373,14 @@
{
EntityItem var3 = new EntityItem(this.worldObj, this.posX, this.posY + (double)par2, this.posZ, par1ItemStack);
var3.delayBeforeCanPickup = 10;
- this.worldObj.spawnEntityInWorld(var3);
+ if (captureDrops)
+ {
+ capturedDrops.add(var3);
+ }
+ else
+ {
+ this.worldObj.spawnEntityInWorld(var3);
+ }
return var3;
}

View file

@ -1,6 +1,15 @@
--- ../src_base/minecraft_server/net/minecraft/src/EntityLiving.java 0000-00-00 00:00:00.000000000 -0000
+++ ../src_work/minecraft_server/net/minecraft/src/EntityLiving.java 0000-00-00 00:00:00.000000000 -0000
@@ -59,7 +59,7 @@
@@ -6,6 +6,8 @@
import java.util.List;
import java.util.Random;
+import net.minecraft.src.forge.ForgeHooks;
+
public abstract class EntityLiving extends Entity
{
public int heartsHalvesLife = 20;
@@ -59,7 +61,7 @@
* in each step in the damage calculations, this is set to the 'carryover' that would result if someone was damaged
* .25 hearts (for example), and added to the damage in the next step
*/
@ -9,7 +18,117 @@
/** Number of ticks since this EntityLiving last produced its sound */
private int livingSoundTime;
@@ -1307,7 +1307,7 @@
@@ -300,6 +302,7 @@
public void setAttackTarget(EntityLiving par1EntityLiving)
{
this.attackTarget = par1EntityLiving;
+ ForgeHooks.onEntityLivingSetAttackTarget(this, par1EntityLiving);
}
public boolean func_48336_a(Class par1Class)
@@ -356,6 +359,7 @@
{
this.entityLivingToAttack = par1EntityLiving;
this.revengeTimer = this.entityLivingToAttack != null ? 60 : 0;
+ ForgeHooks.onEntityLivingSetAttackTarget(this, par1EntityLiving);
}
protected void entityInit()
@@ -616,6 +620,11 @@
*/
public void onUpdate()
{
+ if (ForgeHooks.onEntityLivingUpdate(this))
+ {
+ return;
+ }
+
super.onUpdate();
if (this.arrowHitTempCounter > 0)
@@ -808,6 +817,11 @@
*/
public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
{
+ if (ForgeHooks.onEntityLivingAttacked(this, par1DamageSource, par2))
+ {
+ return false;
+ }
+
if (this.worldObj.isRemote)
{
return false;
@@ -977,6 +991,12 @@
*/
protected void damageEntity(DamageSource par1DamageSource, int par2)
{
+ par2 = ForgeHooks.onEntityLivingHurt(this, par1DamageSource, par2);
+ if (par2 == 0)
+ {
+ return;
+ }
+
par2 = this.applyArmorCalculations(par1DamageSource, par2);
par2 = this.applyPotionDamageCalculations(par1DamageSource, par2);
this.health -= par2;
@@ -1040,6 +1060,11 @@
*/
public void onDeath(DamageSource par1DamageSource)
{
+ if (ForgeHooks.onEntityLivingDeath(this, par1DamageSource))
+ {
+ return;
+ }
+
Entity var2 = par1DamageSource.getEntity();
if (this.scoreValue >= 0 && var2 != null)
@@ -1063,13 +1088,17 @@
var3 = EnchantmentHelper.getLootingModifier(((EntityPlayer)var2).inventory);
}
+ captureDrops = true;
+ capturedDrops.clear();
+ int var4 = 0;
+
if (!this.isChild())
{
this.dropFewItems(this.recentlyHit > 0, var3);
if (this.recentlyHit > 0)
{
- int var4 = this.rand.nextInt(200) - var3;
+ var4 = this.rand.nextInt(200) - var3;
if (var4 < 5)
{
@@ -1077,6 +1106,13 @@
}
}
}
+
+ captureDrops = false;
+ ForgeHooks.onEntityLivingDrops(this, par1DamageSource, capturedDrops, var3, recentlyHit > 0, var4);
+ for (EntityItem item : capturedDrops)
+ {
+ worldObj.spawnEntityInWorld(item);
+ }
}
this.worldObj.setEntityState(this, (byte)3);
@@ -1120,6 +1156,11 @@
*/
protected void fall(float par1)
{
+ if (ForgeHooks.onEntityLivingFall(this, par1))
+ {
+ return;
+ }
+
super.fall(par1);
int var2 = (int)Math.ceil((double)(par1 - 3.0F));
@@ -1307,7 +1348,7 @@
int var2 = MathHelper.floor_double(this.boundingBox.minY);
int var3 = MathHelper.floor_double(this.posZ);
int var4 = this.worldObj.getBlockId(var1, var2, var3);
@ -17,4 +136,13 @@
+ return (Block.blocksList[var4] != null && Block.blocksList[var4].isLadder(worldObj, var1, var2, var3));
}
/**
@@ -1578,6 +1619,8 @@
}
this.isAirBorne = true;
+
+ ForgeHooks.onEntityLivingJump(this);
}
/**

View file

@ -72,7 +72,18 @@
float var3 = var2;
int var4 = EnchantmentHelper.getEfficiencyModifier(this.inventory);
@@ -914,7 +944,11 @@
@@ -909,12 +939,22 @@
*/
protected void damageEntity(DamageSource par1DamageSource, int par2)
{
+ par2 = ForgeHooks.onEntityLivingHurt(this, par1DamageSource, par2);
+ if (par2 == 0)
+ {
+ return;
+ }
+
if (!par1DamageSource.isUnblockable() && this.isBlocking())
{
par2 = 1 + par2 >> 1;
}
@ -85,7 +96,7 @@
par2 = this.applyPotionDamageCalculations(par1DamageSource, par2);
this.addExhaustion(par1DamageSource.getHungerDamage());
this.health -= par2;
@@ -945,6 +979,10 @@
@@ -945,6 +985,10 @@
*/
public void useCurrentItemOnEntity(Entity par1Entity)
{
@ -96,7 +107,7 @@
if (!par1Entity.interact(this))
{
ItemStack var2 = this.getCurrentEquippedItem();
@@ -975,7 +1013,9 @@
@@ -975,7 +1019,9 @@
*/
public void destroyCurrentEquippedItem()
{
@ -106,7 +117,7 @@
}
/**
@@ -1004,6 +1044,16 @@
@@ -1004,6 +1050,16 @@
*/
public void attackTargetEntityWithCurrentItem(Entity par1Entity)
{
@ -123,7 +134,7 @@
if (par1Entity.canAttackWithItem())
{
int var2 = this.inventory.getDamageVsEntity(par1Entity);
@@ -1142,6 +1192,12 @@
@@ -1142,6 +1198,12 @@
*/
public EnumStatus sleepInBedAt(int par1, int par2, int par3)
{
@ -136,7 +147,7 @@
if (!this.worldObj.isRemote)
{
if (this.isPlayerSleeping() || !this.isEntityAlive())
@@ -1181,6 +1237,11 @@
@@ -1181,6 +1243,11 @@
{
int var9 = this.worldObj.getBlockMetadata(par1, par2, par3);
int var5 = BlockBed.getDirection(var9);
@ -148,7 +159,7 @@
float var10 = 0.5F;
float var7 = 0.5F;
@@ -1250,11 +1311,12 @@
@@ -1250,11 +1317,12 @@
this.resetHeight();
ChunkCoordinates var4 = this.playerLocation;
ChunkCoordinates var5 = this.playerLocation;
@ -164,7 +175,7 @@
if (var5 == null)
{
@@ -1291,7 +1353,9 @@
@@ -1291,7 +1359,9 @@
*/
private boolean isInBed()
{
@ -175,7 +186,7 @@
}
/**
@@ -1306,13 +1370,15 @@
@@ -1306,13 +1376,15 @@
var2.loadChunk(par1ChunkCoordinates.posX - 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4);
var2.loadChunk(par1ChunkCoordinates.posX + 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4);
@ -193,7 +204,7 @@
return var3;
}
}
@@ -1719,4 +1785,45 @@
@@ -1719,4 +1791,45 @@
}
public void func_50022_L() {}

View file

@ -28,11 +28,16 @@
}
}
@@ -211,6 +214,11 @@
@@ -211,6 +214,16 @@
*/
private static void creatureSpecificInit(EntityLiving par0EntityLiving, World par1World, float par2, float par3, float par4)
{
+ if (ForgeHooks.onEntitySpawnSpecial(par0EntityLiving, par1World, par2, par3, par4))
+ if (ForgeHooks.onEntitySpawnSpecial(par0EntityLiving, par1World, par2, par3, par4)) //Deprecated in 1.2.5, remove in 1.3
+ {
+ return;
+ }
+
+ if (ForgeHooks.onEntityLivingSpawn(par0EntityLiving, par1World, par2, par3, par4))
+ {
+ return;
+ }