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 public String field_82913_c;
014
015 /** World chunk manager being used to generate chunks */
016 public WorldChunkManager worldChunkMgr;
017
018 /**
019 * States whether the Hell world provider is used(true) or if the normal world provider is used(false)
020 */
021 public boolean isHellWorld = false;
022
023 /**
024 * A boolean that tells if a world does not have a sky. Used in calculating weather and skylight
025 */
026 public boolean hasNoSky = false;
027
028 /** Light to brightness conversion table */
029 public float[] lightBrightnessTable = new float[16];
030
031 /** The id for the dimension (ex. -1: Nether, 0: Overworld, 1: The End) */
032 public int dimensionId = 0;
033
034 /** Array for sunrise/sunset colors (RGBA) */
035 private float[] colorsSunriseSunset = new float[4];
036
037 /**
038 * associate an existing world with a World provider, and setup its lightbrightness table
039 */
040 public final void registerWorld(World par1World)
041 {
042 this.worldObj = par1World;
043 this.terrainType = par1World.getWorldInfo().getTerrainType();
044 this.field_82913_c = par1World.getWorldInfo().func_82571_y();
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 worldChunkMgr = terrainType.getChunkManager(worldObj);
069 }
070
071 /**
072 * Returns the chunk provider back for the world provider
073 */
074 public IChunkProvider getChunkProvider()
075 {
076 return terrainType.getChunkGenerator(worldObj, field_82913_c);
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 this.worldObj.getWorldVec3Pool().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 /**
258 * Returns the dimension's name, e.g. "The End", "Nether", or "Overworld".
259 */
260 public abstract String getDimensionName();
261
262 /*======================================= Forge Start =========================================*/
263 private SkyProvider skyProvider = null;
264 /**
265 * Sets the providers current dimension ID, used in default getSaveFolder()
266 * Added to allow default providers to be registered for multiple dimensions.
267 *
268 * @param dim Dimension ID
269 */
270 public void setDimension(int dim)
271 {
272 this.dimensionId = dim;
273 }
274
275 /**
276 * Returns the sub-folder of the world folder that this WorldProvider saves to.
277 * EXA: DIM1, DIM-1
278 * @return The sub-folder name to save this world's chunks to.
279 */
280 public String getSaveFolder()
281 {
282 return (dimensionId == 0 ? null : "DIM" + dimensionId);
283 }
284
285 /**
286 * A message to display to the user when they transfer to this dimension.
287 *
288 * @return The message to be displayed
289 */
290 public String getWelcomeMessage()
291 {
292 if (this instanceof WorldProviderEnd)
293 {
294 return "Entering the End";
295 }
296 else if (this instanceof WorldProviderHell)
297 {
298 return "Entering the Nether";
299 }
300 return null;
301 }
302
303 /**
304 * A Message to display to the user when they transfer out of this dismension.
305 *
306 * @return The message to be displayed
307 */
308 public String getDepartMessage()
309 {
310 if (this instanceof WorldProviderEnd)
311 {
312 return "Leaving the End";
313 }
314 else if (this instanceof WorldProviderHell)
315 {
316 return "Leaving the Nether";
317 }
318 return null;
319 }
320
321 /**
322 * The dimensions movement factor. Relative to normal overworld.
323 * It is applied to the players position when they transfer dimensions.
324 * Exa: Nether movement is 8.0
325 * @return The movement factor
326 */
327 public double getMovementFactor()
328 {
329 if (this instanceof WorldProviderHell)
330 {
331 return 8.0;
332 }
333 return 1.0;
334 }
335
336 @SideOnly(Side.CLIENT)
337 public SkyProvider getSkyProvider()
338 {
339 return this.skyProvider;
340 }
341
342 @SideOnly(Side.CLIENT)
343 public void setSkyProvider(SkyProvider skyProvider)
344 {
345 this.skyProvider = skyProvider;
346 }
347
348 public ChunkCoordinates getRandomizedSpawnPoint()
349 {
350 ChunkCoordinates var5 = new ChunkCoordinates(this.worldObj.getSpawnPoint());
351
352 boolean isAdventure = worldObj.getWorldInfo().getGameType() != EnumGameType.ADVENTURE;
353 int spawnFuzz = terrainType.getSpawnFuzz();
354 int spawnFuzzHalf = spawnFuzz / 2;
355
356 if (!this.hasNoSky && !isAdventure)
357 {
358 var5.posX += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf;
359 var5.posZ += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf;
360 var5.posY = this.worldObj.getTopSolidOrLiquidBlock(var5.posX, var5.posZ);
361 }
362
363 return var5;
364 }
365
366 /*======================================= Start Moved From World =========================================*/
367
368 public BiomeGenBase getBiomeGenForCoords(int x, int z)
369 {
370 return worldObj.getBiomeGenForCoordsBody(x, z);
371 }
372
373 public boolean isDaytime()
374 {
375 return worldObj.skylightSubtracted < 4;
376 }
377
378 @SideOnly(Side.CLIENT)
379 public Vec3 getSkyColor(Entity cameraEntity, float partialTicks)
380 {
381 return worldObj.getSkyColorBody(cameraEntity, partialTicks);
382 }
383
384 @SideOnly(Side.CLIENT)
385 public Vec3 drawClouds(float partialTicks)
386 {
387 return worldObj.drawCloudsBody(partialTicks);
388 }
389
390 @SideOnly(Side.CLIENT)
391 public float getStarBrightness(float par1)
392 {
393 return worldObj.getStarBrightnessBody(par1);
394 }
395
396 public void setAllowedSpawnTypes(boolean allowHostile, boolean allowPeaceful)
397 {
398 worldObj.spawnHostileMobs = allowHostile;
399 worldObj.spawnPeacefulMobs = allowPeaceful;
400 }
401
402 public void calculateInitialWeather()
403 {
404 worldObj.calculateInitialWeatherBody();
405 }
406
407 public void updateWeather()
408 {
409 worldObj.updateWeatherBody();
410 }
411
412 public void toggleRain()
413 {
414 worldObj.worldInfo.setRainTime(1);
415 }
416
417 public boolean canBlockFreeze(int x, int y, int z, boolean byWater)
418 {
419 return worldObj.canBlockFreezeBody(x, y, z, byWater);
420 }
421
422 public boolean canSnowAt(int x, int y, int z)
423 {
424 return worldObj.canSnowAtBody(x, y, z);
425 }
426
427 public void setWorldTime(long time)
428 {
429 worldObj.worldInfo.setWorldTime(time);
430 }
431
432 public long getSeed()
433 {
434 return worldObj.worldInfo.getSeed();
435 }
436
437 public long getWorldTime()
438 {
439 return worldObj.worldInfo.getWorldTime();
440 }
441
442 public ChunkCoordinates getSpawnPoint()
443 {
444 WorldInfo info = worldObj.worldInfo;
445 return new ChunkCoordinates(info.getSpawnX(), info.getSpawnY(), info.getSpawnZ());
446 }
447
448 public void setSpawnPoint(int x, int y, int z)
449 {
450 worldObj.worldInfo.setSpawnPosition(x, y, z);
451 }
452
453 public boolean canMineBlock(EntityPlayer player, int x, int y, int z)
454 {
455 return worldObj.canMineBlockBody(player, x, y, z);
456 }
457
458 public boolean isBlockHighHumidity(int x, int y, int z)
459 {
460 return worldObj.getBiomeGenForCoords(x, z).isHighHumidity();
461 }
462
463 public int getHeight()
464 {
465 return 256;
466 }
467
468 public int getActualHeight()
469 {
470 return hasNoSky ? 128 : 256;
471 }
472
473 public double getHorizon()
474 {
475 return worldObj.worldInfo.getTerrainType().getHorizon(worldObj);
476 }
477
478 public void resetRainAndThunder()
479 {
480 worldObj.worldInfo.setRainTime(0);
481 worldObj.worldInfo.setRaining(false);
482 worldObj.worldInfo.setThunderTime(0);
483 worldObj.worldInfo.setThundering(false);
484 }
485
486 public boolean canDoLightning(Chunk chunk)
487 {
488 return true;
489 }
490
491 public boolean canDoRainSnowIce(Chunk chunk)
492 {
493 return true;
494 }
495 }