Package com.bergerkiller.bukkit.mw

Source Code of com.bergerkiller.bukkit.mw.WorldConfig

package com.bergerkiller.bukkit.mw;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Difficulty;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.Plugin;

import com.bergerkiller.bukkit.common.config.ConfigurationNode;
import com.bergerkiller.bukkit.common.nbt.CommonTagCompound;
import com.bergerkiller.bukkit.common.utils.CommonUtil;
import com.bergerkiller.bukkit.common.utils.LogicUtil;
import com.bergerkiller.bukkit.common.utils.MaterialUtil;
import com.bergerkiller.bukkit.common.utils.ParseUtil;
import com.bergerkiller.bukkit.common.utils.StreamUtil;
import com.bergerkiller.bukkit.common.utils.WorldUtil;
import com.bergerkiller.bukkit.mw.external.MultiverseHandler;

public class WorldConfig extends WorldConfigStore {
  public String worldname;
  public boolean keepSpawnInMemory = true;
  public WorldMode worldmode = WorldMode.NORMAL;
  private String chunkGeneratorName;
  public Difficulty difficulty = Difficulty.NORMAL;
  public Position spawnPoint;
  public GameMode gameMode = null;
  public boolean holdWeather = false;
  public boolean pvp = true;
  public final SpawnControl spawnControl = new SpawnControl();
  public final TimeControl timeControl = new TimeControl(this);
  private String defaultNetherPortal;
  private String defaultEnderPortal;
  public List<String> OPlist = new ArrayList<String>();
  public boolean allowHunger = true;
  public boolean autosave = true;
  public boolean reloadWhenEmpty = false;
  public boolean formSnow = true;
  public boolean formIce = true;
  public boolean clearInventory = false;
  public boolean forcedRespawn = false;
  public boolean rememberLastPlayerPosition = false;
  public WorldInventory inventory;

  protected WorldConfig(String worldname) {
    this.worldname = worldname;
  }

  /**
   * Resets all settings in this World Configuration to the defaults.
   * This method acts as if the world is loaded again for the first time.
   */
  public void reset() {
    // Try to import from other World Management plugins
    if (!MyWorlds.importFromMultiVerse || !MultiverseHandler.readWorldConfiguration(this)) {
      // Not imported, (try to) load from the default world configuration
      ConfigurationNode defaultsConfig = getDefaultProperties();
      if (defaultsConfig != null) {
        // Load using a clone to prevent altering the original
        this.load(defaultsConfig);
        if (defaultsConfig.contains(this.worldmode.getName())) {
          this.load(defaultsConfig.getNode(this.worldmode.getName()));
        }
      }
    }

    // Refresh
    World world = getWorld();
    if (world != null) {
      updateAll(world);
    }
  }

  /**
   * Loads the default settings for a world.
   * This method expects the world to be registered in the mapping prior.
   */
  protected void loadDefaults() {
    World world = this.getWorld();
    if (world != null) {
      // Read from the loaded world directly
      this.keepSpawnInMemory = world.getKeepSpawnInMemory();
      this.worldmode = WorldMode.get(world);
      this.difficulty = world.getDifficulty();
      this.spawnPoint = new Position(world.getSpawnLocation());
      this.pvp = world.getPVP();
      this.autosave = world.isAutoSave();
      this.getChunkGeneratorName();
    } else {
      this.worldmode = WorldMode.get(worldname);
      this.spawnPoint = new Position(worldname, 0, 128, 0);
      if (WorldManager.worldExists(this.worldname)) {
        // Open up the level.dat of the World and read the settings from it
        CommonTagCompound data = this.getData();
        if (data != null) {
          // Read the settings from it
          this.spawnPoint.setX(data.getValue("SpawnX", this.spawnPoint.getBlockX()));
          this.spawnPoint.setY(data.getValue("SpawnY", this.spawnPoint.getBlockY()));
          this.spawnPoint.setZ(data.getValue("SpawnZ", this.spawnPoint.getBlockZ()));
        }
        // Figure out the world mode by inspecting the region files in the world
        // On failure, it will resort to using the world name to figure it out
        File regions = this.getRegionFolder();
        if (regions != null && regions.isDirectory()) {
          // Skip the 'region' folder found in the dimension folder
          regions = regions.getParentFile();
          // Find out what name the current folder is
          // If this is DIM1 or DIM-1 then it is the_end/nether
          // Otherwise we will resort to using the world name
          String dimName = regions.getName();
          if (dimName.equals("DIM1")) {
            this.worldmode = WorldMode.THE_END;
          } else if (dimName.equals("DIM-1")) {
            this.worldmode = WorldMode.NETHER;
          }
        }
      }
    }
    if (MyWorlds.useWorldOperators) {
      for (OfflinePlayer op : Bukkit.getServer().getOperators()) {
        this.OPlist.add(op.getName());
      }
    }
    this.inventory = WorldInventory.create(this.worldname);
  }
 
