001    package net.minecraft.src;
002    
003    import net.minecraftforge.client.SkyProvider;
004    import net.minecraftforge.common.DimensionManager;
005    import cpw.mods.fml.common.Side;
006    import cpw.mods.fml.common.asm.SideOnly;
007    
008    public abstract class WorldProvider
009    {
010        /** world object being used */
011        public World worldObj;
012        public WorldType terrainType;
013    
014        /** World chunk manager being used to generate chunks */
015        public WorldChunkManager worldChunkMgr;
016    
017        /**
018         * States whether the Hell world provider is used(true) or if the normal world provider is used(false)
019         */
020        public boolean isHellWorld = false;
021    
022        /**
023         * A boolean that tells if a world does not have a sky. Used in calculating weather and skylight
024         */
025        public boolean hasNoSky = false;
026    
027        /** Light to brightness conversion table */
028        public float[] lightBrightnessTable = new float[16];
029    
030        /** 0 for normal world -1 for hell */
031        public int worldType = 0;
032    
033        /** Array for sunrise/sunset colors (RGBA) */
034        private float[] colorsSunriseSunset = new float[4];
035    
036        private SkyProvider skyProvider = null;
037    
038        /**
039         * associate an existing world with a World provider, and setup its lightbrightness table
040         */
041        public final void registerWorld(World par1World)
042        {
043            this.worldObj = par1World;
044            this.terrainType = par1World.getWorldInfo().getTerrainType();
045            this.registerWorldChunkManager();
046            this.generateLightBrightnessTable();
047        }
048    
049        /**
050         * Creates the light to brightness table
051         */
052        protected void generateLightBrightnessTable()
053        {
054            float var1 = 0.0F;
055    
056            for (int var2 = 0; var2 <= 15; ++var2)
057            {
058                float var3 = 1.0F - (float)var2 / 15.0F;
059                this.lightBrightnessTable[var2] = (1.0F - var3) / (var3 * 3.0F + 1.0F) * (1.0F - var1) + var1;
060            }
061        }
062    
063        /**
064         * creates a new world chunk manager for WorldProvider
065         */
066        protected void registerWorldChunkManager()
067        {
068            this.worldChunkMgr = this.terrainType.getChunkManager(this.worldObj);
069        }
070    
071        /**
072         * Returns the chunk provider back for the world provider
073         */
074        public IChunkProvider getChunkProvider()
075        {
076            return this.terrainType.getChunkGenerator(this.worldObj);
077        }
078    
079        /**
080         * Will check if the x, z position specified is alright to be set as the map spawn point
081         */
082        public boolean canCoordinateBeSpawn(int par1, int par2)
083        {
084            int var3 = this.worldObj.getFirstUncoveredBlock(par1, par2);
085            return var3 == Block.grass.blockID;
086        }
087    
088        /**
089         * Calculates the angle of sun and moon in the sky relative to a specified time (usually worldTime)
090         */
091        public float calculateCelestialAngle(long par1, float par3)
092        {
093            int var4 = (int)(par1 % 24000L);
094            float var5 = ((float)var4 + par3) / 24000.0F - 0.25F;
095    
096            if (var5 < 0.0F)
097            {
098                ++var5;
099            }
100    
101            if (var5 > 1.0F)
102            {
103                --var5;
104            }
105    
106            float var6 = var5;
107            var5 = 1.0F - (float)((Math.cos((double)var5 * Math.PI) + 1.0D) / 2.0D);
108            var5 = var6 + (var5 - var6) / 3.0F;
109            return var5;
110        }
111    
112        @SideOnly(Side.CLIENT)
113        public int getMoonPhase(long par1, float par3)
114        {
115            return (int)(par1 / 24000L) % 8;
116        }
117    
118        /**
119         * Returns 'true' if in the "main surface world", but 'false' if in the Nether or End dimensions.
120         */
121        public boolean isSurfaceWorld()
122        {
123            return true;
124        }
125    
126        @SideOnly(Side.CLIENT)
127    
128        /**
129         * Returns array with sunrise/sunset colors
130         */
131        public float[] calcSunriseSunsetColors(float par1, float par2)
132        {
133            float var3 = 0.4F;
134            float var4 = MathHelper.cos(par1 * (float)Math.PI * 2.0F) - 0.0F;
135            float var5 = -0.0F;
136    
137            if (var4 >= var5 - var3 && var4 <= var5 + var3)
138            {
139                float var6 = (var4 - var5) / var3 * 0.5F + 0.5F;
140                float var7 = 1.0F - (1.0F - MathHelper.sin(var6 * (float)Math.PI)) * 0.99F;
141                var7 *= var7;
142                this.colorsSunriseSunset[0] = var6 * 0.3F + 0.7F;
143                this.colorsSunriseSunset[1] = var6 * var6 * 0.7F + 0.2F;
144                this.colorsSunriseSunset[2] = var6 * var6 * 0.0F + 0.2F;
145                this.colorsSunriseSunset[3] = var7;
146                return this.colorsSunriseSunset;
147            }
148            else
149            {
150                return null;
151            }
152        }
153    
154        @SideOnly(Side.CLIENT)
155    
156        /**
157         * Return Vec3D with biome specific fog color
158         */
159        public Vec3 getFogColor(float par1, float par2)
160        {
161            float var3 = MathHelper.cos(par1 * (float)Math.PI * 2.0F) * 2.0F + 0.5F;
162    
163            if (var3 < 0.0F)
164            {
165                var3 = 0.0F;
166            }
167    
168            if (var3 > 1.0F)
169            {
170                var3 = 1.0F;
171            }
172    
173            float var4 = 0.7529412F;
174            float var5 = 0.84705883F;
175            float var6 = 1.0F;
176            var4 *= var3 * 0.94F + 0.06F;
177            var5 *= var3 * 0.94F + 0.06F;
178            var6 *= var3 * 0.91F + 0.09F;
179            return Vec3.getVec3Pool().getVecFromPool((double)var4, (double)var5, (double)var6);
180        }
181    
182        /**
183         * True if the player can respawn in this dimension (true = overworld, false = nether).
184         */
185        public boolean canRespawnHere()
186        {
187            return true;
188        }
189    
190        public static WorldProvider getProviderForDimension(int par0)
191        {
192            return DimensionManager.createProviderFor(par0);
193        }
194    
195        @SideOnly(Side.CLIENT)
196    
197        /**
198         * the y level at which clouds are rendered.
199         */
200        public float getCloudHeight()
201        {
202            return 128.0F;
203        }
204    
205        @SideOnly(Side.CLIENT)
206        public boolean isSkyColored()
207        {
208            return true;
209        }
210    
211        /**
212         * Gets the hard-coded portal location to use when entering this dimension
213         */
214        public ChunkCoordinates getEntrancePortalLocation()
215        {
216            return null;
217        }
218    
219        public int getAverageGroundLevel()
220        {
221            return this.terrainType.getMinimumSpawnHeight(this.worldObj);
222        }
223    
224        @SideOnly(Side.CLIENT)
225    
226        /**
227         * returns true if this dimension is supposed to display void particles and pull in the far plane based on the
228         * user's Y offset.
229         */
230        public boolean getWorldHasVoidParticles()
231        {
232            return this.terrainType.hasVoidParticles(this.hasNoSky);
233        }
234    
235        @SideOnly(Side.CLIENT)
236    
237        /**
238         * Returns a double value representing the Y value relative to the top of the map at which void fog is at its
239         * maximum. The default factor of 0.03125 relative to 256, for example, means the void fog will be at its maximum at
240         * (256*0.03125), or 8.
241         */
242        public double getVoidFogYFactor()
243        {
244            return this.terrainType.voidFadeMagnitude();
245        }
246    
247        @SideOnly(Side.CLIENT)
248    
249        /**
250         * Returns true if the given X,Z coordinate should show environmental fog.
251         */
252        public boolean doesXZShowFog(int par1, int par2)
253        {
254            return false;
255        }
256    
257        public abstract String func_80007_l();
258    
259        /*======================================= Forge Start =========================================*/
260        private int dimensionID = 0;
261    
262        /**
263         * Sets the providers current dimension ID, used in default getSaveFolder()
264         * Added to allow default providers to be registered for multiple dimensions.
265         * 
266         * @param dim Dimension ID
267         */
268        public void setDimension(int dim)
269        {
270            this.dimensionID = dim;
271        }
272    
273        /**
274         * Returns the sub-folder of the world folder that this WorldProvider saves to.
275         * EXA: DIM1, DIM-1
276         * @return The sub-folder name to save this world's chunks to.
277         */
278        public String getSaveFolder()
279        {
280            return (dimensionID == 0 ? null : "DIM" + dimensionID);
281        }
282    
283        /**
284         * A message to display to the user when they transfer to this dimension.
285         *
286         * @return The message to be displayed
287         */
288        public String getWelcomeMessage()
289        {
290            if (this instanceof WorldProviderEnd)
291            {
292                return "Entering the End";
293            }
294            else if (this instanceof WorldProviderHell)
295            {
296                return "Entering the Nether";
297            }
298            return null;
299        }
300    
301        /**
302         * A Message to display to the user when they transfer out of this dismension.
303         *
304         * @return The message to be displayed
305         */
306        public String getDepartMessage()
307        {
308            if (this instanceof WorldProviderEnd)
309            {
310                return "Leaving the End";
311            }
312            else if (this instanceof WorldProviderHell)
313            {
314                return "Leaving the Nether";
315            } 
316            return null;
317        }
318    
319        /**
320         * The dimensions movement factor. Relative to normal overworld.
321         * It is applied to the players position when they transfer dimensions.
322         * Exa: Nether movement is 8.0
323         * @return The movement factor
324         */
325        public double getMovementFactor()
326        {
327            if (this instanceof WorldProviderHell)
328            {
329                return 8.0;
330            }
331            return 1.0;
332        }
333    
334        @SideOnly(Side.CLIENT)
335        public SkyProvider getSkyProvider()
336        {
337            return this.skyProvider;
338        }
339    
340        @SideOnly(Side.CLIENT)
341        public void setSkyProvider(SkyProvider skyProvider)
342        {
343            this.skyProvider = skyProvider;
344        }
345    
346        public ChunkCoordinates getRandomizedSpawnPoint()
347        {
348            ChunkCoordinates var5 = new ChunkCoordinates(this.worldObj.getSpawnPoint());
349    
350            boolean isAdventure = worldObj.getWorldInfo().getGameType() != EnumGameType.ADVENTURE;
351            int spawnFuzz = terrainType.getSpawnFuzz();
352            int spawnFuzzHalf = spawnFuzz / 2;
353    
354            if (!this.hasNoSky && !isAdventure)
355            {
356                var5.posX += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf;
357                var5.posZ += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf;
358                var5.posY = this.worldObj.getTopSolidOrLiquidBlock(var5.posX, var5.posZ);
359            }
360    
361            return var5;
362        }
363    }