    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}