Posted March 31, 201411 yr (Forge version = 1047) [updated subject to be more specific] Okay, so I have created an EntityTiger that is essentially a re-textured vanilla wolf, and it works perfectly (basically behaves like a wolf in that it is passive unless attacked, can be tamed, hunts sheep on its own, etc.) I want to make a sub-class EntityManEatingTiger which extends EntityTiger but basically is always hostile and will attack a player on sight. I thought I could do this by setAngry(true) and setting target to the player (I realize this isn't really good practice for multiplayer, but will fix that later). I also have setTamed(false). So I have an untamed, angry tiger with player as the target. It does in fact look angry (red eyes texture), and it follows my player and leaps at it just like it is attacking me. However, it doesn't actually do any damage (not a real attack). If I hit it though, then it will attack me for real. So I'm missing something -- how do you make it actually attack rather than follow me with red eyes? Here are the two classes. EntityTiger package wildanimals.entities; import net.minecraft.block.Block; import net.minecraft.block.BlockColored; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityAgeable; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.EntityAIAttackOnCollide; import net.minecraft.entity.ai.EntityAIBase; import net.minecraft.entity.ai.EntityAIFollowOwner; import net.minecraft.entity.ai.EntityAIHurtByTarget; import net.minecraft.entity.ai.EntityAILeapAtTarget; import net.minecraft.entity.ai.EntityAILookIdle; import net.minecraft.entity.ai.EntityAIMate; import net.minecraft.entity.ai.EntityAIOwnerHurtByTarget; import net.minecraft.entity.ai.EntityAIOwnerHurtTarget; import net.minecraft.entity.ai.EntityAISwimming; import net.minecraft.entity.ai.EntityAITargetNonTamed; import net.minecraft.entity.ai.EntityAIWander; import net.minecraft.entity.ai.EntityAIWatchClosest; import net.minecraft.entity.monster.EntityCreeper; import net.minecraft.entity.monster.EntityGhast; import net.minecraft.entity.passive.EntityAnimal; import net.minecraft.entity.passive.EntityHorse; import net.minecraft.entity.passive.EntitySheep; import net.minecraft.entity.passive.EntityTameable; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.projectile.EntityArrow; import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemFood; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.pathfinding.PathEntity; import net.minecraft.util.DamageSource; import net.minecraft.util.MathHelper; import net.minecraft.world.World; import wildanimals.entities.ai.EntityAIBegTiger; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public class EntityTiger extends EntityTameable { protected float field_70926_e; protected float field_70924_f; /** * true is the tiger is wet else false */ protected boolean isShaking; protected boolean field_70928_h; /** * This time increases while tiger is shaking and emitting water particles. */ protected float timeTigerIsShaking; protected float prevTimeTigerIsShaking; protected static final String __OBFID = "CL_00001654"; // good to have instances of AI so task list can be modified, including in sub-classes protected EntityAIBase aiSwimming = new EntityAISwimming(this); protected EntityAIBase aiLeapAtTarget = new EntityAILeapAtTarget(this, 0.4F); protected EntityAIBase aiAttackOnCollide = new EntityAIAttackOnCollide(this, 1.0D, true); protected EntityAIBase aiFollowOwner = new EntityAIFollowOwner(this, 1.0D, 10.0F, 2.0F); protected EntityAIBase aiMate = new EntityAIMate(this, 1.0D); protected EntityAIBase aiWander = new EntityAIWander(this, 1.0D); protected EntityAIBase aiBeg = new EntityAIBegTiger(this, 8.0F); // in vanilla begging is only for wolf protected EntityAIBase aiWatchClosest = new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F); protected EntityAIBase aiLookIdle = new EntityAILookIdle(this); protected EntityAIBase aiOwnerHurtByTarget = new EntityAIOwnerHurtByTarget(this); protected EntityAIBase aiOwnerHurtTarget = new EntityAIOwnerHurtTarget(this); protected EntityAIBase aiHurtByTarget = new EntityAIHurtByTarget(this, true); protected EntityAIBase aiTargetNonTamed = new EntityAITargetNonTamed(this, EntitySheep.class, 200, false); public EntityTiger(World par1World) { super(par1World); // DEBUG System.out.println("EntityTiger constructor()"); this.setSize(0.6F, 0.8F); this.getNavigator().setAvoidsWater(true); this.tasks.addTask(1, this.aiSwimming); this.tasks.addTask(2, this.aiSit); this.tasks.addTask(3, this.aiLeapAtTarget); this.tasks.addTask(4, this.aiAttackOnCollide); this.tasks.addTask(5, this.aiFollowOwner); this.tasks.addTask(6, this.aiMate); this.tasks.addTask(7, this.aiWander); this.tasks.addTask(8, this.aiBeg); // in vanilla begging is only for wolf this.tasks.addTask(9, this.aiWatchClosest); this.tasks.addTask(10, this.aiLookIdle); this.targetTasks.addTask(1, this.aiOwnerHurtByTarget); this.targetTasks.addTask(2, this.aiOwnerHurtTarget); this.targetTasks.addTask(3, this.aiHurtByTarget); this.targetTasks.addTask(4, this.aiTargetNonTamed); this.setTamed(false); } // use clear tasks for subclasses then build up their ai task list specifically protected void clearAITasks() { this.tasks.removeTask(this.aiSwimming); this.tasks.removeTask(this.aiSit); this.tasks.removeTask(this.aiLeapAtTarget); this.tasks.removeTask(this.aiAttackOnCollide); this.tasks.removeTask(this.aiFollowOwner); this.tasks.removeTask(this.aiMate); this.tasks.removeTask(this.aiWander); this.tasks.removeTask(this.aiBeg); // in vanilla begging is only for wolf this.tasks.removeTask(this.aiWatchClosest); this.tasks.removeTask(this.aiLookIdle); this.targetTasks.removeTask(this.aiOwnerHurtByTarget); this.targetTasks.removeTask(this.aiOwnerHurtTarget); this.targetTasks.removeTask(this.aiHurtByTarget); this.targetTasks.removeTask(this.aiTargetNonTamed); } @Override protected void applyEntityAttributes() { super.applyEntityAttributes(); this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.30000001192092896D); if (this.isTamed()) { this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(20.0D); } else { this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(8.0D); } } /** * Returns true if the newer Entity AI code should be run */ @Override public boolean isAIEnabled() { return true; } /** * Sets the active target the Task system uses for tracking */ @Override public void setAttackTarget(EntityLivingBase par1EntityLivingBase) { super.setAttackTarget(par1EntityLivingBase); if (par1EntityLivingBase == null) { this.setAngry(false); } else if (!this.isTamed()) { this.setAngry(true); } } /** * main AI tick function, replaces updateEntityActionState */ @Override protected void updateAITick() { this.dataWatcher.updateObject(18, Float.valueOf(this.getHealth())); } @Override protected void entityInit() { super.entityInit(); this.dataWatcher.addObject(18, new Float(this.getHealth())); this.dataWatcher.addObject(19, new Byte((byte)0)); this.dataWatcher.addObject(20, new Byte((byte)BlockColored.func_150032_b(1))); } @Override protected void func_145780_a(int p_145780_1_, int p_145780_2_, int p_145780_3_, Block p_145780_4_) { this.playSound("wildanimals:mob.tiger.step", 0.15F, 1.0F); // this is randomized from 1 to 5 } /** * (abstract) Protected helper method to write subclass entity data to NBT. */ @Override public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) { super.writeEntityToNBT(par1NBTTagCompound); par1NBTTagCompound.setBoolean("Angry", this.isAngry()); par1NBTTagCompound.setByte("CollarColor", (byte)this.getCollarColor()); } /** * (abstract) Protected helper method to read subclass entity data from NBT. */ @Override public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) { super.readEntityFromNBT(par1NBTTagCompound); this.setAngry(par1NBTTagCompound.getBoolean("Angry")); if (par1NBTTagCompound.hasKey("CollarColor", 99)) { this.setCollarColor(par1NBTTagCompound.getByte("CollarColor")); } } /** * Returns the sound this mob makes while it's alive. */ @Override protected String getLivingSound() { return this.isAngry() ? "wildanimals:mob.tiger.growl" : (this.rand.nextInt(3) == 0 ? (this.isTamed() && this.dataWatcher.getWatchableObjectFloat(18) < 10.0F ? "wildanimals:mob.tiger.whine" : "wildanimals:mob.tiger.panting") : "wildanimals:mob.tiger.bark"); } /** * Returns the sound this mob makes when it is hurt. */ @Override protected String getHurtSound() { return "wildanimals:mob.tiger.hurt"; // It uses sounds.json file to randomize and adds 1, 2 or 3 and .ogg } /** * Returns the sound this mob makes on death. */ @Override protected String getDeathSound() { return "wildanimals:mob.tiger.death"; } /** * Returns the volume for the sounds this mob makes. */ @Override protected float getSoundVolume() { return 0.4F; } @Override protected Item getDropItem() { return Item.getItemById(-1); } /** * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons * use this to react to sunlight and start to burn. */ @Override public void onLivingUpdate() { super.onLivingUpdate(); if (!this.worldObj.isRemote && this.isShaking && !this.field_70928_h && !this.hasPath() && this.onGround) { this.field_70928_h = true; this.timeTigerIsShaking = 0.0F; this.prevTimeTigerIsShaking = 0.0F; this.worldObj.setEntityState(this, (byte); } } /** * Called to update the entity's position/logic. */ @Override public void onUpdate() { super.onUpdate(); this.field_70924_f = this.field_70926_e; if (this.func_70922_bv()) { this.field_70926_e += (1.0F - this.field_70926_e) * 0.4F; } else { this.field_70926_e += (0.0F - this.field_70926_e) * 0.4F; } if (this.func_70922_bv()) { this.numTicksToChaseTarget = 10; } if (this.isWet()) { this.isShaking = true; this.field_70928_h = false; this.timeTigerIsShaking = 0.0F; this.prevTimeTigerIsShaking = 0.0F; } else if ((this.isShaking || this.field_70928_h) && this.field_70928_h) { if (this.timeTigerIsShaking == 0.0F) { this.playSound("wildanimals:mob.tiger.shake", this.getSoundVolume(), (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F); } this.prevTimeTigerIsShaking = this.timeTigerIsShaking; this.timeTigerIsShaking += 0.05F; if (this.prevTimeTigerIsShaking >= 2.0F) { this.isShaking = false; this.field_70928_h = false; this.prevTimeTigerIsShaking = 0.0F; this.timeTigerIsShaking = 0.0F; } if (this.timeTigerIsShaking > 0.4F) { float f = (float)this.boundingBox.minY; int i = (int)(MathHelper.sin((this.timeTigerIsShaking - 0.4F) * (float)Math.PI) * 7.0F); for (int j = 0; j < i; ++j) { float f1 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width * 0.5F; float f2 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width * 0.5F; this.worldObj.spawnParticle("splash", this.posX + f1, f + 0.8F, this.posZ + f2, this.motionX, this.motionY, this.motionZ); } } } } @SideOnly(Side.CLIENT) public boolean getTigerShaking() { return this.isShaking; } /** * Used when calculating the amount of shading to apply while the tiger is shaking. */ @SideOnly(Side.CLIENT) public float getShadingWhileShaking(float par1) { return 0.75F + (this.prevTimeTigerIsShaking + (this.timeTigerIsShaking - this.prevTimeTigerIsShaking) * par1) / 2.0F * 0.25F; } @SideOnly(Side.CLIENT) public float getShakeAngle(float par1, float par2) { float f2 = (this.prevTimeTigerIsShaking + (this.timeTigerIsShaking - this.prevTimeTigerIsShaking) * par1 + par2) / 1.8F; if (f2 < 0.0F) { f2 = 0.0F; } else if (f2 > 1.0F) { f2 = 1.0F; } return MathHelper.sin(f2 * (float)Math.PI) * MathHelper.sin(f2 * (float)Math.PI * 11.0F) * 0.15F * (float)Math.PI; } @Override public float getEyeHeight() { return this.height * 0.8F; } @SideOnly(Side.CLIENT) public float getInterestedAngle(float par1) { return (this.field_70924_f + (this.field_70926_e - this.field_70924_f) * par1) * 0.15F * (float)Math.PI; } /** * The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently * use in wolves. */ @Override public int getVerticalFaceSpeed() { return this.isSitting() ? 20 : super.getVerticalFaceSpeed(); } /** * Called when the entity is attacked. */ @Override public boolean attackEntityFrom(DamageSource par1DamageSource, float par2) { if (this.isEntityInvulnerable()) { return false; } else { Entity entity = par1DamageSource.getEntity(); this.aiSit.setSitting(false); if (entity != null && !(entity instanceof EntityPlayer) && !(entity instanceof EntityArrow)) { par2 = (par2 + 1.0F) / 2.0F; } return super.attackEntityFrom(par1DamageSource, par2); } } @Override public boolean attackEntityAsMob(Entity par1Entity) { int i = this.isTamed() ? 4 : 2; return par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), i); } @Override public void setTamed(boolean par1) { super.setTamed(par1); if (par1) { this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(20.0D); } else { this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(8.0D); } } /** * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig. */ @Override public boolean interact(EntityPlayer par1EntityPlayer) { ItemStack itemstack = par1EntityPlayer.inventory.getCurrentItem(); if (this.isTamed()) { if (itemstack != null) { if (itemstack.getItem() instanceof ItemFood) { ItemFood itemfood = (ItemFood)itemstack.getItem(); if (itemfood.isWolfsFavoriteMeat() && this.dataWatcher.getWatchableObjectFloat(18) < 20.0F) { if (!par1EntityPlayer.capabilities.isCreativeMode) { --itemstack.stackSize; } this.heal(itemfood.func_150905_g(itemstack)); if (itemstack.stackSize <= 0) { par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem, (ItemStack)null); } return true; } } else if (itemstack.getItem() == Items.dye) { int i = BlockColored.func_150032_b(itemstack.getItemDamage()); if (i != this.getCollarColor()) { this.setCollarColor(i); if (!par1EntityPlayer.capabilities.isCreativeMode && --itemstack.stackSize <= 0) { par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem, (ItemStack)null); } return true; } } } if (par1EntityPlayer.getCommandSenderName().equalsIgnoreCase(this.getOwnerName()) && !this.worldObj.isRemote && !this.isBreedingItem(itemstack)) { this.aiSit.setSitting(!this.isSitting()); this.isJumping = false; this.setPathToEntity((PathEntity)null); this.setTarget((Entity)null); this.setAttackTarget((EntityLivingBase)null); } } else if (itemstack != null && itemstack.getItem() == Items.bone && !this.isAngry()) { if (!par1EntityPlayer.capabilities.isCreativeMode) { --itemstack.stackSize; } if (itemstack.stackSize <= 0) { par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem, (ItemStack)null); } if (!this.worldObj.isRemote) { if (this.rand.nextInt(3) == 0) { this.setTamed(true); this.setPathToEntity((PathEntity)null); this.setAttackTarget((EntityLivingBase)null); this.aiSit.setSitting(true); this.setHealth(20.0F); this.setOwner(par1EntityPlayer.getCommandSenderName()); this.playTameEffect(true); this.worldObj.setEntityState(this, (byte)7); } else { this.playTameEffect(false); this.worldObj.setEntityState(this, (byte)6); } } return true; } return super.interact(par1EntityPlayer); } @Override @SideOnly(Side.CLIENT) public void handleHealthUpdate(byte par1) { if (par1 == { this.field_70928_h = true; this.timeTigerIsShaking = 0.0F; this.prevTimeTigerIsShaking = 0.0F; } else { super.handleHealthUpdate(par1); } } @SideOnly(Side.CLIENT) public float getTailRotation() { return this.isAngry() ? 1.5393804F : (this.isTamed() ? (0.55F - (20.0F - this.dataWatcher.getWatchableObjectFloat(18)) * 0.02F) * (float)Math.PI : ((float)Math.PI / 5F)); } /** * Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on * the animal type) */ @Override public boolean isBreedingItem(ItemStack par1ItemStack) { return par1ItemStack == null ? false : (!(par1ItemStack.getItem() instanceof ItemFood) ? false : ((ItemFood)par1ItemStack.getItem()).isWolfsFavoriteMeat()); } /** * Will return how many at most can spawn in a chunk at once. */ @Override public int getMaxSpawnedInChunk() { return 8; } /** * Determines whether this tiger is angry or not. */ public boolean isAngry() { return (this.dataWatcher.getWatchableObjectByte(16) & 2) != 0; } /** * Sets whether this tiger is angry or not. */ public void setAngry(boolean par1) { byte b0 = this.dataWatcher.getWatchableObjectByte(16); if (par1) { this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 | 2))); } else { this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 & -3))); } } /** * Return this tiger's collar color. */ public int getCollarColor() { return this.dataWatcher.getWatchableObjectByte(20) & 15; } /** * Set this tiger's collar color. */ public void setCollarColor(int par1) { this.dataWatcher.updateObject(20, Byte.valueOf((byte)(par1 & 15))); } @Override public EntityTiger createChild(EntityAgeable par1EntityAgeable) { EntityTiger entitytiger = new EntityTiger(this.worldObj); String s = this.getOwnerName(); if (s != null && s.trim().length() > 0) { entitytiger.setOwner(s); entitytiger.setTamed(true); } return entitytiger; } public void func_70918_i(boolean par1) { if (par1) { this.dataWatcher.updateObject(19, Byte.valueOf((byte)1)); } else { this.dataWatcher.updateObject(19, Byte.valueOf((byte)0)); } } /** * Returns true if the mob is currently able to mate with the specified mob. */ @Override public boolean canMateWith(EntityAnimal par1EntityAnimal) { if (par1EntityAnimal == this) { return false; } else if (!this.isTamed()) { return false; } else if (!(par1EntityAnimal instanceof EntityTiger)) { return false; } else { EntityTiger entitytiger = (EntityTiger)par1EntityAnimal; return !entitytiger.isTamed() ? false : (entitytiger.isSitting() ? false : this.isInLove() && entitytiger.isInLove()); } } public boolean func_70922_bv() { return this.dataWatcher.getWatchableObjectByte(19) == 1; } /** * Determines if an entity can be despawned, used on idle far away entities */ @Override protected boolean canDespawn() { return !this.isTamed() && this.ticksExisted > 2400; } @Override public boolean func_142018_a(EntityLivingBase par1EntityLivingBase, EntityLivingBase par2EntityLivingBase) { if (!(par1EntityLivingBase instanceof EntityCreeper) && !(par1EntityLivingBase instanceof EntityGhast)) { if (par1EntityLivingBase instanceof EntityTiger) { EntityTiger entitytiger = (EntityTiger)par1EntityLivingBase; if (entitytiger.isTamed() && entitytiger.getOwner() == par2EntityLivingBase) { return false; } } return par1EntityLivingBase instanceof EntityPlayer && par2EntityLivingBase instanceof EntityPlayer && !((EntityPlayer)par2EntityLivingBase).canAttackPlayer((EntityPlayer)par1EntityLivingBase) ? false : !(par1EntityLivingBase instanceof EntityHorse) || !((EntityHorse)par1EntityLivingBase).isTame(); } else { return false; } } } EntityManEatingTiger package wildanimals.entities; import net.minecraft.client.Minecraft; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.world.World; public class EntityManEatingTiger extends EntityTiger { public EntityManEatingTiger(World par1World) { super(par1World); // DEBUG System.out.println("EntityManEatingTiger constructor()"); this.setSize(0.6F, 0.8F); // rebuild AI task list specific to this sub-class clearAITasks(); this.tasks.addTask(1, this.aiSwimming); this.tasks.addTask(2, this.aiLeapAtTarget); this.tasks.addTask(3, this.aiAttackOnCollide); this.tasks.addTask(4, this.aiWander); this.tasks.addTask(5, this.aiWatchClosest); this.tasks.addTask(6, this.aiLookIdle); this.targetTasks.addTask(1, this.aiHurtByTarget); this.targetTasks.addTask(2, this.aiTargetNonTamed); this.setTamed(false); // make him a man-eater by starting angry this.setAngry(true); // make him hunt the player super.setAttackTarget(Minecraft.getMinecraft().thePlayer); } @Override protected void applyEntityAttributes() { super.applyEntityAttributes(); this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.30000001192092896D); this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(8.0D); } /** * Sets the active target the Task system uses for tracking */ @Override public void setAttackTarget(EntityLivingBase par1EntityLivingBase) { if (par1EntityLivingBase!=null) // already has target { super.setAttackTarget(par1EntityLivingBase); } else // make player target { super.setAttackTarget(Minecraft.getMinecraft().thePlayer); } // always angry makes him a man-eater this.setAngry(true); } @Override protected void entityInit() { super.entityInit(); // note that custom datawatcher objects are created in EntityTiger superclass this.setAngry(true); // starting angry makes it a man-eater } /** * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons * use this to react to sunlight and start to burn. */ @Override public void onLivingUpdate() { super.onLivingUpdate(); this.setAngry(true); // keep the man-eater angry if (!this.worldObj.isRemote && this.isShaking && !this.field_70928_h && !this.hasPath() && this.onGround) { this.field_70928_h = true; this.timeTigerIsShaking = 0.0F; this.prevTimeTigerIsShaking = 0.0F; this.worldObj.setEntityState(this, (byte); } } @Override public void setTamed(boolean par1) { // man-eating tiger can't be tamed } /** * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig. */ @Override public boolean interact(EntityPlayer par1EntityPlayer) { // no special interaction for a man-eater! return super.interact(par1EntityPlayer); } /** * Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on * the animal type) */ @Override public boolean isBreedingItem(ItemStack par1ItemStack) { return false; // can't breed man-eating tiger } /** * Will return how many at most can spawn in a chunk at once. */ @Override public int getMaxSpawnedInChunk() { return 8; } } Check out my tutorials here: http://jabelarminecraft.blogspot.com/
April 2, 201411 yr Author Okay, I had some success by changing the way I reference the player. Originally I had: super.setAttackTarget(Minecraft.getMinecraft().thePlayer); Which I replaced with: hunted_player = this.worldObj.getClosestVulnerablePlayerToEntity(this, 32.0D); super.setAttackTarget(hunted_player != null && this.canEntityBeSeen(hunted_player) ? hunted_player : null); I guess I'm okay now that it works, but I like to understand code that doesn't behave how I expect. Why would the original code make the entity look like it attacked (but with no damage) whereas the second version works? I'm guessing it has to do with server side versus client side? Maybe the first one wasn't properly updating the server version of the player object so what looked like an attack on the client side didn't really cause damage? client - server stuff is still something I mess up a lot ... Check out my tutorials here: http://jabelarminecraft.blogspot.com/
April 2, 201411 yr Exactly. NEVER use Minecraft.getMinecraft() for anything unless you are absolutely sure it will only ever run on the client. If you ran your original code on a server, it would crash as soon as your tiger tried to attack. http://i.imgur.com/NdrFdld.png[/img]
April 2, 201411 yr Author Okay, thanks. Solution: I was referencing a client side player instance rather than a server side. Check out my tutorials here: http://jabelarminecraft.blogspot.com/
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.