    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            Iterator var1 = this.newDoors.iterator();
    148
    149            while (var1.hasNext())
    150            {
    151                VillageDoorInfo var2 = (VillageDoorInfo)var1.next();
    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                    break;
    181                }
    182            }
    183
    184            this.newDoors.clear();
    185        }
    186
    187        private void addUnassignedWoodenDoorsAroundToNewDoorsList(ChunkCoordinates par1ChunkCoordinates)
    188        {
    189            byte var2 = 16;
    190            byte var3 = 4;
    191            byte var4 = 16;
    192
    193            for (int var5 = par1ChunkCoordinates.posX - var2; var5 < par1ChunkCoordinates.posX + var2; ++var5)
    194            {
    195                for (int var6 = par1ChunkCoordinates.posY - var3; var6 < par1ChunkCoordinates.posY + var3; ++var6)
    196                {
    197                    for (int var7 = par1ChunkCoordinates.posZ - var4; var7 < par1ChunkCoordinates.posZ + var4; ++var7)
    198                    {
    199                        if (this.isWoodenDoorAt(var5, var6, var7))
    200                        {
    201                            VillageDoorInfo var8 = this.getVillageDoorAt(var5, var6, var7);
    202
    203                            if (var8 == null)
    204                            {
    205                                this.addDoorToNewListIfAppropriate(var5, var6, var7);
    206                            }
    207                            else
    208                            {
    209                                var8.lastActivityTimestamp = this.tickCounter;
    210                            }
    211                        }
    212                    }
    213                }
    214            }
    215        }
    216
    217        private VillageDoorInfo getVillageDoorAt(int par1, int par2, int par3)
    218        {
    219            Iterator var4 = this.newDoors.iterator();
    220            VillageDoorInfo var5;
    221
    222            do
    223            {
    224                if (!var4.hasNext())
    225                {
    226                    var4 = this.villageList.iterator();
    227                    VillageDoorInfo var6;
    228
    229                    do
    230                    {
    231                        if (!var4.hasNext())
    232                        {
    233                            return null;
    234                        }
    235
    236                        Village var7 = (Village)var4.next();
    237                        var6 = var7.getVillageDoorAt(par1, par2, par3);
    238                    }
    239                    while (var6 == null);
    240
    241                    return var6;
    242                }
    243
    244                var5 = (VillageDoorInfo)var4.next();
    245            }
    246            while (var5.posX != par1 || var5.posZ != par3 || Math.abs(var5.posY - par2) > 1);
    247
    248            return var5;
    249        }
    250
    251        private void addDoorToNewListIfAppropriate(int par1, int par2, int par3)
    252        {
    253            int var4 = ((BlockDoor)Block.doorWood).getDoorOrientation(this.worldObj, par1, par2, par3);
    254            int var5;
    255            int var6;
    256
    257            if (var4 != 0 && var4 != 2)
    258            {
    259                var5 = 0;
    260
    261                for (var6 = -5; var6 < 0; ++var6)
    262                {
    263                    if (this.worldObj.canBlockSeeTheSky(par1, par2, par3 + var6))
    264                    {
    265                        --var5;
    266                    }
    267                }
    268
    269                for (var6 = 1; var6 <= 5; ++var6)
    270                {
    271                    if (this.worldObj.canBlockSeeTheSky(par1, par2, par3 + var6))
    272                    {
    273                        ++var5;
    274                    }
    275                }
    276
    277                if (var5 != 0)
    278                {
    279                    this.newDoors.add(new VillageDoorInfo(par1, par2, par3, 0, var5 > 0 ? -2 : 2, this.tickCounter));
    280                }
    281            }
    282            else
    283            {
    284                var5 = 0;
    285
    286                for (var6 = -5; var6 < 0; ++var6)
    287                {
    288                    if (this.worldObj.canBlockSeeTheSky(par1 + var6, par2, par3))
    289                    {
    290                        --var5;
    291                    }
    292                }
    293
    294                for (var6 = 1; var6 <= 5; ++var6)
    295                {
    296                    if (this.worldObj.canBlockSeeTheSky(par1 + var6, par2, par3))
    297                    {
    298                        ++var5;
    299                    }
    300                }
    301
    302                if (var5 != 0)
    303                {
    304                    this.newDoors.add(new VillageDoorInfo(par1, par2, par3, var5 > 0 ? -2 : 2, 0, this.tickCounter));
    305                }
    306            }
    307        }
    308
    309        private boolean isVillagerPositionPresent(int par1, int par2, int par3)
    310        {
    311            Iterator var4 = this.villagerPositionsList.iterator();
    312            ChunkCoordinates var5;
    313
    314            do
    315            {
    316                if (!var4.hasNext())
    317                {
    318                    return false;
    319                }
    320
    321                var5 = (ChunkCoordinates)var4.next();
    322            }
    323            while (var5.posX != par1 || var5.posY != par2 || var5.posZ != par3);
    324
    325            return true;
    326        }
    327
    328        private boolean isWoodenDoorAt(int par1, int par2, int par3)
    329        {
    330            int var4 = this.worldObj.getBlockId(par1, par2, par3);
    331            return var4 == Block.doorWood.blockID;
    332        }
    333
    334        /**
    335         * reads in data from the NBTTagCompound into this MapDataBase
    336         */
    337        public void readFromNBT(NBTTagCompound par1NBTTagCompound)
    338        {
    339            this.tickCounter = par1NBTTagCompound.getInteger("Tick");
    340            NBTTagList var2 = par1NBTTagCompound.getTagList("Villages");
    341
    342            for (int var3 = 0; var3 < var2.tagCount(); ++var3)
    343            {
    344                NBTTagCompound var4 = (NBTTagCompound)var2.tagAt(var3);
    345                Village var5 = new Village();
    346                var5.func_82690_a(var4);
    347                this.villageList.add(var5);
    348            }
    349        }
    350
    351        /**
    352         * write data to NBTTagCompound from this MapDataBase, similar to Entities and TileEntities
    353         */
    354        public void writeToNBT(NBTTagCompound par1NBTTagCompound)
    355        {
    356            par1NBTTagCompound.setInteger("Tick", this.tickCounter);
    357            NBTTagList var2 = new NBTTagList("Villages");
    358            Iterator var3 = this.villageList.iterator();
    359
    360            while (var3.hasNext())
    361            {
    362                Village var4 = (Village)var3.next();
    363                NBTTagCompound var5 = new NBTTagCompound("Village");
    364                var4.func_82689_b(var5);
    365                var2.appendTag(var5);
    366            }
    367
    368            par1NBTTagCompound.setTag("Villages", var2);
    369        }
    370    }