    001    package net.minecraft.src;
    002
    003    import cpw.mods.fml.common.Side;
    004    import cpw.mods.fml.common.asm.SideOnly;
    005    import java.util.Iterator;
    006
    007    public class TileEntityMobSpawner extends TileEntity
    008    {
    009        /** The stored delay before a new spawn. */
    010        public int delay = -1;
    011
    012        /**
    013         * The string ID of the mobs being spawned from this spawner. Defaults to pig, apparently.
    014         */
    015        private String mobID = "Pig";
    016
    017        /** The extra NBT data to add to spawned entities */
    018        private NBTTagCompound spawnerTags = null;
    019        public double yaw;
    020        public double yaw2 = 0.0D;
    021        private int minSpawnDelay = 200;
    022        private int maxSpawnDelay = 800;
    023        private int spawnCount = 4;
    024        @SideOnly(Side.CLIENT)
    025        private Entity spawnedMob;
    026        private int field_82350_j = 6;
    027        private int field_82349_r = 16;
    028        private int field_82348_s = 4;
    029
    030        public TileEntityMobSpawner()
    031        {
    032            this.delay = 20;
    033        }
    034
    035        @SideOnly(Side.CLIENT)
    036        public String getMobID()
    037        {
    038            return this.mobID;
    039        }
    040
    041        public void setMobID(String par1Str)
    042        {
    043            this.mobID = par1Str;
    044        }
    045
    046        /**
    047         * Returns true if there is a player in range (using World.getClosestPlayer)
    048         */
    049        public boolean anyPlayerInRange()
    050        {
    051            return this.worldObj.getClosestPlayer((double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D, (double)this.field_82349_r) != null;
    052        }
    053
    054        /**
    055         * Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count
    056         * ticks and creates a new spawn inside its implementation.
    057         */
    058        public void updateEntity()
    059        {
    060            if (this.anyPlayerInRange())
    061            {
    062                if (this.worldObj.isRemote)
    063                {
    064                    double var1 = (double)((float)this.xCoord + this.worldObj.rand.nextFloat());
    065                    double var3 = (double)((float)this.yCoord + this.worldObj.rand.nextFloat());
    066                    double var5 = (double)((float)this.zCoord + this.worldObj.rand.nextFloat());
    067                    this.worldObj.spawnParticle("smoke", var1, var3, var5, 0.0D, 0.0D, 0.0D);
    068                    this.worldObj.spawnParticle("flame", var1, var3, var5, 0.0D, 0.0D, 0.0D);
    069
    070                    if (this.delay > 0)
    071                    {
    072                        --this.delay;
    073                    }
    074
    075                    this.yaw2 = this.yaw;
    076                    this.yaw = (this.yaw + (double)(1000.0F / ((float)this.delay + 200.0F))) % 360.0D;
    077                }
    078                else
    079                {
    080                    if (this.delay == -1)
    081                    {
    082                        this.updateDelay();
    083                    }
    084
    085                    if (this.delay > 0)
    086                    {
    087                        --this.delay;
    088                        return;
    089                    }
    090
    091                    for (int var11 = 0; var11 < this.spawnCount; ++var11)
    092                    {
    093                        Entity var2 = EntityList.createEntityByName(this.mobID, this.worldObj);
    094
    095                        if (var2 == null)
    096                        {
    097                            return;
    098                        }
    099
    100                        int var12 = this.worldObj.getEntitiesWithinAABB(var2.getClass(), AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)this.xCoord, (double)this.yCoord, (double)this.zCoord, (double)(this.xCoord + 1), (double)(this.yCoord + 1), (double)(this.zCoord + 1)).expand((double)(this.field_82348_s * 2), 4.0D, (double)(this.field_82348_s * 2))).size();
    101
    102                        if (var12 >= this.field_82350_j)
    103                        {
    104                            this.updateDelay();
    105                            return;
    106                        }
    107
    108                        if (var2 != null)
    109                        {
    110                            double var4 = (double)this.xCoord + (this.worldObj.rand.nextDouble() - this.worldObj.rand.nextDouble()) * (double)this.field_82348_s;
    111                            double var6 = (double)(this.yCoord + this.worldObj.rand.nextInt(3) - 1);
    112                            double var8 = (double)this.zCoord + (this.worldObj.rand.nextDouble() - this.worldObj.rand.nextDouble()) * (double)this.field_82348_s;
    113                            EntityLiving var10 = var2 instanceof EntityLiving ? (EntityLiving)var2 : null;
    114                            var2.setLocationAndAngles(var4, var6, var8, this.worldObj.rand.nextFloat() * 360.0F, 0.0F);
    115
    116                            if (var10 == null || var10.getCanSpawnHere())
    117                            {
    118                                this.writeNBTTagsTo(var2);
    119                                this.worldObj.spawnEntityInWorld(var2);
    120                                this.worldObj.playAuxSFX(2004, this.xCoord, this.yCoord, this.zCoord, 0);
    121
    122                                if (var10 != null)
    123                                {
    124                                    var10.spawnExplosionParticle();
    125                                }
    126
    127                                this.updateDelay();
    128                            }
    129                        }
    130                    }
    131                }
    132
    133                super.updateEntity();
    134            }
    135        }
    136
    137        public void writeNBTTagsTo(Entity par1Entity)
    138        {
    139            if (this.spawnerTags != null)
    140            {
    141                NBTTagCompound var2 = new NBTTagCompound();
    142                par1Entity.addEntityID(var2);
    143                Iterator var3 = this.spawnerTags.getTags().iterator();
    144
    145                while (var3.hasNext())
    146                {
    147                    NBTBase var4 = (NBTBase)var3.next();
    148                    var2.setTag(var4.getName(), var4.copy());
    149                }
    150
    151                par1Entity.readFromNBT(var2);
    152            }
    153            else if (par1Entity instanceof EntityLiving && par1Entity.worldObj != null)
    154            {
    155                ((EntityLiving)par1Entity).func_82163_bD();
    156            }
    157        }
    158
    159        /**
    160         * Sets the delay before a new spawn (base delay of 200 + random number up to 600).
    161         */
    162        private void updateDelay()
    163        {
    164            this.delay = this.minSpawnDelay + this.worldObj.rand.nextInt(this.maxSpawnDelay - this.minSpawnDelay);
    165            this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType().blockID, 1, 0);
    166        }
    167
    168        /**
    169         * Reads a tile entity from NBT.
    170         */
    171        public void readFromNBT(NBTTagCompound par1NBTTagCompound)
    172        {
    173            super.readFromNBT(par1NBTTagCompound);
    174            this.mobID = par1NBTTagCompound.getString("EntityId");
    175            this.delay = par1NBTTagCompound.getShort("Delay");
    176
    177            if (par1NBTTagCompound.hasKey("SpawnData"))
    178            {
    179                this.spawnerTags = par1NBTTagCompound.getCompoundTag("SpawnData");
    180            }
    181            else
    182            {
    183                this.spawnerTags = null;
    184            }
    185
    186            if (par1NBTTagCompound.hasKey("MinSpawnDelay"))
    187            {
    188                this.minSpawnDelay = par1NBTTagCompound.getShort("MinSpawnDelay");
    189                this.maxSpawnDelay = par1NBTTagCompound.getShort("MaxSpawnDelay");
    190                this.spawnCount = par1NBTTagCompound.getShort("SpawnCount");
    191            }
    192
    193            if (par1NBTTagCompound.hasKey("MaxNearbyEntities"))
    194            {
    195                this.field_82350_j = par1NBTTagCompound.getShort("MaxNearbyEntities");
    196                this.field_82349_r = par1NBTTagCompound.getShort("RequiredPlayerRange");
    197            }
    198
    199            if (par1NBTTagCompound.hasKey("SpawnRange"))
    200            {
    201                this.field_82348_s = par1NBTTagCompound.getShort("SpawnRange");
    202            }
    203        }
    204
    205        /**
    206         * Writes a tile entity to NBT.
    207         */
    208        public void writeToNBT(NBTTagCompound par1NBTTagCompound)
    209        {
    210            super.writeToNBT(par1NBTTagCompound);
    211            par1NBTTagCompound.setString("EntityId", this.mobID);
    212            par1NBTTagCompound.setShort("Delay", (short)this.delay);
    213            par1NBTTagCompound.setShort("MinSpawnDelay", (short)this.minSpawnDelay);
    214            par1NBTTagCompound.setShort("MaxSpawnDelay", (short)this.maxSpawnDelay);
    215            par1NBTTagCompound.setShort("SpawnCount", (short)this.spawnCount);
    216            par1NBTTagCompound.setShort("MaxNearbyEntities", (short)this.field_82350_j);
    217            par1NBTTagCompound.setShort("RequiredPlayerRange", (short)this.field_82349_r);
    218            par1NBTTagCompound.setShort("SpawnRange", (short)this.field_82348_s);
    219
    220            if (this.spawnerTags != null)
    221            {
    222                par1NBTTagCompound.setCompoundTag("SpawnData", this.spawnerTags);
    223            }
    224        }
    225
    226        @SideOnly(Side.CLIENT)
    227
    228        /**
    229         * will create the entity from the internalID the first time it is accessed
    230         */
    231        public Entity getMobEntity()
    232        {
    233            if (this.spawnedMob == null)
    234            {
    235                Entity var1 = EntityList.createEntityByName(this.getMobID(), (World)null);
    236                this.writeNBTTagsTo(var1);
    237                this.spawnedMob = var1;
    238            }
    239
    240            return this.spawnedMob;
    241        }
    242
    243        /**
    244         * Overriden in a sign to provide the text.
    245         */
    246        public Packet getDescriptionPacket()
    247        {
    248            NBTTagCompound var1 = new NBTTagCompound();
    249            this.writeToNBT(var1);
    250            return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 1, var1);
    251        }
    252
    253        /**
    254         * Called when a client event is received with the event number and argument, see World.sendClientEvent
    255         */
    256        public void receiveClientEvent(int par1, int par2)
    257        {
    258            if (par1 == 1 && this.worldObj.isRemote)
    259            {
    260                this.delay = this.minSpawnDelay;
    261            }
    262        }
    263    }