package game.village; import java.util.Iterator; import java.util.List; import game.collect.Lists; import game.block.Block; import game.block.BlockDoor; import game.material.Material; import game.nbt.NBTTagCompound; import game.nbt.NBTTagList; import game.world.BlockPos; import game.world.Facing; import game.world.WorldServer; public class VillageCollection { private final List villagerPositionsList = Lists.newArrayList(); private final List newDoors = Lists.newArrayList(); private final List villageList = Lists.newArrayList(); private int tickCounter; private boolean dirty; public VillageCollection(NBTTagCompound nbt) { if(nbt != null) { this.tickCounter = nbt.getInteger("Tick"); NBTTagList nbttaglist = nbt.getTagList("Villages", 10); for (int i = 0; i < nbttaglist.tagCount(); ++i) { NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i); Village village = new Village(); village.readVillageDataFromNBT(nbttagcompound); this.villageList.add(village); } } } public void addToVillagerPositionList(BlockPos pos) { if (this.villagerPositionsList.size() <= 64) { if (!this.positionInList(pos)) { this.villagerPositionsList.add(pos); } } } public void tick(WorldServer world) { ++this.tickCounter; for (Village village : this.villageList) { village.tick(world, this.tickCounter); } this.removeAnnihilatedVillages(); this.dropOldestVillagerPosition(world); this.addNewDoorsToVillageOrCreateVillage(); if (this.tickCounter % 400 == 0) { this.dirty = true; } } private void removeAnnihilatedVillages() { Iterator iterator = this.villageList.iterator(); while (iterator.hasNext()) { Village village = (Village)iterator.next(); if (village.isAnnihilated()) { iterator.remove(); this.dirty = true; } } } public List getVillageList() { return this.villageList; } public Village getNearestVillage(BlockPos doorBlock, int radius) { Village village = null; double d0 = 3.4028234663852886E38D; for (Village village1 : this.villageList) { double d1 = village1.getCenter().distanceSq(doorBlock); if (d1 < d0) { float f = (float)(radius + village1.getRadius()); if (d1 <= (double)(f * f)) { village = village1; d0 = d1; } } } return village; } private void dropOldestVillagerPosition(WorldServer world) { if (!this.villagerPositionsList.isEmpty()) { this.addDoorsAround(world, this.villagerPositionsList.remove(0)); } } private void addNewDoorsToVillageOrCreateVillage() { for (int i = 0; i < this.newDoors.size(); ++i) { VillageDoorInfo villagedoorinfo = (VillageDoorInfo)this.newDoors.get(i); Village village = this.getNearestVillage(villagedoorinfo.getDoorBlockPos(), 32); if (village == null) { village = new Village(); this.villageList.add(village); this.dirty = true; } village.addDoor(villagedoorinfo); } this.newDoors.clear(); } private void addDoorsAround(WorldServer world, BlockPos central) { int i = 16; int j = 4; int k = 16; for (int l = -i; l < i; ++l) { for (int i1 = -j; i1 < j; ++i1) { for (int j1 = -k; j1 < k; ++j1) { BlockPos blockpos = central.add(l, i1, j1); if (this.isWoodDoor(world, blockpos)) { VillageDoorInfo villagedoorinfo = this.checkDoorExistence(blockpos); if (villagedoorinfo == null) { this.addToNewDoorsList(world, blockpos); } else { villagedoorinfo.func_179849_a(this.tickCounter); } } } } } } private VillageDoorInfo checkDoorExistence(BlockPos doorBlock) { for (VillageDoorInfo villagedoorinfo : this.newDoors) { if (villagedoorinfo.getDoorBlockPos().getX() == doorBlock.getX() && villagedoorinfo.getDoorBlockPos().getZ() == doorBlock.getZ() && Math.abs(villagedoorinfo.getDoorBlockPos().getY() - doorBlock.getY()) <= 1) { return villagedoorinfo; } } for (Village village : this.villageList) { VillageDoorInfo villagedoorinfo1 = village.getExistedDoor(doorBlock); if (villagedoorinfo1 != null) { return villagedoorinfo1; } } return null; } private void addToNewDoorsList(WorldServer world, BlockPos doorBlock) { Facing enumfacing = BlockDoor.getFacing(world, doorBlock); Facing enumfacing1 = enumfacing.getOpposite(); int i = this.countBlocksCanSeeSky(world, doorBlock, enumfacing, 5); int j = this.countBlocksCanSeeSky(world, doorBlock, enumfacing1, i + 1); if (i != j) { this.newDoors.add(new VillageDoorInfo(doorBlock, i < j ? enumfacing : enumfacing1, this.tickCounter)); } } private int countBlocksCanSeeSky(WorldServer world, BlockPos centerPos, Facing direction, int limitation) { int i = 0; for (int j = 1; j <= 5; ++j) { if (world.canSeeSky(centerPos.offset(direction, j))) { ++i; if (i >= limitation) { return i; } } } return i; } private boolean positionInList(BlockPos pos) { for (BlockPos blockpos : this.villagerPositionsList) { if (blockpos.equals(pos)) { return true; } } return false; } private boolean isWoodDoor(WorldServer world, BlockPos doorPos) { Block block = world.getState(doorPos).getBlock(); return block instanceof BlockDoor ? block.getMaterial() == Material.wood : false; } public NBTTagCompound writeToNBT() { NBTTagCompound nbt = new NBTTagCompound(); nbt.setInteger("Tick", this.tickCounter); NBTTagList nbttaglist = new NBTTagList(); for (Village village : this.villageList) { NBTTagCompound nbttagcompound = new NBTTagCompound(); village.writeVillageDataToNBT(nbttagcompound); nbttaglist.appendTag(nbttagcompound); } nbt.setTag("Villages", nbttaglist); this.dirty = false; return nbt; } public boolean isDirty() { return this.dirty; } }