  /**
   * Sets the generator name and arguments for this World.
   * Note that this does not alter the generator for a possible loaded world.
   * Only after re-loading does this take effect.
   *
   * @param name to set to
   */
  public void setChunkGeneratorName(String name) {
    this.chunkGeneratorName = name;
  }

  /**
   * Gets the generator name and arguments of this World
   *
   * @return Chunk Generator name and arguments
   */
  public String getChunkGeneratorName() {
    if (this.chunkGeneratorName == null) {
      World world = this.getWorld();
      if (world != null) {
        ChunkGenerator gen = world.getGenerator();
        if (gen != null) {
          Plugin genPlugin = CommonUtil.getPluginByClass(gen.getClass());
          if (genPlugin != null) {
            this.chunkGeneratorName = genPlugin.getName();
          }
        }
      }
    }
    return this.chunkGeneratorName;
  }

  /**
   * Loads all settings of a world over from another world configuration.
   * This method can be called Async and does not update the settings on any
   * loaded worlds.
   *
   * @param config to load from
   */
  public void load(WorldConfig config) {
    this.keepSpawnInMemory = config.keepSpawnInMemory;
    this.worldmode = config.worldmode;
    this.chunkGeneratorName = config.chunkGeneratorName;
    this.difficulty = config.difficulty;
    this.spawnPoint = config.spawnPoint.clone();
    this.gameMode = config.gameMode;
    this.allowHunger = config.allowHunger;
    this.holdWeather = config.holdWeather;
    this.pvp = config.pvp;
    this.spawnControl.deniedCreatures.clear();
    this.spawnControl.deniedCreatures.addAll(config.spawnControl.deniedCreatures);
    this.timeControl.setLocking(config.timeControl.isLocked());
    this.timeControl.setTime(timeControl.getTime());
    this.autosave = config.autosave;
    this.reloadWhenEmpty = config.reloadWhenEmpty;
    this.formSnow = config.formSnow;
    this.formIce = config.formIce;
    this.clearInventory = config.clearInventory;
    this.forcedRespawn = config.forcedRespawn;
    this.inventory = config.inventory.add(this.worldname);
  }

