diff --git a/MobArena.jar b/MobArena.jar index 93d21ae..2e26df0 100644 Binary files a/MobArena.jar and b/MobArena.jar differ diff --git a/resources/plugin.yml b/resources/plugin.yml index 1b1ed23..fb7ab1c 100644 --- a/resources/plugin.yml +++ b/resources/plugin.yml @@ -1,7 +1,7 @@ name: MobArena author: garbagemule main: com.garbagemule.MobArena.MobArena -version: 0.94.4.65 +version: 0.94.4.75 softdepend: [Spout,MultiVerse,XcraftGate,Towny,Heroes,MagicSpells,Vault] commands: ma: diff --git a/resources/res/class-limits.yml b/resources/res/class-limits.yml new file mode 100644 index 0000000..3753416 --- /dev/null +++ b/resources/res/class-limits.yml @@ -0,0 +1,5 @@ +Knight: -1 +Tank: -1 +Archer: -1 +Chemist: -1 +Oddjob: -1 \ No newline at end of file diff --git a/src/com/garbagemule/MobArena/ArenaClass.java b/src/com/garbagemule/MobArena/ArenaClass.java index d3d3b51..85940ab 100644 --- a/src/com/garbagemule/MobArena/ArenaClass.java +++ b/src/com/garbagemule/MobArena/ArenaClass.java @@ -101,6 +101,12 @@ public class ArenaClass else if (stack.getType() == Material.BONE) { pets += stack.getAmount(); } + else if (stack.getAmount() > 64) { + while (stack.getAmount() > 64) { + items.add(new ItemStack(stack.getType(), 64)); + stack.setAmount(stack.getAmount() - 64); + } + } items.add(stack); } @@ -229,7 +235,7 @@ public class ArenaClass /** * Used by isWeapon() to determine if an ItemStack is a weapon type. */ - private static int[] weaponTypes = new int[]{256,257,258,267,268,269,270,271,272,273,274,275,276,277,278,279,283,284,285,286,290,291,292,293,294}; + private static int[] weaponTypes = new int[]{256,257,258,261,267,268,269,270,271,272,273,274,275,276,277,278,279,283,284,285,286,290,291,292,293,294}; /** * Returns true, if the ItemStack appears to be a weapon, in which case diff --git a/src/com/garbagemule/MobArena/ArenaImpl.java b/src/com/garbagemule/MobArena/ArenaImpl.java index 3e48b6d..f172370 100644 --- a/src/com/garbagemule/MobArena/ArenaImpl.java +++ b/src/com/garbagemule/MobArena/ArenaImpl.java @@ -72,8 +72,9 @@ public class ArenaImpl implements Arena private Leaderboard leaderboard; // Player stuff - private InventoryManager inventoryManager; - private RewardManager rewardManager; + private InventoryManager inventoryManager; + private RewardManager rewardManager; + private ClassLimitManager limitManager; private Map arenaPlayerMap; private Map playerData = new HashMap(); @@ -100,6 +101,7 @@ public class ArenaImpl implements Arena private Map> everyWaveMap, afterWaveMap; // Logging + private boolean logging; private ArenaLog log; private LogSessionBuilder sessionBuilder; private LogTotalsBuilder totalsBuilder; @@ -124,6 +126,7 @@ public class ArenaImpl implements Arena this.enabled = settings.getBoolean("enabled", false); this.protect = settings.getBoolean("protect", true); + this.logging = settings.getBoolean("logging", true); this.running = false; this.edit = false; @@ -143,8 +146,9 @@ public class ArenaImpl implements Arena this.randoms = new HashSet(); // Classes, items and permissions - this.classes = plugin.getArenaMaster().getClasses(); - this.attachments = new HashMap(); + this.classes = plugin.getArenaMaster().getClasses(); + this.attachments = new HashMap(); + this.limitManager = new ClassLimitManager(this, classes); // Blocks and pets this.repairQueue = new PriorityBlockingQueue(100, new RepairableComparator()); @@ -170,11 +174,13 @@ public class ArenaImpl implements Arena Time time = Enums.getEnumFromString(Time.class, timeString); this.timeStrategy = (time != null ? new TimeStrategyLocked(time) : new TimeStrategyNull()); - this.dir = new File(plugin.getDataFolder() + File.separator + "arenas" + File.separator + name); - this.sessionBuilder = new YMLSessionBuilder(new File(dir, "log_session.yml")); - this.totalsBuilder = new YMLTotalsBuilder(new File(dir, "log_totals.yml")); - - this.log = new ArenaLog(this, sessionBuilder, totalsBuilder); + if (logging) { + this.dir = new File(plugin.getDataFolder() + File.separator + "arenas" + File.separator + name); + this.sessionBuilder = new YMLSessionBuilder(new File(dir, "log_session.yml")); + this.totalsBuilder = new YMLTotalsBuilder(new File(dir, "log_totals.yml")); + + this.log = new ArenaLog(this, sessionBuilder, totalsBuilder); + } } @@ -219,6 +225,18 @@ public class ArenaImpl implements Arena @Override public void setProtected(boolean value) { protect = value; + settings.set("protect", protect); + } + + @Override + public boolean isLogging() { + return logging; + } + + @Override + public void setLogging(boolean value) { + logging = value; + settings.set("logging", logging); } @Override @@ -367,6 +385,11 @@ public class ArenaImpl implements Arena return monsterManager; } + @Override + public ClassLimitManager getClassLimitManager() { + return limitManager; + } + @Override public ArenaLog getLog() { return log; @@ -408,6 +431,7 @@ public class ArenaImpl implements Arena for (Player p : randoms) { assignRandomClass(p); } + randoms.clear(); // Then check if there are still players left. if (arenaPlayers.isEmpty()) { @@ -416,6 +440,14 @@ public class ArenaImpl implements Arena // Teleport players, give full health, initialize map for (Player p : arenaPlayers) { + // TODO figure out how people die in lobby and get sent to spectator area early + // Remove player from spec list to avoid invincibility issues + if (inSpec(p)) { + specPlayers.remove(p); + System.out.println("[MobArena] Player " + p.getName() + " joined the arena from the spec area!"); + System.out.println("[MobArena] Invincibility glitch attempt stopped!"); + } + p.teleport(region.getArenaWarp()); //movePlayerToLocation(p, region.getArenaWarp()); setHealth(p, 20); @@ -434,9 +466,13 @@ public class ArenaImpl implements Arena // Spawn pets (must happen after 'running = true;') spawnPets(); + // Clear the classes in use map, as they're no longer needed + limitManager.clearClassesInUse(); + // Start logging rewardManager.reset(); - log.start(); + if (logging) + log.start(); // Initialize leaderboards and start displaying info. leaderboard.initialize(); @@ -471,7 +507,8 @@ public class ArenaImpl implements Arena leaderboard.update(); // Finish logging - log.end(); + if (logging) + log.end(); // Stop spawning. stopSpawner(); @@ -580,18 +617,19 @@ public class ArenaImpl implements Arena removePotionEffects(p); ArenaPlayer ap = arenaPlayerMap.get(p); - if (ap != null && running) log.playerDeath(ap); - + if (logging) + if (ap != null && running) + log.playerDeath(ap); + + restoreInvAndExp(p); if (inLobby(p) || inArena(p)) { - inventoryManager.clearInventory(p); - inventoryManager.restoreInventory(p); - rewardManager.grantRewards(p); refund(p); - //p.updateInventory(); } - else if (inSpec(p)) { - inventoryManager.restoreInventory(p); - //p.updateInventory(); + + if (inLobby(p)) { + if (ap.getArenaClass() != null) { + limitManager.playerLeftClass(ap.getArenaClass()); + } } movePlayerToEntry(p); @@ -609,7 +647,9 @@ public class ArenaImpl implements Arena plugin.getServer().getPluginManager().callEvent(event); ArenaPlayer ap = arenaPlayerMap.get(p); - if (ap != null) log.playerDeath(ap); + if (logging) + if (ap != null) + log.playerDeath(ap); arenaPlayers.remove(p); @@ -643,7 +683,9 @@ public class ArenaImpl implements Arena if (settings.getBoolean("spectate-on-death", true)) { movePlayerToSpec(p); - restoreInvAndExp(p); + Messenger.tellPlayer(p, Msg.SPEC_FROM_ARENA); + Messenger.tellPlayer(p, Msg.MISC_MA_LEAVE_REMINDER); + //restoreInvAndExp(p); } else { restoreInvAndExp(p); movePlayerToEntry(p); @@ -701,7 +743,7 @@ public class ArenaImpl implements Arena private void removePotionEffects(Player p) { for (PotionEffect effect : p.getActivePotionEffects()) { - p.addPotionEffect(new PotionEffect(effect.getType(), 0, 0), true); + p.removePotionEffect(effect.getType()); } } @@ -873,6 +915,9 @@ public class ArenaImpl implements Arena if (!settings.getBoolean("keep-exp", false)) { playerData.get(p).restoreData(); } + else { + p.setFoodLevel(playerData.get(p).food()); + } } @Override @@ -943,6 +988,11 @@ public class ArenaImpl implements Arena arenaPlayer.setArenaClass(arenaClass); arenaClass.grantItems(p); } + + @Override + public void addRandomPlayer(Player p) { + randoms.add(p); + } @Override public void assignRandomClass(Player p) @@ -963,7 +1013,7 @@ public class ArenaImpl implements Arena } assignClass(p, className); - Messenger.tellPlayer(p, Msg.LOBBY_CLASS_PICKED, className); + Messenger.tellPlayer(p, Msg.LOBBY_CLASS_PICKED, TextUtils.camelCase(className), getClassLogo(className)); } @Override diff --git a/src/com/garbagemule/MobArena/ArenaListener.java b/src/com/garbagemule/MobArena/ArenaListener.java index 3dd394f..9f971d6 100644 --- a/src/com/garbagemule/MobArena/ArenaListener.java +++ b/src/com/garbagemule/MobArena/ArenaListener.java @@ -88,6 +88,7 @@ public class ArenaListener private Arena arena; private ArenaRegion region; private MonsterManager monsters; + private ClassLimitManager classLimits; private boolean softRestore, softRestoreDrops, @@ -97,6 +98,7 @@ public class ArenaListener pvpEnabled, foodRegen, lockFoodLevel; + @SuppressWarnings("unused") private boolean allowTeleport, canShare, allowMonsters, @@ -128,6 +130,8 @@ public class ArenaListener this.allowTeleport = s.getBoolean("allow-teleporting", false); this.canShare = s.getBoolean("share-items-in-arena", true); this.autoIgniteTNT = s.getBoolean("auto-ignite-tnt", false); + + this.classLimits = arena.getClassLimitManager(); this.allowMonsters = arena.getWorld().getAllowMonsters(); @@ -135,6 +139,16 @@ public class ArenaListener } public void onBlockBreak(BlockBreakEvent event) { + if (!arena.getRegion().contains(event.getBlock().getLocation())) + return; + + if (!arena.inArena(event.getPlayer())) { + if (arena.inEditMode()) + return; + else + event.setCancelled(true); + } + if (onBlockDestroy(event)) return; @@ -142,24 +156,30 @@ public class ArenaListener } public void onBlockBurn(BlockBurnEvent event) { - if (onBlockDestroy(event)) + if (!arena.getRegion().contains(event.getBlock().getLocation()) || onBlockDestroy(event)) return; event.setCancelled(true); } private boolean onBlockDestroy(BlockEvent event) { - if (!arena.getRegion().contains(event.getBlock().getLocation()) || arena.inEditMode() || (!arena.isProtected() && arena.isRunning())) + if (arena.inEditMode()) return true; + + if (!arena.isRunning()) + return false; Block b = event.getBlock(); if (arena.removeBlock(b) || b.getType() == Material.TNT) return true; - - if (softRestore && arena.isRunning()) { + + if (softRestore) { + if (arena.isProtected()) + return false; + BlockState state = b.getState(); - Repairable r = null; + if (state instanceof InventoryHolder) r = new RepairableContainer(state); else if (state instanceof Sign) @@ -170,10 +190,9 @@ public class ArenaListener r = new RepairableBlock(state); arena.addRepairable(r); - + if (!softRestoreDrops) b.setTypeId(0); - return true; } @@ -256,8 +275,13 @@ public class ArenaListener } if (event.getSpawnReason() != SpawnReason.CUSTOM) { - event.setCancelled(true); - return; + if (event.getSpawnReason() == SpawnReason.BUILD_IRONGOLEM || event.getSpawnReason() == SpawnReason.BUILD_SNOWMAN) { + monsters.addGolem(event.getEntity()); + } + else { + event.setCancelled(true); + return; + } } LivingEntity entity = (LivingEntity) event.getEntity(); @@ -345,6 +369,9 @@ public class ArenaListener else if (monsters.removeMonster(event.getEntity())) { onMonsterDeath(event); } + else if (monsters.removeGolem(event.getEntity())) { + Messenger.tellAll(arena, Msg.GOLEM_DIED); + } } private void onPlayerDeath(PlayerDeathEvent event, Player player) { @@ -450,7 +477,7 @@ public class ArenaListener else if (damagee instanceof Player) { onPlayerDamage(event, (Player) damagee, damager); } - // Snowman + // Snowmen melting else if (damagee instanceof Snowman && event.getCause() == DamageCause.MELTING) { event.setCancelled(true); } @@ -462,6 +489,10 @@ public class ArenaListener else if (monsters.getMonsters().contains(damagee)) { onMonsterDamage(event, damagee, damager); } + // Player made golems + else if (monsters.getGolems().contains(damagee)) { + onGolemDamage(event, damagee, damager); + } } private void onPlayerDamage(EntityDamageEvent event, Player player, Entity damager) { @@ -509,6 +540,21 @@ public class ArenaListener event.setCancelled(true); } } + + private void onGolemDamage(EntityDamageEvent event, Entity golem, Entity damager) { + if (damager instanceof Player) { + Player p = (Player) damager; + if (!arena.inArena(p)) { + event.setCancelled(true); + return; + } + + if (!pvpEnabled) { + event.setCancelled(true); + return; + } + } + } private void onBossDamage(EntityDamageEvent event, LivingEntity monster, Entity damager) { // Health the boss back up. @@ -742,6 +788,31 @@ public class ArenaListener Messenger.tellPlayer(p, Msg.LOBBY_CLASS_PERMISSION); return; } + + ArenaClass oldAC = arena.getArenaPlayer(p).getArenaClass(); + ArenaClass newAC = arena.getClasses().get(className); + + // If they already had a class, make sure to change the "in use" in the Class Limit Manager + if (oldAC != null) { + p.sendMessage("already had a class"); + // If they picked the same sign, don't do anything + if (oldAC.equals(newAC)) { + p.sendMessage("picked the same class"); + return; + } + System.out.println("decrementing the classesInUse of " + oldAC.getName()); + classLimits.playerLeftClass(oldAC); + } + + // If they can not join the class, deny them + if (!classLimits.canPlayerJoinClass(newAC)) { + Messenger.tellPlayer(p, Msg.LOBBY_CLASS_FULL); + return; + } + + // Increment the "in use" in the Class Limit Manager + System.out.println("incrementing the classesInUse of " + newAC.getName()); + classLimits.playerPickedClass(newAC); // Delay the inventory stuff to ensure that right-clicking works. delayAssignClass(p, className); @@ -750,20 +821,23 @@ public class ArenaListener private void delayAssignClass(final Player p, final String className) { plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin,new Runnable() { public void run() { - arena.assignClass(p, className); - - if (!className.equalsIgnoreCase("random")) + if (!className.equalsIgnoreCase("random")) { + arena.assignClass(p, className); Messenger.tellPlayer(p, Msg.LOBBY_CLASS_PICKED, TextUtils.camelCase(className), arena.getClassLogo(className)); - else + } + else { + arena.addRandomPlayer(p); Messenger.tellPlayer(p, Msg.LOBBY_CLASS_RANDOM); + } } }); } public void onPlayerQuit(PlayerQuitEvent event) { Player p = event.getPlayer(); - if (!arena.isEnabled() || (!arena.inArena(p) && !arena.inLobby(p))) + if (!arena.isEnabled() || (!arena.inArena(p) && !arena.inLobby(p) && !arena.inSpec(p))) { return; + } arena.playerLeave(p); banned.add(p); @@ -772,7 +846,7 @@ public class ArenaListener public void onPlayerKick(PlayerKickEvent event) { Player p = event.getPlayer(); - if (!arena.isEnabled() || (!arena.inArena(p) && !arena.inLobby(p))) { + if (!arena.isEnabled() || (!arena.inArena(p) && !arena.inLobby(p) && !arena.inSpec(p))) { return; } diff --git a/src/com/garbagemule/MobArena/ArenaMasterImpl.java b/src/com/garbagemule/MobArena/ArenaMasterImpl.java index 9548694..891f139 100644 --- a/src/com/garbagemule/MobArena/ArenaMasterImpl.java +++ b/src/com/garbagemule/MobArena/ArenaMasterImpl.java @@ -24,6 +24,7 @@ import com.garbagemule.MobArena.ArenaClass.ArmorType; import com.garbagemule.MobArena.framework.Arena; import com.garbagemule.MobArena.framework.ArenaMaster; import com.garbagemule.MobArena.util.ItemParser; +import com.garbagemule.MobArena.util.TextUtils; import com.garbagemule.MobArena.util.config.Config; import com.garbagemule.MobArena.util.config.ConfigSection; import com.garbagemule.MobArena.util.config.ConfigUtils; @@ -424,6 +425,7 @@ public class ArenaMasterImpl implements ArenaMaster } private boolean addRemoveClassPermission(String classname, String perm, boolean add) { + classname = TextUtils.camelCase(classname); String path = "classes." + classname; if (config.getConfigSection(path) == null) return false; @@ -433,16 +435,19 @@ public class ArenaMasterImpl implements ArenaMaster // Get any previous nodes List nodes = section.getStringList("permissions", null); - if (nodes.contains(perm)) + + if (nodes.contains(perm) && add) { return false; - - // Add or remove. - if (add) { + } + else if (nodes.contains(perm) && !add) { + nodes.remove(perm); + } + else if (!nodes.contains(perm) && add) { removeContradictions(nodes, perm); nodes.add(perm); } - else { - nodes.remove(perm); + else if (!nodes.contains(perm) && !add) { + return false; } // Replace the set. diff --git a/src/com/garbagemule/MobArena/ClassLimitManager.java b/src/com/garbagemule/MobArena/ClassLimitManager.java new file mode 100644 index 0000000..d030702 --- /dev/null +++ b/src/com/garbagemule/MobArena/ClassLimitManager.java @@ -0,0 +1,93 @@ +package com.garbagemule.MobArena; + +import java.util.HashMap; +import java.util.Map; + +import com.garbagemule.MobArena.framework.Arena; +import com.garbagemule.MobArena.util.config.ConfigSection; +import com.garbagemule.MobArena.util.config.ConfigUtils; + +public class ClassLimitManager +{ + private HashMap classLimits, classesInUse; + private ConfigSection limits; + private MobArena plugin; + private Map classes; + + public ClassLimitManager(Arena arena, Map classes) { + this.plugin = arena.getPlugin(); + ConfigUtils.addMissingNodes(plugin, plugin.getMAConfig(), "arenas." + arena.configName() + ".class-limits", "class-limits.yml"); + this.limits = new ConfigSection(plugin.getMAConfig(), "arenas." + arena.configName() + ".class-limits"); + //TODO figure out why limits is not loading the proper values from the config + //TODO perhaps send along the limits config section from the ArenaImpl class? + //TODO try to use ArenaRegion's config stuff to set up CLM properly + + this.classes = classes; + this.classLimits = new HashMap(); + this.classesInUse = new HashMap(); + + loadLimitMap(); + initInUseMap(); + } + + private void loadLimitMap() { + for (ArenaClass ac : classes.values()) { + classLimits.put(ac, limits.getInt(ac.getName(), -1)); + } + } + + private void initInUseMap() { + for (ArenaClass ac : classes.values()) { + classesInUse.put(ac, 0); + } + } + + /** + * This is the class a player is changing to + * @param ac the new ArenaClass + */ + public void playerPickedClass(ArenaClass ac) { + classesInUse.put(ac, classesInUse.get(ac) + 1); + debug(); + } + + /** + * This is the class a player left + * @param ac the current/old ArenaClass + */ + public void playerLeftClass(ArenaClass ac) { + classesInUse.put(ac, classesInUse.get(ac) - 1); + debug(); + } + + /** + * Checks to see if a player can pick a specific class + * @param ac the ArenaClass to check + * @return true/false + */ + public boolean canPlayerJoinClass(ArenaClass ac) { + debug(); + if (classLimits.get(ac) <= -1) + return true; + else if (classesInUse.get(ac) >= classLimits.get(ac)) + return false; + else + return true; + } + + public void clearClassesInUse() { + classesInUse.clear(); + initInUseMap(); + debug(); + } + + private void debug() { + System.out.println("classesInUse:"); + for (ArenaClass ac : classesInUse.keySet()) + System.out.println(ac.getName() + " has " + classesInUse.get(ac).intValue() + " players using it."); + System.out.println(); + System.out.println("classLimits:"); + for (ArenaClass ac : classLimits.keySet()) + System.out.println(ac.getName() + " has a limit of " + classLimits.get(ac).intValue() + " players."); + } +} \ No newline at end of file diff --git a/src/com/garbagemule/MobArena/MASpawnThread.java b/src/com/garbagemule/MobArena/MASpawnThread.java index 12355b4..33a342c 100644 --- a/src/com/garbagemule/MobArena/MASpawnThread.java +++ b/src/com/garbagemule/MobArena/MASpawnThread.java @@ -247,6 +247,10 @@ public class MASpawnThread implements Runnable continue; } + // TODO remove debug message + Location l = p.getLocation(); + System.out.println("Player: " + p.getName() + " found at location:" + l.getX() + ", " + l.getY() + ", " + l.getZ()); + Messenger.tellPlayer(p, "Leaving so soon?"); p.getInventory().clear(); arena.playerLeave(p); @@ -299,7 +303,7 @@ public class MASpawnThread implements Runnable Messenger.warning("Could not add null reward. Please check the config-file!"); } else if (reward.getTypeId() == MobArena.ECONOMY_MONEY_ID) { - if (plugin.giveMoney(p, reward.getAmount())) { + if (plugin.giveMoney(p, reward.getAmount())) { // Money already awarded here, not needed at end of match as well Messenger.tellPlayer(p, Msg.WAVE_REWARD, plugin.economyFormat(reward.getAmount())); } else { diff --git a/src/com/garbagemule/MobArena/MonsterManager.java b/src/com/garbagemule/MobArena/MonsterManager.java index 4f97228..4f2d41d 100644 --- a/src/com/garbagemule/MobArena/MonsterManager.java +++ b/src/com/garbagemule/MobArena/MonsterManager.java @@ -17,7 +17,7 @@ import com.garbagemule.MobArena.waves.MABoss; public class MonsterManager { - private Set monsters, sheep; + private Set monsters, sheep, golems; private Set pets; private Map bosses; private Map> suppliers; @@ -25,6 +25,7 @@ public class MonsterManager public MonsterManager() { this.monsters = new HashSet(); this.sheep = new HashSet(); + this.golems = new HashSet(); this.pets = new HashSet(); this.bosses = new HashMap(); this.suppliers = new HashMap>(); @@ -33,6 +34,7 @@ public class MonsterManager public void reset() { monsters.clear(); sheep.clear(); + golems.clear(); pets.clear(); bosses.clear(); suppliers.clear(); @@ -41,6 +43,7 @@ public class MonsterManager public void clear() { removeAll(monsters); removeAll(sheep); + removeAll(golems); removeAll(pets); removeAll(bosses.keySet()); removeAll(suppliers.keySet()); @@ -80,6 +83,18 @@ public class MonsterManager return sheep.remove(e); } + public Set getGolems() { + return golems; + } + + public void addGolem(LivingEntity e) { + golems.add(e); + } + + public boolean removeGolem(LivingEntity e) { + return golems.remove(e); + } + public Set getPets() { return pets; } diff --git a/src/com/garbagemule/MobArena/Msg.java b/src/com/garbagemule/MobArena/Msg.java index da4f453..1641980 100644 --- a/src/com/garbagemule/MobArena/Msg.java +++ b/src/com/garbagemule/MobArena/Msg.java @@ -7,6 +7,7 @@ public enum Msg ARENA_START("Let the slaughter begin!", "Arena started!", Material.REDSTONE_TORCH_ON), ARENA_END("Arena finished.", "Arena finished.", Material.REDSTONE_TORCH_OFF), ARENA_DOES_NOT_EXIST("That arena does not exist. Type /ma arenas for a list.", "Can't find arena."), + ARENA_LBOARD_NOT_FOUND("That arena does not have a leaderboard set up."), JOIN_NOT_ENABLED("MobArena is not enabled.", "MobArena disabled.", Material.REDSTONE_TORCH_OFF), JOIN_IN_OTHER_ARENA("You are already in an arena! Leave that one first.", "In another arena."), JOIN_ARENA_NOT_ENABLED("This arena is not enabled.", "Arena disabled.", Material.REDSTONE_TORCH_OFF), @@ -28,7 +29,9 @@ public enum Msg LEAVE_NOT_PLAYING("You are not in the arena.", "Not in arena."), LEAVE_PLAYER_LEFT("You left the arena. Thanks for playing!", "Left arena.", Material.WOOD_DOOR), PLAYER_DIED("% died!", "% died!", Material.BONE), + GOLEM_DIED("A friendly Golem has died!", "A Golem has died!", Material.PUMPKIN), SPEC_PLAYER_SPECTATE("Enjoy the show!", "Enjoy the show!"), + SPEC_FROM_ARENA("Enjoy the rest of the show!", "Enjoy the show!"), SPEC_NOT_RUNNING("This arena isn't running.", "Arena not running.", Material.REDSTONE_TORCH_OFF), SPEC_EMPTY_INV("Empty your inventory first!", "Empty your inventory.", Material.CHEST), SPEC_ALREADY_PLAYING("Can't spectate when in the arena!", "Already playing!"), @@ -43,6 +46,7 @@ public enum Msg LOBBY_DROP_ITEM("No sharing allowed at this time!", "Can't drop items here."), LOBBY_PLAYER_READY("You have been flagged as ready!", "Flagged as ready!"), LOBBY_PICK_CLASS("You must first pick a class!", "Pick a class first!"), + LOBBY_CLASS_FULL("This class can no longer be selected, class limit reached!", "Class limit reached!"), LOBBY_NOT_ENOUGH_PLAYERS("Not enough players to start. Need at least % players.", "Need more players."), LOBBY_RIGHT_CLICK("Punch the sign. Don't right-click.", "Punch the sign."), LOBBY_CLASS_PICKED("You have chosen % as your class!", "%"), diff --git a/src/com/garbagemule/MobArena/RewardManager.java b/src/com/garbagemule/MobArena/RewardManager.java index 0c0f657..4cee6ad 100644 --- a/src/com/garbagemule/MobArena/RewardManager.java +++ b/src/com/garbagemule/MobArena/RewardManager.java @@ -15,6 +15,7 @@ import com.garbagemule.MobArena.framework.Arena; public class RewardManager { + @SuppressWarnings("unused") private MobArena plugin; @SuppressWarnings("unused") private Arena arena; @@ -57,13 +58,12 @@ public class RewardManager } if (stack.getTypeId() == MobArena.ECONOMY_MONEY_ID) { - plugin.giveMoney(p, stack.getAmount()); + // plugin.giveMoney(p, stack.getAmount()); - removed to fix double money rewards continue; } p.getInventory().addItem(stack); } - rewarded.add(p); } -} +} \ No newline at end of file diff --git a/src/com/garbagemule/MobArena/commands/CommandHandler.java b/src/com/garbagemule/MobArena/commands/CommandHandler.java index 2c2fa65..c49eaa4 100644 --- a/src/com/garbagemule/MobArena/commands/CommandHandler.java +++ b/src/com/garbagemule/MobArena/commands/CommandHandler.java @@ -185,6 +185,7 @@ public class CommandHandler implements CommandExecutor register(RemoveClassCommand.class); register(RemoveClassPermCommand.class); register(RemoveContainerCommand.class); + register(RemoveLeaderboardCommand.class); register(RemoveSpawnpointCommand.class); register(SetArenaCommand.class); register(SetClassCommand.class); diff --git a/src/com/garbagemule/MobArena/commands/setup/ListClassesCommand.java b/src/com/garbagemule/MobArena/commands/setup/ListClassesCommand.java index fc08fc0..b13d938 100644 --- a/src/com/garbagemule/MobArena/commands/setup/ListClassesCommand.java +++ b/src/com/garbagemule/MobArena/commands/setup/ListClassesCommand.java @@ -10,7 +10,7 @@ import com.garbagemule.MobArena.framework.ArenaMaster; @CommandInfo( name = "listclasses", - pattern = "(list)?class(.)*", + pattern = "(list)?classes(.)*", usage = "/ma listclasses", desc = "list all current classes", permission = "mobarena.setup.classes" diff --git a/src/com/garbagemule/MobArena/commands/setup/RemoveLeaderboardCommand.java b/src/com/garbagemule/MobArena/commands/setup/RemoveLeaderboardCommand.java new file mode 100644 index 0000000..74eba70 --- /dev/null +++ b/src/com/garbagemule/MobArena/commands/setup/RemoveLeaderboardCommand.java @@ -0,0 +1,56 @@ +package com.garbagemule.MobArena.commands.setup; + +import org.bukkit.command.CommandSender; + +import com.garbagemule.MobArena.Messenger; +import com.garbagemule.MobArena.Msg; +import com.garbagemule.MobArena.commands.Command; +import com.garbagemule.MobArena.commands.CommandInfo; +import com.garbagemule.MobArena.framework.ArenaMaster; + +@CommandInfo( + name = "removeleaderboard", + pattern = "(del(.)*|r(e)?m(ove)?)leaderboard", + usage = "/ma removeleaderboard ", + desc = "remove the selected arena's leaderboard", + permission = "mobarena.setup.leaderboards" + ) +public class RemoveLeaderboardCommand implements Command{ + + @Override + public boolean execute(ArenaMaster am, CommandSender sender, String... args) { + // Grab the argument, if any. + String arg1 = (args.length > 0 ? args[0] : ""); + + // If no argument, use the currently selected arena + if (arg1.equals("")) { + if (am.getSelectedArena().getRegion().getLeaderboard() != null) { + am.getSelectedArena().getRegion().set("leaderboard", null); + Messenger.tellPlayer(sender, "Leaderboard for " + am.getSelectedArena().arenaName() + " successfully removed!"); + return true; + } + else { + Messenger.tellPlayer(sender, Msg.ARENA_LBOARD_NOT_FOUND); + } + } + else { + if (am.getArenaWithName(arg1) != null) { + if (am.getSelectedArena().getRegion().getLeaderboard() != null) { + am.getArenaWithName(arg1).getRegion().set("leaderboard", null); + Messenger.tellPlayer(sender, "Leaderboard for " + am.getArenaWithName(arg1).arenaName() + " successfully removed!"); + return true; + } + else { + Messenger.tellPlayer(sender, Msg.ARENA_LBOARD_NOT_FOUND); + } + } + else { + Messenger.tellPlayer(sender, "Usage: /ma removeleaderboard "); + return false; + } + } + + return false; + } + +} \ No newline at end of file diff --git a/src/com/garbagemule/MobArena/commands/user/JoinCommand.java b/src/com/garbagemule/MobArena/commands/user/JoinCommand.java index 4bb74f6..ef55c45 100644 --- a/src/com/garbagemule/MobArena/commands/user/JoinCommand.java +++ b/src/com/garbagemule/MobArena/commands/user/JoinCommand.java @@ -29,17 +29,24 @@ public class JoinCommand implements Command String arg1 = (args.length > 0 ? args[0] : null); // Run some rough sanity checks, and grab the arena to join. - Arena arena = Commands.getArenaToJoinOrSpec(am, p, arg1); - if (arena == null) { + Arena toArena = Commands.getArenaToJoinOrSpec(am, p, arg1); + Arena fromArena = am.getArenaWithPlayer(p); + if (toArena == null) { + return false; + } + + // Deny joining from other arenas + if (fromArena != null && (fromArena.inArena(p) || fromArena.inLobby(p))) { + Messenger.tellPlayer(p, Msg.JOIN_ALREADY_PLAYING); return false; } // Per-arena sanity checks - if (!arena.canJoin(p)) { + if (!toArena.canJoin(p)) { return false; } // Join the arena! - return arena.playerJoin(p, p.getLocation()); + return toArena.playerJoin(p, p.getLocation()); } } diff --git a/src/com/garbagemule/MobArena/framework/Arena.java b/src/com/garbagemule/MobArena/framework/Arena.java index c194c69..2a73079 100644 --- a/src/com/garbagemule/MobArena/framework/Arena.java +++ b/src/com/garbagemule/MobArena/framework/Arena.java @@ -13,6 +13,7 @@ import org.bukkit.inventory.ItemStack; import com.garbagemule.MobArena.ArenaClass; import com.garbagemule.MobArena.ArenaListener; import com.garbagemule.MobArena.ArenaPlayer; +import com.garbagemule.MobArena.ClassLimitManager; import com.garbagemule.MobArena.MASpawnThread; import com.garbagemule.MobArena.MobArena; import com.garbagemule.MobArena.MonsterManager; @@ -48,6 +49,10 @@ public interface Arena public void setProtected(boolean value); + public boolean isLogging(); + + public void setLogging(boolean value); + public boolean isRunning(); public boolean inEditMode(); @@ -100,6 +105,8 @@ public interface Arena public MonsterManager getMonsterManager(); + public ClassLimitManager getClassLimitManager(); + public void revivePlayer(Player p); public ArenaLog getLog(); @@ -171,6 +178,8 @@ public interface Arena ////////////////////////////////////////////////////////////////////*/ public void assignClass(Player p, String className); + + public void addRandomPlayer(Player p); public void assignRandomClass(Player p); diff --git a/src/com/garbagemule/MobArena/listeners/MAGlobalListener.java b/src/com/garbagemule/MobArena/listeners/MAGlobalListener.java index 71af19d..fb868ba 100644 --- a/src/com/garbagemule/MobArena/listeners/MAGlobalListener.java +++ b/src/com/garbagemule/MobArena/listeners/MAGlobalListener.java @@ -40,7 +40,7 @@ public class MAGlobalListener implements Listener // // /////////////////////////////////////////////////////////////////////////// - + //TODO watch block physics, piston extend, and piston retract events @EventHandler(priority = EventPriority.HIGHEST) public void blockBreak(BlockBreakEvent event) { for (Arena arena : am.getArenas()) diff --git a/src/com/garbagemule/MobArena/log/YMLSessionBuilder.java b/src/com/garbagemule/MobArena/log/YMLSessionBuilder.java index 3a2b7ee..d5f2cc1 100644 --- a/src/com/garbagemule/MobArena/log/YMLSessionBuilder.java +++ b/src/com/garbagemule/MobArena/log/YMLSessionBuilder.java @@ -16,9 +16,9 @@ import com.garbagemule.MobArena.util.config.Config; public class YMLSessionBuilder implements LogSessionBuilder { - private final String GENERAL = "general-info."; - private final String PLAYERS = "players."; - private final String CLASSES = "class-distribution."; + private final String GENERAL = "general-info"; + private final String PLAYERS = "players"; + private final String CLASSES = "class-distribution"; private Config config; private long start, end; @@ -31,42 +31,42 @@ public class YMLSessionBuilder implements LogSessionBuilder @Override public void buildStartTime() { start = new Date().getTime(); - config.set(GENERAL + "start-time", TimeUtils.toDateTime(start)); + config.set(GENERAL + ".start-time", TimeUtils.toDateTime(start)); } @Override public void buildEndTime() { end = new Date().getTime(); - config.set(GENERAL + "end-time", TimeUtils.toDateTime(end)); + config.set(GENERAL + ".end-time", TimeUtils.toDateTime(end)); } @Override public void buildDuration() { String duration = TimeUtils.toTime(end - start); - config.set(GENERAL + "duration", duration); + config.set(GENERAL + ".duration", duration); } @Override public void buildLastWave(int lastWave) { - config.set(GENERAL + "last-wave", lastWave); + config.set(GENERAL + ".last-wave", lastWave); } @Override public void buildNumberOfPlayers(int amount) { - config.set(GENERAL + "number-of-players", amount); + config.set(GENERAL + ".number-of-players", amount); } @Override public void buildClassDistribution(Map classDistribution) { for (Entry entry : classDistribution.entrySet()) { int amount = entry.getValue().value(); - config.set(CLASSES + entry.getKey(), amount); + config.set(CLASSES + "." + entry.getKey(), amount); } } @Override public void buildPlayerEntry(ArenaLogPlayerEntry entry, List rewards) { - String path = PLAYERS + entry.playername + "."; + String path = PLAYERS + "." + entry.playername + "."; // Name and class config.set(path + "name", entry.playername); @@ -106,8 +106,11 @@ public class YMLSessionBuilder implements LogSessionBuilder } private void reset() { - config.set(GENERAL, null); - config.set(CLASSES, null); - config.set(PLAYERS, null); + if(config.get(GENERAL) != null) + config.set(GENERAL, null); + if(config.get(CLASSES) != null) + config.set(CLASSES, null); + if(config.get(PLAYERS) != null) + config.set(PLAYERS, null); } } diff --git a/src/com/garbagemule/MobArena/region/ArenaRegion.java b/src/com/garbagemule/MobArena/region/ArenaRegion.java index d437976..1adc7eb 100644 --- a/src/com/garbagemule/MobArena/region/ArenaRegion.java +++ b/src/com/garbagemule/MobArena/region/ArenaRegion.java @@ -193,7 +193,7 @@ public class ArenaRegion // Region expand public void expandUp(int amount) { - p2.setY(Math.min(127D, p2.getY() + amount)); + p2.setY(Math.min(arena.getWorld().getMaxHeight(), p2.getY() + amount)); set(RegionPoint.P2, p2); } @@ -221,7 +221,7 @@ public class ArenaRegion // Lobby expand public void expandLobbyUp(int amount) { - l2.setY(Math.min(127D, l2.getY() + amount)); + l2.setY(Math.min(arena.getWorld().getMaxHeight(), l2.getY() + amount)); set(RegionPoint.L2, l2); } diff --git a/src/com/garbagemule/MobArena/util/ItemParser.java b/src/com/garbagemule/MobArena/util/ItemParser.java index 12d45c4..6bc59ed 100644 --- a/src/com/garbagemule/MobArena/util/ItemParser.java +++ b/src/com/garbagemule/MobArena/util/ItemParser.java @@ -57,12 +57,12 @@ public class ItemParser int lvl = entry.getValue(); // :; - enchantments += "; " + id + ":" + lvl; + enchantments += ";" + id + ":" + lvl; } // Trim off the leading ';' if it is there if (!enchantments.equals("")) { - enchantments = enchantments.substring(2); + enchantments = enchantments.substring(1); } // @@ -149,7 +149,7 @@ public class ItemParser } private static ItemStack withDataAndAmount(String item, String data, String amount) { - Material m = getMaterial(item.toUpperCase()); + Material m = getMaterial(item); short d = getData(data, m); int a = getAmount(amount); diff --git a/src/com/garbagemule/MobArena/waves/MACreature.java b/src/com/garbagemule/MobArena/waves/MACreature.java index 681f286..9cd8686 100644 --- a/src/com/garbagemule/MobArena/waves/MACreature.java +++ b/src/com/garbagemule/MobArena/waves/MACreature.java @@ -89,6 +89,7 @@ public enum MACreature public LivingEntity spawn(Arena arena, World world, Location loc) { LivingEntity e = world.spawnCreature(loc, type); + //TODO change this to: LivingEntity e = (LivingEntity) world.spawnEntity(loc, type); switch (this) { case SHEEP: diff --git a/src/com/garbagemule/MobArena/waves/WaveParser.java b/src/com/garbagemule/MobArena/waves/WaveParser.java index 7920ee2..0bc9bf4 100644 --- a/src/com/garbagemule/MobArena/waves/WaveParser.java +++ b/src/com/garbagemule/MobArena/waves/WaveParser.java @@ -250,9 +250,9 @@ public class WaveParser } } - // As well as the ability interval. - int interval = config.getInt("ability-interval", 3) * 20; - result.setAbilityInterval(interval); + // As well as the ability interval and ability announce. + result.setAbilityInterval(config.getInt("ability-interval", 3) * 20); + result.setAbilityAnnounce(config.getBoolean("ability-announce", true)); return result; } diff --git a/src/com/garbagemule/MobArena/waves/types/BossWave.java b/src/com/garbagemule/MobArena/waves/types/BossWave.java index b9814fd..e5d6045 100644 --- a/src/com/garbagemule/MobArena/waves/types/BossWave.java +++ b/src/com/garbagemule/MobArena/waves/types/BossWave.java @@ -25,7 +25,7 @@ public class BossWave extends AbstractWave private BossHealth health; private List abilities; - private boolean activated; + private boolean activated, abilityAnnounce; private int abilityInterval; @@ -34,6 +34,7 @@ public class BossWave extends AbstractWave this.bosses = new HashSet(); this.abilities = new ArrayList(); this.activated = false; + this.abilityAnnounce = false; this.setType(WaveType.BOSS); } @@ -78,6 +79,14 @@ public class BossWave extends AbstractWave this.abilityInterval = abilityInterval; } + public boolean getAbilityAnnounce() { + return abilityAnnounce; + } + + public void setAbilityAnnounce(boolean abilityAnnounce) { + this.abilityAnnounce = abilityAnnounce; + } + public void activateAbilities(Arena arena) { if (activated) { return; @@ -89,7 +98,9 @@ public class BossWave extends AbstractWave } public void announceAbility(Ability ability, MABoss boss, Arena arena) { - AbilityInfo info = ability.getClass().getAnnotation(AbilityInfo.class); - Messenger.tellAll(arena, Msg.WAVE_BOSS_ABILITY, info.name()); + if(getAbilityAnnounce()) { + AbilityInfo info = ability.getClass().getAnnotation(AbilityInfo.class); + Messenger.tellAll(arena, Msg.WAVE_BOSS_ABILITY, info.name()); + } } }