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