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 }