    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}