    001    package net.minecraft.src;
    002
    003    import java.util.ArrayList;
    004    import java.util.Iterator;
    005    import java.util.List;
    006
    007    public class VillageCollection extends WorldSavedData
    008    {
    009        private World worldObj;
    010
    011        /**
    012         * This is a black hole. You can add data to this list through a public interface, but you can't query that
    013         * information in any way and it's not used internally either.
    014         */
    015        private final List villagerPositionsList = new ArrayList();
    016        private final List newDoors = new ArrayList();
    017        private final List villageList = new ArrayList();
    018        private int tickCounter = 0;
    019
    020        public VillageCollection(String par1Str)
    021        {
    022            super(par1Str);
    023        }
    024
    025        public VillageCollection(World par1World)
    026        {
    027            super("villages");
    028            this.worldObj = par1World;
    029            this.markDirty();
    030        }
    031
    032        public void func_82566_a(World par1World)
    033        {
    034            this.worldObj = par1World;
    035            Iterator var2 = this.villageList.iterator();
    036
    037            while (var2.hasNext())
    038            {
    039                Village var3 = (Village)var2.next();
    040                var3.func_82691_a(par1World);
    041            }
    042        }
    043
    044        /**
    045         * This is a black hole. You can add data to this list through a public interface, but you can't query that
    046         * information in any way and it's not used internally either.
    047         */
    048        public void addVillagerPosition(int par1, int par2, int par3)
    049        {
    050            if (this.villagerPositionsList.size() <= 64)
    051            {
    052                if (!this.isVillagerPositionPresent(par1, par2, par3))
    053                {
    054                    this.villagerPositionsList.add(new ChunkCoordinates(par1, par2, par3));
    055                }
    056            }
    057        }
    058
    059        /**
    060         * Runs a single tick for the village collection
    061         */
    062        public void tick()
    063        {
    064            ++this.tickCounter;
    065            Iterator var1 = this.villageList.iterator();
    066
    067            while (var1.hasNext())
    068            {
    069                Village var2 = (Village)var1.next();
    070                var2.tick(this.tickCounter);
    071            }
    072
    073            this.removeAnnihilatedVillages();
    074            this.dropOldestVillagerPosition();
    075            this.addNewDoorsToVillageOrCreateVillage();
    076
    077            if (this.tickCounter % 400 == 0)
    078            {
    079                this.markDirty();
    080            }
    081        }
    082
    083        private void removeAnnihilatedVillages()
    084        {
    085            Iterator var1 = this.villageList.iterator();
    086
    087            while (var1.hasNext())
    088            {
    089                Village var2 = (Village)var1.next();
    090
    091                if (var2.isAnnihilated())
    092                {
    093                    var1.remove();
    094                    this.markDirty();
    095                }
    096            }
    097        }
    098
    099        /**
    100         * Get a list of villages.
    101         */
    102        public List getVillageList()
    103        {
    104            return this.villageList;
    105        }
    106
    107        /**
    108         * Finds the nearest village, but only the given coordinates are withing it's bounding box plus the given the
    109         * distance.
    110         */
    111        public Village findNearestVillage(int par1, int par2, int par3, int par4)
    112        {
    113            Village var5 = null;
    114            float var6 = Float.MAX_VALUE;
    115            Iterator var7 = this.villageList.iterator();
    116
    117            while (var7.hasNext())
    118            {
    119                Village var8 = (Village)var7.next();
    120                float var9 = var8.getCenter().getDistanceSquared(par1, par2, par3);
    121
    122                if (var9 < var6)
    123                {
    124                    int var10 = par4 + var8.getVillageRadius();
    125
    126                    if (var9 <= (float)(var10 * var10))
    127                    {
    128                        var5 = var8;
    129                        var6 = var9;
    130                    }
    131                }
    132            }
    133
    134            return var5;
    135        }
    136
    137        private void dropOldestVillagerPosition()
    138        {
    139            if (!this.villagerPositionsList.isEmpty())
    140            {
    141                this.addUnassignedWoodenDoorsAroundToNewDoorsList((ChunkCoordinates)this.villagerPositionsList.remove(0));
    142            }
    143        }
    144
    145        private void addNewDoorsToVillageOrCreateVillage()
    146        {
    147            int var1 = 0;
    148
    149            while (var1 < this.newDoors.size())
    150            {
    151                VillageDoorInfo var2 = (VillageDoorInfo)this.newDoors.get(var1);
    152                boolean var3 = false;
    153                Iterator var4 = this.villageList.iterator();
    154
    155                while (true)
    156                {
    157                    if (var4.hasNext())
    158                    {
    159                        Village var5 = (Village)var4.next();
    160                        int var6 = (int)var5.getCenter().getDistanceSquared(var2.posX, var2.posY, var2.posZ);
    161                        int var7 = 32 + var5.getVillageRadius();
    162
    163                        if (var6 > var7 * var7)
    164                        {
    165                            continue;
    166                        }
    167
    168                        var5.addVillageDoorInfo(var2);
    169                        var3 = true;
    170                    }
    171
    172                    if (!var3)
    173                    {
    174                        Village var8 = new Village(this.worldObj);
    175                        var8.addVillageDoorInfo(var2);
    176                        this.villageList.add(var8);
    177                        this.markDirty();
    178                    }
    179
    180                    ++var1;
    181                    break;
    182                }
    183            }
    184
    185            this.newDoors.clear();
    186        }
    187
    188        private void addUnassignedWoodenDoorsAroundToNewDoorsList(ChunkCoordinates par1ChunkCoordinates)
    189        {
    190            byte var2 = 16;
    191            byte var3 = 4;
    192            byte var4 = 16;
    193
    194            for (int var5 = par1ChunkCoordinates.posX - var2; var5 < par1ChunkCoordinates.posX + var2; ++var5)
    195            {
    196                for (int var6 = par1ChunkCoordinates.posY - var3; var6 < par1ChunkCoordinates.posY + var3; ++var6)
    197                {
    198                    for (int var7 = par1ChunkCoordinates.posZ - var4; var7 < par1ChunkCoordinates.posZ + var4; ++var7)
    199                    {
    200                        if (this.isWoodenDoorAt(var5, var6, var7))
    201                        {
    202                            VillageDoorInfo var8 = this.getVillageDoorAt(var5, var6, var7);
    203
    204                            if (var8 == null)
    205                            {
    206                                this.addDoorToNewListIfAppropriate(var5, var6, var7);
    207                            }
    208                            else
    209                            {
    210                                var8.lastActivityTimestamp = this.tickCounter;
    211                            }
    212                        }
    213                    }
    214                }
    215            }
    216        }
    217
    218        private VillageDoorInfo getVillageDoorAt(int par1, int par2, int par3)
    219        {
    220            Iterator var4 = this.newDoors.iterator();
    221            VillageDoorInfo var5;
    222
    223            do
    224            {
    225                if (!var4.hasNext())
    226                {
    227                    var4 = this.villageList.iterator();
    228                    VillageDoorInfo var6;
    229
    230                    do
    231                    {
    232                        if (!var4.hasNext())
    233                        {
    234                            return null;
    235                        }
    236
    237                        Village var7 = (Village)var4.next();
    238                        var6 = var7.getVillageDoorAt(par1, par2, par3);
    239                    }
    240                    while (var6 == null);
    241
    242                    return var6;
    243                }
    244
    245                var5 = (VillageDoorInfo)var4.next();
    246            }
    247            while (var5.posX != par1 || var5.posZ != par3 || Math.abs(var5.posY - par2) > 1);
    248
    249            return var5;
    250        }
    251
    252        private void addDoorToNewListIfAppropriate(int par1, int par2, int par3)
    253        {
    254            int var4 = ((BlockDoor)Block.doorWood).getDoorOrientation(this.worldObj, par1, par2, par3);
    255            int var5;
    256            int var6;
    257
    258            if (var4 != 0 && var4 != 2)
    259            {
    260                var5 = 0;
    261
    262                for (var6 = -5; var6 < 0; ++var6)
    263                {
    264                    if (this.worldObj.canBlockSeeTheSky(par1, par2, par3 + var6))
    265                    {
    266                        --var5;
    267                    }
    268                }
    269
    270                for (var6 = 1; var6 <= 5; ++var6)
    271                {
    272                    if (this.worldObj.canBlockSeeTheSky(par1, par2, par3 + var6))
    273                    {
    274                        ++var5;
    275                    }
    276                }
    277
    278                if (var5 != 0)
    279                {
    280                    this.newDoors.add(new VillageDoorInfo(par1, par2, par3, 0, var5 > 0 ? -2 : 2, this.tickCounter));
    281                }
    282            }
    283            else
    284            {
    285                var5 = 0;
    286
    287                for (var6 = -5; var6 < 0; ++var6)
    288                {
    289                    if (this.worldObj.canBlockSeeTheSky(par1 + var6, par2, par3))
    290                    {
    291                        --var5;
    292                    }
    293                }
    294
    295                for (var6 = 1; var6 <= 5; ++var6)
    296                {
    297                    if (this.worldObj.canBlockSeeTheSky(par1 + var6, par2, par3))
    298                    {
    299                        ++var5;
    300                    }
    301                }
    302
    303                if (var5 != 0)
    304                {
    305                    this.newDoors.add(new VillageDoorInfo(par1, par2, par3, var5 > 0 ? -2 : 2, 0, this.tickCounter));
    306                }
    307            }
    308        }
    309
    310        private boolean isVillagerPositionPresent(int par1, int par2, int par3)
    311        {
    312            Iterator var4 = this.villagerPositionsList.iterator();
    313            ChunkCoordinates var5;
    314
    315            do
    316            {
    317                if (!var4.hasNext())
    318                {
    319                    return false;
    320                }
    321
    322                var5 = (ChunkCoordinates)var4.next();
    323            }
    324            while (var5.posX != par1 || var5.posY != par2 || var5.posZ != par3);
    325
    326            return true;
    327        }
    328
    329        private boolean isWoodenDoorAt(int par1, int par2, int par3)
    330        {
    331            int var4 = this.worldObj.getBlockId(par1, par2, par3);
    332            return var4 == Block.doorWood.blockID;
    333        }
    334
    335        /**
    336         * reads in data from the NBTTagCompound into this MapDataBase
    337         */
    338        public void readFromNBT(NBTTagCompound par1NBTTagCompound)
    339        {
    340            this.tickCounter = par1NBTTagCompound.getInteger("Tick");
    341            NBTTagList var2 = par1NBTTagCompound.getTagList("Villages");
    342
    343            for (int var3 = 0; var3 < var2.tagCount(); ++var3)
    344            {
    345                NBTTagCompound var4 = (NBTTagCompound)var2.tagAt(var3);
    346                Village var5 = new Village();
    347                var5.readVillageDataFromNBT(var4);
    348                this.villageList.add(var5);
    349            }
    350        }
    351
    352        /**
    353         * write data to NBTTagCompound from this MapDataBase, similar to Entities and TileEntities
    354         */
    355        public void writeToNBT(NBTTagCompound par1NBTTagCompound)
    356        {
    357            par1NBTTagCompound.setInteger("Tick", this.tickCounter);
    358            NBTTagList var2 = new NBTTagList("Villages");
    359            Iterator var3 = this.villageList.iterator();
    360
    361            while (var3.hasNext())
    362            {
    363                Village var4 = (Village)var3.next();
    364                NBTTagCompound var5 = new NBTTagCompound("Village");
    365                var4.writeVillageDataToNBT(var5);
    366                var2.appendTag(var5);
    367            }
    368
    369            par1NBTTagCompound.setTag("Villages", var2);
    370        }
    371    }