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    }