diff --git a/MobArena.jar b/MobArena.jar index 6ba17dd..9d0d2ce 100644 Binary files a/MobArena.jar and b/MobArena.jar differ diff --git a/resources/plugin.yml b/resources/plugin.yml index 99f1913..e44728d 100644 --- a/resources/plugin.yml +++ b/resources/plugin.yml @@ -1,6 +1,6 @@ name: MobArena main: com.garbagemule.MobArena.MobArena -version: 0.94.3.7 +version: 0.94.3.8 softdepend: [Spout,Permissions,MultiVerse,XcraftGate,Towny,Heroes,MagicSpells] commands: ma: @@ -83,6 +83,7 @@ permissions: mobarena.setup.containers: true mobarena.setup.addcontainer: true mobarena.setup.delcontainer: true + mobarena.setup.leaderboards: true mobarena.setup.checkdata: true mobarena.setup.autogenerate: true mobarena.setup.autodegenerate: true @@ -140,6 +141,9 @@ permissions: mobarena.setup.delcontainer: description: Delete a container. default: false + mobarena.setup.leaderboards: + description: Set up leaderboards. + default: false mobarena.setup.checkdata: description: Check which points need to be set up. default: false diff --git a/src/com/garbagemule/MobArena/Arena.java b/src/com/garbagemule/MobArena/Arena.java index e26ee5c..bb82d05 100644 --- a/src/com/garbagemule/MobArena/Arena.java +++ b/src/com/garbagemule/MobArena/Arena.java @@ -6,7 +6,9 @@ import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; @@ -45,6 +47,7 @@ import org.bukkit.permissions.PermissionAttachment; import org.bukkit.util.config.Configuration; import com.garbagemule.MobArena.MAMessages.Msg; +import com.garbagemule.MobArena.leaderboards.Leaderboard; import com.garbagemule.MobArena.repairable.Repairable; import com.garbagemule.MobArena.repairable.RepairableComparator; import com.garbagemule.MobArena.repairable.RepairableContainer; @@ -112,6 +115,8 @@ public class Arena // Logging protected ArenaLog log; + protected Map arenaPlayerMap; + protected Leaderboard leaderboard; protected MAListener eventListener; @@ -148,6 +153,7 @@ public class Arena repairables = new LinkedList(); containables = new LinkedList(); attachments = new HashMap(); + arenaPlayerMap = new HashMap(); running = false; edit = false; @@ -194,6 +200,7 @@ public class Arena p.setHealth(20); p.setFoodLevel(20); assignClassPermissions(p); + arenaPlayerMap.put(p, new ArenaPlayer(p, this, plugin)); } // Copy the singleWaves Set for polling. @@ -213,6 +220,9 @@ public class Arena log = new ArenaLog(plugin, this); log.start(); + // Initialize leaderboards and start displaying info. + leaderboard.initialize(); + // Announce and notify. MAUtils.tellAll(this, Msg.ARENA_START); @@ -235,6 +245,9 @@ public class Arena // Set the boolean. running = false; + // Stop tracking leaderboards + leaderboard.update(); + // Finish logging log.end(); if (logging != null) @@ -262,6 +275,7 @@ public class Arena // Announce and clear sets. MAUtils.tellAll(this, Msg.ARENA_END, true); arenaPlayers.clear(); + arenaPlayerMap.clear(); lobbyPlayers.clear(); readyPlayers.clear(); notifyPlayers.clear(); @@ -321,12 +335,13 @@ public class Arena { storePlayerData(p, loc); MAUtils.sitPets(p); + p.setHealth(20); if (plugin.getHeroManager() != null) { Hero hero = plugin.getHeroManager().getHero(p); hero.setHealth(hero.getMaxHealth()); + hero.syncHealth(); } - p.setHealth(20); p.setFoodLevel(20); p.setGameMode(GameMode.SURVIVAL); movePlayerToLobby(p); @@ -510,7 +525,7 @@ public class Arena if (p == null || log.players.get(p) == null) return; - log.players.get(p).kills++; + arenaPlayerMap.get(p).getStats().kills++; } public void restoreInvAndGiveRewardsDelayed(final Player p) @@ -633,6 +648,7 @@ public class Arena { Hero hero = plugin.getHeroManager().getHero(p); hero.setHealth(health * hero.getMaxHealth() / 20); + hero.syncHealth(); } } @@ -685,7 +701,7 @@ public class Arena else restoreInvAndGiveRewards(p); if (log != null && spawnThread != null) - log.players.get(p).lastWave = spawnThread.getWave() - 1; + arenaPlayerMap.get(p).getStats().lastWave = spawnThread.getWave() - 1; } public void repairBlocks() @@ -898,6 +914,7 @@ public class Arena spawnpoints = MAUtils.getArenaSpawnpoints(config, world, configName); spawnpointsBoss = MAUtils.getArenaBossSpawnpoints(config, world, configName); containers = MAUtils.getArenaContainers(config, world, configName); + leaderboard = new Leaderboard(plugin, this, config); // NEW WAVES singleWaves = WaveUtils.getWaves(this, config, WaveBranch.SINGLE); @@ -1214,6 +1231,22 @@ public class Arena return arenaPlayers; } + public Collection getArenaPlayerSet() + { + return arenaPlayerMap.values(); + } + + public List getArenaPlayerStatistics(Comparator comparator) + { + List list = new ArrayList(); + + for (ArenaPlayer ap : arenaPlayerMap.values()) + list.add(ap.getStats()); + + Collections.sort(list, comparator); + return list; + } + public List getNonreadyPlayers() { List result = new LinkedList(); diff --git a/src/com/garbagemule/MobArena/ArenaLog.java b/src/com/garbagemule/MobArena/ArenaLog.java index 0c37451..0c78f57 100644 --- a/src/com/garbagemule/MobArena/ArenaLog.java +++ b/src/com/garbagemule/MobArena/ArenaLog.java @@ -126,16 +126,16 @@ public class ArenaLog public void playerKill(Player p) { - players.get(p).kills++; + players.get(p).getStats().kills++; } public void playerDamager(Player p, int damage) { - players.get(p).dmgDone += damage; + players.get(p).getStats().dmgDone += damage; } public void playerDamagee(Player p, int damage) { - players.get(p).dmgTaken += damage; + players.get(p).getStats().dmgTaken += damage; } } diff --git a/src/com/garbagemule/MobArena/ArenaPlayer.java b/src/com/garbagemule/MobArena/ArenaPlayer.java index fc3b215..119acab 100644 --- a/src/com/garbagemule/MobArena/ArenaPlayer.java +++ b/src/com/garbagemule/MobArena/ArenaPlayer.java @@ -16,18 +16,10 @@ public class ArenaPlayer public List rewards; public List blocks; + private ArenaPlayerStatistics stats; + protected boolean inArena, inLobby, inSpec, isReady; - // Session fields. - public int kills, dmgDone, dmgTaken, swings, hits, deaths, lastWave; - public int flagCaps, flagAttempts, flagReturns; // BG: Capture the Pumpkin - public int baseCaps; // BG: Domination - - // All-time fields. - protected int totalKills, totalDmgDone, totalDmgTaken, totalSwings, totalHits, totalDeaths; - protected int totalFlagCaps, totalFlagAttempts, totalFlagReturns; // BG: Capture the Pumpkin - protected int totalBaseCaps; // BG: Domination - public ArenaPlayer(Player player, Arena arena, MobArena plugin) { this.player = player; @@ -37,9 +29,12 @@ public class ArenaPlayer className = arena.classMap.get(player); rewards = new LinkedList(); blocks = new LinkedList(); + + stats = new ArenaPlayerStatistics(this); } public Player getPlayer() { return player; } public Arena getArena() { return arena; } public String getClassName() { return className; } + public ArenaPlayerStatistics getStats() { return stats; } } diff --git a/src/com/garbagemule/MobArena/ArenaPlayerStatistics.java b/src/com/garbagemule/MobArena/ArenaPlayerStatistics.java new file mode 100644 index 0000000..be9f017 --- /dev/null +++ b/src/com/garbagemule/MobArena/ArenaPlayerStatistics.java @@ -0,0 +1,74 @@ +package com.garbagemule.MobArena; + +import java.util.Comparator; + +import org.bukkit.entity.Player; + +public class ArenaPlayerStatistics +{ + private String playerName, className; + private ArenaPlayer player; + public int kills, dmgDone, dmgTaken, swings, hits, lastWave; + + public ArenaPlayerStatistics(ArenaPlayer player) + { + this.player = player; + this.playerName = player.getPlayer().getName(); + this.className = player.getClassName(); + } + + public ArenaPlayerStatistics(Player p, Arena arena, MobArena plugin) + { + this(new ArenaPlayer(p, arena, plugin)); + } + + public ArenaPlayer getArenaPlayer() + { + return player; + } + + public static Comparator killComparator() + { + return new Comparator() + { + public int compare(ArenaPlayerStatistics s1, ArenaPlayerStatistics s2) + { + if (s1.kills > s2.kills) + return 1; + else if (s1.kills < s2.kills) + return -1; + return 0; + } + }; + } + + public static Comparator waveComparator() + { + return new Comparator() + { + public int compare(ArenaPlayerStatistics s1, ArenaPlayerStatistics s2) + { + if (s1.lastWave > s2.lastWave) + return 1; + else if (s1.lastWave < s2.lastWave) + return -1; + return 0; + } + }; + } + + public static Comparator dmgDoneComparator() + { + return new Comparator() + { + public int compare(ArenaPlayerStatistics s1, ArenaPlayerStatistics s2) + { + if (s1.dmgDone > s2.dmgDone) + return 1; + else if (s1.dmgDone < s2.dmgDone) + return -1; + return 0; + } + }; + } +} diff --git a/src/com/garbagemule/MobArena/MABlockListener.java b/src/com/garbagemule/MobArena/MABlockListener.java index cbc057b..47c9c8c 100644 --- a/src/com/garbagemule/MobArena/MABlockListener.java +++ b/src/com/garbagemule/MobArena/MABlockListener.java @@ -1,10 +1,14 @@ package com.garbagemule.MobArena; +import org.bukkit.ChatColor; import org.bukkit.event.block.BlockBurnEvent; import org.bukkit.event.block.BlockIgniteEvent; import org.bukkit.event.block.BlockListener; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.SignChangeEvent; + +import com.garbagemule.MobArena.leaderboards.Stats; public class MABlockListener extends BlockListener { @@ -39,6 +43,37 @@ public class MABlockListener extends BlockListener arena.eventListener.onBlockIgnite(event); } + public void onSignChange(SignChangeEvent event) + { + if (!event.getPlayer().hasPermission("mobarena.setup.leaderboards")) + return; + + if (event.getLine(0).startsWith("[MA]")) + { + String text = event.getLine(0).substring((4)); + Arena arena; + Stats stat; + if ((arena = am.getArenaWithName(text)) != null) + { + arena.eventListener.onSignChange(event); + setSignLines(event, ChatColor.GREEN + "MobArena", ChatColor.YELLOW + arena.arenaName(), ChatColor.AQUA + "Players", "---------------"); + } + else if ((stat = Stats.fromString(text)) != null) + { + setSignLines(event, ChatColor.GREEN + "", "", ChatColor.AQUA + stat.getFullName(), "---------------"); + MAUtils.tellPlayer(event.getPlayer(), "Stat sign created."); + } + } + } + + private void setSignLines(SignChangeEvent event, String s1, String s2, String s3, String s4) + { + event.setLine(0, s1); + event.setLine(1, s2); + event.setLine(2, s3); + event.setLine(3, s4); + } + /* public void onBlockPhysics(BlockPhysicsEvent event) { diff --git a/src/com/garbagemule/MobArena/MAListener.java b/src/com/garbagemule/MobArena/MAListener.java index 37c8150..3d0eba8 100644 --- a/src/com/garbagemule/MobArena/MAListener.java +++ b/src/com/garbagemule/MobArena/MAListener.java @@ -21,6 +21,7 @@ import org.bukkit.event.block.BlockBurnEvent; import org.bukkit.event.block.BlockEvent; import org.bukkit.event.block.BlockIgniteEvent; import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.SignChangeEvent; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EndermanPickupEvent; import org.bukkit.event.entity.EndermanPlaceEvent; @@ -49,6 +50,7 @@ import org.bukkit.material.Door; import org.bukkit.material.Redstone; import com.garbagemule.MobArena.MAMessages.Msg; +import com.garbagemule.MobArena.leaderboards.Leaderboard; import com.garbagemule.MobArena.repairable.*; public class MAListener implements ArenaListener @@ -154,6 +156,13 @@ public class MAListener implements ArenaListener break; } } + + public void onSignChange(SignChangeEvent event) + { + arena.leaderboard = new Leaderboard(plugin, arena, event.getBlock().getLocation()); + MAUtils.setArenaCoord(plugin.getConfig(), arena, "leaderboard", event.getBlock().getLocation()); + MAUtils.tellPlayer(event.getPlayer(), "Leaderboard made. Now set up the stat signs!"); + } public void onCreatureSpawn(CreatureSpawnEvent event) { @@ -331,7 +340,7 @@ public class MAListener implements ArenaListener // Log damage if (!event.isCancelled()) - arena.log.players.get(player).dmgTaken += event.getDamage(); + arena.arenaPlayerMap.get(player).getStats().dmgTaken += event.getDamage(); } private void onPetDamage(EntityDamageEvent event, Wolf pet, Entity damager) @@ -352,13 +361,13 @@ public class MAListener implements ArenaListener return; } - arena.log.players.get((Player) damager).dmgDone += event.getDamage(); - arena.log.players.get((Player) damager).hits++; + arena.arenaPlayerMap.get((Player) damager).getStats().dmgDone += event.getDamage(); + arena.arenaPlayerMap.get((Player) damager).getStats().hits++; } else if (damager instanceof Wolf && arena.pets.contains(damager)) { event.setDamage(1); - arena.log.players.get((Player) ((Wolf) damager).getOwner()).dmgDone += event.getDamage(); + arena.arenaPlayerMap.get((Player) ((Wolf) damager).getOwner()).getStats().dmgDone += event.getDamage(); } else if (damager instanceof LivingEntity) { @@ -465,7 +474,7 @@ public class MAListener implements ArenaListener if (!arena.running || !arena.arenaPlayers.contains(event.getPlayer())) return; - arena.log.players.get(event.getPlayer()).swings++; + arena.arenaPlayerMap.get(event.getPlayer()).getStats().swings++; } public void onPlayerDropItem(PlayerDropItemEvent event) diff --git a/src/com/garbagemule/MobArena/MobArena.java b/src/com/garbagemule/MobArena/MobArena.java index 7f4af56..bad4da6 100644 --- a/src/com/garbagemule/MobArena/MobArena.java +++ b/src/com/garbagemule/MobArena/MobArena.java @@ -125,6 +125,7 @@ public class MobArena extends JavaPlugin pm.registerEvent(Event.Type.BLOCK_BURN, blockListener, Priority.Highest, this); pm.registerEvent(Event.Type.BLOCK_PLACE, blockListener, Priority.Highest, this); pm.registerEvent(Event.Type.BLOCK_IGNITE, blockListener, Priority.Highest, this); + pm.registerEvent(Event.Type.SIGN_CHANGE, blockListener, Priority.Normal, this); pm.registerEvent(Event.Type.PLAYER_INTERACT, playerListener, Priority.Normal, this); pm.registerEvent(Event.Type.PLAYER_DROP_ITEM, playerListener, Priority.Normal, this); pm.registerEvent(Event.Type.PLAYER_BUCKET_EMPTY, playerListener, Priority.Normal, this); diff --git a/src/com/garbagemule/MobArena/leaderboards/Leaderboard.java b/src/com/garbagemule/MobArena/leaderboards/Leaderboard.java new file mode 100644 index 0000000..f95dc1e --- /dev/null +++ b/src/com/garbagemule/MobArena/leaderboards/Leaderboard.java @@ -0,0 +1,257 @@ +package com.garbagemule.MobArena.leaderboards; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.block.Sign; +import org.bukkit.util.config.Configuration; + +import com.garbagemule.MobArena.Arena; +import com.garbagemule.MobArena.ArenaPlayer; +import com.garbagemule.MobArena.ArenaPlayerStatistics; +import com.garbagemule.MobArena.MobArena; +import com.garbagemule.MobArena.util.ConfigUtils; + +public class Leaderboard +{ + private MobArena plugin; + private Arena arena; + + private Location topLeft; + private Sign topLeftSign; + private BlockFace direction; + private int rows, cols, trackingId; + + private List boards; + private List stats; + + private boolean isValid; + + /** + * Default constructor. + * Creates a new leaderboard with no signs or locations or anything. + * @param plugin MobArena instance. + * @param arena The arena to which this leaderboard belongs. + */ + public Leaderboard(MobArena plugin, Arena arena) + { + this.plugin = plugin; + this.arena = arena; + this.boards = new ArrayList(); + this.stats = new ArrayList(); + } + + /** + * Config constructor. + * Used to create a leaderboard from the location persisted in the config-file. + * @param plugin MobArena instance. + * @param arena The arena to which this leaderboard belongs. + * @param config The config-file in which the location is specified. + */ + public Leaderboard(MobArena plugin, Arena arena, Configuration config) + { + this(plugin, arena); + + // Grab the coords from the config-file. + String coords = config.getString("arenas." + arena.configName() + ".coords.leaderboard", null); + + if (coords != null) + { + // Grab the top left sign. + topLeft = ConfigUtils.parseLocation(arena.getWorld(), coords); + + // If it is a sign, validate. + if (topLeft.getBlock().getState() instanceof Sign) + isValid = isGridWellFormed(); + } + } + + /** + * Location constructor. + * Used to create a leaderboard on-the-fly from the location from the SignChangeEvent. + * @param plugin MobArena instance. + * @param arena The arena to which this leaderboard belongs. + * @param topLeft The location at which the main leaderboard sign exists. + */ + public Leaderboard(MobArena plugin, Arena arena, Location topLeft) + { + this(plugin, arena); + + if (!(topLeft.getBlock().getState() instanceof Sign)) + throw new IllegalArgumentException("Block must be a sign!"); + + this.topLeft = topLeft; + } + + /** + * Grab all adjacent signs and register the individual columns. + */ + public void initialize() + { + if (!isGridWellFormed()) + return; + + initializeBoards(); + initializeStats(); + } + + public void update() + { + Collections.sort(stats, ArenaPlayerStatistics.waveComparator()); + + for (LeaderboardColumn column : boards) + column.update(stats); + } + + public void startTracking() + { + trackingId = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, + new Runnable() + { + public void run() + { + update(); + } + }, 100, 100); + } + + public void stopTracking() + { + Bukkit.getServer().getScheduler().cancelTask(trackingId); + } + + /** + * Check if the leaderboards grid is well-formed. + * @return true, if the grid is well-formed, false otherwise. + */ + private boolean isGridWellFormed() + { + if (topLeft == null) + return false; + + BlockState state = topLeft.getBlock().getState(); + + if (!(state instanceof Sign)) + { + MobArena.error("Leaderboards for '" + arena.configName() + "' could not be established!"); + return false; + } + + // Grab the top left sign and set up a copy for parsing. + this.topLeftSign = (Sign) state; + Sign current = this.topLeftSign; + + // Calculate matrix dimensions. + this.direction = getRightDirection(current); + this.rows = getSignCount(current, BlockFace.DOWN); + this.cols = getSignCount(current, direction); + + // Require at least 2x2 to be valid + if (rows <= 1 || cols <= 1) + return false; + + // Get the left-most sign in the current row. + Sign first = getAdjacentSign(current, BlockFace.DOWN); + + for (int i = 1; i < rows; i++) + { + // Back to the first sign of the row. + current = first; + for (int j = 1; j < cols; j++) + { + // Grab the sign to the right, if not a sign, grid is ill-formed. + current = getAdjacentSign(current, direction); + if (current == null) return false; + } + + // Hop down to the next row. + first = getAdjacentSign(first, BlockFace.DOWN); + } + return true; + } + + /** + * Build the leaderboards. + * Requires: The grid MUST be valid! + */ + private void initializeBoards() + { + boards.clear(); + Sign header = this.topLeftSign; + Sign current; + + do + { + // Strip the sign of any colors. + String name = ChatColor.stripColor(header.getLine(2)); + + // Grab the stat to track. + Stats stat = Stats.getByFullName(name); + if (stat == null) continue; + + // Create the list of signs + List signs = new ArrayList(); + current = header; + for (int i = 1; i < rows; i++) + { + current = getAdjacentSign(current, BlockFace.DOWN); + signs.add(current); + } + + // Create the column. + LeaderboardColumn column = LeaderboardColumn.create(stat.getShortName(), header, signs); + if (column == null) continue; + this.boards.add(column); + } + while ((header = getAdjacentSign(header, direction)) != null); + } + + private void initializeStats() + { + stats.clear(); + for (ArenaPlayer ap : arena.getArenaPlayerSet()) + stats.add(ap.getStats()); + } + + private int getSignCount(Sign s, BlockFace direction) + { + int i = 1; + + BlockState state = s.getBlock().getState(); + while ((state = state.getBlock().getRelative(direction).getState()) instanceof Sign) + i++; + + return i; + } + + private Sign getAdjacentSign(Sign s, BlockFace direction) + { + BlockState state = s.getBlock().getRelative(direction).getState(); + if (state instanceof Sign) + return (Sign) state; + return null; + } + + private BlockFace getRightDirection(Sign s) + { + byte data = s.getRawData(); + + if (data == 2) return BlockFace.NORTH; + if (data == 3) return BlockFace.SOUTH; + if (data == 4) return BlockFace.WEST; + if (data == 5) return BlockFace.EAST; + + return null; + } + + public boolean isValid() + { + return isValid; + } +} diff --git a/src/com/garbagemule/MobArena/leaderboards/LeaderboardColumn.java b/src/com/garbagemule/MobArena/leaderboards/LeaderboardColumn.java new file mode 100644 index 0000000..ffc36a5 --- /dev/null +++ b/src/com/garbagemule/MobArena/leaderboards/LeaderboardColumn.java @@ -0,0 +1,78 @@ +package com.garbagemule.MobArena.leaderboards; + +import java.lang.reflect.Field; +import java.util.List; + +import org.bukkit.block.Sign; + +import com.garbagemule.MobArena.ArenaPlayerStatistics; + +public class LeaderboardColumn +{ + private Field field; + private Sign header; + private List signs; + + private LeaderboardColumn(String statname, Sign header, List signs) throws Exception + { + this.field = ArenaPlayerStatistics.class.getDeclaredField(statname); + this.header = header; + this.signs = signs; + } + + /** + * Safely create a new LeaderboardColumn. + * Avoid the try-catch blocks by creating columns with this method. + * @param statname The name of the stat to track + * @param header The header sign + * @param signs A list of signs + * @return A new LeaderboardColumn, or null + */ + public static LeaderboardColumn create(String statname, Sign header, List signs) + { + try + { + return new LeaderboardColumn(statname, header, signs); + } + catch (Exception e) + { + e.printStackTrace(); + return null; + } + } + + public void update(List stats) + { + // Make sure the stats will fit on the signs. + int range = Math.min(stats.size(), signs.size()*4); + + try + { + for (int i = 0; i < range; i++) + { + // Grab the right sign. + Sign s = signs.get(i/4); + + // Get the stat value. + field.setAccessible(true); + Object o = field.get(stats.get(i)); + field.setAccessible(false); + + // Set the value on the right line. + s.setLine(i % 4, o.toString()); + s.update(); + } + } + catch (Exception e) { e.printStackTrace(); } + } + + public Sign getHeader() + { + return header; + } + + public List getSigns() + { + return signs; + } +} diff --git a/src/com/garbagemule/MobArena/leaderboards/Stats.java b/src/com/garbagemule/MobArena/leaderboards/Stats.java new file mode 100644 index 0000000..71c1786 --- /dev/null +++ b/src/com/garbagemule/MobArena/leaderboards/Stats.java @@ -0,0 +1,49 @@ +package com.garbagemule.MobArena.leaderboards; + +import com.garbagemule.MobArena.util.WaveUtils; + +public enum Stats +{ + players("Players", "playerName"), + className("Class", "className"), + kills("Kills", "kills"), + dmgDone("Damage Done", "dmgDone"), + dmgTaken("Damage Taken", "dmgTaken"), + swings("Swings", "swings"), + hits("Hits", "hits"), + lastWave("Last Wave", "lastWave"); + + private String name, shortName; + + private Stats(String name, String shortName) + { + this.name = name; + this.shortName = shortName; + } + + public String getShortName() + { + return shortName; + } + + public String getFullName() + { + return name; + } + + public static Stats fromString(String name) + { + if (name.equals("class")) + return Stats.className; + return WaveUtils.getEnumFromStringCaseSensitive(Stats.class, name); + } + + public static Stats getByFullName(String name) + { + + for (Stats s : Stats.values()) + if (s.name.equals(name)) + return s; + return null; + } +} diff --git a/src/com/garbagemule/MobArena/util/ConfigUtils.java b/src/com/garbagemule/MobArena/util/ConfigUtils.java new file mode 100644 index 0000000..469ebc7 --- /dev/null +++ b/src/com/garbagemule/MobArena/util/ConfigUtils.java @@ -0,0 +1,47 @@ +package com.garbagemule.MobArena.util; + +import org.bukkit.Location; +import org.bukkit.World; + +public class ConfigUtils +{ + public static Location parseLocation(World world, String coords) + { + String[] parts = coords.split(","); + if (parts.length != 5) + throw new IllegalArgumentException("Input string must contain x, y, z, yaw and pitch"); + + Integer x = getInt(parts[0]); + Integer y = getInt(parts[1]); + Integer z = getInt(parts[2]); + Float yaw = getFloat(parts[3]); + Float pitch = getFloat(parts[4]); + + if (x == null || y == null || z == null || yaw == null || pitch == null) + throw new NullPointerException("Some of the parsed values are null!"); + + return new Location(world, x, y, z, yaw, pitch); + } + + private static Integer getInt(String s) + { + try + { + return Integer.parseInt(s.trim()); + } + catch (Exception e) {} + + return null; + } + + private static Float getFloat(String s) + { + try + { + return Float.parseFloat(s.trim()); + } + catch (Exception e) {} + + return null; + } +} diff --git a/src/com/garbagemule/MobArena/util/WaveUtils.java b/src/com/garbagemule/MobArena/util/WaveUtils.java index 656488e..8ae51ca 100644 --- a/src/com/garbagemule/MobArena/util/WaveUtils.java +++ b/src/com/garbagemule/MobArena/util/WaveUtils.java @@ -542,4 +542,20 @@ public class WaveUtils } return null; } + + /** + * Get the enum value of a string, null if it doesn't exist. + */ + public static > T getEnumFromStringCaseSensitive(Class c, String string) + { + if(c != null && string != null) + { + try + { + return Enum.valueOf(c, string); + } + catch(IllegalArgumentException ex) { } + } + return null; + } } diff --git a/src/com/garbagemule/MobArena/util/data/PlainText.java b/src/com/garbagemule/MobArena/util/data/PlainText.java index 46c521e..c0cf907 100644 --- a/src/com/garbagemule/MobArena/util/data/PlainText.java +++ b/src/com/garbagemule/MobArena/util/data/PlainText.java @@ -129,11 +129,11 @@ public class PlainText buffy.append("- "); buffy.append(TextUtils.padRight(name, NAME)); buffy.append(pad); buffy.append(TextUtils.padRight(ap.getClassName(), CLASS)); buffy.append(pad); - buffy.append(TextUtils.padLeft(ap.lastWave, WAVE)); buffy.append(pad); - buffy.append(TextUtils.padLeft(ap.kills, KILLS)); buffy.append(pad); - buffy.append(TextUtils.padLeft(ap.dmgDone, DMGDONE)); buffy.append(pad); - buffy.append(TextUtils.padLeft(ap.dmgTaken, DMGTAKEN)); buffy.append(pad); - buffy.append(TextUtils.padLeft(((ap.swings != 0) ? ap.hits*100/ap.swings : 0), ACCURACY-1)); buffy.append("%"); buffy.append(pad); + buffy.append(TextUtils.padLeft(ap.getStats().lastWave, WAVE)); buffy.append(pad); + buffy.append(TextUtils.padLeft(ap.getStats().kills, KILLS)); buffy.append(pad); + buffy.append(TextUtils.padLeft(ap.getStats().dmgDone, DMGDONE)); buffy.append(pad); + buffy.append(TextUtils.padLeft(ap.getStats().dmgTaken, DMGTAKEN)); buffy.append(pad); + buffy.append(TextUtils.padLeft(((ap.getStats().swings != 0) ? ap.getStats().hits*100/ap.getStats().swings : 0), ACCURACY-1)); buffy.append("%"); buffy.append(pad); buffy.append(MAUtils.listToString(ap.rewards)); result.add(buffy.toString()); diff --git a/src/com/garbagemule/MobArena/util/data/Totals.java b/src/com/garbagemule/MobArena/util/data/Totals.java index e47b1c4..087ac8d 100644 --- a/src/com/garbagemule/MobArena/util/data/Totals.java +++ b/src/com/garbagemule/MobArena/util/data/Totals.java @@ -59,12 +59,12 @@ public class Totals for (ArenaPlayer ap : log.players.values()) { // Basic values - updateInt(totals,"players." + ap.player.getName() + ".games-played", 1, true); - updateInt(totals,"players." + ap.player.getName() + ".kills", ap.kills, true); - updateInt(totals,"players." + ap.player.getName() + ".damage-done", ap.dmgDone, true); - updateInt(totals,"players." + ap.player.getName() + ".damage-taken", ap.dmgTaken, true); - updateInt(totals,"players." + ap.player.getName() + ".swings", ap.swings, true); - updateInt(totals,"players." + ap.player.getName() + ".hits", ap.hits, true); + updateInt(totals,"players." + ap.player.getName() + ".games-played", 1, true); + updateInt(totals,"players." + ap.player.getName() + ".kills", ap.getStats().kills, true); + updateInt(totals,"players." + ap.player.getName() + ".damage-done", ap.getStats().dmgDone, true); + updateInt(totals,"players." + ap.player.getName() + ".damage-taken", ap.getStats().dmgTaken, true); + updateInt(totals,"players." + ap.player.getName() + ".swings", ap.getStats().swings, true); + updateInt(totals,"players." + ap.player.getName() + ".hits", ap.getStats().hits, true); // Class count updateInt(totals,"players." + ap.player.getName() + ".classes." + ap.className,1,true); @@ -131,7 +131,7 @@ public class Totals { int kills = 0; for (ArenaPlayer ap : log.players.values()) - kills += ap.kills; + kills += ap.getStats().kills; return kills; } @@ -149,9 +149,9 @@ public class Totals if (!ap.className.equals(className)) continue; - kills += ap.kills; - dmgDone += ap.dmgDone; - dmgTaken += ap.dmgTaken; + kills += ap.getStats().kills; + dmgDone += ap.getStats().dmgDone; + dmgTaken += ap.getStats().dmgTaken; } return new int[]{kills, dmgDone, dmgTaken}; } diff --git a/src/com/garbagemule/MobArena/util/data/XML.java b/src/com/garbagemule/MobArena/util/data/XML.java index 2ca86ac..a0502e0 100644 --- a/src/com/garbagemule/MobArena/util/data/XML.java +++ b/src/com/garbagemule/MobArena/util/data/XML.java @@ -48,12 +48,12 @@ public class XML 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 + "")); + p.addContent(new Element("last-wave").addContent(ap.getStats().lastWave + "")); + p.addContent(new Element("kills").addContent(ap.getStats().lastWave + "")); + p.addContent(new Element("damage-done").addContent(ap.getStats().dmgDone + "")); + p.addContent(new Element("damage-taken").addContent(ap.getStats().dmgTaken + "")); + p.addContent(new Element("swings").addContent(ap.getStats().swings + "")); + p.addContent(new Element("hits").addContent(ap.getStats().hits + "")); // Rewards Element rw = new Element("rewards"); diff --git a/src/com/garbagemule/MobArena/util/data/YAML.java b/src/com/garbagemule/MobArena/util/data/YAML.java index 7f04417..a6d6006 100644 --- a/src/com/garbagemule/MobArena/util/data/YAML.java +++ b/src/com/garbagemule/MobArena/util/data/YAML.java @@ -43,12 +43,12 @@ public class YAML 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); + config.setProperty("player-data." + p + ".last-wave", ap.getStats().lastWave); + config.setProperty("player-data." + p + ".kills", ap.getStats().kills); + config.setProperty("player-data." + p + ".damage-done", ap.getStats().dmgDone); + config.setProperty("player-data." + p + ".damage-taken", ap.getStats().dmgTaken); + config.setProperty("player-data." + p + ".swings", ap.getStats().swings); + config.setProperty("player-data." + p + ".hits", ap.getStats().hits); for (ItemStack stack : ap.rewards) { boolean money = stack.getTypeId() == MobArena.ECONOMY_MONEY_ID;