001package net.minecraft.tileentity;
002
003import cpw.mods.fml.relauncher.Side;
004import cpw.mods.fml.relauncher.SideOnly;
005import java.util.ArrayList;
006import java.util.Iterator;
007import java.util.List;
008import net.minecraft.entity.Entity;
009import net.minecraft.entity.EntityList;
010import net.minecraft.entity.EntityLiving;
011import net.minecraft.nbt.NBTBase;
012import net.minecraft.nbt.NBTTagCompound;
013import net.minecraft.nbt.NBTTagList;
014import net.minecraft.util.AxisAlignedBB;
015import net.minecraft.util.WeightedRandom;
016import net.minecraft.world.World;
017
018public abstract class MobSpawnerBaseLogic
019{
020    /** The delay to spawn. */
021    public int spawnDelay = 20;
022    private String mobID = "Pig";
023
024    /** List of minecart to spawn. */
025    private List minecartToSpawn = null;
026    private WeightedRandomMinecart randomMinecart = null;
027    public double field_98287_c;
028    public double field_98284_d = 0.0D;
029    private int minSpawnDelay = 200;
030    private int maxSpawnDelay = 800;
031
032    /** A counter for spawn tries. */
033    private int spawnCount = 4;
034    private Entity field_98291_j;
035    private int maxNearbyEntities = 6;
036
037    /** The distance from which a player activates the spawner. */
038    private int activatingRangeFromPlayer = 16;
039
040    /** The range coefficient for spawning entities around. */
041    private int spawnRange = 4;
042
043    /**
044     * Gets the entity name that should be spawned.
045     */
046    public String getEntityNameToSpawn()
047    {
048        if (this.getRandomMinecart() == null)
049        {
050            if (this.mobID.equals("Minecart"))
051            {
052                this.mobID = "MinecartRideable";
053            }
054
055            return this.mobID;
056        }
057        else
058        {
059            return this.getRandomMinecart().minecartName;
060        }
061    }
062
063    public void setMobID(String par1Str)
064    {
065        this.mobID = par1Str;
066    }
067
068    /**
069     * Returns true if there's a player close enough to this mob spawner to activate it.
070     */
071    public boolean canRun()
072    {
073        return this.getSpawnerWorld().getClosestPlayer((double)this.getSpawnerX() + 0.5D, (double)this.getSpawnerY() + 0.5D, (double)this.getSpawnerZ() + 0.5D, (double)this.activatingRangeFromPlayer) != null;
074    }
075
076    public void updateSpawner()
077    {
078        if (this.canRun())
079        {
080            double d0;
081
082            if (this.getSpawnerWorld().isRemote)
083            {
084                double d1 = (double)((float)this.getSpawnerX() + this.getSpawnerWorld().rand.nextFloat());
085                double d2 = (double)((float)this.getSpawnerY() + this.getSpawnerWorld().rand.nextFloat());
086                d0 = (double)((float)this.getSpawnerZ() + this.getSpawnerWorld().rand.nextFloat());
087                this.getSpawnerWorld().spawnParticle("smoke", d1, d2, d0, 0.0D, 0.0D, 0.0D);
088                this.getSpawnerWorld().spawnParticle("flame", d1, d2, d0, 0.0D, 0.0D, 0.0D);
089
090                if (this.spawnDelay > 0)
091                {
092                    --this.spawnDelay;
093                }
094
095                this.field_98284_d = this.field_98287_c;
096                this.field_98287_c = (this.field_98287_c + (double)(1000.0F / ((float)this.spawnDelay + 200.0F))) % 360.0D;
097            }
098            else
099            {
100                if (this.spawnDelay == -1)
101                {
102                    this.func_98273_j();
103                }
104
105                if (this.spawnDelay > 0)
106                {
107                    --this.spawnDelay;
108                    return;
109                }
110
111                boolean flag = false;
112
113                for (int i = 0; i < this.spawnCount; ++i)
114                {
115                    Entity entity = EntityList.createEntityByName(this.getEntityNameToSpawn(), this.getSpawnerWorld());
116
117                    if (entity == null)
118                    {
119                        return;
120                    }
121
122                    int j = this.getSpawnerWorld().getEntitiesWithinAABB(entity.getClass(), AxisAlignedBB.getAABBPool().getAABB((double)this.getSpawnerX(), (double)this.getSpawnerY(), (double)this.getSpawnerZ(), (double)(this.getSpawnerX() + 1), (double)(this.getSpawnerY() + 1), (double)(this.getSpawnerZ() + 1)).expand((double)(this.spawnRange * 2), 4.0D, (double)(this.spawnRange * 2))).size();
123
124                    if (j >= this.maxNearbyEntities)
125                    {
126                        this.func_98273_j();
127                        return;
128                    }
129
130                    d0 = (double)this.getSpawnerX() + (this.getSpawnerWorld().rand.nextDouble() - this.getSpawnerWorld().rand.nextDouble()) * (double)this.spawnRange;
131                    double d3 = (double)(this.getSpawnerY() + this.getSpawnerWorld().rand.nextInt(3) - 1);
132                    double d4 = (double)this.getSpawnerZ() + (this.getSpawnerWorld().rand.nextDouble() - this.getSpawnerWorld().rand.nextDouble()) * (double)this.spawnRange;
133                    EntityLiving entityliving = entity instanceof EntityLiving ? (EntityLiving)entity : null;
134                    entity.setLocationAndAngles(d0, d3, d4, this.getSpawnerWorld().rand.nextFloat() * 360.0F, 0.0F);
135
136                    if (entityliving == null || entityliving.getCanSpawnHere())
137                    {
138                        this.func_98265_a(entity);
139                        this.getSpawnerWorld().playAuxSFX(2004, this.getSpawnerX(), this.getSpawnerY(), this.getSpawnerZ(), 0);
140
141                        if (entityliving != null)
142                        {
143                            entityliving.spawnExplosionParticle();
144                        }
145
146                        flag = true;
147                    }
148                }
149
150                if (flag)
151                {
152                    this.func_98273_j();
153                }
154            }
155        }
156    }
157
158    public Entity func_98265_a(Entity par1Entity)
159    {
160        if (this.getRandomMinecart() != null)
161        {
162            NBTTagCompound nbttagcompound = new NBTTagCompound();
163            par1Entity.addEntityID(nbttagcompound);
164            Iterator iterator = this.getRandomMinecart().field_98222_b.getTags().iterator();
165
166            while (iterator.hasNext())
167            {
168                NBTBase nbtbase = (NBTBase)iterator.next();
169                nbttagcompound.setTag(nbtbase.getName(), nbtbase.copy());
170            }
171
172            par1Entity.readFromNBT(nbttagcompound);
173
174            if (par1Entity.worldObj != null)
175            {
176                par1Entity.worldObj.spawnEntityInWorld(par1Entity);
177            }
178
179            NBTTagCompound nbttagcompound1;
180
181            for (Entity entity1 = par1Entity; nbttagcompound.hasKey("Riding"); nbttagcompound = nbttagcompound1)
182            {
183                nbttagcompound1 = nbttagcompound.getCompoundTag("Riding");
184                Entity entity2 = EntityList.createEntityByName(nbttagcompound1.getString("id"), this.getSpawnerWorld());
185
186                if (entity2 != null)
187                {
188                    NBTTagCompound nbttagcompound2 = new NBTTagCompound();
189                    entity2.addEntityID(nbttagcompound2);
190                    Iterator iterator1 = nbttagcompound1.getTags().iterator();
191
192                    while (iterator1.hasNext())
193                    {
194                        NBTBase nbtbase1 = (NBTBase)iterator1.next();
195                        nbttagcompound2.setTag(nbtbase1.getName(), nbtbase1.copy());
196                    }
197
198                    entity2.readFromNBT(nbttagcompound2);
199                    entity2.setLocationAndAngles(entity1.posX, entity1.posY, entity1.posZ, entity1.rotationYaw, entity1.rotationPitch);
200                    this.getSpawnerWorld().spawnEntityInWorld(entity2);
201                    entity1.mountEntity(entity2);
202                }
203
204                entity1 = entity2;
205            }
206        }
207        else if (par1Entity instanceof EntityLiving && par1Entity.worldObj != null)
208        {
209            ((EntityLiving)par1Entity).initCreature();
210            this.getSpawnerWorld().spawnEntityInWorld(par1Entity);
211        }
212
213        return par1Entity;
214    }
215
216    private void func_98273_j()
217    {
218        if (this.maxSpawnDelay <= this.minSpawnDelay)
219        {
220            this.spawnDelay = this.minSpawnDelay;
221        }
222        else
223        {
224            int i = this.maxSpawnDelay - this.minSpawnDelay;
225            this.spawnDelay = this.minSpawnDelay + this.getSpawnerWorld().rand.nextInt(i);
226        }
227
228        if (this.minecartToSpawn != null && this.minecartToSpawn.size() > 0)
229        {
230            this.setRandomMinecart((WeightedRandomMinecart)WeightedRandom.getRandomItem(this.getSpawnerWorld().rand, this.minecartToSpawn));
231        }
232
233        this.func_98267_a(1);
234    }
235
236    public void readFromNBT(NBTTagCompound par1NBTTagCompound)
237    {
238        this.mobID = par1NBTTagCompound.getString("EntityId");
239        this.spawnDelay = par1NBTTagCompound.getShort("Delay");
240
241        if (par1NBTTagCompound.hasKey("SpawnPotentials"))
242        {
243            this.minecartToSpawn = new ArrayList();
244            NBTTagList nbttaglist = par1NBTTagCompound.getTagList("SpawnPotentials");
245
246            for (int i = 0; i < nbttaglist.tagCount(); ++i)
247            {
248                this.minecartToSpawn.add(new WeightedRandomMinecart(this, (NBTTagCompound)nbttaglist.tagAt(i)));
249            }
250        }
251        else
252        {
253            this.minecartToSpawn = null;
254        }
255
256        if (par1NBTTagCompound.hasKey("SpawnData"))
257        {
258            this.setRandomMinecart(new WeightedRandomMinecart(this, par1NBTTagCompound.getCompoundTag("SpawnData"), this.mobID));
259        }
260        else
261        {
262            this.setRandomMinecart((WeightedRandomMinecart)null);
263        }
264
265        if (par1NBTTagCompound.hasKey("MinSpawnDelay"))
266        {
267            this.minSpawnDelay = par1NBTTagCompound.getShort("MinSpawnDelay");
268            this.maxSpawnDelay = par1NBTTagCompound.getShort("MaxSpawnDelay");
269            this.spawnCount = par1NBTTagCompound.getShort("SpawnCount");
270        }
271
272        if (par1NBTTagCompound.hasKey("MaxNearbyEntities"))
273        {
274            this.maxNearbyEntities = par1NBTTagCompound.getShort("MaxNearbyEntities");
275            this.activatingRangeFromPlayer = par1NBTTagCompound.getShort("RequiredPlayerRange");
276        }
277
278        if (par1NBTTagCompound.hasKey("SpawnRange"))
279        {
280            this.spawnRange = par1NBTTagCompound.getShort("SpawnRange");
281        }
282
283        if (this.getSpawnerWorld() != null && this.getSpawnerWorld().isRemote)
284        {
285            this.field_98291_j = null;
286        }
287    }
288
289    public void writeToNBT(NBTTagCompound par1NBTTagCompound)
290    {
291        par1NBTTagCompound.setString("EntityId", this.getEntityNameToSpawn());
292        par1NBTTagCompound.setShort("Delay", (short)this.spawnDelay);
293        par1NBTTagCompound.setShort("MinSpawnDelay", (short)this.minSpawnDelay);
294        par1NBTTagCompound.setShort("MaxSpawnDelay", (short)this.maxSpawnDelay);
295        par1NBTTagCompound.setShort("SpawnCount", (short)this.spawnCount);
296        par1NBTTagCompound.setShort("MaxNearbyEntities", (short)this.maxNearbyEntities);
297        par1NBTTagCompound.setShort("RequiredPlayerRange", (short)this.activatingRangeFromPlayer);
298        par1NBTTagCompound.setShort("SpawnRange", (short)this.spawnRange);
299
300        if (this.getRandomMinecart() != null)
301        {
302            par1NBTTagCompound.setCompoundTag("SpawnData", (NBTTagCompound)this.getRandomMinecart().field_98222_b.copy());
303        }
304
305        if (this.getRandomMinecart() != null || this.minecartToSpawn != null && this.minecartToSpawn.size() > 0)
306        {
307            NBTTagList nbttaglist = new NBTTagList();
308
309            if (this.minecartToSpawn != null && this.minecartToSpawn.size() > 0)
310            {
311                Iterator iterator = this.minecartToSpawn.iterator();
312
313                while (iterator.hasNext())
314                {
315                    WeightedRandomMinecart weightedrandomminecart = (WeightedRandomMinecart)iterator.next();
316                    nbttaglist.appendTag(weightedrandomminecart.func_98220_a());
317                }
318            }
319            else
320            {
321                nbttaglist.appendTag(this.getRandomMinecart().func_98220_a());
322            }
323
324            par1NBTTagCompound.setTag("SpawnPotentials", nbttaglist);
325        }
326    }
327
328    /**
329     * Sets the delay to minDelay if parameter given is 1, else return false.
330     */
331    public boolean setDelayToMin(int par1)
332    {
333        if (par1 == 1 && this.getSpawnerWorld().isRemote)
334        {
335            this.spawnDelay = this.minSpawnDelay;
336            return true;
337        }
338        else
339        {
340            return false;
341        }
342    }
343
344    @SideOnly(Side.CLIENT)
345    public Entity func_98281_h()
346    {
347        if (this.field_98291_j == null)
348        {
349            Entity entity = EntityList.createEntityByName(this.getEntityNameToSpawn(), (World)null);
350            entity = this.func_98265_a(entity);
351            this.field_98291_j = entity;
352        }
353
354        return this.field_98291_j;
355    }
356
357    public WeightedRandomMinecart getRandomMinecart()
358    {
359        return this.randomMinecart;
360    }
361
362    public void setRandomMinecart(WeightedRandomMinecart par1WeightedRandomMinecart)
363    {
364        this.randomMinecart = par1WeightedRandomMinecart;
365    }
366
367    public abstract void func_98267_a(int i);
368
369    public abstract World getSpawnerWorld();
370
371    public abstract int getSpawnerX();
372
373    public abstract int getSpawnerY();
374
375    public abstract int getSpawnerZ();
376}