  public void load(ConfigurationNode node) {
    this.keepSpawnInMemory = node.get("keepSpawnLoaded", this.keepSpawnInMemory);
    this.worldmode = WorldMode.get(node.get("environment", this.worldmode.getName()));
    this.chunkGeneratorName = node.get("chunkGenerator", String.class, this.chunkGeneratorName);
    if (LogicUtil.nullOrEmpty(this.chunkGeneratorName)) {
      this.chunkGeneratorName = null;
    }
    this.difficulty = node.get("difficulty", Difficulty.class, this.difficulty);
    this.gameMode = node.get("gamemode", GameMode.class, this.gameMode);
    this.clearInventory = node.get("clearInventory", this.clearInventory);
    String worldspawn = node.get("spawn.world", String.class);
    if (worldspawn != null) {
      double x = node.get("spawn.x", 0.0);
      double y = node.get("spawn.y", 64.0);
      double z = node.get("spawn.z", 0.0);
      double yaw = node.get("spawn.yaw", 0.0);
      double pitch = node.get("spawn.pitch", 0.0);
      this.spawnPoint = new Position(worldspawn, x, y, z, (float) yaw, (float) pitch);
    }
    this.holdWeather = node.get("holdWeather", this.holdWeather);
    this.formIce = node.get("formIce", this.formIce);
    this.formSnow = node.get("formSnow", this.formSnow);
    this.pvp = node.get("pvp", this.pvp);
    this.forcedRespawn = node.get("forcedRespawn", this.forcedRespawn);
    this.allowHunger = node.get("hunger", this.allowHunger);
    this.rememberLastPlayerPosition = node.get("rememberlastplayerpos", this.rememberLastPlayerPosition);
    this.reloadWhenEmpty = node.get("reloadWhenEmpty", this.reloadWhenEmpty);
    for (String type : node.getList("deniedCreatures", String.class)) {
      type = type.toUpperCase();
      if (type.equals("ANIMALS")) {
        this.spawnControl.setAnimals(true);
      } else if (type.equals("MONSTERS")) {
        this.spawnControl.setMonsters(true);
      } else {
        EntityType t = ParseUtil.parseEnum(EntityType.class, type, null);
        if (t != null) {
          this.spawnControl.deniedCreatures.add(t);
        }
      }
    }
      long time = node.get("lockedtime", Integer.MIN_VALUE);
      if (time != Integer.MIN_VALUE) {
      this.timeControl.setTime(time);
      this.timeControl.setLocking(true);
      }
    this.defaultNetherPortal = node.get("defaultNetherPortal", String.class, this.defaultNetherPortal);
    this.defaultEnderPortal = node.get("defaultEndPortal", String.class, this.defaultEnderPortal);
      if (node.contains("defaultPortal")) {
        // Compatibility mode
        this.defaultNetherPortal = node.get("defaultPortal", String.class, this.defaultNetherPortal);
        node.set("defaultPortal", null);
      }
      this.OPlist = node.getList("operators", String.class, this.OPlist);
  }

  public void saveDefault(ConfigurationNode node) {
    save(node);
    // Remove nodes we rather not see
    node.remove("environment");
    node.remove("name");
    node.remove("chunkGenerator");
    node.remove("spawn");
    node.remove("loaded");
  }

  public void save(ConfigurationNode node) {
    //Set if the world can be directly accessed
    World w = this.getWorld();
    if (w != null) {
          this.difficulty = w.getDifficulty();
          this.keepSpawnInMemory = w.getKeepSpawnInMemory();
          this.autosave = w.isAutoSave();
    }
    if (this.worldname == null || this.worldname.equals(this.getConfigName())) {
      node.remove("name");
    } else {
      node.set("name", this.worldname);
    }
    node.set("loaded", w != null);
    node.set("keepSpawnLoaded", this.keepSpawnInMemory);
    node.set("environment", this.worldmode.getName());
    node.set("chunkGenerator", LogicUtil.fixNull(this.getChunkGeneratorName(), ""));
    node.set("clearInventory", this.clearInventory ? true : null);
    node.set("gamemode", this.gameMode == null ? "NONE" : this.gameMode.toString());

    if (this.timeControl.isLocked()) {
      node.set("lockedtime", this.timeControl.getTime());
    } else {
      node.remove("lockedtime");
    }

    ArrayList<String> creatures = new ArrayList<String>();
    for (EntityType type : this.spawnControl.deniedCreatures) {
      creatures.add(type.name());
    }
    node.set("forcedRespawn", this.forcedRespawn);
    node.set("rememberlastplayerpos", this.rememberLastPlayerPosition);
    node.set("pvp", this.pvp);
    node.set("defaultNetherPortal", this.defaultNetherPortal);
    node.set("defaultEndPortal", this.defaultEnderPortal);
    node.set("operators", this.OPlist);
    node.set("deniedCreatures", creatures);
    node.set("holdWeather", this.holdWeather);
    node.set("hunger", this.allowHunger);
    node.set("formIce", this.formIce);
    node.set("formSnow", this.formSnow);
    node.set("difficulty", this.difficulty == null ? "NONE" : this.difficulty.toString());
    node.set("reloadWhenEmpty", this.reloadWhenEmpty);
    if (this.spawnPoint == null) {
      node.remove("spawn");
    } else {
      node.set("spawn.world", this.spawnPoint.getWorldName());
      node.set("spawn.x", this.spawnPoint.getX());
      node.set("spawn.y", this.spawnPoint.getY());
      node.set("spawn.z", this.spawnPoint.getZ());
      node.set("spawn.yaw", (double) this.spawnPoint.getYaw());
      node.set("spawn.pitch", (double) this.spawnPoint.getPitch());
    }
  }

