package net.minecraft.entity.boss; import java.util.List; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.EnumCreatureAttribute; import net.minecraft.entity.IRangedAttackMob; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.projectile.EntityArrow; import net.minecraft.entity.projectile.EntityWitherSkull; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.PotionEffect; import net.minecraft.util.BlockPos; import net.minecraft.util.DamageSource; import net.minecraft.util.EntitySelectors; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.MathHelper; import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; /**+ * This portion of EaglercraftX contains deobfuscated Minecraft 1.8 source code. * * Minecraft 1.8.8 bytecode is (c) 2015 Mojang AB. "Do not distribute!" * Mod Coder Pack v9.18 deobfuscation configs are (c) Copyright by the MCP Team * * EaglercraftX 1.8 patch files are (c) 2022 LAX1DUDE. All Rights Reserved. * * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. * * NOT FOR COMMERCIAL OR MALICIOUS USE * * (please read the 'LICENSE' file this repo's root directory for more info) * */ public class EntityWither extends EntityMob implements IBossDisplayData, IRangedAttackMob { private float[] field_82220_d = new float[2]; private float[] field_82221_e = new float[2]; private float[] field_82217_f = new float[2]; private float[] field_82218_g = new float[2]; private int[] field_82223_h = new int[2]; private int[] field_82224_i = new int[2]; private int blockBreakCounter; /**+ * Selector used to determine the entities a wither boss should * attack. */ private static final Predicate attackEntitySelector = new Predicate() { public boolean apply(Entity entity) { return entity instanceof EntityLivingBase && ((EntityLivingBase) entity).getCreatureAttribute() != EnumCreatureAttribute.UNDEAD; } }; public EntityWither(World worldIn) { super(worldIn); this.setHealth(this.getMaxHealth()); this.setSize(0.9F, 3.5F); this.isImmuneToFire = true; this.experienceValue = 50; } protected void entityInit() { super.entityInit(); this.dataWatcher.addObject(17, new Integer(0)); this.dataWatcher.addObject(18, new Integer(0)); this.dataWatcher.addObject(19, new Integer(0)); this.dataWatcher.addObject(20, new Integer(0)); } /**+ * (abstract) Protected helper method to write subclass entity * data to NBT. */ public void writeEntityToNBT(NBTTagCompound nbttagcompound) { super.writeEntityToNBT(nbttagcompound); nbttagcompound.setInteger("Invul", this.getInvulTime()); } /**+ * (abstract) Protected helper method to read subclass entity * data from NBT. */ public void readEntityFromNBT(NBTTagCompound nbttagcompound) { super.readEntityFromNBT(nbttagcompound); this.setInvulTime(nbttagcompound.getInteger("Invul")); } /**+ * Returns the sound this mob makes while it's alive. */ protected String getLivingSound() { return "mob.wither.idle"; } /**+ * Returns the sound this mob makes when it is hurt. */ protected String getHurtSound() { return "mob.wither.hurt"; } /**+ * Returns the sound this mob makes on death. */ protected String getDeathSound() { return "mob.wither.death"; } /**+ * Called frequently so the entity can update its state every * tick as required. For example, zombies and skeletons use this * to react to sunlight and start to burn. */ public void onLivingUpdate() { this.motionY *= 0.6000000238418579D; if (this.motionX * this.motionX + this.motionZ * this.motionZ > 0.05000000074505806D) { this.rotationYaw = (float) MathHelper.func_181159_b(this.motionZ, this.motionX) * 57.295776F - 90.0F; } super.onLivingUpdate(); for (int i = 0; i < 2; ++i) { this.field_82218_g[i] = this.field_82221_e[i]; this.field_82217_f[i] = this.field_82220_d[i]; } for (int j = 0; j < 2; ++j) { int k = this.getWatchedTargetId(j + 1); Entity entity1 = null; if (k > 0) { entity1 = this.worldObj.getEntityByID(k); } if (entity1 != null) { double d11 = this.func_82214_u(j + 1); double d12 = this.func_82208_v(j + 1); double d13 = this.func_82213_w(j + 1); double d6 = entity1.posX - d11; double d7 = entity1.posY + (double) entity1.getEyeHeight() - d12; double d8 = entity1.posZ - d13; double d9 = (double) MathHelper.sqrt_double(d6 * d6 + d8 * d8); float f = (float) (MathHelper.func_181159_b(d8, d6) * 180.0D / 3.1415927410125732D) - 90.0F; float f1 = (float) (-(MathHelper.func_181159_b(d7, d9) * 180.0D / 3.1415927410125732D)); this.field_82220_d[j] = this.func_82204_b(this.field_82220_d[j], f1, 40.0F); this.field_82221_e[j] = this.func_82204_b(this.field_82221_e[j], f, 10.0F); } else { this.field_82221_e[j] = this.func_82204_b(this.field_82221_e[j], this.renderYawOffset, 10.0F); } } boolean flag = this.isArmored(); for (int l = 0; l < 3; ++l) { double d10 = this.func_82214_u(l); double d2 = this.func_82208_v(l); double d4 = this.func_82213_w(l); this.worldObj.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d10 + this.rand.nextGaussian() * 0.30000001192092896D, d2 + this.rand.nextGaussian() * 0.30000001192092896D, d4 + this.rand.nextGaussian() * 0.30000001192092896D, 0.0D, 0.0D, 0.0D, new int[0]); if (flag && this.worldObj.rand.nextInt(4) == 0) { this.worldObj.spawnParticle(EnumParticleTypes.SPELL_MOB, d10 + this.rand.nextGaussian() * 0.30000001192092896D, d2 + this.rand.nextGaussian() * 0.30000001192092896D, d4 + this.rand.nextGaussian() * 0.30000001192092896D, 0.699999988079071D, 0.699999988079071D, 0.5D, new int[0]); } } if (this.getInvulTime() > 0) { for (int i1 = 0; i1 < 3; ++i1) { this.worldObj.spawnParticle(EnumParticleTypes.SPELL_MOB, this.posX + this.rand.nextGaussian() * 1.0D, this.posY + (double) (this.rand.nextFloat() * 3.3F), this.posZ + this.rand.nextGaussian() * 1.0D, 0.699999988079071D, 0.699999988079071D, 0.8999999761581421D, new int[0]); } } } protected void updateAITasks() { if (this.getInvulTime() > 0) { int j1 = this.getInvulTime() - 1; if (j1 <= 0) { this.worldObj.newExplosion(this, this.posX, this.posY + (double) this.getEyeHeight(), this.posZ, 7.0F, false, this.worldObj.getGameRules().getBoolean("mobGriefing")); this.worldObj.playBroadcastSound(1013, new BlockPos(this), 0); } this.setInvulTime(j1); if (this.ticksExisted % 10 == 0) { this.heal(10.0F); } } else { super.updateAITasks(); for (int i = 1; i < 3; ++i) { if (this.ticksExisted >= this.field_82223_h[i - 1]) { this.field_82223_h[i - 1] = this.ticksExisted + 10 + this.rand.nextInt(10); if (this.worldObj.getDifficulty() == EnumDifficulty.NORMAL || this.worldObj.getDifficulty() == EnumDifficulty.HARD) { int j3 = i - 1; int k3 = this.field_82224_i[i - 1]; this.field_82224_i[j3] = this.field_82224_i[i - 1] + 1; if (k3 > 15) { float f = 10.0F; float f1 = 5.0F; double d0 = MathHelper.getRandomDoubleInRange(this.rand, this.posX - (double) f, this.posX + (double) f); double d1 = MathHelper.getRandomDoubleInRange(this.rand, this.posY - (double) f1, this.posY + (double) f1); double d2 = MathHelper.getRandomDoubleInRange(this.rand, this.posZ - (double) f, this.posZ + (double) f); this.launchWitherSkullToCoords(i + 1, d0, d1, d2, true); this.field_82224_i[i - 1] = 0; } } int k1 = this.getWatchedTargetId(i); if (k1 > 0) { Entity entity = this.worldObj.getEntityByID(k1); if (entity != null && entity.isEntityAlive() && this.getDistanceSqToEntity(entity) <= 900.0D && this.canEntityBeSeen(entity)) { if (entity instanceof EntityPlayer && ((EntityPlayer) entity).capabilities.disableDamage) { this.updateWatchedTargetId(i, 0); } else { this.launchWitherSkullToEntity(i + 1, (EntityLivingBase) entity); this.field_82223_h[i - 1] = this.ticksExisted + 40 + this.rand.nextInt(20); this.field_82224_i[i - 1] = 0; } } else { this.updateWatchedTargetId(i, 0); } } else { List list = this.worldObj.getEntitiesWithinAABB(EntityLivingBase.class, this.getEntityBoundingBox().expand(20.0D, 8.0D, 20.0D), Predicates.and(attackEntitySelector, EntitySelectors.NOT_SPECTATING)); for (int j2 = 0; j2 < 10 && !list.isEmpty(); ++j2) { EntityLivingBase entitylivingbase = (EntityLivingBase) list .get(this.rand.nextInt(list.size())); if (entitylivingbase != this && entitylivingbase.isEntityAlive() && this.canEntityBeSeen(entitylivingbase)) { if (entitylivingbase instanceof EntityPlayer) { if (!((EntityPlayer) entitylivingbase).capabilities.disableDamage) { this.updateWatchedTargetId(i, entitylivingbase.getEntityId()); } } else { this.updateWatchedTargetId(i, entitylivingbase.getEntityId()); } break; } list.remove(entitylivingbase); } } } } if (this.getAttackTarget() != null) { this.updateWatchedTargetId(0, this.getAttackTarget().getEntityId()); } else { this.updateWatchedTargetId(0, 0); } if (this.blockBreakCounter > 0) { --this.blockBreakCounter; if (this.blockBreakCounter == 0 && this.worldObj.getGameRules().getBoolean("mobGriefing")) { int i1 = MathHelper.floor_double(this.posY); int l1 = MathHelper.floor_double(this.posX); int i2 = MathHelper.floor_double(this.posZ); boolean flag = false; for (int k2 = -1; k2 <= 1; ++k2) { for (int l2 = -1; l2 <= 1; ++l2) { for (int j = 0; j <= 3; ++j) { int i3 = l1 + k2; int k = i1 + j; int l = i2 + l2; BlockPos blockpos = new BlockPos(i3, k, l); Block block = this.worldObj.getBlockState(blockpos).getBlock(); if (block.getMaterial() != Material.air && func_181033_a(block)) { flag = this.worldObj.destroyBlock(blockpos, true) || flag; } } } } if (flag) { this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1012, new BlockPos(this), 0); } } } if (this.ticksExisted % 20 == 0) { this.heal(1.0F); } } } public static boolean func_181033_a(Block parBlock) { return parBlock != Blocks.bedrock && parBlock != Blocks.end_portal && parBlock != Blocks.end_portal_frame && parBlock != Blocks.command_block && parBlock != Blocks.barrier; } public void func_82206_m() { this.setInvulTime(220); this.setHealth(this.getMaxHealth() / 3.0F); } /**+ * Sets the Entity inside a web block. */ public void setInWeb() { } /**+ * Returns the current armor value as determined by a call to * InventoryPlayer.getTotalArmorValue */ public int getTotalArmorValue() { return 4; } private double func_82214_u(int parInt1) { if (parInt1 <= 0) { return this.posX; } else { float f = (this.renderYawOffset + (float) (180 * (parInt1 - 1))) / 180.0F * 3.1415927F; float f1 = MathHelper.cos(f); return this.posX + (double) f1 * 1.3D; } } private double func_82208_v(int parInt1) { return parInt1 <= 0 ? this.posY + 3.0D : this.posY + 2.2D; } private double func_82213_w(int parInt1) { if (parInt1 <= 0) { return this.posZ; } else { float f = (this.renderYawOffset + (float) (180 * (parInt1 - 1))) / 180.0F * 3.1415927F; float f1 = MathHelper.sin(f); return this.posZ + (double) f1 * 1.3D; } } private float func_82204_b(float parFloat1, float parFloat2, float parFloat3) { float f = MathHelper.wrapAngleTo180_float(parFloat2 - parFloat1); if (f > parFloat3) { f = parFloat3; } if (f < -parFloat3) { f = -parFloat3; } return parFloat1 + f; } private void launchWitherSkullToEntity(int parInt1, EntityLivingBase parEntityLivingBase) { this.launchWitherSkullToCoords(parInt1, parEntityLivingBase.posX, parEntityLivingBase.posY + (double) parEntityLivingBase.getEyeHeight() * 0.5D, parEntityLivingBase.posZ, parInt1 == 0 && this.rand.nextFloat() < 0.001F); } /**+ * Launches a Wither skull toward (par2, par4, par6) */ private void launchWitherSkullToCoords(int x, double y, double z, double invulnerable, boolean parFlag) { this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1014, new BlockPos(this), 0); double d0 = this.func_82214_u(x); double d1 = this.func_82208_v(x); double d2 = this.func_82213_w(x); double d3 = y - d0; double d4 = z - d1; double d5 = invulnerable - d2; EntityWitherSkull entitywitherskull = new EntityWitherSkull(this.worldObj, this, d3, d4, d5); if (parFlag) { entitywitherskull.setInvulnerable(true); } entitywitherskull.posY = d1; entitywitherskull.posX = d0; entitywitherskull.posZ = d2; this.worldObj.spawnEntityInWorld(entitywitherskull); } /**+ * Attack the specified entity using a ranged attack. */ public void attackEntityWithRangedAttack(EntityLivingBase entitylivingbase, float var2) { this.launchWitherSkullToEntity(0, entitylivingbase); } /**+ * Called when the entity is attacked. */ public boolean attackEntityFrom(DamageSource damagesource, float f) { if (this.isEntityInvulnerable(damagesource)) { return false; } else if (damagesource != DamageSource.drown && !(damagesource.getEntity() instanceof EntityWither)) { if (this.getInvulTime() > 0 && damagesource != DamageSource.outOfWorld) { return false; } else { if (this.isArmored()) { Entity entity = damagesource.getSourceOfDamage(); if (entity instanceof EntityArrow) { return false; } } Entity entity1 = damagesource.getEntity(); if (entity1 != null && !(entity1 instanceof EntityPlayer) && entity1 instanceof EntityLivingBase && ((EntityLivingBase) entity1).getCreatureAttribute() == this.getCreatureAttribute()) { return false; } else { if (this.blockBreakCounter <= 0) { this.blockBreakCounter = 20; } for (int i = 0; i < this.field_82224_i.length; ++i) { this.field_82224_i[i] += 3; } return super.attackEntityFrom(damagesource, f); } } } else { return false; } } /**+ * Drop 0-2 items of this living's type */ protected void dropFewItems(boolean var1, int var2) { EntityItem entityitem = this.dropItem(Items.nether_star, 1); if (entityitem != null) { entityitem.setNoDespawn(); } } /**+ * Makes the entity despawn if requirements are reached */ protected void despawnEntity() { this.entityAge = 0; } public int getBrightnessForRender(float var1) { return 15728880; } public void fall(float var1, float var2) { } /**+ * adds a PotionEffect to the entity */ public void addPotionEffect(PotionEffect var1) { } protected void applyEntityAttributes() { super.applyEntityAttributes(); this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(300.0D); this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.6000000238418579D); this.getEntityAttribute(SharedMonsterAttributes.followRange).setBaseValue(40.0D); } public float func_82207_a(int parInt1) { return this.field_82221_e[parInt1]; } public float func_82210_r(int parInt1) { return this.field_82220_d[parInt1]; } public int getInvulTime() { return this.dataWatcher.getWatchableObjectInt(20); } public void setInvulTime(int parInt1) { this.dataWatcher.updateObject(20, Integer.valueOf(parInt1)); } /**+ * Returns the target entity ID if present, or -1 if not @param * par1 The target offset, should be from 0-2 */ public int getWatchedTargetId(int parInt1) { return this.dataWatcher.getWatchableObjectInt(17 + parInt1); } /**+ * Updates the target entity ID */ public void updateWatchedTargetId(int targetOffset, int newId) { this.dataWatcher.updateObject(17 + targetOffset, Integer.valueOf(newId)); } /**+ * Returns whether the wither is armored with its boss armor or * not by checking whether its health is below half of its * maximum. */ public boolean isArmored() { return this.getHealth() <= this.getMaxHealth() / 2.0F; } /**+ * Get this Entity's EnumCreatureAttribute */ public EnumCreatureAttribute getCreatureAttribute() { return EnumCreatureAttribute.UNDEAD; } /**+ * Called when a player mounts an entity. e.g. mounts a pig, * mounts a boat. */ public void mountEntity(Entity var1) { this.ridingEntity = null; } }