2677 lines
79 KiB
Java
Executable file
2677 lines
79 KiB
Java
Executable file
package game.entity;
|
|
|
|
import java.util.List;
|
|
|
|
import game.audio.SoundType;
|
|
import game.block.Block;
|
|
import game.block.BlockFence;
|
|
import game.block.BlockFenceGate;
|
|
import game.block.BlockLiquid;
|
|
import game.block.BlockWall;
|
|
import game.color.TextColor;
|
|
import game.dimension.DimType;
|
|
import game.enchantment.EnchantmentHelper;
|
|
import game.enchantment.EnchantmentProtection;
|
|
import game.entity.effect.EntityLightning;
|
|
import game.entity.item.EntityItem;
|
|
import game.entity.npc.EntityNPC;
|
|
import game.entity.types.EntityLiving;
|
|
import game.init.BlockRegistry;
|
|
import game.init.Blocks;
|
|
import game.init.Config;
|
|
import game.init.EntityRegistry;
|
|
import game.init.ItemRegistry;
|
|
import game.init.SoundEvent;
|
|
import game.init.UniverseRegistry;
|
|
import game.item.Item;
|
|
import game.item.ItemStack;
|
|
import game.material.Material;
|
|
import game.nbt.NBTTagCompound;
|
|
import game.nbt.NBTTagDouble;
|
|
import game.nbt.NBTTagFloat;
|
|
import game.nbt.NBTTagList;
|
|
import game.renderer.particle.ParticleType;
|
|
import game.rng.Random;
|
|
import game.util.ExtMath;
|
|
import game.world.BlockPos;
|
|
import game.world.BoundingBox;
|
|
import game.world.Explosion;
|
|
import game.world.Facing;
|
|
import game.world.HitPosition;
|
|
import game.world.PortalType;
|
|
import game.world.Position;
|
|
import game.world.State;
|
|
import game.world.Vec3;
|
|
import game.world.World;
|
|
import game.world.WorldServer;
|
|
|
|
public abstract class Entity
|
|
{
|
|
private static final BoundingBox ZERO_AABB = new BoundingBox(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D);
|
|
private static int nextID;
|
|
|
|
protected final DataWatcher dataWatcher;
|
|
protected final Random rand;
|
|
|
|
private int eid;
|
|
public World worldObj;
|
|
private BoundingBox bbox;
|
|
public Entity passenger;
|
|
public Entity vehicle;
|
|
|
|
public double renderDistWeight;
|
|
public boolean preventSpawning;
|
|
public boolean forceSpawn;
|
|
public boolean ignoreFall;
|
|
public double prevX;
|
|
public double prevY;
|
|
public double prevZ;
|
|
public double posX;
|
|
public double posY;
|
|
public double posZ;
|
|
public double motionX;
|
|
public double motionY;
|
|
public double motionZ;
|
|
public float rotYaw;
|
|
public float rotPitch;
|
|
public float prevYaw;
|
|
public float prevPitch;
|
|
public boolean onGround;
|
|
public boolean collidedHorizontally;
|
|
public boolean collidedVertically;
|
|
public boolean collided;
|
|
public boolean veloChanged;
|
|
protected boolean inWeb;
|
|
private boolean outsideBorder;
|
|
public boolean dead;
|
|
public float width;
|
|
public float height;
|
|
public float prevWalkDistMod;
|
|
public float walkDistMod;
|
|
public float stepDistMod;
|
|
public float fallDistance;
|
|
private int nextStepDist;
|
|
public double lastTickPosX;
|
|
public double lastTickPosY;
|
|
public double lastTickPosZ;
|
|
public float stepHeight;
|
|
public boolean noClip;
|
|
public float collisionReduction;
|
|
public int ticksExisted;
|
|
public int fireResistance;
|
|
private int fire;
|
|
protected boolean inLiquid;
|
|
public int hurtResistance;
|
|
protected boolean firstUpdate;
|
|
// protected boolean fireImmune;
|
|
private double riderPitchDelta;
|
|
private double riderYawDelta;
|
|
public boolean addedToChunk;
|
|
public int chunkCoordX;
|
|
public int chunkCoordY;
|
|
public int chunkCoordZ;
|
|
public int serverPosX;
|
|
public int serverPosY;
|
|
public int serverPosZ;
|
|
public boolean noFrustumCheck;
|
|
public boolean isAirBorne;
|
|
protected PortalType inPortal;
|
|
// private boolean invulnerable;
|
|
|
|
public int getId()
|
|
{
|
|
return this.eid;
|
|
}
|
|
|
|
public void setId(int id)
|
|
{
|
|
this.eid = id;
|
|
}
|
|
|
|
public Entity(World worldIn)
|
|
{
|
|
this.eid = nextID++;
|
|
// if(!worldIn.client && Config.persistEntities) {
|
|
// do {
|
|
// this.persistentId = Server.getServer().getRNG().longv();
|
|
// }
|
|
// while(this.persistentId == 0L);
|
|
// }
|
|
this.renderDistWeight = 1.0D;
|
|
this.bbox = ZERO_AABB;
|
|
this.width = 0.6F;
|
|
this.height = 1.8F;
|
|
this.nextStepDist = 1;
|
|
this.rand = new Random();
|
|
this.fireResistance = 1;
|
|
this.firstUpdate = true;
|
|
this.worldObj = worldIn;
|
|
this.setPosition(0.0D, 0.0D, 0.0D);
|
|
|
|
this.dataWatcher = new DataWatcher(this);
|
|
this.dataWatcher.addObject(0, Byte.valueOf((byte)0));
|
|
// this.dataWatcher.addObject(1, Short.valueOf((short)300));
|
|
// this.dataWatcher.addObject(3, Byte.valueOf((byte)0));
|
|
this.dataWatcher.addObject(1, "");
|
|
// this.dataWatcher.addObject(4, Byte.valueOf((byte)0));
|
|
this.entityInit();
|
|
}
|
|
|
|
protected abstract void entityInit();
|
|
|
|
public final DataWatcher getDataWatcher()
|
|
{
|
|
return this.dataWatcher;
|
|
}
|
|
|
|
public boolean equals(Object obj)
|
|
{
|
|
return obj instanceof Entity ? ((Entity)obj).eid == this.eid : false;
|
|
}
|
|
|
|
public int hashCode()
|
|
{
|
|
return this.eid;
|
|
}
|
|
|
|
/**
|
|
* Keeps moving the entity up so it isn't colliding with blocks and other requirements for this entity to be spawned
|
|
* (only actually used on players though its also on Entity)
|
|
*/
|
|
protected void preparePlayerToSpawn()
|
|
{
|
|
if (this.worldObj != null)
|
|
{
|
|
while (this.posY > 0.0D && this.posY < 512.0D)
|
|
{
|
|
this.setPosition(this.posX, this.posY, this.posZ);
|
|
|
|
if (this.worldObj.getCollidingBoundingBoxes(this, this.getEntityBoundingBox()).isEmpty())
|
|
{
|
|
break;
|
|
}
|
|
|
|
++this.posY;
|
|
}
|
|
|
|
this.motionX = this.motionY = this.motionZ = 0.0D;
|
|
this.rotPitch = 0.0F;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Will get destroyed next tick.
|
|
*/
|
|
public void setDead()
|
|
{
|
|
this.dead = true;
|
|
}
|
|
|
|
/**
|
|
* Sets the width and height of the entity. Args: width, height
|
|
*/
|
|
protected void setSize(float width, float height)
|
|
{
|
|
if (width != this.width || height != this.height)
|
|
{
|
|
float f = this.width;
|
|
this.width = width;
|
|
this.height = height;
|
|
this.setEntityBoundingBox(new BoundingBox(this.getEntityBoundingBox().minX, this.getEntityBoundingBox().minY, this.getEntityBoundingBox().minZ, this.getEntityBoundingBox().minX + (double)this.width, this.getEntityBoundingBox().minY + (double)this.height, this.getEntityBoundingBox().minZ + (double)this.width));
|
|
|
|
if (this.width > f && !this.firstUpdate && !this.worldObj.client)
|
|
{
|
|
this.moveEntity((double)(f - this.width), 0.0D, (double)(f - this.width));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the rotation of the entity. Args: yaw, pitch (both in degrees)
|
|
*/
|
|
protected void setRotation(float yaw, float pitch)
|
|
{
|
|
this.rotYaw = yaw % 360.0F;
|
|
this.rotPitch = pitch % 360.0F;
|
|
}
|
|
|
|
/**
|
|
* Sets the x,y,z of the entity from the given parameters. Also seems to set up a bounding box.
|
|
*/
|
|
public void setPosition(double x, double y, double z)
|
|
{
|
|
this.posX = x;
|
|
this.posY = y;
|
|
this.posZ = z;
|
|
float f = this.width / 2.0F;
|
|
float f1 = this.height;
|
|
this.setEntityBoundingBox(new BoundingBox(x - (double)f, y, z - (double)f, x + (double)f, y + (double)f1, z + (double)f));
|
|
}
|
|
|
|
/**
|
|
* Adds 15% to the entity's yaw and subtracts 15% from the pitch. Clamps pitch from -90 to 90. Both arguments in
|
|
* degrees.
|
|
*/
|
|
public void setAngles(float yaw, float pitch)
|
|
{
|
|
float f = this.rotPitch;
|
|
float f1 = this.rotYaw;
|
|
this.rotYaw = (float)((double)this.rotYaw + (double)yaw * 0.15D);
|
|
this.rotPitch = (float)((double)this.rotPitch - (double)pitch * 0.15D);
|
|
this.rotPitch = ExtMath.clampf(this.rotPitch, -90.0F, 90.0F);
|
|
this.prevPitch += this.rotPitch - f;
|
|
this.prevYaw += this.rotYaw - f1;
|
|
}
|
|
|
|
/**
|
|
* Called to update the entity's position/logic.
|
|
*/
|
|
public void onUpdate()
|
|
{
|
|
this.onEntityUpdate();
|
|
}
|
|
|
|
protected void checkPortal() {
|
|
if(this.inPortal != null) {
|
|
if(this.vehicle == null && this.passenger == null && Config.portals) {
|
|
int current = this.worldObj.dimension.getDimensionId();
|
|
int dest = UniverseRegistry.getPortalDest(current, this.inPortal);
|
|
if(dest != current) {
|
|
this.travelToDimension(dest, null, 0.0f, 0.0f, this.inPortal);
|
|
this.inPortal = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets called every tick from main Entity class
|
|
*/
|
|
public void onEntityUpdate()
|
|
{
|
|
// this.worldObj.profiler.start("entityBaseTick");
|
|
|
|
if (this.vehicle != null && this.vehicle.dead)
|
|
{
|
|
this.vehicle = null;
|
|
}
|
|
|
|
this.prevWalkDistMod = this.walkDistMod;
|
|
this.prevX = this.posX;
|
|
this.prevY = this.posY;
|
|
this.prevZ = this.posZ;
|
|
this.prevPitch = this.rotPitch;
|
|
this.prevYaw = this.rotYaw;
|
|
|
|
if (!this.worldObj.client)
|
|
{
|
|
this.checkPortal();
|
|
}
|
|
|
|
this.spawnRunningParticles();
|
|
this.handleWaterMovement();
|
|
|
|
if (this.worldObj.client)
|
|
{
|
|
this.fire = 0;
|
|
}
|
|
else if (this.fire > 0)
|
|
{
|
|
if (this.isImmuneToFire())
|
|
{
|
|
this.fire -= 4;
|
|
|
|
if (this.fire < 0)
|
|
{
|
|
this.fire = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Config.damageFire && this.fire % 20 == 0)
|
|
{
|
|
this.attackEntityFrom(DamageSource.onFire, 1);
|
|
}
|
|
|
|
--this.fire;
|
|
}
|
|
}
|
|
|
|
if (this.isInMolten())
|
|
{
|
|
this.setOnFireFromLava();
|
|
this.fallDistance *= 0.5F;
|
|
}
|
|
else if(this.worldObj.canBurnAt(this.getPosition()) && this.isInDownfall()) {
|
|
this.setOnFireFromMolten();
|
|
}
|
|
|
|
if (this.posY < -64.0D)
|
|
{
|
|
this.onVoidUpdate();
|
|
}
|
|
|
|
if (!this.worldObj.client)
|
|
{
|
|
this.setFlag(0, this.fire > 0);
|
|
}
|
|
|
|
this.firstUpdate = false;
|
|
// this.worldObj.profiler.end();
|
|
}
|
|
|
|
protected void onVoidUpdate() {
|
|
if(!this.worldObj.client && this.worldObj.dimension.getType() != DimType.SPACE) {
|
|
// this.worldObj.profiler.start("descent");
|
|
int current = this.worldObj.dimension.getDimensionId();
|
|
int dim = Config.voidPortal ? UniverseRegistry.getPortalDest(current, PortalType.VOID) : current;
|
|
if(dim == current) { // && (!(this.isPlayer()) || !((EntityNPCMP)this).creative)) {
|
|
this.kill();
|
|
}
|
|
// else if(dim == current) {
|
|
// this.setY((float)ExtMath.clampi(Config.portalHeight, 0, 16384));
|
|
// this.ignoreFall = true;
|
|
// }
|
|
else if(this.vehicle == null && this.passenger == null) {
|
|
Entity ent = this.travelToDimension(dim,
|
|
new BlockPos(this.posX, (float)ExtMath.clampi(Config.portalHeight, 0, 16384), this.posZ),
|
|
this.rotYaw, this.rotPitch, PortalType.VOID);
|
|
ent.ignoreFall = true;
|
|
}
|
|
// this.worldObj.profiler.end();
|
|
}
|
|
// else if(this.worldObj.dimension.getGravity() != 0.0f) {
|
|
// this.kill();
|
|
// }
|
|
}
|
|
|
|
// /**
|
|
// * Return the amount of time this entity should stay in a portal before being transported.
|
|
// */
|
|
// public int getMaxInPortalTime()
|
|
// {
|
|
// return 0;
|
|
// }
|
|
|
|
/**
|
|
* Called whenever the entity is walking inside of lava.
|
|
*/
|
|
protected void setOnFireFromLava()
|
|
{
|
|
if (!this.isImmuneToFire())
|
|
{
|
|
if(Config.damageLava)
|
|
this.attackEntityFrom(DamageSource.hotLiquid, 4);
|
|
this.setFire(15);
|
|
}
|
|
}
|
|
|
|
protected void setOnFireFromMolten()
|
|
{
|
|
if (!this.isImmuneToFire())
|
|
{
|
|
if(Config.damageMolten)
|
|
this.attackEntityFrom(DamageSource.molten, 2);
|
|
this.setFire(10);
|
|
}
|
|
}
|
|
|
|
public void setOnFireFromObject(int ticks)
|
|
{
|
|
if(!this.isImmuneToFire())
|
|
this.setFire(ticks);
|
|
}
|
|
|
|
/**
|
|
* Sets entity to burn for x amount of seconds, cannot lower amount of existing fire.
|
|
*/
|
|
public void setFire(int seconds)
|
|
{
|
|
int i = seconds * 20;
|
|
i = EnchantmentProtection.getFireTimeForEntity(this, i);
|
|
|
|
if (this.fire < i)
|
|
{
|
|
this.fire = i;
|
|
}
|
|
}
|
|
|
|
public void setFire()
|
|
{
|
|
this.fire = Integer.MAX_VALUE / 2;
|
|
}
|
|
|
|
/**
|
|
* Removes fire from entity.
|
|
*/
|
|
public void extinguish()
|
|
{
|
|
this.fire = 0;
|
|
}
|
|
|
|
protected void kill()
|
|
{
|
|
this.setDead();
|
|
}
|
|
|
|
/**
|
|
* Checks if the offset position from the entity's current position is inside of liquid. Args: x, y, z
|
|
*/
|
|
public boolean isOffsetPositionInLiquid(double x, double y, double z)
|
|
{
|
|
BoundingBox axisalignedbb = this.getEntityBoundingBox().offset(x, y, z);
|
|
return this.isLiquidPresentInAABB(axisalignedbb);
|
|
}
|
|
|
|
/**
|
|
* Determines if a liquid is present within the specified AxisAlignedBB.
|
|
*/
|
|
private boolean isLiquidPresentInAABB(BoundingBox bb)
|
|
{
|
|
return this.worldObj.getCollidingBoundingBoxes(this, bb).isEmpty() && !this.worldObj.isAnyLiquid(bb);
|
|
}
|
|
|
|
/**
|
|
* Tries to moves the entity by the passed in displacement. Args: x, y, z
|
|
*/
|
|
public void moveEntity(double x, double y, double z)
|
|
{
|
|
if (this.noClip)
|
|
{
|
|
this.setEntityBoundingBox(this.getEntityBoundingBox().offset(x, y, z));
|
|
this.resetPositionToBB();
|
|
}
|
|
else
|
|
{
|
|
// this.worldObj.profiler.start("move");
|
|
double d0 = this.posX;
|
|
double d1 = this.posY;
|
|
double d2 = this.posZ;
|
|
|
|
if (this.inWeb)
|
|
{
|
|
this.inWeb = false;
|
|
x *= 0.25D;
|
|
y *= 0.05000000074505806D;
|
|
z *= 0.25D;
|
|
this.motionX = 0.0D;
|
|
this.motionY = 0.0D;
|
|
this.motionZ = 0.0D;
|
|
}
|
|
|
|
double d3 = x;
|
|
double d4 = y;
|
|
double d5 = z;
|
|
boolean flag = this.onGround && this.isSneaking() && this.isPlayer();
|
|
|
|
if (flag)
|
|
{
|
|
double d6;
|
|
|
|
for (d6 = 0.05D; x != 0.0D && this.worldObj.getCollidingBoundingBoxes(this, this.getEntityBoundingBox().offset(x, -1.0D, 0.0D)).isEmpty(); d3 = x)
|
|
{
|
|
if (x < d6 && x >= -d6)
|
|
{
|
|
x = 0.0D;
|
|
}
|
|
else if (x > 0.0D)
|
|
{
|
|
x -= d6;
|
|
}
|
|
else
|
|
{
|
|
x += d6;
|
|
}
|
|
}
|
|
|
|
for (; z != 0.0D && this.worldObj.getCollidingBoundingBoxes(this, this.getEntityBoundingBox().offset(0.0D, -1.0D, z)).isEmpty(); d5 = z)
|
|
{
|
|
if (z < d6 && z >= -d6)
|
|
{
|
|
z = 0.0D;
|
|
}
|
|
else if (z > 0.0D)
|
|
{
|
|
z -= d6;
|
|
}
|
|
else
|
|
{
|
|
z += d6;
|
|
}
|
|
}
|
|
|
|
for (; x != 0.0D && z != 0.0D && this.worldObj.getCollidingBoundingBoxes(this, this.getEntityBoundingBox().offset(x, -1.0D, z)).isEmpty(); d5 = z)
|
|
{
|
|
if (x < d6 && x >= -d6)
|
|
{
|
|
x = 0.0D;
|
|
}
|
|
else if (x > 0.0D)
|
|
{
|
|
x -= d6;
|
|
}
|
|
else
|
|
{
|
|
x += d6;
|
|
}
|
|
|
|
d3 = x;
|
|
|
|
if (z < d6 && z >= -d6)
|
|
{
|
|
z = 0.0D;
|
|
}
|
|
else if (z > 0.0D)
|
|
{
|
|
z -= d6;
|
|
}
|
|
else
|
|
{
|
|
z += d6;
|
|
}
|
|
}
|
|
}
|
|
|
|
List<BoundingBox> list1 = this.worldObj.getCollidingBoundingBoxes(this, this.getEntityBoundingBox().addCoord(x, y, z));
|
|
BoundingBox axisalignedbb = this.getEntityBoundingBox();
|
|
|
|
for (BoundingBox axisalignedbb1 : list1)
|
|
{
|
|
y = axisalignedbb1.calculateYOffset(this.getEntityBoundingBox(), y);
|
|
}
|
|
|
|
this.setEntityBoundingBox(this.getEntityBoundingBox().offset(0.0D, y, 0.0D));
|
|
boolean flag1 = this.onGround || d4 != y && d4 < 0.0D;
|
|
|
|
for (BoundingBox axisalignedbb2 : list1)
|
|
{
|
|
x = axisalignedbb2.calculateXOffset(this.getEntityBoundingBox(), x);
|
|
}
|
|
|
|
this.setEntityBoundingBox(this.getEntityBoundingBox().offset(x, 0.0D, 0.0D));
|
|
|
|
for (BoundingBox axisalignedbb13 : list1)
|
|
{
|
|
z = axisalignedbb13.calculateZOffset(this.getEntityBoundingBox(), z);
|
|
}
|
|
|
|
this.setEntityBoundingBox(this.getEntityBoundingBox().offset(0.0D, 0.0D, z));
|
|
|
|
if (this.stepHeight > 0.0F && flag1 && (d3 != x || d5 != z))
|
|
{
|
|
double d11 = x;
|
|
double d7 = y;
|
|
double d8 = z;
|
|
BoundingBox axisalignedbb3 = this.getEntityBoundingBox();
|
|
this.setEntityBoundingBox(axisalignedbb);
|
|
y = (double)this.stepHeight;
|
|
List<BoundingBox> list = this.worldObj.getCollidingBoundingBoxes(this, this.getEntityBoundingBox().addCoord(d3, y, d5));
|
|
BoundingBox axisalignedbb4 = this.getEntityBoundingBox();
|
|
BoundingBox axisalignedbb5 = axisalignedbb4.addCoord(d3, 0.0D, d5);
|
|
double d9 = y;
|
|
|
|
for (BoundingBox axisalignedbb6 : list)
|
|
{
|
|
d9 = axisalignedbb6.calculateYOffset(axisalignedbb5, d9);
|
|
}
|
|
|
|
axisalignedbb4 = axisalignedbb4.offset(0.0D, d9, 0.0D);
|
|
double d15 = d3;
|
|
|
|
for (BoundingBox axisalignedbb7 : list)
|
|
{
|
|
d15 = axisalignedbb7.calculateXOffset(axisalignedbb4, d15);
|
|
}
|
|
|
|
axisalignedbb4 = axisalignedbb4.offset(d15, 0.0D, 0.0D);
|
|
double d16 = d5;
|
|
|
|
for (BoundingBox axisalignedbb8 : list)
|
|
{
|
|
d16 = axisalignedbb8.calculateZOffset(axisalignedbb4, d16);
|
|
}
|
|
|
|
axisalignedbb4 = axisalignedbb4.offset(0.0D, 0.0D, d16);
|
|
BoundingBox axisalignedbb14 = this.getEntityBoundingBox();
|
|
double d17 = y;
|
|
|
|
for (BoundingBox axisalignedbb9 : list)
|
|
{
|
|
d17 = axisalignedbb9.calculateYOffset(axisalignedbb14, d17);
|
|
}
|
|
|
|
axisalignedbb14 = axisalignedbb14.offset(0.0D, d17, 0.0D);
|
|
double d18 = d3;
|
|
|
|
for (BoundingBox axisalignedbb10 : list)
|
|
{
|
|
d18 = axisalignedbb10.calculateXOffset(axisalignedbb14, d18);
|
|
}
|
|
|
|
axisalignedbb14 = axisalignedbb14.offset(d18, 0.0D, 0.0D);
|
|
double d19 = d5;
|
|
|
|
for (BoundingBox axisalignedbb11 : list)
|
|
{
|
|
d19 = axisalignedbb11.calculateZOffset(axisalignedbb14, d19);
|
|
}
|
|
|
|
axisalignedbb14 = axisalignedbb14.offset(0.0D, 0.0D, d19);
|
|
double d20 = d15 * d15 + d16 * d16;
|
|
double d10 = d18 * d18 + d19 * d19;
|
|
|
|
if (d20 > d10)
|
|
{
|
|
x = d15;
|
|
z = d16;
|
|
y = -d9;
|
|
this.setEntityBoundingBox(axisalignedbb4);
|
|
}
|
|
else
|
|
{
|
|
x = d18;
|
|
z = d19;
|
|
y = -d17;
|
|
this.setEntityBoundingBox(axisalignedbb14);
|
|
}
|
|
|
|
for (BoundingBox axisalignedbb12 : list)
|
|
{
|
|
y = axisalignedbb12.calculateYOffset(this.getEntityBoundingBox(), y);
|
|
}
|
|
|
|
this.setEntityBoundingBox(this.getEntityBoundingBox().offset(0.0D, y, 0.0D));
|
|
|
|
if (d11 * d11 + d8 * d8 >= x * x + z * z)
|
|
{
|
|
x = d11;
|
|
y = d7;
|
|
z = d8;
|
|
this.setEntityBoundingBox(axisalignedbb3);
|
|
}
|
|
}
|
|
|
|
// this.worldObj.profiler.end();
|
|
// this.worldObj.profiler.start("rest");
|
|
this.resetPositionToBB();
|
|
this.collidedHorizontally = d3 != x || d5 != z;
|
|
this.collidedVertically = d4 != y;
|
|
this.onGround = this.collidedVertically && d4 < 0.0D;
|
|
this.collided = this.collidedHorizontally || this.collidedVertically;
|
|
int i = ExtMath.floord(this.posX);
|
|
int j = ExtMath.floord(this.posY - 0.20000000298023224D);
|
|
int k = ExtMath.floord(this.posZ);
|
|
BlockPos blockpos = new BlockPos(i, j, k);
|
|
Block block1 = this.worldObj.getState(blockpos).getBlock();
|
|
|
|
if (block1.getMaterial() == Material.air)
|
|
{
|
|
Block block = this.worldObj.getState(blockpos.down()).getBlock();
|
|
|
|
if (block instanceof BlockFence || block instanceof BlockWall || block instanceof BlockFenceGate)
|
|
{
|
|
block1 = block;
|
|
blockpos = blockpos.down();
|
|
}
|
|
}
|
|
|
|
this.updateFallState(y, this.onGround, block1, blockpos);
|
|
|
|
if (d3 != x)
|
|
{
|
|
this.motionX = 0.0D;
|
|
}
|
|
|
|
if (d5 != z)
|
|
{
|
|
this.motionZ = 0.0D;
|
|
}
|
|
|
|
if (d4 != y)
|
|
{
|
|
block1.onLanded(this.worldObj, this);
|
|
}
|
|
|
|
if (this.canTriggerWalking() && !flag && this.vehicle == null)
|
|
{
|
|
double d12 = this.posX - d0;
|
|
double d13 = this.posY - d1;
|
|
double d14 = this.posZ - d2;
|
|
|
|
if (block1 != Blocks.ladder)
|
|
{
|
|
d13 = 0.0D;
|
|
}
|
|
|
|
if (block1 != null && this.onGround)
|
|
{
|
|
block1.onEntityCollidedWithBlock(this.worldObj, blockpos, this);
|
|
}
|
|
|
|
this.walkDistMod = (float)((double)this.walkDistMod + (double)ExtMath.sqrtd(d12 * d12 + d14 * d14) * 0.6D);
|
|
this.stepDistMod = (float)((double)this.stepDistMod + (double)ExtMath.sqrtd(d12 * d12 + d13 * d13 + d14 * d14) * 0.6D);
|
|
|
|
if (this.stepDistMod > (float)this.nextStepDist && block1.getMaterial() != Material.air)
|
|
{
|
|
this.nextStepDist = (int)this.stepDistMod + 1;
|
|
|
|
if (this.isInLiquid())
|
|
{
|
|
float f = ExtMath.sqrtd(this.motionX * this.motionX * 0.20000000298023224D + this.motionY * this.motionY + this.motionZ * this.motionZ * 0.20000000298023224D) * 0.35F;
|
|
|
|
if (f > 1.0F)
|
|
{
|
|
f = 1.0F;
|
|
}
|
|
|
|
// this.playSound(this.getSwimSound(), f, 1.0F + (this.rand.floatv() - this.rand.floatv()) * 0.4F);
|
|
}
|
|
|
|
this.playStepSound(blockpos, block1);
|
|
}
|
|
}
|
|
|
|
this.doBlockCollisions();
|
|
|
|
boolean flag2 = this.isWet();
|
|
|
|
if (this.worldObj.isFlammableWithin(this.getEntityBoundingBox().contract(0.001D, 0.001D, 0.001D)))
|
|
{
|
|
this.dealFireDamage(1);
|
|
|
|
if (!flag2)
|
|
{
|
|
++this.fire;
|
|
|
|
if (this.fire == 0)
|
|
{
|
|
this.setFire(8);
|
|
}
|
|
}
|
|
}
|
|
else if (this.fire <= 0)
|
|
{
|
|
this.fire = -this.fireResistance;
|
|
}
|
|
|
|
if (flag2 && this.fire > 0)
|
|
{
|
|
this.playSound(SoundEvent.FIZZ, 0.7F);
|
|
this.fire = -this.fireResistance;
|
|
}
|
|
|
|
// this.worldObj.profiler.end();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resets the entity's position to the center (planar) and bottom (vertical) points of its bounding box.
|
|
*/
|
|
private void resetPositionToBB()
|
|
{
|
|
this.posX = (this.getEntityBoundingBox().minX + this.getEntityBoundingBox().maxX) / 2.0D;
|
|
this.posY = this.getEntityBoundingBox().minY;
|
|
this.posZ = (this.getEntityBoundingBox().minZ + this.getEntityBoundingBox().maxZ) / 2.0D;
|
|
}
|
|
|
|
// protected String getSwimSound()
|
|
// {
|
|
// return "random.swim";
|
|
// }
|
|
|
|
protected void doBlockCollisions()
|
|
{
|
|
BlockPos blockpos = new BlockPos(this.getEntityBoundingBox().minX + 0.001D, this.getEntityBoundingBox().minY + 0.001D, this.getEntityBoundingBox().minZ + 0.001D);
|
|
BlockPos blockpos1 = new BlockPos(this.getEntityBoundingBox().maxX - 0.001D, this.getEntityBoundingBox().maxY - 0.001D, this.getEntityBoundingBox().maxZ - 0.001D);
|
|
|
|
if (this.worldObj.isAreaLoaded(blockpos, blockpos1))
|
|
{
|
|
for (int i = blockpos.getX(); i <= blockpos1.getX(); ++i)
|
|
{
|
|
for (int j = blockpos.getY(); j <= blockpos1.getY(); ++j)
|
|
{
|
|
for (int k = blockpos.getZ(); k <= blockpos1.getZ(); ++k)
|
|
{
|
|
BlockPos blockpos2 = new BlockPos(i, j, k);
|
|
State iblockstate = this.worldObj.getState(blockpos2);
|
|
|
|
iblockstate.getBlock().onEntityCollidedWithBlock(this.worldObj, blockpos2, iblockstate, this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void playStepSound(BlockPos pos, Block blockIn)
|
|
{
|
|
SoundType block$soundtype = blockIn.sound;
|
|
|
|
if (this.worldObj.getState(pos.up()).getBlock() == Blocks.snow_layer)
|
|
{
|
|
block$soundtype = Blocks.snow_layer.sound;
|
|
if(block$soundtype.getStepSound() != null)
|
|
this.playSound(block$soundtype.getStepSound(), 0.15F);
|
|
}
|
|
else if (!blockIn.getMaterial().isLiquid() && block$soundtype.getStepSound() != null)
|
|
{
|
|
this.playSound(block$soundtype.getStepSound(), 0.15F);
|
|
}
|
|
}
|
|
|
|
public void playSound(SoundEvent name, float volume)
|
|
{
|
|
// if (!this.isSilent())
|
|
// {
|
|
this.worldObj.playSoundAtEntity(this, name, volume);
|
|
// }
|
|
}
|
|
|
|
// /**
|
|
// * @return True if this entity will not play sounds
|
|
// */
|
|
// public boolean isSilent()
|
|
// {
|
|
// return this.dataWatcher.getWatchableObjectByte(4) == 1;
|
|
// }
|
|
|
|
// /**
|
|
// * When set to true the entity will not play sounds.
|
|
// */
|
|
// public void setSilent(boolean isSilent)
|
|
// {
|
|
// this.dataWatcher.updateObject(4, Byte.valueOf((byte)(isSilent ? 1 : 0)));
|
|
// }
|
|
|
|
/**
|
|
* returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
|
|
* prevent them from trampling crops
|
|
*/
|
|
protected boolean canTriggerWalking()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
protected void updateFallState(double y, boolean onGroundIn, Block blockIn, BlockPos pos)
|
|
{
|
|
if (onGroundIn)
|
|
{
|
|
if (this.fallDistance > 0.0F)
|
|
{
|
|
if(this.ignoreFall) {
|
|
this.ignoreFall = false;
|
|
}
|
|
else if (blockIn != null)
|
|
{
|
|
blockIn.onFallenUpon(this.worldObj, pos, this, this.fallDistance);
|
|
}
|
|
else
|
|
{
|
|
this.fall(this.fallDistance, 1.0F);
|
|
}
|
|
|
|
this.fallDistance = 0.0F;
|
|
}
|
|
}
|
|
else if (y < 0.0D)
|
|
{
|
|
this.fallDistance = (float)((double)this.fallDistance - y);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the collision bounding box for this entity
|
|
*/
|
|
public BoundingBox getCollisionBoundingBox()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Will deal the specified amount of damage to the entity if the entity isn't immune to fire damage. Args:
|
|
* amountDamage
|
|
*/
|
|
protected void dealFireDamage(int amount)
|
|
{
|
|
if(!this.isImmuneToFire() && Config.damageFire)
|
|
this.attackEntityFrom(DamageSource.inFire, amount);
|
|
}
|
|
|
|
public boolean isImmuneToFire()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public void fall(float distance, float damageMultiplier)
|
|
{
|
|
if (this.passenger != null)
|
|
{
|
|
this.passenger.fall(distance, damageMultiplier);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if this entity is either in water or on an open air block in rain (used in wolves).
|
|
*/
|
|
public boolean isWet()
|
|
{
|
|
return this.inLiquid || this.worldObj.isRainingAt(new BlockPos(this.posX, this.posY, this.posZ), true) || this.worldObj.isRainingAt(new BlockPos(this.posX, this.posY + (double)this.height, this.posZ), true);
|
|
}
|
|
|
|
public boolean isInDownfall()
|
|
{
|
|
return this.worldObj.isRainingAt(new BlockPos(this.posX, this.posY, this.posZ), false) || this.worldObj.isRainingAt(new BlockPos(this.posX, this.posY + (double)this.height, this.posZ), false);
|
|
}
|
|
|
|
/**
|
|
* Checks if this entity is inside water (if inWater field is true as a result of handleWaterMovement() returning
|
|
* true)
|
|
*/
|
|
public boolean isInLiquid()
|
|
{
|
|
return this.inLiquid;
|
|
}
|
|
|
|
/**
|
|
* Returns if this entity is in water and will end up adding the waters velocity to the entity
|
|
*/
|
|
public boolean handleWaterMovement()
|
|
{
|
|
if (this.worldObj.handleLiquidAcceleration(this.getEntityBoundingBox().expand(0.0D, -0.4000000059604645D, 0.0D).contract(0.001D, 0.001D, 0.001D), this))
|
|
{
|
|
if (!this.inLiquid && !this.firstUpdate)
|
|
{
|
|
this.onEnterLiquid();
|
|
}
|
|
|
|
this.fallDistance = 0.0F;
|
|
this.inLiquid = true;
|
|
this.fire = 0;
|
|
}
|
|
else
|
|
{
|
|
this.inLiquid = false;
|
|
}
|
|
|
|
return this.inLiquid;
|
|
}
|
|
|
|
protected void onEnterLiquid()
|
|
{
|
|
float f = ExtMath.sqrtd(this.motionX * this.motionX * 0.20000000298023224D + this.motionY * this.motionY + this.motionZ * this.motionZ * 0.20000000298023224D) * 0.2F;
|
|
|
|
if (f > 1.0F)
|
|
{
|
|
f = 1.0F;
|
|
}
|
|
|
|
this.playSound(SoundEvent.SPLASH, f);
|
|
float f1 = (float)ExtMath.floord(this.getEntityBoundingBox().minY);
|
|
|
|
for (int i = 0; (float)i < 1.0F + this.width * 20.0F; ++i)
|
|
{
|
|
float f2 = (this.rand.floatv() * 2.0F - 1.0F) * this.width;
|
|
float f3 = (this.rand.floatv() * 2.0F - 1.0F) * this.width;
|
|
this.worldObj.spawnParticle(ParticleType.WATER_BUBBLE, this.posX + (double)f2, (double)(f1 + 1.0F), this.posZ + (double)f3, this.motionX, this.motionY - (double)(this.rand.floatv() * 0.2F), this.motionZ);
|
|
}
|
|
|
|
if(this.worldObj.getState(new BlockPos(this.posX, this.posY, this.posZ)).getBlock().getMaterial() == Material.water) {
|
|
for (int j = 0; (float)j < 1.0F + this.width * 20.0F; ++j)
|
|
{
|
|
float f4 = (this.rand.floatv() * 2.0F - 1.0F) * this.width;
|
|
float f5 = (this.rand.floatv() * 2.0F - 1.0F) * this.width;
|
|
this.worldObj.spawnParticle(ParticleType.WATER_SPLASH, this.posX + (double)f4, (double)(f1 + 1.0F), this.posZ + (double)f5, this.motionX, this.motionY, this.motionZ);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Attempts to create sprinting particles if the entity is sprinting and not in water.
|
|
*/
|
|
public void spawnRunningParticles()
|
|
{
|
|
if (this.isSprinting() && !this.isInLiquid())
|
|
{
|
|
this.createRunningParticles();
|
|
}
|
|
}
|
|
|
|
protected void createRunningParticles()
|
|
{
|
|
int i = ExtMath.floord(this.posX);
|
|
int j = ExtMath.floord(this.posY - 0.20000000298023224D);
|
|
int k = ExtMath.floord(this.posZ);
|
|
BlockPos blockpos = new BlockPos(i, j, k);
|
|
State iblockstate = this.worldObj.getState(blockpos);
|
|
Block block = iblockstate.getBlock();
|
|
|
|
if (block.getRenderType() != -1)
|
|
{
|
|
this.worldObj.spawnParticle(ParticleType.BLOCK_CRACK, this.posX + ((double)this.rand.floatv() - 0.5D) * (double)this.width, this.getEntityBoundingBox().minY + 0.1D, this.posZ + ((double)this.rand.floatv() - 0.5D) * (double)this.width, -this.motionX * 4.0D, 1.5D, -this.motionZ * 4.0D, BlockRegistry.getStateId(iblockstate));
|
|
}
|
|
}
|
|
|
|
// protected String getSplashSound()
|
|
// {
|
|
// return "random.splash";
|
|
// }
|
|
|
|
/**
|
|
* Checks if the current block the entity is within of the specified material type
|
|
*/
|
|
public boolean isInsideOfLiquid()
|
|
{
|
|
double d0 = this.posY + (double)this.getEyeHeight();
|
|
BlockPos blockpos = new BlockPos(this.posX, d0, this.posZ);
|
|
State iblockstate = this.worldObj.getState(blockpos);
|
|
Block block = iblockstate.getBlock();
|
|
|
|
if (block.getMaterial().isColdLiquid())
|
|
{
|
|
float f = BlockLiquid.getLiquidHeightPercent(iblockstate.getBlock().getMetaFromState(iblockstate)) - 0.11111111F;
|
|
float f1 = (float)(blockpos.getY() + 1) - f;
|
|
boolean flag = d0 < (double)f1;
|
|
return !flag && this.isPlayer() ? false : flag;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public boolean isInMolten()
|
|
{
|
|
return this.worldObj.isMaterialInMolten(this.getEntityBoundingBox().expand(-0.10000000149011612D, -0.4000000059604645D, -0.10000000149011612D));
|
|
}
|
|
|
|
/**
|
|
* Used in both water and by flying objects
|
|
*/
|
|
public void moveFlying(float strafe, float forward, float friction)
|
|
{
|
|
float f = strafe * strafe + forward * forward;
|
|
|
|
if (f >= 1.0E-4F)
|
|
{
|
|
f = ExtMath.sqrtf(f);
|
|
|
|
if (f < 1.0F)
|
|
{
|
|
f = 1.0F;
|
|
}
|
|
|
|
f = friction / f;
|
|
strafe = strafe * f;
|
|
forward = forward * f;
|
|
float f1 = ExtMath.sin(this.rotYaw * (float)Math.PI / 180.0F);
|
|
float f2 = ExtMath.cos(this.rotYaw * (float)Math.PI / 180.0F);
|
|
this.motionX += (double)(strafe * f2 - forward * f1);
|
|
this.motionZ += (double)(forward * f2 + strafe * f1);
|
|
}
|
|
}
|
|
|
|
public int getBrightnessForRender(float partialTicks)
|
|
{
|
|
BlockPos blockpos = new BlockPos(this.posX, this.posY + (double)this.getEyeHeight(), this.posZ);
|
|
return this.worldObj.isBlockLoaded(blockpos) ? this.worldObj.getCombinedLight(blockpos, 0) : 0;
|
|
}
|
|
|
|
/**
|
|
* Gets how bright this entity is.
|
|
*/
|
|
public float getBrightness(float partialTicks)
|
|
{
|
|
BlockPos blockpos = new BlockPos(this.posX, this.posY + (double)this.getEyeHeight(), this.posZ);
|
|
return this.worldObj.isBlockLoaded(blockpos) ? this.worldObj.getLightBrightness(blockpos) : 0.0F;
|
|
}
|
|
|
|
/**
|
|
* Sets the reference to the World object.
|
|
*/
|
|
public void setWorld(World worldIn)
|
|
{
|
|
this.worldObj = worldIn;
|
|
}
|
|
|
|
/**
|
|
* Sets the entity's position and rotation.
|
|
*/
|
|
public void setPositionAndRotation(double x, double y, double z, float yaw, float pitch)
|
|
{
|
|
this.prevX = this.posX = x;
|
|
this.prevY = this.posY = y;
|
|
this.prevZ = this.posZ = z;
|
|
this.prevYaw = this.rotYaw = yaw;
|
|
this.prevPitch = this.rotPitch = pitch;
|
|
double d0 = (double)(this.prevYaw - yaw);
|
|
|
|
if (d0 < -180.0D)
|
|
{
|
|
this.prevYaw += 360.0F;
|
|
}
|
|
|
|
if (d0 >= 180.0D)
|
|
{
|
|
this.prevYaw -= 360.0F;
|
|
}
|
|
|
|
this.setPosition(this.posX, this.posY, this.posZ);
|
|
this.setRotation(yaw, pitch);
|
|
}
|
|
|
|
public void moveToBlockPosAndAngles(BlockPos pos, float rotationYawIn, float rotationPitchIn)
|
|
{
|
|
this.setLocationAndAngles((double)pos.getX() + 0.5D, (double)pos.getY(), (double)pos.getZ() + 0.5D, rotationYawIn, rotationPitchIn);
|
|
}
|
|
|
|
/**
|
|
* Sets the location and Yaw/Pitch of an entity in the world
|
|
*/
|
|
public void setLocationAndAngles(double x, double y, double z, float yaw, float pitch)
|
|
{
|
|
this.lastTickPosX = this.prevX = this.posX = x;
|
|
this.lastTickPosY = this.prevY = this.posY = y;
|
|
this.lastTickPosZ = this.prevZ = this.posZ = z;
|
|
this.rotYaw = yaw;
|
|
this.rotPitch = pitch;
|
|
this.setPosition(this.posX, this.posY, this.posZ);
|
|
}
|
|
|
|
/**
|
|
* Returns the distance to the entity. Args: entity
|
|
*/
|
|
public float getDistanceToEntity(Entity entityIn)
|
|
{
|
|
float f = (float)(this.posX - entityIn.posX);
|
|
float f1 = (float)(this.posY - entityIn.posY);
|
|
float f2 = (float)(this.posZ - entityIn.posZ);
|
|
return ExtMath.sqrtf(f * f + f1 * f1 + f2 * f2);
|
|
}
|
|
|
|
/**
|
|
* Gets the squared distance to the position. Args: x, y, z
|
|
*/
|
|
public double getDistanceSq(double x, double y, double z)
|
|
{
|
|
double d0 = this.posX - x;
|
|
double d1 = this.posY - y;
|
|
double d2 = this.posZ - z;
|
|
return d0 * d0 + d1 * d1 + d2 * d2;
|
|
}
|
|
|
|
public double getDistanceSq(BlockPos pos)
|
|
{
|
|
return pos.distanceSq(this.posX, this.posY, this.posZ);
|
|
}
|
|
|
|
public double getDistanceSqToCenter(BlockPos pos)
|
|
{
|
|
return pos.distanceSqToCenter(this.posX, this.posY, this.posZ);
|
|
}
|
|
|
|
/**
|
|
* Gets the distance to the position. Args: x, y, z
|
|
*/
|
|
public double getDistance(double x, double y, double z)
|
|
{
|
|
double d0 = this.posX - x;
|
|
double d1 = this.posY - y;
|
|
double d2 = this.posZ - z;
|
|
return (double)ExtMath.sqrtd(d0 * d0 + d1 * d1 + d2 * d2);
|
|
}
|
|
|
|
/**
|
|
* Returns the squared distance to the entity. Args: entity
|
|
*/
|
|
public double getDistanceSqToEntity(Entity entityIn)
|
|
{
|
|
double d0 = this.posX - entityIn.posX;
|
|
double d1 = this.posY - entityIn.posY;
|
|
double d2 = this.posZ - entityIn.posZ;
|
|
return d0 * d0 + d1 * d1 + d2 * d2;
|
|
}
|
|
|
|
/**
|
|
* Called by a player entity when they collide with an entity
|
|
*/
|
|
public void onCollideWithPlayer(EntityNPC entityIn)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Applies a velocity to each of the entities pushing them away from each other. Args: entity
|
|
*/
|
|
public void applyEntityCollision(Entity entityIn)
|
|
{
|
|
if (entityIn.passenger != this && entityIn.vehicle != this)
|
|
{
|
|
if (!entityIn.noClip && !this.noClip)
|
|
{
|
|
double d0 = entityIn.posX - this.posX;
|
|
double d1 = entityIn.posZ - this.posZ;
|
|
double v1 = d0 < 0.0D ? -d0 : d0;
|
|
double v2 = d1 < 0.0D ? -d1 : d1;
|
|
double d2 = v1 > v2 ? v1 : v2;
|
|
// double d2 = ExtMath.abs_max(d0, d1);
|
|
|
|
if (d2 >= 0.009999999776482582D)
|
|
{
|
|
d2 = (double)ExtMath.sqrtd(d2);
|
|
d0 = d0 / d2;
|
|
d1 = d1 / d2;
|
|
double d3 = 1.0D / d2;
|
|
|
|
if (d3 > 1.0D)
|
|
{
|
|
d3 = 1.0D;
|
|
}
|
|
|
|
d0 = d0 * d3;
|
|
d1 = d1 * d3;
|
|
d0 = d0 * 0.05000000074505806D;
|
|
d1 = d1 * 0.05000000074505806D;
|
|
d0 = d0 * (double)(1.0F - this.collisionReduction);
|
|
d1 = d1 * (double)(1.0F - this.collisionReduction);
|
|
|
|
if (this.passenger == null)
|
|
{
|
|
this.addVelocity(-d0, 0.0D, -d1);
|
|
}
|
|
|
|
if (entityIn.passenger == null)
|
|
{
|
|
entityIn.addVelocity(d0, 0.0D, d1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds to the current velocity of the entity. Args: x, y, z
|
|
*/
|
|
public void addVelocity(double x, double y, double z)
|
|
{
|
|
this.motionX += x;
|
|
this.motionY += y;
|
|
this.motionZ += z;
|
|
this.isAirBorne = true;
|
|
}
|
|
|
|
public void addKnockback(double x, double y, double z)
|
|
{
|
|
float mult = this.worldObj.client ? 1.0f : Config.knockback;
|
|
this.addVelocity(x * mult, y * mult, z * mult);
|
|
}
|
|
|
|
/**
|
|
* Sets that this entity has been attacked.
|
|
*/
|
|
protected void setBeenAttacked()
|
|
{
|
|
this.veloChanged = true;
|
|
}
|
|
|
|
/**
|
|
* Called when the entity is attacked.
|
|
*/
|
|
public boolean attackEntityFrom(DamageSource source, int amount)
|
|
{
|
|
if (this.isEntityInvulnerable(source))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
this.setBeenAttacked();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* interpolated look vector
|
|
*/
|
|
public Vec3 getLook(float partialTicks)
|
|
{
|
|
if (partialTicks == 1.0F)
|
|
{
|
|
return this.getVectorForRotation(this.rotPitch, this.rotYaw);
|
|
}
|
|
else
|
|
{
|
|
float f = this.prevPitch + (this.rotPitch - this.prevPitch) * partialTicks;
|
|
float f1 = this.prevYaw + (this.rotYaw - this.prevYaw) * partialTicks;
|
|
return this.getVectorForRotation(f, f1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a Vec3 using the pitch and yaw of the entities rotation.
|
|
*/
|
|
protected final Vec3 getVectorForRotation(float pitch, float yaw)
|
|
{
|
|
float f = ExtMath.cos(-yaw * 0.017453292F - (float)Math.PI);
|
|
float f1 = ExtMath.sin(-yaw * 0.017453292F - (float)Math.PI);
|
|
float f2 = -ExtMath.cos(-pitch * 0.017453292F);
|
|
float f3 = ExtMath.sin(-pitch * 0.017453292F);
|
|
return new Vec3((double)(f1 * f2), (double)f3, (double)(f * f2));
|
|
}
|
|
|
|
public Vec3 getPositionEyes(float partialTicks)
|
|
{
|
|
if (partialTicks == 1.0F)
|
|
{
|
|
return new Vec3(this.posX, this.posY + (double)this.getEyeHeight(), this.posZ);
|
|
}
|
|
else
|
|
{
|
|
double d0 = this.prevX + (this.posX - this.prevX) * (double)partialTicks;
|
|
double d1 = this.prevY + (this.posY - this.prevY) * (double)partialTicks + (double)this.getEyeHeight();
|
|
double d2 = this.prevZ + (this.posZ - this.prevZ) * (double)partialTicks;
|
|
return new Vec3(d0, d1, d2);
|
|
}
|
|
}
|
|
|
|
public HitPosition rayTrace(double blockReachDistance, float partialTicks)
|
|
{
|
|
Vec3 vec3 = this.getPositionEyes(partialTicks);
|
|
Vec3 vec31 = this.getLook(partialTicks);
|
|
Vec3 vec32 = vec3.addVector(vec31.xCoord * blockReachDistance, vec31.yCoord * blockReachDistance, vec31.zCoord * blockReachDistance);
|
|
return this.worldObj.rayTraceBlocks(vec3, vec32, false, false, true);
|
|
}
|
|
|
|
/**
|
|
* Returns true if other Entities should be prevented from moving through this Entity.
|
|
*/
|
|
public boolean canBeCollidedWith()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns true if this entity should push and be pushed by other entities when colliding.
|
|
*/
|
|
public boolean canBePushed()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public boolean isInRangeToRender3d(double x, double y, double z)
|
|
{
|
|
double d0 = this.posX - x;
|
|
double d1 = this.posY - y;
|
|
double d2 = this.posZ - z;
|
|
double d3 = d0 * d0 + d1 * d1 + d2 * d2;
|
|
return this.isInRangeToRenderDist(d3);
|
|
}
|
|
|
|
/**
|
|
* Checks if the entity is in range to render by using the past in distance and comparing it to its average edge
|
|
* length * 64 * renderDistanceWeight Args: distance
|
|
*/
|
|
public boolean isInRangeToRenderDist(double distance)
|
|
{
|
|
double d0 = this.getEntityBoundingBox().getAverageEdgeLength();
|
|
|
|
if (Double.isNaN(d0))
|
|
{
|
|
d0 = 1.0D;
|
|
}
|
|
|
|
d0 = d0 * 64.0D * this.renderDistWeight;
|
|
return distance < d0 * d0;
|
|
}
|
|
|
|
/**
|
|
* Like writeToNBTOptional but does not check if the entity is ridden. Used for saving ridden entities with their
|
|
* riders.
|
|
*/
|
|
public boolean writeMountToNBT(NBTTagCompound tagCompund)
|
|
{
|
|
String s = EntityRegistry.getEntityString(this);
|
|
|
|
if (!this.dead && !this.isPlayer() && s != null)
|
|
{
|
|
tagCompund.setString("id", s);
|
|
this.writeToNBT(tagCompund);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Either write this entity to the NBT tag given and return true, or return false without doing anything. If this
|
|
* returns false the entity is not saved on disk. Ridden entities return false here as they are saved with their
|
|
* rider.
|
|
*/
|
|
public boolean writeToNBTOptional(NBTTagCompound tagCompund)
|
|
{
|
|
String s = EntityRegistry.getEntityString(this);
|
|
|
|
if (!this.dead && !this.isPlayer() && s != null && (this.passenger == null || this.passenger.isPlayer()))
|
|
{
|
|
tagCompund.setString("id", s);
|
|
this.writeToNBT(tagCompund);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// public void setTag(String tag) {
|
|
// this.tag = tag.isEmpty() ? null : tag;
|
|
// }
|
|
//
|
|
// public String getTag() {
|
|
// return this.tag;
|
|
// }
|
|
//
|
|
// public boolean hasTag() {
|
|
// return this.tag != null;
|
|
// }
|
|
|
|
// public void setPersistentId(long id) {
|
|
// this.persistentId = id;
|
|
// }
|
|
//
|
|
// public long getPersistentId() {
|
|
// return this.persistentId;
|
|
// }
|
|
//
|
|
// public boolean hasPersistentId() {
|
|
// return this.persistentId != 0L;
|
|
// }
|
|
|
|
/**
|
|
* Save the entity to NBT (calls an abstract helper method to write extra data)
|
|
*/
|
|
public void writeToNBT(NBTTagCompound tagCompund)
|
|
{
|
|
// if(this.persistentId != 0L) {
|
|
// tagCompund.setLong("PersistID", this.persistentId);
|
|
// }
|
|
// if(this.tag != null) {
|
|
// tagCompund.setString("ObjectTag", this.tag);
|
|
// }
|
|
|
|
tagCompund.setTag("Pos", this.newDoubleNBTList(this.posX, this.posY, this.posZ));
|
|
tagCompund.setTag("Motion", this.newDoubleNBTList(this.motionX, this.motionY, this.motionZ));
|
|
tagCompund.setTag("Rotation", this.newFloatNBTList(this.rotYaw, this.rotPitch));
|
|
tagCompund.setFloat("FallDistance", this.fallDistance);
|
|
tagCompund.setShort("Fire", (short)this.fire);
|
|
// tagCompund.setShort("Air", (short)this.getAir());
|
|
tagCompund.setBoolean("OnGround", this.onGround);
|
|
// tagCompund.setBoolean("Invulnerable", this.invulnerable);
|
|
// tagCompund.setInteger("PortalCooldown", this.portalTimer);
|
|
|
|
if (this.getCustomNameTag() != null && this.getCustomNameTag().length() > 0)
|
|
{
|
|
tagCompund.setString("CustomName", this.getCustomNameTag());
|
|
// tagCompund.setBoolean("CustomNameVisible", this.getAlwaysRenderNameTag());
|
|
}
|
|
|
|
// if (this.isSilent())
|
|
// {
|
|
// tagCompund.setBoolean("Silent", this.isSilent());
|
|
// }
|
|
|
|
if(this.ignoreFall)
|
|
tagCompund.setBoolean("IgnoreFall", this.ignoreFall);
|
|
|
|
this.writeEntityToNBT(tagCompund);
|
|
|
|
if (this.vehicle != null && !(this.isPlayer()))
|
|
{
|
|
NBTTagCompound nbttagcompound = new NBTTagCompound();
|
|
|
|
if (this.vehicle.writeMountToNBT(nbttagcompound))
|
|
{
|
|
tagCompund.setTag("Riding", nbttagcompound);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads the entity from NBT (calls an abstract helper method to read specialized data)
|
|
*/
|
|
public void readFromNBT(NBTTagCompound tagCompund)
|
|
{
|
|
// if(tagCompund.hasKey("PersistID", 4))
|
|
// this.setPersistentId(tagCompund.getLong("PersistID"));
|
|
// this.setTag(tagCompund.getString("ObjectTag"));
|
|
|
|
NBTTagList nbttaglist = tagCompund.getTagList("Pos", 6);
|
|
NBTTagList nbttaglist1 = tagCompund.getTagList("Motion", 6);
|
|
NBTTagList nbttaglist2 = tagCompund.getTagList("Rotation", 5);
|
|
this.motionX = nbttaglist1.getDoubleAt(0);
|
|
this.motionY = nbttaglist1.getDoubleAt(1);
|
|
this.motionZ = nbttaglist1.getDoubleAt(2);
|
|
|
|
if (Math.abs(this.motionX) > 10.0D)
|
|
{
|
|
this.motionX = 0.0D;
|
|
}
|
|
|
|
if (Math.abs(this.motionY) > 10.0D)
|
|
{
|
|
this.motionY = 0.0D;
|
|
}
|
|
|
|
if (Math.abs(this.motionZ) > 10.0D)
|
|
{
|
|
this.motionZ = 0.0D;
|
|
}
|
|
|
|
this.prevX = this.lastTickPosX = this.posX = nbttaglist.getDoubleAt(0);
|
|
this.prevY = this.lastTickPosY = this.posY = nbttaglist.getDoubleAt(1);
|
|
this.prevZ = this.lastTickPosZ = this.posZ = nbttaglist.getDoubleAt(2);
|
|
this.prevYaw = this.rotYaw = nbttaglist2.getFloatAt(0);
|
|
this.prevPitch = this.rotPitch = nbttaglist2.getFloatAt(1);
|
|
this.setRotationYawHead(this.rotYaw);
|
|
this.setRenderYawOffset(this.rotYaw);
|
|
this.fallDistance = tagCompund.getFloat("FallDistance");
|
|
this.fire = tagCompund.getShort("Fire");
|
|
// this.setAir(tagCompund.getShort("Air"));
|
|
this.onGround = tagCompund.getBoolean("OnGround");
|
|
// this.invulnerable = tagCompund.getBoolean("Invulnerable");
|
|
// this.portalTimer = tagCompund.getInteger("PortalCooldown");
|
|
|
|
this.setPosition(this.posX, this.posY, this.posZ);
|
|
this.setRotation(this.rotYaw, this.rotPitch);
|
|
|
|
if (tagCompund.hasKey("CustomName", 8) && tagCompund.getString("CustomName").length() > 0)
|
|
{
|
|
this.setCustomNameTag(tagCompund.getString("CustomName"));
|
|
}
|
|
|
|
// this.setAlwaysRenderNameTag(tagCompund.getBoolean("CustomNameVisible"));
|
|
// this.setSilent(tagCompund.getBoolean("Silent"));
|
|
this.ignoreFall = tagCompund.getBoolean("IgnoreFall");
|
|
this.readEntityFromNBT(tagCompund);
|
|
|
|
if (this.shouldSetPosAfterLoading())
|
|
{
|
|
this.setPosition(this.posX, this.posY, this.posZ);
|
|
}
|
|
}
|
|
|
|
protected boolean shouldSetPosAfterLoading()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// /**
|
|
// * Returns the string that identifies this Entity's class
|
|
// */
|
|
// protected final String getEntityString()
|
|
// {
|
|
// return EntityRegistry.getEntityString(this);
|
|
// }
|
|
|
|
/**
|
|
* (abstract) Protected helper method to read subclass entity data from NBT.
|
|
*/
|
|
protected abstract void readEntityFromNBT(NBTTagCompound tagCompund);
|
|
|
|
/**
|
|
* (abstract) Protected helper method to write subclass entity data to NBT.
|
|
*/
|
|
protected abstract void writeEntityToNBT(NBTTagCompound tagCompound);
|
|
|
|
public void onChunkLoad()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* creates a NBT list from the array of doubles passed to this function
|
|
*/
|
|
protected NBTTagList newDoubleNBTList(double... numbers)
|
|
{
|
|
NBTTagList nbttaglist = new NBTTagList();
|
|
|
|
for (double d0 : numbers)
|
|
{
|
|
nbttaglist.appendTag(new NBTTagDouble(d0));
|
|
}
|
|
|
|
return nbttaglist;
|
|
}
|
|
|
|
/**
|
|
* Returns a new NBTTagList filled with the specified floats
|
|
*/
|
|
protected NBTTagList newFloatNBTList(float... numbers)
|
|
{
|
|
NBTTagList nbttaglist = new NBTTagList();
|
|
|
|
for (float f : numbers)
|
|
{
|
|
nbttaglist.appendTag(new NBTTagFloat(f));
|
|
}
|
|
|
|
return nbttaglist;
|
|
}
|
|
|
|
public EntityItem dropItem(Item itemIn, int size)
|
|
{
|
|
return this.dropItemWithOffset(itemIn, size, 0.0F);
|
|
}
|
|
|
|
public EntityItem dropItemWithOffset(Item itemIn, int size, float offsetY)
|
|
{
|
|
return this.entityDropItem(new ItemStack(itemIn, size, 0), offsetY);
|
|
}
|
|
|
|
/**
|
|
* Drops an item at the position of the entity.
|
|
*/
|
|
public EntityItem entityDropItem(ItemStack itemStackIn, float offsetY)
|
|
{
|
|
if (itemStackIn.stackSize != 0 && itemStackIn.getItem() != null)
|
|
{
|
|
EntityItem entityitem = new EntityItem(this.worldObj, this.posX, this.posY + (double)offsetY, this.posZ, itemStackIn);
|
|
entityitem.setDefaultPickupDelay();
|
|
this.worldObj.spawnEntityInWorld(entityitem);
|
|
return entityitem;
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks whether target entity is alive.
|
|
*/
|
|
public boolean isEntityAlive()
|
|
{
|
|
return !this.dead;
|
|
}
|
|
|
|
/**
|
|
* Checks if this entity is inside of an opaque block
|
|
*/
|
|
public boolean isEntityInsideOpaqueBlock()
|
|
{
|
|
if (this.noClip)
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE);
|
|
|
|
for (int i = 0; i < 8; ++i)
|
|
{
|
|
int j = ExtMath.floord(this.posY + (double)(((float)((i >> 0) % 2) - 0.5F) * 0.1F) + (double)this.getEyeHeight());
|
|
int k = ExtMath.floord(this.posX + (double)(((float)((i >> 1) % 2) - 0.5F) * this.width * 0.8F));
|
|
int l = ExtMath.floord(this.posZ + (double)(((float)((i >> 2) % 2) - 0.5F) * this.width * 0.8F));
|
|
|
|
if (blockpos$mutableblockpos.getX() != k || blockpos$mutableblockpos.getY() != j || blockpos$mutableblockpos.getZ() != l)
|
|
{
|
|
blockpos$mutableblockpos.set(k, j, l);
|
|
|
|
if (this.worldObj.getState(blockpos$mutableblockpos).getBlock().isVisuallyOpaque())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* First layer of player interaction
|
|
*/
|
|
public boolean interactFirst(EntityNPC playerIn)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns a boundingBox used to collide the entity with other entities and blocks. This enables the entity to be
|
|
* pushable on contact, like boats or minecarts.
|
|
*/
|
|
public BoundingBox getCollisionBox(Entity entityIn)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Handles updating while being ridden by an entity
|
|
*/
|
|
public void updateRidden()
|
|
{
|
|
if (this.vehicle.dead)
|
|
{
|
|
this.vehicle = null;
|
|
}
|
|
else
|
|
{
|
|
this.motionX = 0.0D;
|
|
this.motionY = 0.0D;
|
|
this.motionZ = 0.0D;
|
|
this.onUpdate();
|
|
|
|
if (this.vehicle != null)
|
|
{
|
|
this.vehicle.updateRiderPosition();
|
|
this.riderYawDelta += (double)(this.vehicle.rotYaw - this.vehicle.prevYaw);
|
|
|
|
for (this.riderPitchDelta += (double)(this.vehicle.rotPitch - this.vehicle.prevPitch); this.riderYawDelta >= 180.0D; this.riderYawDelta -= 360.0D)
|
|
{
|
|
;
|
|
}
|
|
|
|
while (this.riderYawDelta < -180.0D)
|
|
{
|
|
this.riderYawDelta += 360.0D;
|
|
}
|
|
|
|
while (this.riderPitchDelta >= 180.0D)
|
|
{
|
|
this.riderPitchDelta -= 360.0D;
|
|
}
|
|
|
|
while (this.riderPitchDelta < -180.0D)
|
|
{
|
|
this.riderPitchDelta += 360.0D;
|
|
}
|
|
|
|
double d0 = this.riderYawDelta * 0.5D;
|
|
double d1 = this.riderPitchDelta * 0.5D;
|
|
float f = 10.0F;
|
|
|
|
if (d0 > (double)f)
|
|
{
|
|
d0 = (double)f;
|
|
}
|
|
|
|
if (d0 < (double)(-f))
|
|
{
|
|
d0 = (double)(-f);
|
|
}
|
|
|
|
if (d1 > (double)f)
|
|
{
|
|
d1 = (double)f;
|
|
}
|
|
|
|
if (d1 < (double)(-f))
|
|
{
|
|
d1 = (double)(-f);
|
|
}
|
|
|
|
this.riderYawDelta -= d0;
|
|
this.riderPitchDelta -= d1;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void updateRiderPosition()
|
|
{
|
|
if (this.passenger != null)
|
|
{
|
|
this.passenger.setPosition(this.posX, this.posY + this.getMountedYOffset() + this.passenger.getYOffset(), this.posZ);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the Y Offset of this entity.
|
|
*/
|
|
public double getYOffset()
|
|
{
|
|
return 0.0D;
|
|
}
|
|
|
|
/**
|
|
* Returns the Y offset from the entity's position for any entity riding this one.
|
|
*/
|
|
public double getMountedYOffset()
|
|
{
|
|
return (double)this.height * 0.75D;
|
|
}
|
|
|
|
public void teleport(double x, double y, double z, float yaw, float pitch, int dimension) {
|
|
x = ExtMath.clampd(x, -World.MAX_SIZE + 1, World.MAX_SIZE - 1);
|
|
z = ExtMath.clampd(z, -World.MAX_SIZE + 1, World.MAX_SIZE - 1);
|
|
this.unmount();
|
|
Entity entity = this;
|
|
if(this.worldObj.dimension.getDimensionId() != dimension) {
|
|
entity = this.travelToDimension(dimension, new BlockPos(x, y, z), yaw, pitch, null);
|
|
}
|
|
entity.setLocationAndAngles(x, y, z, yaw, pitch);
|
|
entity.setRotationYawHead(yaw);
|
|
}
|
|
|
|
// protected void setY(double y) {
|
|
// this.unmount();
|
|
// this.setLocationAndAngles(this.posX, y, this.posZ, this.rotYaw, this.rotPitch);
|
|
// this.setRotationYawHead(this.rotYaw);
|
|
// }
|
|
|
|
public final void teleport(Position pos) {
|
|
this.teleport(pos.x, pos.y, pos.z, pos.yaw, pos.pitch, pos.dim);
|
|
}
|
|
|
|
public final void teleport(BlockPos pos, int dim) {
|
|
this.teleport(((double)pos.getX()) + 0.5, (double)pos.getY(), ((double)pos.getZ()) + 0.5, this.rotYaw, this.rotPitch, dim);
|
|
}
|
|
|
|
// public final Position getLocation() {
|
|
// return new Position(this);
|
|
// }
|
|
|
|
/**
|
|
* Called when a player mounts an entity. e.g. mounts a pig, mounts a boat.
|
|
*/
|
|
public void mountEntity(Entity entityIn)
|
|
{
|
|
this.riderPitchDelta = 0.0D;
|
|
this.riderYawDelta = 0.0D;
|
|
|
|
if (entityIn == null)
|
|
{
|
|
if (this.vehicle != null)
|
|
{
|
|
this.setLocationAndAngles(this.vehicle.posX, this.vehicle.getEntityBoundingBox().minY + (double)this.vehicle.height, this.vehicle.posZ, this.rotYaw, this.rotPitch);
|
|
this.vehicle.passenger = null;
|
|
}
|
|
|
|
this.vehicle = null;
|
|
}
|
|
else
|
|
{
|
|
if (this.vehicle != null)
|
|
{
|
|
this.vehicle.passenger = null;
|
|
}
|
|
|
|
if (entityIn != null)
|
|
{
|
|
for (Entity entity = entityIn.vehicle; entity != null; entity = entity.vehicle)
|
|
{
|
|
if (entity == this)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.vehicle = entityIn;
|
|
entityIn.passenger = this;
|
|
}
|
|
}
|
|
|
|
public void setPositionAndRotation2(double x, double y, double z, float yaw, float pitch, int posRotationIncrements, boolean p_180426_10_)
|
|
{
|
|
this.setPosition(x, y, z);
|
|
this.setRotation(yaw, pitch);
|
|
List<BoundingBox> list = this.worldObj.getCollidingBoundingBoxes(this, this.getEntityBoundingBox().contract(0.03125D, 0.0D, 0.03125D));
|
|
|
|
if (!list.isEmpty())
|
|
{
|
|
double d0 = 0.0D;
|
|
|
|
for (BoundingBox axisalignedbb : list)
|
|
{
|
|
if (axisalignedbb.maxY > d0)
|
|
{
|
|
d0 = axisalignedbb.maxY;
|
|
}
|
|
}
|
|
|
|
y = y + (d0 - this.getEntityBoundingBox().minY);
|
|
this.setPosition(x, y, z);
|
|
}
|
|
}
|
|
|
|
public float getCollisionBorderSize()
|
|
{
|
|
return 0.1F;
|
|
}
|
|
|
|
/**
|
|
* returns a (normalized) vector of where this entity is looking
|
|
*/
|
|
public Vec3 getLookVec()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Marks the entity as being inside a portal, activating teleportation logic in onEntityUpdate() in the following
|
|
* tick(s).
|
|
*
|
|
* @param pos The postion of the portal that the entity is in
|
|
*/
|
|
public void setPortal(int dim)
|
|
{
|
|
// if (this.portalTimer > 0)
|
|
// {
|
|
// this.portalTimer = this.getPortalCooldown();
|
|
// }
|
|
// else
|
|
// {
|
|
// if (!this.worldObj.client && !pos.equals(this.portalPos))
|
|
// {
|
|
// this.portalPos = pos;
|
|
// BlockPattern.PatternHelper blockpattern$patternhelper = Blocks.portal.func_181089_f(this.worldObj, pos);
|
|
// double d0 = blockpattern$patternhelper.getFinger().getAxis() == EnumFacing.Axis.X ? (double)blockpattern$patternhelper.getPos().getZ() : (double)blockpattern$patternhelper.getPos().getX();
|
|
// double d1 = blockpattern$patternhelper.getFinger().getAxis() == EnumFacing.Axis.X ? this.posZ : this.posX;
|
|
// d1 = Math.abs(MathHelper.func_181160_c(d1 - (double)(blockpattern$patternhelper.getFinger().rotateY().getAxisDirection() == EnumFacing.AxisDirection.NEGATIVE ? 1 : 0), d0, d0 - (double)blockpattern$patternhelper.getPalmLength()));
|
|
// double d2 = MathHelper.func_181160_c(this.posY - 1.0D, (double)blockpattern$patternhelper.getPos().getY(), (double)(blockpattern$patternhelper.getPos().getY() - blockpattern$patternhelper.getThumbLength()));
|
|
// this.portalVec = new Vec3(d1, d2, 0.0D);
|
|
// this.portalDir = blockpattern$patternhelper.getFinger();
|
|
// }
|
|
//
|
|
if(!this.worldObj.client)
|
|
this.unmount();
|
|
this.inPortal = PortalType.values()[dim];
|
|
// }
|
|
}
|
|
|
|
public void setFlatPortal()
|
|
{
|
|
// if (this.portalTimer > 0)
|
|
// {
|
|
// this.portalTimer = this.getPortalCooldown();
|
|
// }
|
|
// else
|
|
// {
|
|
if(!this.worldObj.client)
|
|
this.unmount();
|
|
this.inPortal = PortalType.FLOOR;
|
|
// }
|
|
}
|
|
|
|
public void unmount()
|
|
{
|
|
if(this.passenger != null) {
|
|
this.passenger.mountEntity(null);
|
|
}
|
|
this.mountEntity(null);
|
|
}
|
|
|
|
// /**
|
|
// * Return the amount of cooldown before this entity can use a portal again.
|
|
// */
|
|
// public int getPortalCooldown()
|
|
// {
|
|
// return 40;
|
|
// }
|
|
|
|
/**
|
|
* Sets the velocity to the args. Args: x, y, z
|
|
*/
|
|
public void setVelocity(double x, double y, double z)
|
|
{
|
|
this.motionX = x;
|
|
this.motionY = y;
|
|
this.motionZ = z;
|
|
}
|
|
|
|
public void handleStatusUpdate(byte id)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Setups the entity to do the hurt animation. Only used by packets in multiplayer.
|
|
*/
|
|
public void performHurtAnimation()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* returns the inventory of this entity (only used in EntityNPCMP it seems)
|
|
*/
|
|
public ItemStack[] getInventory()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor. Params: Item, slot
|
|
*/
|
|
public void setItem(int slot, ItemStack stack)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Returns true if the entity is on fire. Used by render to add the fire effect on rendering.
|
|
*/
|
|
public boolean isBurning()
|
|
{
|
|
boolean flag = this.worldObj != null && this.worldObj.client;
|
|
return !this.isImmuneToFire() && (this.fire > 0 || flag && this.getFlag(0));
|
|
}
|
|
|
|
/**
|
|
* Returns true if the entity is riding another entity, used by render to rotate the legs to be in 'sit' position
|
|
* for players.
|
|
*/
|
|
public boolean isRiding()
|
|
{
|
|
return this.vehicle != null;
|
|
}
|
|
|
|
/**
|
|
* Returns if this entity is sneaking.
|
|
*/
|
|
public boolean isSneaking()
|
|
{
|
|
return this.getFlag(1);
|
|
}
|
|
|
|
/**
|
|
* Sets the sneaking flag.
|
|
*/
|
|
public void setSneaking(boolean sneaking)
|
|
{
|
|
this.setFlag(1, sneaking);
|
|
}
|
|
|
|
/**
|
|
* Get if the Entity is sprinting.
|
|
*/
|
|
public boolean isSprinting()
|
|
{
|
|
return this.getFlag(2);
|
|
}
|
|
|
|
/**
|
|
* Set sprinting switch for Entity.
|
|
*/
|
|
public void setSprinting(boolean sprinting)
|
|
{
|
|
this.setFlag(2, sprinting);
|
|
}
|
|
|
|
// public boolean isInvisible()
|
|
// {
|
|
// return false;
|
|
// }
|
|
|
|
// public void setInvisible(boolean invisible)
|
|
// {
|
|
// this.setFlag(3, invisible);
|
|
// }
|
|
|
|
/**
|
|
* Returns true if the flag is active for the entity. Known flags: 0) is burning; 1) is sneaking; 2) is riding
|
|
* something; 3) is sprinting; 4) is eating
|
|
*/
|
|
protected boolean getFlag(int flag)
|
|
{
|
|
return (this.dataWatcher.getWatchableObjectByte(0) & 1 << flag) != 0;
|
|
}
|
|
|
|
/**
|
|
* Enable or disable a entity flag, see getEntityFlag to read the know flags.
|
|
*/
|
|
protected void setFlag(int flag, boolean set)
|
|
{
|
|
byte b0 = this.dataWatcher.getWatchableObjectByte(0);
|
|
|
|
if (set)
|
|
{
|
|
this.dataWatcher.updateObject(0, Byte.valueOf((byte)(b0 | 1 << flag)));
|
|
}
|
|
else
|
|
{
|
|
this.dataWatcher.updateObject(0, Byte.valueOf((byte)(b0 & ~(1 << flag))));
|
|
}
|
|
}
|
|
|
|
// public int getAir()
|
|
// {
|
|
// return this.dataWatcher.getWatchableObjectShort(1);
|
|
// }
|
|
//
|
|
// public void setAir(int air)
|
|
// {
|
|
// this.dataWatcher.updateObject(1, Short.valueOf((short)air));
|
|
// }
|
|
|
|
/**
|
|
* Called when a lightning bolt hits the entity.
|
|
*/
|
|
public void onStruckByLightning(EntityLightning bolt)
|
|
{
|
|
if((this.worldObj.client || Config.damageLightning) && bolt.damage > 0)
|
|
this.attackEntityFrom(DamageSource.causeLightningDamage(bolt.summoner), this.worldObj.rand.range(bolt.damage, ((bolt.damage * 3) / 2)));
|
|
if(bolt.fire) {
|
|
++this.fire;
|
|
if(this.fire == 0)
|
|
this.setFire(8);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This method gets called when the entity kills another one.
|
|
*/
|
|
public void onKillEntity(EntityLiving entityLivingIn)
|
|
{
|
|
}
|
|
|
|
private boolean isBlockFullCube(BlockPos pos) {
|
|
State state = this.worldObj.getState(pos);
|
|
BoundingBox bb = state.getBlock().getCollisionBoundingBox(this.worldObj, pos, state);
|
|
return bb != null && bb.getAverageEdgeLength() >= 1.0D;
|
|
}
|
|
|
|
protected boolean pushOutOfBlocks(double x, double y, double z)
|
|
{
|
|
BlockPos blockpos = new BlockPos(x, y, z);
|
|
double d0 = x - (double)blockpos.getX();
|
|
double d1 = y - (double)blockpos.getY();
|
|
double d2 = z - (double)blockpos.getZ();
|
|
List<BoundingBox> list = this.worldObj.getCollisionBoxes(this.getEntityBoundingBox());
|
|
|
|
if (list.isEmpty() && !this.isBlockFullCube(blockpos))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
int i = 3;
|
|
double d3 = 9999.0D;
|
|
|
|
if (!this.isBlockFullCube(blockpos.west()) && d0 < d3)
|
|
{
|
|
d3 = d0;
|
|
i = 0;
|
|
}
|
|
|
|
if (!this.isBlockFullCube(blockpos.east()) && 1.0D - d0 < d3)
|
|
{
|
|
d3 = 1.0D - d0;
|
|
i = 1;
|
|
}
|
|
|
|
if (!this.isBlockFullCube(blockpos.up()) && 1.0D - d1 < d3)
|
|
{
|
|
d3 = 1.0D - d1;
|
|
i = 3;
|
|
}
|
|
|
|
if (!this.isBlockFullCube(blockpos.north()) && d2 < d3)
|
|
{
|
|
d3 = d2;
|
|
i = 4;
|
|
}
|
|
|
|
if (!this.isBlockFullCube(blockpos.south()) && 1.0D - d2 < d3)
|
|
{
|
|
d3 = 1.0D - d2;
|
|
i = 5;
|
|
}
|
|
|
|
float f = this.rand.floatv() * 0.2F + 0.1F;
|
|
|
|
if (i == 0)
|
|
{
|
|
this.motionX = (double)(-f);
|
|
}
|
|
|
|
if (i == 1)
|
|
{
|
|
this.motionX = (double)f;
|
|
}
|
|
|
|
if (i == 3)
|
|
{
|
|
this.motionY = (double)f;
|
|
}
|
|
|
|
if (i == 4)
|
|
{
|
|
this.motionZ = (double)(-f);
|
|
}
|
|
|
|
if (i == 5)
|
|
{
|
|
this.motionZ = (double)f;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the Entity inside a web block.
|
|
*/
|
|
public void setInWeb()
|
|
{
|
|
this.inWeb = true;
|
|
this.fallDistance = 0.0F;
|
|
}
|
|
|
|
/**
|
|
* Get the name of this object. For players this returns their username
|
|
*/
|
|
public String getTypeName()
|
|
{
|
|
if (this.hasCustomName())
|
|
{
|
|
return this.getCustomNameTag();
|
|
}
|
|
else
|
|
{
|
|
String s = EntityRegistry.getEntityString(this);
|
|
|
|
if (s == null)
|
|
{
|
|
s = "generic";
|
|
}
|
|
|
|
return EntityRegistry.getEntityName(s);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return the Entity parts making up this Entity (currently only for dragons)
|
|
*/
|
|
public Entity[] getParts()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Returns true if Entity argument is equal to this Entity
|
|
*/
|
|
public boolean isEntityEqual(Entity entityIn)
|
|
{
|
|
return this == entityIn;
|
|
}
|
|
|
|
public float getRotationYawHead()
|
|
{
|
|
return 0.0F;
|
|
}
|
|
|
|
/**
|
|
* Sets the head's yaw rotation of the entity.
|
|
*/
|
|
public void setRotationYawHead(float rotation)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Set the render yaw offset
|
|
*
|
|
* @param offset The render yaw offset
|
|
*/
|
|
public void setRenderYawOffset(float offset)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* If returns false, the item will not inflict any damage against entities.
|
|
*/
|
|
public boolean canAttackWithItem()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Called when a player attacks an entity. If this returns true the attack will not happen.
|
|
*/
|
|
public boolean hitByEntity(Entity entityIn)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// public String toString()
|
|
// {
|
|
// return String.format("%s[\'%s\'/%d, l=\'%s\', x=%.2f, y=%.2f, z=%.2f]", this.getClass().getSimpleName(), this.getName(), this.eid, this.worldObj == null ? "~NULL~" : this.worldObj.dimension.getDimensionId(), this.posX, this.posY, this.posZ);
|
|
// }
|
|
|
|
public final boolean isEntityInvulnerable(DamageSource source)
|
|
{
|
|
return false; // this.invulnerable && source != DamageSource.outOfWorld; // && !source.isCreativePlayer();
|
|
}
|
|
|
|
/**
|
|
* Sets this entity's location and angles to the location and angles of the passed in entity.
|
|
*/
|
|
public void copyLocationAndAnglesFrom(Entity entityIn)
|
|
{
|
|
this.setLocationAndAngles(entityIn.posX, entityIn.posY, entityIn.posZ, entityIn.rotYaw, entityIn.rotPitch);
|
|
}
|
|
|
|
/**
|
|
* Prepares this entity in new dimension by copying NBT data from entity in old dimension
|
|
*/
|
|
public void copyDataFromOld(Entity entityIn)
|
|
{
|
|
NBTTagCompound nbttagcompound = new NBTTagCompound();
|
|
entityIn.writeToNBT(nbttagcompound);
|
|
this.readFromNBT(nbttagcompound);
|
|
// this.portalTimer = entityIn.portalTimer;
|
|
// this.portalPos = entityIn.portalPos;
|
|
// this.portalVec = entityIn.portalVec;
|
|
// this.portalDir = entityIn.portalDir;
|
|
}
|
|
|
|
/**
|
|
* Teleports the entity to another dimension. Params: Dimension number to teleport to
|
|
*/
|
|
public Entity travelToDimension(int dimensionId, BlockPos pos, float yaw, float pitch, PortalType portal)
|
|
{
|
|
if (!this.worldObj.client && !this.dead)
|
|
{
|
|
// this.worldObj.profiler.start("changeDimension");
|
|
// Server server = Server.getServer();
|
|
// int oldDim = this.dimension;
|
|
WorldServer worldserver = (WorldServer)this.worldObj; // server.getWorld(oldDim);
|
|
WorldServer worldserver1 = worldserver.getServer().getWorld(dimensionId);
|
|
// this.dimension = dimensionId;
|
|
|
|
// if (i == 1 && dimensionId == 1)
|
|
// {
|
|
// worldserver1 = server.getWorld(0);
|
|
// this.dimension = 0;
|
|
// }
|
|
|
|
this.worldObj.removeEntity(this);
|
|
this.dead = false;
|
|
// this.worldObj.profiler.start("reposition");
|
|
worldserver.getServer().placeInDimension(this, worldserver, worldserver1, pos, portal);
|
|
if(this.isEntityAlive())
|
|
worldserver1.updateEntity(this, false);
|
|
// this.worldObj.profiler.next("reloading");
|
|
Entity entity = EntityRegistry.createEntityByName(EntityRegistry.getEntityString(this), worldserver1);
|
|
|
|
if (entity != null)
|
|
{
|
|
entity.copyDataFromOld(this);
|
|
|
|
if(pos != null) {
|
|
entity.moveToBlockPosAndAngles(pos, yaw, pitch);
|
|
}
|
|
// else if (oldDim != 1 && dimensionId == 1)
|
|
// {
|
|
// BlockPos blockpos = this.worldObj.getTopSolidOrLiquidBlock(worldserver1.getSpawnPoint());
|
|
// entity.moveToBlockPosAndAngles(blockpos, entity.rotationYaw, entity.rotationPitch);
|
|
// }
|
|
|
|
worldserver1.spawnEntityInWorld(entity);
|
|
}
|
|
|
|
this.dead = true;
|
|
// this.worldObj.profiler.end();
|
|
worldserver.resetUpdateEntityTick();
|
|
worldserver1.resetUpdateEntityTick();
|
|
// this.worldObj.profiler.end();
|
|
return entity;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Explosion resistance of a block relative to this entity
|
|
*/
|
|
public float getExplosionResistance(Explosion explosionIn, World worldIn, BlockPos pos, State blockStateIn)
|
|
{
|
|
return blockStateIn.getBlock().getExplosionResistance(this);
|
|
}
|
|
|
|
public boolean verifyExplosion(Explosion explosionIn, World worldIn, BlockPos pos, State blockStateIn, float p_174816_5_)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* The maximum height from where the entity is alowed to jump (used in pathfinder)
|
|
*/
|
|
public int getMaxFallHeight()
|
|
{
|
|
return 3;
|
|
}
|
|
|
|
// public Vec3 getLastPortal()
|
|
// {
|
|
// return this.portalVec != null ? this.portalVec : new Vec3(0.0d, 0.0d, 0.0d);
|
|
// }
|
|
//
|
|
// public EnumFacing getTeleportDirection()
|
|
// {
|
|
// return this.portalDir != null ? this.portalDir : EnumFacing.EAST;
|
|
// }
|
|
|
|
/**
|
|
* Return whether this entity should NOT trigger a pressure plate or a tripwire.
|
|
*/
|
|
public boolean doesEntityNotTriggerPressurePlate()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Return whether this entity should be rendered as on fire.
|
|
*/
|
|
public boolean canRenderOnFire()
|
|
{
|
|
return this.isBurning();
|
|
}
|
|
|
|
public boolean isPushedByWater()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Get the formatted ChatComponent that will be used for the sender's username in chat
|
|
*/
|
|
public String getName()
|
|
{
|
|
return this.getTypeName();
|
|
// this.formatComponent(comp);
|
|
// return comp;
|
|
}
|
|
|
|
public String getDisplayName()
|
|
{
|
|
return this.hasCustomName() ? this.getName() : null;
|
|
}
|
|
|
|
public final String getCommandName()
|
|
{
|
|
return TextColor.stripCodes(this.getName());
|
|
}
|
|
|
|
public final String getColoredName(TextColor reset)
|
|
{
|
|
return TextColor.DGRAY + "[" + this.getName() + TextColor.DGRAY + "]" + reset;
|
|
}
|
|
|
|
// public Text formatComponent(Text comp) {
|
|
// comp.setReplacement("/tp #" + this.getId()).setEntityInfo(this).setInsertion("#" + this.getId());
|
|
// return comp;
|
|
// }
|
|
|
|
/**
|
|
* Sets the custom name tag for this entity
|
|
*/
|
|
public void setCustomNameTag(String name)
|
|
{
|
|
this.dataWatcher.updateObject(1, name);
|
|
}
|
|
|
|
public String getCustomNameTag()
|
|
{
|
|
return this.dataWatcher.getWatchableObjectString(1);
|
|
}
|
|
|
|
/**
|
|
* Returns true if this thing is named
|
|
*/
|
|
public boolean hasCustomName()
|
|
{
|
|
return this.dataWatcher.getWatchableObjectString(1).length() > 0;
|
|
}
|
|
|
|
// public void setAlwaysRenderNameTag(boolean alwaysRenderNameTag)
|
|
// {
|
|
// this.dataWatcher.updateObject(3, Byte.valueOf((byte)(alwaysRenderNameTag ? 1 : 0)));
|
|
// }
|
|
//
|
|
// public boolean getAlwaysRenderNameTag()
|
|
// {
|
|
// return this.dataWatcher.getWatchableObjectByte(3) == 1;
|
|
// }
|
|
|
|
/**
|
|
* Sets the position of the entity and updates the 'last' variables
|
|
*/
|
|
public void setPositionAndUpdate(double x, double y, double z)
|
|
{
|
|
this.setLocationAndAngles(x, y, z, this.rotYaw, this.rotPitch);
|
|
}
|
|
|
|
// public boolean getAlwaysRenderNameTagForRender()
|
|
// {
|
|
// return this.getAlwaysRenderNameTag();
|
|
// }
|
|
|
|
public void onDataWatcherUpdate(int dataID)
|
|
{
|
|
}
|
|
|
|
public Facing getHorizontalFacing()
|
|
{
|
|
return Facing.getHorizontal(ExtMath.floord((double)(this.rotYaw * 4.0F / 360.0F) + 0.5D) & 3);
|
|
}
|
|
|
|
// protected HoverEvent getHoverEvent()
|
|
// {
|
|
// NBTTagCompound nbttagcompound = new NBTTagCompound();
|
|
// String s = EntityRegistry.getEntityString(this);
|
|
// nbttagcompound.setString("id", "#" + this.getId());
|
|
// if(this.hasPersistentId())
|
|
// nbttagcompound.setString("pid", String.format("$%016x", this.getPersistentId()));
|
|
// if(this.hasTag())
|
|
// nbttagcompound.setString("otag", this.getTag());
|
|
//
|
|
// if (s != null)
|
|
// {
|
|
// nbttagcompound.setString("type", s);
|
|
// }
|
|
//
|
|
// nbttagcompound.setString("name", IChatComponent.Serializer.componentToJson(this.getTypeName()));
|
|
// return new HoverEvent(HoverEvent.Action.SHOW_ENTITY, new ChatComponentText(nbttagcompound.toString()));
|
|
// }
|
|
|
|
// public boolean isVisibleTo(EntityNPCMP player)
|
|
// {
|
|
// return true;
|
|
// }
|
|
|
|
public BoundingBox getEntityBoundingBox()
|
|
{
|
|
return this.bbox;
|
|
}
|
|
|
|
public void setEntityBoundingBox(BoundingBox bb)
|
|
{
|
|
this.bbox = bb;
|
|
}
|
|
|
|
public float getEyeHeight()
|
|
{
|
|
return this.height * 0.85F;
|
|
}
|
|
|
|
public boolean isOutsideBorder()
|
|
{
|
|
return this.outsideBorder;
|
|
}
|
|
|
|
public void setOutsideBorder(boolean outsideBorder)
|
|
{
|
|
this.outsideBorder = outsideBorder;
|
|
}
|
|
|
|
// public boolean setSlot(int slot, ItemStack stack)
|
|
// {
|
|
// return false;
|
|
// }
|
|
|
|
/**
|
|
* Get the position in the world. <b>{@code null} is not allowed!</b> If you are not an entity in the world, return
|
|
* the coordinates 0, 0, 0
|
|
*/
|
|
public final BlockPos getPosition()
|
|
{
|
|
return new BlockPos(this.posX, this.posY + 0.5D, this.posZ);
|
|
}
|
|
|
|
public NBTTagCompound getNBTTagCompound()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Called when client receives entity's NBTTagCompound from server.
|
|
*/
|
|
public void clientUpdateEntityNBT(NBTTagCompound compound)
|
|
{
|
|
}
|
|
|
|
// /**
|
|
// * New version of interactWith that includes vector information on where precisely the player targeted.
|
|
// */
|
|
// public boolean interactAt(EntityNPC player, Vec3 targetVec3)
|
|
// {
|
|
// return false;
|
|
// }
|
|
|
|
public boolean isImmuneToExplosions()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
protected void applyEnchantments(EntityLiving entityLivingBaseIn, Entity entityIn)
|
|
{
|
|
if (entityIn instanceof EntityLiving)
|
|
{
|
|
EnchantmentHelper.applyThornEnchantments((EntityLiving)entityIn, entityLivingBaseIn);
|
|
}
|
|
|
|
EnchantmentHelper.applyArthropodEnchantments(entityLivingBaseIn, entityIn);
|
|
}
|
|
|
|
public abstract int getTrackingRange();
|
|
public abstract int getUpdateFrequency();
|
|
public abstract boolean isSendingVeloUpdates();
|
|
|
|
public boolean isMagnetic() {
|
|
return false;
|
|
}
|
|
|
|
public boolean hasSpawnVelocity() {
|
|
return false;
|
|
}
|
|
|
|
public boolean isPlayer() {
|
|
return false;
|
|
}
|
|
|
|
public Item getItem() {
|
|
String id = EntityRegistry.getEntityString(this);
|
|
if(!EntityRegistry.SPAWN_EGGS.containsKey(id))
|
|
return null;
|
|
return ItemRegistry.getRegisteredItem(id.toLowerCase() + "_spawner");
|
|
}
|
|
|
|
public Position getPos() {
|
|
return new Position(this.posX, this.posY, this.posZ, this.rotYaw, this.rotPitch, this.worldObj.dimension.getDimensionId());
|
|
}
|
|
}
|