  /**
   * Regenerates the spawn point for a world if it is not properly set<br>
   * Also updates the spawn position in the world configuration
   */
  public void fixSpawnLocation() {
    // Obtain the configuration and the set spawn position from it
    World world = spawnPoint.getWorld();
    if (world != null) {
      // Obtain a new safe position to spawn at
      spawnPoint = new Position(WorldManager.getSafeSpawn(spawnPoint));

      // Apply position to the world if same world
      if (!isOtherWorldSpawn()) {
        world.setSpawnLocation(spawnPoint.getBlockX(), spawnPoint.getBlockY(), spawnPoint.getBlockZ());
      }
    }
  }

  public boolean isOtherWorldSpawn() {
    return !spawnPoint.getWorldName().equalsIgnoreCase(worldname);
  }

  /**
   * Gets the name of the destination default nether portals teleport to on this World.
   * If this returns null, then none is known at this time, indicating that it can be
   * automatically set. If this returns an empty String, it indicates the user forcibly
   * requested no destination and no automatic detection will be attempted.
   *
   * @return Default nether portal destination name
   */
  public String getNetherPortal() {
    return this.defaultNetherPortal;
  }

  public void setNetherPortal(String destination) {
    this.defaultNetherPortal = destination;
  }

  /**
   * Gets the name of the destination default ender portals teleport to on this World.
   * If this returns null, then none is known at this time, indicating that it can be
   * automatically set. If this returns an empty String, it indicates the user forcibly
   * requested no destination and no automatic detection will be attempted.
   *
   * @return Default ender portal destination name
   */
  public String getEnderPortal() {
    return this.defaultEnderPortal;
  }

  public void setEnderPortal(String destination) {
    this.defaultEnderPortal = destination;
  }

  /**
   * Fired right before a player respawns.
   * Note that no leave is fired after this event.
   * It is a replacement for leaving a world (if that is the case)
   *
   * @param player that respawns
   */
  public void onRespawn(Player player, Location respawnLocation) {
    MyWorlds.plugin.getPlayerDataController().onRespawnSave(player, respawnLocation);
  }

  /**
   * Fired when a player leaves this world
   *
   * @param player that is about to leave this world
   * @param quit state: True if the player left the server, False if not
   */
  public void onPlayerLeave(Player player, boolean quit) {
    // If not quiting (it saves then anyhow!) save the old information
    if (!quit) {
      CommonUtil.savePlayer(player);
    }
  }

  /**
   * Fired when a player left this world and already joined another world.
   * If the old player position, inventory and etc. is important, add the logic in
   * {@link #onPlayerLeave(Player, boolean)} instead.
   *
   * @param player that left this world (may no longer contain valid information)
   */
  public void onPlayerLeft(Player player) {
    this.updateReload();
  }

  /**
   * Fired when a player joined this world
   *
   * @param player that just entered this world
   */
  public void onPlayerEnter(Player player) {
    // Apply world-specific settings
    updateOP(player);
    updateGamemode(player);
    updateHunger(player);
    // Refresh states based on the new world the player joined
    MWPlayerDataController.refreshState(player);
  }

