split entity ai to server #1
This commit is contained in:
parent
6e5c9e842e
commit
02c0bfcbf6
10 changed files with 706 additions and 634 deletions
17
common/src/common/ai/IEntityNode.java
Normal file
17
common/src/common/ai/IEntityNode.java
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package common.ai;
|
||||||
|
|
||||||
|
import common.entity.DamageSource;
|
||||||
|
import common.entity.types.EntityLiving;
|
||||||
|
import common.nbt.NBTTagCompound;
|
||||||
|
|
||||||
|
public interface IEntityNode {
|
||||||
|
void update();
|
||||||
|
void updateRenderAngles();
|
||||||
|
void updateLeashedState();
|
||||||
|
void setLeashTag(NBTTagCompound tag);
|
||||||
|
EntityLiving getAttacking();
|
||||||
|
EntityLiving getAttackTarget();
|
||||||
|
void resetCombat();
|
||||||
|
void trackDamage(DamageSource source, int amount);
|
||||||
|
void sendDeathMessage();
|
||||||
|
}
|
|
@ -2428,14 +2428,6 @@ public abstract class Entity
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximum height from where the entity is alowed to jump (used in pathfinder)
|
|
||||||
*/
|
|
||||||
public int getMaxFallHeight()
|
|
||||||
{
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// public Vec3 getLastPortal()
|
// public Vec3 getLastPortal()
|
||||||
// {
|
// {
|
||||||
// return this.portalVec != null ? this.portalVec : new Vec3(0.0d, 0.0d, 0.0d);
|
// return this.portalVec != null ? this.portalVec : new Vec3(0.0d, 0.0d, 0.0d);
|
||||||
|
|
|
@ -258,14 +258,6 @@ public class EntityHorse extends EntityAnimal implements IInvBasic
|
||||||
return !this.isUndead() && super.allowLeashing();
|
return !this.isUndead() && super.allowLeashing();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onUpdateLeashed(float distance)
|
|
||||||
{
|
|
||||||
if (distance > 6.0F && this.isEatingHaystack())
|
|
||||||
{
|
|
||||||
this.setEatingHaystack(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isChested()
|
public boolean isChested()
|
||||||
{
|
{
|
||||||
return this.getHorseWatchableBoolean(8);
|
return this.getHorseWatchableBoolean(8);
|
||||||
|
|
|
@ -35,11 +35,6 @@ public class EntityArachnoid extends EntityNPC
|
||||||
// return 0.9375f * this.height / 1.6f;
|
// return 0.9375f * this.height / 1.6f;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
protected PathNavigate getNewNavigator(World worldIn)
|
|
||||||
{
|
|
||||||
return new PathNavigateClimber(this, worldIn);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void entityInit()
|
protected void entityInit()
|
||||||
{
|
{
|
||||||
super.entityInit();
|
super.entityInit();
|
||||||
|
|
|
@ -31,11 +31,6 @@ public class EntityHaunter extends EntityNPC {
|
||||||
this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.25D);
|
this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.25D);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxFallHeight()
|
|
||||||
{
|
|
||||||
return this.getAttackTarget() == null ? 3 : 3 + (this.getHealth() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fall(float distance, float damageMultiplier)
|
public void fall(float distance, float damageMultiplier)
|
||||||
{
|
{
|
||||||
super.fall(distance, damageMultiplier);
|
super.fall(distance, damageMultiplier);
|
||||||
|
|
|
@ -134,46 +134,10 @@ public abstract class EntityNPC extends EntityLiving
|
||||||
// return (character.substring(0, 1).toUpperCase() + character.substring(1)).replace('_', ' ').replaceAll("( [a-z])", "$1");
|
// return (character.substring(0, 1).toUpperCase() + character.substring(1)).replace('_', ' ').replaceAll("( [a-z])", "$1");
|
||||||
// }
|
// }
|
||||||
|
|
||||||
protected final EntityAIAttackOnCollide aiMelee = new EntityAIAttackOnCollide(this, EntityLiving.class, 1.0D, true, true) {
|
|
||||||
public boolean shouldExecute()
|
|
||||||
{
|
|
||||||
return !EntityNPC.this.fleeing && super.shouldExecute();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean continueExecuting()
|
|
||||||
{
|
|
||||||
return !EntityNPC.this.fleeing && super.shouldExecute();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
protected final AIRangedAttack aiRanged = new AIRangedAttack(this, 1.0D, this.getAttackSpeed(), this.getAttackSpeed() * 3, 15.0F) {
|
|
||||||
// public void startExecuting()
|
|
||||||
// {
|
|
||||||
// super.startExecuting();
|
|
||||||
// EntityNPC.this.setUsingItem(true);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public void resetTask()
|
|
||||||
// {
|
|
||||||
// super.resetTask();
|
|
||||||
// EntityNPC.this.setUsingItem(false);
|
|
||||||
// }
|
|
||||||
|
|
||||||
public boolean shouldExecute()
|
|
||||||
{
|
|
||||||
return !EntityNPC.this.fleeing && super.shouldExecute();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean continueExecuting()
|
|
||||||
{
|
|
||||||
return !EntityNPC.this.fleeing && super.shouldExecute();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected final SpeciesInfo species;
|
protected final SpeciesInfo species;
|
||||||
|
|
||||||
private EntityNPC talkingPlayer;
|
private EntityNPC talkingPlayer;
|
||||||
private boolean isWilling;
|
private boolean isWilling;
|
||||||
private boolean fleeing;
|
|
||||||
private boolean playing;
|
private boolean playing;
|
||||||
protected boolean noPickup;
|
protected boolean noPickup;
|
||||||
private ItemStack[] equipment = new ItemStack[5];
|
private ItemStack[] equipment = new ItemStack[5];
|
||||||
|
@ -255,120 +219,6 @@ public abstract class EntityNPC extends EntityLiving
|
||||||
// this.setCharacter("");
|
// this.setCharacter("");
|
||||||
if(this.species != null)
|
if(this.species != null)
|
||||||
this.setSize(this.getSpeciesBaseSize() * this.species.renderer.width / this.species.renderer.height, this.getSpeciesBaseSize()); // /* 0.6F, */ 1.8F);
|
this.setSize(this.getSpeciesBaseSize() * this.species.renderer.width / this.species.renderer.height, this.getSpeciesBaseSize()); // /* 0.6F, */ 1.8F);
|
||||||
if(this.getNavigator() instanceof PathNavigateGround) {
|
|
||||||
((PathNavigateGround)this.getNavigator()).setBreakDoors(true);
|
|
||||||
((PathNavigateGround)this.getNavigator()).setAvoidsWater(true);
|
|
||||||
}
|
|
||||||
this.tasks.addTask(0, new EntityAISwimming(this));
|
|
||||||
// this.tasks.addTask(1, new EntityAIAttackOnCollide(this, EntityNPC.class, 0.6D, true, true));
|
|
||||||
// this.tasks.addTask(1, new EntityAIAttackOnCollide(this, EntityLivingBase.class, 0.6D, true, true));
|
|
||||||
this.tasks.addTask(1, new EntityAINpcMate(this));
|
|
||||||
this.tasks.addTask(2, new EntityAIAvoidEntity(this, EntityLiving.class, new Predicate<EntityLiving>() {
|
|
||||||
public boolean test(EntityLiving entity) {
|
|
||||||
return entity != EntityNPC.this && EntityNPC.this.shouldFlee(entity);
|
|
||||||
}
|
|
||||||
}, 8.0F, 1.1D, 1.1D) {
|
|
||||||
{
|
|
||||||
this.setMutexBits(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startExecuting() {
|
|
||||||
EntityNPC.this.setAttackTarget(null);
|
|
||||||
EntityNPC.this.fleeing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean continueExecuting() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateTask()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// public void resetTask() {
|
|
||||||
// super.resetTask();
|
|
||||||
// EntityNPC.this.isFleeing = false;
|
|
||||||
// }
|
|
||||||
});
|
|
||||||
this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityLiving.class, new Predicate<EntityLiving>() {
|
|
||||||
public boolean test(EntityLiving entity) {
|
|
||||||
return entity != EntityNPC.this && EntityNPC.this.shouldFlee(entity);
|
|
||||||
}
|
|
||||||
}, 8.0F, 1.1D, 1.1D) {
|
|
||||||
public void startExecuting() {
|
|
||||||
super.startExecuting();
|
|
||||||
EntityNPC.this.setAttackTarget(null);
|
|
||||||
EntityNPC.this.fleeing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void resetTask() {
|
|
||||||
super.resetTask();
|
|
||||||
EntityNPC.this.fleeing = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// this.tasks.addTask(2, new EntityAITempt(this, 1.0D, Items.golden_apple, false));
|
|
||||||
this.tasks.addTask(4, new EntityAIOpenDoor(this, true));
|
|
||||||
this.tasks.addTask(5, new EntityAINagPlayer(this));
|
|
||||||
this.tasks.addTask(5, new EntityAILookAtTalkingPlayer(this));
|
|
||||||
this.tasks.addTask(6, new EntityAIWatchClosest2(this, null, 3.0F, 1.0F) {
|
|
||||||
private int sneakTime;
|
|
||||||
|
|
||||||
public void updateTask()
|
|
||||||
{
|
|
||||||
super.updateTask();
|
|
||||||
boolean flag = this.closestEntity.isPlayer() && this.closestEntity.isSneaking();
|
|
||||||
if(this.sneakTime > 0) {
|
|
||||||
if(--this.sneakTime == 0) {
|
|
||||||
EntityNPC.this.setSneaking(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(EntityNPC.this.getAttackTarget() == null && EntityNPC.this.rand.chance(flag ? 5 : 200)) {
|
|
||||||
EntityNPC.this.setSneaking(true);
|
|
||||||
this.sneakTime = EntityNPC.this.rand.range(60, flag ? 160 : 120);
|
|
||||||
}
|
|
||||||
else if(EntityNPC.this.getAttackTarget() != null) {
|
|
||||||
EntityNPC.this.setSneaking(false);
|
|
||||||
this.sneakTime = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void resetTask()
|
|
||||||
{
|
|
||||||
super.resetTask();
|
|
||||||
EntityNPC.this.setSneaking(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.tasks.addTask(7, new EntityAINpcInteract(this));
|
|
||||||
this.tasks.addTask(8, new EntityAIWander(this, 1.0D));
|
|
||||||
this.tasks.addTask(8, new EntityAIPlay(this, 1.1D));
|
|
||||||
this.tasks.addTask(9, new EntityAIWatchClosest(this, EntityLiving.class, 8.0F));
|
|
||||||
this.targets.addTask(1, new EntityAIHurtByTarget(this, false, /* EntityNPC.class, */ EntityLiving.class) {
|
|
||||||
protected boolean isSuitableTarget(EntityLiving entity) {
|
|
||||||
if(entity != null && entity != EntityNPC.this && EntityNPC.this.shouldFlee(entity)) {
|
|
||||||
EntityNPC.this.setAttackTarget(null);
|
|
||||||
EntityNPC.this.fleeing = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return entity != null && entity != EntityNPC.this && (!(entity.isPlayer()) || EntityNPC.this.rand.chance(entity.getAttackedBy() == EntityNPC.this ? 2 : 4))
|
|
||||||
&& EntityNPC.this.canCounter(entity) && super.isSuitableTarget(entity);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.targets.addTask(2, new EntityAINearestAttackableTarget(this, EntityLiving.class, 10, true, false, new Predicate<EntityLiving>() {
|
|
||||||
public boolean test(EntityLiving entity) {
|
|
||||||
if(entity != null && entity != EntityNPC.this && EntityNPC.this.shouldFlee(entity)) {
|
|
||||||
EntityNPC.this.setAttackTarget(null);
|
|
||||||
EntityNPC.this.fleeing = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return entity != null && entity != EntityNPC.this && !EntityNPC.this.fleeing && EntityNPC.this.canAmbush(entity) && EntityNPC.this.canAttack(entity);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
// this.setCanPickUpLoot(true);
|
|
||||||
|
|
||||||
if (worldIn != null && !worldIn.client)
|
|
||||||
{
|
|
||||||
this.setCombatTask();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -657,7 +507,7 @@ public abstract class EntityNPC extends EntityLiving
|
||||||
}
|
}
|
||||||
else if (!flag && !this.isPlayer() && this.isEntityAlive() && !this.isTalking())
|
else if (!flag && !this.isPlayer() && this.isEntityAlive() && !this.isTalking())
|
||||||
{
|
{
|
||||||
if (!this.worldObj.client && this.canTrade() && this.getAttackTarget() == null)
|
if (!this.worldObj.client && this.canTrade() && this.node.getAttackTarget() == null)
|
||||||
{
|
{
|
||||||
this.setTalking(player);
|
this.setTalking(player);
|
||||||
player.connection.displayTradeGui(this);
|
player.connection.displayTradeGui(this);
|
||||||
|
@ -1168,10 +1018,6 @@ public abstract class EntityNPC extends EntityLiving
|
||||||
return this.playing;
|
return this.playing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFleeing() {
|
|
||||||
return this.fleeing;
|
|
||||||
}
|
|
||||||
|
|
||||||
// public boolean canPlay() {
|
// public boolean canPlay() {
|
||||||
// return ;
|
// return ;
|
||||||
// }
|
// }
|
||||||
|
@ -2032,7 +1878,8 @@ public abstract class EntityNPC extends EntityLiving
|
||||||
{
|
{
|
||||||
// float f1 = this.getHealth();
|
// float f1 = this.getHealth();
|
||||||
this.setHealth(this.getHealth() - damageAmount);
|
this.setHealth(this.getHealth() - damageAmount);
|
||||||
this.trackDamage(damageSrc, damageAmount);
|
if(this.node != null)
|
||||||
|
this.node.trackDamage(damageSrc, damageAmount);
|
||||||
|
|
||||||
// if ((float)damageAmount < 3.4028235E37F)
|
// if ((float)damageAmount < 3.4028235E37F)
|
||||||
// {
|
// {
|
||||||
|
@ -2835,7 +2682,7 @@ public abstract class EntityNPC extends EntityLiving
|
||||||
else {
|
else {
|
||||||
this.setItemNoUpdate(slot, stack);
|
this.setItemNoUpdate(slot, stack);
|
||||||
if(!this.worldObj.client && slot == 0)
|
if(!this.worldObj.client && slot == 0)
|
||||||
this.setCombatTask();
|
this.node.setCombatTask();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3443,7 +3290,7 @@ public abstract class EntityNPC extends EntityLiving
|
||||||
this.skin = tagCompund.getByteArray("Skin");
|
this.skin = tagCompund.getByteArray("Skin");
|
||||||
|
|
||||||
// this.setCanPickUpLoot(true);
|
// this.setCanPickUpLoot(true);
|
||||||
this.setCombatTask();
|
this.node.setCombatTask();
|
||||||
|
|
||||||
if(this.isPlayer()) {
|
if(this.isPlayer()) {
|
||||||
// this.entityUniqueID = getOfflineUUID(this.user);
|
// this.entityUniqueID = getOfflineUUID(this.user);
|
||||||
|
@ -4462,16 +4309,6 @@ public abstract class EntityNPC extends EntityLiving
|
||||||
return !this.isPlayer() && super.interactFirst(playerIn);
|
return !this.isPlayer() && super.interactFirst(playerIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxFallHeight()
|
|
||||||
{
|
|
||||||
return this.isPlayer() ? 3 : super.getMaxFallHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void updateLeashedState() {
|
|
||||||
if(!this.isPlayer())
|
|
||||||
super.updateLeashedState();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLeashedTo(Entity entity, boolean pkt) {
|
public void setLeashedTo(Entity entity, boolean pkt) {
|
||||||
if(!this.isPlayer())
|
if(!this.isPlayer())
|
||||||
super.setLeashedTo(entity, pkt);
|
super.setLeashedTo(entity, pkt);
|
||||||
|
@ -4486,14 +4323,15 @@ public abstract class EntityNPC extends EntityLiving
|
||||||
super.clearLeashed(pkt, dropLead);
|
super.clearLeashed(pkt, dropLead);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float updateDistance(float p_110146_1_, float p_110146_2_)
|
protected void updateDistance(float p_110146_1_, float p_110146_2_)
|
||||||
{
|
{
|
||||||
if(!this.isPlayer())
|
if(!this.isPlayer()) {
|
||||||
return super.updateDistance(p_110146_1_, p_110146_2_);
|
super.updateDistance(p_110146_1_, p_110146_2_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
float f = ExtMath.wrapf(p_110146_1_ - this.yawOffset);
|
float f = ExtMath.wrapf(p_110146_1_ - this.yawOffset);
|
||||||
this.yawOffset += f * 0.3F;
|
this.yawOffset += f * 0.3F;
|
||||||
float f1 = ExtMath.wrapf(this.rotYaw - this.yawOffset);
|
float f1 = ExtMath.wrapf(this.rotYaw - this.yawOffset);
|
||||||
boolean flag = f1 < -90.0F || f1 >= 90.0F;
|
|
||||||
|
|
||||||
if (f1 < -75.0F)
|
if (f1 < -75.0F)
|
||||||
{
|
{
|
||||||
|
@ -4511,13 +4349,6 @@ public abstract class EntityNPC extends EntityLiving
|
||||||
{
|
{
|
||||||
this.yawOffset += f1 * 0.2F;
|
this.yawOffset += f1 * 0.2F;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
p_110146_2_ *= -1.0F;
|
|
||||||
}
|
|
||||||
|
|
||||||
return p_110146_2_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getCanSpawnHere() {
|
public boolean getCanSpawnHere() {
|
||||||
|
@ -4587,24 +4418,6 @@ public abstract class EntityNPC extends EntityLiving
|
||||||
this.equipment[slot] = stack;
|
this.equipment[slot] = stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCombatTask()
|
|
||||||
{
|
|
||||||
if(!this.isPlayer()) {
|
|
||||||
this.tasks.removeTask(this.aiMelee);
|
|
||||||
this.tasks.removeTask(this.aiRanged);
|
|
||||||
ItemStack itemstack = this.getHeldItem();
|
|
||||||
|
|
||||||
if (this.isRangedWeapon(itemstack))
|
|
||||||
{
|
|
||||||
this.tasks.addTask(3, this.aiRanged);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.tasks.addTask(3, this.aiMelee);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract int getBaseHealth(Random rand); // {
|
public abstract int getBaseHealth(Random rand); // {
|
||||||
// return 20;
|
// return 20;
|
||||||
// }
|
// }
|
||||||
|
@ -4650,10 +4463,6 @@ public abstract class EntityNPC extends EntityLiving
|
||||||
return this.isPlayer() ? 0xff00ff : 0x5000ad;
|
return this.isPlayer() ? 0xff00ff : 0x5000ad;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendDeathMessage() {
|
|
||||||
this.sendDeathMessage(this.isPlayer(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean canRegenerateHealth() {
|
protected boolean canRegenerateHealth() {
|
||||||
return this.isPlayer();
|
return this.isPlayer();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,22 +6,14 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import common.ai.EntityAIBase;
|
import common.ai.IEntityNode;
|
||||||
import common.ai.EntityAIMoveTowardsRestriction;
|
|
||||||
import common.ai.EntityAITasks;
|
|
||||||
import common.ai.EntityJumpHelper;
|
|
||||||
import common.ai.EntityLookHelper;
|
|
||||||
import common.ai.EntityMoveHelper;
|
|
||||||
import common.ai.EntitySenses;
|
|
||||||
import common.block.Block;
|
import common.block.Block;
|
||||||
import common.block.SoundType;
|
import common.block.SoundType;
|
||||||
import common.collect.Lists;
|
|
||||||
import common.collect.Maps;
|
import common.collect.Maps;
|
||||||
import common.color.TextColor;
|
import common.color.TextColor;
|
||||||
import common.enchantment.EnchantmentHelper;
|
import common.enchantment.EnchantmentHelper;
|
||||||
import common.entity.DamageSource;
|
import common.entity.DamageSource;
|
||||||
import common.entity.Entity;
|
import common.entity.Entity;
|
||||||
import common.entity.EntityDamageSource;
|
|
||||||
import common.entity.animal.EntityWolf;
|
import common.entity.animal.EntityWolf;
|
||||||
import common.entity.attributes.Attribute;
|
import common.entity.attributes.Attribute;
|
||||||
import common.entity.attributes.AttributeInstance;
|
import common.entity.attributes.AttributeInstance;
|
||||||
|
@ -50,12 +42,9 @@ import common.material.Material;
|
||||||
import common.model.ParticleType;
|
import common.model.ParticleType;
|
||||||
import common.nbt.NBTTagCompound;
|
import common.nbt.NBTTagCompound;
|
||||||
import common.nbt.NBTTagList;
|
import common.nbt.NBTTagList;
|
||||||
import common.network.IPlayer;
|
|
||||||
import common.packet.S1BPacketEntityAttach;
|
import common.packet.S1BPacketEntityAttach;
|
||||||
import common.packet.SPacketAnimation;
|
import common.packet.SPacketAnimation;
|
||||||
import common.packet.SPacketCollectItem;
|
import common.packet.SPacketCollectItem;
|
||||||
import common.pathfinding.PathNavigate;
|
|
||||||
import common.pathfinding.PathNavigateGround;
|
|
||||||
import common.potion.Potion;
|
import common.potion.Potion;
|
||||||
import common.potion.PotionEffect;
|
import common.potion.PotionEffect;
|
||||||
import common.potion.PotionHelper;
|
import common.potion.PotionHelper;
|
||||||
|
@ -72,23 +61,13 @@ public abstract class EntityLiving extends Entity
|
||||||
{
|
{
|
||||||
private static final ItemStack[] EMPTY_INV = new ItemStack[5];
|
private static final ItemStack[] EMPTY_INV = new ItemStack[5];
|
||||||
|
|
||||||
|
protected IEntityNode node;
|
||||||
private AttributeMap attributes;
|
private AttributeMap attributes;
|
||||||
private final List<CombatEntry> combat = Lists.<CombatEntry>newArrayList();
|
|
||||||
private final Map<Potion, PotionEffect> effects = Maps.<Potion, PotionEffect>newEnumMap(Potion.class);
|
private final Map<Potion, PotionEffect> effects = Maps.<Potion, PotionEffect>newEnumMap(Potion.class);
|
||||||
public int soundTimer;
|
public int soundTimer;
|
||||||
protected int xpValue;
|
protected int xpValue;
|
||||||
private EntityLookHelper lookHelper;
|
|
||||||
protected EntityMoveHelper moveHelper;
|
|
||||||
protected EntityJumpHelper jumpHelper;
|
|
||||||
private EntityBodyHelper bodyHelper;
|
|
||||||
protected PathNavigate navigator;
|
|
||||||
protected final EntityAITasks tasks;
|
|
||||||
protected final EntityAITasks targets;
|
|
||||||
private EntityLiving target;
|
|
||||||
private EntitySenses senses;
|
|
||||||
private boolean leashed;
|
private boolean leashed;
|
||||||
private Entity leashedTo;
|
private Entity leashedTo;
|
||||||
private NBTTagCompound leashTag;
|
|
||||||
|
|
||||||
public float prevCamPitch;
|
public float prevCamPitch;
|
||||||
public float camPitch;
|
public float camPitch;
|
||||||
|
@ -100,8 +79,6 @@ public abstract class EntityLiving extends Entity
|
||||||
protected float landMovement;
|
protected float landMovement;
|
||||||
protected float prevGroundFactor;
|
protected float prevGroundFactor;
|
||||||
protected float groundFactor;
|
protected float groundFactor;
|
||||||
protected float movedDist;
|
|
||||||
protected float prevMovedDist;
|
|
||||||
protected boolean jumping;
|
protected boolean jumping;
|
||||||
public float moveStrafe;
|
public float moveStrafe;
|
||||||
public float moveForward;
|
public float moveForward;
|
||||||
|
@ -135,19 +112,14 @@ public abstract class EntityLiving extends Entity
|
||||||
private int lastAttacked;
|
private int lastAttacked;
|
||||||
private EntityLiving attacker;
|
private EntityLiving attacker;
|
||||||
private int lastAttackTime;
|
private int lastAttackTime;
|
||||||
private int lastDamaged;
|
|
||||||
|
|
||||||
// protected int entityAge;
|
// protected int entityAge;
|
||||||
private int absorptionAmount;
|
private int absorptionAmount;
|
||||||
private boolean effectsDirty = true;
|
private boolean effectsDirty = true;
|
||||||
protected boolean firstEffectUpdate = true;
|
protected boolean firstEffectUpdate = true;
|
||||||
private boolean attacked;
|
|
||||||
private boolean damaged;
|
|
||||||
|
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
private String blockType;
|
|
||||||
|
|
||||||
private float radiation;
|
private float radiation;
|
||||||
|
|
||||||
protected int particleTimer;
|
protected int particleTimer;
|
||||||
|
@ -156,8 +128,6 @@ public abstract class EntityLiving extends Entity
|
||||||
protected int growingAge;
|
protected int growingAge;
|
||||||
private float ageWidth = -1.0F;
|
private float ageWidth = -1.0F;
|
||||||
private float ageHeight;
|
private float ageHeight;
|
||||||
private EntityAIBase aiBase = new EntityAIMoveTowardsRestriction(this, 1.0D);
|
|
||||||
private boolean isMovementAITaskSet;
|
|
||||||
|
|
||||||
public EntityLiving(World worldIn)
|
public EntityLiving(World worldIn)
|
||||||
{
|
{
|
||||||
|
@ -171,15 +141,6 @@ public abstract class EntityLiving extends Entity
|
||||||
this.rotYaw = (float)(Math.random() * Math.PI * 2.0D);
|
this.rotYaw = (float)(Math.random() * Math.PI * 2.0D);
|
||||||
this.headYaw = this.rotYaw;
|
this.headYaw = this.rotYaw;
|
||||||
this.stepHeight = 0.6F;
|
this.stepHeight = 0.6F;
|
||||||
|
|
||||||
this.tasks = new EntityAITasks();
|
|
||||||
this.targets = new EntityAITasks();
|
|
||||||
this.lookHelper = new EntityLookHelper(this);
|
|
||||||
this.moveHelper = new EntityMoveHelper(this);
|
|
||||||
this.jumpHelper = new EntityJumpHelper(this);
|
|
||||||
this.bodyHelper = new EntityBodyHelper(this);
|
|
||||||
this.navigator = this.getNewNavigator(worldIn);
|
|
||||||
this.senses = new EntitySenses(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void entityInit()
|
protected void entityInit()
|
||||||
|
@ -394,7 +355,6 @@ public abstract class EntityLiving extends Entity
|
||||||
this.radiation = 0.0f;
|
this.radiation = 0.0f;
|
||||||
}
|
}
|
||||||
this.updateEffects();
|
this.updateEffects();
|
||||||
this.prevMovedDist = this.movedDist;
|
|
||||||
this.prevYawOffset = this.yawOffset;
|
this.prevYawOffset = this.yawOffset;
|
||||||
this.prevHeadYaw = this.headYaw;
|
this.prevHeadYaw = this.headYaw;
|
||||||
this.prevYaw = this.rotYaw;
|
this.prevYaw = this.rotYaw;
|
||||||
|
@ -666,7 +626,7 @@ public abstract class EntityLiving extends Entity
|
||||||
this.leashed = tagCompund.getBoolean("Leashed");
|
this.leashed = tagCompund.getBoolean("Leashed");
|
||||||
|
|
||||||
if(this.leashed && tagCompund.hasKey("Leash", 10)) {
|
if(this.leashed && tagCompund.hasKey("Leash", 10)) {
|
||||||
this.leashTag = tagCompund.getCompoundTag("Leash");
|
this.node.setLeashTag(tagCompund.getCompoundTag("Leash"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1109,11 +1069,12 @@ public abstract class EntityLiving extends Entity
|
||||||
entity.onKillEntity(this);
|
entity.onKillEntity(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.worldObj.client)
|
if(!this.worldObj.client) {
|
||||||
this.sendDeathMessage();
|
this.node.sendDeathMessage();
|
||||||
|
|
||||||
// this.noPickup = true;
|
// this.noPickup = true;
|
||||||
this.resetCombat();
|
this.node.resetCombat();
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.worldObj.client)
|
if (!this.worldObj.client)
|
||||||
{
|
{
|
||||||
|
@ -1368,7 +1329,8 @@ public abstract class EntityLiving extends Entity
|
||||||
{
|
{
|
||||||
// float f1 = this.getHealth();
|
// float f1 = this.getHealth();
|
||||||
this.setHealth(this.getHealth() - damageAmount);
|
this.setHealth(this.getHealth() - damageAmount);
|
||||||
this.trackDamage(damageSrc, damageAmount);
|
if(this.node != null)
|
||||||
|
this.node.trackDamage(damageSrc, damageAmount);
|
||||||
this.setAbsorptionAmount(this.getAbsorptionAmount() - damageAmount);
|
this.setAbsorptionAmount(this.getAbsorptionAmount() - damageAmount);
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
|
@ -1376,7 +1338,7 @@ public abstract class EntityLiving extends Entity
|
||||||
|
|
||||||
public EntityLiving getAttackingEntity()
|
public EntityLiving getAttackingEntity()
|
||||||
{
|
{
|
||||||
return (EntityLiving)(this.getAttacking() != null ? this.getAttacking() : (this.playerAttacker != null ? this.playerAttacker : (this.attackedBy != null ? this.attackedBy : null)));
|
return (EntityLiving)(this.node.getAttacking() != null ? this.node.getAttacking() : (this.playerAttacker != null ? this.playerAttacker : (this.attackedBy != null ? this.attackedBy : null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int getMaxHealth()
|
public final int getMaxHealth()
|
||||||
|
@ -1916,7 +1878,7 @@ public abstract class EntityLiving extends Entity
|
||||||
|
|
||||||
if (this.ticksExisted % 20 == 0)
|
if (this.ticksExisted % 20 == 0)
|
||||||
{
|
{
|
||||||
this.resetCombat();
|
this.node.resetCombat();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1948,7 +1910,7 @@ public abstract class EntityLiving extends Entity
|
||||||
|
|
||||||
this.groundFactor += (f3 - this.groundFactor) * 0.3F;
|
this.groundFactor += (f3 - this.groundFactor) * 0.3F;
|
||||||
// this.worldObj.profiler.start("headTurn");
|
// this.worldObj.profiler.start("headTurn");
|
||||||
f2 = this.updateDistance(f1, f2);
|
this.updateDistance(f1, f2);
|
||||||
// this.worldObj.profiler.end();
|
// this.worldObj.profiler.end();
|
||||||
// this.worldObj.profiler.start("rangeChecks");
|
// this.worldObj.profiler.start("rangeChecks");
|
||||||
|
|
||||||
|
@ -1993,10 +1955,9 @@ public abstract class EntityLiving extends Entity
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.worldObj.profiler.end();
|
// this.worldObj.profiler.end();
|
||||||
this.movedDist += f2;
|
|
||||||
|
|
||||||
if(!this.worldObj.client) {
|
if(!this.worldObj.client) {
|
||||||
this.updateLeashedState();
|
this.node.updateLeashedState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2431,159 +2392,6 @@ public abstract class EntityLiving extends Entity
|
||||||
this.radiation = 0.0f;
|
this.radiation = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void trackDamage(DamageSource source, int amount) {
|
|
||||||
this.resetCombat();
|
|
||||||
this.blockType = null;
|
|
||||||
if(this.isOnLadder()) {
|
|
||||||
Block block = this.worldObj
|
|
||||||
.getState(new BlockPos(this.posX, this.getEntityBoundingBox().minY, this.posZ)).getBlock();
|
|
||||||
if(block == Blocks.ladder)
|
|
||||||
this.blockType = "von einer Leiter";
|
|
||||||
else if(block == Blocks.vine)
|
|
||||||
this.blockType = "von Ranken";
|
|
||||||
}
|
|
||||||
else if(this.isInLiquid()) {
|
|
||||||
this.blockType = "aus dem Wasser";
|
|
||||||
}
|
|
||||||
CombatEntry entry = new CombatEntry(source, amount, this.blockType, this.fallDistance);
|
|
||||||
this.combat.add(entry);
|
|
||||||
this.lastDamaged = this.ticksExisted;
|
|
||||||
this.damaged = true;
|
|
||||||
if(entry.getSource().getEntity() instanceof EntityLiving && !this.attacked && this.isEntityAlive())
|
|
||||||
this.attacked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void sendDeathMessage() {
|
|
||||||
this.sendDeathMessage(false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void sendDeathMessage(boolean natural, boolean forAll) {
|
|
||||||
if(this.worldObj.client)
|
|
||||||
return;
|
|
||||||
String msg;
|
|
||||||
String kill;
|
|
||||||
IPlayer receiver = null;
|
|
||||||
if(this.combat.size() == 0) {
|
|
||||||
msg = kill = natural ? String.format("%s starb", this.getColoredName(TextColor.LGRAY)) : null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
CombatEntry strong = null;
|
|
||||||
CombatEntry block = null;
|
|
||||||
int min = 0;
|
|
||||||
float max = 0.0F;
|
|
||||||
|
|
||||||
for(int z = 0; z < this.combat.size(); ++z) {
|
|
||||||
CombatEntry entry = (CombatEntry)this.combat.get(z);
|
|
||||||
CombatEntry last = z > 0 ? (CombatEntry)this.combat.get(z - 1) : null;
|
|
||||||
|
|
||||||
if((entry.getSource() == DamageSource.fall || entry.getSource() == DamageSource.outOfWorld) &&
|
|
||||||
entry.getFallDistance() > 0.0F && (strong == null || entry.getFallDistance() > max)) {
|
|
||||||
if(z > 0) {
|
|
||||||
strong = last;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
strong = entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
max = entry.getFallDistance();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(entry.getBlockType() != null && (block == null || entry.getDamage() > min)) {
|
|
||||||
block = entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CombatEntry fall = max > 5.0F && strong != null ? strong : (min > 5 && block != null ? block : null);
|
|
||||||
CombatEntry last = (CombatEntry)this.combat.get(this.combat.size() - 1);
|
|
||||||
Entity lastEnt = last.getSource().getEntity();
|
|
||||||
|
|
||||||
if(fall != null && last.getSource() == DamageSource.fall) {
|
|
||||||
if(fall.getSource() != DamageSource.fall && fall.getSource() != DamageSource.outOfWorld) {
|
|
||||||
Entity fallEnt = fall.getSource().getEntity();
|
|
||||||
if(fallEnt != null && (lastEnt == null || fallEnt != lastEnt)) {
|
|
||||||
ItemStack fallItem = fallEnt instanceof EntityLiving ? ((EntityLiving)fallEnt).getHeldItem() : null;
|
|
||||||
receiver = fallEnt.isPlayer() ? ((EntityNPC)fallEnt).connection : null;
|
|
||||||
if(fallItem != null) { // && fallItem.hasDisplayName()) {
|
|
||||||
msg = String.format("%s wurde von %s mit %s zum Fallen verdammt", this.getColoredName(TextColor.CYAN),
|
|
||||||
fallEnt.getColoredName(TextColor.CYAN), fallItem.getColoredName(TextColor.CYAN));
|
|
||||||
kill = String.format(TextColor.CYAN + "* %s mit %s zum Fallen verdammt",
|
|
||||||
this.getColoredName(TextColor.CYAN), fallItem.getColoredName(TextColor.CYAN));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
msg = String.format("%s wurde von %s zum Fallen verdammt", this.getColoredName(TextColor.CYAN),
|
|
||||||
fallEnt.getColoredName(TextColor.CYAN));
|
|
||||||
kill = String.format(TextColor.CYAN + "* %s zum Fallen verdammt",
|
|
||||||
this.getColoredName(TextColor.CYAN));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(lastEnt != null) {
|
|
||||||
ItemStack lastItem = lastEnt instanceof EntityLiving ? ((EntityLiving)lastEnt).getHeldItem() : null;
|
|
||||||
receiver = lastEnt.isPlayer() ? ((EntityNPC)lastEnt).connection : null;
|
|
||||||
if(lastItem != null) { // && lastItem.hasDisplayName()) {
|
|
||||||
msg = String.format("%s fiel zu tief und wurde von %s mit %s erledigt",
|
|
||||||
this.getColoredName(TextColor.BLUE),
|
|
||||||
lastEnt.getColoredName(TextColor.BLUE), lastItem.getColoredName(TextColor.BLUE));
|
|
||||||
kill = String.format(TextColor.BLUE + "* %s mit %s erledigt",
|
|
||||||
this.getColoredName(TextColor.BLUE), lastItem.getColoredName(TextColor.BLUE));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
msg = String.format("%s fiel zu tief und wurde von %s erledigt", this.getColoredName(TextColor.BLUE),
|
|
||||||
lastEnt.getColoredName(TextColor.BLUE));
|
|
||||||
kill = String.format(TextColor.BLUE + "%s erledigt", this.getColoredName(TextColor.BLUE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
msg = kill = natural ? String.format("%s wurde zum Fallen verdammt", this.getColoredName(TextColor.CYAN)) : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
msg = kill = natural ? String.format("%s fiel " + (fall.getBlockType() == null ? "aus zu großer Höhe" : fall.getBlockType()),
|
|
||||||
this.getColoredName(TextColor.NEON)) : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
receiver = last.getSource().getEntity() != null && last.getSource().getEntity().isPlayer() ? ((EntityNPC)last.getSource().getEntity()).connection : null;
|
|
||||||
msg = natural || (last.getSource() instanceof EntityDamageSource ? last.getSource().getEntity() != null : this.getAttackingEntity() != null) ? last.getSource().getDeathMessage(this) : null;
|
|
||||||
kill = msg == null ? null : last.getSource().getKillMessage(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(msg == null)
|
|
||||||
return;
|
|
||||||
if(receiver != null)
|
|
||||||
receiver.addFeed(kill);
|
|
||||||
if(forAll)
|
|
||||||
for(IPlayer player : ((WorldServer)this.worldObj).getServer().getIPlayers()) {
|
|
||||||
if(player != receiver)
|
|
||||||
player.addFeed(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public EntityLiving getAttacking() {
|
|
||||||
EntityLiving entity = null;
|
|
||||||
EntityNPC player = null;
|
|
||||||
int edmg = 0;
|
|
||||||
int pdmg = 0;
|
|
||||||
for(CombatEntry entry : this.combat) {
|
|
||||||
if(entry.getSource().getEntity() != null && entry.getSource().getEntity().isPlayer() && (player == null || entry.getDamage() > pdmg)) {
|
|
||||||
pdmg = entry.getDamage();
|
|
||||||
player = (EntityNPC)entry.getSource().getEntity();
|
|
||||||
}
|
|
||||||
if(entry.getSource().getEntity() instanceof EntityLiving && (entity == null || entry.getDamage() > edmg)) {
|
|
||||||
edmg = entry.getDamage();
|
|
||||||
entity = (EntityLiving)entry.getSource().getEntity();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return player != null && pdmg >= edmg / 3 ? player : entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void resetCombat() {
|
|
||||||
int timeout = this.attacked ? 300 : 100;
|
|
||||||
if(this.damaged && (!this.isEntityAlive() || this.ticksExisted - this.lastDamaged > timeout)) {
|
|
||||||
this.damaged = false;
|
|
||||||
this.attacked = false;
|
|
||||||
this.combat.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSneakingVisually() {
|
public boolean isSneakingVisually() {
|
||||||
return this.isSneaking();
|
return this.isSneaking();
|
||||||
}
|
}
|
||||||
|
@ -2804,22 +2612,6 @@ public abstract class EntityLiving extends Entity
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxFallHeight() {
|
|
||||||
if(this.getAttackTarget() == null) {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int i = (int)((float)this.getHealth() - (float)this.getMaxHealth() * 0.33F);
|
|
||||||
// i = i - (3 - this.worldObj.getDifficulty().getId()) * 4;
|
|
||||||
|
|
||||||
if(i < 0) {
|
|
||||||
i = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i + 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// public boolean getCanSpawnHere() {
|
// public boolean getCanSpawnHere() {
|
||||||
// return true;
|
// return true;
|
||||||
// }
|
// }
|
||||||
|
@ -2882,34 +2674,8 @@ public abstract class EntityLiving extends Entity
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateEntityActionState() {
|
protected void updateEntityActionState() {
|
||||||
// ++this.entityAge;
|
if(this.node != null)
|
||||||
// this.worldObj.profiler.start("checkDespawn");
|
this.node.update();
|
||||||
// this.despawnEntity();
|
|
||||||
// this.worldObj.profiler.end();
|
|
||||||
// this.worldObj.profiler.start("sensing");
|
|
||||||
this.senses.clearSensingCache();
|
|
||||||
// this.worldObj.profiler.end();
|
|
||||||
// this.worldObj.profiler.start("targetSelector");
|
|
||||||
this.targets.onUpdateTasks();
|
|
||||||
// this.worldObj.profiler.end();
|
|
||||||
// this.worldObj.profiler.start("goalSelector");
|
|
||||||
this.tasks.onUpdateTasks();
|
|
||||||
// this.worldObj.profiler.end();
|
|
||||||
// this.worldObj.profiler.start("navigation");
|
|
||||||
this.navigator.onUpdateNavigation();
|
|
||||||
// this.worldObj.profiler.end();
|
|
||||||
// this.worldObj.profiler.start("mob tick");
|
|
||||||
this.updateAITasks();
|
|
||||||
// this.worldObj.profiler.end();
|
|
||||||
// this.worldObj.profiler.start("controls");
|
|
||||||
// this.worldObj.profiler.start("move");
|
|
||||||
this.moveHelper.onUpdateMoveHelper();
|
|
||||||
// this.worldObj.profiler.next("look");
|
|
||||||
this.lookHelper.onUpdateLook();
|
|
||||||
// this.worldObj.profiler.next("jump");
|
|
||||||
this.jumpHelper.doJump();
|
|
||||||
// this.worldObj.profiler.end();
|
|
||||||
// this.worldObj.profiler.end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// protected void despawnEntity() {
|
// protected void despawnEntity() {
|
||||||
|
@ -2968,122 +2734,11 @@ public abstract class EntityLiving extends Entity
|
||||||
// this.getAttributeMap().registerAttribute(Attributes.FOLLOW_RANGE).setBaseValue(16.0D);
|
// this.getAttributeMap().registerAttribute(Attributes.FOLLOW_RANGE).setBaseValue(16.0D);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
protected PathNavigate getNewNavigator(World worldIn) {
|
|
||||||
return new PathNavigateGround(this, worldIn);
|
|
||||||
}
|
|
||||||
|
|
||||||
public EntityLookHelper getLookHelper() {
|
|
||||||
return this.lookHelper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EntityMoveHelper getMoveHelper() {
|
|
||||||
return this.moveHelper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EntityJumpHelper getJumpHelper() {
|
|
||||||
return this.jumpHelper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PathNavigate getNavigator() {
|
|
||||||
return this.navigator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EntitySenses getEntitySenses() {
|
|
||||||
return this.senses;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EntityLiving getAttackTarget() {
|
|
||||||
return this.target;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAttackTarget(EntityLiving entitylivingbaseIn) {
|
|
||||||
this.target = entitylivingbaseIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
// public boolean canAttackClass(Class<? extends EntityLiving> cls) {
|
// public boolean canAttackClass(Class<? extends EntityLiving> cls) {
|
||||||
// return /* cls != EntityFireDemon.class && */
|
// return /* cls != EntityFireDemon.class && */
|
||||||
// ;
|
// ;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
protected void updateLeashedState() {
|
|
||||||
if(this.leashTag != null) {
|
|
||||||
this.recreateLeash();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.leashed) {
|
|
||||||
if(!this.isEntityAlive()) {
|
|
||||||
this.clearLeashed(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.leashedTo == null || this.leashedTo.dead) {
|
|
||||||
this.clearLeashed(true, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.getLeashed() && this.getLeashedTo() != null && this.getLeashedTo().worldObj == this.worldObj)
|
|
||||||
{
|
|
||||||
Entity entity = this.getLeashedTo();
|
|
||||||
this.setHomePosAndDistance(new BlockPos((int)entity.posX, (int)entity.posY, (int)entity.posZ), 5);
|
|
||||||
float f = this.getDistanceToEntity(entity);
|
|
||||||
|
|
||||||
if (this instanceof EntityTameable && ((EntityTameable)this).isSitting())
|
|
||||||
{
|
|
||||||
if (f > 10.0F)
|
|
||||||
{
|
|
||||||
this.clearLeashed(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.isMovementAITaskSet)
|
|
||||||
{
|
|
||||||
this.tasks.addTask(2, this.aiBase);
|
|
||||||
|
|
||||||
if (this.getNavigator() instanceof PathNavigateGround)
|
|
||||||
{
|
|
||||||
((PathNavigateGround)this.getNavigator()).setAvoidsWater(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isMovementAITaskSet = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onUpdateLeashed(f);
|
|
||||||
|
|
||||||
if (f > 4.0F)
|
|
||||||
{
|
|
||||||
this.getNavigator().tryMoveToEntityLiving(entity, 1.0D);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f > 6.0F)
|
|
||||||
{
|
|
||||||
double d0 = (entity.posX - this.posX) / (double)f;
|
|
||||||
double d1 = (entity.posY - this.posY) / (double)f;
|
|
||||||
double d2 = (entity.posZ - this.posZ) / (double)f;
|
|
||||||
this.motionX += d0 * Math.abs(d0) * 0.4D;
|
|
||||||
this.motionY += d1 * Math.abs(d1) * 0.4D;
|
|
||||||
this.motionZ += d2 * Math.abs(d2) * 0.4D;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f > 10.0F)
|
|
||||||
{
|
|
||||||
this.clearLeashed(true, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!this.getLeashed() && this.isMovementAITaskSet)
|
|
||||||
{
|
|
||||||
this.isMovementAITaskSet = false;
|
|
||||||
this.tasks.removeTask(this.aiBase);
|
|
||||||
|
|
||||||
if (this.getNavigator() instanceof PathNavigateGround)
|
|
||||||
{
|
|
||||||
((PathNavigateGround)this.getNavigator()).setAvoidsWater(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.detachHome();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearLeashed(boolean pkt, boolean dropLead) {
|
public void clearLeashed(boolean pkt, boolean dropLead) {
|
||||||
if(this.leashed) {
|
if(this.leashed) {
|
||||||
this.leashed = false;
|
this.leashed = false;
|
||||||
|
@ -3120,43 +2775,9 @@ public abstract class EntityLiving extends Entity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void recreateLeash() {
|
protected void updateDistance(float p_110146_1_, float p_110146_2_) {
|
||||||
if(this.leashed && this.leashTag != null) {
|
if(this.node != null)
|
||||||
// if(this.leashTag.hasKey("PlayerName", 8)) {
|
this.node.updateRenderAngles();
|
||||||
// String id = this.leashTag.getString("PlayerName");
|
|
||||||
// if(!id.isEmpty()) {
|
|
||||||
// for(EntityNPC entitylivingbase : this.worldObj.getEntitiesWithinAABB(EntityNPC.class,
|
|
||||||
// this.getEntityBoundingBox().expand(10.0D, 10.0D, 10.0D))) {
|
|
||||||
// if(entitylivingbase.getUser().equals(id)) {
|
|
||||||
// this.leashedTo = entitylivingbase;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
if(this.leashTag.hasKey("X", 99) && this.leashTag.hasKey("Y", 99) && this.leashTag.hasKey("Z", 99)) {
|
|
||||||
BlockPos blockpos = new BlockPos(this.leashTag.getInteger("X"), this.leashTag.getInteger("Y"),
|
|
||||||
this.leashTag.getInteger("Z"));
|
|
||||||
EntityLeashKnot entityleashknot = EntityLeashKnot.getKnotForPosition(this.worldObj, blockpos);
|
|
||||||
|
|
||||||
if(entityleashknot == null) {
|
|
||||||
entityleashknot = EntityLeashKnot.createKnot(this.worldObj, blockpos);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.leashedTo = entityleashknot;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.clearLeashed(false, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.leashTag = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected float updateDistance(float p_110146_1_, float p_110146_2_) {
|
|
||||||
this.bodyHelper.updateRenderAngles();
|
|
||||||
return p_110146_2_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemStack[] getInventory() {
|
public ItemStack[] getInventory() {
|
||||||
|
@ -3288,11 +2909,6 @@ public abstract class EntityLiving extends Entity
|
||||||
return this.getBlockPathWeight(new BlockPos(this.posX, this.getEntityBoundingBox().minY, this.posZ)) >= 0.0F;
|
return this.getBlockPathWeight(new BlockPos(this.posX, this.getEntityBoundingBox().minY, this.posZ)) >= 0.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPath()
|
|
||||||
{
|
|
||||||
return !this.navigator.noPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isWithinHomeDistanceCurrentPosition()
|
public boolean isWithinHomeDistanceCurrentPosition()
|
||||||
{
|
{
|
||||||
return this.isWithinHomeDistanceFromPosition(new BlockPos(this));
|
return this.isWithinHomeDistanceFromPosition(new BlockPos(this));
|
||||||
|
@ -3329,10 +2945,6 @@ public abstract class EntityLiving extends Entity
|
||||||
return this.maximumHomeDistance != -1.0F;
|
return this.maximumHomeDistance != -1.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onUpdateLeashed(float distance)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setSize(float width, float height)
|
protected void setSize(float width, float height)
|
||||||
{
|
{
|
||||||
boolean flag = this.ageWidth > 0.0F;
|
boolean flag = this.ageWidth > 0.0F;
|
||||||
|
|
224
server/src/server/ai/EntityNPCNode.java
Normal file
224
server/src/server/ai/EntityNPCNode.java
Normal file
|
@ -0,0 +1,224 @@
|
||||||
|
package server.ai;
|
||||||
|
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import common.ai.AIRangedAttack;
|
||||||
|
import common.ai.EntityAIAttackOnCollide;
|
||||||
|
import common.ai.EntityAIAvoidEntity;
|
||||||
|
import common.ai.EntityAIHurtByTarget;
|
||||||
|
import common.ai.EntityAILookAtTalkingPlayer;
|
||||||
|
import common.ai.EntityAINagPlayer;
|
||||||
|
import common.ai.EntityAINearestAttackableTarget;
|
||||||
|
import common.ai.EntityAINpcInteract;
|
||||||
|
import common.ai.EntityAINpcMate;
|
||||||
|
import common.ai.EntityAIOpenDoor;
|
||||||
|
import common.ai.EntityAIPlay;
|
||||||
|
import common.ai.EntityAISwimming;
|
||||||
|
import common.ai.EntityAIWander;
|
||||||
|
import common.ai.EntityAIWatchClosest;
|
||||||
|
import common.ai.EntityAIWatchClosest2;
|
||||||
|
import common.entity.npc.EntityNPC;
|
||||||
|
import common.entity.types.EntityLiving;
|
||||||
|
import common.item.ItemStack;
|
||||||
|
import common.pathfinding.PathNavigateGround;
|
||||||
|
|
||||||
|
public class EntityNPCNode extends EntityNode {
|
||||||
|
protected final EntityAIAttackOnCollide aiMelee;
|
||||||
|
protected final AIRangedAttack aiRanged;
|
||||||
|
private boolean fleeing;
|
||||||
|
|
||||||
|
public EntityNPCNode(EntityNPC entity) {
|
||||||
|
super(entity);
|
||||||
|
this.aiMelee = new EntityAIAttackOnCollide(entity, EntityLiving.class, 1.0D, true, true) {
|
||||||
|
public boolean shouldExecute()
|
||||||
|
{
|
||||||
|
return !EntityNPCNode.this.fleeing && super.shouldExecute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean continueExecuting()
|
||||||
|
{
|
||||||
|
return !EntityNPCNode.this.fleeing && super.shouldExecute();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.aiRanged = new AIRangedAttack(entity, 1.0D, entity.getAttackSpeed(), entity.getAttackSpeed() * 3, 15.0F) {
|
||||||
|
// public void startExecuting()
|
||||||
|
// {
|
||||||
|
// super.startExecuting();
|
||||||
|
// EntityNPC.this.setUsingItem(true);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public void resetTask()
|
||||||
|
// {
|
||||||
|
// super.resetTask();
|
||||||
|
// EntityNPC.this.setUsingItem(false);
|
||||||
|
// }
|
||||||
|
|
||||||
|
public boolean shouldExecute()
|
||||||
|
{
|
||||||
|
return !EntityNPCNode.this.fleeing && super.shouldExecute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean continueExecuting()
|
||||||
|
{
|
||||||
|
return !EntityNPCNode.this.fleeing && super.shouldExecute();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityNPC getEntity() {
|
||||||
|
return (EntityNPC)this.entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void registerTasks() {
|
||||||
|
if(this.getNavigator() instanceof PathNavigateGround) {
|
||||||
|
((PathNavigateGround)this.getNavigator()).setBreakDoors(true);
|
||||||
|
((PathNavigateGround)this.getNavigator()).setAvoidsWater(true);
|
||||||
|
}
|
||||||
|
this.tasks.addTask(0, new EntityAISwimming(this.getEntity()));
|
||||||
|
// this.tasks.addTask(1, new EntityAIAttackOnCollide(this, EntityNPC.class, 0.6D, true, true));
|
||||||
|
// this.tasks.addTask(1, new EntityAIAttackOnCollide(this, EntityLivingBase.class, 0.6D, true, true));
|
||||||
|
this.tasks.addTask(1, new EntityAINpcMate(this.getEntity()));
|
||||||
|
this.tasks.addTask(2, new EntityAIAvoidEntity(this.getEntity(), EntityLiving.class, new Predicate<EntityLiving>() {
|
||||||
|
public boolean test(EntityLiving entity) {
|
||||||
|
return entity != EntityNPCNode.this.entity && EntityNPC.this.shouldFlee(entity);
|
||||||
|
}
|
||||||
|
}, 8.0F, 1.1D, 1.1D) {
|
||||||
|
{
|
||||||
|
this.setMutexBits(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startExecuting() {
|
||||||
|
EntityNPCNode.this.setAttackTarget(null);
|
||||||
|
EntityNPCNode.this.fleeing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean continueExecuting() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateTask()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void resetTask() {
|
||||||
|
// super.resetTask();
|
||||||
|
// EntityNPC.this.isFleeing = false;
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityLiving.class, new Predicate<EntityLiving>() {
|
||||||
|
public boolean test(EntityLiving entity) {
|
||||||
|
return entity != EntityNPC.this && EntityNPC.this.shouldFlee(entity);
|
||||||
|
}
|
||||||
|
}, 8.0F, 1.1D, 1.1D) {
|
||||||
|
public void startExecuting() {
|
||||||
|
super.startExecuting();
|
||||||
|
EntityNPC.this.setAttackTarget(null);
|
||||||
|
EntityNPC.this.fleeing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetTask() {
|
||||||
|
super.resetTask();
|
||||||
|
EntityNPC.this.fleeing = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// this.tasks.addTask(2, new EntityAITempt(this, 1.0D, Items.golden_apple, false));
|
||||||
|
this.tasks.addTask(4, new EntityAIOpenDoor(this, true));
|
||||||
|
this.tasks.addTask(5, new EntityAINagPlayer(this));
|
||||||
|
this.tasks.addTask(5, new EntityAILookAtTalkingPlayer(this));
|
||||||
|
this.tasks.addTask(6, new EntityAIWatchClosest2(this, null, 3.0F, 1.0F) {
|
||||||
|
private int sneakTime;
|
||||||
|
|
||||||
|
public void updateTask()
|
||||||
|
{
|
||||||
|
super.updateTask();
|
||||||
|
boolean flag = this.closestEntity.isPlayer() && this.closestEntity.isSneaking();
|
||||||
|
if(this.sneakTime > 0) {
|
||||||
|
if(--this.sneakTime == 0) {
|
||||||
|
EntityNPC.this.setSneaking(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(EntityNPC.this.getAttackTarget() == null && EntityNPC.this.rand.chance(flag ? 5 : 200)) {
|
||||||
|
EntityNPC.this.setSneaking(true);
|
||||||
|
this.sneakTime = EntityNPC.this.rand.range(60, flag ? 160 : 120);
|
||||||
|
}
|
||||||
|
else if(EntityNPC.this.getAttackTarget() != null) {
|
||||||
|
EntityNPC.this.setSneaking(false);
|
||||||
|
this.sneakTime = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetTask()
|
||||||
|
{
|
||||||
|
super.resetTask();
|
||||||
|
EntityNPC.this.setSneaking(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.tasks.addTask(7, new EntityAINpcInteract(this));
|
||||||
|
this.tasks.addTask(8, new EntityAIWander(this, 1.0D));
|
||||||
|
this.tasks.addTask(8, new EntityAIPlay(this, 1.1D));
|
||||||
|
this.tasks.addTask(9, new EntityAIWatchClosest(this, EntityLiving.class, 8.0F));
|
||||||
|
this.targets.addTask(1, new EntityAIHurtByTarget(this, false, /* EntityNPC.class, */ EntityLiving.class) {
|
||||||
|
protected boolean isSuitableTarget(EntityLiving entity) {
|
||||||
|
if(entity != null && entity != EntityNPC.this && EntityNPC.this.shouldFlee(entity)) {
|
||||||
|
EntityNPC.this.setAttackTarget(null);
|
||||||
|
EntityNPC.this.fleeing = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return entity != null && entity != EntityNPC.this && (!(entity.isPlayer()) || EntityNPC.this.rand.chance(entity.getAttackedBy() == EntityNPC.this ? 2 : 4))
|
||||||
|
&& EntityNPC.this.canCounter(entity) && super.isSuitableTarget(entity);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.targets.addTask(2, new EntityAINearestAttackableTarget(this, EntityLiving.class, 10, true, false, new Predicate<EntityLiving>() {
|
||||||
|
public boolean test(EntityLiving entity) {
|
||||||
|
if(entity != null && entity != EntityNPC.this && EntityNPC.this.shouldFlee(entity)) {
|
||||||
|
EntityNPC.this.setAttackTarget(null);
|
||||||
|
EntityNPC.this.fleeing = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return entity != null && entity != EntityNPC.this && !EntityNPC.this.fleeing && EntityNPC.this.canAmbush(entity) && EntityNPC.this.canAttack(entity);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
// this.setCanPickUpLoot(true);
|
||||||
|
|
||||||
|
if (worldIn != null && !worldIn.client)
|
||||||
|
{
|
||||||
|
this.setCombatTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateLeashedState() {
|
||||||
|
if(!this.player)
|
||||||
|
super.updateLeashedState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendDeathMessage() {
|
||||||
|
this.sendDeathMessage(this.player, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxFallHeight()
|
||||||
|
{
|
||||||
|
return this.player ? 3 : super.getMaxFallHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCombatTask()
|
||||||
|
{
|
||||||
|
if(!this.player) {
|
||||||
|
this.tasks.removeTask(this.aiMelee);
|
||||||
|
this.tasks.removeTask(this.aiRanged);
|
||||||
|
ItemStack itemstack = this.getEntity().getHeldItem();
|
||||||
|
|
||||||
|
if (this.getEntity().isRangedWeapon(itemstack))
|
||||||
|
{
|
||||||
|
this.tasks.addTask(3, this.aiRanged);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.tasks.addTask(3, this.aiMelee);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFleeing() {
|
||||||
|
return this.fleeing;
|
||||||
|
}
|
||||||
|
}
|
436
server/src/server/ai/EntityNode.java
Normal file
436
server/src/server/ai/EntityNode.java
Normal file
|
@ -0,0 +1,436 @@
|
||||||
|
package server.ai;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import common.ai.EntityAIBase;
|
||||||
|
import common.ai.EntityAIMoveTowardsRestriction;
|
||||||
|
import common.ai.EntityAITasks;
|
||||||
|
import common.ai.EntityJumpHelper;
|
||||||
|
import common.ai.EntityLookHelper;
|
||||||
|
import common.ai.EntityMoveHelper;
|
||||||
|
import common.ai.EntitySenses;
|
||||||
|
import common.ai.IEntityNode;
|
||||||
|
import common.block.Block;
|
||||||
|
import common.collect.Lists;
|
||||||
|
import common.color.TextColor;
|
||||||
|
import common.entity.DamageSource;
|
||||||
|
import common.entity.Entity;
|
||||||
|
import common.entity.EntityDamageSource;
|
||||||
|
import common.entity.item.EntityLeashKnot;
|
||||||
|
import common.entity.npc.EntityNPC;
|
||||||
|
import common.entity.types.CombatEntry;
|
||||||
|
import common.entity.types.EntityBodyHelper;
|
||||||
|
import common.entity.types.EntityLiving;
|
||||||
|
import common.entity.types.EntityTameable;
|
||||||
|
import common.init.Blocks;
|
||||||
|
import common.item.ItemStack;
|
||||||
|
import common.nbt.NBTTagCompound;
|
||||||
|
import common.network.IPlayer;
|
||||||
|
import common.pathfinding.PathNavigate;
|
||||||
|
import common.pathfinding.PathNavigateGround;
|
||||||
|
import common.util.BlockPos;
|
||||||
|
import common.world.WorldServer;
|
||||||
|
|
||||||
|
public abstract class EntityNode implements IEntityNode {
|
||||||
|
protected final EntityLiving entity;
|
||||||
|
protected final boolean player;
|
||||||
|
private final List<CombatEntry> combat = Lists.<CombatEntry>newArrayList();
|
||||||
|
private EntityLookHelper lookHelper;
|
||||||
|
protected EntityMoveHelper moveHelper;
|
||||||
|
protected EntityJumpHelper jumpHelper;
|
||||||
|
private EntityBodyHelper bodyHelper;
|
||||||
|
protected PathNavigate navigator;
|
||||||
|
protected final EntityAITasks tasks;
|
||||||
|
protected final EntityAITasks targets;
|
||||||
|
private EntityLiving target;
|
||||||
|
private EntitySenses senses;
|
||||||
|
private Runnable tickFunc;
|
||||||
|
private NBTTagCompound leashTag;
|
||||||
|
private boolean isMovementAITaskSet;
|
||||||
|
private EntityAIBase aiBase;
|
||||||
|
private boolean attacked;
|
||||||
|
private boolean damaged;
|
||||||
|
private String blockType;
|
||||||
|
private int lastDamaged;
|
||||||
|
|
||||||
|
public EntityNode(EntityLiving entity) {
|
||||||
|
this.entity = entity;
|
||||||
|
this.player = entity.isPlayer();
|
||||||
|
this.tasks = new EntityAITasks();
|
||||||
|
this.targets = new EntityAITasks();
|
||||||
|
this.lookHelper = new EntityLookHelper(entity);
|
||||||
|
this.moveHelper = new EntityMoveHelper(entity);
|
||||||
|
this.jumpHelper = new EntityJumpHelper(entity);
|
||||||
|
this.bodyHelper = new EntityBodyHelper(entity);
|
||||||
|
this.navigator = this.getNewNavigator();
|
||||||
|
this.senses = new EntitySenses(entity);
|
||||||
|
this.aiBase = new EntityAIMoveTowardsRestriction(entity, 1.0D);
|
||||||
|
this.registerTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PathNavigate getNewNavigator() {
|
||||||
|
return new PathNavigateGround(this.entity, this.entity.worldObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// protected PathNavigate getNewNavigator() { EntityArachnoid
|
||||||
|
// return new PathNavigateClimber(this.entity, this.entity.worldObj);
|
||||||
|
// }
|
||||||
|
|
||||||
|
protected abstract void registerTasks();
|
||||||
|
|
||||||
|
public void setTickFunction(Runnable func) {
|
||||||
|
this.tickFunc = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityLookHelper getLookHelper() {
|
||||||
|
return this.lookHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityMoveHelper getMoveHelper() {
|
||||||
|
return this.moveHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityJumpHelper getJumpHelper() {
|
||||||
|
return this.jumpHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PathNavigate getNavigator() {
|
||||||
|
return this.navigator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntitySenses getEntitySenses() {
|
||||||
|
return this.senses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityLiving getAttackTarget() {
|
||||||
|
return this.target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttackTarget(EntityLiving entitylivingbaseIn) {
|
||||||
|
this.target = entitylivingbaseIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPath()
|
||||||
|
{
|
||||||
|
return !this.navigator.noPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateRenderAngles() {
|
||||||
|
this.bodyHelper.updateRenderAngles();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
this.senses.clearSensingCache();
|
||||||
|
this.targets.onUpdateTasks();
|
||||||
|
this.tasks.onUpdateTasks();
|
||||||
|
this.navigator.onUpdateNavigation();
|
||||||
|
if(this.tickFunc != null)
|
||||||
|
this.tickFunc.run();
|
||||||
|
this.moveHelper.onUpdateMoveHelper();
|
||||||
|
this.lookHelper.onUpdateLook();
|
||||||
|
this.jumpHelper.doJump();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLeashTag(NBTTagCompound tag) {
|
||||||
|
this.leashTag = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recreateLeash() {
|
||||||
|
if(this.entity.getLeashed() && this.leashTag != null) {
|
||||||
|
// if(this.leashTag.hasKey("PlayerName", 8)) {
|
||||||
|
// String id = this.leashTag.getString("PlayerName");
|
||||||
|
// if(!id.isEmpty()) {
|
||||||
|
// for(EntityNPC entitylivingbase : this.worldObj.getEntitiesWithinAABB(EntityNPC.class,
|
||||||
|
// this.getEntityBoundingBox().expand(10.0D, 10.0D, 10.0D))) {
|
||||||
|
// if(entitylivingbase.getUser().equals(id)) {
|
||||||
|
// this.leashedTo = entitylivingbase;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
if(this.leashTag.hasKey("X", 99) && this.leashTag.hasKey("Y", 99) && this.leashTag.hasKey("Z", 99)) {
|
||||||
|
BlockPos blockpos = new BlockPos(this.leashTag.getInteger("X"), this.leashTag.getInteger("Y"),
|
||||||
|
this.leashTag.getInteger("Z"));
|
||||||
|
EntityLeashKnot entityleashknot = EntityLeashKnot.getKnotForPosition(this.entity.worldObj, blockpos);
|
||||||
|
|
||||||
|
if(entityleashknot == null) {
|
||||||
|
entityleashknot = EntityLeashKnot.createKnot(this.entity.worldObj, blockpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.entity.setLeashedTo(entityleashknot, false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.entity.clearLeashed(false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.leashTag = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onUpdateLeashed(float distance)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// protected void onUpdateLeashed(float distance) EntityHorse
|
||||||
|
// {
|
||||||
|
// if (distance > 6.0F && this.entity.isEatingHaystack())
|
||||||
|
// {
|
||||||
|
// this.entity.setEatingHaystack(false);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void updateLeashedState() {
|
||||||
|
if(this.leashTag != null) {
|
||||||
|
this.recreateLeash();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.entity.getLeashed()) {
|
||||||
|
if(!this.entity.isEntityAlive()) {
|
||||||
|
this.entity.clearLeashed(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.entity.getLeashedTo() == null || this.entity.getLeashedTo().dead) {
|
||||||
|
this.entity.clearLeashed(true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.entity.getLeashed() && this.entity.getLeashedTo() != null && this.entity.getLeashedTo().worldObj == this.entity.worldObj)
|
||||||
|
{
|
||||||
|
Entity entity = this.entity.getLeashedTo();
|
||||||
|
this.entity.setHomePosAndDistance(new BlockPos((int)entity.posX, (int)entity.posY, (int)entity.posZ), 5);
|
||||||
|
float f = this.entity.getDistanceToEntity(entity);
|
||||||
|
|
||||||
|
if (this.entity instanceof EntityTameable && ((EntityTameable)this.entity).isSitting())
|
||||||
|
{
|
||||||
|
if (f > 10.0F)
|
||||||
|
{
|
||||||
|
this.entity.clearLeashed(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.isMovementAITaskSet)
|
||||||
|
{
|
||||||
|
this.tasks.addTask(2, this.aiBase);
|
||||||
|
|
||||||
|
if (this.getNavigator() instanceof PathNavigateGround)
|
||||||
|
{
|
||||||
|
((PathNavigateGround)this.getNavigator()).setAvoidsWater(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isMovementAITaskSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onUpdateLeashed(f);
|
||||||
|
|
||||||
|
if (f > 4.0F)
|
||||||
|
{
|
||||||
|
this.getNavigator().tryMoveToEntityLiving(entity, 1.0D);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f > 6.0F)
|
||||||
|
{
|
||||||
|
double d0 = (entity.posX - this.entity.posX) / (double)f;
|
||||||
|
double d1 = (entity.posY - this.entity.posY) / (double)f;
|
||||||
|
double d2 = (entity.posZ - this.entity.posZ) / (double)f;
|
||||||
|
this.entity.motionX += d0 * Math.abs(d0) * 0.4D;
|
||||||
|
this.entity.motionY += d1 * Math.abs(d1) * 0.4D;
|
||||||
|
this.entity.motionZ += d2 * Math.abs(d2) * 0.4D;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f > 10.0F)
|
||||||
|
{
|
||||||
|
this.entity.clearLeashed(true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!this.entity.getLeashed() && this.isMovementAITaskSet)
|
||||||
|
{
|
||||||
|
this.isMovementAITaskSet = false;
|
||||||
|
this.tasks.removeTask(this.aiBase);
|
||||||
|
|
||||||
|
if (this.getNavigator() instanceof PathNavigateGround)
|
||||||
|
{
|
||||||
|
((PathNavigateGround)this.getNavigator()).setAvoidsWater(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.entity.detachHome();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void trackDamage(DamageSource source, int amount) {
|
||||||
|
this.resetCombat();
|
||||||
|
this.blockType = null;
|
||||||
|
if(this.entity.isOnLadder()) {
|
||||||
|
Block block = this.entity.worldObj
|
||||||
|
.getState(new BlockPos(this.entity.posX, this.entity.getEntityBoundingBox().minY, this.entity.posZ)).getBlock();
|
||||||
|
if(block == Blocks.ladder)
|
||||||
|
this.blockType = "von einer Leiter";
|
||||||
|
else if(block == Blocks.vine)
|
||||||
|
this.blockType = "von Ranken";
|
||||||
|
}
|
||||||
|
else if(this.entity.isInLiquid()) {
|
||||||
|
this.blockType = "aus dem Wasser";
|
||||||
|
}
|
||||||
|
CombatEntry entry = new CombatEntry(source, amount, this.blockType, this.entity.fallDistance);
|
||||||
|
this.combat.add(entry);
|
||||||
|
this.lastDamaged = this.entity.ticksExisted;
|
||||||
|
this.damaged = true;
|
||||||
|
if(entry.getSource().getEntity() instanceof EntityLiving && !this.attacked && this.entity.isEntityAlive())
|
||||||
|
this.attacked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendDeathMessage() {
|
||||||
|
this.sendDeathMessage(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void sendDeathMessage(boolean natural, boolean forAll) {
|
||||||
|
// if(this.entity.worldObj.client)
|
||||||
|
// return;
|
||||||
|
String msg;
|
||||||
|
String kill;
|
||||||
|
IPlayer receiver = null;
|
||||||
|
if(this.combat.size() == 0) {
|
||||||
|
msg = kill = natural ? String.format("%s starb", this.entity.getColoredName(TextColor.LGRAY)) : null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CombatEntry strong = null;
|
||||||
|
CombatEntry block = null;
|
||||||
|
int min = 0;
|
||||||
|
float max = 0.0F;
|
||||||
|
|
||||||
|
for(int z = 0; z < this.combat.size(); ++z) {
|
||||||
|
CombatEntry entry = (CombatEntry)this.combat.get(z);
|
||||||
|
CombatEntry last = z > 0 ? (CombatEntry)this.combat.get(z - 1) : null;
|
||||||
|
|
||||||
|
if((entry.getSource() == DamageSource.fall || entry.getSource() == DamageSource.outOfWorld) &&
|
||||||
|
entry.getFallDistance() > 0.0F && (strong == null || entry.getFallDistance() > max)) {
|
||||||
|
if(z > 0) {
|
||||||
|
strong = last;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strong = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
max = entry.getFallDistance();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(entry.getBlockType() != null && (block == null || entry.getDamage() > min)) {
|
||||||
|
block = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CombatEntry fall = max > 5.0F && strong != null ? strong : (min > 5 && block != null ? block : null);
|
||||||
|
CombatEntry last = (CombatEntry)this.combat.get(this.combat.size() - 1);
|
||||||
|
Entity lastEnt = last.getSource().getEntity();
|
||||||
|
|
||||||
|
if(fall != null && last.getSource() == DamageSource.fall) {
|
||||||
|
if(fall.getSource() != DamageSource.fall && fall.getSource() != DamageSource.outOfWorld) {
|
||||||
|
Entity fallEnt = fall.getSource().getEntity();
|
||||||
|
if(fallEnt != null && (lastEnt == null || fallEnt != lastEnt)) {
|
||||||
|
ItemStack fallItem = fallEnt instanceof EntityLiving ? ((EntityLiving)fallEnt).getHeldItem() : null;
|
||||||
|
receiver = fallEnt.isPlayer() ? ((EntityNPC)fallEnt).connection : null;
|
||||||
|
if(fallItem != null) { // && fallItem.hasDisplayName()) {
|
||||||
|
msg = String.format("%s wurde von %s mit %s zum Fallen verdammt", this.entity.getColoredName(TextColor.CYAN),
|
||||||
|
fallEnt.getColoredName(TextColor.CYAN), fallItem.getColoredName(TextColor.CYAN));
|
||||||
|
kill = String.format(TextColor.CYAN + "* %s mit %s zum Fallen verdammt",
|
||||||
|
this.entity.getColoredName(TextColor.CYAN), fallItem.getColoredName(TextColor.CYAN));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg = String.format("%s wurde von %s zum Fallen verdammt", this.entity.getColoredName(TextColor.CYAN),
|
||||||
|
fallEnt.getColoredName(TextColor.CYAN));
|
||||||
|
kill = String.format(TextColor.CYAN + "* %s zum Fallen verdammt",
|
||||||
|
this.entity.getColoredName(TextColor.CYAN));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(lastEnt != null) {
|
||||||
|
ItemStack lastItem = lastEnt instanceof EntityLiving ? ((EntityLiving)lastEnt).getHeldItem() : null;
|
||||||
|
receiver = lastEnt.isPlayer() ? ((EntityNPC)lastEnt).connection : null;
|
||||||
|
if(lastItem != null) { // && lastItem.hasDisplayName()) {
|
||||||
|
msg = String.format("%s fiel zu tief und wurde von %s mit %s erledigt",
|
||||||
|
this.entity.getColoredName(TextColor.BLUE),
|
||||||
|
lastEnt.getColoredName(TextColor.BLUE), lastItem.getColoredName(TextColor.BLUE));
|
||||||
|
kill = String.format(TextColor.BLUE + "* %s mit %s erledigt",
|
||||||
|
this.entity.getColoredName(TextColor.BLUE), lastItem.getColoredName(TextColor.BLUE));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg = String.format("%s fiel zu tief und wurde von %s erledigt", this.entity.getColoredName(TextColor.BLUE),
|
||||||
|
lastEnt.getColoredName(TextColor.BLUE));
|
||||||
|
kill = String.format(TextColor.BLUE + "%s erledigt", this.entity.getColoredName(TextColor.BLUE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg = kill = natural ? String.format("%s wurde zum Fallen verdammt", this.entity.getColoredName(TextColor.CYAN)) : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg = kill = natural ? String.format("%s fiel " + (fall.getBlockType() == null ? "aus zu großer Höhe" : fall.getBlockType()),
|
||||||
|
this.entity.getColoredName(TextColor.NEON)) : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
receiver = last.getSource().getEntity() != null && last.getSource().getEntity().isPlayer() ? ((EntityNPC)last.getSource().getEntity()).connection : null;
|
||||||
|
msg = natural || (last.getSource() instanceof EntityDamageSource ? last.getSource().getEntity() != null : this.entity.getAttackingEntity() != null) ? last.getSource().getDeathMessage(this.entity) : null;
|
||||||
|
kill = msg == null ? null : last.getSource().getKillMessage(this.entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(msg == null)
|
||||||
|
return;
|
||||||
|
if(receiver != null)
|
||||||
|
receiver.addFeed(kill);
|
||||||
|
if(forAll)
|
||||||
|
for(IPlayer player : ((WorldServer)this.entity.worldObj).getServer().getIPlayers()) {
|
||||||
|
if(player != receiver)
|
||||||
|
player.addFeed(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityLiving getAttacking() {
|
||||||
|
EntityLiving entity = null;
|
||||||
|
EntityNPC player = null;
|
||||||
|
int edmg = 0;
|
||||||
|
int pdmg = 0;
|
||||||
|
for(CombatEntry entry : this.combat) {
|
||||||
|
if(entry.getSource().getEntity() != null && entry.getSource().getEntity().isPlayer() && (player == null || entry.getDamage() > pdmg)) {
|
||||||
|
pdmg = entry.getDamage();
|
||||||
|
player = (EntityNPC)entry.getSource().getEntity();
|
||||||
|
}
|
||||||
|
if(entry.getSource().getEntity() instanceof EntityLiving && (entity == null || entry.getDamage() > edmg)) {
|
||||||
|
edmg = entry.getDamage();
|
||||||
|
entity = (EntityLiving)entry.getSource().getEntity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return player != null && pdmg >= edmg / 3 ? player : entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetCombat() {
|
||||||
|
int timeout = this.attacked ? 300 : 100;
|
||||||
|
if(this.damaged && (!this.entity.isEntityAlive() || this.entity.ticksExisted - this.lastDamaged > timeout)) {
|
||||||
|
this.damaged = false;
|
||||||
|
this.attacked = false;
|
||||||
|
this.combat.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxFallHeight() {
|
||||||
|
if(this.target == null) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int i = (int)((float)this.entity.getHealth() - (float)this.entity.getMaxHealth() * 0.33F);
|
||||||
|
// i = i - (3 - this.worldObj.getDifficulty().getId()) * 4;
|
||||||
|
|
||||||
|
if(i < 0) {
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i + 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// public int getMaxFallHeight() EntityHaunter
|
||||||
|
// {
|
||||||
|
// return this.getAttackTarget() == null ? 3 : 3 + (this.getHealth() - 1);
|
||||||
|
// }
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue