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 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 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 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 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. {@code null} is not allowed! 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()); } }