  public void onWorldLoad(World world) {
    // Update settings
    updateAll(world);
    // Detect default portals
    tryCreatePortalLink();
  }

  public void onWorldUnload(World world) {
    // If the actual World spawnpoint changed, be sure to update accordingly
    if (!isOtherWorldSpawn()) {
      Location spawn = world.getSpawnLocation();
      if (spawnPoint.getBlockX() != spawn.getBlockX() || spawnPoint.getBlockY() != spawn.getBlockY()
          || spawnPoint.getBlockZ() != spawn.getBlockZ()) {
        spawnPoint = new Position(spawn);
      }
    }

    // Disable time control
    timeControl.updateWorld(null);
  }

  public World loadWorld() {
    if (WorldManager.worldExists(this.worldname)) {
      World w = WorldManager.getOrCreateWorld(this.worldname);
      if (w == null) {
        MyWorlds.plugin.log(Level.SEVERE, "Failed to (pre)load world: " + worldname);
      } else {
        return w;
      }
    } else {
      MyWorlds.plugin.log(Level.WARNING, "World: " + worldname + " could not be loaded because it no longer exists!");
    }
    return null;
  }
  public boolean unloadWorld() {
    return WorldManager.unload(this.getWorld());
  }

  /**
   * Updates all components of this World Configuration to the loaded world specified
   *
   * @param world to apply it to
   */
  public void updateAll(World world) {
    // Fix spawn point if needed
    if (MaterialUtil.SUFFOCATES.get(this.spawnPoint.getBlock())) {
      this.fixSpawnLocation();
    } else if (!isOtherWorldSpawn()) {
      world.setSpawnLocation(this.spawnPoint.getBlockX(), this.spawnPoint.getBlockY(), this.spawnPoint.getBlockZ());
    }
    // Update world settings
    updatePVP(world);
    updateKeepSpawnInMemory(world);
    updateDifficulty(world);
    updateAutoSave(world);
    timeControl.updateWorld(world);
  }
  public void updateReload() {
    World world = this.getWorld();
    if (world == null) return;
    if (!this.reloadWhenEmpty) return;
    if (world.getPlayers().size() > 0) return;
    //reload world
    MyWorlds.plugin.log(Level.INFO, "Reloading world '" + worldname + "' - world became empty");
    if (!this.unloadWorld()) {
      MyWorlds.plugin.log(Level.WARNING, "Failed to unload world: " + worldname + " for reload purposes");
    } else if (this.loadWorld() == null) {
      MyWorlds.plugin.log(Level.WARNING, "Failed to load world: " + worldname + " for reload purposes");
    } else {
      MyWorlds.plugin.log(Level.INFO, "World reloaded successfully");
    }
  }
  public void updateAutoSave(World world) {
    if (world != null && world.isAutoSave() != this.autosave) {
      world.setAutoSave(this.autosave);
    }
  }
  public void updateOP(Player player) {
    if (MyWorlds.useWorldOperators) {
      boolean op = this.isOP(player);
      if (op != player.isOp()) {
        player.setOp(op);
        if (op) {
          player.sendMessage(ChatColor.YELLOW + "You are now op!");
        } else {
          player.sendMessage(ChatColor.RED + "You are no longer op!");
        }
      }
    }
  }
  public void updateOP(World world) {
    if (MyWorlds.useWorldOperators) {
      for (Player p : world.getPlayers()) updateOP(p);
    }
  }
  public void updateHunger(Player player) {
    if (!allowHunger) {
      player.setFoodLevel(20);
    }
  }
  public void updateHunger(World world) {
    for (Player player : WorldUtil.getPlayers(world)) {
      updateHunger(player);
    }
  }
  public void updateGamemode(Player player) {
    if (this.gameMode != null && !Permission.GENERAL_IGNOREGM.has(player)) {
      player.setGameMode(this.gameMode);
    }
  }
  public void updatePVP(World world) {
    if (world != null && this.pvp != world.getPVP()) {
      world.setPVP(this.pvp);
    }
  }
  public void updateKeepSpawnInMemory(World world) {
    if (world != null && world.getKeepSpawnInMemory() != this.keepSpawnInMemory) {
      world.setKeepSpawnInMemory(this.keepSpawnInMemory);
    }
  }
  public void updateDifficulty(World world) {
    if (world != null && world.getDifficulty() != this.difficulty) {
      world.setDifficulty(this.difficulty);
    }
  }

