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        public List func_75540_b()
075        {
076            return this.villageList;
077        }
078    
079        /**
080         * Finds the nearest village, but only the given coordinates are withing it's bounding box plus the given the
081         * distance.
082         */
083        public Village findNearestVillage(int par1, int par2, int par3, int par4)
084        {
085            Village var5 = null;
086            float var6 = Float.MAX_VALUE;
087            Iterator var7 = this.villageList.iterator();
088    
089            while (var7.hasNext())
090            {
091                Village var8 = (Village)var7.next();
092                float var9 = var8.getCenter().getDistanceSquared(par1, par2, par3);
093    
094                if (var9 < var6)
095                {
096                    int var10 = par4 + var8.getVillageRadius();
097    
098                    if (var9 <= (float)(var10 * var10))
099                    {
100                        var5 = var8;
101                        var6 = var9;
102                    }
103                }
104            }
105    
106            return var5;
107        }
108    
109        private void dropOldestVillagerPosition()
110        {
111            if (!this.villagerPositionsList.isEmpty())
112            {
113                this.addUnassignedWoodenDoorsAroundToNewDoorsList((ChunkCoordinates)this.villagerPositionsList.remove(0));
114            }
115        }
116    
117        private void addNewDoorsToVillageOrCreateVillage()
118        {
119            Iterator var1 = this.newDoors.iterator();
120    
121            while (var1.hasNext())
122            {
123                VillageDoorInfo var2 = (VillageDoorInfo)var1.next();
124                boolean var3 = false;
125                Iterator var4 = this.villageList.iterator();
126    
127                while (true)
128                {
129                    if (var4.hasNext())
130                    {
131                        Village var5 = (Village)var4.next();
132                        int var6 = (int)var5.getCenter().getDistanceSquared(var2.posX, var2.posY, var2.posZ);
133                        int var7 = 32 + var5.getVillageRadius();
134    
135                        if (var6 > var7 * var7)
136                        {
137                            continue;
138                        }
139    
140                        var5.addVillageDoorInfo(var2);
141                        var3 = true;
142                    }
143    
144                    if (!var3)
145                    {
146                        Village var8 = new Village(this.worldObj);
147                        var8.addVillageDoorInfo(var2);
148                        this.villageList.add(var8);
149                    }
150    
151                    break;
152                }
153            }
154    
155            this.newDoors.clear();
156        }
157    
158        private void addUnassignedWoodenDoorsAroundToNewDoorsList(ChunkCoordinates par1ChunkCoordinates)
159        {
160            byte var2 = 16;
161            byte var3 = 4;
162            byte var4 = 16;
163    
164            for (int var5 = par1ChunkCoordinates.posX - var2; var5 < par1ChunkCoordinates.posX + var2; ++var5)
165            {
166                for (int var6 = par1ChunkCoordinates.posY - var3; var6 < par1ChunkCoordinates.posY + var3; ++var6)
167                {
168                    for (int var7 = par1ChunkCoordinates.posZ - var4; var7 < par1ChunkCoordinates.posZ + var4; ++var7)
169                    {
170                        if (this.isWoodenDoorAt(var5, var6, var7))
171                        {
172                            VillageDoorInfo var8 = this.getVillageDoorAt(var5, var6, var7);
173    
174                            if (var8 == null)
175                            {
176                                this.addDoorToNewListIfAppropriate(var5, var6, var7);
177                            }
178                            else
179                            {
180                                var8.lastActivityTimestamp = this.tickCounter;
181                            }
182                        }
183                    }
184                }
185            }
186        }
187    
188        private VillageDoorInfo getVillageDoorAt(int par1, int par2, int par3)
189        {
190            Iterator var4 = this.newDoors.iterator();
191            VillageDoorInfo var5;
192    
193            do
194            {
195                if (!var4.hasNext())
196                {
197                    var4 = this.villageList.iterator();
198                    VillageDoorInfo var6;
199    
200                    do
201                    {
202                        if (!var4.hasNext())
203                        {
204                            return null;
205                        }
206    
207                        Village var7 = (Village)var4.next();
208                        var6 = var7.getVillageDoorAt(par1, par2, par3);
209                    }
210                    while (var6 == null);
211    
212                    return var6;
213                }
214    
215                var5 = (VillageDoorInfo)var4.next();
216            }
217            while (var5.posX != par1 || var5.posZ != par3 || Math.abs(var5.posY - par2) > 1);
218    
219            return var5;
220        }
221    
222        private void addDoorToNewListIfAppropriate(int par1, int par2, int par3)
223        {
224            int var4 = ((BlockDoor)Block.doorWood).getDoorOrientation(this.worldObj, par1, par2, par3);
225            int var5;
226            int var6;
227    
228            if (var4 != 0 && var4 != 2)
229            {
230                var5 = 0;
231    
232                for (var6 = -5; var6 < 0; ++var6)
233                {
234                    if (this.worldObj.canBlockSeeTheSky(par1, par2, par3 + var6))
235                    {
236                        --var5;
237                    }
238                }
239    
240                for (var6 = 1; var6 <= 5; ++var6)
241                {
242                    if (this.worldObj.canBlockSeeTheSky(par1, par2, par3 + var6))
243                    {
244                        ++var5;
245                    }
246                }
247    
248                if (var5 != 0)
249                {
250                    this.newDoors.add(new VillageDoorInfo(par1, par2, par3, 0, var5 > 0 ? -2 : 2, this.tickCounter));
251                }
252            }
253            else
254            {
255                var5 = 0;
256    
257                for (var6 = -5; var6 < 0; ++var6)
258                {
259                    if (this.worldObj.canBlockSeeTheSky(par1 + var6, par2, par3))
260                    {
261                        --var5;
262                    }
263                }
264    
265                for (var6 = 1; var6 <= 5; ++var6)
266                {
267                    if (this.worldObj.canBlockSeeTheSky(par1 + var6, par2, par3))
268                    {
269                        ++var5;
270                    }
271                }
272    
273                if (var5 != 0)
274                {
275                    this.newDoors.add(new VillageDoorInfo(par1, par2, par3, var5 > 0 ? -2 : 2, 0, this.tickCounter));
276                }
277            }
278        }
279    
280        private boolean isVillagerPositionPresent(int par1, int par2, int par3)
281        {
282            Iterator var4 = this.villagerPositionsList.iterator();
283            ChunkCoordinates var5;
284    
285            do
286            {
287                if (!var4.hasNext())
288                {
289                    return false;
290                }
291    
292                var5 = (ChunkCoordinates)var4.next();
293            }
294            while (var5.posX != par1 || var5.posY != par2 || var5.posZ != par3);
295    
296            return true;
297        }
298    
299        private boolean isWoodenDoorAt(int par1, int par2, int par3)
300        {
301            int var4 = this.worldObj.getBlockId(par1, par2, par3);
302            return var4 == Block.doorWood.blockID;
303        }
304    }