001package net.minecraft.world.gen; 002 003import java.util.ArrayList; 004import java.util.Iterator; 005import java.util.List; 006import java.util.Map; 007import java.util.Random; 008import net.minecraft.block.Block; 009import net.minecraft.entity.EnumCreatureType; 010import net.minecraft.util.IProgressUpdate; 011import net.minecraft.world.ChunkPosition; 012import net.minecraft.world.World; 013import net.minecraft.world.biome.BiomeGenBase; 014import net.minecraft.world.chunk.Chunk; 015import net.minecraft.world.chunk.IChunkProvider; 016import net.minecraft.world.chunk.storage.ExtendedBlockStorage; 017import net.minecraft.world.gen.feature.MapGenScatteredFeature; 018import net.minecraft.world.gen.feature.WorldGenDungeons; 019import net.minecraft.world.gen.feature.WorldGenLakes; 020import net.minecraft.world.gen.structure.MapGenMineshaft; 021import net.minecraft.world.gen.structure.MapGenStronghold; 022import net.minecraft.world.gen.structure.MapGenStructure; 023import net.minecraft.world.gen.structure.MapGenVillage; 024 025public 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 structureGenerators = new ArrayList(); 033 private final boolean field_82697_g; 034 private final boolean field_82702_h; 035 private WorldGenLakes waterLakeGenerator; 036 private WorldGenLakes lavaLakeGenerator; 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 map = this.field_82699_e.getWorldFeatures(); 047 048 if (map.containsKey("village")) 049 { 050 Map map1 = (Map)map.get("village"); 051 052 if (!map1.containsKey("size")) 053 { 054 map1.put("size", "1"); 055 } 056 057 this.structureGenerators.add(new MapGenVillage(map1)); 058 } 059 060 if (map.containsKey("biome_1")) 061 { 062 this.structureGenerators.add(new MapGenScatteredFeature((Map)map.get("biome_1"))); 063 } 064 065 if (map.containsKey("mineshaft")) 066 { 067 this.structureGenerators.add(new MapGenMineshaft((Map)map.get("mineshaft"))); 068 } 069 070 if (map.containsKey("stronghold")) 071 { 072 this.structureGenerators.add(new MapGenStronghold((Map)map.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.waterLakeGenerator = new WorldGenLakes(Block.waterStill.blockID); 081 } 082 083 if (this.field_82699_e.getWorldFeatures().containsKey("lava_lake")) 084 { 085 this.lavaLakeGenerator = new WorldGenLakes(Block.lavaStill.blockID); 086 } 087 088 this.field_82702_h = this.field_82699_e.getWorldFeatures().containsKey("dungeon"); 089 Iterator iterator = this.field_82699_e.getFlatLayers().iterator(); 090 091 while (iterator.hasNext()) 092 { 093 FlatLayerInfo flatlayerinfo = (FlatLayerInfo)iterator.next(); 094 095 for (int j = flatlayerinfo.getMinY(); j < flatlayerinfo.getMinY() + flatlayerinfo.getLayerCount(); ++j) 096 { 097 this.field_82700_c[j] = (byte)(flatlayerinfo.getFillBlock() & 255); 098 this.field_82698_d[j] = (byte)flatlayerinfo.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 chunk = new Chunk(this.worldObj, par1, par2); 118 119 for (int k = 0; k < this.field_82700_c.length; ++k) 120 { 121 int l = k >> 4; 122 ExtendedBlockStorage extendedblockstorage = chunk.getBlockStorageArray()[l]; 123 124 if (extendedblockstorage == null) 125 { 126 extendedblockstorage = new ExtendedBlockStorage(k, !this.worldObj.provider.hasNoSky); 127 chunk.getBlockStorageArray()[l] = extendedblockstorage; 128 } 129 130 for (int i1 = 0; i1 < 16; ++i1) 131 { 132 for (int j1 = 0; j1 < 16; ++j1) 133 { 134 extendedblockstorage.setExtBlockID(i1, k & 15, j1, this.field_82700_c[k] & 255); 135 extendedblockstorage.setExtBlockMetadata(i1, k & 15, j1, this.field_82698_d[k]); 136 } 137 } 138 } 139 140 chunk.generateSkylightMap(); 141 BiomeGenBase[] abiomegenbase = this.worldObj.getWorldChunkManager().loadBlockGeneratorData((BiomeGenBase[])null, par1 * 16, par2 * 16, 16, 16); 142 byte[] abyte = chunk.getBiomeArray(); 143 144 for (int k1 = 0; k1 < abyte.length; ++k1) 145 { 146 abyte[k1] = (byte)abiomegenbase[k1].biomeID; 147 } 148 149 Iterator iterator = this.structureGenerators.iterator(); 150 151 while (iterator.hasNext()) 152 { 153 MapGenStructure mapgenstructure = (MapGenStructure)iterator.next(); 154 mapgenstructure.generate(this, this.worldObj, par1, par2, (byte[])null); 155 } 156 157 chunk.generateSkylightMap(); 158 return chunk; 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 k = par2 * 16; 175 int l = par3 * 16; 176 BiomeGenBase biomegenbase = this.worldObj.getBiomeGenForCoords(k + 16, l + 16); 177 boolean flag = false; 178 this.random.setSeed(this.worldObj.getSeed()); 179 long i1 = this.random.nextLong() / 2L * 2L + 1L; 180 long j1 = this.random.nextLong() / 2L * 2L + 1L; 181 this.random.setSeed((long)par2 * i1 + (long)par3 * j1 ^ this.worldObj.getSeed()); 182 Iterator iterator = this.structureGenerators.iterator(); 183 184 while (iterator.hasNext()) 185 { 186 MapGenStructure mapgenstructure = (MapGenStructure)iterator.next(); 187 boolean flag1 = mapgenstructure.generateStructuresInChunk(this.worldObj, this.random, par2, par3); 188 189 if (mapgenstructure instanceof MapGenVillage) 190 { 191 flag |= flag1; 192 } 193 } 194 195 int k1; 196 int l1; 197 int i2; 198 199 if (this.waterLakeGenerator != null && !flag && this.random.nextInt(4) == 0) 200 { 201 l1 = k + this.random.nextInt(16) + 8; 202 k1 = this.random.nextInt(128); 203 i2 = l + this.random.nextInt(16) + 8; 204 this.waterLakeGenerator.generate(this.worldObj, this.random, l1, k1, i2); 205 } 206 207 if (this.lavaLakeGenerator != null && !flag && this.random.nextInt(8) == 0) 208 { 209 l1 = k + this.random.nextInt(16) + 8; 210 k1 = this.random.nextInt(this.random.nextInt(120) + 8); 211 i2 = l + this.random.nextInt(16) + 8; 212 213 if (k1 < 63 || this.random.nextInt(10) == 0) 214 { 215 this.lavaLakeGenerator.generate(this.worldObj, this.random, l1, k1, i2); 216 } 217 } 218 219 if (this.field_82702_h) 220 { 221 for (l1 = 0; l1 < 8; ++l1) 222 { 223 k1 = k + this.random.nextInt(16) + 8; 224 i2 = this.random.nextInt(128); 225 int j2 = l + this.random.nextInt(16) + 8; 226 (new WorldGenDungeons()).generate(this.worldObj, this.random, k1, i2, j2); 227 } 228 } 229 230 if (this.field_82697_g) 231 { 232 biomegenbase.decorate(this.worldObj, this.random, k, l); 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 chunks that are marked to be unloaded. This is not guaranteed to unload every such chunk. 247 */ 248 public boolean unloadQueuedChunks() 249 { 250 return false; 251 } 252 253 /** 254 * Returns if the IChunkProvider supports saving. 255 */ 256 public boolean canSave() 257 { 258 return true; 259 } 260 261 /** 262 * Converts the instance data to a readable string. 263 */ 264 public String makeString() 265 { 266 return "FlatLevelSource"; 267 } 268 269 /** 270 * Returns a list of creatures of the specified type that can spawn at the given location. 271 */ 272 public List getPossibleCreatures(EnumCreatureType par1EnumCreatureType, int par2, int par3, int par4) 273 { 274 BiomeGenBase biomegenbase = this.worldObj.getBiomeGenForCoords(par2, par4); 275 return biomegenbase == null ? null : biomegenbase.getSpawnableList(par1EnumCreatureType); 276 } 277 278 /** 279 * Returns the location of the closest structure of the specified type. If not found returns null. 280 */ 281 public ChunkPosition findClosestStructure(World par1World, String par2Str, int par3, int par4, int par5) 282 { 283 if ("Stronghold".equals(par2Str)) 284 { 285 Iterator iterator = this.structureGenerators.iterator(); 286 287 while (iterator.hasNext()) 288 { 289 MapGenStructure mapgenstructure = (MapGenStructure)iterator.next(); 290 291 if (mapgenstructure instanceof MapGenStronghold) 292 { 293 return mapgenstructure.getNearestInstance(par1World, par3, par4, par5); 294 } 295 } 296 } 297 298 return null; 299 } 300 301 public int getLoadedChunkCount() 302 { 303 return 0; 304 } 305 306 public void recreateStructures(int par1, int par2) 307 { 308 Iterator iterator = this.structureGenerators.iterator(); 309 310 while (iterator.hasNext()) 311 { 312 MapGenStructure mapgenstructure = (MapGenStructure)iterator.next(); 313 mapgenstructure.generate(this, this.worldObj, par1, par2, (byte[])null); 314 } 315 } 316}