  /**
   * Gets a safe configuration name for this World Configuration<br>
   * Unsafe characters, such as dots, are replaced
   *
   * @return Safe config world name
   */
  public String getConfigName() {
    if (this.worldname == null) {
      return "";
    }
    return this.worldname.replace('.', '_').replace(':', '_');
  }

  /**
   * Gets the loaded World of this world configuration<br>
   * If the world is not loaded, null is returned
   *
   * @return the World
   */
  public World getWorld() {
    return this.worldname == null ? null : WorldManager.getWorld(this.worldname);
  }

  public boolean isOP(Player player) {
    for (String playername : OPlist) {
      if (playername.equals("\\*")) return true;
      if (player.getName().equalsIgnoreCase(playername)) return true;
    }
    return false;
  }
  public void setGameMode(GameMode mode) {
    if (this.gameMode != mode) {
      this.gameMode = mode;
      if (mode != null) {
        World world = this.getWorld();
        if (world != null) {
          for (Player p : world.getPlayers()) {
            this.updateGamemode(p);
          }
        }
      }
    }
  }

  /**
   * Tries to create a portal link with another world currently available.
   *
   * @see #tryCreatePortalLink(WorldConfig, WorldConfig)
   */
  public void tryCreatePortalLink() {
    // Try to detect a possible portal link between worlds
    for (WorldConfig otherConfig : WorldConfig.all()) {
      if (otherConfig != this) {
        WorldConfig.tryCreatePortalLink(this, otherConfig);
      }
    }
  }

  /**
   * Tries to create a default portal link if none is currently set between two worlds
   * Only if the worlds match names and no portal is set will this create a link.
   *
   * @param world1
   * @param world1
   */
  public static void tryCreatePortalLink(WorldConfig world1, WorldConfig world2) {
    // Name compatibility check
    if (!world1.getRawWorldName().equals(world2.getRawWorldName())) {
      return;
    }
    // If same environment, directly stop it here
    if (world1.worldmode == world2.worldmode) {
      return;
    }
    // Default nether portal check and detection
    if (world1.defaultNetherPortal == null && world2.defaultEnderPortal == null) {
      // Try to create a link with the nether portals
      if ((world1.worldmode == WorldMode.NETHER && world2.worldmode == WorldMode.NORMAL) ||
          (world2.worldmode == WorldMode.NETHER && world1.worldmode == WorldMode.NORMAL)) {
        // Nether link detected!
        world1.defaultNetherPortal = world2.worldname;
        world2.defaultNetherPortal = world1.worldname;
        MyWorlds.plugin.log(Level.INFO, "Created nether portal link between worlds '" + world1.worldname + "' and '" + world2.worldname + "'!");
      }
    }
    // Default ender portal check and detection
    if (world1.defaultEnderPortal == null && world2.defaultEnderPortal == null) {
      // Try to create a link with the nether portals
      if ((world1.worldmode == WorldMode.THE_END && world2.worldmode == WorldMode.NORMAL) ||
          (world2.worldmode == WorldMode.THE_END && world1.worldmode == WorldMode.NORMAL)) {
        // Nether link detected!
        world1.defaultEnderPortal = world2.worldname;
        world2.defaultEnderPortal = world1.worldname;
        MyWorlds.plugin.log(Level.INFO, "Created ender portal link between worlds '" + world1.worldname + "' and '" + world2.worldname + "'!");
      }
    }
  }

