001package net.minecraft.world.biome;
002
003import cpw.mods.fml.relauncher.Side;
004import cpw.mods.fml.relauncher.SideOnly;
005import java.util.ArrayList;
006import java.util.Arrays;
007import java.util.List;
008import java.util.Random;
009import net.minecraft.world.ChunkPosition;
010import net.minecraft.world.World;
011import net.minecraft.world.WorldType;
012import net.minecraft.world.gen.layer.GenLayer;
013import net.minecraft.world.gen.layer.IntCache;
014
015import net.minecraftforge.common.*;
016import net.minecraftforge.event.terraingen.*;
017import static net.minecraft.world.biome.BiomeGenBase.*;
018
019public class WorldChunkManager
020{
021    public static ArrayList<BiomeGenBase> allowedBiomes = new ArrayList<BiomeGenBase>(Arrays.asList(forest, plains, taiga, taigaHills, forestHills, jungle. jungleHills));
022    private GenLayer genBiomes;
023
024    /** A GenLayer containing the indices into BiomeGenBase.biomeList[] */
025    private GenLayer biomeIndexLayer;
026
027    /** The BiomeCache object for this world. */
028    private BiomeCache biomeCache;
029
030    /** A list of biomes that the player can spawn in. */
031    private List biomesToSpawnIn;
032
033    protected WorldChunkManager()
034    {
035        this.biomeCache = new BiomeCache(this);
036        this.biomesToSpawnIn = new ArrayList();
037        this.biomesToSpawnIn.addAll(allowedBiomes);
038    }
039
040    public WorldChunkManager(long par1, WorldType par3WorldType)
041    {
042        this();
043        GenLayer[] agenlayer = GenLayer.initializeAllBiomeGenerators(par1, par3WorldType);
044        agenlayer = getModdedBiomeGenerators(par3WorldType, par1, agenlayer);
045        this.genBiomes = agenlayer[0];
046        this.biomeIndexLayer = agenlayer[1];
047    }
048
049    public WorldChunkManager(World par1World)
050    {
051        this(par1World.getSeed(), par1World.getWorldInfo().getTerrainType());
052    }
053
054    /**
055     * Gets the list of valid biomes for the player to spawn in.
056     */
057    public List getBiomesToSpawnIn()
058    {
059        return this.biomesToSpawnIn;
060    }
061
062    /**
063     * Returns the BiomeGenBase related to the x, z position on the world.
064     */
065    public BiomeGenBase getBiomeGenAt(int par1, int par2)
066    {
067        return this.biomeCache.getBiomeGenAt(par1, par2);
068    }
069
070    /**
071     * Returns a list of rainfall values for the specified blocks. Args: listToReuse, x, z, width, length.
072     */
073    public float[] getRainfall(float[] par1ArrayOfFloat, int par2, int par3, int par4, int par5)
074    {
075        IntCache.resetIntCache();
076
077        if (par1ArrayOfFloat == null || par1ArrayOfFloat.length < par4 * par5)
078        {
079            par1ArrayOfFloat = new float[par4 * par5];
080        }
081
082        int[] aint = this.biomeIndexLayer.getInts(par2, par3, par4, par5);
083
084        for (int i1 = 0; i1 < par4 * par5; ++i1)
085        {
086            float f = (float)BiomeGenBase.biomeList[aint[i1]].getIntRainfall() / 65536.0F;
087
088            if (f > 1.0F)
089            {
090                f = 1.0F;
091            }
092
093            par1ArrayOfFloat[i1] = f;
094        }
095
096        return par1ArrayOfFloat;
097    }
098
099    @SideOnly(Side.CLIENT)
100
101    /**
102     * Return an adjusted version of a given temperature based on the y height
103     */
104    public float getTemperatureAtHeight(float par1, int par2)
105    {
106        return par1;
107    }
108
109    /**
110     * Returns a list of temperatures to use for the specified blocks.  Args: listToReuse, x, y, width, length
111     */
112    public float[] getTemperatures(float[] par1ArrayOfFloat, int par2, int par3, int par4, int par5)
113    {
114        IntCache.resetIntCache();
115
116        if (par1ArrayOfFloat == null || par1ArrayOfFloat.length < par4 * par5)
117        {
118            par1ArrayOfFloat = new float[par4 * par5];
119        }
120
121        int[] aint = this.biomeIndexLayer.getInts(par2, par3, par4, par5);
122
123        for (int i1 = 0; i1 < par4 * par5; ++i1)
124        {
125            float f = (float)BiomeGenBase.biomeList[aint[i1]].getIntTemperature() / 65536.0F;
126
127            if (f > 1.0F)
128            {
129                f = 1.0F;
130            }
131
132            par1ArrayOfFloat[i1] = f;
133        }
134
135        return par1ArrayOfFloat;
136    }
137
138    /**
139     * Returns an array of biomes for the location input.
140     */
141    public BiomeGenBase[] getBiomesForGeneration(BiomeGenBase[] par1ArrayOfBiomeGenBase, int par2, int par3, int par4, int par5)
142    {
143        IntCache.resetIntCache();
144
145        if (par1ArrayOfBiomeGenBase == null || par1ArrayOfBiomeGenBase.length < par4 * par5)
146        {
147            par1ArrayOfBiomeGenBase = new BiomeGenBase[par4 * par5];
148        }
149
150        int[] aint = this.genBiomes.getInts(par2, par3, par4, par5);
151
152        for (int i1 = 0; i1 < par4 * par5; ++i1)
153        {
154            par1ArrayOfBiomeGenBase[i1] = BiomeGenBase.biomeList[aint[i1]];
155        }
156
157        return par1ArrayOfBiomeGenBase;
158    }
159
160    /**
161     * Returns biomes to use for the blocks and loads the other data like temperature and humidity onto the
162     * WorldChunkManager Args: oldBiomeList, x, z, width, depth
163     */
164    public BiomeGenBase[] loadBlockGeneratorData(BiomeGenBase[] par1ArrayOfBiomeGenBase, int par2, int par3, int par4, int par5)
165    {
166        return this.getBiomeGenAt(par1ArrayOfBiomeGenBase, par2, par3, par4, par5, true);
167    }
168
169    /**
170     * Return a list of biomes for the specified blocks. Args: listToReuse, x, y, width, length, cacheFlag (if false,
171     * don't check biomeCache to avoid infinite loop in BiomeCacheBlock)
172     */
173    public BiomeGenBase[] getBiomeGenAt(BiomeGenBase[] par1ArrayOfBiomeGenBase, int par2, int par3, int par4, int par5, boolean par6)
174    {
175        IntCache.resetIntCache();
176
177        if (par1ArrayOfBiomeGenBase == null || par1ArrayOfBiomeGenBase.length < par4 * par5)
178        {
179            par1ArrayOfBiomeGenBase = new BiomeGenBase[par4 * par5];
180        }
181
182        if (par6 && par4 == 16 && par5 == 16 && (par2 & 15) == 0 && (par3 & 15) == 0)
183        {
184            BiomeGenBase[] abiomegenbase1 = this.biomeCache.getCachedBiomes(par2, par3);
185            System.arraycopy(abiomegenbase1, 0, par1ArrayOfBiomeGenBase, 0, par4 * par5);
186            return par1ArrayOfBiomeGenBase;
187        }
188        else
189        {
190            int[] aint = this.biomeIndexLayer.getInts(par2, par3, par4, par5);
191
192            for (int i1 = 0; i1 < par4 * par5; ++i1)
193            {
194                par1ArrayOfBiomeGenBase[i1] = BiomeGenBase.biomeList[aint[i1]];
195            }
196
197            return par1ArrayOfBiomeGenBase;
198        }
199    }
200
201    /**
202     * checks given Chunk's Biomes against List of allowed ones
203     */
204    public boolean areBiomesViable(int par1, int par2, int par3, List par4List)
205    {
206        IntCache.resetIntCache();
207        int l = par1 - par3 >> 2;
208        int i1 = par2 - par3 >> 2;
209        int j1 = par1 + par3 >> 2;
210        int k1 = par2 + par3 >> 2;
211        int l1 = j1 - l + 1;
212        int i2 = k1 - i1 + 1;
213        int[] aint = this.genBiomes.getInts(l, i1, l1, i2);
214
215        for (int j2 = 0; j2 < l1 * i2; ++j2)
216        {
217            BiomeGenBase biomegenbase = BiomeGenBase.biomeList[aint[j2]];
218
219            if (!par4List.contains(biomegenbase))
220            {
221                return false;
222            }
223        }
224
225        return true;
226    }
227
228    /**
229     * Finds a valid position within a range, that is in one of the listed biomes. Searches {par1,par2} +-par3 blocks.
230     * Strongly favors positive y positions.
231     */
232    public ChunkPosition findBiomePosition(int par1, int par2, int par3, List par4List, Random par5Random)
233    {
234        IntCache.resetIntCache();
235        int l = par1 - par3 >> 2;
236        int i1 = par2 - par3 >> 2;
237        int j1 = par1 + par3 >> 2;
238        int k1 = par2 + par3 >> 2;
239        int l1 = j1 - l + 1;
240        int i2 = k1 - i1 + 1;
241        int[] aint = this.genBiomes.getInts(l, i1, l1, i2);
242        ChunkPosition chunkposition = null;
243        int j2 = 0;
244
245        for (int k2 = 0; k2 < l1 * i2; ++k2)
246        {
247            int l2 = l + k2 % l1 << 2;
248            int i3 = i1 + k2 / l1 << 2;
249            BiomeGenBase biomegenbase = BiomeGenBase.biomeList[aint[k2]];
250
251            if (par4List.contains(biomegenbase) && (chunkposition == null || par5Random.nextInt(j2 + 1) == 0))
252            {
253                chunkposition = new ChunkPosition(l2, 0, i3);
254                ++j2;
255            }
256        }
257
258        return chunkposition;
259    }
260
261    /**
262     * Calls the WorldChunkManager's biomeCache.cleanupCache()
263     */
264    public void cleanupCache()
265    {
266        this.biomeCache.cleanupCache();
267    }
268
269    public GenLayer[] getModdedBiomeGenerators(WorldType worldType, long seed, GenLayer[] original)
270    {
271        WorldTypeEvent.InitBiomeGens event = new WorldTypeEvent.InitBiomeGens(worldType, seed, original);
272        MinecraftForge.TERRAIN_GEN_BUS.post(event);
273        return event.newBiomeGens;
274    }
275}