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
027 public TileEntityMobSpawner()
028 {
029 this.delay = 20;
030 }
031
032 @SideOnly(Side.CLIENT)
033 public String getMobID()
034 {
035 return this.mobID;
036 }
037
038 public void setMobID(String par1Str)
039 {
040 this.mobID = par1Str;
041 }
042
043 /**
044 * Returns true if there is a player in range (using World.getClosestPlayer)
045 */
046 public boolean anyPlayerInRange()
047 {
048 return this.worldObj.getClosestPlayer((double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D, 16.0D) != null;
049 }
050
051 /**
052 * Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count
053 * ticks and creates a new spawn inside its implementation.
054 */
055 public void updateEntity()
056 {
057 if (this.anyPlayerInRange())
058 {
059 if (this.worldObj.isRemote)
060 {
061 double var1 = (double)((float)this.xCoord + this.worldObj.rand.nextFloat());
062 double var3 = (double)((float)this.yCoord + this.worldObj.rand.nextFloat());
063 double var5 = (double)((float)this.zCoord + this.worldObj.rand.nextFloat());
064 this.worldObj.spawnParticle("smoke", var1, var3, var5, 0.0D, 0.0D, 0.0D);
065 this.worldObj.spawnParticle("flame", var1, var3, var5, 0.0D, 0.0D, 0.0D);
066 this.yaw2 = this.yaw % 360.0D;
067 this.yaw += 4.545454502105713D;
068 }
069 else
070 {
071 if (this.delay == -1)
072 {
073 this.updateDelay();
074 }
075
076 if (this.delay > 0)
077 {
078 --this.delay;
079 return;
080 }
081
082 for (int var11 = 0; var11 < this.spawnCount; ++var11)
083 {
084 Entity var2 = EntityList.createEntityByName(this.mobID, this.worldObj);
085
086 if (var2 == null)
087 {
088 return;
089 }
090
091 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(8.0D, 4.0D, 8.0D)).size();
092
093 if (var12 >= 6)
094 {
095 this.updateDelay();
096 return;
097 }
098
099 if (var2 != null)
100 {
101 double var4 = (double)this.xCoord + (this.worldObj.rand.nextDouble() - this.worldObj.rand.nextDouble()) * 4.0D;
102 double var6 = (double)(this.yCoord + this.worldObj.rand.nextInt(3) - 1);
103 double var8 = (double)this.zCoord + (this.worldObj.rand.nextDouble() - this.worldObj.rand.nextDouble()) * 4.0D;
104 EntityLiving var10 = var2 instanceof EntityLiving ? (EntityLiving)var2 : null;
105 var2.setLocationAndAngles(var4, var6, var8, this.worldObj.rand.nextFloat() * 360.0F, 0.0F);
106
107 if (var10 == null || var10.getCanSpawnHere())
108 {
109 this.writeNBTTagsTo(var2);
110 this.worldObj.spawnEntityInWorld(var2);
111 this.worldObj.playAuxSFX(2004, this.xCoord, this.yCoord, this.zCoord, 0);
112
113 if (var10 != null)
114 {
115 var10.spawnExplosionParticle();
116 }
117
118 this.updateDelay();
119 }
120 }
121 }
122 }
123
124 super.updateEntity();
125 }
126 }
127
128 public void writeNBTTagsTo(Entity par1Entity)
129 {
130 if (this.spawnerTags != null)
131 {
132 NBTTagCompound var2 = new NBTTagCompound();
133 par1Entity.addEntityID(var2);
134 Iterator var3 = this.spawnerTags.getTags().iterator();
135
136 while (var3.hasNext())
137 {
138 NBTBase var4 = (NBTBase)var3.next();
139 var2.setTag(var4.getName(), var4.copy());
140 }
141
142 par1Entity.readFromNBT(var2);
143 }
144 }
145
146 /**
147 * Sets the delay before a new spawn (base delay of 200 + random number up to 600).
148 */
149 private void updateDelay()
150 {
151 this.delay = this.minSpawnDelay + this.worldObj.rand.nextInt(this.maxSpawnDelay - this.minSpawnDelay);
152 }
153
154 /**
155 * Reads a tile entity from NBT.
156 */
157 public void readFromNBT(NBTTagCompound par1NBTTagCompound)
158 {
159 super.readFromNBT(par1NBTTagCompound);
160 this.mobID = par1NBTTagCompound.getString("EntityId");
161 this.delay = par1NBTTagCompound.getShort("Delay");
162
163 if (par1NBTTagCompound.hasKey("SpawnData"))
164 {
165 this.spawnerTags = par1NBTTagCompound.getCompoundTag("SpawnData");
166 }
167 else
168 {
169 this.spawnerTags = null;
170 }
171
172 if (par1NBTTagCompound.hasKey("MinSpawnDelay"))
173 {
174 this.minSpawnDelay = par1NBTTagCompound.getShort("MinSpawnDelay");
175 this.maxSpawnDelay = par1NBTTagCompound.getShort("MaxSpawnDelay");
176 this.spawnCount = par1NBTTagCompound.getShort("SpawnCount");
177 }
178 }
179
180 /**
181 * Writes a tile entity to NBT.
182 */
183 public void writeToNBT(NBTTagCompound par1NBTTagCompound)
184 {
185 super.writeToNBT(par1NBTTagCompound);
186 par1NBTTagCompound.setString("EntityId", this.mobID);
187 par1NBTTagCompound.setShort("Delay", (short)this.delay);
188 par1NBTTagCompound.setShort("MinSpawnDelay", (short)this.minSpawnDelay);
189 par1NBTTagCompound.setShort("MaxSpawnDelay", (short)this.maxSpawnDelay);
190 par1NBTTagCompound.setShort("SpawnCount", (short)this.spawnCount);
191
192 if (this.spawnerTags != null)
193 {
194 par1NBTTagCompound.setCompoundTag("SpawnData", this.spawnerTags);
195 }
196 }
197
198 @SideOnly(Side.CLIENT)
199
200 /**
201 * will create the entity from the internalID the first time it is accessed
202 */
203 public Entity getMobEntity()
204 {
205 if (this.spawnedMob == null)
206 {
207 Entity var1 = EntityList.createEntityByName(this.getMobID(), (World)null);
208 this.writeNBTTagsTo(var1);
209 this.spawnedMob = var1;
210 }
211
212 return this.spawnedMob;
213 }
214
215 /**
216 * Overriden in a sign to provide the text.
217 */
218 public Packet getDescriptionPacket()
219 {
220 NBTTagCompound var1 = new NBTTagCompound();
221 this.writeToNBT(var1);
222 return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 1, var1);
223 }
224 }