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 }