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