package net.minecraft.world;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.world.WorldSettings.GameType;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.biome.WorldChunkManager;
import net.minecraft.world.biome.WorldChunkManagerHell;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.ChunkProviderFlat;
import net.minecraft.world.gen.ChunkProviderGenerate;
import net.minecraft.world.gen.FlatGeneratorInfo;
import net.minecraft.world.storage.WorldInfo;
import net.minecraftforge.client.IRenderHandler;
import net.minecraftforge.common.DimensionManager;
public abstract class WorldProvider
{
public static final float[] moonPhaseFactors = new float[] {1.0F, 0.75F, 0.5F, 0.25F, 0.0F, 0.25F, 0.5F, 0.75F};
/** world object being used */
public World worldObj;
public WorldType terrainType;
public String field_82913_c;
/** World chunk manager being used to generate chunks */
public WorldChunkManager worldChunkMgr;
/** States whether the Hell world provider is used(true) or if the normal world provider is used(false) */
public boolean isHellWorld;
/** A boolean that tells if a world does not have a sky. Used in calculating weather and skylight */
public boolean hasNoSky;
/** Light to brightness conversion table */
public float[] lightBrightnessTable = new float[16];
/** The id for the dimension (ex. -1: Nether, 0: Overworld, 1: The End) */
public int dimensionId;
/** Array for sunrise/sunset colors (RGBA) */
private float[] colorsSunriseSunset = new float[4];
private static final String __OBFID = "CL_00000386";
/**
* associate an existing world with a World provider, and setup its lightbrightness table
*/
public final void registerWorld(World p_76558_1_)
{
this.worldObj = p_76558_1_;
this.terrainType = p_76558_1_.getWorldInfo().getTerrainType();
this.field_82913_c = p_76558_1_.getWorldInfo().getGeneratorOptions();
this.registerWorldChunkManager();
this.generateLightBrightnessTable();
}
/**
* Creates the light to brightness table
*/
protected void generateLightBrightnessTable()
{
float f = 0.0F;
for (int i = 0; i <= 15; ++i)
{
float f1 = 1.0F - (float)i / 15.0F;
this.lightBrightnessTable[i] = (1.0F - f1) / (f1 * 3.0F + 1.0F) * (1.0F - f) + f;
}
}
/**
* creates a new world chunk manager for WorldProvider
*/
protected void registerWorldChunkManager()
{
this.worldChunkMgr = terrainType.getChunkManager(worldObj);
}
/**
* Returns a new chunk provider which generates chunks for this world
*/
public IChunkProvider createChunkGenerator()
{
return terrainType.getChunkGenerator(worldObj, field_82913_c);
}
/**
* Will check if the x, z position specified is alright to be set as the map spawn point
*/
public boolean canCoordinateBeSpawn(int p_76566_1_, int p_76566_2_)
{
return this.worldObj.getTopBlock(p_76566_1_, p_76566_2_) == Blocks.grass;
}
/**
* Calculates the angle of sun and moon in the sky relative to a specified time (usually worldTime)
*/
public float calculateCelestialAngle(long p_76563_1_, float p_76563_3_)
{
int j = (int)(p_76563_1_ % 24000L);
float f1 = ((float)j + p_76563_3_) / 24000.0F - 0.25F;
if (f1 < 0.0F)
{
++f1;
}
if (f1 > 1.0F)
{
--f1;
}
float f2 = f1;
f1 = 1.0F - (float)((Math.cos((double)f1 * Math.PI) + 1.0D) / 2.0D);
f1 = f2 + (f1 - f2) / 3.0F;
return f1;
}
public int getMoonPhase(long p_76559_1_)
{
return (int)(p_76559_1_ / 24000L % 8L + 8L) % 8;
}
/**
* Returns 'true' if in the "main surface world", but 'false' if in the Nether or End dimensions.
*/
public boolean isSurfaceWorld()
{
return true;
}
/**
* Returns array with sunrise/sunset colors
*/
@SideOnly(Side.CLIENT)
public float[] calcSunriseSunsetColors(float p_76560_1_, float p_76560_2_)
{
float f2 = 0.4F;
float f3 = MathHelper.cos(p_76560_1_ * (float)Math.PI * 2.0F) - 0.0F;
float f4 = -0.0F;
if (f3 >= f4 - f2 && f3 <= f4 + f2)
{
float f5 = (f3 - f4) / f2 * 0.5F + 0.5F;
float f6 = 1.0F - (1.0F - MathHelper.sin(f5 * (float)Math.PI)) * 0.99F;
f6 *= f6;
this.colorsSunriseSunset[0] = f5 * 0.3F + 0.7F;
this.colorsSunriseSunset[1] = f5 * f5 * 0.7F + 0.2F;
this.colorsSunriseSunset[2] = f5 * f5 * 0.0F + 0.2F;
this.colorsSunriseSunset[3] = f6;
return this.colorsSunriseSunset;
}
else
{
return null;
}
}
/**
* Return Vec3D with biome specific fog color
*/
@SideOnly(Side.CLIENT)
public Vec3 getFogColor(float p_76562_1_, float p_76562_2_)
{
float f2 = MathHelper.cos(p_76562_1_ * (float)Math.PI * 2.0F) * 2.0F + 0.5F;
if (f2 < 0.0F)
{
f2 = 0.0F;
}
if (f2 > 1.0F)
{
f2 = 1.0F;
}
float f3 = 0.7529412F;
float f4 = 0.84705883F;
float f5 = 1.0F;
f3 *= f2 * 0.94F + 0.06F;
f4 *= f2 * 0.94F + 0.06F;
f5 *= f2 * 0.91F + 0.09F;
return Vec3.createVectorHelper((double)f3, (double)f4, (double)f5);
}
/**
* True if the player can respawn in this dimension (true = overworld, false = nether).
*/
public boolean canRespawnHere()
{
return true;
}
public static WorldProvider getProviderForDimension(int p_76570_0_)
{
return DimensionManager.createProviderFor(p_76570_0_);
}
/**
* the y level at which clouds are rendered.
*/
@SideOnly(Side.CLIENT)
public float getCloudHeight()
{
return this.terrainType.getCloudHeight();
}
@SideOnly(Side.CLIENT)
public boolean isSkyColored()
{
return true;
}
/**
* Gets the hard-coded portal location to use when entering this dimension.
*/
public ChunkCoordinates getEntrancePortalLocation()
{
return null;
}
public int getAverageGroundLevel()
{
return this.terrainType.getMinimumSpawnHeight(this.worldObj);
}
/**
* returns true if this dimension is supposed to display void particles and pull in the far plane based on the
* user's Y offset.
*/
@SideOnly(Side.CLIENT)
public boolean getWorldHasVoidParticles()
{
return this.terrainType.hasVoidParticles(this.hasNoSky);
}
/**
* Returns a double value representing the Y value relative to the top of the map at which void fog is at its
* maximum. The default factor of 0.03125 relative to 256, for example, means the void fog will be at its maximum at
* (256*0.03125), or 8.
*/
@SideOnly(Side.CLIENT)
public double getVoidFogYFactor()
{
return this.terrainType.voidFadeMagnitude();
}
/**
* Returns true if the given X,Z coordinate should show environmental fog.
*/
@SideOnly(Side.CLIENT)
public boolean doesXZShowFog(int p_76568_1_, int p_76568_2_)
{
return false;
}
/**
* Returns the dimension's name, e.g. "The End", "Nether", or "Overworld".
*/
public abstract String getDimensionName();
/*======================================= Forge Start =========================================*/
private IRenderHandler skyRenderer = null;
private IRenderHandler cloudRenderer = null;
private IRenderHandler weatherRenderer = null;
/**
* Sets the providers current dimension ID, used in default getSaveFolder()
* Added to allow default providers to be registered for multiple dimensions.
*
* @param dim Dimension ID
*/
public void setDimension(int dim)
{
this.dimensionId = dim;
}
/**
* Returns the sub-folder of the world folder that this WorldProvider saves to.
* EXA: DIM1, DIM-1
* @return The sub-folder name to save this world's chunks to.
*/
public String getSaveFolder()
{
return (dimensionId == 0 ? null : "DIM" + dimensionId);
}
/**
* A message to display to the user when they transfer to this dimension.
*
* @return The message to be displayed
*/
public String getWelcomeMessage()
{
if (this instanceof WorldProviderEnd)
{
return "Entering the End";
}
else if (this instanceof WorldProviderHell)
{
return "Entering the Nether";
}
return null;
}
/**
* A Message to display to the user when they transfer out of this dismension.
*
* @return The message to be displayed
*/
public String getDepartMessage()
{
if (this instanceof WorldProviderEnd)
{
return "Leaving the End";
}
else if (this instanceof WorldProviderHell)
{
return "Leaving the Nether";
}
return null;
}
/**
* The dimensions movement factor. Relative to normal overworld.
* It is applied to the players position when they transfer dimensions.
* Exa: Nether movement is 8.0
* @return The movement factor
*/
public double getMovementFactor()
{
if (this instanceof WorldProviderHell)
{
return 8.0;
}
return 1.0;
}
@SideOnly(Side.CLIENT)
public IRenderHandler getSkyRenderer()
{
return this.skyRenderer;
}
@SideOnly(Side.CLIENT)
public void setSkyRenderer(IRenderHandler skyRenderer)
{
this.skyRenderer = skyRenderer;
}
@SideOnly(Side.CLIENT)
public IRenderHandler getCloudRenderer()
{
return cloudRenderer;
}
@SideOnly(Side.CLIENT)
public void setCloudRenderer(IRenderHandler renderer)
{
cloudRenderer = renderer;
}
@SideOnly(Side.CLIENT)
public IRenderHandler getWeatherRenderer()
{
return weatherRenderer;
}
@SideOnly(Side.CLIENT)
public void setWeatherRenderer(IRenderHandler renderer)
{
weatherRenderer = renderer;
}
public ChunkCoordinates getRandomizedSpawnPoint()
{
ChunkCoordinates chunkcoordinates = new ChunkCoordinates(this.worldObj.getSpawnPoint());
boolean isAdventure = worldObj.getWorldInfo().getGameType() == GameType.ADVENTURE;
int spawnFuzz = terrainType.getSpawnFuzz();
int spawnFuzzHalf = spawnFuzz / 2;
if (!hasNoSky && !isAdventure && net.minecraftforge.common.ForgeModContainer.defaultHasSpawnFuzz)
{
chunkcoordinates.posX += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf;
chunkcoordinates.posZ += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf;
chunkcoordinates.posY = this.worldObj.getTopSolidOrLiquidBlock(chunkcoordinates.posX, chunkcoordinates.posZ);
}
return chunkcoordinates;
}
/**
* Determine if the cusor on the map should 'spin' when rendered, like it does for the player in the nether.
*
* @param entity The entity holding the map, playername, or frame-ENTITYID
* @param x X Position
* @param y Y Position
* @param z Z Postion
* @return True to 'spin' the cursor
*/
public boolean shouldMapSpin(String entity, double x, double y, double z)
{
return dimensionId < 0;
}
/**
* Determines the dimension the player will be respawned in, typically this brings them back to the overworld.
*
* @param player The player that is respawning
* @return The dimension to respawn the player in
*/
public int getRespawnDimension(EntityPlayerMP player)
{
return 0;
}
/*======================================= Start Moved From World =========================================*/
public BiomeGenBase getBiomeGenForCoords(int x, int z)
{
return worldObj.getBiomeGenForCoordsBody(x, z);
}
public boolean isDaytime()
{
return worldObj.skylightSubtracted < 4;
}
/**
* The current sun brightness factor for this dimension.
* 0.0f means no light at all, and 1.0f means maximum sunlight.
* This will be used for the "calculateSkylightSubtracted"
* which is for Sky light value calculation.
*
* @return The current brightness factor
* */
public float getSunBrightnessFactor(float par1)
{
return worldObj.getSunBrightnessFactor(par1);
}
/**
* Calculates the current moon phase factor.
* This factor is effective for slimes.
* (This method do not affect the moon rendering)
* */
public float getCurrentMoonPhaseFactor()
{
return worldObj.getCurrentMoonPhaseFactorBody();
}
@SideOnly(Side.CLIENT)
public Vec3 getSkyColor(Entity cameraEntity, float partialTicks)
{
return worldObj.getSkyColorBody(cameraEntity, partialTicks);
}
@SideOnly(Side.CLIENT)
public Vec3 drawClouds(float partialTicks)
{
return worldObj.drawCloudsBody(partialTicks);
}
/**
* Gets the Sun Brightness for rendering sky.
* */
@SideOnly(Side.CLIENT)
public float getSunBrightness(float par1)
{
return worldObj.getSunBrightnessBody(par1);
}
/**
* Gets the Star Brightness for rendering sky.
* */
@SideOnly(Side.CLIENT)
public float getStarBrightness(float par1)
{
return worldObj.getStarBrightnessBody(par1);
}
public void setAllowedSpawnTypes(boolean allowHostile, boolean allowPeaceful)
{
worldObj.spawnHostileMobs = allowHostile;
worldObj.spawnPeacefulMobs = allowPeaceful;
}
public void calculateInitialWeather()
{
worldObj.calculateInitialWeatherBody();
}
public void updateWeather()
{
worldObj.updateWeatherBody();
}
public boolean canBlockFreeze(int x, int y, int z, boolean byWater)
{
return worldObj.canBlockFreezeBody(x, y, z, byWater);
}
public boolean canSnowAt(int x, int y, int z, boolean checkLight)
{
return worldObj.canSnowAtBody(x, y, z, checkLight);
}
public void setWorldTime(long time)
{
worldObj.worldInfo.setWorldTime(time);
}
public long getSeed()
{
return worldObj.worldInfo.getSeed();
}
public long getWorldTime()
{
return worldObj.worldInfo.getWorldTime();
}
public ChunkCoordinates getSpawnPoint()
{
WorldInfo info = worldObj.worldInfo;
return new ChunkCoordinates(info.getSpawnX(), info.getSpawnY(), info.getSpawnZ());
}
public void setSpawnPoint(int x, int y, int z)
{
worldObj.worldInfo.setSpawnPosition(x, y, z);
}
public boolean canMineBlock(EntityPlayer player, int x, int y, int z)
{
return worldObj.canMineBlockBody(player, x, y, z);
}
public boolean isBlockHighHumidity(int x, int y, int z)
{
return worldObj.getBiomeGenForCoords(x, z).isHighHumidity();
}
public int getHeight()
{
return 256;
}
public int getActualHeight()
{
return hasNoSky ? 128 : 256;
}
public double getHorizon()
{
return worldObj.worldInfo.getTerrainType().getHorizon(worldObj);
}
public void resetRainAndThunder()
{
worldObj.worldInfo.setRainTime(0);
worldObj.worldInfo.setRaining(false);
worldObj.worldInfo.setThunderTime(0);
worldObj.worldInfo.setThundering(false);
}
public boolean canDoLightning(Chunk chunk)
{
return true;
}
public boolean canDoRainSnowIce(Chunk chunk)
{
return true;
}
}