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 }