    001    package net.minecraft.world;
    002
    003    import cpw.mods.fml.relauncher.Side;
    004    import cpw.mods.fml.relauncher.SideOnly;
    005    import net.minecraft.block.Block;
    006    import net.minecraft.entity.Entity;
    007    import net.minecraft.entity.player.EntityPlayer;
    008    import net.minecraft.entity.player.EntityPlayerMP;
    009    import net.minecraft.util.ChunkCoordinates;
    010    import net.minecraft.util.MathHelper;
    011    import net.minecraft.util.Vec3;
    012    import net.minecraft.world.biome.BiomeGenBase;
    013    import net.minecraft.world.biome.WorldChunkManager;
    014    import net.minecraft.world.biome.WorldChunkManagerHell;
    015    import net.minecraft.world.chunk.Chunk;
    016    import net.minecraft.world.chunk.IChunkProvider;
    017    import net.minecraft.world.gen.ChunkProviderFlat;
    018    import net.minecraft.world.gen.ChunkProviderGenerate;
    019    import net.minecraft.world.gen.FlatGeneratorInfo;
    020    import net.minecraft.world.storage.WorldInfo;
    021    import net.minecraftforge.client.IRenderHandler;
    022    import net.minecraftforge.common.DimensionManager;
    023
    024    public abstract class WorldProvider
    025    {
    026        /** world object being used */
    027        public World worldObj;
    028        public WorldType terrainType;
    029        public String field_82913_c;
    030
    031        /** World chunk manager being used to generate chunks */
    032        public WorldChunkManager worldChunkMgr;
    033
    034        /**
    035         * States whether the Hell world provider is used(true) or if the normal world provider is used(false)
    036         */
    037        public boolean isHellWorld = false;
    038
    039        /**
    040         * A boolean that tells if a world does not have a sky. Used in calculating weather and skylight
    041         */
    042        public boolean hasNoSky = false;
    043
    044        /** Light to brightness conversion table */
    045        public float[] lightBrightnessTable = new float[16];
    046
    047        /** The id for the dimension (ex. -1: Nether, 0: Overworld, 1: The End) */
    048        public int dimensionId = 0;
    049
    050        /** Array for sunrise/sunset colors (RGBA) */
    051        private float[] colorsSunriseSunset = new float[4];
    052
    053        /**
    054         * associate an existing world with a World provider, and setup its lightbrightness table
    055         */
    056        public final void registerWorld(World par1World)
    057        {
    058            this.worldObj = par1World;
    059            this.terrainType = par1World.getWorldInfo().getTerrainType();
    060            this.field_82913_c = par1World.getWorldInfo().func_82571_y();
    061            this.registerWorldChunkManager();
    062            this.generateLightBrightnessTable();
    063        }
    064
    065        /**
    066         * Creates the light to brightness table
    067         */
    068        protected void generateLightBrightnessTable()
    069        {
    070            float var1 = 0.0F;
    071
    072            for (int var2 = 0; var2 <= 15; ++var2)
    073            {
    074                float var3 = 1.0F - (float)var2 / 15.0F;
    075                this.lightBrightnessTable[var2] = (1.0F - var3) / (var3 * 3.0F + 1.0F) * (1.0F - var1) + var1;
    076            }
    077        }
    078
    079        /**
    080         * creates a new world chunk manager for WorldProvider
    081         */
    082        protected void registerWorldChunkManager()
    083        {
    084            worldChunkMgr = terrainType.getChunkManager(worldObj);
    085        }
    086
    087        /**
    088         * Returns a new chunk provider which generates chunks for this world
    089         */
    090        public IChunkProvider createChunkGenerator()
    091        {
    092            return terrainType.getChunkGenerator(worldObj, field_82913_c);
    093        }
    094
    095        /**
    096         * Will check if the x, z position specified is alright to be set as the map spawn point
    097         */
    098        public boolean canCoordinateBeSpawn(int par1, int par2)
    099        {
    100            int var3 = this.worldObj.getFirstUncoveredBlock(par1, par2);
    101            return var3 == Block.grass.blockID;
    102        }
    103
    104        /**
    105         * Calculates the angle of sun and moon in the sky relative to a specified time (usually worldTime)
    106         */
    107        public float calculateCelestialAngle(long par1, float par3)
    108        {
    109            int var4 = (int)(par1 % 24000L);
    110            float var5 = ((float)var4 + par3) / 24000.0F - 0.25F;
    111
    112            if (var5 < 0.0F)
    113            {
    114                ++var5;
    115            }
    116
    117            if (var5 > 1.0F)
    118            {
    119                --var5;
    120            }
    121
    122            float var6 = var5;
    123            var5 = 1.0F - (float)((Math.cos((double)var5 * Math.PI) + 1.0D) / 2.0D);
    124            var5 = var6 + (var5 - var6) / 3.0F;
    125            return var5;
    126        }
    127
    128        @SideOnly(Side.CLIENT)
    129        public int getMoonPhase(long par1, float par3)
    130        {
    131            return (int)(par1 / 24000L) % 8;
    132        }
    133
    134        /**
    135         * Returns 'true' if in the "main surface world", but 'false' if in the Nether or End dimensions.
    136         */
    137        public boolean isSurfaceWorld()
    138        {
    139            return true;
    140        }
    141
    142        @SideOnly(Side.CLIENT)
    143
    144        /**
    145         * Returns array with sunrise/sunset colors
    146         */
    147        public float[] calcSunriseSunsetColors(float par1, float par2)
    148        {
    149            float var3 = 0.4F;
    150            float var4 = MathHelper.cos(par1 * (float)Math.PI * 2.0F) - 0.0F;
    151            float var5 = -0.0F;
    152
    153            if (var4 >= var5 - var3 && var4 <= var5 + var3)
    154            {
    155                float var6 = (var4 - var5) / var3 * 0.5F + 0.5F;
    156                float var7 = 1.0F - (1.0F - MathHelper.sin(var6 * (float)Math.PI)) * 0.99F;
    157                var7 *= var7;
    158                this.colorsSunriseSunset[0] = var6 * 0.3F + 0.7F;
    159                this.colorsSunriseSunset[1] = var6 * var6 * 0.7F + 0.2F;
    160                this.colorsSunriseSunset[2] = var6 * var6 * 0.0F + 0.2F;
    161                this.colorsSunriseSunset[3] = var7;
    162                return this.colorsSunriseSunset;
    163            }
    164            else
    165            {
    166                return null;
    167            }
    168        }
    169
    170        @SideOnly(Side.CLIENT)
    171
    172        /**
    173         * Return Vec3D with biome specific fog color
    174         */
    175        public Vec3 getFogColor(float par1, float par2)
    176        {
    177            float var3 = MathHelper.cos(par1 * (float)Math.PI * 2.0F) * 2.0F + 0.5F;
    178
    179            if (var3 < 0.0F)
    180            {
    181                var3 = 0.0F;
    182            }
    183
    184            if (var3 > 1.0F)
    185            {
    186                var3 = 1.0F;
    187            }
    188
    189            float var4 = 0.7529412F;
    190            float var5 = 0.84705883F;
    191            float var6 = 1.0F;
    192            var4 *= var3 * 0.94F + 0.06F;
    193            var5 *= var3 * 0.94F + 0.06F;
    194            var6 *= var3 * 0.91F + 0.09F;
    195            return this.worldObj.getWorldVec3Pool().getVecFromPool((double)var4, (double)var5, (double)var6);
    196        }
    197
    198        /**
    199         * True if the player can respawn in this dimension (true = overworld, false = nether).
    200         */
    201        public boolean canRespawnHere()
    202        {
    203            return true;
    204        }
    205
    206        public static WorldProvider getProviderForDimension(int par0)
    207        {
    208            return DimensionManager.createProviderFor(par0);
    209        }
    210
    211        @SideOnly(Side.CLIENT)
    212
    213        /**
    214         * the y level at which clouds are rendered.
    215         */
    216        public float getCloudHeight()
    217        {
    218            return 128.0F;
    219        }
    220
    221        @SideOnly(Side.CLIENT)
    222        public boolean isSkyColored()
    223        {
    224            return true;
    225        }
    226
    227        /**
    228         * Gets the hard-coded portal location to use when entering this dimension.
    229         */
    230        public ChunkCoordinates getEntrancePortalLocation()
    231        {
    232            return null;
    233        }
    234
    235        public int getAverageGroundLevel()
    236        {
    237            return this.terrainType.getMinimumSpawnHeight(this.worldObj);
    238        }
    239
    240        @SideOnly(Side.CLIENT)
    241
    242        /**
    243         * returns true if this dimension is supposed to display void particles and pull in the far plane based on the
    244         * user's Y offset.
    245         */
    246        public boolean getWorldHasVoidParticles()
    247        {
    248            return this.terrainType.hasVoidParticles(this.hasNoSky);
    249        }
    250
    251        @SideOnly(Side.CLIENT)
    252
    253        /**
    254         * Returns a double value representing the Y value relative to the top of the map at which void fog is at its
    255         * maximum. The default factor of 0.03125 relative to 256, for example, means the void fog will be at its maximum at
    256         * (256*0.03125), or 8.
    257         */
    258        public double getVoidFogYFactor()
    259        {
    260            return this.terrainType.voidFadeMagnitude();
    261        }
    262
    263        @SideOnly(Side.CLIENT)
    264
    265        /**
    266         * Returns true if the given X,Z coordinate should show environmental fog.
    267         */
    268        public boolean doesXZShowFog(int par1, int par2)
    269        {
    270            return false;
    271        }
    272
    273        /**
    274         * Returns the dimension's name, e.g. "The End", "Nether", or "Overworld".
    275         */
    276        public abstract String getDimensionName();
    277
    278        /*======================================= Forge Start =========================================*/
    279        private IRenderHandler skyRenderer = null;
    280        private IRenderHandler cloudRenderer = null;
    281
    282        /**
    283         * Sets the providers current dimension ID, used in default getSaveFolder()
    284         * Added to allow default providers to be registered for multiple dimensions.
    285         *
    286         * @param dim Dimension ID
    287         */
    288        public void setDimension(int dim)
    289        {
    290            this.dimensionId = dim;
    291        }
    292
    293        /**
    294         * Returns the sub-folder of the world folder that this WorldProvider saves to.
    295         * EXA: DIM1, DIM-1
    296         * @return The sub-folder name to save this world's chunks to.
    297         */
    298        public String getSaveFolder()
    299        {
    300            return (dimensionId == 0 ? null : "DIM" + dimensionId);
    301        }
    302
    303        /**
    304         * A message to display to the user when they transfer to this dimension.
    305         *
    306         * @return The message to be displayed
    307         */
    308        public String getWelcomeMessage()
    309        {
    310            if (this instanceof WorldProviderEnd)
    311            {
    312                return "Entering the End";
    313            }
    314            else if (this instanceof WorldProviderHell)
    315            {
    316                return "Entering the Nether";
    317            }
    318            return null;
    319        }
    320
    321        /**
    322         * A Message to display to the user when they transfer out of this dismension.
    323         *
    324         * @return The message to be displayed
    325         */
    326        public String getDepartMessage()
    327        {
    328            if (this instanceof WorldProviderEnd)
    329            {
    330                return "Leaving the End";
    331            }
    332            else if (this instanceof WorldProviderHell)
    333            {
    334                return "Leaving the Nether";
    335            }
    336            return null;
    337        }
    338
    339        /**
    340         * The dimensions movement factor. Relative to normal overworld.
    341         * It is applied to the players position when they transfer dimensions.
    342         * Exa: Nether movement is 8.0
    343         * @return The movement factor
    344         */
    345        public double getMovementFactor()
    346        {
    347            if (this instanceof WorldProviderHell)
    348            {
    349                return 8.0;
    350            }
    351            return 1.0;
    352        }
    353
    354        @SideOnly(Side.CLIENT)
    355        public IRenderHandler getSkyRenderer()
    356        {
    357            return this.skyRenderer;
    358        }
    359
    360        @SideOnly(Side.CLIENT)
    361        public void setSkyRenderer(IRenderHandler skyRenderer)
    362        {
    363            this.skyRenderer = skyRenderer;
    364        }
    365
    366        @SideOnly(Side.CLIENT)
    367        public IRenderHandler getCloudRenderer()
    368        {
    369            return cloudRenderer;
    370        }
    371
    372        @SideOnly(Side.CLIENT)
    373        public void setCloudRenderer(IRenderHandler renderer)
    374        {
    375            cloudRenderer = renderer;
    376        }
    377
    378        public ChunkCoordinates getRandomizedSpawnPoint()
    379        {
    380            ChunkCoordinates var5 = new ChunkCoordinates(this.worldObj.getSpawnPoint());
    381
    382            boolean isAdventure = worldObj.getWorldInfo().getGameType() == EnumGameType.ADVENTURE;
    383            int spawnFuzz = terrainType.getSpawnFuzz();
    384            int spawnFuzzHalf = spawnFuzz / 2;
    385
    386            if (!hasNoSky && !isAdventure)
    387            {
    388                var5.posX += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf;
    389                var5.posZ += this.worldObj.rand.nextInt(spawnFuzz) - spawnFuzzHalf;
    390                var5.posY = this.worldObj.getTopSolidOrLiquidBlock(var5.posX, var5.posZ);
    391            }
    392
    393            return var5;
    394        }
    395
    396        /**
    397         * Determine if the cusor on the map should 'spin' when rendered, like it does for the player in the nether.
    398         *
    399         * @param entity The entity holding the map, playername, or frame-ENTITYID
    400         * @param x X Position
    401         * @param y Y Position
    402         * @param z Z Postion
    403         * @return True to 'spin' the cursor
    404         */
    405        public boolean shouldMapSpin(String entity, double x, double y, double z)
    406        {
    407            return dimensionId < 0;
    408        }
    409
    410        /**
    411         * Determines the dimension the player will be respawned in, typically this brings them back to the overworld.
    412         *
    413         * @param player The player that is respawning
    414         * @return The dimension to respawn the player in
    415         */
    416        public int getRespawnDimension(EntityPlayerMP player)
    417        {
    418            return 0;
    419        }
    420
    421        /*======================================= Start Moved From World =========================================*/
    422
    423        public BiomeGenBase getBiomeGenForCoords(int x, int z)
    424        {
    425            return worldObj.getBiomeGenForCoordsBody(x, z);
    426        }
    427
    428        public boolean isDaytime()
    429        {
    430            return worldObj.skylightSubtracted < 4;
    431        }
    432
    433        @SideOnly(Side.CLIENT)
    434        public Vec3 getSkyColor(Entity cameraEntity, float partialTicks)
    435        {
    436            return worldObj.getSkyColorBody(cameraEntity, partialTicks);
    437        }
    438
    439        @SideOnly(Side.CLIENT)
    440        public Vec3 drawClouds(float partialTicks)
    441        {
    442            return worldObj.drawCloudsBody(partialTicks);
    443        }
    444
    445        @SideOnly(Side.CLIENT)
    446        public float getStarBrightness(float par1)
    447        {
    448            return worldObj.getStarBrightnessBody(par1);
    449        }
    450
    451        public void setAllowedSpawnTypes(boolean allowHostile, boolean allowPeaceful)
    452        {
    453            worldObj.spawnHostileMobs = allowHostile;
    454            worldObj.spawnPeacefulMobs = allowPeaceful;
    455        }
    456
    457        public void calculateInitialWeather()
    458        {
    459            worldObj.calculateInitialWeatherBody();
    460        }
    461
    462        public void updateWeather()
    463        {
    464            worldObj.updateWeatherBody();
    465        }
    466
    467        public void toggleRain()
    468        {
    469            worldObj.worldInfo.setRainTime(1);
    470        }
    471
    472        public boolean canBlockFreeze(int x, int y, int z, boolean byWater)
    473        {
    474            return worldObj.canBlockFreezeBody(x, y, z, byWater);
    475        }
    476
    477        public boolean canSnowAt(int x, int y, int z)
    478        {
    479            return worldObj.canSnowAtBody(x, y, z);
    480        }
    481
    482        public void setWorldTime(long time)
    483        {
    484            worldObj.worldInfo.setWorldTime(time);
    485        }
    486
    487        public long getSeed()
    488        {
    489            return worldObj.worldInfo.getSeed();
    490        }
    491
    492        public long getWorldTime()
    493        {
    494            return worldObj.worldInfo.getWorldTime();
    495        }
    496
    497        public ChunkCoordinates getSpawnPoint()
    498        {
    499            WorldInfo info = worldObj.worldInfo;
    500            return new ChunkCoordinates(info.getSpawnX(), info.getSpawnY(), info.getSpawnZ());
    501        }
    502
    503        public void setSpawnPoint(int x, int y, int z)
    504        {
    505            worldObj.worldInfo.setSpawnPosition(x, y, z);
    506        }
    507
    508        public boolean canMineBlock(EntityPlayer player, int x, int y, int z)
    509        {
    510            return worldObj.canMineBlockBody(player, x, y, z);
    511        }
    512
    513        public boolean isBlockHighHumidity(int x, int y, int z)
    514        {
    515            return worldObj.getBiomeGenForCoords(x, z).isHighHumidity();
    516        }
    517
    518        public int getHeight()
    519        {
    520            return 256;
    521        }
    522
    523        public int getActualHeight()
    524        {
    525            return hasNoSky ? 128 : 256;
    526        }
    527
    528        public double getHorizon()
    529        {
    530            return worldObj.worldInfo.getTerrainType().getHorizon(worldObj);
    531        }
    532
    533        public void resetRainAndThunder()
    534        {
    535            worldObj.worldInfo.setRainTime(0);
    536            worldObj.worldInfo.setRaining(false);
    537            worldObj.worldInfo.setThunderTime(0);
    538            worldObj.worldInfo.setThundering(false);
    539        }
    540
    541        public boolean canDoLightning(Chunk chunk)
    542        {
    543            return true;
    544        }
    545
    546        public boolean canDoRainSnowIce(Chunk chunk)
    547        {
    548            return true;
    549        }
    550    }