diff --git a/.classpath b/.classpath index 2fc2280..2433097 100644 --- a/.classpath +++ b/.classpath @@ -2,13 +2,16 @@ - - - - - - - + + + + + + + + + + diff --git a/MobArena.jar b/MobArena.jar index bac09c4..9bdfef0 100644 Binary files a/MobArena.jar and b/MobArena.jar differ diff --git a/resources/plugin.yml b/resources/plugin.yml index 1ab4980..7b35118 100644 --- a/resources/plugin.yml +++ b/resources/plugin.yml @@ -1,7 +1,7 @@ name: MobArena main: com.garbagemule.MobArena.MobArena version: 0.93.4 -softdepend: [MultiVerse,XcraftGate,Towny] +softdepend: [Permissions,MultiVerse,XcraftGate,Towny] commands: ma: description: Base command for MobArena diff --git a/src/com/garbagemule/MobArena/Arena.java b/src/com/garbagemule/MobArena/Arena.java index 6bd2b66..67e1335 100644 --- a/src/com/garbagemule/MobArena/Arena.java +++ b/src/com/garbagemule/MobArena/Arena.java @@ -47,10 +47,12 @@ public class Arena // Setup fields protected String name; protected World world; - protected boolean enabled, protect, logging, running, setup, lobbySetup, autoEquip, forceRestore, softRestore, softRestoreDrops, emptyInvJoin, emptyInvSpec, pvp, monsterInfight, allowWarp; + protected boolean enabled, protect, running, setup, lobbySetup, autoEquip, forceRestore, softRestore, softRestoreDrops, emptyInvJoin, emptyInvSpec, pvp, monsterInfight, allowWarp; + protected boolean edit, waveClear, detCreepers, detDamage, lightning, hellhounds, specOnDeath, shareInArena; protected Location p1, p2, l1, l2, arenaLoc, lobbyLoc, spectatorLoc; protected Map spawnpoints; + protected String logging; // Wave/reward/entryfee fields protected int spawnTaskId, waveDelay, waveInterval, specialModulo, spawnMonstersInt, maxIdleTime; @@ -197,9 +199,13 @@ public class Arena // Set the boolean. running = false; + // Finish logging log.end(); - log.saveSessionData(); - log.updateArenaTotals(); + if (logging != null) + { + log.saveSessionData(); + log.updateArenaTotals(); + } // Stop spawning. stopSpawning(); @@ -220,7 +226,6 @@ public class Arena notifyPlayers.clear(); rewardedPlayers.clear(); classMap.clear(); - //rewardMap.clear(); spawnThread = null; // Notify listeners. @@ -273,8 +278,8 @@ public class Arena public void playerJoin(Player p, Location loc) { storePlayerData(p, loc); - p.setHealth(20); MAUtils.sitPets(p); + p.setHealth(20); movePlayerToLobby(p); } @@ -292,29 +297,19 @@ public class Arena } public void playerLeave(Player p) - { - //if (arenaPlayers.contains(p) || lobbyPlayers.contains(p)) - // MAUtils.clearInventory(p); - + { if (arenaPlayers.contains(p)) finishArenaPlayer(p); else if (lobbyPlayers.contains(p)) MAUtils.clearInventory(p); - //restoreInvAndGiveRewards(p); - //if (log != null && log.players.get(p) != null) - // log.players.get(p).lastWave = spawnThread.getWave() - 1; movePlayerToEntry(p); - finishWithPlayer(p); + discardPlayer(p); endArena(); } public void playerDeath(Player p) { - //MAUtils.clearInventory(p); - //restoreInvAndGiveRewards(p); - //log.players.get(p).lastWave = spawnThread.getWave() - 1; - finishArenaPlayer(p); if (specOnDeath) @@ -325,7 +320,7 @@ public class Arena else { movePlayerToEntry(p); - finishWithPlayer(p); + discardPlayer(p); } if (running && spawnThread != null) @@ -472,12 +467,7 @@ public class Arena { if (healthMap.containsKey(p)) p.setHealth(healthMap.remove(p)); - - removePlayer(p); - } - - public void removePlayer(Player p) - { + // Put out fire. p.setFireTicks(0); @@ -491,18 +481,29 @@ public class Arena lobbyPlayers.remove(p); } - private void finishWithPlayer(Player p) + /** + * Completely remove a player from the arena collections. + * @param p A player + */ + private void discardPlayer(Player p) { locations.remove(p); plugin.getAM().arenaMap.remove(p); resetPlayer(p); } + /** + * Give the player back his inventory and record his last wave. + * Called when a player dies or leaves prematurely. + * @param p + */ private void finishArenaPlayer(Player p) { MAUtils.clearInventory(p); restoreInvAndGiveRewards(p); - log.players.get(p).lastWave = spawnThread.getWave() - 1; + + if (log != null) + log.players.get(p).lastWave = spawnThread.getWave() - 1; } @@ -545,7 +546,7 @@ public class Arena { if (classes.isEmpty()) { - System.out.println("[MobArena] ERROR! Player '" + p.getName() + "' has no class permissions!"); + MobArena.info("Player '" + p.getName() + "' has no class permissions!"); playerLeave(p); return; } @@ -641,7 +642,7 @@ public class Arena enabled = config.getBoolean(arenaPath + "enabled", true); protect = config.getBoolean(arenaPath + "protect", true); - logging = config.getBoolean(arenaPath + "logging", false); + logging = config.getString(arenaPath + "logging", null); autoEquip = config.getBoolean(arenaPath + "auto-equip-armor", true); waveClear = config.getBoolean(arenaPath + "clear-wave-before-next", false); detCreepers = config.getBoolean(arenaPath + "detonate-creepers", false); @@ -689,12 +690,12 @@ public class Arena System.out.println(); System.out.println("ARENA: " + configName); - System.out.println("Single waves"); + System.out.println("- Single waves"); for (Wave w : singleWaves) - System.out.println("- " + w); - System.out.println("Reccurent waves"); + System.out.println(" - " + w); + System.out.println("- Reccurent waves"); for (Wave w : recurrentWaves) - System.out.println("- " + w); + System.out.println(" - " + w); System.out.println(); @@ -775,7 +776,7 @@ public class Arena } catch (Exception e) { - System.out.println("[MobArena] ERROR! Could not create region file. The arena will not be started!"); + MobArena.warning("Could not create region file. The arena will not be started!"); e.printStackTrace(); return false; } @@ -799,7 +800,7 @@ public class Arena } catch (Exception e) { - System.out.println("[MobArena] ERROR! Could not find region file. The arena cannot be restored!"); + MobArena.warning("Could not find region file. The arena cannot be restored!"); e.printStackTrace(); return false; } diff --git a/src/com/garbagemule/MobArena/ArenaLog.java b/src/com/garbagemule/MobArena/ArenaLog.java index 723a6fa..0c37451 100644 --- a/src/com/garbagemule/MobArena/ArenaLog.java +++ b/src/com/garbagemule/MobArena/ArenaLog.java @@ -9,6 +9,8 @@ import org.bukkit.entity.Player; import com.garbagemule.MobArena.util.data.PlainText; import com.garbagemule.MobArena.util.data.Totals; +import com.garbagemule.MobArena.util.data.XML; +import com.garbagemule.MobArena.util.data.YAML; public class ArenaLog { @@ -20,6 +22,11 @@ public class ArenaLog public Map players; public Map distribution; + /** + * Create a new ArenaLog. + * @param plugin MobArena instance + * @param arena The arena + */ public ArenaLog(MobArena plugin, Arena arena) { this.plugin = plugin; @@ -28,6 +35,10 @@ public class ArenaLog this.distribution = new HashMap(arena.classes.size()); } + /** + * Start logging by creating ArenaPlayer objects and recording + * the class distributions and the start time. + */ public void start() { // Populate the data maps @@ -35,9 +46,12 @@ public class ArenaLog populateDistributionMap(); // Grab the current timestamp - startTime = new Timestamp((new Date()).getTime()); + startTime = new Timestamp((new Date()).getTime()); } + /** + * End logging by recording the last wave and the end time. + */ public void end() { lastWave = arena.spawnThread.getWave() - 1; @@ -72,19 +86,26 @@ public class ArenaLog */ public void saveSessionData() { - /* - * Call saveSessionData on the correct utility class - */ - //XML.saveSessionData(this, plugin); + if (arena.logging.equals("xml")) + XML.saveSessionData(this); + else if (arena.logging.equals("yml") || arena.logging.equals("yaml")) + YAML.saveSessionData(this); + else + PlainText.saveSessionData(this); //CSV.saveSessionData(this, plugin); - //YAML.saveSessionData(this, plugin); - PlainText.saveSessionData(this); + //YAML.saveSessionData(this); } + /** + * Update the totals-file + */ public void updateArenaTotals() { Totals.updateArenaTotals(this); - PlainText.updateArenaTotals(this); + + if (arena.logging.equals("xml")) + XML.updateArenaTotals(this); + //PlainText.updateArenaTotals(this); } /** diff --git a/src/com/garbagemule/MobArena/ArenaMaster.java b/src/com/garbagemule/MobArena/ArenaMaster.java index a40e0ac..a8ccc28 100644 --- a/src/com/garbagemule/MobArena/ArenaMaster.java +++ b/src/com/garbagemule/MobArena/ArenaMaster.java @@ -230,7 +230,7 @@ public class ArenaMaster World world; if (worldName == null || worldName.equals("")) { - System.out.println("[MobArena] ERROR! Could not find the world for arena '" + configName + "'. Using default world! Check the config-file!"); + MobArena.warning("Could not find the world for arena '" + configName + "'. Using default world! Check the config-file!"); world = Bukkit.getServer().getWorlds().get(0); } else world = Bukkit.getServer().getWorld(worldName); diff --git a/src/com/garbagemule/MobArena/MACommands.java b/src/com/garbagemule/MobArena/MACommands.java index eeef246..92428b4 100644 --- a/src/com/garbagemule/MobArena/MACommands.java +++ b/src/com/garbagemule/MobArena/MACommands.java @@ -156,8 +156,10 @@ public class MACommands implements CommandExecutor error = MAUtils.tellPlayer(p, MAMessages.get(Msg.JOIN_IN_OTHER_ARENA)); else if (!arena.enabled) error = MAUtils.tellPlayer(p, MAMessages.get(Msg.JOIN_ARENA_NOT_ENABLED)); - else if (!arena.setup || arena.edit) + else if (!arena.setup || arena.recurrentWaves.isEmpty()) error = MAUtils.tellPlayer(p, MAMessages.get(Msg.JOIN_ARENA_NOT_SETUP)); + else if (arena.edit) + error = MAUtils.tellPlayer(p, MAMessages.get(Msg.JOIN_ARENA_EDIT_MODE)); else if (arena.running && (arena.notifyPlayers.contains(p) || arena.notifyPlayers.add(p))) error = MAUtils.tellPlayer(p, MAMessages.get(Msg.JOIN_ARENA_IS_RUNNING)); else if (arena.arenaPlayers.contains(p)) diff --git a/src/com/garbagemule/MobArena/MAMessages.java b/src/com/garbagemule/MobArena/MAMessages.java index 1b7d52d..626d26e 100644 --- a/src/com/garbagemule/MobArena/MAMessages.java +++ b/src/com/garbagemule/MobArena/MAMessages.java @@ -13,7 +13,7 @@ public class MAMessages { protected static Map msgMap; private static Map defaults = new HashMap(); - protected static enum Msg + public static enum Msg { ARENA_START, ARENA_END, @@ -23,6 +23,7 @@ public class MAMessages JOIN_IN_OTHER_ARENA, JOIN_ARENA_NOT_ENABLED, JOIN_ARENA_NOT_SETUP, + JOIN_ARENA_EDIT_MODE, JOIN_ARENA_PERMISSION, JOIN_FEE_REQUIRED, JOIN_FEE_PAID, @@ -61,12 +62,15 @@ public class MAMessages WARP_FROM_ARENA, WAVE_DEFAULT, WAVE_SPECIAL, + WAVE_SWARM, + WAVE_BOSS, + WAVE_BOSS_ABILITY, WAVE_REWARD, MISC_LIST_ARENAS, MISC_LIST_PLAYERS, MISC_COMMAND_NOT_ALLOWED, MISC_NO_ACCESS, - MISC_NONE + MISC_NONE; } // Populate the defaults map. @@ -79,6 +83,7 @@ public class MAMessages defaults.put(Msg.JOIN_IN_OTHER_ARENA, "You are already in an arena! Leave that one first."); defaults.put(Msg.JOIN_ARENA_NOT_ENABLED, "This arena is not enabled."); defaults.put(Msg.JOIN_ARENA_NOT_SETUP, "This arena has not been set up yet."); + defaults.put(Msg.JOIN_ARENA_EDIT_MODE, "This arena is in edit mode."); defaults.put(Msg.JOIN_ARENA_PERMISSION, "You don't have permission to join this arena."); defaults.put(Msg.JOIN_FEE_REQUIRED, "Insufficient funds. Price: %"); defaults.put(Msg.JOIN_FEE_PAID, "Price to join was: %"); @@ -116,8 +121,11 @@ public class MAMessages defaults.put(Msg.LOBBY_CLASS_PERMISSION, "You don't have permission to use this class!"); defaults.put(Msg.WARP_TO_ARENA, "Can't warp to the arena during battle!"); defaults.put(Msg.WARP_FROM_ARENA, "Warping not allowed in the arena!"); - defaults.put(Msg.WAVE_DEFAULT, "Get ready for wave #%!"); - defaults.put(Msg.WAVE_SPECIAL, "Get ready for wave #%! [SPECIAL]"); + defaults.put(Msg.WAVE_DEFAULT, "Wave #%!"); + defaults.put(Msg.WAVE_SPECIAL, "Wave #%! [SPECIAL]"); + defaults.put(Msg.WAVE_SWARM, "Wave #%! [SWARM]"); + defaults.put(Msg.WAVE_BOSS, "Wave #%! [BOSS]"); + defaults.put(Msg.WAVE_BOSS_ABILITY, "Boss used ability: %!"); defaults.put(Msg.WAVE_REWARD, "You just earned a reward: %"); defaults.put(Msg.MISC_LIST_PLAYERS, "Live players: %"); defaults.put(Msg.MISC_LIST_ARENAS, "Available arenas: %"); @@ -143,7 +151,7 @@ public class MAMessages // If it doesn't exist, create it. if (!msgFile.exists()) { - System.out.println("[MobArena] Announcements-file not found. Creating one..."); + MobArena.info("Announcements-file not found. Creating one..."); msgFile.createNewFile(); BufferedWriter bw = new BufferedWriter(new FileWriter(msgFile)); @@ -159,7 +167,7 @@ public class MAMessages } catch (Exception e) { - System.out.println("[MobArena] ERROR! Couldn't initialize announcements-file. Using defaults."); + MobArena.warning("Couldn't initialize announcements-file. Using defaults."); return; } @@ -181,7 +189,7 @@ public class MAMessages catch (Exception e) { e.printStackTrace(); - System.out.println("[MobArena] ERROR! Problem with announcements-file. Using defaults."); + MobArena.warning("Problem with announcements-file. Using defaults."); return; } } @@ -220,7 +228,7 @@ public class MAMessages String[] split = s.split("="); if (split.length != 2) { - System.out.println("[MobArena] ERROR! Couldn't parse \"" + s + "\". Check announcements-file."); + MobArena.warning("Couldn't parse \"" + s + "\". Check announcements-file."); return; } @@ -236,7 +244,7 @@ public class MAMessages } catch (Exception e) { - System.out.println("[MobArena] ERROR! " + key + " is not a valid key. Check announcements-file."); + MobArena.warning(key + " is not a valid key. Check announcements-file."); return; } } diff --git a/src/com/garbagemule/MobArena/MASpawnThread.java b/src/com/garbagemule/MobArena/MASpawnThread.java index d9eb482..76e42b5 100644 --- a/src/com/garbagemule/MobArena/MASpawnThread.java +++ b/src/com/garbagemule/MobArena/MASpawnThread.java @@ -1,6 +1,5 @@ package com.garbagemule.MobArena; -import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -50,35 +49,6 @@ public class MASpawnThread implements Runnable this.arena = arena; wave = 1; playerCount = arena.arenaPlayers.size(); - - /* - modulo = arena.specialModulo; - if (modulo <= 0) modulo = -32768; - - taskId = -32768; - - noOfPlayers = arena.arenaPlayers.size(); - wave = 1; - random = new Random(); - - // Set up the distribution variables for the random spawner. - // Note: Updating these means MAUtils.getArenaDistributions() must also be updated! - dZombies = arena.distDefault.get("zombies"); - dSkeletons = dZombies + arena.distDefault.get("skeletons"); - dSpiders = dSkeletons + arena.distDefault.get("spiders"); - dCreepers = dSpiders + arena.distDefault.get("creepers"); - dWolves = dCreepers + arena.distDefault.get("wolves"); - if (dWolves < 1) { dZombies = 1; dSkeletons = 2; dSpiders = 3; dCreepers = 4; dWolves = 5; } - - dPoweredCreepers = arena.distSpecial.get("powered-creepers"); - dPigZombies = dPoweredCreepers + arena.distSpecial.get("zombie-pigmen"); - dSlimes = dPigZombies + arena.distSpecial.get("slimes"); - dMonsters = dSlimes + arena.distSpecial.get("humans"); - dAngryWolves = dMonsters + arena.distSpecial.get("angry-wolves"); - dGiants = dAngryWolves + arena.distSpecial.get("giants"); - dGhasts = dGiants + arena.distSpecial.get("ghasts"); - if (dGhasts < 1) { dPoweredCreepers = 1; dPigZombies = 2; dSlimes = 3; dMonsters = 4; dAngryWolves = 5; dGiants = 5; dGhasts = 5; } - */ } public void run() @@ -134,8 +104,6 @@ public class MASpawnThread implements Runnable if (!singleWaves.isEmpty() && singleWaves.first().matches(wave)) { w = singleWaves.pollFirst(); - //singleWaves.pollFirst().spawn(wave, arena.spawnpoints.values()); - //return; } else { @@ -197,60 +165,6 @@ public class MASpawnThread implements Runnable this.previousSize = previousSize; } - /* - public void run1() - { - if (arena.arenaPlayers.isEmpty()) - return; - - List tmp = new LinkedList(arena.monsters); - for (Entity e : tmp) - if (e.isDead()) - arena.monsters.remove(e); - - // Check if wave needs to be cleared first. If so, return! - if (arena.waveClear && wave > 1) - { - if (!arena.monsters.isEmpty()) - return; - } - - // Check if we need to grant more rewards with the recurrent waves. - for (Map.Entry> entry : arena.everyWaveMap.entrySet()) - if (wave % entry.getKey() == 0) - addReward(entry.getValue()); - - // Same deal, this time with the one-time waves. - if (arena.afterWaveMap.containsKey(wave)) - addReward(arena.afterWaveMap.get(wave)); - - // Check if this is a special wave. - if (wave % modulo == 0) - { - MAUtils.tellAll(arena, MAMessages.get(Msg.WAVE_SPECIAL, ""+wave)); - detonateCreepers(arena.detCreepers); - specialWave(); - - // Notify listeners. - for (MobArenaListener listener : plugin.getAM().listeners) - listener.onSpecialWave(wave, wave/modulo); - } - else - { - MAUtils.tellAll(arena, MAMessages.get(Msg.WAVE_DEFAULT, ""+wave)); - detonateCreepers(arena.detCreepers); - defaultWave(); - - // Notify listeners. - for (MobArenaListener listener : plugin.getAM().listeners) - listener.onDefaultWave(wave); - } - - wave++; - if (arena.maxIdleTime > 0 && arena.monsters.isEmpty()) arena.resetIdleTimer(); - } - */ - /** * Rewards all players with an item from the input String. */ @@ -267,13 +181,13 @@ public class MASpawnThread implements Runnable if (reward == null) { MAUtils.tellPlayer(p, "ERROR! Problem with economy rewards. Notify server host!"); - System.out.println("[MobArena] ERROR! Could not add null reward. Please check the config-file!"); + MobArena.warning("Could not add null reward. Please check the config-file!"); } else if (reward.getTypeId() == MobArena.ECONOMY_MONEY_ID) { if (plugin.Methods.hasMethod()) MAUtils.tellPlayer(p, MAMessages.get(Msg.WAVE_REWARD, plugin.Method.format(reward.getAmount()))); - else System.out.println("[MobArena] ERROR! No economy plugin detected!"); + else MobArena.warning("Tried to add money, but no economy plugin detected!"); } else { @@ -282,134 +196,6 @@ public class MASpawnThread implements Runnable } } - /** - * Spawns a default wave of monsters. - */ - /*private void defaultWave() - { - Location loc; - List spawnpoints = getValidSpawnpoints(); - int noOfSpawnpoints = spawnpoints.size(); - int count = wave + noOfPlayers; - CreatureType mob; - - for (int i = 0; i < count; i++) - { - loc = spawnpoints.get(i % noOfSpawnpoints); - ran = random.nextInt(dWolves); - - /* Because of the nature of the if-elseif-else statement, - * we're able to evaluate the random number in this way. - * If dSpiders = 0, then dSpiders = dSkeletons, which - * means if the random number is below that value, we will - * spawn a skeleton and break out of the statement. */ /* - if (ran < dZombies) mob = CreatureType.ZOMBIE; - else if (ran < dSkeletons) mob = CreatureType.SKELETON; - else if (ran < dSpiders) mob = CreatureType.SPIDER; - else if (ran < dCreepers) mob = CreatureType.CREEPER; - else if (ran < dWolves) mob = CreatureType.WOLF; - else continue; - - LivingEntity e = arena.world.spawnCreature(loc,mob); - arena.monsters.add(e); - - if (mob == CreatureType.WOLF) - ((Wolf)e).setOwner(null); - - // Grab a random target. - Creature c = (Creature) e; - c.setTarget(getClosestPlayer(e)); - } - }*/ - - /** - * Spawns a special wave of monsters. - */ - /*private void specialWave() - { - Location loc; - List spawnpoints = getValidSpawnpoints(); - int noOfSpawnpoints = spawnpoints.size(); - CreatureType mob; - ran = random.nextInt(dGhasts); - - int count; - boolean slime = false; - boolean wolf = false; - boolean ghast = false; - boolean creeper = false; - - if (ran < dPoweredCreepers) mob = CreatureType.CREEPER; - else if (ran < dPigZombies) mob = CreatureType.PIG_ZOMBIE; - else if (ran < dSlimes) mob = CreatureType.SLIME; - else if (ran < dMonsters) mob = CreatureType.MONSTER; - else if (ran < dAngryWolves) mob = CreatureType.WOLF; - else if (ran < dGiants) mob = CreatureType.GIANT; - else if (ran < dGhasts) mob = CreatureType.GHAST; - else return; - - switch(mob) - { - case CREEPER: - count = noOfPlayers * 3; - creeper = true; - break; - case PIG_ZOMBIE: - count = noOfPlayers * 2; - break; - case SLIME: - count = noOfPlayers * 4; - slime = true; - break; - case MONSTER: - count = noOfPlayers + 1; - break; - case WOLF: - count = noOfPlayers * 3; - wolf = true; - break; - case GIANT: - count = 1; - break; - case GHAST: - count = 2; - ghast = true; - break; - default: - count = 50; - break; - } - - // Spawn the hippie monsters. - for (int i = 0; i < count; i++) - { - loc = spawnpoints.get(i % noOfSpawnpoints); - - LivingEntity e = arena.world.spawnCreature(loc,mob); - arena.monsters.add(e); - - if (slime) ((Slime)e).setSize(2); - if (wolf) { ((Wolf)e).setAngry(true); ((Wolf)e).setOwner(null); } - if (ghast) ((Ghast)e).setHealth(Math.min(noOfPlayers*25, 200)); - if (creeper) ((Creeper)e).setPowered(true); - - // Slimes can't have targets, apparently. - if (!(e instanceof Creature)) - continue; - - // Grab a random target. - Creature c = (Creature) e; - c.setTarget(getClosestPlayer(e)); - } - - if (!arena.lightning) - return; - - // Lightning, just for effect ;) - for (Location spawn : arena.spawnpoints.values()) - arena.world.strikeLightningEffect(spawn); - }*/ - /** * "Detonates" all the Creepers in the monsterSet. */ @@ -437,74 +223,6 @@ public class MASpawnThread implements Runnable } } - /** - * Get all the spawnpoints that have players nearby. - */ - public List getValidSpawnpoints() - { - List result = new ArrayList(); - - for (Location s : arena.spawnpoints.values()) - { - //for (Player p : arena.livePlayers) - for (Player p : arena.arenaPlayers) - { - if (!arena.world.equals(p.getWorld())) - { - System.out.println("[MobArena] MASpawnThread:291: Player '" + p.getName() + "' is not in the right world. Force leaving..."); - arena.playerLeave(p); - MAUtils.tellPlayer(p, "You warped out of the arena world."); - continue; - } - - if (s.distanceSquared(p.getLocation()) > MobArena.MIN_PLAYER_DISTANCE) - continue; - - result.add(s); - break; - } - } - - // If no players are in range, just use all the spawnpoints. - if (result.isEmpty()) - result.addAll(arena.spawnpoints.values()); - - return result; - } - - /** - * Get the player closest to the input entity. - */ - // TODO: Move this into MAUtils - public Player getClosestPlayer(Entity e) - { - // Set up the comparison variable and the result. - double dist = 0; - double current = Double.POSITIVE_INFINITY; - Player result = null; - - /* Iterate through the ArrayList, and update current and result every - * time a squared distance smaller than current is found. */ - //for (Player p : arena.livePlayers) - for (Player p : arena.arenaPlayers) - { - if (!arena.world.equals(p.getWorld())) - { - System.out.println("[MobArena] MASpawnThread:329: Player '" + p.getName() + "' is not in the right world. Force leaving..."); - arena.playerLeave(p); - MAUtils.tellPlayer(p, "You warped out of the arena world."); - continue; - } - dist = p.getLocation().distanceSquared(e.getLocation()); - if (dist < current && dist < MobArena.MIN_PLAYER_DISTANCE) - { - current = dist; - result = p; - } - } - return result; - } - /** * Update the targets of all monsters, if their targets aren't alive. */ @@ -524,7 +242,7 @@ public class MASpawnThread implements Runnable if (target instanceof Player && arena.arenaPlayers.contains(target)) continue; - c.setTarget(getClosestPlayer(e)); + c.setTarget(MAUtils.getClosestPlayer(e, arena)); } } } \ No newline at end of file diff --git a/src/com/garbagemule/MobArena/MAUtils.java b/src/com/garbagemule/MobArena/MAUtils.java index 437602f..8bede2a 100644 --- a/src/com/garbagemule/MobArena/MAUtils.java +++ b/src/com/garbagemule/MobArena/MAUtils.java @@ -363,7 +363,7 @@ public class MAUtils catch (Exception e) { e.printStackTrace(); - System.out.println("[MobArena] ERROR! Could not create backup file for " + p.getName() + "."); + MobArena.warning("Could not create backup file for " + p.getName() + "."); return false; } @@ -410,7 +410,7 @@ public class MAUtils catch (Exception e) { e.printStackTrace(); - System.out.println("[MobArena] ERROR! Could not restore inventory for " + p.getName()); + MobArena.warning("Could not restore inventory for " + p.getName()); return false; } @@ -559,7 +559,7 @@ public class MAUtils } catch (Exception e) { - System.out.println("[MobArena] ERROR! Could not create item \"" + name + "\". Check config.yml"); + MobArena.warning("Could not create item \"" + name + "\". Check config.yml"); return null; } } @@ -592,10 +592,7 @@ public class MAUtils public static void sitPets(Player p) { if (p == null) - { - System.out.println("Player is null!"); return; - } List entities = p.getNearbyEntities(80, 40, 80); for (Entity e : entities) @@ -609,18 +606,6 @@ public class MAUtils } } - /** - * Removes all the pets belonging to this player. - *//* - public static void clearPets(Arena arena, Player p) - { - for (Wolf w : arena.pets) - { - if (w.getOwner().equals(p)) - w.remove(); - } - }*/ - /* ///////////////////////////////////////////////////////////////////// // @@ -885,11 +870,6 @@ public class MAUtils // ///////////////////////////////////////////////////////////////////// */ - public static void error(String msg) - { - System.out.println("[MobArena] ERROR! " + msg); - } - /** * Sends a message to a player. */ @@ -932,8 +912,8 @@ public class MAUtils { if (!arena.world.equals(p.getWorld())) { - System.out.println("[MobArena] MAUtils:908: Player '" + p.getName() + "' is not in the right world. Force leaving..."); - arena.playerLeave(p); + MobArena.info("Player '" + p.getName() + "' is not in the right world. Kicking..."); + p.kickPlayer("[MobArena] Cheater! (Warped out of the arena world.)"); tellPlayer(p, "You warped out of the arena world."); continue; } @@ -1238,7 +1218,7 @@ public class MAUtils catch (Exception e) { e.printStackTrace(); - System.out.println("[MobArena] ERROR! Couldn't create backup file. Aborting auto-generate..."); + MobArena.warning("Couldn't create backup file. Aborting auto-generate..."); return false; } @@ -1371,7 +1351,7 @@ public class MAUtils } catch (Exception e) { - if (error) System.out.println("[MobArena] ERROR! Couldn't find backup file for arena '" + name + "'"); + if (error) MobArena.warning("Couldn't find backup file for arena '" + name + "'"); return false; } diff --git a/src/com/garbagemule/MobArena/MobArena.java b/src/com/garbagemule/MobArena/MobArena.java index c28bebf..43fe433 100644 --- a/src/com/garbagemule/MobArena/MobArena.java +++ b/src/com/garbagemule/MobArena/MobArena.java @@ -2,6 +2,7 @@ package com.garbagemule.MobArena; import java.io.File; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.Event.Priority; @@ -44,12 +45,12 @@ public class MobArena extends JavaPlugin public void onEnable() { - // Description file and data folder + // Description file and data folders desc = getDescription(); dir = getDataFolder(); arenaDir = new File(dir, "arenas"); if (!dir.exists()) dir.mkdir(); - //if (!arenaDir.exists()) arenaDir.mkdir(); + if (!arenaDir.exists()) arenaDir.mkdir(); // Create default files and initialize config-file FileUtils.extractDefaults("config.yml", "announcements.properties"); @@ -71,7 +72,7 @@ public class MobArena extends JavaPlugin registerListeners(); // Announce enable! - System.out.println("[MobArena] v" + desc.getVersion() + " enabled."); + info("v" + desc.getVersion() + " enabled."); } public void onDisable() @@ -86,10 +87,10 @@ public class MobArena extends JavaPlugin if (Methods != null && Methods.hasMethod()) { Methods = null; - System.out.println("[MobArena] Payment method was disabled. No longer accepting payments."); + info("Payment method was disabled. No longer accepting payments."); } - System.out.println("[MobArena] disabled."); + info("disabled."); } private void loadConfig() @@ -97,13 +98,13 @@ public class MobArena extends JavaPlugin File file = new File(dir, "config.yml"); if (!file.exists()) { - System.out.println("[MobArena] ERROR! Config-file could not be created!"); + error("Config-file could not be created!"); return; } config = new Configuration(file); config.load(); - config.setHeader(header()); + config.setHeader(getHeader()); } private void registerListeners() @@ -154,6 +155,11 @@ public class MobArena extends JavaPlugin return (permissionHandler == null || permissionHandler.has(p, s)); } + // Console printing + public static void info(String msg) { Bukkit.getServer().getLogger().info("[MobArena] " + msg); } + public static void warning(String msg) { Bukkit.getServer().getLogger().warning("[MobArena] " + msg); } + public static void error(String msg) { Bukkit.getServer().getLogger().severe("[MobArena] " + msg); } + private void setupPermissions() { if (permissionHandler != null) @@ -171,7 +177,7 @@ public class MobArena extends JavaPlugin if (!Methods.hasMethod() && Methods.setMethod(this)) { Method = Methods.getMethod(); - System.out.println("[MobArena] Payment method found (" + Method.getName() + " version: " + Method.getVersion() + ")"); + info("Payment method found (" + Method.getName() + " version: " + Method.getVersion() + ")"); } } @@ -179,7 +185,7 @@ public class MobArena extends JavaPlugin public ArenaMaster getAM() { return am; } // More convenient. public ArenaMaster getArenaMaster() { return am; } - private String header() + private String getHeader() { String sep = System.getProperty("line.separator"); return "# MobArena v" + desc.getVersion() + " - Config-file" + sep + diff --git a/src/com/garbagemule/MobArena/util/FileUtils.java b/src/com/garbagemule/MobArena/util/FileUtils.java index ef905df..30a4f03 100644 --- a/src/com/garbagemule/MobArena/util/FileUtils.java +++ b/src/com/garbagemule/MobArena/util/FileUtils.java @@ -73,7 +73,7 @@ public class FileUtils catch (Exception e) { e.printStackTrace(); - System.out.println("[MobArena] ERROR! Problem creating file '" + filename + "'!"); + MobArena.warning("Problem creating file '" + filename + "'!"); } } @@ -108,7 +108,7 @@ public class FileUtils if (!config.getString("arenas." + a + ".settings.logging", "").equalsIgnoreCase(lib)) continue; - System.out.println("[MobArena] ERROR! Unrecognized format for arena '" + a + "': " + lib + ". Logging disabled."); + MobArena.warning("Unrecognized format for arena '" + a + "': " + lib + ". Logging disabled."); config.setProperty("arenas." + a + ".logging", "false"); } } @@ -135,7 +135,7 @@ public class FileUtils if (file.exists()) return true; long startTime = System.currentTimeMillis(); - System.out.println("[MobArena] Downloading library: " + lib.filename + "..."); + MobArena.info("Downloading library: " + lib.filename + "..."); // Set up the streams in = con.getInputStream(); @@ -149,12 +149,12 @@ public class FileUtils while ((length = in.read(buffer)) > 0) out.write(buffer, 0, length); - System.out.println("[MobArena] " + lib.filename + " downloaded in " + ((System.currentTimeMillis()-startTime)/1000.0) + " seconds."); + MobArena.info(lib.filename + " downloaded in " + ((System.currentTimeMillis()-startTime)/1000.0) + " seconds."); } catch (Exception e) { e.printStackTrace(); - System.out.println("[MobArena] ERROR! Couldn't download library: " + lib.filename); + MobArena.warning("Couldn't download library: " + lib.filename); return false; } finally diff --git a/src/com/garbagemule/MobArena/util/WaveUtils.java b/src/com/garbagemule/MobArena/util/WaveUtils.java index 2e76077..ea43408 100644 --- a/src/com/garbagemule/MobArena/util/WaveUtils.java +++ b/src/com/garbagemule/MobArena/util/WaveUtils.java @@ -7,13 +7,11 @@ import java.util.List; import java.util.TreeSet; import org.bukkit.Location; -import org.bukkit.entity.CreatureType; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.util.config.Configuration; import com.garbagemule.MobArena.Arena; -import com.garbagemule.MobArena.MAUtils; import com.garbagemule.MobArena.MobArena; import com.garbagemule.MobArena.waves.*; import com.garbagemule.MobArena.waves.Wave.*; @@ -34,7 +32,7 @@ public class WaveUtils // If the player somehow got out of the arena world, kick him. if (!s.getWorld().getName().equals(p.getWorld().getName())) { - System.out.println("[MobArena] Player '" + p.getName() + "' is not in the right world. Kicking..."); + MobArena.info("Player '" + p.getName() + "' is not in the right world. Kicking..."); p.kickPlayer("[MobArena] Cheater! (Warped out of the arena world.)"); continue; } @@ -55,7 +53,6 @@ public class WaveUtils return result; } - public static Player getClosestPlayer(Arena arena, Entity e) { // Set up the comparison variable and the result. @@ -65,14 +62,12 @@ public class WaveUtils /* Iterate through the ArrayList, and update current and result every * time a squared distance smaller than current is found. */ - //for (Player p : arena.livePlayers) for (Player p : arena.getLivingPlayers()) { if (!arena.getWorld().equals(p.getWorld())) { - System.out.println("[MobArena] Player '" + p.getName() + "' is not in the right world. Force leaving..."); - arena.playerLeave(p); - MAUtils.tellPlayer(p, "You warped out of the arena world."); + MobArena.info("Player '" + p.getName() + "' is not in the right world. Kicking..."); + p.kickPlayer("[MobArena] Cheater! (Warped out of the arena world.)"); continue; } @@ -105,21 +100,23 @@ public class WaveUtils Wave wave; for (String w : waves) { + // ---------- path ----------- -- w -- // path argument becomes: "arenas..waves..." wave = getWave(arena, config, path + "." + w + ".", w, branch); - if (wave != null) result.add(wave); + if (wave != null) + result.add(wave); + else MobArena.warning("Wave '" + w + "' in " + path + " was not added!"); } } - // If there are no waves and the type is 'recurrent', add a default wave. + // If there are no waves and the type is 'recurrent', add a couple of auto-generated waves. if (branch == WaveBranch.RECURRENT && (result.isEmpty() || waves == null)) { - /* - DefaultWave def = new DefaultWave(arena, "DEF_WAVE_AUTO", 1, 1, 1, null, null); - def.setType(WaveType.DEFAULT); - def.setGrowth(WaveGrowth.MEDIUM); + MobArena.info("No valid recurrent waves detected for arena '" + arena.configName() + "'. Using defaults..."); + DefaultWave def = new DefaultWave(arena, "DEF_WAVE_AUTO", 1, 1, 1, config, path + ".DEF_WAVE_AUTO."); + SpecialWave spec = new SpecialWave(arena, "SPEC_WAVE_AUTO", 4, 4, 2, config, path + ".SPEC_WAVE_AUTO."); result.add(def); - */ + result.add(spec); } return result; @@ -189,31 +186,43 @@ public class WaveUtils * @param path The absolute path of the wave * @param branch The branch of the wave * @param type The wave type - * @return true, if the wave is well-defined, false otherwise + * @return true, only if the entire wave-node is well-defined. */ private static boolean isWaveWellDefined(Configuration config, String path, WaveBranch branch, WaveType type) { + // This boolean is used in the "leaf methods" + boolean wellDefined = true; + if (branch == WaveBranch.RECURRENT) { // REQUIRED: Priority and frequency int priority = config.getInt(path + "priority", 0); int frequency = config.getInt(path + "frequency", 0); - if (priority == 0 || frequency == 0) - return false; - - // TODO: OPTIONAL: Wave growth, others? + if (priority == 0) + { + MobArena.warning("Missing 'priority'-node in " + path); + wellDefined = false; + } + if (frequency == 0) + { + MobArena.warning("Missing 'frequency'-node in " + path); + wellDefined = false; + } } else if (branch == WaveBranch.SINGLE) { // REQUIRED: Wave number int wave = config.getInt(path + "wave", 0); if (wave == 0) - return false; + { + MobArena.warning("Missing 'wave'-node in " + path); + wellDefined = false; + } } - else return false; + else wellDefined = false; // Passed branch-checks; check type - return isTypeWellDefined(config, path, type); + return isTypeWellDefined(config, path, type, wellDefined); } /** @@ -223,20 +232,58 @@ public class WaveUtils * @param config Config-file Configuration * @param path The absolute path of the wave * @param type The wave type - * @return true, if the wave type is well-defined, false otherwise + * @param wellDefined Pass-through boolean for "leaf methods". + * @return true, only if the entire wave-node is well-defined. */ - private static boolean isTypeWellDefined(Configuration config, String path, WaveType type) + private static boolean isTypeWellDefined(Configuration config, String path, WaveType type, boolean wellDefined) { - if (type == WaveType.DEFAULT || type == WaveType.SPECIAL) - return isNormalWaveWellDefined(config, path); + if (type == WaveType.DEFAULT) + return isDefaultWaveWellDefined(config, path, wellDefined); + else if (type == WaveType.SPECIAL) + return isSpecialWaveWellDefined(config, path, wellDefined); else if (type == WaveType.BOSS) - return isBossWaveWellDefined(config, path); + return isBossWaveWellDefined(config, path, wellDefined); else if (type == WaveType.SWARM) - return isSwarmWaveWellDefined(config, path); + return isSwarmWaveWellDefined(config, path, wellDefined); return false; } + /** + * Check if a default wave is well-defined. + * The default waves have an optional wave growth node. Otherwise, + * they share nodes with special waves. + * @param config Config-file Configuration + * @param path The absolute path of the wave + * @param wellDefined Pass-through boolean for "leaf methods". + * @return true, only if the entire wave-node is well-defined. + */ + private static boolean isDefaultWaveWellDefined(Configuration config, String path, boolean wellDefined) + { + // OPTIONAL: Wave growth + String growth = config.getString(path + "growth"); + if (growth != null && WaveGrowth.fromString(growth) == null) + { + MobArena.warning("Invalid wave growth '" + growth + "' in " + path); + wellDefined = false; + } + + return isNormalWaveWellDefined(config, path, wellDefined); + } + + /** + * Check if a special wave is well-defined. + * The special waves have no unique nodes. + * @param config Config-file Configuration + * @param path The absolute path of the wave + * @param wellDefined Pass-through boolean for "leaf methods". + * @return true, only if the entire wave-node is well-defined. + */ + private static boolean isSpecialWaveWellDefined(Configuration config, String path, boolean wellDefined) + { + return isNormalWaveWellDefined(config, path, wellDefined); + } + /** * Check if a default or special wave is well-defined. * There are no REQUIRED nodes for default or special wave types, besides @@ -244,75 +291,82 @@ public class WaveUtils * The only OPTIONAL node is (currently) 'monsters' * @param config Config-file Configuration * @param path The absolute path of the wave - * @return true, if the wave type is well-defined, false otherwise + * @param wellDefined Pass-through boolean for "leaf methods". + * @return true, wellDefined is true. */ - private static boolean isNormalWaveWellDefined(Configuration config, String path) + private static boolean isNormalWaveWellDefined(Configuration config, String path, boolean wellDefined) { // OPTIONAL: Monsters List monsters = config.getKeys(path + "monsters"); - if (monsters == null) - return true; - - for (String monster : monsters) + if (monsters != null) { - if (getEnumFromString(MACreature.class, monster) != null) - continue; - - MAUtils.error("Invalid monster type '" + monster + "' in " + path); - return false; + for (String monster : monsters) + { + if (getEnumFromString(MACreature.class, monster) != null) + continue; + + MobArena.warning("Invalid monster type '" + monster + "' in " + path); + wellDefined = false; + } } + else MobArena.info("No monsters listed in " + path + ", using defaults..."); - return true; + return wellDefined; } /** * Check if a swarm wave is well defined * @param config Config-file Configuration * @param path The absolute path of the wave - * @return true, if the wave type is well-defined, false otherwise + * @param wellDefined Pass-through boolean for "leaf methods". + * @return true, wellDefined is true. */ - private static boolean isSwarmWaveWellDefined(Configuration config, String path) + private static boolean isSwarmWaveWellDefined(Configuration config, String path, boolean wellDefined) { // REQUIRED: Monster type String monster = config.getString(path + "monster"); if (monster == null) { - MAUtils.error("Missing monster type in '" + path); - return false; + MobArena.warning("Missing monster type in '" + path); + wellDefined = false; } else if (getEnumFromString(MACreature.class, monster) == null) { - MAUtils.error("Invalid monster type '" + monster + "' in " + path); - return false; + MobArena.warning("Invalid monster type '" + monster + "' in " + path); + wellDefined = false; } // OPTIONAL: Amount String amount = config.getString(path + "amount"); if (amount != null && SwarmAmount.fromString(amount) == null) - return false; + { + MobArena.warning("Invalid swarm amount '" + amount + "' in " + path); + wellDefined = false; + } - return true; + return wellDefined; } /** * Check if a boss wave is well defined. * @param config Config-file Configuration * @param path The absolute path of the wave - * @return true, if the wave type is well-defined, false otherwise + * @param wellDefined Pass-through boolean for "leaf methods". + * @return true, wellDefined is true. */ - private static boolean isBossWaveWellDefined(Configuration config, String path) + private static boolean isBossWaveWellDefined(Configuration config, String path, boolean wellDefined) { // REQUIRED: Monster type String monster = config.getString(path + "monster"); if (monster == null) { - MAUtils.error("Missing monster type in '" + path); - return false; + MobArena.warning("Missing monster type in '" + path); + wellDefined = false; } else if (getEnumFromString(MACreature.class, monster) == null) { - MAUtils.error("Invalid monster type '" + monster + "' in " + path); - return false; + MobArena.warning("Invalid monster type '" + monster + "' in " + path); + wellDefined = false; } // OPTIONAL: Abilities @@ -324,8 +378,8 @@ public class WaveUtils if (BossAbility.fromString(ability.trim().replaceAll("-", "_").toUpperCase()) != null) continue; - MAUtils.error("Invalid boss ability '" + ability + "' in " + path); - return false; + MobArena.warning("Invalid boss ability '" + ability + "' in " + path); + wellDefined = false; } } @@ -335,9 +389,12 @@ public class WaveUtils // OPTIONAL: Health String health = config.getString(path + "health"); if (health != null && BossHealth.fromString(health) == null) - return false; + { + MobArena.warning("Invalid boss health '" + health + "' in " + path); + wellDefined = false; + } - return true; + return wellDefined; } diff --git a/src/com/garbagemule/MobArena/util/data/PlainText.java b/src/com/garbagemule/MobArena/util/data/PlainText.java index a4a34d8..46c521e 100644 --- a/src/com/garbagemule/MobArena/util/data/PlainText.java +++ b/src/com/garbagemule/MobArena/util/data/PlainText.java @@ -44,24 +44,7 @@ public class PlainText toWrite.addAll(getPlayerData(log.players, classLength)); // Serialize! - try - { - File file = new File(dir, "lastsession.txt"); - if (!file.exists()) file.createNewFile(); - - FileWriter fw = new FileWriter(file); - for (String s : toWrite) - { - fw.write(s); - fw.write(System.getProperty("line.separator")); - } - fw.close(); - } - catch (Exception e) - { - e.printStackTrace(); - System.out.println("[MobArena] ERROR! Problem saving session data for arena '" + log.getArena().configName() + "'"); - } + serialize(log, dir, "lastsession.txt", toWrite); } public static void updateArenaTotals(ArenaLog log) @@ -71,14 +54,33 @@ public class PlainText // Parse shit + // Serialize + } - /* public static void updateTotals(ArenaLog log, MobArena plugin) + private static void serialize(ArenaLog log, File dir, String filename, List toWrite) { - File dir = new File(MobArena.arenaDir, log.getArena().configName()); - if (!dir.exists()) dir.mkdir(); - } */ + try + { + File file = new File(dir, filename); + if (!file.exists()) file.createNewFile(); + + FileWriter fw = new FileWriter(file); + String linebreak = System.getProperty("line.separator"); + for (String s : toWrite) + { + fw.write(s); + fw.write(linebreak); + } + fw.close(); + } + catch (Exception e) + { + e.printStackTrace(); + MobArena.warning("Problem saving session data for arena '" + log.getArena().configName() + "'"); + } + } private static List getClassDistribution(Map map, int playerCount, int classLength) { diff --git a/src/com/garbagemule/MobArena/util/data/XML.java b/src/com/garbagemule/MobArena/util/data/XML.java index cc85469..81efeec 100644 --- a/src/com/garbagemule/MobArena/util/data/XML.java +++ b/src/com/garbagemule/MobArena/util/data/XML.java @@ -1,6 +1,171 @@ package com.garbagemule.MobArena.util.data; +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; +import java.util.Map; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.config.Configuration; +import org.jdom.Attribute; +import org.jdom.Document; +import org.jdom.Element; +//import org.jdom.Namespace; +import org.jdom.output.XMLOutputter; + +import com.garbagemule.MobArena.ArenaLog; +import com.garbagemule.MobArena.ArenaPlayer; +import com.garbagemule.MobArena.MobArena; + public class XML { + public static void saveSessionData(ArenaLog log) + { + File dir = new File(MobArena.arenaDir, log.getArena().configName()); + if (!dir.exists()) dir.mkdirs(); + + // It's here if people want it. + //Namespace w = Namespace.getNamespace("com.garbagemule.MobArena"); + + // General info + Element ge = new Element("general-info"); + ge.addContent(new Element("start-time").addContent(log.getStartTime().toString())); + ge.addContent(new Element("end-time").addContent(log.getEndTime().toString())); + ge.addContent(new Element("duration").addContent(log.getDuration().toString())); + ge.addContent(new Element("last-wave").addContent(log.getLastWave() + "")); + + // Class distribution + Element cd = new Element("class-distribution"); + for (Map.Entry entry : log.distribution.entrySet()) + cd.addContent(new Element(entry.getKey()).addContent(entry.getValue() + "")); + + // Player data + Element pd = new Element("player-data"); + for (Map.Entry entry : log.players.entrySet()) + { + // Name as attribute + Element p = new Element("player").setAttribute(new Attribute("name", entry.getKey().getName())); + ArenaPlayer ap = entry.getValue(); + p.addContent(new Element("last-wave").addContent(ap.lastWave + "")); + p.addContent(new Element("kills").addContent(ap.lastWave + "")); + p.addContent(new Element("damage-done").addContent(ap.dmgDone + "")); + p.addContent(new Element("damage-taken").addContent(ap.dmgTaken + "")); + p.addContent(new Element("swings").addContent(ap.swings + "")); + p.addContent(new Element("hits").addContent(ap.hits + "")); + + // Rewards + Element rewards = new Element("rewards"); + for (ItemStack stack : ap.rewards) + { + Element r = new Element("reward"); + r.setAttribute(new Attribute("id", stack.getTypeId() + "")); + r.setAttribute(new Attribute("material", stack.getType().toString().toLowerCase())); + r.setAttribute(new Attribute("data", (stack.getData() != null) ? stack.getData().toString().toLowerCase() : "0")); + r.setAttribute(new Attribute("amount", stack.getAmount() + "")); + + rewards.addContent(r); + } + p.addContent(rewards); + pd.addContent(p); + } + + // Add the main nodes + Element root = new Element("last-session"); + root.addContent(ge); + root.addContent(cd); + root.addContent(pd); + + // Create a new document + Document doc = new Document(); + doc.addContent(root); + + // Serialize! + serialize(log, dir, doc, "lastsession.xml"); + } + + public static void updateArenaTotals(ArenaLog log) + { + Configuration totals = Totals.getArenaTotals(log.arena); + totals.load(); + + // General data + Element gd = new Element("general-info"); + gd.addContent(new Element("total-games-played").addContent(totals.getInt("general-info.total-games-played", 0) + "")); + gd.addContent(new Element("most-players").addContent(totals.getInt("general-info.most-players", 0) + "")); + gd.addContent(new Element("highest-wave-reached").addContent(totals.getInt("general-info.highest-wave-reached", 0) + "")); + gd.addContent(new Element("total-monsters-killed").addContent(totals.getInt("general-info.total-monsters-killed", 0) + "")); + gd.addContent(new Element("total-duration").addContent(totals.getString("general-info.total-duration", "0:00:00"))); + gd.addContent(new Element("longest-session-duration").addContent(totals.getString("general-info.longest-session-duration", "0:00:00"))); + + // Classes + Element cl = new Element("classes"); + for (String c : log.arena.getClasses()) + { + Element e = new Element("class").setAttribute(new Attribute("name", c)); + e.addContent(new Element("kills").addContent(totals.getInt("classes." + c + ".kills", 0) + "")); + e.addContent(new Element("damage-done").addContent(totals.getInt("classes." + c + ".damage-done", 0) + "")); + e.addContent(new Element("damage-taken").addContent(totals.getInt("classes." + c + ".damage-taken", 0) + "")); + cl.addContent(e); + } + + // Rewards TODO: THIS! + + // Players + Element pl = new Element("players"); + for (ArenaPlayer ap : log.players.values()) + { + String name = ap.player.getName(); + Element p = new Element("player").setAttribute(new Attribute("name", name)); + p.addContent(new Element("games-played").addContent(totals.getInt("players." + name + ".games-played", 1) + "")); + p.addContent(new Element("kills").addContent(totals.getInt("players." + name + ".kills", 1) + "")); + p.addContent(new Element("damage-done").addContent(totals.getInt("players." + name + ".damage-done", 1) + "")); + p.addContent(new Element("damage-taken").addContent(totals.getInt("players." + name + ".damage-taken", 1) + "")); + p.addContent(new Element("swings").addContent(totals.getInt("players." + name + ".swings", 1) + "")); + p.addContent(new Element("hits").addContent(totals.getInt("players." + name + ".hits", 1) + "")); + + List classes = totals.getKeys("players." + name + ".classes"); + Element pcl = new Element("classes"); + if (classes != null) + { + for (String c : classes) + pcl.addContent(new Element("class").setAttribute(new Attribute("name", c)).addContent(totals.getInt("players." + name + ".classes." + c, 0) + "")); + } + + p.addContent(pcl); + pl.addContent(p); + } + + // Add the main nodes + Element root = new Element("last-session"); + root.addContent(gd); + root.addContent(cl); + root.addContent(pl); + + // Create a new document + Document doc = new Document(); + doc.addContent(root); + + // Serialize! + File dir = new File(MobArena.arenaDir, log.getArena().configName()); + if (!dir.exists()) dir.mkdirs(); + serialize(log, dir, doc, "totals.xml"); + } + + private static void serialize(ArenaLog log, File dir, Document doc, String filename) + { + try + { + File file = new File(dir, filename); + FileOutputStream fop = new FileOutputStream(file); + XMLOutputter out = new XMLOutputter(); + out.output(doc, fop); + } + catch (Exception e) + { + e.printStackTrace(); + MobArena.warning("Problem saving session data for arena '" + log.getArena().configName() + "'"); + } + } } diff --git a/src/com/garbagemule/MobArena/util/data/YAML.java b/src/com/garbagemule/MobArena/util/data/YAML.java new file mode 100644 index 0000000..4825610 --- /dev/null +++ b/src/com/garbagemule/MobArena/util/data/YAML.java @@ -0,0 +1,62 @@ +package com.garbagemule.MobArena.util.data; + +import java.io.File; +import java.util.Map; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.config.Configuration; + +import com.garbagemule.MobArena.ArenaLog; +import com.garbagemule.MobArena.ArenaPlayer; +import com.garbagemule.MobArena.MobArena; + +public class YAML +{ + public static void saveSessionData(ArenaLog log) + { + File dir = new File(MobArena.arenaDir, log.getArena().configName()); + if (!dir.exists()) dir.mkdirs(); + + // Make Configuration object + Configuration config = new Configuration(new File(dir, "lastsession.yml")); + config.load(); + + // Reset any existing data + config.setProperty("general-info", null); + config.setProperty("class-distribution", null); + config.setProperty("player-data", null); + + // General information + config.setProperty("general-info.start-time", log.getStartTime()); + config.setProperty("general-info.end-time", log.getEndTime()); + config.setProperty("general-info.duration", log.getDuration()); + config.setProperty("general-info.last-wave", log.getLastWave()); + + // Class distribution + for (Map.Entry entry : log.distribution.entrySet()) + config.setProperty("class-distribution." + entry.getKey(), entry.getValue()); + + // Player data + for (Map.Entry entry : log.players.entrySet()) + { + String p = entry.getKey().getName(); + ArenaPlayer ap = entry.getValue(); + + config.setProperty("player-data." + p + ".last-wave", ap.lastWave); + config.setProperty("player-data." + p + ".kills", ap.kills); + config.setProperty("player-data." + p + ".damage-done", ap.dmgDone); + config.setProperty("player-data." + p + ".damage-taken", ap.dmgTaken); + config.setProperty("player-data." + p + ".swings", ap.swings); + config.setProperty("player-data." + p + ".hits", ap.hits); + for (ItemStack stack : ap.rewards) + { + String path = "player-data." + p + ".rewards." + stack.getType().toString().toLowerCase(); + config.setProperty(path, config.getInt(path, 0) + stack.getAmount()); + } + } + + // Save the file + config.save(); + } +} diff --git a/src/com/garbagemule/MobArena/waves/BossWave.java b/src/com/garbagemule/MobArena/waves/BossWave.java index 1be97c2..37b87c0 100644 --- a/src/com/garbagemule/MobArena/waves/BossWave.java +++ b/src/com/garbagemule/MobArena/waves/BossWave.java @@ -10,7 +10,9 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.util.config.Configuration; import com.garbagemule.MobArena.Arena; +import com.garbagemule.MobArena.MAMessages; import com.garbagemule.MobArena.MAUtils; +import com.garbagemule.MobArena.MAMessages.Msg; import com.garbagemule.MobArena.util.WaveUtils; public class BossWave extends AbstractWave// TODO: implement/extend something? @@ -54,7 +56,6 @@ public class BossWave extends AbstractWave// TODO: implement/extend something? for (String a : abilities.split(",")) { String ability = a.trim().replaceAll("-", "_").toUpperCase(); - System.out.println(ability); addAbility(BossAbility.fromString(ability)); } } @@ -62,6 +63,9 @@ public class BossWave extends AbstractWave// TODO: implement/extend something? public void spawn(int wave) { + // Announce spawning + MAUtils.tellAll(getArena(), MAMessages.get(Msg.WAVE_BOSS, ""+wave)); + // Spawn the boss and set the arena bossCreature = boss.spawn(getWorld(), getArena().getBossSpawnpoint()); if (bossCreature instanceof Creature) @@ -89,6 +93,10 @@ public class BossWave extends AbstractWave// TODO: implement/extend something? { public void run() { + // Announce ability + MAUtils.tellAll(getArena(), MAMessages.get(Msg.WAVE_BOSS_ABILITY, MAUtils.toCamelCase(ability.toString()))); + + // Activate! ability.activate(getArena(), bossCreature); } }, 50*i, 50*abilityCount); diff --git a/src/com/garbagemule/MobArena/waves/DefaultWave.java b/src/com/garbagemule/MobArena/waves/DefaultWave.java index ba160bc..37f2d09 100644 --- a/src/com/garbagemule/MobArena/waves/DefaultWave.java +++ b/src/com/garbagemule/MobArena/waves/DefaultWave.java @@ -9,6 +9,9 @@ import org.bukkit.Location; import org.bukkit.util.config.Configuration; import com.garbagemule.MobArena.Arena; +import com.garbagemule.MobArena.MAMessages; +import com.garbagemule.MobArena.MAMessages.Msg; +import com.garbagemule.MobArena.MAUtils; import com.garbagemule.MobArena.util.WaveUtils; public class DefaultWave extends NormalWave @@ -34,6 +37,9 @@ public class DefaultWave extends NormalWave */ public void spawn(int wave) { + // Announce spawning + MAUtils.tellAll(getArena(), MAMessages.get(Msg.WAVE_DEFAULT, ""+wave)); + // Get the valid spawnpoints, and initialize counter List validSpawnpoints = WaveUtils.getValidSpawnpoints(getArena().getSpawnpoints(), getArena().getLivingPlayers()); diff --git a/src/com/garbagemule/MobArena/waves/NormalWave.java b/src/com/garbagemule/MobArena/waves/NormalWave.java index 3488392..0e438bf 100644 --- a/src/com/garbagemule/MobArena/waves/NormalWave.java +++ b/src/com/garbagemule/MobArena/waves/NormalWave.java @@ -48,28 +48,33 @@ public abstract class NormalWave extends AbstractWave for (String m : config.getKeys(path + "monsters")) { prob = config.getInt(path + "monsters." + m, 1); + if (prob == 0) continue; + incTotalProbability(prob); - getProbabilityMap().put(getTotalProbability(), MACreature.fromString(m)); + probabilities.put(totalProbability, MACreature.fromString(m)); } } else { if (type == WaveType.DEFAULT) { - getProbabilityMap().put(10, MACreature.ZOMBIES); - getProbabilityMap().put(10, MACreature.SKELETONS); - getProbabilityMap().put(10, MACreature.SPIDERS); - getProbabilityMap().put(10, MACreature.CREEPERS); - getProbabilityMap().put(10, MACreature.WOLVES); + probabilities.put(10, MACreature.ZOMBIES); + probabilities.put(20, MACreature.SKELETONS); + probabilities.put(30, MACreature.SPIDERS); + probabilities.put(40, MACreature.CREEPERS); + probabilities.put(50, MACreature.WOLVES); + totalProbability = 50; } else if (type == WaveType.SPECIAL) { - getProbabilityMap().put(10, MACreature.POWERED_CREEPERS); - getProbabilityMap().put(10, MACreature.ANGRY_WOLVES); - getProbabilityMap().put(10, MACreature.ZOMBIE_PIGMEN); - getProbabilityMap().put(10, MACreature.SLIMES); + probabilities.put(10, MACreature.POWERED_CREEPERS); + probabilities.put(20, MACreature.ANGRY_WOLVES); + probabilities.put(30, MACreature.ZOMBIE_PIGMEN); + probabilities.put(40, MACreature.SLIMES); + totalProbability = 40; } } + System.out.println(probabilities); } public int getTotalProbability() diff --git a/src/com/garbagemule/MobArena/waves/SpecialWave.java b/src/com/garbagemule/MobArena/waves/SpecialWave.java index 4a2f1d4..e17df1b 100644 --- a/src/com/garbagemule/MobArena/waves/SpecialWave.java +++ b/src/com/garbagemule/MobArena/waves/SpecialWave.java @@ -9,6 +9,9 @@ import org.bukkit.Location; import org.bukkit.util.config.Configuration; import com.garbagemule.MobArena.Arena; +import com.garbagemule.MobArena.MAMessages; +import com.garbagemule.MobArena.MAUtils; +import com.garbagemule.MobArena.MAMessages.Msg; import com.garbagemule.MobArena.util.WaveUtils; public class SpecialWave extends NormalWave @@ -29,6 +32,9 @@ public class SpecialWave extends NormalWave public void spawn(int wave) { + // Announce spawning + MAUtils.tellAll(getArena(), MAMessages.get(Msg.WAVE_SPECIAL, ""+wave)); + // Get the valid spawnpoints, and initialize counter List validSpawnpoints = WaveUtils.getValidSpawnpoints(getArena().getSpawnpoints(), getArena().getLivingPlayers()); diff --git a/src/com/garbagemule/MobArena/waves/SwarmWave.java b/src/com/garbagemule/MobArena/waves/SwarmWave.java index 60618c2..a294cad 100644 --- a/src/com/garbagemule/MobArena/waves/SwarmWave.java +++ b/src/com/garbagemule/MobArena/waves/SwarmWave.java @@ -7,6 +7,9 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.util.config.Configuration; import com.garbagemule.MobArena.Arena; +import com.garbagemule.MobArena.MAMessages; +import com.garbagemule.MobArena.MAUtils; +import com.garbagemule.MobArena.MAMessages.Msg; import com.garbagemule.MobArena.util.WaveUtils; public class SwarmWave extends AbstractWave @@ -30,6 +33,9 @@ public class SwarmWave extends AbstractWave private void load(Configuration config, String path) { + // Set the wave type + setType(WaveType.SWARM); + // Get the monster type monster = MACreature.fromString(config.getString(path + "monster")); @@ -39,11 +45,15 @@ public class SwarmWave extends AbstractWave public void spawn(int wave) { + // Announce spawning + MAUtils.tellAll(getArena(), MAMessages.get(Msg.WAVE_SWARM, ""+wave)); + // Get the valid spawnpoints, and initialize counter List validSpawnpoints = WaveUtils.getValidSpawnpoints(getArena().getSpawnpoints(), getArena().getLivingPlayers()); // Spawn the hellians! spawnAll(monster, amount.getAmount(getArena().getPlayerCount()), validSpawnpoints); + System.out.println("WAVE SPAWN! Wave: " + wave + ", name: " + getName() + ", type: " + getType() + ", amount: " + amount); } public void spawnAll(MACreature monster, int amount, List spawnpoints) diff --git a/src/com/garbagemule/MobArena/waves/Wave.java b/src/com/garbagemule/MobArena/waves/Wave.java index 11ecae9..eb6742c 100644 --- a/src/com/garbagemule/MobArena/waves/Wave.java +++ b/src/com/garbagemule/MobArena/waves/Wave.java @@ -27,7 +27,7 @@ public interface Wave public static WaveType fromString(String string) { - return WaveUtils.getEnumFromString(WaveType.class, string, DEFAULT); + return WaveUtils.getEnumFromString(WaveType.class, string); } } diff --git a/src/com/garbagemule/register/payment/methods/BOSE6.java b/src/com/garbagemule/register/payment/methods/BOSE6.java index 5dfdf3b..efd6053 100644 --- a/src/com/garbagemule/register/payment/methods/BOSE6.java +++ b/src/com/garbagemule/register/payment/methods/BOSE6.java @@ -76,35 +76,35 @@ public class BOSE6 implements Method { } public double balance() { - return (double) this.BOSEconomy.getPlayerMoney(this.name); + return (double) this.BOSEconomy.getPlayerMoneyDouble(this.name); } public boolean set(double amount) { int IntAmount = (int)Math.ceil(amount); - return this.BOSEconomy.setPlayerMoney(this.name, IntAmount, false); + return this.BOSEconomy.setPlayerMoney(this.name, (double) IntAmount, false); } public boolean add(double amount) { int IntAmount = (int)Math.ceil(amount); - return this.BOSEconomy.addPlayerMoney(this.name, IntAmount, false); + return this.BOSEconomy.addPlayerMoney(this.name, (double) IntAmount, false); } public boolean subtract(double amount) { int IntAmount = (int)Math.ceil(amount); int balance = (int)this.balance(); - return this.BOSEconomy.setPlayerMoney(this.name, (balance - IntAmount), false); + return this.BOSEconomy.setPlayerMoney(this.name, (double) (balance - IntAmount), false); } public boolean multiply(double amount) { int IntAmount = (int)Math.ceil(amount); int balance = (int)this.balance(); - return this.BOSEconomy.setPlayerMoney(this.name, (balance * IntAmount), false); + return this.BOSEconomy.setPlayerMoney(this.name, (double) (balance * IntAmount), false); } public boolean divide(double amount) { int IntAmount = (int)Math.ceil(amount); int balance = (int)this.balance(); - return this.BOSEconomy.setPlayerMoney(this.name, (balance / IntAmount), false); + return this.BOSEconomy.setPlayerMoney(this.name, (double) (balance / IntAmount), false); } public boolean hasEnough(double amount) { @@ -146,36 +146,36 @@ public class BOSE6 implements Method { } public double balance() { - return (double) this.BOSEconomy.getBankMoney(bank); + return (double) this.BOSEconomy.getBankMoneyDouble(bank); } public boolean set(double amount) { int IntAmount = (int)Math.ceil(amount); - return this.BOSEconomy.setBankMoney(bank, IntAmount, true); + return this.BOSEconomy.setBankMoney(bank, (double) IntAmount, true); } public boolean add(double amount) { int IntAmount = (int)Math.ceil(amount); int balance = (int)this.balance(); - return this.BOSEconomy.setBankMoney(bank, (balance + IntAmount), false); + return this.BOSEconomy.setBankMoney(bank, (double) (balance + IntAmount), false); } public boolean subtract(double amount) { int IntAmount = (int)Math.ceil(amount); int balance = (int)this.balance(); - return this.BOSEconomy.setBankMoney(bank, (balance - IntAmount), false); + return this.BOSEconomy.setBankMoney(bank, (double) (balance - IntAmount), false); } public boolean multiply(double amount) { int IntAmount = (int)Math.ceil(amount); int balance = (int)this.balance(); - return this.BOSEconomy.setBankMoney(bank, (balance * IntAmount), false); + return this.BOSEconomy.setBankMoney(bank, (double) (balance * IntAmount), false); } public boolean divide(double amount) { int IntAmount = (int)Math.ceil(amount); int balance = (int)this.balance(); - return this.BOSEconomy.setBankMoney(bank, (balance / IntAmount), false); + return this.BOSEconomy.setBankMoney(bank, (double) (balance / IntAmount), false); } public boolean hasEnough(double amount) {