001 package net.minecraft.world.gen; 002 003 import java.util.ArrayList; 004 import java.util.Iterator; 005 import java.util.List; 006 import java.util.Map; 007 import java.util.Random; 008 import net.minecraft.block.Block; 009 import net.minecraft.entity.EnumCreatureType; 010 import net.minecraft.util.IProgressUpdate; 011 import net.minecraft.world.ChunkPosition; 012 import net.minecraft.world.World; 013 import net.minecraft.world.biome.BiomeGenBase; 014 import net.minecraft.world.chunk.Chunk; 015 import net.minecraft.world.chunk.IChunkProvider; 016 import net.minecraft.world.chunk.storage.ExtendedBlockStorage; 017 import net.minecraft.world.gen.feature.MapGenScatteredFeature; 018 import net.minecraft.world.gen.feature.WorldGenDungeons; 019 import net.minecraft.world.gen.feature.WorldGenLakes; 020 import net.minecraft.world.gen.structure.MapGenMineshaft; 021 import net.minecraft.world.gen.structure.MapGenStronghold; 022 import net.minecraft.world.gen.structure.MapGenStructure; 023 import net.minecraft.world.gen.structure.MapGenVillage; 024 025 public class ChunkProviderFlat implements IChunkProvider 026 { 027 private World worldObj; 028 private Random random; 029 private final byte[] field_82700_c = new byte[256]; 030 private final byte[] field_82698_d = new byte[256]; 031 private final FlatGeneratorInfo field_82699_e; 032 private final List field_82696_f = new ArrayList(); 033 private final boolean field_82697_g; 034 private final boolean field_82702_h; 035 private WorldGenLakes field_82703_i; 036 private WorldGenLakes field_82701_j; 037 038 public ChunkProviderFlat(World par1World, long par2, boolean par4, String par5Str) 039 { 040 this.worldObj = par1World; 041 this.random = new Random(par2); 042 this.field_82699_e = FlatGeneratorInfo.createFlatGeneratorFromString(par5Str); 043 044 if (par4) 045 { 046 Map var6 = this.field_82699_e.getWorldFeatures(); 047 048 if (var6.containsKey("village")) 049 { 050 Map var7 = (Map)var6.get("village"); 051 052 if (!var7.containsKey("size")) 053 { 054 var7.put("size", "1"); 055 } 056 057 this.field_82696_f.add(new MapGenVillage(var7)); 058 } 059 060 if (var6.containsKey("biome_1")) 061 { 062 this.field_82696_f.add(new MapGenScatteredFeature((Map)var6.get("biome_1"))); 063 } 064 065 if (var6.containsKey("mineshaft")) 066 { 067 this.field_82696_f.add(new MapGenMineshaft((Map)var6.get("mineshaft"))); 068 } 069 070 if (var6.containsKey("stronghold")) 071 { 072 this.field_82696_f.add(new MapGenStronghold((Map)var6.get("stronghold"))); 073 } 074 } 075 076 this.field_82697_g = this.field_82699_e.getWorldFeatures().containsKey("decoration"); 077 078 if (this.field_82699_e.getWorldFeatures().containsKey("lake")) 079 { 080 this.field_82703_i = new WorldGenLakes(Block.waterStill.blockID); 081 } 082 083 if (this.field_82699_e.getWorldFeatures().containsKey("lava_lake")) 084 { 085 this.field_82701_j = new WorldGenLakes(Block.lavaStill.blockID); 086 } 087 088 this.field_82702_h = this.field_82699_e.getWorldFeatures().containsKey("dungeon"); 089 Iterator var9 = this.field_82699_e.getFlatLayers().iterator(); 090 091 while (var9.hasNext()) 092 { 093 FlatLayerInfo var10 = (FlatLayerInfo)var9.next(); 094 095 for (int var8 = var10.getMinY(); var8 < var10.getMinY() + var10.getLayerCount(); ++var8) 096 { 097 this.field_82700_c[var8] = (byte)(var10.getFillBlock() & 255); 098 this.field_82698_d[var8] = (byte)var10.getFillBlockMeta(); 099 } 100 } 101 } 102 103 /** 104 * loads or generates the chunk at the chunk location specified 105 */ 106 public Chunk loadChunk(int par1, int par2) 107 { 108 return this.provideChunk(par1, par2); 109 } 110 111 /** 112 * Will return back a chunk, if it doesn't exist and its not a MP client it will generates all the blocks for the 113 * specified chunk from the map seed and chunk seed 114 */ 115 public Chunk provideChunk(int par1, int par2) 116 { 117 Chunk var3 = new Chunk(this.worldObj, par1, par2); 118 119 for (int var4 = 0; var4 < this.field_82700_c.length; ++var4) 120 { 121 int var5 = var4 >> 4; 122 ExtendedBlockStorage var6 = var3.getBlockStorageArray()[var5]; 123 124 if (var6 == null) 125 { 126 var6 = new ExtendedBlockStorage(var4, !this.worldObj.provider.hasNoSky); 127 var3.getBlockStorageArray()[var5] = var6; 128 } 129 130 for (int var7 = 0; var7 < 16; ++var7) 131 { 132 for (int var8 = 0; var8 < 16; ++var8) 133 { 134 var6.setExtBlockID(var7, var4 & 15, var8, this.field_82700_c[var4] & 255); 135 var6.setExtBlockMetadata(var7, var4 & 15, var8, this.field_82698_d[var4]); 136 } 137 } 138 } 139 140 var3.generateSkylightMap(); 141 BiomeGenBase[] var9 = this.worldObj.getWorldChunkManager().loadBlockGeneratorData((BiomeGenBase[])null, par1 * 16, par2 * 16, 16, 16); 142 byte[] var10 = var3.getBiomeArray(); 143 144 for (int var11 = 0; var11 < var10.length; ++var11) 145 { 146 var10[var11] = (byte)var9[var11].biomeID; 147 } 148 149 Iterator var12 = this.field_82696_f.iterator(); 150 151 while (var12.hasNext()) 152 { 153 MapGenStructure var13 = (MapGenStructure)var12.next(); 154 var13.generate(this, this.worldObj, par1, par2, (byte[])null); 155 } 156 157 var3.generateSkylightMap(); 158 return var3; 159 } 160 161 /** 162 * Checks to see if a chunk exists at x, y 163 */ 164 public boolean chunkExists(int par1, int par2) 165 { 166 return true; 167 } 168 169 /** 170 * Populates chunk with ores etc etc 171 */ 172 public void populate(IChunkProvider par1IChunkProvider, int par2, int par3) 173 { 174 int var4 = par2 * 16; 175 int var5 = par3 * 16; 176 BiomeGenBase var6 = this.worldObj.getBiomeGenForCoords(var4 + 16, var5 + 16); 177 boolean var7 = false; 178 this.random.setSeed(this.worldObj.getSeed()); 179 long var8 = this.random.nextLong() / 2L * 2L + 1L; 180 long var10 = this.random.nextLong() / 2L * 2L + 1L; 181 this.random.setSeed((long)par2 * var8 + (long)par3 * var10 ^ this.worldObj.getSeed()); 182 Iterator var12 = this.field_82696_f.iterator(); 183 184 while (var12.hasNext()) 185 { 186 MapGenStructure var13 = (MapGenStructure)var12.next(); 187 boolean var14 = var13.generateStructuresInChunk(this.worldObj, this.random, par2, par3); 188 189 if (var13 instanceof MapGenVillage) 190 { 191 var7 |= var14; 192 } 193 } 194 195 int var17; 196 int var16; 197 int var18; 198 199 if (this.field_82703_i != null && !var7 && this.random.nextInt(4) == 0) 200 { 201 var16 = var4 + this.random.nextInt(16) + 8; 202 var17 = this.random.nextInt(128); 203 var18 = var5 + this.random.nextInt(16) + 8; 204 this.field_82703_i.generate(this.worldObj, this.random, var16, var17, var18); 205 } 206 207 if (this.field_82701_j != null && !var7 && this.random.nextInt(8) == 0) 208 { 209 var16 = var4 + this.random.nextInt(16) + 8; 210 var17 = this.random.nextInt(this.random.nextInt(120) + 8); 211 var18 = var5 + this.random.nextInt(16) + 8; 212 213 if (var17 < 63 || this.random.nextInt(10) == 0) 214 { 215 this.field_82701_j.generate(this.worldObj, this.random, var16, var17, var18); 216 } 217 } 218 219 if (this.field_82702_h) 220 { 221 for (var16 = 0; var16 < 8; ++var16) 222 { 223 var17 = var4 + this.random.nextInt(16) + 8; 224 var18 = this.random.nextInt(128); 225 int var15 = var5 + this.random.nextInt(16) + 8; 226 (new WorldGenDungeons()).generate(this.worldObj, this.random, var17, var18, var15); 227 } 228 } 229 230 if (this.field_82697_g) 231 { 232 var6.decorate(this.worldObj, this.random, var4, var5); 233 } 234 } 235 236 /** 237 * Two modes of operation: if passed true, save all Chunks in one go. If passed false, save up to two chunks. 238 * Return true if all chunks have been saved. 239 */ 240 public boolean saveChunks(boolean par1, IProgressUpdate par2IProgressUpdate) 241 { 242 return true; 243 } 244 245 /** 246 * Unloads the 100 oldest chunks from memory, due to a bug with chunkSet.add() never being called it thinks the list 247 * is always empty and will not remove any chunks. 248 */ 249 public boolean unload100OldestChunks() 250 { 251 return false; 252 } 253 254 /** 255 * Returns if the IChunkProvider supports saving. 256 */ 257 public boolean canSave() 258 { 259 return true; 260 } 261 262 /** 263 * Converts the instance data to a readable string. 264 */ 265 public String makeString() 266 { 267 return "FlatLevelSource"; 268 } 269 270 /** 271 * Returns a list of creatures of the specified type that can spawn at the given location. 272 */ 273 public List getPossibleCreatures(EnumCreatureType par1EnumCreatureType, int par2, int par3, int par4) 274 { 275 BiomeGenBase var5 = this.worldObj.getBiomeGenForCoords(par2, par4); 276 return var5 == null ? null : var5.getSpawnableList(par1EnumCreatureType); 277 } 278 279 /** 280 * Returns the location of the closest structure of the specified type. If not found returns null. 281 */ 282 public ChunkPosition findClosestStructure(World par1World, String par2Str, int par3, int par4, int par5) 283 { 284 if ("Stronghold".equals(par2Str)) 285 { 286 Iterator var6 = this.field_82696_f.iterator(); 287 288 while (var6.hasNext()) 289 { 290 MapGenStructure var7 = (MapGenStructure)var6.next(); 291 292 if (var7 instanceof MapGenStronghold) 293 { 294 return var7.getNearestInstance(par1World, par3, par4, par5); 295 } 296 } 297 } 298 299 return null; 300 } 301 302 public int getLoadedChunkCount() 303 { 304 return 0; 305 } 306 307 public void recreateStructures(int par1, int par2) 308 { 309 Iterator var3 = this.field_82696_f.iterator(); 310 311 while (var3.hasNext()) 312 { 313 MapGenStructure var4 = (MapGenStructure)var3.next(); 314 var4.generate(this, this.worldObj, par1, par2, (byte[])null); 315 } 316 } 317 }