    001package net.minecraft.world.storage;
    002
    003import java.util.Map;
    004
    005import cpw.mods.fml.relauncher.Side;
    006import cpw.mods.fml.relauncher.SideOnly;
    007import net.minecraft.crash.CrashReportCategory;
    008import net.minecraft.nbt.NBTBase;
    009import net.minecraft.nbt.NBTTagCompound;
    010import net.minecraft.world.EnumGameType;
    011import net.minecraft.world.GameRules;
    012import net.minecraft.world.WorldSettings;
    013import net.minecraft.world.WorldType;
    014
    015public class WorldInfo
    016{
    017    /** Holds the seed of the currently world. */
    018    private long randomSeed;
    019    private WorldType terrainType;
    020    private String generatorOptions;
    021
    022    /** The spawn zone position X coordinate. */
    023    private int spawnX;
    024
    025    /** The spawn zone position Y coordinate. */
    026    private int spawnY;
    027
    028    /** The spawn zone position Z coordinate. */
    029    private int spawnZ;
    030
    031    /** Total time for this world. */
    032    private long totalTime;
    033
    034    /** The current world time in ticks, ranging from 0 to 23999. */
    035    private long worldTime;
    036
    037    /** The last time the player was in this world. */
    038    private long lastTimePlayed;
    039
    040    /** The size of entire save of current world on the disk, isn't exactly. */
    041    private long sizeOnDisk;
    042    private NBTTagCompound playerTag;
    043    private int dimension;
    044
    045    /** The name of the save defined at world creation. */
    046    private String levelName;
    047
    048    /** Introduced in beta 1.3, is the save version for future control. */
    049    private int saveVersion;
    050
    051    /** True if it's raining, false otherwise. */
    052    private boolean raining;
    053
    054    /** Number of ticks until next rain. */
    055    private int rainTime;
    056
    057    /** Is thunderbolts failing now? */
    058    private boolean thundering;
    059
    060    /** Number of ticks untils next thunderbolt. */
    061    private int thunderTime;
    062
    063    /** The Game Type. */
    064    private EnumGameType theGameType;
    065
    066    /**
    067     * Whether the map features (e.g. strongholds) generation is enabled or disabled.
    068     */
    069    private boolean mapFeaturesEnabled;
    070
    071    /** Hardcore mode flag */
    072    private boolean hardcore;
    073    private boolean allowCommands;
    074    private boolean initialized;
    075    private GameRules theGameRules;
    076    private Map<String, NBTBase> additionalProperties;
    077
    078    protected WorldInfo()
    079    {
    080        this.terrainType = WorldType.DEFAULT;
    081        this.generatorOptions = "";
    082        this.theGameRules = new GameRules();
    083    }
    084
    085    public WorldInfo(NBTTagCompound par1NBTTagCompound)
    086    {
    087        this.terrainType = WorldType.DEFAULT;
    088        this.generatorOptions = "";
    089        this.theGameRules = new GameRules();
    090        this.randomSeed = par1NBTTagCompound.getLong("RandomSeed");
    091
    092        if (par1NBTTagCompound.hasKey("generatorName"))
    093        {
    094            String s = par1NBTTagCompound.getString("generatorName");
    095            this.terrainType = WorldType.parseWorldType(s);
    096
    097            if (this.terrainType == null)
    098            {
    099                this.terrainType = WorldType.DEFAULT;
    100            }
    101            else if (this.terrainType.isVersioned())
    102            {
    103                int i = 0;
    104
    105                if (par1NBTTagCompound.hasKey("generatorVersion"))
    106                {
    107                    i = par1NBTTagCompound.getInteger("generatorVersion");
    108                }
    109
    110                this.terrainType = this.terrainType.getWorldTypeForGeneratorVersion(i);
    111            }
    112
    113            if (par1NBTTagCompound.hasKey("generatorOptions"))
    114            {
    115                this.generatorOptions = par1NBTTagCompound.getString("generatorOptions");
    116            }
    117        }
    118
    119        this.theGameType = EnumGameType.getByID(par1NBTTagCompound.getInteger("GameType"));
    120
    121        if (par1NBTTagCompound.hasKey("MapFeatures"))
    122        {
    123            this.mapFeaturesEnabled = par1NBTTagCompound.getBoolean("MapFeatures");
    124        }
    125        else
    126        {
    127            this.mapFeaturesEnabled = true;
    128        }
    129
    130        this.spawnX = par1NBTTagCompound.getInteger("SpawnX");
    131        this.spawnY = par1NBTTagCompound.getInteger("SpawnY");
    132        this.spawnZ = par1NBTTagCompound.getInteger("SpawnZ");
    133        this.totalTime = par1NBTTagCompound.getLong("Time");
    134
    135        if (par1NBTTagCompound.hasKey("DayTime"))
    136        {
    137            this.worldTime = par1NBTTagCompound.getLong("DayTime");
    138        }
    139        else
    140        {
    141            this.worldTime = this.totalTime;
    142        }
    143
    144        this.lastTimePlayed = par1NBTTagCompound.getLong("LastPlayed");
    145        this.sizeOnDisk = par1NBTTagCompound.getLong("SizeOnDisk");
    146        this.levelName = par1NBTTagCompound.getString("LevelName");
    147        this.saveVersion = par1NBTTagCompound.getInteger("version");
    148        this.rainTime = par1NBTTagCompound.getInteger("rainTime");
    149        this.raining = par1NBTTagCompound.getBoolean("raining");
    150        this.thunderTime = par1NBTTagCompound.getInteger("thunderTime");
    151        this.thundering = par1NBTTagCompound.getBoolean("thundering");
    152        this.hardcore = par1NBTTagCompound.getBoolean("hardcore");
    153
    154        if (par1NBTTagCompound.hasKey("initialized"))
    155        {
    156            this.initialized = par1NBTTagCompound.getBoolean("initialized");
    157        }
    158        else
    159        {
    160            this.initialized = true;
    161        }
    162
    163        if (par1NBTTagCompound.hasKey("allowCommands"))
    164        {
    165            this.allowCommands = par1NBTTagCompound.getBoolean("allowCommands");
    166        }
    167        else
    168        {
    169            this.allowCommands = this.theGameType == EnumGameType.CREATIVE;
    170        }
    171
    172        if (par1NBTTagCompound.hasKey("Player"))
    173        {
    174            this.playerTag = par1NBTTagCompound.getCompoundTag("Player");
    175            this.dimension = this.playerTag.getInteger("Dimension");
    176        }
    177
    178        if (par1NBTTagCompound.hasKey("GameRules"))
    179        {
    180            this.theGameRules.readGameRulesFromNBT(par1NBTTagCompound.getCompoundTag("GameRules"));
    181        }
    182    }
    183
    184    public WorldInfo(WorldSettings par1WorldSettings, String par2Str)
    185    {
    186        this.terrainType = WorldType.DEFAULT;
    187        this.generatorOptions = "";
    188        this.theGameRules = new GameRules();
    189        this.randomSeed = par1WorldSettings.getSeed();
    190        this.theGameType = par1WorldSettings.getGameType();
    191        this.mapFeaturesEnabled = par1WorldSettings.isMapFeaturesEnabled();
    192        this.levelName = par2Str;
    193        this.hardcore = par1WorldSettings.getHardcoreEnabled();
    194        this.terrainType = par1WorldSettings.getTerrainType();
    195        this.generatorOptions = par1WorldSettings.func_82749_j();
    196        this.allowCommands = par1WorldSettings.areCommandsAllowed();
    197        this.initialized = false;
    198    }
    199
    200    public WorldInfo(WorldInfo par1WorldInfo)
    201    {
    202        this.terrainType = WorldType.DEFAULT;
    203        this.generatorOptions = "";
    204        this.theGameRules = new GameRules();
    205        this.randomSeed = par1WorldInfo.randomSeed;
    206        this.terrainType = par1WorldInfo.terrainType;
    207        this.generatorOptions = par1WorldInfo.generatorOptions;
    208        this.theGameType = par1WorldInfo.theGameType;
    209        this.mapFeaturesEnabled = par1WorldInfo.mapFeaturesEnabled;
    210        this.spawnX = par1WorldInfo.spawnX;
    211        this.spawnY = par1WorldInfo.spawnY;
    212        this.spawnZ = par1WorldInfo.spawnZ;
    213        this.totalTime = par1WorldInfo.totalTime;
    214        this.worldTime = par1WorldInfo.worldTime;
    215        this.lastTimePlayed = par1WorldInfo.lastTimePlayed;
    216        this.sizeOnDisk = par1WorldInfo.sizeOnDisk;
    217        this.playerTag = par1WorldInfo.playerTag;
    218        this.dimension = par1WorldInfo.dimension;
    219        this.levelName = par1WorldInfo.levelName;
    220        this.saveVersion = par1WorldInfo.saveVersion;
    221        this.rainTime = par1WorldInfo.rainTime;
    222        this.raining = par1WorldInfo.raining;
    223        this.thunderTime = par1WorldInfo.thunderTime;
    224        this.thundering = par1WorldInfo.thundering;
    225        this.hardcore = par1WorldInfo.hardcore;
    226        this.allowCommands = par1WorldInfo.allowCommands;
    227        this.initialized = par1WorldInfo.initialized;
    228        this.theGameRules = par1WorldInfo.theGameRules;
    229    }
    230
    231    /**
    232     * Gets the NBTTagCompound for the worldInfo
    233     */
    234    public NBTTagCompound getNBTTagCompound()
    235    {
    236        NBTTagCompound nbttagcompound = new NBTTagCompound();
    237        this.updateTagCompound(nbttagcompound, this.playerTag);
    238        return nbttagcompound;
    239    }
    240
    241    /**
    242     * Creates a new NBTTagCompound for the world, with the given NBTTag as the "Player"
    243     */
    244    public NBTTagCompound cloneNBTCompound(NBTTagCompound par1NBTTagCompound)
    245    {
    246        NBTTagCompound nbttagcompound1 = new NBTTagCompound();
    247        this.updateTagCompound(nbttagcompound1, par1NBTTagCompound);
    248        return nbttagcompound1;
    249    }
    250
    251    private void updateTagCompound(NBTTagCompound par1NBTTagCompound, NBTTagCompound par2NBTTagCompound)
    252    {
    253        par1NBTTagCompound.setLong("RandomSeed", this.randomSeed);
    254        par1NBTTagCompound.setString("generatorName", this.terrainType.getWorldTypeName());
    255        par1NBTTagCompound.setInteger("generatorVersion", this.terrainType.getGeneratorVersion());
    256        par1NBTTagCompound.setString("generatorOptions", this.generatorOptions);
    257        par1NBTTagCompound.setInteger("GameType", this.theGameType.getID());
    258        par1NBTTagCompound.setBoolean("MapFeatures", this.mapFeaturesEnabled);
    259        par1NBTTagCompound.setInteger("SpawnX", this.spawnX);
    260        par1NBTTagCompound.setInteger("SpawnY", this.spawnY);
    261        par1NBTTagCompound.setInteger("SpawnZ", this.spawnZ);
    262        par1NBTTagCompound.setLong("Time", this.totalTime);
    263        par1NBTTagCompound.setLong("DayTime", this.worldTime);
    264        par1NBTTagCompound.setLong("SizeOnDisk", this.sizeOnDisk);
    265        par1NBTTagCompound.setLong("LastPlayed", System.currentTimeMillis());
    266        par1NBTTagCompound.setString("LevelName", this.levelName);
    267        par1NBTTagCompound.setInteger("version", this.saveVersion);
    268        par1NBTTagCompound.setInteger("rainTime", this.rainTime);
    269        par1NBTTagCompound.setBoolean("raining", this.raining);
    270        par1NBTTagCompound.setInteger("thunderTime", this.thunderTime);
    271        par1NBTTagCompound.setBoolean("thundering", this.thundering);
    272        par1NBTTagCompound.setBoolean("hardcore", this.hardcore);
    273        par1NBTTagCompound.setBoolean("allowCommands", this.allowCommands);
    274        par1NBTTagCompound.setBoolean("initialized", this.initialized);
    275        par1NBTTagCompound.setCompoundTag("GameRules", this.theGameRules.writeGameRulesToNBT());
    276
    277        if (par2NBTTagCompound != null)
    278        {
    279            par1NBTTagCompound.setCompoundTag("Player", par2NBTTagCompound);
    280        }
    281    }
    282
    283    /**
    284     * Returns the seed of current world.
    285     */
    286    public long getSeed()
    287    {
    288        return this.randomSeed;
    289    }
    290
    291    /**
    292     * Returns the x spawn position
    293     */
    294    public int getSpawnX()
    295    {
    296        return this.spawnX;
    297    }
    298
    299    /**
    300     * Return the Y axis spawning point of the player.
    301     */
    302    public int getSpawnY()
    303    {
    304        return this.spawnY;
    305    }
    306
    307    /**
    308     * Returns the z spawn position
    309     */
    310    public int getSpawnZ()
    311    {
    312        return this.spawnZ;
    313    }
    314
    315    public long getWorldTotalTime()
    316    {
    317        return this.totalTime;
    318    }
    319
    320    /**
    321     * Get current world time
    322     */
    323    public long getWorldTime()
    324    {
    325        return this.worldTime;
    326    }
    327
    328    @SideOnly(Side.CLIENT)
    329    public long getSizeOnDisk()
    330    {
    331        return this.sizeOnDisk;
    332    }
    333
    334    /**
    335     * Returns the player's NBTTagCompound to be loaded
    336     */
    337    public NBTTagCompound getPlayerNBTTagCompound()
    338    {
    339        return this.playerTag;
    340    }
    341
    342    public int getDimension()
    343    {
    344        return this.dimension;
    345    }
    346
    347    @SideOnly(Side.CLIENT)
    348
    349    /**
    350     * Set the x spawn position to the passed in value
    351     */
    352    public void setSpawnX(int par1)
    353    {
    354        this.spawnX = par1;
    355    }
    356
    357    @SideOnly(Side.CLIENT)
    358
    359    /**
    360     * Sets the y spawn position
    361     */
    362    public void setSpawnY(int par1)
    363    {
    364        this.spawnY = par1;
    365    }
    366
    367    public void incrementTotalWorldTime(long par1)
    368    {
    369        this.totalTime = par1;
    370    }
    371
    372    @SideOnly(Side.CLIENT)
    373
    374    /**
    375     * Set the z spawn position to the passed in value
    376     */
    377    public void setSpawnZ(int par1)
    378    {
    379        this.spawnZ = par1;
    380    }
    381
    382    /**
    383     * Set current world time
    384     */
    385    public void setWorldTime(long par1)
    386    {
    387        this.worldTime = par1;
    388    }
    389
    390    /**
    391     * Sets the spawn zone position. Args: x, y, z
    392     */
    393    public void setSpawnPosition(int par1, int par2, int par3)
    394    {
    395        this.spawnX = par1;
    396        this.spawnY = par2;
    397        this.spawnZ = par3;
    398    }
    399
    400    /**
    401     * Get current world name
    402     */
    403    public String getWorldName()
    404    {
    405        return this.levelName;
    406    }
    407
    408    public void setWorldName(String par1Str)
    409    {
    410        this.levelName = par1Str;
    411    }
    412
    413    /**
    414     * Returns the save version of this world
    415     */
    416    public int getSaveVersion()
    417    {
    418        return this.saveVersion;
    419    }
    420
    421    /**
    422     * Sets the save version of the world
    423     */
    424    public void setSaveVersion(int par1)
    425    {
    426        this.saveVersion = par1;
    427    }
    428
    429    @SideOnly(Side.CLIENT)
    430
    431    /**
    432     * Return the last time the player was in this world.
    433     */
    434    public long getLastTimePlayed()
    435    {
    436        return this.lastTimePlayed;
    437    }
    438
    439    /**
    440     * Returns true if it is thundering, false otherwise.
    441     */
    442    public boolean isThundering()
    443    {
    444        return this.thundering;
    445    }
    446
    447    /**
    448     * Sets whether it is thundering or not.
    449     */
    450    public void setThundering(boolean par1)
    451    {
    452        this.thundering = par1;
    453    }
    454
    455    /**
    456     * Returns the number of ticks until next thunderbolt.
    457     */
    458    public int getThunderTime()
    459    {
    460        return this.thunderTime;
    461    }
    462
    463    /**
    464     * Defines the number of ticks until next thunderbolt.
    465     */
    466    public void setThunderTime(int par1)
    467    {
    468        this.thunderTime = par1;
    469    }
    470
    471    /**
    472     * Returns true if it is raining, false otherwise.
    473     */
    474    public boolean isRaining()
    475    {
    476        return this.raining;
    477    }
    478
    479    /**
    480     * Sets whether it is raining or not.
    481     */
    482    public void setRaining(boolean par1)
    483    {
    484        this.raining = par1;
    485    }
    486
    487    /**
    488     * Return the number of ticks until rain.
    489     */
    490    public int getRainTime()
    491    {
    492        return this.rainTime;
    493    }
    494
    495    /**
    496     * Sets the number of ticks until rain.
    497     */
    498    public void setRainTime(int par1)
    499    {
    500        this.rainTime = par1;
    501    }
    502
    503    /**
    504     * Gets the GameType.
    505     */
    506    public EnumGameType getGameType()
    507    {
    508        return this.theGameType;
    509    }
    510
    511    /**
    512     * Get whether the map features (e.g. strongholds) generation is enabled or disabled.
    513     */
    514    public boolean isMapFeaturesEnabled()
    515    {
    516        return this.mapFeaturesEnabled;
    517    }
    518
    519    /**
    520     * Sets the GameType.
    521     */
    522    public void setGameType(EnumGameType par1EnumGameType)
    523    {
    524        this.theGameType = par1EnumGameType;
    525    }
    526
    527    /**
    528     * Returns true if hardcore mode is enabled, otherwise false
    529     */
    530    public boolean isHardcoreModeEnabled()
    531    {
    532        return this.hardcore;
    533    }
    534
    535    public WorldType getTerrainType()
    536    {
    537        return this.terrainType;
    538    }
    539
    540    public void setTerrainType(WorldType par1WorldType)
    541    {
    542        this.terrainType = par1WorldType;
    543    }
    544
    545    public String getGeneratorOptions()
    546    {
    547        return this.generatorOptions;
    548    }
    549
    550    /**
    551     * Returns true if commands are allowed on this World.
    552     */
    553    public boolean areCommandsAllowed()
    554    {
    555        return this.allowCommands;
    556    }
    557
    558    /**
    559     * Returns true if the World is initialized.
    560     */
    561    public boolean isInitialized()
    562    {
    563        return this.initialized;
    564    }
    565
    566    /**
    567     * Sets the initialization status of the World.
    568     */
    569    public void setServerInitialized(boolean par1)
    570    {
    571        this.initialized = par1;
    572    }
    573
    574    /**
    575     * Gets the GameRules class Instance.
    576     */
    577    public GameRules getGameRulesInstance()
    578    {
    579        return this.theGameRules;
    580    }
    581
    582    /**
    583     * Adds this WorldInfo instance to the crash report.
    584     */
    585    public void addToCrashReport(CrashReportCategory par1CrashReportCategory)
    586    {
    587        par1CrashReportCategory.addCrashSectionCallable("Level seed", new CallableLevelSeed(this));
    588        par1CrashReportCategory.addCrashSectionCallable("Level generator", new CallableLevelGenerator(this));
    589        par1CrashReportCategory.addCrashSectionCallable("Level generator options", new CallableLevelGeneratorOptions(this));
    590        par1CrashReportCategory.addCrashSectionCallable("Level spawn location", new CallableLevelSpawnLocation(this));
    591        par1CrashReportCategory.addCrashSectionCallable("Level time", new CallableLevelTime(this));
    592        par1CrashReportCategory.addCrashSectionCallable("Level dimension", new CallableLevelDimension(this));
    593        par1CrashReportCategory.addCrashSectionCallable("Level storage version", new CallableLevelStorageVersion(this));
    594        par1CrashReportCategory.addCrashSectionCallable("Level weather", new CallableLevelWeather(this));
    595        par1CrashReportCategory.addCrashSectionCallable("Level game mode", new CallableLevelGamemode(this));
    596    }
    597
    598    /**
    599     * Return the terrain type of a world
    600     */
    601    static WorldType getTerrainTypeOfWorld(WorldInfo par0WorldInfo)
    602    {
    603        return par0WorldInfo.terrainType;
    604    }
    605
    606    /**
    607     * Return the map feautures enabled of a world
    608     */
    609    static boolean getMapFeaturesEnabled(WorldInfo par0WorldInfo)
    610    {
    611        return par0WorldInfo.mapFeaturesEnabled;
    612    }
    613
    614    static String getWorldGeneratorOptions(WorldInfo par0WorldInfo)
    615    {
    616        return par0WorldInfo.generatorOptions;
    617    }
    618
    619    static int getSpawnXCoordinate(WorldInfo par0WorldInfo)
    620    {
    621        return par0WorldInfo.spawnX;
    622    }
    623
    624    static int getSpawnYCoordinate(WorldInfo par0WorldInfo)
    625    {
    626        return par0WorldInfo.spawnY;
    627    }
    628
    629    static int getSpawnZCoordinate(WorldInfo par0WorldInfo)
    630    {
    631        return par0WorldInfo.spawnZ;
    632    }
    633
    634    static long func_85126_g(WorldInfo par0WorldInfo)
    635    {
    636        return par0WorldInfo.totalTime;
    637    }
    638
    639    static long getWorldTime(WorldInfo par0WorldInfo)
    640    {
    641        return par0WorldInfo.worldTime;
    642    }
    643
    644    static int func_85122_i(WorldInfo par0WorldInfo)
    645    {
    646        return par0WorldInfo.dimension;
    647    }
    648
    649    static int getSaveVersion(WorldInfo par0WorldInfo)
    650    {
    651        return par0WorldInfo.saveVersion;
    652    }
    653
    654    static int getRainTime(WorldInfo par0WorldInfo)
    655    {
    656        return par0WorldInfo.rainTime;
    657    }
    658
    659    /**
    660     * Returns wether it's raining or not.
    661     */
    662    static boolean getRaining(WorldInfo par0WorldInfo)
    663    {
    664        return par0WorldInfo.raining;
    665    }
    666
    667    static int getThunderTime(WorldInfo par0WorldInfo)
    668    {
    669        return par0WorldInfo.thunderTime;
    670    }
    671
    672    /**
    673     * Returns wether it's thundering or not.
    674     */
    675    static boolean getThundering(WorldInfo par0WorldInfo)
    676    {
    677        return par0WorldInfo.thundering;
    678    }
    679
    680    static EnumGameType getGameType(WorldInfo par0WorldInfo)
    681    {
    682        return par0WorldInfo.theGameType;
    683    }
    684
    685    static boolean func_85117_p(WorldInfo par0WorldInfo)
    686    {
    687        return par0WorldInfo.hardcore;
    688    }
    689
    690    static boolean func_85131_q(WorldInfo par0WorldInfo)
    691    {
    692        return par0WorldInfo.allowCommands;
    693    }
    694
    695    /**
    696     * Allow access to additional mod specific world based properties
    697     * Used by FML to store mod list associated with a world, and maybe an id map
    698     * Used by Forge to store the dimensions available to a world
    699     * @param additionalProperties
    700     */
    701    public void setAdditionalProperties(Map<String,NBTBase> additionalProperties)
    702    {
    703        // one time set for this
    704        if (this.additionalProperties == null)
    705        {
    706            this.additionalProperties = additionalProperties;
    707        }
    708    }
    709
    710    public NBTBase getAdditionalProperty(String additionalProperty)
    711    {
    712        return this.additionalProperties!=null? this.additionalProperties.get(additionalProperty) : null;
    713    }
    714}