001 package net.minecraft.src; 002 003 import java.util.List; 004 import java.util.Random; 005 006 import net.minecraftforge.common.*; 007 import net.minecraftforge.event.Event.*; 008 import net.minecraftforge.event.terraingen.*; 009 010 public abstract class ComponentVillage extends StructureComponent 011 { 012 /** The number of villagers that have been spawned in this component. */ 013 private int villagersSpawned; 014 015 /** The starting piece of the village. */ 016 protected ComponentVillageStartPiece startPiece; 017 018 protected ComponentVillage(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2) 019 { 020 super(par2); 021 this.startPiece = par1ComponentVillageStartPiece; 022 } 023 024 /** 025 * Gets the next village component, with the bounding box shifted -1 in the X and Z direction. 026 */ 027 protected StructureComponent getNextComponentNN(ComponentVillageStartPiece par1ComponentVillageStartPiece, List par2List, Random par3Random, int par4, int par5) 028 { 029 switch (this.coordBaseMode) 030 { 031 case 0: 032 return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.minX - 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5, 1, this.getComponentType()); 033 case 1: 034 return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.minZ - 1, 2, this.getComponentType()); 035 case 2: 036 return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.minX - 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5, 1, this.getComponentType()); 037 case 3: 038 return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.minZ - 1, 2, this.getComponentType()); 039 default: 040 return null; 041 } 042 } 043 044 /** 045 * Gets the next village component, with the bounding box shifted +1 in the X and Z direction. 046 */ 047 protected StructureComponent getNextComponentPP(ComponentVillageStartPiece par1ComponentVillageStartPiece, List par2List, Random par3Random, int par4, int par5) 048 { 049 switch (this.coordBaseMode) 050 { 051 case 0: 052 return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.maxX + 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5, 3, this.getComponentType()); 053 case 1: 054 return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.maxZ + 1, 0, this.getComponentType()); 055 case 2: 056 return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.maxX + 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5, 3, this.getComponentType()); 057 case 3: 058 return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.maxZ + 1, 0, this.getComponentType()); 059 default: 060 return null; 061 } 062 } 063 064 /** 065 * Discover the y coordinate that will serve as the ground level of the supplied BoundingBox. (A median of all the 066 * levels in the BB's horizontal rectangle). 067 */ 068 protected int getAverageGroundLevel(World par1World, StructureBoundingBox par2StructureBoundingBox) 069 { 070 int var3 = 0; 071 int var4 = 0; 072 073 for (int var5 = this.boundingBox.minZ; var5 <= this.boundingBox.maxZ; ++var5) 074 { 075 for (int var6 = this.boundingBox.minX; var6 <= this.boundingBox.maxX; ++var6) 076 { 077 if (par2StructureBoundingBox.isVecInside(var6, 64, var5)) 078 { 079 var3 += Math.max(par1World.getTopSolidOrLiquidBlock(var6, var5), par1World.provider.getAverageGroundLevel()); 080 ++var4; 081 } 082 } 083 } 084 085 if (var4 == 0) 086 { 087 return -1; 088 } 089 else 090 { 091 return var3 / var4; 092 } 093 } 094 095 protected static boolean canVillageGoDeeper(StructureBoundingBox par0StructureBoundingBox) 096 { 097 return par0StructureBoundingBox != null && par0StructureBoundingBox.minY > 10; 098 } 099 100 /** 101 * Spawns a number of villagers in this component. Parameters: world, component bounding box, x offset, y offset, z 102 * offset, number of villagers 103 */ 104 protected void spawnVillagers(World par1World, StructureBoundingBox par2StructureBoundingBox, int par3, int par4, int par5, int par6) 105 { 106 if (this.villagersSpawned < par6) 107 { 108 for (int var7 = this.villagersSpawned; var7 < par6; ++var7) 109 { 110 int var8 = this.getXWithOffset(par3 + var7, par5); 111 int var9 = this.getYWithOffset(par4); 112 int var10 = this.getZWithOffset(par3 + var7, par5); 113 114 if (!par2StructureBoundingBox.isVecInside(var8, var9, var10)) 115 { 116 break; 117 } 118 119 ++this.villagersSpawned; 120 EntityVillager var11 = new EntityVillager(par1World, this.getVillagerType(var7)); 121 var11.setLocationAndAngles((double)var8 + 0.5D, (double)var9, (double)var10 + 0.5D, 0.0F, 0.0F); 122 par1World.spawnEntityInWorld(var11); 123 } 124 } 125 } 126 127 /** 128 * Returns the villager type to spawn in this component, based on the number of villagers already spawned. 129 */ 130 protected int getVillagerType(int par1) 131 { 132 return 0; 133 } 134 135 /** 136 * Gets the replacement block for the current biome 137 */ 138 protected int getBiomeSpecificBlock(int par1, int par2) 139 { 140 BiomeEvent.GetVillageBlockID event = new BiomeEvent.GetVillageBlockID(startPiece.biome, par1, par2); 141 MinecraftForge.TERRAIN_GEN_BUS.post(event); 142 if (event.getResult() == Result.DENY) return event.replacement; 143 144 if (this.startPiece.inDesert) 145 { 146 if (par1 == Block.wood.blockID) 147 { 148 return Block.sandStone.blockID; 149 } 150 151 if (par1 == Block.cobblestone.blockID) 152 { 153 return Block.sandStone.blockID; 154 } 155 156 if (par1 == Block.planks.blockID) 157 { 158 return Block.sandStone.blockID; 159 } 160 161 if (par1 == Block.stairCompactPlanks.blockID) 162 { 163 return Block.stairsSandStone.blockID; 164 } 165 166 if (par1 == Block.stairCompactCobblestone.blockID) 167 { 168 return Block.stairsSandStone.blockID; 169 } 170 171 if (par1 == Block.gravel.blockID) 172 { 173 return Block.sandStone.blockID; 174 } 175 } 176 177 return par1; 178 } 179 180 /** 181 * Gets the replacement block metadata for the current biome 182 */ 183 protected int getBiomeSpecificBlockMetadata(int par1, int par2) 184 { 185 BiomeEvent.GetVillageBlockMeta event = new BiomeEvent.GetVillageBlockMeta(startPiece.biome, par1, par2); 186 MinecraftForge.TERRAIN_GEN_BUS.post(event); 187 if (event.getResult() == Result.DENY) return event.replacement; 188 189 if (this.startPiece.inDesert) 190 { 191 if (par1 == Block.wood.blockID) 192 { 193 return 0; 194 } 195 196 if (par1 == Block.cobblestone.blockID) 197 { 198 return 0; 199 } 200 201 if (par1 == Block.planks.blockID) 202 { 203 return 2; 204 } 205 } 206 207 return par2; 208 } 209 210 /** 211 * current Position depends on currently set Coordinates mode, is computed here 212 */ 213 protected void placeBlockAtCurrentPosition(World par1World, int par2, int par3, int par4, int par5, int par6, StructureBoundingBox par7StructureBoundingBox) 214 { 215 int var8 = this.getBiomeSpecificBlock(par2, par3); 216 int var9 = this.getBiomeSpecificBlockMetadata(par2, par3); 217 super.placeBlockAtCurrentPosition(par1World, var8, var9, par4, par5, par6, par7StructureBoundingBox); 218 } 219 220 /** 221 * arguments: (World worldObj, StructureBoundingBox structBB, int minX, int minY, int minZ, int maxX, int maxY, int 222 * maxZ, int placeBlockId, int replaceBlockId, boolean alwaysreplace) 223 */ 224 protected void fillWithBlocks(World par1World, StructureBoundingBox par2StructureBoundingBox, int par3, int par4, int par5, int par6, int par7, int par8, int par9, int par10, boolean par11) 225 { 226 int var12 = this.getBiomeSpecificBlock(par9, 0); 227 int var13 = this.getBiomeSpecificBlockMetadata(par9, 0); 228 int var14 = this.getBiomeSpecificBlock(par10, 0); 229 int var15 = this.getBiomeSpecificBlockMetadata(par10, 0); 230 super.fillWithMetadataBlocks(par1World, par2StructureBoundingBox, par3, par4, par5, par6, par7, par8, var12, var13, var14, var15, par11); 231 } 232 233 /** 234 * Overwrites air and liquids from selected position downwards, stops at hitting anything else. 235 */ 236 protected void fillCurrentPositionBlocksDownwards(World par1World, int par2, int par3, int par4, int par5, int par6, StructureBoundingBox par7StructureBoundingBox) 237 { 238 int var8 = this.getBiomeSpecificBlock(par2, par3); 239 int var9 = this.getBiomeSpecificBlockMetadata(par2, par3); 240 super.fillCurrentPositionBlocksDownwards(par1World, var8, var9, par4, par5, par6, par7StructureBoundingBox); 241 } 242 }