  /**
   * Gets the World Name of this World excluding any _nether, _the_end or DIM extensions from the name.
   * Returns an empty String if the world name equals DIM1 or DIM-1 (for MCPC+ server).
   * In all cases, a lower-cased world name is returned.
   *
   * @return Raw world name
   */
  private String getRawWorldName() {
    String lower = this.worldname.toLowerCase();
    if (lower.endsWith("_nether")) {
      return lower.substring(0, lower.length() - 7);
    }
    if (lower.endsWith("_the_end")) {
      return lower.substring(0, lower.length() - 8);
    }
    if (lower.equals("dim1") || lower.equals("dim-1")) {
      return "";
    }
    return lower;
  }

  /**
   * Gets the File folder where the data of this World is stored
   *
   * @return World Folder
   */
  public File getWorldFolder() {
    return WorldUtil.getWorldFolder(this.worldname);
  }

  /**
   * Gets the File folder where player data of this World is saved
   *
   * @return Player data folder
   */
  public File getPlayerFolder() {
    World world = getWorld();
    if (world == null) {
      return new File(getWorldFolder(), "playerdata");
    } else {
      return WorldUtil.getPlayersFolder(world);
    }
  }

  /**
   * Gets the File where player data for this world could be saved
   *
   * @param playerName (case-sensitive)
   * @param mkDir - True to create the player folder
   * @return Player Data File
   */
  public File getPlayerData(String playerName) {
    return new File(getPlayerFolder(), playerName + ".dat");
  }

  /**
   * Gets the File Location where the regions of this world are contained
   *
   * @return Region Folder
   */
  public File getRegionFolder() {
    return WorldUtil.getWorldRegionFolder(this.worldname);
  }

  /**
   * Gets the File pointing to the level.dat of the world
   *
   * @return Data File
   */
  public File getDataFile() {
    return new File(getWorldFolder(), "level.dat");
  }

  /**
   * Gets the File pointing to the uid.dat of the world
   *
   * @return UID File
   */
  public File getUIDFile() {
    return new File(getWorldFolder(), "uid.dat");
  }

  /**
   * Gets the amount of bytes of data stored on disk about this World
   *
   * @return World file size
   */
  public long getWorldSize() {
    return Util.getFileSize(getWorldFolder());
  }

  /**
   * Creates a new Data compound for this World, storing the default values
   *
   * @param seed to use
   * @return Data compound
   */
  public CommonTagCompound createData(long seed) {
    CommonTagCompound data = new CommonTagCompound();
    data.putValue("thundering", (byte) 0);
    data.putValue("thundering", (byte) 0);
    data.putValue("LastPlayed", System.currentTimeMillis());
    data.putValue("RandomSeed", seed);
    data.putValue("version", (int) 19133);
    data.putValue("initialized", (byte) 0); // Spawn point needs to be re-initialized, etc.
    data.putValue("Time", 0L);
    data.putValue("raining", (byte) 0);
    data.putValue("SpawnX", 0);
    data.putValue("thunderTime", (int) 200000000);
    data.putValue("SpawnY", 64);
    data.putValue("SpawnZ", 0);
    data.putValue("LevelName", worldname);
    data.putValue("SizeOnDisk", getWorldSize());
    data.putValue("rainTime", (int) 50000);
    return data;
  }

  /**
   * Gets the Data compound stored for this World
   *
   * @return World Data
   */
  public CommonTagCompound getData() {
    File f = getDataFile();
    if (!f.exists()) {
      return null;
    }
    try {
      CommonTagCompound root = CommonTagCompound.readFrom(f);
      if (root != null) {
        return root.get("Data", CommonTagCompound.class);
      } else {
        return null;
      }
    } catch (Exception ex) {
      return null;
    }
  }

  /**
   * Sets the Data compound stored by this world
   *
   * @param data to set to
   * @return True if successful, False if not
   */
  public boolean setData(CommonTagCompound data) {
      try {
      CommonTagCompound root = new CommonTagCompound();
      root.put("Data", data);
      FileOutputStream out = StreamUtil.createOutputStream(getDataFile());
      try {
        root.writeTo(out);
      } finally {
        out.close();
      }
      return true;
    } catch (IOException e) {
      e.printStackTrace();
      return false;
    }
  }

