package net.shockverse.survivalgames; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.util.*; import net.lingala.zip4j.core.ZipFile; import net.lingala.zip4j.model.ZipParameters; import net.lingala.zip4j.progress.ProgressMonitor; import net.minecraft.util.org.apache.commons.io.FileUtils; import net.minecraft.util.org.apache.commons.lang3.tuple.Pair; import net.shockverse.survivalgames.core.*; import net.shockverse.survivalgames.data.ArenaData; import net.shockverse.survivalgames.data.ContainerData; import net.shockverse.survivalgames.data.RewardData; import net.shockverse.survivalgames.exceptions.PropertyException; import net.shockverse.survivalgames.extras.GameTask; import net.shockverse.survivalgames.extras.PropertyEntry; import net.shockverse.survivalgames.extras.PropertyFile; import net.shockverse.survivalgames.extras.PropertyList; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.world.WorldUnloadEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; /** * @description Handles property files * @author LegitModern, Tagette */ public class ArenaManager extends HashMap<String, ArenaData> { private SurvivalGames plugin; private String arenaConfig = "Arenas"; private String rewardsConfig = "Rewards"; private String spawnsConfig = "Spawns"; private String blockConfig = "Blocks"; private Settings settings; private PropertyFile arenaFile; private HashMap<String, PropertyFile> spawnFiles; private HashMap<String, PropertyFile> rewardFiles; private HashMap<String, PropertyFile> blockFiles; private ArenaData lobby; private VoteManager voteMan; private String WORLD; private String LASTWORLD; private String NEXTWORLD; public List<String> arenaOrder; public HashMap<Block, Inventory> lootedContainers; private HashMap<String, String> editors; private HashMap<String, ProgressMonitor> progressMonitors; public ArenaManager(SurvivalGames instance, String arenaConfig, String rewardsConfig, String spawnsConfig) { plugin = instance; this.settings = plugin.getSettings(); this.arenaConfig = arenaConfig; this.rewardsConfig = rewardsConfig; this.spawnsConfig = spawnsConfig; spawnFiles = new HashMap<String, PropertyFile>(); rewardFiles = new HashMap<String, PropertyFile>(); blockFiles = new HashMap<String, PropertyFile>(); arenaOrder = new ArrayList<String>(); lootedContainers = new HashMap<Block, Inventory>(); editors = new HashMap<String, String>(); progressMonitors = new HashMap<String, ProgressMonitor>(); voteMan = new VoteManager(); } public void disable(){ this.clear(); arenaOrder.clear(); voteMan.clear(); lootedContainers.clear(); editors.clear(); } public void load() { if (!plugin.getDataFolder().exists()) { plugin.getDataFolder().mkdirs(); } // Dont know why but needed to repeat.. if (!plugin.getDataFolder().exists()) { plugin.getDataFolder().mkdirs(); } try { File configFile = new File(plugin.getDataFolder(), arenaConfig + ".cfg"); arenaFile = new PropertyFile(arenaConfig, configFile); arenaFile.loadProperties(); setup(arenaFile.getProperties()); arenaFile.saveProperties(); for(String shortcut : arenaFile.getShortcuts().keySet()) plugin.getDebug().everything(shortcut); if(size() <= 1) Logger.error("No arenas were loaded."); if (!settings.LowDetailMode) { Logger.info("Arena config loaded."); } } catch (PropertyException pe) { Logger.error(pe.getMessage()); } catch(Exception ex) { Logger.error("Could not load " + arenaConfig + ".cfg file."); ex.printStackTrace(); } } private void setup(PropertyList props) { // Declare settings here. Note that if config is not found these values should be placed into a new config file. props.comment("-- Worlds --"); props.newLine(); lobby = new ArenaData(); // Also gets default values. PropertyList lobbyList = props.getList("lobby"); lobby.worldName = lobbyList.getString("worldFolder", "lobby"); if(lobby.worldName.equals("")) lobby.worldName = "lobby"; lobby.enabled = true; lobby.name = Tools.parseColors(lobbyList.getString("lobbyName", "Lobby")); lobby.gameTime = lobbyList.getInt("lobbyTime", 240, "Lobby seconds."); lobby.stateMessageTime = lobbyList.getInt("stateMessageTime", lobby.stateMessageTime, "How often the state message appears."); lobby.adminChat = lobbyList.getString("adminChat", lobby.adminChat, "The format of the chat for admins."); lobby.specChat = lobbyList.getString("spectatorChat", lobby.specChat, "The format of the chat for spectators."); lobby.tributeChat = lobbyList.getString("tributeChat", lobby.tributeChat, "The format of the chat for tributes."); World lobbyWorld = plugin.getServer().getWorld(lobby.worldName); lobby.spectatorSpawn = Tools.getLocation(lobbyWorld, lobbyList.getVector("lobbySpawn", Tools.getVector(lobbyWorld.getSpawnLocation(), false), "The spawn location for the lobby.")); put(lobby.worldName, lobby); loadWorld(lobby.worldName); if(!settings.LowDetailMode) Logger.info(" '" + lobby.name + "' has been loaded."); PropertyList arenaList = props.getList("worlds"); for(PropertyEntry arenaEntry : arenaList.getProperties()) { if(arenaEntry instanceof PropertyList) { // Build world. PropertyList arenaProps = arenaList.getList(arenaEntry.getKey(), "Your world folder name."); ArenaData aData = setupArena(arenaProps, arenaEntry.getKey()); this.put(arenaEntry.getKey(), aData); if(aData.enabled && !settings.LowDetailMode) Logger.info(" Arena '" + aData.name + "' has been loaded."); } } } private ArenaData setupArena(PropertyList arenaProps, String wName) { ArenaData aData = new ArenaData(); // Also gets default values. aData.name = Tools.parseColors(arenaProps.getString("arenaName", aData.name)); aData.enabled = arenaProps.getBoolean("enabled", aData.enabled); aData.worldName = wName; if(aData.enabled) { if(!wName.equals("")) { loadWorld(aData.worldName); // Make sure a zip exists. createWorldZips(wName, false); } } else { Logger.warning("Arena '" + wName + "' is disabled."); } aData.graceTime = arenaProps.getInt("graceTime", aData.graceTime, "Grace period seconds."); aData.gameCountdown = arenaProps.getInt("gameCountdown", aData.gameCountdown, "Countdown seconds before game begins."); aData.gameTime = arenaProps.getInt("gameTime", aData.gameTime, "Game minutes.") * 60; aData.deathMatchCountdown = arenaProps.getInt("deathMatchCountdown", aData.deathMatchCountdown, "Countdown before deathmatch."); aData.deathMatchTime = arenaProps.getInt("deathMatchTime", aData.deathMatchTime, "Death match seconds."); aData.minStartTributes = arenaProps.getInt("minStartTributes", aData.minStartTributes, "The minimum amount of tributes needed to start the game."); aData.minTributes = arenaProps.getInt("minDMTributes", aData.minTributes, "The amount of tributes that need to be left for the deathmatch to start."); aData.winPoints = arenaProps.getInt("winPoints", aData.winPoints); aData.killPoints = arenaProps.getInt("killPoints", aData.killPoints); aData.killPercent = arenaProps.getInt("killPercent", aData.killPercent, "This amount will be rewarded from a player you killed."); aData.moneyMultiplier = arenaProps.getDouble("moneyMultiplier", aData.moneyMultiplier, "When rewarding money, points will be multiplied by this number. 0.0 = disable"); aData.loseMoneyOnDeath = arenaProps.getBoolean("loseMoneyOnDeath", aData.loseMoneyOnDeath, "If true than players will lose money when they die."); aData.worldStartTime = arenaProps.getInt("worldStartTime", aData.worldStartTime, "The world time the game will start at. (In ticks)"); aData.stormy = arenaProps.getBoolean("stormy", aData.stormy, "If true then the world will be stormy."); aData.refillWorldTime = arenaProps.getInt("refillWorldTime", aData.refillWorldTime, "The chests will be refilled after this amount of time. (In ticks)"); aData.refillCount = arenaProps.getInt("refillCount", aData.refillCount, "The number of times the chests will be refilled."); aData.killDMRun = arenaProps.getBoolean("killDMRun", aData.killDMRun, "Kills the tribute when they run away."); aData.dmRange = arenaProps.getDouble("dmRange", aData.dmRange, "The distance in blocks before the player is teleported or killed in deathmatch."); aData.adminChat = arenaProps.getString("adminChat", aData.adminChat, "The format of the chat for admins."); aData.specChat = arenaProps.getString("spectatorChat", aData.specChat, "The format of the chat for spectators."); aData.tributeChat = arenaProps.getString("tributeChat", aData.tributeChat, "The format of the chat for tributes."); aData.arenaDetails = arenaProps.getString("arenaDetails", aData.arenaDetails); aData = loadArenaSpawns(aData); aData = loadArenaRewards(aData); aData = loadArenaWhiteList(aData); return aData; } private ArenaData loadArenaRewards(ArenaData aData) { try { File worldFolder = new File(plugin.getDataFolder().getPath() + "/" + aData.worldName); if(!worldFolder.exists()) { worldFolder.mkdirs(); } if(!worldFolder.exists()) { worldFolder.mkdirs(); } File configFile = new File(plugin.getDataFolder().getPath() + "/" + aData.worldName, rewardsConfig + ".cfg"); rewardFiles.put(aData.worldName, new PropertyFile(aData.worldName + "/" + rewardsConfig, configFile)); rewardFiles.get(aData.worldName).loadProperties(); PropertyList rewardProps = rewardFiles.get(aData.worldName).getProperties(); if (aData.enabled && !settings.LowDetailMode) { Logger.info(" " + aData.worldName + " - loading container rewards..."); } aData = setupArenaRewards(rewardProps, aData); rewardFiles.get(aData.worldName).saveProperties(); for(String shortcut : rewardFiles.get(aData.worldName).getShortcuts().keySet()) plugin.getDebug().everything(shortcut); if (aData.enabled && !settings.LowDetailMode) { Logger.info(" " + aData.containers.size() + " container(s) loaded. (" + rewardsConfig + ".cfg)"); } } catch (PropertyException pe) { if(aData.enabled) Logger.error(pe.getMessage()); } catch(Exception ex) { if(aData.enabled) { Logger.error("Could not load " + aData.worldName + "/" + rewardsConfig + ".cfg file."); ex.printStackTrace(); } } return aData; } private ArenaData setupArenaRewards(PropertyList rewardProps, ArenaData aData) { rewardProps.comment("-- Rewards --"); rewardProps.newLine(); aData.lighterUses = rewardProps.getInt("lighterUses", aData.lighterUses, "The number of uses a lighter has left."); rewardProps.newLine(); PropertyList containerList = rewardProps.getList("containers"); int totalRewards = 0; for(PropertyEntry entry : containerList.getProperties()) { if(entry instanceof PropertyList) { Pair<Material, Byte> matByIdName = Tools.getMatByNameId(entry.getKey()); if(matByIdName != null && matByIdName.getLeft() != null) { ContainerData cData = new ContainerData(); cData.material = matByIdName.getLeft(); cData.data = matByIdName.getRight(); if(cData.material.isBlock()) { PropertyList containerProps = containerList.getList(entry.getKey()); //String[] inherits = Tools.processArray(containerProps.getString("inherit", "")); cData.enabled = containerProps.getBoolean("enabled", cData.enabled); cData.title = containerProps.getString("name", cData.title, "The title that appears for the inventory."); cData.minChestRewards = containerProps.getInt("minChestRewards", cData.minChestRewards, "The min amount of rewards that can be in a chest."); cData.maxChestRewards = containerProps.getInt("maxChestRewards", cData.maxChestRewards, "The max amount of rewards that can be in a chest."); if(!cData.enabled) Logger.warning(" " + cData.material + ":" + cData.data + " - Disabled. (" + rewardsConfig + ".cfg)"); containerProps.comment("Item/Id = rarity x amount (or min, max)"); PropertyList rewardList = containerProps.getList("rewards"); for(PropertyEntry rewardEntry : rewardList.getProperties()) { RewardData reward = new RewardData(); String itemNameId = rewardEntry.getKey(); reward.item = Tools.getMatByNameId(itemNameId).getLeft(); reward.data = Tools.getMatByNameId(itemNameId).getRight(); if(reward.item != null) { String rewardStr = rewardList.getString(rewardEntry.getKey(), "0"); if(rewardStr.contains("x")) { String rarityStr = rewardStr.split("x")[0]; String amountStr = rewardStr.split("x")[1]; if(rarityStr != null && Tools.isInt(rarityStr.trim())) reward.rarity = Integer.parseInt(rarityStr.trim()); if(amountStr != null) { if(amountStr.contains(",")) { String minStr = amountStr.split(",")[0]; String maxStr = amountStr.split(",")[1]; if(minStr != null && Tools.isInt(minStr.trim())) { reward.min = Integer.parseInt(minStr.trim()); } if(maxStr != null && Tools.isInt(maxStr.trim())) { reward.max = Integer.parseInt(maxStr.trim()); } if(minStr == null && maxStr != null) { reward.min = reward.max; } if(minStr != null && maxStr == null) { reward.max = reward.min; } } else if(Tools.isInt(amountStr.trim())) { reward.min = Integer.parseInt(amountStr.trim()); reward.max = reward.min; } } } else if(Tools.isInt(rewardStr)) { reward.rarity = Integer.parseInt(rewardStr.trim()); } if(!cData.rewards.contains(reward)) { cData.rewards.add(reward); totalRewards++; } } else { Logger.warning("Unknown reward type " + rewardEntry.getKey() + " for " + cData.material + ". Ignored."); } } if(!aData.containers.containsKey(cData.material)) { aData.containers.put(cData.material, cData); if (aData.enabled && cData.enabled && !settings.LowDetailMode) { Logger.info(" " + cData.material + ":" + cData.data + " - " + cData.rewards.size() + " reward(s) loaded. (" + rewardsConfig + ".cfg)"); } } } else { Logger.warning("Container type " + entry.getKey() + " is not a block. Ignored."); } } else { Logger.warning("Unkown container type " + entry.getKey() + ". Ignored."); } } if(aData.containers.isEmpty() || totalRewards == 0) { Logger.warning("No rewards have been added to '" + aData.name + "'. Arena disabled."); aData.enabled = false; } } return aData; } private ArenaData loadArenaSpawns(ArenaData aData) { try { File worldFolder = new File(plugin.getDataFolder().getPath() + "/" + aData.worldName); if(!worldFolder.exists()) { worldFolder.mkdirs(); } if(!worldFolder.exists()) { worldFolder.mkdirs(); } File configFile = new File(plugin.getDataFolder().getPath() + "/" + aData.worldName, spawnsConfig + ".cfg"); spawnFiles.put(aData.worldName, new PropertyFile(aData.worldName + "/" + spawnsConfig, configFile)); spawnFiles.get(aData.worldName).loadProperties(); PropertyList spawnProps = spawnFiles.get(aData.worldName).getProperties(); aData = setupArenaSpawns(spawnProps, aData); spawnFiles.get(aData.worldName).saveProperties(); if (aData.enabled && !settings.LowDetailMode) { Logger.info(" " + aData.worldName + " - " + aData.spawns.size() + " spawn locations loaded. (" + spawnsConfig + ".cfg)"); } } catch (PropertyException pe) { if(aData.enabled) Logger.error(pe.getMessage()); } catch(Exception ex) { if(aData.enabled) { Logger.error("Could not load " + aData.worldName + "/" + spawnsConfig + ".cfg file."); ex.printStackTrace(); } } return aData; } private ArenaData setupArenaSpawns(PropertyList spawnProps, ArenaData aData) { World world = plugin.getServer().getWorld(aData.worldName); if(world == null) Logger.info("World is null."); Vector worldSpawnPos = Tools.round(Tools.getVector(world.getSpawnLocation(), false), 2); spawnProps.comment("-- Arena Spawns --"); spawnProps.newLine(); aData.spectatorSpawn = Tools.getLocation(world, spawnProps.getVector("spectatorSpawn", worldSpawnPos)); spawnProps.comment("Orders by the index."); spawnProps.comment("indexNumber = x, y, z"); int index = 0; PropertyList spawnList = spawnProps.getList("spawns"); HashMap<Integer, Location> worldSpawns = new HashMap<Integer, Location>(); for(PropertyEntry spawnEntry : spawnList.getProperties()){ if(Tools.isInt(spawnEntry.getKey())) { index = Integer.parseInt(spawnEntry.getKey()); Location loc = Tools.getLocation(world, spawnList.getVector(spawnEntry.getKey(), new Vector())); worldSpawns.put(index, loc); } } index = 0; // Put the spawns in order. while(!worldSpawns.isEmpty()) { if(worldSpawns.containsKey(index)) { aData.spawns.put(index, worldSpawns.get(index)); worldSpawns.remove(index); } index++; } spawnProps.newLine(); spawnProps.comment("-- Deathmatch Spawns --"); spawnProps.newLine(); aData.dmCenter = Tools.getLocation(world, spawnProps.getVector("dmCenter", worldSpawnPos, "Used in deathmatch to keep players in.")); aData.dmSpectatorSpawn = Tools.getLocation(world, spawnProps.getVector("dmSpectatorSpawn", worldSpawnPos)); spawnProps.comment("Leave everything blank to use arena spawns for deathmatch."); PropertyList dmSpawnList = spawnProps.getList("deathmatch spawns"); HashMap<Integer, Location> dmSpawns = new HashMap<Integer, Location>(); for(PropertyEntry spawnEntry : dmSpawnList.getProperties()){ if(Tools.isInt(spawnEntry.getKey())) { index = Integer.parseInt(spawnEntry.getKey()); Location loc = Tools.getLocation(world, dmSpawnList.getVector(spawnEntry.getKey(), new Vector(0, 0, 0))); dmSpawns.put(index, loc); } } index = 0; // Put the spawns in order. while(!dmSpawns.isEmpty()) { if(dmSpawns.containsKey(index)) { aData.dmSpawns.put(index, dmSpawns.get(index)); dmSpawns.remove(index); } index++; } if(aData.spawns.isEmpty()) { Logger.warning("No spawns have been set in '" + aData.name + "'. Arena disabled."); aData.enabled = false; } return aData; } private ArenaData loadArenaWhiteList(ArenaData aData) { try { File worldFolder = new File(plugin.getDataFolder().getPath() + "/" + aData.worldName); if(!worldFolder.exists()) { worldFolder.mkdirs(); } if(!worldFolder.exists()) { worldFolder.mkdirs(); } File configFile = new File(plugin.getDataFolder().getPath() + "/" + aData.worldName, blockConfig + ".cfg"); blockFiles.put(aData.worldName, new PropertyFile(aData.worldName + "/" + blockConfig, configFile)); blockFiles.get(aData.worldName).loadProperties(); PropertyList spawnProps = blockFiles.get(aData.worldName).getProperties(); aData = setupArenaWhiteList(spawnProps, aData); blockFiles.get(aData.worldName).saveProperties(); if (aData.enabled && !settings.LowDetailMode) { Logger.info(" " + aData.worldName + " - block whitelist loaded. (" + blockConfig + ".cfg)"); } } catch (PropertyException pe) { if(aData.enabled) Logger.error(pe.getMessage()); } catch(Exception ex) { if(aData.enabled) { Logger.error("Could not load " + aData.worldName + "/" + blockConfig + ".cfg file."); ex.printStackTrace(); } } return aData; } private ArenaData setupArenaWhiteList(PropertyList blockProps, ArenaData aData) { blockProps.comment("-- Blocks --"); blockProps.newLine(); PropertyList placeList = blockProps.getList("place"); for(Material mat : Material.values()) { if(mat.isBlock()) { boolean allowed = placeList.getBoolean(mat.name(), blockPlaceDefault(mat)); if(allowed) aData.placeWhitelist.add(mat); else aData.placeWhitelist.remove(mat); } } PropertyList breakList = blockProps.getList("break"); for(Material mat : Material.values()) { if(mat.isBlock()) { boolean allowed = breakList.getBoolean(mat.name(), blockBreakDefault(mat)); if(allowed) aData.breakWhitelist.add(mat); else aData.breakWhitelist.remove(mat); } } return aData; } private boolean blockPlaceDefault(Material mat) { return mat == Material.TNT || mat == Material.WEB || mat == Material.FIRE || mat == Material.CAKE_BLOCK; } private boolean blockBreakDefault(Material mat) { return mat == Material.LEAVES || mat == Material.VINE || mat == Material.RED_MUSHROOM || mat == Material.BROWN_MUSHROOM || mat == Material.WEB || mat == Material.CAKE_BLOCK; } public List<Player> getEditors() { List<Player> editorList = new ArrayList<Player>(); for(String name : editors.keySet()) { editorList.add(Bukkit.getPlayer(name)); } return editorList; } public List<Player> getEditors(String wName) { List<Player> editorList = new ArrayList<Player>(); for(String pName : editors.keySet()) { if(editors.get(pName).equals(wName)) { if(Bukkit.getPlayer(pName) != null) editorList.add(Bukkit.getPlayer(pName)); } } return editorList; } public boolean isEditor(String pName) { return editors.containsKey(pName); } public boolean isEditing(String pName, String wName) { return editors.containsKey(pName) && editors.get(pName).equals(wName); } public void startEditting(String pName, String wName) { editors.put(pName, wName); if(get(wName).enabled) { // Disable disableArena(wName, true); // Remove from voting arenaOrder.remove(wName); // Make sure the world is loaded. loadWorld(wName); } } public void finishEditting(String pName) { final String wName = editors.get(pName); editors.remove(pName); if(getEditors(wName).isEmpty()) { World world = plugin.getServer().getWorld(wName); Player player = plugin.getServer().getPlayer(pName); ArenaData aData = get(wName); if(aData != getLobby()) { Logger.info("Saving '" + aData.worldName + "'..."); world.save(); new GameTask(plugin, 2L) { @Override public void run() { createWorldZips(wName, true); } }; } enableArena(aData.worldName, true); if(player != null) { player.setGameMode(GameMode.SURVIVAL); player.setFlying(false); player.setAllowFlight(false); if(world.getName().equals(wName)) player.teleport(plugin.getArenaManager().getLobby().spectatorSpawn); Language.setVar("worldname", aData.worldName); Language.setVar("arenaname", aData.name); Language.sendLanguage(player, Language.LangKey.adminSave); } } } public void cancelEditting(String pName) { final String wName = editors.get(pName); editors.remove(pName); if(getEditors(wName).isEmpty()) { World world = plugin.getServer().getWorld(wName); Player player = plugin.getServer().getPlayer(pName); ArenaData aData = get(wName); if(aData != getLobby()) { Logger.info("Discarding '" + aData.worldName + "' changes..."); resetArena(wName); } enableArena(aData.worldName, true); if(player != null) { player.setGameMode(GameMode.SURVIVAL); player.setFlying(false); player.setAllowFlight(false); if(world.getName().equals(wName)) player.teleport(plugin.getArenaManager().getLobby().spectatorSpawn); Language.setVar("worldname", aData.worldName); Language.setVar("arenaname", aData.name); Language.sendLanguage(player, Language.LangKey.adminSave); } } } public VoteManager getVoteManager() { return voteMan; } public ArenaData getLastArena() { return plugin.getArenaManager().get(LASTWORLD); } public void setLastArena(ArenaData aData) { LASTWORLD = aData.worldName; } public void setLastArena(String worldFolder) { LASTWORLD = worldFolder; } public ArenaData getCurrentArena() { return plugin.getArenaManager().get(WORLD); } public void setCurrentArena(ArenaData aData) { WORLD = aData.worldName; } public void setCurrentArena(String worldName) { WORLD = worldName; } public ArenaData getNextArena() { return plugin.getArenaManager().get(NEXTWORLD); } public void setNextArena(ArenaData aData) { NEXTWORLD = aData.worldName; } public void setNextArena(String worldFolder) { NEXTWORLD = worldFolder; } public ArenaData getLobby() { return lobby; } public void setLobbySpawn(Location loc) { lobby.spectatorSpawn = loc; PropertyEntry entry = arenaFile.getProperty("lobby.lobbySpawn"); entry.setValue(Tools.toString(loc, false)); arenaFile.saveProperties(); } public void setSpawn(String wName, int spawnNumber, Location spawnLoc) { ArenaData aData = this.get(wName); aData.spawns.put(spawnNumber, spawnLoc); // Hard part... PropertyList list = (PropertyList) spawnFiles.get(wName).getProperty("spawns"); if(list != null) list.setVector(spawnNumber + "", Tools.getVector(spawnLoc, false)); spawnFiles.get(wName).saveProperties(); } public void removeSpawn(String wName, int spawnNumber) { ArenaData aData = this.get(wName); if(aData.spawns.containsKey(spawnNumber)) { aData.spawns.remove(spawnNumber); } // Hard part... PropertyEntry entry = spawnFiles.get(wName).getProperty("spawns"); if(entry != null && entry instanceof PropertyList) { ((PropertyList) entry).removeProperty(spawnNumber + ""); spawnFiles.get(wName).saveProperties(); } } public List<Location> getSpawnsInOrder(String arenaName) { HashMap<Integer, Location> spawns = get(arenaName).spawns; List<Location> spawnsInOrder = new ArrayList<Location>(); int maxKey = 0; for(int key : spawns.keySet()) if(key > maxKey) maxKey = key; for(int i = 0; i <= maxKey; i++) { if(spawns.containsKey(i)) spawnsInOrder.add(spawns.get(i)); } return spawnsInOrder; } public void setSpectatorSpawn(String wName, Location loc) { ArenaData aData = this.get(wName); aData.spectatorSpawn = loc; PropertyEntry entry = spawnFiles.get(wName).getProperty("spectatorSpawn"); entry.setValue(Tools.toString(loc, false)); spawnFiles.get(wName).saveProperties(); } public void setDMCenter(String wName, Location loc) { ArenaData aData = this.get(wName); aData.dmCenter = loc; PropertyEntry entry = spawnFiles.get(wName).getProperty("dmCenter"); entry.setValue(Tools.toString(loc, false)); spawnFiles.get(wName).saveProperties(); } public void setDMSpectatorSpawn(String wName, Location loc) { ArenaData aData = this.get(wName); aData.dmSpectatorSpawn = loc; PropertyEntry entry = spawnFiles.get(wName).getProperty("dmSpectatorSpawn"); entry.setValue(Tools.toString(loc, false)); spawnFiles.get(wName).saveProperties(); } public void setDMSpawn(String wName, int spawnNumber, Location spawnLoc) { ArenaData aData = this.get(wName); aData.dmSpawns.put(spawnNumber, spawnLoc); // Hard part... PropertyList list = (PropertyList) spawnFiles.get(wName).getProperty("deathmatch spawns"); if(list != null) list.setVector(spawnNumber + "", Tools.getVector(spawnLoc, false)); spawnFiles.get(wName).saveProperties(); } public void removeDMSpawn(String wName, int spawnNumber) { ArenaData aData = this.get(wName); if(aData.dmSpawns.containsKey(spawnNumber)) { aData.dmSpawns.remove(spawnNumber); } // Hard part... PropertyEntry entry = spawnFiles.get(wName).getProperty("deathmatch spawns"); if(entry != null && entry instanceof PropertyList) { ((PropertyList) entry).removeProperty(spawnNumber + ""); spawnFiles.get(wName).saveProperties(); } } public List<Location> getDMSpawnsInOrder(String arenaName) { HashMap<Integer, Location> spawns = this.get(arenaName).dmSpawns; List<Location> spawnsInOrder = new ArrayList<Location>(); int maxKey = 0; for(int key : spawns.keySet()) if(key > maxKey) maxKey = key; for(int i = 0; i < maxKey; i++) { if(spawns.containsKey(i)) spawnsInOrder.add(spawns.get(i)); } return spawnsInOrder; } public void randomizeArenaOrder() { List<String> worlds = new ArrayList<String>(); arenaOrder.clear(); // Add enabled worlds. for (String key : this.keySet()) { if (get(key).enabled && !key.equals(lobby.worldName)) { worlds.add(key); } } // Add the worlds to arena order in random order. while (!worlds.isEmpty() && arenaOrder.size() < settings.maxVoteList) { Random rand = plugin.getRandom(); int randIndex = rand.nextInt(worlds.size()); if(!worlds.get(randIndex).equals(LASTWORLD)) { arenaOrder.add(worlds.get(randIndex)); worlds.remove(randIndex); } } if(arenaOrder.size() < settings.maxVoteList && !worlds.isEmpty()) { arenaOrder.add(worlds.get(0)); // Add the last played world anyways. } if(!arenaOrder.isEmpty()) setNextArena(arenaOrder.get(0)); } public void refillContainers() { lootedContainers.clear(); } public boolean canFillContainer(Block block) { return !lootedContainers.containsKey(block); } public void fillContainer(Block block, Inventory inv) { ArenaData aData = get(block.getWorld().getName()); if(!aData.containers.isEmpty()) { ContainerData cData = aData.containers.get(block.getType()); lootedContainers.put(block, inv); Random rand = plugin.getRandom(); int min = cData.minChestRewards; int max = cData.maxChestRewards; if(max > inv.getSize()) max = inv.getSize(); int rewardsLeft = min + (int)(rand.nextDouble() * (max - min)); while (rewardsLeft > 0) { RewardData reward = getRandomReward(cData); int slot = rand.nextInt(inv.getSize()); if (inv.getContents()[slot] == null) { int amount = reward.min + (int)(rand.nextDouble() * (reward.max - reward.min)); // FLint and steel should be damaged. ItemStack item = new ItemStack(reward.item, amount); if(reward.item == Material.FLINT_AND_STEEL) item.setDurability((short) (Material.FLINT_AND_STEEL.getMaxDurability() - aData.lighterUses)); else item.setDurability(reward.data); inv.setItem(slot, item); rewardsLeft--; } } } } public void clearContainer(Block block) { if(lootedContainers.containsKey(block)) { Inventory inv = lootedContainers.get(block); inv.setContents(new ItemStack[inv.getSize()]); } } public void clearContainers() { for (Block block : lootedContainers.keySet()) { clearContainer(block); } } private RewardData getRandomReward(ContainerData cData) { RewardData treasure = null; if(getCurrentArena() != null) { Random rand = plugin.getRandom(); while (treasure == null && cData != null && !cData.rewards.isEmpty()) { RewardData reward = (RewardData) cData.rewards.get(rand.nextInt(cData.rewards.size())); if (rand.nextInt(101) <= reward.rarity) { treasure = reward; } } } return treasure; } public boolean addArena(String wName) { File worldFolder = new File(wName); boolean added = false; if(worldFolder.isDirectory()) { // Save to config for(PropertyEntry entry : arenaFile.getProperties().getProperties()) { if(entry instanceof PropertyList && entry.getKey().equals("worlds")) { PropertyList worldList = (PropertyList) entry; if(!worldList.containsProperty(wName)){ PropertyList arenaProps = worldList.getList(wName, "Your world folder name."); ArenaData aData = setupArena(arenaProps, wName); this.put(wName, aData); added = true; } } } if(added) arenaFile.saveProperties(); } return added; } public boolean removeArena(String wName) { File worldFolder = new File(wName); boolean removed = false; if(worldFolder.isDirectory()) { // Save to config for(PropertyEntry entry : arenaFile.getProperties().getProperties()) { if(entry instanceof PropertyList && entry.getKey().equals("worlds")) { PropertyList worldList = (PropertyList) entry; if(worldList.containsProperty(wName)) { disableArena(wName, true); unloadWorld(wName, true); worldList.removeProperty(wName); this.remove(wName); removed = true; } } } if(removed) arenaFile.saveProperties(); } return removed; } public void enableArena(String wName, boolean show) { ArenaData aData = get(wName); if (aData != null) { if (!aData.enabled) { aData.enabled = true; // Save to config if(aData != lobby) { PropertyEntry entry = arenaFile.getProperty("worlds." + aData.worldName + ".enabled"); entry.setValue("true"); arenaFile.saveProperties(); if(arenaOrder.size() < plugin.getSettings().maxVoteList) arenaOrder.add(wName); } if(show) { Language.setVar("arenaname", aData.name); Language.broadcastLanguage(Language.LangKey.arenaLoaded); } plugin.getGameManager().resetScoreBoards(); } } } public void disableArena(String wName, boolean show) { ArenaData aData = get(wName); if (aData != null) { if (aData.enabled) { aData.enabled = false; // Save to config if(aData != lobby) { PropertyEntry entry = arenaFile.getProperty("worlds." + aData.worldName + ".enabled"); entry.setValue("false"); arenaFile.saveProperties(); arenaOrder.remove(wName); } if(show) { Language.setVar("arenaname", aData.name); Language.broadcastLanguage(Language.LangKey.arenaUnloaded); } plugin.getGameManager().resetScoreBoards(); } } } public boolean isResetting() { for(ArenaData aData : this.values()) { if(aData.resetting) return true; } return false; } public boolean isResetting(String wName) { return containsKey(wName) && get(wName).resetting; } public void resetArena(String wName) { final String fwName = wName; if(containsKey(fwName)) { // Start resetting the arena. get(fwName).resetting = true; // Disable the arena. disableArena(fwName, false); // Register the world unload listener. plugin.getArenaManager().extractWorldZips(fwName); // Make a task that waits until the task is done. new GameTask(plugin, 10L, 5L) { // Check every 1/4th of a second. @Override public void run() { if((progressMonitors.containsKey(fwName) && progressMonitors.get(fwName).getResult() != ProgressMonitor.RESULT_WORKING) /**&& (progressMonitors.containsKey(fwName + ".level") && progressMonitors.get(fwName + ".level").getResult() != ProgressMonitor.RESULT_WORKING) && (progressMonitors.containsKey(fwName + ".uid") && progressMonitors.get(fwName + ".uid").getResult() != ProgressMonitor.RESULT_WORKING) && (progressMonitors.containsKey(fwName + ".levelOld") && progressMonitors.get(fwName + ".levelOld").getResult() != ProgressMonitor.RESULT_WORKING)**/) { if(progressMonitors.containsKey(fwName)) progressMonitors.remove(fwName); /**if(progressMonitors.containsKey(fwName + ".level")) progressMonitors.remove(fwName + ".level"); if(progressMonitors.containsKey(fwName + ".levelOld")) progressMonitors.remove(fwName + ".levelOld"); if(progressMonitors.containsKey(fwName + ".uid")) progressMonitors.remove(fwName + ".uid");**/ ArenaManager arenaMan = plugin.getArenaManager(); // Enable the world. arenaMan.enableArena(fwName, false); // Finish the resetting. arenaMan.get(fwName).resetting = false; setCancelled(true); } } }; } } public void loadWorld(String wName) { Logger.info("Loading world '" + wName + "'..."); WorldCreator creator = new WorldCreator(wName); creator.generateStructures(false); creator.type(WorldType.FLAT); creator.seed(0); plugin.getServer().createWorld(creator); if(!settings.LowDetailMode) Logger.info(" World '" + wName + "' loaded."); } public void unloadWorld(String wName, boolean save) { ArenaData aData = get(wName); World world = plugin.getServer().getWorld(aData.worldName); if (world != null) { Logger.info("Unloading world '" + aData.name + "'... (" + aData.worldName + ")"); Logger.info(" Unloading chunks..."); int chunkCount = 0; for(Chunk chunk : world.getLoadedChunks()) { world.unloadChunk(chunk); chunkCount++; } if(!settings.LowDetailMode) Logger.info(" " + chunkCount + " chunks unloaded."); plugin.getServer().unloadWorld(wName, save); if(!settings.LowDetailMode) Logger.info("World '" + aData.name + "' unloaded. (" + aData.worldName + ")"); } } public void createWorldZips(String worldName, boolean overwrite) { File regionFile = new File(worldName + ".zip"); if(regionFile.exists() && !overwrite) { if(!settings.LowDetailMode) Logger.info(" Using existing world zip '" + worldName + "'."); } else { deleteFile(regionFile); if(!settings.LowDetailMode) { Logger.info(" Existing '" + worldName + "' world zip deleted."); } Logger.info(" Creating world zip '" + worldName + ".zip'..."); try { long startTime = System.currentTimeMillis(); ZipFile regionZip = new ZipFile(regionFile); regionZip.setRunInThread(false); regionZip.createZipFileFromFolder(new File(worldName), new ZipParameters(), false, 0); if(!settings.LowDetailMode) Logger.info(" Created world zip '" + worldName + ".zip' in " + (System.currentTimeMillis() - startTime) + "ms."); } catch(Exception ex) { Logger.error("Unable to create zip for world '" + worldName + "'."); Logger.error(ex.getMessage()); } } /**File regionFile = new File(worldName + "/region.zip"); if(regionFile.exists() && !overwrite) { if(!settings.LowDetailMode) Logger.info(" Using existing world region zip '" + worldName + "'."); } else { deleteFile(regionFile); if(!settings.LowDetailMode) { Logger.info(" Existing '" + worldName + "' world region zip deleted."); } Logger.info(" Creating world region zip '" + worldName + "/region.zip'..."); try { long startTime = System.currentTimeMillis(); ZipFile regionZip = new ZipFile(regionFile); regionZip.setRunInThread(false); regionZip.createZipFileFromFolder(new File(worldName + "/region"), new ZipParameters(), false, 0); if(!settings.LowDetailMode) Logger.info(" Created world region zip '" + worldName + "/region.zip' in " + (System.currentTimeMillis() - startTime) + "ms."); } catch(Exception ex) { Logger.error("Unable to create region zip for world '" + worldName + "'."); Logger.error(ex.getMessage()); } } File levelZipFile = new File(worldName + "/level.dat.zip"); if(levelZipFile.exists() && !overwrite) { if(!settings.LowDetailMode) Logger.info(" Using existing world level zip '" + worldName + "'."); } else { deleteFile(levelZipFile); if(!settings.LowDetailMode) Logger.info(" Existing '" + worldName + "' world level zip deleted."); Logger.info(" Creating world level zip '" + worldName + "/level.dat.zip'..."); try { long startTime = System.currentTimeMillis(); ZipFile levelZip = new ZipFile(worldName + "/level.dat.zip"); levelZip.setRunInThread(false); levelZip.createZipFile(new File(worldName + "/level.dat"), new ZipParameters()); if(!settings.LowDetailMode) Logger.info(" Created world level zip '" + worldName + "/level.dat.zip' in " + (System.currentTimeMillis() - startTime) + "ms."); } catch(Exception ex) { Logger.error("Unable to create level zip for world '" + worldName + "'."); Logger.error(ex.getMessage()); } } File levelOldFile = new File(worldName + "/level.dat_old"); if(levelOldFile.exists()) { File levelOldZipFile = new File(worldName + "/level.dat_old.zip"); if(levelOldZipFile.exists() && !overwrite) { if(!settings.LowDetailMode) Logger.info(" Using existing world level old zip '" + worldName + "'."); } else { deleteFile(levelOldZipFile); if(!settings.LowDetailMode) Logger.info(" Existing '" + worldName + "' world level old zip deleted."); Logger.info(" Creating world level old zip '" + worldName + "/level.dat_old.zip'..."); try { long startTime = System.currentTimeMillis(); ZipFile levelOldZip = new ZipFile(worldName + "/level.dat_old.zip"); levelOldZip.setRunInThread(false); levelOldZip.createZipFile(new File(worldName + "/level.dat_old"), new ZipParameters()); if(!settings.LowDetailMode) Logger.info(" Created world level old zip '" + worldName + "/level.dat_old.zip' in " + (System.currentTimeMillis() - startTime) + "ms."); } catch(Exception ex) { Logger.error("Unable to create level old zip for world '" + worldName + "'."); Logger.error(ex.getMessage()); } } } File uidZipFile = new File(worldName + "/uid.dat.zip"); if(uidZipFile.exists() && !overwrite) { if(!settings.LowDetailMode) Logger.info(" Using existing world uid zip '" + worldName + "'."); } else { deleteFile(uidZipFile); if(!settings.LowDetailMode) Logger.info(" Existing '" + worldName + "' world uid zip deleted."); Logger.info(" Creating world uid zip '" + worldName + "/uid.dat.zip'..."); try { long startTime = System.currentTimeMillis(); ZipFile uidZip = new ZipFile(worldName + "/uid.dat.zip"); uidZip.setRunInThread(false); uidZip.createZipFile(new File(worldName + "/uid.dat"), new ZipParameters()); if(!settings.LowDetailMode) Logger.info(" Created world uid zip '" + worldName + "/uid.dat.zip' in " + (System.currentTimeMillis() - startTime) + "ms."); } catch(Exception ex) { Logger.error("Unable to create uid zip for world '" + worldName + "'."); Logger.error(ex.getMessage()); } } **/ } public void extractWorldZips(String worldName) { Logger.info(" Extracting world zip '" + worldName + ".zip'..."); try { File regionFolder = new File(worldName); ZipFile regionZip = new ZipFile(worldName + ".zip"); if(regionZip.getFile().exists()) { if(regionFolder.isDirectory() || regionFolder.exists()) { deleteDirectory(new File(worldName), true); Logger.info(" Existing world folder deleted."); } long startTime = System.currentTimeMillis(); regionZip.setRunInThread(true); //if (!regionFolder.exists()) //regionFolder.mkdir(); regionZip.extractAll("."); progressMonitors.put(worldName, regionZip.getProgressMonitor()); if(!settings.LowDetailMode) Logger.info(" Finished extracting world zip '" + worldName + ".zip' in " + (System.currentTimeMillis() - startTime) + "ms."); } } catch(Exception ex) { Logger.error("Unable to unzip world zip! (" + worldName + ".zip)"); ex.printStackTrace(); } /**Logger.info(" Extracting world region zip '" + worldName + "/region.zip'..."); try { File regionFolder = new File(worldName + "/region"); ZipFile regionZip = new ZipFile(worldName + "/region.zip"); if(regionZip.getFile().exists()) { if(regionFolder.isDirectory() || regionFolder.exists()) { deleteDirectory(regionFolder, true); Logger.info(" Existing world region folder deleted."); } long startTime = System.currentTimeMillis(); regionZip.setRunInThread(true); regionZip.extractAll(worldName + "/"); progressMonitors.put(worldName + ".region", regionZip.getProgressMonitor()); if(!settings.LowDetailMode) Logger.info(" Finished extracting world region zip '" + worldName + "/region.zip' in " + (System.currentTimeMillis() - startTime) + "ms."); } } catch(Exception ex) { Logger.error("Unable to unzip world region zip! (" + worldName + "/region.zip)"); ex.printStackTrace(); } Logger.info(" Extracting world level zip '" + worldName + "/level.dat.zip'..."); try { File levelFile = new File(worldName + "/level.dat"); ZipFile levelZip = new ZipFile(worldName + "/level.dat.zip"); if(levelZip.getFile().exists()) { if(levelFile.exists()) { deleteFile(levelFile); Logger.info(" Existing world level file deleted."); } long startTime = System.currentTimeMillis(); levelZip.setRunInThread(true); levelZip.extractAll(worldName + "/"); progressMonitors.put(worldName + ".level", levelZip.getProgressMonitor()); if(!settings.LowDetailMode) Logger.info(" Finished extracting world level zip '" + worldName + "/level.dat.zip' in " + (System.currentTimeMillis() - startTime) + "ms."); } } catch(Exception ex) { Logger.error("Unable to unzip world level zip! (" + worldName + "/level.dat.zip)"); ex.printStackTrace(); } Logger.info(" Extracting world level old zip '" + worldName + "/level.dat_old.zip'..."); try { File levelOldFile = new File(worldName + "/level.dat_old"); ZipFile levelOldZip = new ZipFile(worldName + "/level.dat_old.zip"); if(levelOldZip.getFile().exists()) { if(levelOldFile.exists()) { deleteFile(levelOldFile); Logger.info(" Existing world level old file deleted."); } long startTime = System.currentTimeMillis(); levelOldZip.setRunInThread(true); levelOldZip.extractAll(worldName + "/"); progressMonitors.put(worldName + ".levelOld", levelOldZip.getProgressMonitor()); if(!settings.LowDetailMode) Logger.info(" Finished extracting world level old zip '" + worldName + "/level.dat_old.zip' in " + (System.currentTimeMillis() - startTime) + "ms."); } } catch(Exception ex) { Logger.error("Unable to unzip world level old zip! (" + worldName + "/level.dat_old.zip)"); ex.printStackTrace(); } Logger.info(" Extracting world uid zip '" + worldName + "/uid.dat.zip'..."); try { File uidFile = new File(worldName + "/uid.dat"); ZipFile uidZip = new ZipFile(worldName + "/uid.dat.zip"); if(uidZip.getFile().exists()) { if(uidFile.exists()) { deleteFile(uidFile); Logger.info(" Existing world uid file deleted."); } long startTime = System.currentTimeMillis(); uidZip.setRunInThread(true); uidZip.extractAll(worldName + "/"); progressMonitors.put(worldName + ".uid", uidZip.getProgressMonitor()); if(!settings.LowDetailMode) Logger.info(" Finished extracting world uid zip '" + worldName + "/uid.dat.zip' in " + (System.currentTimeMillis() - startTime) + "ms."); } } catch(Exception ex) { Logger.error("Unable to unzip world uid zip! (" + worldName + "/uid.dat.zip)"); ex.printStackTrace(); } **/ } public void deleteDirectory(File folder, boolean waitTillAvailable) throws IOException { deleteDirectory(folder, waitTillAvailable, 3000); } public void deleteDirectory(File folder, boolean waitTillAvailable, long waitTimeout) throws IOException { if(folder.isDirectory()) { List<File> unavailableFiles = new ArrayList<File>(); for(File file : folder.listFiles()) { if(!file.canWrite() && !deleteFile(file) && waitTillAvailable) { Logger.info(file.getName() + " was unavailable."); unavailableFiles.add(file); } } long startTime = System.currentTimeMillis(); while(!unavailableFiles.isEmpty() && System.currentTimeMillis() - startTime < waitTimeout) { File unavailableFile = unavailableFiles.get(0); if(deleteFile(unavailableFile)) { unavailableFiles.remove(unavailableFile); } } if(!unavailableFiles.isEmpty()) { throw new IOException(unavailableFiles.size() + " files were unavailable to delete."); } } folder.delete(); } public boolean deleteFile(File file) { boolean fileAvailable = false; try { RandomAccessFile raf = new RandomAccessFile(file, "rw"); FileChannel channel = raf.getChannel(); FileLock lock = channel.tryLock(); if(lock != null) { Logger.info("Releasing " + file.getName() + "..."); lock.release(); Logger.info("Deleting " + file.getName() + "..."); file.delete(); fileAvailable = true; } raf.close(); } catch(Exception ex) { ex.printStackTrace(); } return fileAvailable; } }