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 a new chunk provider which generates chunks for this world 073 */ 074 public IChunkProvider createChunkGenerator() 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 private SkyProvider cloudRenderer = null; 265 266 /** 267 * Sets the providers current dimension ID, used in default getSaveFolder() 268 * Added to allow default providers to be registered for multiple dimensions. 269 * 270 * @param dim Dimension ID 271 */ 272 public void setDimension(int dim) 273 { 274 this.dimensionId = dim; 275 } 276 277 /** 278 * Returns the sub-folder of the world folder that this WorldProvider saves to. 279 * EXA: DIM1, DIM-1 280 * @return The sub-folder name to save this world's chunks to. 281 */ 282 public String getSaveFolder() 283 { 284 return (dimensionId == 0 ? null : "DIM" + dimensionId); 285 } 286 287 /** 288 * A message to display to the user when they transfer to this dimension. 289 * 290 * @return The message to be displayed 291 */ 292 public String getWelcomeMessage() 293 { 294 if (this instanceof WorldProviderEnd) 295 { 296 return "Entering the End"; 297 } 298 else if (this instanceof WorldProviderHell) 299 { 300 return "Entering the Nether"; 301 } 302 return null; 303 } 304 305 /** 306 * A Message to display to the user when they transfer out of this dismension. 307 * 308 * @return The message to be displayed 309 */ 310 public String getDepartMessage() 311 { 312 if (this instanceof WorldProviderEnd) 313 { 314 return "Leaving the End"; 315 } 316 else if (this instanceof WorldProviderHell) 317 { 318 return "Leaving the Nether"; 319 } 320 return null; 321 } 322 323 /** 324 * The dimensions movement factor. Relative to normal overworld. 325 * It is applied to the players position when they transfer dimensions. 326 * Exa: Nether movement is 8.0 327 * @return The movement factor 328 */ 329 public double getMovementFactor() 330 { 331 if (this instanceof WorldProviderHell) 332 { 333 return 8.0; 334 } 335 return 1.0; 336 } 337 338 @SideOnly(Side.CLIENT) 339 public SkyProvider getSkyProvider() 340 { 341 return this.skyProvider; 342 } 343 344 @SideOnly(Side.CLIENT) 345 public void setSkyProvider(SkyProvider skyProvider) 346 { 347 this.skyProvider = skyProvider; 348 } 349 350 @SideOnly(Side.CLIENT) 351 public SkyProvider getCloudRenderer() 352 { 353 return cloudRenderer; 354 } 355 356 @SideOnly(Side.CLIENT) 357 public void setCloudRenderer(SkyProvider renderer) 358 { 359 cloudRenderer = renderer; 360 } 361 362 public ChunkCoordinates getRandomizedSpawnPoint() 363 { 364 ChunkCoordinates var5 = new ChunkCoordinates(this.worldObj.getSpawnPoint()); 365 366 boolean isAdventure = worldObj.getWorldInfo().getGameType() == EnumGameType.ADVENTURE; 367 int spawnFuzz = terrainType.getSpawnFuzz(); 368 int spawnFuzzHalf = spawnFuzz / 2; 369 370 if (!hasNoSky && !isAdventure) 371 { 372 var5.posX += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf; 373 var5.posZ += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf; 374 var5.posY = this.worldObj.getTopSolidOrLiquidBlock(var5.posX, var5.posZ); 375 } 376 377 return var5; 378 } 379 380 /** 381 * Determine if the cusor on the map should 'spin' when rendered, like it does for the player in the nether. 382 * 383 * @param entity The entity holding the map, playername, or frame-ENTITYID 384 * @param x X Position 385 * @param y Y Position 386 * @param z Z Postion 387 * @return True to 'spin' the cursor 388 */ 389 public boolean shouldMapSpin(String entity, double x, double y, double z) 390 { 391 return dimensionId < 0; 392 } 393 394 /** 395 * Determines the dimension the player will be respawned in, typically this brings them back to the overworld. 396 * 397 * @param player The player that is respawning 398 * @return The dimension to respawn the player in 399 */ 400 public int getRespawnDimension(EntityPlayerMP player) 401 { 402 return 0; 403 } 404 405 /*======================================= Start Moved From World =========================================*/ 406 407 public BiomeGenBase getBiomeGenForCoords(int x, int z) 408 { 409 return worldObj.getBiomeGenForCoordsBody(x, z); 410 } 411 412 public boolean isDaytime() 413 { 414 return worldObj.skylightSubtracted < 4; 415 } 416 417 @SideOnly(Side.CLIENT) 418 public Vec3 getSkyColor(Entity cameraEntity, float partialTicks) 419 { 420 return worldObj.getSkyColorBody(cameraEntity, partialTicks); 421 } 422 423 @SideOnly(Side.CLIENT) 424 public Vec3 drawClouds(float partialTicks) 425 { 426 return worldObj.drawCloudsBody(partialTicks); 427 } 428 429 @SideOnly(Side.CLIENT) 430 public float getStarBrightness(float par1) 431 { 432 return worldObj.getStarBrightnessBody(par1); 433 } 434 435 public void setAllowedSpawnTypes(boolean allowHostile, boolean allowPeaceful) 436 { 437 worldObj.spawnHostileMobs = allowHostile; 438 worldObj.spawnPeacefulMobs = allowPeaceful; 439 } 440 441 public void calculateInitialWeather() 442 { 443 worldObj.calculateInitialWeatherBody(); 444 } 445 446 public void updateWeather() 447 { 448 worldObj.updateWeatherBody(); 449 } 450 451 public void toggleRain() 452 { 453 worldObj.worldInfo.setRainTime(1); 454 } 455 456 public boolean canBlockFreeze(int x, int y, int z, boolean byWater) 457 { 458 return worldObj.canBlockFreezeBody(x, y, z, byWater); 459 } 460 461 public boolean canSnowAt(int x, int y, int z) 462 { 463 return worldObj.canSnowAtBody(x, y, z); 464 } 465 466 public void setWorldTime(long time) 467 { 468 worldObj.worldInfo.setWorldTime(time); 469 } 470 471 public long getSeed() 472 { 473 return worldObj.worldInfo.getSeed(); 474 } 475 476 public long getWorldTime() 477 { 478 return worldObj.worldInfo.getWorldTime(); 479 } 480 481 public ChunkCoordinates getSpawnPoint() 482 { 483 WorldInfo info = worldObj.worldInfo; 484 return new ChunkCoordinates(info.getSpawnX(), info.getSpawnY(), info.getSpawnZ()); 485 } 486 487 public void setSpawnPoint(int x, int y, int z) 488 { 489 worldObj.worldInfo.setSpawnPosition(x, y, z); 490 } 491 492 public boolean canMineBlock(EntityPlayer player, int x, int y, int z) 493 { 494 return worldObj.canMineBlockBody(player, x, y, z); 495 } 496 497 public boolean isBlockHighHumidity(int x, int y, int z) 498 { 499 return worldObj.getBiomeGenForCoords(x, z).isHighHumidity(); 500 } 501 502 public int getHeight() 503 { 504 return 256; 505 } 506 507 public int getActualHeight() 508 { 509 return hasNoSky ? 128 : 256; 510 } 511 512 public double getHorizon() 513 { 514 return worldObj.worldInfo.getTerrainType().getHorizon(worldObj); 515 } 516 517 public void resetRainAndThunder() 518 { 519 worldObj.worldInfo.setRainTime(0); 520 worldObj.worldInfo.setRaining(false); 521 worldObj.worldInfo.setThunderTime(0); 522 worldObj.worldInfo.setThundering(false); 523 } 524 525 public boolean canDoLightning(Chunk chunk) 526 { 527 return true; 528 } 529 530 public boolean canDoRainSnowIce(Chunk chunk) 531 { 532 return true; 533 } 534 }