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 iterator = this.villageList.iterator(); while (iterator.hasNext()) { Village village = (Village)iterator.next(); village.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 iterator = this.villageList.iterator(); while (iterator.hasNext()) { Village village = (Village)iterator.next(); village.tick(this.tickCounter); } this.removeAnnihilatedVillages(); this.dropOldestVillagerPosition(); this.addNewDoorsToVillageOrCreateVillage(); if (this.tickCounter % 400 == 0) { this.markDirty(); } } private void removeAnnihilatedVillages() { Iterator iterator = this.villageList.iterator(); while (iterator.hasNext()) { Village village = (Village)iterator.next(); if (village.isAnnihilated()) { iterator.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 village = null; float f = Float.MAX_VALUE; Iterator iterator = this.villageList.iterator(); while (iterator.hasNext()) { Village village1 = (Village)iterator.next(); float f1 = village1.getCenter().getDistanceSquared(par1, par2, par3); if (f1 < f) { int i1 = par4 + village1.getVillageRadius(); if (f1 <= (float)(i1 * i1)) { village = village1; f = f1; } } } return village; } private void dropOldestVillagerPosition() { if (!this.villagerPositionsList.isEmpty()) { this.addUnassignedWoodenDoorsAroundToNewDoorsList((ChunkCoordinates)this.villagerPositionsList.remove(0)); } } private void addNewDoorsToVillageOrCreateVillage() { int i = 0; while (i < this.newDoors.size()) { VillageDoorInfo villagedoorinfo = (VillageDoorInfo)this.newDoors.get(i); boolean flag = false; Iterator iterator = this.villageList.iterator(); while (true) { if (iterator.hasNext()) { Village village = (Village)iterator.next(); int j = (int)village.getCenter().getDistanceSquared(villagedoorinfo.posX, villagedoorinfo.posY, villagedoorinfo.posZ); int k = 32 + village.getVillageRadius(); if (j > k * k) { continue; } village.addVillageDoorInfo(villagedoorinfo); flag = true; } if (!flag) { Village village1 = new Village(this.worldObj); village1.addVillageDoorInfo(villagedoorinfo); this.villageList.add(village1); this.markDirty(); } ++i; break; } } this.newDoors.clear(); } private void addUnassignedWoodenDoorsAroundToNewDoorsList(ChunkCoordinates par1ChunkCoordinates) { byte b0 = 16; byte b1 = 4; byte b2 = 16; for (int i = par1ChunkCoordinates.posX - b0; i < par1ChunkCoordinates.posX + b0; ++i) { for (int j = par1ChunkCoordinates.posY - b1; j < par1ChunkCoordinates.posY + b1; ++j) { for (int k = par1ChunkCoordinates.posZ - b2; k < par1ChunkCoordinates.posZ + b2; ++k) { if (this.isWoodenDoorAt(i, j, k)) { VillageDoorInfo villagedoorinfo = this.getVillageDoorAt(i, j, k); if (villagedoorinfo == null) { this.addDoorToNewListIfAppropriate(i, j, k); } else { villagedoorinfo.lastActivityTimestamp = this.tickCounter; } } } } } } private VillageDoorInfo getVillageDoorAt(int par1, int par2, int par3) { Iterator iterator = this.newDoors.iterator(); VillageDoorInfo villagedoorinfo; do { if (!iterator.hasNext()) { iterator = this.villageList.iterator(); VillageDoorInfo villagedoorinfo1; do { if (!iterator.hasNext()) { return null; } Village village = (Village)iterator.next(); villagedoorinfo1 = village.getVillageDoorAt(par1, par2, par3); } while (villagedoorinfo1 == null); return villagedoorinfo1; } villagedoorinfo = (VillageDoorInfo)iterator.next(); } while (villagedoorinfo.posX != par1 || villagedoorinfo.posZ != par3 || Math.abs(villagedoorinfo.posY - par2) > 1); return villagedoorinfo; } private void addDoorToNewListIfAppropriate(int par1, int par2, int par3) { int l = ((BlockDoor)Block.doorWood).getDoorOrientation(this.worldObj, par1, par2, par3); int i1; int j1; if (l != 0 && l != 2) { i1 = 0; for (j1 = -5; j1 < 0; ++j1) { if (this.worldObj.canBlockSeeTheSky(par1, par2, par3 + j1)) { --i1; } } for (j1 = 1; j1 <= 5; ++j1) { if (this.worldObj.canBlockSeeTheSky(par1, par2, par3 + j1)) { ++i1; } } if (i1 != 0) { this.newDoors.add(new VillageDoorInfo(par1, par2, par3, 0, i1 > 0 ? -2 : 2, this.tickCounter)); } } else { i1 = 0; for (j1 = -5; j1 < 0; ++j1) { if (this.worldObj.canBlockSeeTheSky(par1 + j1, par2, par3)) { --i1; } } for (j1 = 1; j1 <= 5; ++j1) { if (this.worldObj.canBlockSeeTheSky(par1 + j1, par2, par3)) { ++i1; } } if (i1 != 0) { this.newDoors.add(new VillageDoorInfo(par1, par2, par3, i1 > 0 ? -2 : 2, 0, this.tickCounter)); } } } private boolean isVillagerPositionPresent(int par1, int par2, int par3) { Iterator iterator = this.villagerPositionsList.iterator(); ChunkCoordinates chunkcoordinates; do { if (!iterator.hasNext()) { return false; } chunkcoordinates = (ChunkCoordinates)iterator.next(); } while (chunkcoordinates.posX != par1 || chunkcoordinates.posY != par2 || chunkcoordinates.posZ != par3); return true; } private boolean isWoodenDoorAt(int par1, int par2, int par3) { int l = this.worldObj.getBlockId(par1, par2, par3); return l == Block.doorWood.blockID; } /** * reads in data from the NBTTagCompound into this MapDataBase */ public void readFromNBT(NBTTagCompound par1NBTTagCompound) { this.tickCounter = par1NBTTagCompound.getInteger("Tick"); NBTTagList nbttaglist = par1NBTTagCompound.getTagList("Villages"); for (int i = 0; i < nbttaglist.tagCount(); ++i) { NBTTagCompound nbttagcompound1 = (NBTTagCompound)nbttaglist.tagAt(i); Village village = new Village(); village.readVillageDataFromNBT(nbttagcompound1); this.villageList.add(village); } } /** * write data to NBTTagCompound from this MapDataBase, similar to Entities and TileEntities */ public void writeToNBT(NBTTagCompound par1NBTTagCompound) { par1NBTTagCompound.setInteger("Tick", this.tickCounter); NBTTagList nbttaglist = new NBTTagList("Villages"); Iterator iterator = this.villageList.iterator(); while (iterator.hasNext()) { Village village = (Village)iterator.next(); NBTTagCompound nbttagcompound1 = new NBTTagCompound("Village"); village.writeVillageDataToNBT(nbttagcompound1); nbttaglist.appendTag(nbttagcompound1); } par1NBTTagCompound.setTag("Villages", nbttaglist); } }