  /**
   * Recreates the data file of a world
   *
   * @param seed to store in the new data file
   * @return True if successful, False if not
   */
  public boolean resetData(String seed) {
    return resetData(WorldManager.getRandomSeed(seed));
  }

  /**
   * Recreates the data file of a world
   *
   * @param seed to store in the new data file
   * @return True if successful, False if not
   */
  public boolean resetData(long seed) {
      return setData(createData(seed));
  }

  /**
   * Reads the WorldInfo structure from this World
   *
   * @return WorldInfo structure
   */
  public WorldInfo getInfo() {
    WorldInfo info = null;
    try {
      CommonTagCompound t = getData();
      if (t != null) {
        info = new WorldInfo();
        info.seed = t.getValue("RandomSeed", 0L);
        info.time = t.getValue("Time", 0L);
        info.raining = t.getValue("raining", (byte) 0) != 0;
            info.thundering = t.getValue("thundering", (byte) 0) != 0;
      }
    } catch (Exception ex) {}
    World w = getWorld();
    if (w != null) {
      if (info == null) {
        info = new WorldInfo();
      }
      info.seed = w.getSeed();
      info.time = w.getFullTime();
      info.raining = w.hasStorm();
          info.thundering = w.isThundering();
    }
    if (info != null && MyWorlds.calculateWorldSize) {
      info.size = getWorldSize();
    }
    return info;
  }

  /**
   * Gets whether this World exists on disk at all.
   * If this is not the case, this configuration is either temporary or invalid.
   * Non-existing World Configurations will automatically get purged upon saving.
   *
   * @return True if existing, False if not
   */
  public boolean isExisting() {
    return WorldManager.worldExists(this.worldname);
  }

  /**
   * Gets whether this World is currently loaded
   *
   * @return True if loaded, False if not
   */
  public boolean isLoaded() {
    return getWorld() != null;
  }

  /**
   * Gets whether this World is broken (and needs repairs to properly load)
   *
   * @return True if broken, False if not
   */
  public boolean isBroken() {
    return getData() == null && !isLoaded();
  }

  /**
   * Gets whether the world data of this World has been initialized.
   * If not initialized, then the spawn position needs to be calculated, among other things.
   *
   * @return True if initialized, False if not
   */
  public boolean isInitialized() {
    CommonTagCompound data = getData();
    return data != null && data.getValue("initialized", true);
  }

  /**
   * Copies this World and all of it's set configuration to a new world under a new name.
   * The World Configuration must be gotten prior as to support Async operations.
   *
   * @param newWorldConfig for the world to copy to
   * @return True if successful, False if the operation (partially) failed
   */
  public boolean copyTo(WorldConfig newWorldConfig) {
    // If new world name is already occupied - abort
    if (WorldManager.worldExists(newWorldConfig.worldname)) {
      return false;
    }

    // Copy the world folder over
    if (!StreamUtil.tryCopyFile(this.getWorldFolder(), newWorldConfig.getWorldFolder())) {
      return false;
    }

    // Take over the world configuration
    newWorldConfig.load(this);

    // Delete the UID file, as the new world is unique (forces regeneration)
    File uid = newWorldConfig.getUIDFile();
    if (uid.exists()) {
      uid.delete();
    }

    // Update the name set in the level.dat for the new world
    CommonTagCompound data = newWorldConfig.getData();
    if (data != null) {
      data.putValue("LevelName", newWorldConfig.worldname);
      newWorldConfig.setData(data);
    }
    return true;
  }

  /**
   * Deletes this world from disk and removes all configuration associated with it
   *
   * @return True if successful, False if not
   */
  public boolean deleteWorld() {
    if (this.isLoaded()) {
      return false;
    }
    File worldFolder = this.getWorldFolder();
    WorldConfig.remove(this.worldname);
    return StreamUtil.deleteFile(worldFolder).isEmpty();
  }
}
TOP

Related Classes of com.bergerkiller.bukkit.mw.WorldConfig

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.