package net.minecraft.village; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import net.minecraft.block.Block; import net.minecraft.block.BlockDoor; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.ChunkCoordinates; import net.minecraft.world.World; import net.minecraft.world.WorldSavedData; public class VillageCollection extends WorldSavedData { private World worldObj; /** * This is a black hole. You can add data to this list through a public interface, but you can't query that * information in any way and it's not used internally either. */ private final List villagerPositionsList = new ArrayList(); private final List newDoors = new ArrayList(); private final List villageList = new ArrayList(); private int tickCounter = 0; public VillageCollection(String par1Str) { super(par1Str); } public VillageCollection(World par1World) { super("villages"); this.worldObj = par1World; this.markDirty(); } public void func_82566_a(World par1World) { this.worldObj = par1World; Iterator var2 = this.villageList.iterator(); while (var2.hasNext()) { Village var3 = (Village)var2.next(); var3.func_82691_a(par1World); } } /** * This is a black hole. You can add data to this list through a public interface, but you can't query that * information in any way and it's not used internally either. */ public void addVillagerPosition(int par1, int par2, int par3) { if (this.villagerPositionsList.size() <= 64) { if (!this.isVillagerPositionPresent(par1, par2, par3)) { this.villagerPositionsList.add(new ChunkCoordinates(par1, par2, par3)); } } } /** * Runs a single tick for the village collection */ public void tick() { ++this.tickCounter; Iterator var1 = this.villageList.iterator(); while (var1.hasNext()) { Village var2 = (Village)var1.next(); var2.tick(this.tickCounter); } this.removeAnnihilatedVillages(); this.dropOldestVillagerPosition(); this.addNewDoorsToVillageOrCreateVillage(); if (this.tickCounter % 400 == 0) { this.markDirty(); } } private void removeAnnihilatedVillages() { Iterator var1 = this.villageList.iterator(); while (var1.hasNext()) { Village var2 = (Village)var1.next(); if (var2.isAnnihilated()) { var1.remove(); this.markDirty(); } } } /** * Get a list of villages. */ public List getVillageList() { return this.villageList; } /** * Finds the nearest village, but only the given coordinates are withing it's bounding box plus the given the * distance. */ public Village findNearestVillage(int par1, int par2, int par3, int par4) { Village var5 = null; float var6 = Float.MAX_VALUE; Iterator var7 = this.villageList.iterator(); while (var7.hasNext()) { Village var8 = (Village)var7.next(); float var9 = var8.getCenter().getDistanceSquared(par1, par2, par3); if (var9 < var6) { int var10 = par4 + var8.getVillageRadius(); if (var9 <= (float)(var10 * var10)) { var5 = var8; var6 = var9; } } } return var5; } private void dropOldestVillagerPosition() { if (!this.villagerPositionsList.isEmpty()) { this.addUnassignedWoodenDoorsAroundToNewDoorsList((ChunkCoordinates)this.villagerPositionsList.remove(0)); } } private void addNewDoorsToVillageOrCreateVillage() { int var1 = 0; while (var1 < this.newDoors.size()) { VillageDoorInfo var2 = (VillageDoorInfo)this.newDoors.get(var1); boolean var3 = false; Iterator var4 = this.villageList.iterator(); while (true) { if (var4.hasNext()) { Village var5 = (Village)var4.next(); int var6 = (int)var5.getCenter().getDistanceSquared(var2.posX, var2.posY, var2.posZ); int var7 = 32 + var5.getVillageRadius(); if (var6 > var7 * var7) { continue; } var5.addVillageDoorInfo(var2); var3 = true; } if (!var3) { Village var8 = new Village(this.worldObj); var8.addVillageDoorInfo(var2); this.villageList.add(var8); this.markDirty(); } ++var1; break; } } this.newDoors.clear(); } private void addUnassignedWoodenDoorsAroundToNewDoorsList(ChunkCoordinates par1ChunkCoordinates) { byte var2 = 16; byte var3 = 4; byte var4 = 16; for (int var5 = par1ChunkCoordinates.posX - var2; var5 < par1ChunkCoordinates.posX + var2; ++var5) { for (int var6 = par1ChunkCoordinates.posY - var3; var6 < par1ChunkCoordinates.posY + var3; ++var6) { for (int var7 = par1ChunkCoordinates.posZ - var4; var7 < par1ChunkCoordinates.posZ + var4; ++var7) { if (this.isWoodenDoorAt(var5, var6, var7)) { VillageDoorInfo var8 = this.getVillageDoorAt(var5, var6, var7); if (var8 == null) { this.addDoorToNewListIfAppropriate(var5, var6, var7); } else { var8.lastActivityTimestamp = this.tickCounter; } } } } } } private VillageDoorInfo getVillageDoorAt(int par1, int par2, int par3) { Iterator var4 = this.newDoors.iterator(); VillageDoorInfo var5; do { if (!var4.hasNext()) { var4 = this.villageList.iterator(); VillageDoorInfo var6; do { if (!var4.hasNext()) { return null; } Village var7 = (Village)var4.next(); var6 = var7.getVillageDoorAt(par1, par2, par3); } while (var6 == null); return var6; } var5 = (VillageDoorInfo)var4.next(); } while (var5.posX != par1 || var5.posZ != par3 || Math.abs(var5.posY - par2) > 1); return var5; } private void addDoorToNewListIfAppropriate(int par1, int par2, int par3) { int var4 = ((BlockDoor)Block.doorWood).getDoorOrientation(this.worldObj, par1, par2, par3); int var5; int var6; if (var4 != 0 && var4 != 2) { var5 = 0; for (var6 = -5; var6 < 0; ++var6) { if (this.worldObj.canBlockSeeTheSky(par1, par2, par3 + var6)) { --var5; } } for (var6 = 1; var6 <= 5; ++var6) { if (this.worldObj.canBlockSeeTheSky(par1, par2, par3 + var6)) { ++var5; } } if (var5 != 0) { this.newDoors.add(new VillageDoorInfo(par1, par2, par3, 0, var5 > 0 ? -2 : 2, this.tickCounter)); } } else { var5 = 0; for (var6 = -5; var6 < 0; ++var6) { if (this.worldObj.canBlockSeeTheSky(par1 + var6, par2, par3)) { --var5; } } for (var6 = 1; var6 <= 5; ++var6) { if (this.worldObj.canBlockSeeTheSky(par1 + var6, par2, par3)) { ++var5; } } if (var5 != 0) { this.newDoors.add(new VillageDoorInfo(par1, par2, par3, var5 > 0 ? -2 : 2, 0, this.tickCounter)); } } } private boolean isVillagerPositionPresent(int par1, int par2, int par3) { Iterator var4 = this.villagerPositionsList.iterator(); ChunkCoordinates var5; do { if (!var4.hasNext()) { return false; } var5 = (ChunkCoordinates)var4.next(); } while (var5.posX != par1 || var5.posY != par2 || var5.posZ != par3); return true; } private boolean isWoodenDoorAt(int par1, int par2, int par3) { int var4 = this.worldObj.getBlockId(par1, par2, par3); return var4 == Block.doorWood.blockID; } /** * reads in data from the NBTTagCompound into this MapDataBase */ public void readFromNBT(NBTTagCompound par1NBTTagCompound) { this.tickCounter = par1NBTTagCompound.getInteger("Tick"); NBTTagList var2 = par1NBTTagCompound.getTagList("Villages"); for (int var3 = 0; var3 < var2.tagCount(); ++var3) { NBTTagCompound var4 = (NBTTagCompound)var2.tagAt(var3); Village var5 = new Village(); var5.readVillageDataFromNBT(var4); this.villageList.add(var5); } } /** * write data to NBTTagCompound from this MapDataBase, similar to Entities and TileEntities */ public void writeToNBT(NBTTagCompound par1NBTTagCompound) { par1NBTTagCompound.setInteger("Tick", this.tickCounter); NBTTagList var2 = new NBTTagList("Villages"); Iterator var3 = this.villageList.iterator(); while (var3.hasNext()) { Village var4 = (Village)var3.next(); NBTTagCompound var5 = new NBTTagCompound("Village"); var4.writeVillageDataToNBT(var5); var2.appendTag(var5); } par1NBTTagCompound.setTag("Villages", var2); } }