001    package net.minecraft.src;
002    
003    import cpw.mods.fml.common.Side;
004    import cpw.mods.fml.common.asm.SideOnly;
005    
006    public class EntityIronGolem extends EntityGolem
007    {
008        /** deincrements, and a distance-to-home check is done at 0 */
009        private int homeCheckTimer = 0;
010        Village villageObj = null;
011        private int attackTimer;
012        private int holdRoseTick;
013    
014        public EntityIronGolem(World par1World)
015        {
016            super(par1World);
017            this.texture = "/mob/villager_golem.png";
018            this.setSize(1.4F, 2.9F);
019            this.getNavigator().setAvoidsWater(true);
020            this.tasks.addTask(1, new EntityAIAttackOnCollide(this, 0.25F, true));
021            this.tasks.addTask(2, new EntityAIMoveTowardsTarget(this, 0.22F, 32.0F));
022            this.tasks.addTask(3, new EntityAIMoveThroughVillage(this, 0.16F, true));
023            this.tasks.addTask(4, new EntityAIMoveTwardsRestriction(this, 0.16F));
024            this.tasks.addTask(5, new EntityAILookAtVillager(this));
025            this.tasks.addTask(6, new EntityAIWander(this, 0.16F));
026            this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
027            this.tasks.addTask(8, new EntityAILookIdle(this));
028            this.targetTasks.addTask(1, new EntityAIDefendVillage(this));
029            this.targetTasks.addTask(2, new EntityAIHurtByTarget(this, false));
030            this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityMob.class, 16.0F, 0, false, true));
031        }
032    
033        protected void entityInit()
034        {
035            super.entityInit();
036            this.dataWatcher.addObject(16, Byte.valueOf((byte)0));
037        }
038    
039        /**
040         * Returns true if the newer Entity AI code should be run
041         */
042        public boolean isAIEnabled()
043        {
044            return true;
045        }
046    
047        /**
048         * main AI tick function, replaces updateEntityActionState
049         */
050        protected void updateAITick()
051        {
052            if (--this.homeCheckTimer <= 0)
053            {
054                this.homeCheckTimer = 70 + this.rand.nextInt(50);
055                this.villageObj = this.worldObj.villageCollectionObj.findNearestVillage(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ), 32);
056    
057                if (this.villageObj == null)
058                {
059                    this.detachHome();
060                }
061                else
062                {
063                    ChunkCoordinates var1 = this.villageObj.getCenter();
064                    this.setHomeArea(var1.posX, var1.posY, var1.posZ, this.villageObj.getVillageRadius());
065                }
066            }
067    
068            super.updateAITick();
069        }
070    
071        public int getMaxHealth()
072        {
073            return 100;
074        }
075    
076        /**
077         * Decrements the entity's air supply when underwater
078         */
079        protected int decreaseAirSupply(int par1)
080        {
081            return par1;
082        }
083    
084        /**
085         * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
086         * use this to react to sunlight and start to burn.
087         */
088        public void onLivingUpdate()
089        {
090            super.onLivingUpdate();
091    
092            if (this.attackTimer > 0)
093            {
094                --this.attackTimer;
095            }
096    
097            if (this.holdRoseTick > 0)
098            {
099                --this.holdRoseTick;
100            }
101    
102            if (this.motionX * this.motionX + this.motionZ * this.motionZ > 2.500000277905201E-7D && this.rand.nextInt(5) == 0)
103            {
104                int var1 = MathHelper.floor_double(this.posX);
105                int var2 = MathHelper.floor_double(this.posY - 0.20000000298023224D - (double)this.yOffset);
106                int var3 = MathHelper.floor_double(this.posZ);
107                int var4 = this.worldObj.getBlockId(var1, var2, var3);
108    
109                if (var4 > 0)
110                {
111                    this.worldObj.spawnParticle("tilecrack_" + var4, this.posX + ((double)this.rand.nextFloat() - 0.5D) * (double)this.width, this.boundingBox.minY + 0.1D, this.posZ + ((double)this.rand.nextFloat() - 0.5D) * (double)this.width, 4.0D * ((double)this.rand.nextFloat() - 0.5D), 0.5D, ((double)this.rand.nextFloat() - 0.5D) * 4.0D);
112                }
113            }
114        }
115    
116        public boolean isExplosiveMob(Class par1Class)
117        {
118            return this.getBit1Flag() && EntityPlayer.class.isAssignableFrom(par1Class) ? false : super.isExplosiveMob(par1Class);
119        }
120    
121        public boolean attackEntityAsMob(Entity par1Entity)
122        {
123            this.attackTimer = 10;
124            this.worldObj.setEntityState(this, (byte)4);
125            boolean var2 = par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), 7 + this.rand.nextInt(15));
126    
127            if (var2)
128            {
129                par1Entity.motionY += 0.4000000059604645D;
130            }
131    
132            this.worldObj.playSoundAtEntity(this, "mob.irongolem.throw", 1.0F, 1.0F);
133            return var2;
134        }
135    
136        @SideOnly(Side.CLIENT)
137        public void handleHealthUpdate(byte par1)
138        {
139            if (par1 == 4)
140            {
141                this.attackTimer = 10;
142                this.worldObj.playSoundAtEntity(this, "mob.irongolem.throw", 1.0F, 1.0F);
143            }
144            else if (par1 == 11)
145            {
146                this.holdRoseTick = 400;
147            }
148            else
149            {
150                super.handleHealthUpdate(par1);
151            }
152        }
153    
154        public Village getVillage()
155        {
156            return this.villageObj;
157        }
158    
159        @SideOnly(Side.CLIENT)
160        public int getAttackTimer()
161        {
162            return this.attackTimer;
163        }
164    
165        public void setHoldingRose(boolean par1)
166        {
167            this.holdRoseTick = par1 ? 400 : 0;
168            this.worldObj.setEntityState(this, (byte)11);
169        }
170    
171        /**
172         * Returns the sound this mob makes while it's alive.
173         */
174        protected String getLivingSound()
175        {
176            return "none";
177        }
178    
179        /**
180         * Returns the sound this mob makes when it is hurt.
181         */
182        protected String getHurtSound()
183        {
184            return "mob.irongolem.hit";
185        }
186    
187        /**
188         * Returns the sound this mob makes on death.
189         */
190        protected String getDeathSound()
191        {
192            return "mob.irongolem.death";
193        }
194    
195        /**
196         * Plays step sound at given x, y, z for the entity
197         */
198        protected void playStepSound(int par1, int par2, int par3, int par4)
199        {
200            this.worldObj.playSoundAtEntity(this, "mob.irongolem.walk", 1.0F, 1.0F);
201        }
202    
203        /**
204         * Drop 0-2 items of this living's type
205         */
206        protected void dropFewItems(boolean par1, int par2)
207        {
208            int var3 = this.rand.nextInt(3);
209            int var4;
210    
211            for (var4 = 0; var4 < var3; ++var4)
212            {
213                this.dropItem(Block.plantRed.blockID, 1);
214            }
215    
216            var4 = 3 + this.rand.nextInt(3);
217    
218            for (int var5 = 0; var5 < var4; ++var5)
219            {
220                this.dropItem(Item.ingotIron.shiftedIndex, 1);
221            }
222        }
223    
224        public int getHoldRoseTick()
225        {
226            return this.holdRoseTick;
227        }
228    
229        public boolean getBit1Flag()
230        {
231            return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
232        }
233    
234        public void setBit1FlagTo(boolean par1)
235        {
236            byte var2 = this.dataWatcher.getWatchableObjectByte(16);
237    
238            if (par1)
239            {
240                this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 | 1)));
241            }
242            else
243            {
244                this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 & -2)));
245            }
246        }
247    }