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
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(World par1World)
021        {
022            this.worldObj = par1World;
023        }
024    
025        /**
026         * This is a black hole. You can add data to this list through a public interface, but you can't query that
027         * information in any way and it's not used internally either.
028         */
029        public void addVillagerPosition(int par1, int par2, int par3)
030        {
031            if (this.villagerPositionsList.size() <= 64)
032            {
033                if (!this.isVillagerPositionPresent(par1, par2, par3))
034                {
035                    this.villagerPositionsList.add(new ChunkCoordinates(par1, par2, par3));
036                }
037            }
038        }
039    
040        /**
041         * Runs a single tick for the village collection
042         */
043        public void tick()
044        {
045            ++this.tickCounter;
046            Iterator var1 = this.villageList.iterator();
047    
048            while (var1.hasNext())
049            {
050                Village var2 = (Village)var1.next();
051                var2.tick(this.tickCounter);
052            }
053    
054            this.removeAnnihilatedVillages();
055            this.dropOldestVillagerPosition();
056            this.addNewDoorsToVillageOrCreateVillage();
057        }
058    
059        private void removeAnnihilatedVillages()
060        {
061            Iterator var1 = this.villageList.iterator();
062    
063            while (var1.hasNext())
064            {
065                Village var2 = (Village)var1.next();
066    
067                if (var2.isAnnihilated())
068                {
069                    var1.remove();
070                }
071            }
072        }
073    
074        /**
075         * Get a list of villages.
076         */
077        public List getVillageList()
078        {
079            return this.villageList;
080        }
081    
082        /**
083         * Finds the nearest village, but only the given coordinates are withing it's bounding box plus the given the
084         * distance.
085         */
086        public Village findNearestVillage(int par1, int par2, int par3, int par4)
087        {
088            Village var5 = null;
089            float var6 = Float.MAX_VALUE;
090            Iterator var7 = this.villageList.iterator();
091    
092            while (var7.hasNext())
093            {
094                Village var8 = (Village)var7.next();
095                float var9 = var8.getCenter().getDistanceSquared(par1, par2, par3);
096    
097                if (var9 < var6)
098                {
099                    int var10 = par4 + var8.getVillageRadius();
100    
101                    if (var9 <= (float)(var10 * var10))
102                    {
103                        var5 = var8;
104                        var6 = var9;
105                    }
106                }
107            }
108    
109            return var5;
110        }
111    
112        private void dropOldestVillagerPosition()
113        {
114            if (!this.villagerPositionsList.isEmpty())
115            {
116                this.addUnassignedWoodenDoorsAroundToNewDoorsList((ChunkCoordinates)this.villagerPositionsList.remove(0));
117            }
118        }
119    
120        private void addNewDoorsToVillageOrCreateVillage()
121        {
122            Iterator var1 = this.newDoors.iterator();
123    
124            while (var1.hasNext())
125            {
126                VillageDoorInfo var2 = (VillageDoorInfo)var1.next();
127                boolean var3 = false;
128                Iterator var4 = this.villageList.iterator();
129    
130                while (true)
131                {
132                    if (var4.hasNext())
133                    {
134                        Village var5 = (Village)var4.next();
135                        int var6 = (int)var5.getCenter().getDistanceSquared(var2.posX, var2.posY, var2.posZ);
136                        int var7 = 32 + var5.getVillageRadius();
137    
138                        if (var6 > var7 * var7)
139                        {
140                            continue;
141                        }
142    
143                        var5.addVillageDoorInfo(var2);
144                        var3 = true;
145                    }
146    
147                    if (!var3)
148                    {
149                        Village var8 = new Village(this.worldObj);
150                        var8.addVillageDoorInfo(var2);
151                        this.villageList.add(var8);
152                    }
153    
154                    break;
155                }
156            }
157    
158            this.newDoors.clear();
159        }
160    
161        private void addUnassignedWoodenDoorsAroundToNewDoorsList(ChunkCoordinates par1ChunkCoordinates)
162        {
163            byte var2 = 16;
164            byte var3 = 4;
165            byte var4 = 16;
166    
167            for (int var5 = par1ChunkCoordinates.posX - var2; var5 < par1ChunkCoordinates.posX + var2; ++var5)
168            {
169                for (int var6 = par1ChunkCoordinates.posY - var3; var6 < par1ChunkCoordinates.posY + var3; ++var6)
170                {
171                    for (int var7 = par1ChunkCoordinates.posZ - var4; var7 < par1ChunkCoordinates.posZ + var4; ++var7)
172                    {
173                        if (this.isWoodenDoorAt(var5, var6, var7))
174                        {
175                            VillageDoorInfo var8 = this.getVillageDoorAt(var5, var6, var7);
176    
177                            if (var8 == null)
178                            {
179                                this.addDoorToNewListIfAppropriate(var5, var6, var7);
180                            }
181                            else
182                            {
183                                var8.lastActivityTimestamp = this.tickCounter;
184                            }
185                        }
186                    }
187                }
188            }
189        }
190    
191        private VillageDoorInfo getVillageDoorAt(int par1, int par2, int par3)
192        {
193            Iterator var4 = this.newDoors.iterator();
194            VillageDoorInfo var5;
195    
196            do
197            {
198                if (!var4.hasNext())
199                {
200                    var4 = this.villageList.iterator();
201                    VillageDoorInfo var6;
202    
203                    do
204                    {
205                        if (!var4.hasNext())
206                        {
207                            return null;
208                        }
209    
210                        Village var7 = (Village)var4.next();
211                        var6 = var7.getVillageDoorAt(par1, par2, par3);
212                    }
213                    while (var6 == null);
214    
215                    return var6;
216                }
217    
218                var5 = (VillageDoorInfo)var4.next();
219            }
220            while (var5.posX != par1 || var5.posZ != par3 || Math.abs(var5.posY - par2) > 1);
221    
222            return var5;
223        }
224    
225        private void addDoorToNewListIfAppropriate(int par1, int par2, int par3)
226        {
227            int var4 = ((BlockDoor)Block.doorWood).getDoorOrientation(this.worldObj, par1, par2, par3);
228            int var5;
229            int var6;
230    
231            if (var4 != 0 && var4 != 2)
232            {
233                var5 = 0;
234    
235                for (var6 = -5; var6 < 0; ++var6)
236                {
237                    if (this.worldObj.canBlockSeeTheSky(par1, par2, par3 + var6))
238                    {
239                        --var5;
240                    }
241                }
242    
243                for (var6 = 1; var6 <= 5; ++var6)
244                {
245                    if (this.worldObj.canBlockSeeTheSky(par1, par2, par3 + var6))
246                    {
247                        ++var5;
248                    }
249                }
250    
251                if (var5 != 0)
252                {
253                    this.newDoors.add(new VillageDoorInfo(par1, par2, par3, 0, var5 > 0 ? -2 : 2, this.tickCounter));
254                }
255            }
256            else
257            {
258                var5 = 0;
259    
260                for (var6 = -5; var6 < 0; ++var6)
261                {
262                    if (this.worldObj.canBlockSeeTheSky(par1 + var6, par2, par3))
263                    {
264                        --var5;
265                    }
266                }
267    
268                for (var6 = 1; var6 <= 5; ++var6)
269                {
270                    if (this.worldObj.canBlockSeeTheSky(par1 + var6, par2, par3))
271                    {
272                        ++var5;
273                    }
274                }
275    
276                if (var5 != 0)
277                {
278                    this.newDoors.add(new VillageDoorInfo(par1, par2, par3, var5 > 0 ? -2 : 2, 0, this.tickCounter));
279                }
280            }
281        }
282    
283        private boolean isVillagerPositionPresent(int par1, int par2, int par3)
284        {
285            Iterator var4 = this.villagerPositionsList.iterator();
286            ChunkCoordinates var5;
287    
288            do
289            {
290                if (!var4.hasNext())
291                {
292                    return false;
293                }
294    
295                var5 = (ChunkCoordinates)var4.next();
296            }
297            while (var5.posX != par1 || var5.posY != par2 || var5.posZ != par3);
298    
299            return true;
300        }
301    
302        private boolean isWoodenDoorAt(int par1, int par2, int par3)
303        {
304            int var4 = this.worldObj.getBlockId(par1, par2, par3);
305            return var4 == Block.doorWood.blockID;
306        }
307    }