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 (!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 }