diff --git a/MobArena.jar b/MobArena.jar index d54f03b..66067b4 100644 Binary files a/MobArena.jar and b/MobArena.jar differ diff --git a/resources/plugin.yml b/resources/plugin.yml index 35f45f8..eab0b29 100644 --- a/resources/plugin.yml +++ b/resources/plugin.yml @@ -1,6 +1,6 @@ name: MobArena main: com.garbagemule.MobArena.MobArena -version: 0.94.4.3 +version: 0.94.4.4 softdepend: [Spout,Permissions,MultiVerse,XcraftGate,Towny,Heroes,MagicSpells] commands: ma: diff --git a/resources/plugin_other.yml b/resources/plugin_other.yml deleted file mode 100644 index 4011d0a..0000000 --- a/resources/plugin_other.yml +++ /dev/null @@ -1,155 +0,0 @@ -name: MobArena -main: garbagemule.mobarena.MobArenaPlugin -version: 0.94.3.24 -softdepend: [Spout,Permissions,MultiVerse,XcraftGate,Towny,Heroes,MagicSpells] -commands: - ma: - description: Base command for MobArena - usage: | - YOU HAVE AN ERROR! - Find the error in your server log, copy it into - http://pastebin.com, and then paste the link - in the IRC or on the forums. - mobarena: - description: Base command for MobArena - usage: | - YOU HAVE AN ERROR! - Find the error in your server log, copy it into - http://pastebin.com, and then paste the link - in the IRC or on the forums. -permissions: - mobarena.use: - description: Gives access to usage commands - default: true - children: - mobarena.use.join: true - mobarena.use.spec: true - mobarena.use.leave: true - mobarena.use.join: - default: true - mobarena.use.spec: - default: true - mobarena.use.leave: - default: true - - mobarena.admin: - description: Gives access to all admin commands - default: op - children: - mobarena.admin.enable: true - mobarena.admin.kick: true - mobarena.admin.restore: true - mobarena.admin.force.end: true - mobarena.admin.force.start: true - mobarena.admin.config.reload: true - mobarena.admin.enable: - description: Enable and disable MobArena and/or arenas. - default: false - mobarena.admin.kick: - description: Kick a player from an arena. - default: false - mobarena.admin.restore: - description: Restore a player's inventory. - default: false - mobarena.admin.force.end: - description: Force end an arena. - default: false - mobarena.admin.force.start: - description: Force start an arena. - default: false - mobarena.admin.config.reload: - description: Reload the config-file. - default: false - - mobarena.setup: - description: Gives access to all setup commands - default: op - children: - mobarena.setup.arena: true - mobarena.setup.setarena: true - mobarena.setup.addarena: true - mobarena.setup.delarena: true - mobarena.setup.protect: true - mobarena.setup.editarena: true - mobarena.setup.setregion: true - mobarena.setup.expandregion: true - mobarena.setup.showregion: true - mobarena.setup.setlobbyregion: true - mobarena.setup.expandlobbyregion: true - mobarena.setup.setwarp: true - mobarena.setup.spawnpoints: true - mobarena.setup.addspawn: true - mobarena.setup.delspawn: true - 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 - mobarena.setup.arena: - description: Check which arena is the currently selected arena. - default: false - mobarena.setup.setarena: - description: Select a new arena. - default: false - mobarena.setup.addarena: - description: Add a new arena node. - default: false - mobarena.setup.delarena: - description: Delete an arena. - default: false - mobarena.setup.protect: - description: Turn arena protection on/off. - default: false - mobarena.setup.editarena: - description: Turn editmode on/off. - default: false - mobarena.setup.setregion: - description: Set region points p1/p2. - default: false - mobarena.setup.expandregion: - description: Expand arena region. - default: false - mobarena.setup.showregion: - description: Show arena region. - default: false - mobarena.setup.setlobbyregion: - description: Set lobby region points l1/l2. - default: false - mobarena.setup.expandlobbyregion: - description: Expand lobby region. - default: false - mobarena.setup.setwarp: - description: Set warp points arena/lobby/spectator. - default: false - mobarena.setup.spawnpoints: - description: List all spawnpoints. - default: false - mobarena.setup.addspawn: - description: Add a new spawnpoint. - default: false - mobarena.setup.delspawn: - description: Delete a spawnpoint. - default: false - mobarena.setup.containers: - description: List all containers. - default: false - mobarena.setup.addcontainer: - description: Add a new container. - default: false - 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 - mobarena.setup.autogenerate: - description: Auto-generate an arena. - default: false - mobarena.setup.autodegenerate: - description: Auto-degenerate an arena. - default: false \ No newline at end of file diff --git a/src/com/garbagemule/MobArena/Arena.java b/src/com/garbagemule/MobArena/Arena.java index 897c518..69dba39 100644 --- a/src/com/garbagemule/MobArena/Arena.java +++ b/src/com/garbagemule/MobArena/Arena.java @@ -1,67 +1,28 @@ package com.garbagemule.MobArena; -import java.io.File; -import java.io.FileInputStream; -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; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.TreeSet; +import java.util.*; import java.util.concurrent.PriorityBlockingQueue; -import net.minecraft.server.WorldServer; - import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Chunk; import org.bukkit.GameMode; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; -import org.bukkit.block.BlockState; -import org.bukkit.block.ContainerBlock; -import org.bukkit.craftbukkit.CraftWorld; -import org.bukkit.craftbukkit.entity.CraftEntity; -import org.bukkit.entity.Creature; -import org.bukkit.entity.CreatureType; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Item; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; -import org.bukkit.entity.Slime; import org.bukkit.entity.Wolf; -import org.bukkit.event.entity.EntityRegainHealthEvent; -import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.PlayerInventory; import org.bukkit.permissions.PermissionAttachment; -import org.bukkit.util.config.Configuration; +//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; -import com.garbagemule.MobArena.spout.Spouty; -import com.garbagemule.MobArena.util.Delays; -import com.garbagemule.MobArena.util.InventoryItem; -import com.garbagemule.MobArena.util.WaveUtils; +import com.garbagemule.MobArena.util.Config; import com.garbagemule.MobArena.waves.BossWave; import com.garbagemule.MobArena.waves.Wave; -import com.garbagemule.MobArena.waves.Wave.WaveBranch; -public class Arena +public abstract class Arena { private MobArena plugin; @@ -108,7 +69,7 @@ public class Arena // Other settings protected int minPlayers, maxPlayers, joinDistance; - protected List classes = new LinkedList(); + protected Set classes = new HashSet(); protected Map locations = new HashMap(); protected Map healthMap = new HashMap(); protected Map hungerMap = new HashMap(); @@ -123,6 +84,10 @@ public class Arena protected PriorityBlockingQueue repairQueue; + public Arena() { + + } + /** * Primary constructor. Requires a name and a world. */ @@ -167,556 +132,45 @@ public class Arena repairQueue = new PriorityBlockingQueue(100, new RepairableComparator()); } - public boolean startArena() - { - // Sanity-checks - if (running || lobbyPlayers.isEmpty() || !readyPlayers.containsAll(lobbyPlayers)) - return false; - if (!softRestore && forceRestore && !serializeRegion()) - return false; - - // Store all chest contents. - storeContainerContents(); - - // Populate arenaPlayers and clear the lobby. - arenaPlayers.addAll(lobbyPlayers); - lobbyPlayers.clear(); - readyPlayers.clear(); - - // Assign random classes. - for (Player p : randoms) - assignRandomClass(p); - if (arenaPlayers.isEmpty()) - return false; - - // Teleport players, give full health, initialize maps - for (Player p : arenaPlayers) - { - p.teleport(arenaLoc); - setHealth(p, 20); - p.setFoodLevel(10); - assignClassPermissions(p); - arenaPlayerMap.put(p, new ArenaPlayer(p, this, plugin)); - } - - // Copy the singleWaves Set for polling. - singleWavesInstance = new TreeSet(singleWaves); - - // Start spawning monsters (must happen before 'running = true;') - startSpawning(); - startBouncingSheep(); - - // Set the boolean. - running = true; - - // Spawn pets (must happen after 'running = true;') - spawnPets(); - - // Start logging - log = new ArenaLog(plugin, this); - log.start(); - - // Initialize leaderboards and start displaying info. - leaderboard.initialize(); - leaderboard.startTracking(); - - // Announce and notify. - MAUtils.tellAll(this, Msg.ARENA_START); - - for (MobArenaListener listener : plugin.getAM().listeners) - listener.onArenaStart(this); - - return true; - } + public abstract boolean startArena(); - public boolean endArena() - { - // Sanity-checks. - if (!running || !arenaPlayers.isEmpty()) - { - //System.out.println("Arena was not ended, playercount: " + arenaPlayers.size()); - return false; - } - //else System.out.println("Arena ending..."); - - // Set the boolean. - running = false; - - // Stop tracking leaderboards - leaderboard.stopTracking(); - leaderboard.update(); - - // Finish logging - log.end(); - if (logging != null) - { - log.saveSessionData(); - log.updateArenaTotals(); - } - log.clearSessionData(); - - // Stop spawning. - stopSpawning(); - - // Clean arena floor. - cleanup(); - - // Restore region. - if (softRestore) - restoreRegion(); - else if (forceRestore) - deserializeRegion(); - - // Restore chests - restoreContainerContents(); - - // Announce and clear sets. - MAUtils.tellAll(this, Msg.ARENA_END, true); - arenaPlayers.clear(); - arenaPlayerMap.clear(); - lobbyPlayers.clear(); - readyPlayers.clear(); - notifyPlayers.clear(); - rewardedPlayers.clear(); - classMap.clear(); - - // Notify listeners. - for (MobArenaListener listener : plugin.getAM().listeners) - listener.onArenaEnd(this); - - return true; - } + public abstract boolean endArena(); - public void forceStart() - { - if (running) - return; - - // Set operations. - Set tmp = new HashSet(); - tmp.addAll(lobbyPlayers); - tmp.removeAll(readyPlayers); - - // Force leave. - for (Player p : tmp) - { - plugin.getAM().arenaMap.remove(p); - playerLeave(p); - } - } + public abstract void forceStart(); - public void forceEnd() - { - Bukkit.getServer().getScheduler().cancelTask(spawnTaskId); - Bukkit.getServer().getScheduler().cancelTask(sheepTaskId); - - for (Player p : getAllPlayers()) - playerLeave(p); - - for (Entity e : monsters) - if (e != null) e.remove(); - - if (bossWave != null) - bossWave.clear(); - - arenaPlayers.clear(); - lobbyPlayers.clear(); - readyPlayers.clear(); - - cleanup(); - - spawnTaskId = -1; - sheepTaskId = -1; - } + public abstract void forceEnd(); - public void playerJoin(Player p, Location loc) - { - storePlayerData(p, loc); - MAUtils.sitPets(p); - setHealth(p, 20); - p.setFoodLevel(10); - p.setGameMode(GameMode.SURVIVAL); - movePlayerToLobby(p); - - // Notify listeners. - for (MobArenaListener listener : plugin.getAM().listeners) - listener.onPlayerJoin(this, p); - - if (MobArena.hasSpout && spoutSelect) - Spouty.classSelectionScreen(plugin, this, p); - } + public abstract void playerJoin(Player p, Location loc); - public void playerReady(Player p) - { - readyPlayers.add(p); - - if (minPlayers > 0 && lobbyPlayers.size() < minPlayers) - { - MAUtils.tellPlayer(p, Msg.LOBBY_NOT_ENOUGH_PLAYERS, "" + minPlayers); - return; - } - - startArena(); - } + public abstract void playerReady(Player p); - public void playerLeave(Player p) - { - finishArenaPlayer(p, false); - movePlayerToEntry(p); - discardPlayer(p); - - // Notify listeners. - for (MobArenaListener listener : plugin.getAM().listeners) - listener.onPlayerLeave(this, p); - - // End arena if possible. - endArena(); - } + public abstract void playerLeave(Player p); - public void playerDeath(Player p) - { - finishArenaPlayer(p, true); - - if (specOnDeath) - { - clearPlayer(p); - movePlayerToSpec(p); - } - else - { - movePlayerToEntry(p); - discardPlayer(p); - } - - if (running && spawnThread != null) - spawnThread.updateTargets(); - - MAUtils.tellAll(this, Msg.PLAYER_DIED, p.getName()); - Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, - new Runnable() - { - public void run() - { - endArena(); - } - }); - - // Notify listeners. - for (MobArenaListener listener : plugin.getAM().listeners) - listener.onPlayerDeath(this, p); - } + public abstract void playerDeath(Player p); - public void playerSpec(Player p, Location loc) - { - storePlayerData(p, loc); - MAUtils.sitPets(p); - movePlayerToSpec(p); - } - - private void spawnPets() - { - for (Map.Entry entry : petMap.entrySet()) - { - // Remove the bones from the inventory. - Player p = entry.getKey(); - p.getInventory().removeItem(new ItemStack(Material.BONE, entry.getValue())); - - // Spawn wolves, set owner and health, and add to pet set. - for (int i = 0; i < entry.getValue(); i++) - { - Wolf wolf = (Wolf) world.spawnCreature(p.getLocation(), CreatureType.WOLF); - wolf.setTamed(true); - wolf.setOwner(p); - wolf.setHealth(20); - if (hellhounds) - wolf.setFireTicks(32768); - pets.add(wolf); - } - } - } + public abstract void playerSpec(Player p, Location loc); - private void startSpawning() - { - // Set the spawn flags to enable monster spawning. - MAUtils.setSpawnFlags(plugin, world, 1, allowMonsters, allowAnimals); - - // Start the spawnThread. - spawnThread = new MASpawnThread(plugin, this); - spawnTaskId = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, spawnThread, waveDelay, (!waveClear) ? waveInterval : 60); - } + public abstract void playerKill(Player p); - private void stopSpawning() - { - // Stop the spawn thread. - if (spawnThread != null) - { - Bukkit.getServer().getScheduler().cancelTask(spawnThread.getTaskId()); - Bukkit.getServer().getScheduler().cancelTask(spawnTaskId); - Bukkit.getServer().getScheduler().cancelTask(sheepTaskId); - spawnTaskId = -1; - sheepTaskId = -1; - spawnThread = null; - currentWave = null; - } - else System.out.println("--------- THE SPAWNTHREAD IS NULL! ----------"); - - // Restore spawn flags. - MAUtils.setSpawnFlags(plugin, world, spawnMonsters, allowMonsters, allowAnimals); - } + public abstract void restoreInvAndGiveRewardsDelayed(final Player p); - private void startBouncingSheep() - { - sheepTaskId = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, - new Runnable() - { - public void run() - { - if (explodingSheep.isEmpty()) return; - - for (LivingEntity e : new LinkedList(explodingSheep)) - { - if (e == null) continue; - - Creature c = (Creature) e; - LivingEntity target = c.getTarget(); - if (target != null && target instanceof Player && MAUtils.distanceSquared((Player) target, e.getLocation()) < 8D) - { - CraftEntity ce = (CraftEntity) e; - CraftWorld cw = (CraftWorld) e.getWorld(); - WorldServer ws = cw.getHandle(); - ws.createExplosion(ce.getHandle(), e.getLocation().getX(), e.getLocation().getY() + 1, e.getLocation().getZ(), 2f, false); - e.remove(); - } - - if (e.isDead()) - { - explodingSheep.remove(e); - continue; - } - - if (Math.abs(e.getVelocity().getY()) < 1) - e.setVelocity(e.getVelocity().setY(0.5)); - } - } - }, waveDelay, 20); - } + public abstract void restoreInvAndGiveRewards(final Player p); - private void updateChunk(Location loc) - { - if (!arenaPlayers.isEmpty() || !world.getName().equals(loc.getWorld().getName())) - return; - - Chunk chunk = world.getChunkAt(loc); - if (!world.isChunkLoaded(chunk)) - world.loadChunk(chunk); - else - world.refreshChunk(chunk.getX(), chunk.getZ()); - } + public abstract void storePlayerData(Player p, Location loc); - public void playerKill(Player p) - { - if (p == null || log.players.get(p) == null) - return; - - arenaPlayerMap.get(p).getStats().kills++; - } + public abstract void storeContainerContents(); - public void restoreInvAndGiveRewardsDelayed(final Player p) - { - final List rewards = log != null && log.players.get(p) != null ? log.players.get(p).rewards : new LinkedList(); - final boolean hadRewards = rewardedPlayers.contains(p); - - Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, - new Runnable() - { - public void run() - { - if (!emptyInvJoin) - MAUtils.restoreInventory(p); - - if (hadRewards) - return; - - MAUtils.giveRewards(p, rewards, plugin); - if (running) - rewardedPlayers.add(p); - } - }); - } + public abstract void restoreContainerContents(); - public void restoreInvAndGiveRewards(final Player p) - { - if (!emptyInvJoin) - MAUtils.restoreInventory(p); - - if (rewardedPlayers.contains(p)) - return; - - final List rewards = (log != null && log.players.get(p) != null) ? - log.players.get(p).rewards : - new LinkedList(); - - MAUtils.giveRewards(p, rewards, plugin); - if (running) - rewardedPlayers.add(p); - } + public abstract void movePlayerToLobby(Player p); - public void storePlayerData(Player p, Location loc) - { - plugin.getAM().arenaMap.put(p, this); - - if (!locations.containsKey(p)) - locations.put(p, loc); - - if (!healthMap.containsKey(p)) - healthMap.put(p, p.getHealth()); - - if (!hungerMap.containsKey(p)) - hungerMap.put(p, p.getFoodLevel()); - - if (!modeMap.containsKey(p)) - modeMap.put(p, p.getGameMode()); - } + public abstract void movePlayerToSpec(Player p); - public void storeContainerContents() - { - Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, - new Runnable() - { - public void run() - { - for (Location loc : containers.values()) - { - BlockState state = world.getBlockAt(loc).getState(); - if (state instanceof ContainerBlock) - containables.add(new RepairableContainer(state, false)); - } - } - }); - } + public abstract void movePlayerToEntry(Player p); - public void restoreContainerContents() - { - Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, - new Runnable() - { - public void run() - { - for (Repairable r : containables) - r.repair(); - } - }); - } + public abstract void repairBlocks(); - public void movePlayerToLobby(Player p) - { - updateChunk(lobbyLoc); - lobbyPlayers.add(p); - p.teleport(lobbyLoc); - } - - public void movePlayerToSpec(Player p) - { - updateChunk(spectatorLoc); - specPlayers.add(p); - p.teleport(spectatorLoc); - } - - public void movePlayerToEntry(Player p) - { - Location entry = locations.get(p); - if (entry == null || p.isDead()) return; - - updateChunk(entry); - p.teleport(entry); - } - - private void clearPlayer(Player p) - { - if (healthMap.containsKey(p)) - { - int health = healthMap.remove(p); - setHealth(p, health); - } - - if (hungerMap.containsKey(p)) - p.setFoodLevel(hungerMap.remove(p)); - - if (modeMap.containsKey(p)) - p.setGameMode(modeMap.remove(p)); - - // Put out fire. - Delays.douse(plugin, p, 3); - - // Remove pets. - removePets(p); - - // readyPlayers before lobbyPlayers because of startArena sanity-checks - readyPlayers.remove(p); - specPlayers.remove(p); - arenaPlayers.remove(p); - lobbyPlayers.remove(p); - classMap.remove(p); - arenaPlayerMap.remove(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); - clearPlayer(p); - } - - /** - * Give the player back his inventory and record his last wave. - * Called when a player dies or leaves prematurely. - * @param p A player - * @param dead If the player died or not - */ - private void finishArenaPlayer(Player p, boolean dead) - { - if (!arenaPlayers.contains(p) && !lobbyPlayers.contains(p)) - return; - - removeClassPermissions(p); - MAUtils.clearInventory(p); - - if (dead) restoreInvAndGiveRewardsDelayed(p); - else restoreInvAndGiveRewards(p); - - ArenaPlayer ap = arenaPlayerMap.get(p); - if (ap != null) - ap.setDead(true); - } - - private void setHealth(Player p, int health) - { - // Grab the current health - int current = p.getHealth(); - - // If the health is 20, just leave it at that no matter what. - int regain = health == 20 ? 20 : health - current; - - // Set the health, and fire off the event. - p.setHealth(health); - EntityRegainHealthEvent event = new EntityRegainHealthEvent(p, regain, RegainReason.CUSTOM); - Bukkit.getPluginManager().callEvent(event); - } - - public void repairBlocks() - { - while (!repairQueue.isEmpty()) - repairQueue.poll().repair(); - } - - public void queueRepairable(Repairable r) - { - repairQueue.add(r); - } + public abstract void queueRepairable(Repairable r); @@ -726,138 +180,13 @@ public class Arena // ////////////////////////////////////////////////////////////////////*/ - public void assignClass(Player p, String className) - { - petMap.remove(p); - randoms.remove(p); - classMap.put(p, className); - - MAUtils.clearInventory(p); - - // If random, don't give any items yet. - if (className.equalsIgnoreCase("random")) - { - randoms.add(p); - return; - } - - MAUtils.giveItems(p, classItems.get(className), autoEquip, plugin); - MAUtils.giveItems(p, classArmor.get(className), autoEquip, plugin); - - int pets = MAUtils.getPetAmount(p); - if (pets > 0) petMap.put(p, pets); - } + public abstract void assignClass(Player p, String className); - public void assignRandomClass(Player p) - { - Random r = new Random(); - List classes = new LinkedList(plugin.getAM().classes); - - String className = classes.remove(r.nextInt(classes.size())); - while (!plugin.has(p, "mobarena.classes." + className)) - { - if (classes.isEmpty()) - { - MobArena.info("Player '" + p.getName() + "' has no class permissions!"); - playerLeave(p); - return; - } - className = classes.remove(r.nextInt(classes.size())); - } - - assignClass(p, className); - MAUtils.tellPlayer(p, Msg.LOBBY_CLASS_PICKED, className); - } + public abstract void assignRandomClass(Player p); - public void assignClassPermissions(Player p) - { - Map perms = classPerms.get(classMap.get(p)); - if (perms == null || perms.isEmpty()) return; - - PermissionAttachment pa = p.addAttachment(plugin); - attachments.put(p,pa); - for (Map.Entry entry : perms.entrySet()) - pa.setPermission(entry.getKey(), entry.getValue()); - } + public abstract void assignClassPermissions(Player p); - public void removeClassPermissions(Player p) - { - if (attachments.get(p) == null) return; - - for (PermissionAttachment pa : attachments.values()) - if (pa != null) pa.remove(); - } - - private void cleanup() - { - removeMonsters(); - removeBlocks(); - removePets(); - removeEntities(); - monsters.clear(); - explodingSheep.clear(); - plaguedPigs.clear(); - madCows.clear(); - blocks.clear(); - pets.clear(); - } - - private void removeMonsters() - { - if (bossWave != null) - bossWave.clear(); - for (LivingEntity e : monsters) - if (e != null) e.remove(); - for (LivingEntity e : explodingSheep) - if (e != null) e.remove(); - for (LivingEntity e : plaguedPigs) - if (e != null) e.remove(); - for (LivingEntity e : madCows) - if (e != null) e.remove(); - } - - private void removeBlocks() - { - for (Block b : blocks) - b.setTypeId(0); - } - - private void removePets() - { - for (Wolf w : pets) - { - if (w == null) continue; - - w.setOwner(null); - w.remove(); - } - } - - private void removePets(Player p) - { - for (Wolf w : pets) - { - if (w == null || !(w.getOwner() instanceof Player) || !((Player) w.getOwner()).getName().equals(p.getName())) - continue; - - w.setOwner(null); - w.remove(); - } - petMap.remove(p); - } - - private void removeEntities() - { - if (p1 == null || p2 == null) return; - Chunk c1 = world.getChunkAt(p1); - Chunk c2 = world.getChunkAt(p2); - - for (int i = c1.getX(); i <= c2.getX(); i++) - for (int j = c1.getZ(); j <= c2.getZ(); j++) - for (Entity e : world.getChunkAt(i,j).getEntities()) - if ((e instanceof Item || e instanceof Slime) && inRegion(e.getLocation())) - if (e != null) e.remove(); - } + public abstract void removeClassPermissions(Player p); @@ -867,239 +196,29 @@ public class Arena // ////////////////////////////////////////////////////////////////////*/ - public void load(Configuration config) - { - config.load(); - - String arenaPath = "arenas." + MAUtils.nameArenaToConfig(name) + ".settings."; - String configName = MAUtils.nameArenaToConfig(name); - - enabled = config.getBoolean(arenaPath + "enabled", true); - protect = config.getBoolean(arenaPath + "protect", true); - 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); - detDamage = config.getBoolean(arenaPath + "detonate-damage", false); - lightning = config.getBoolean(arenaPath + "lightning", true); - forceRestore = config.getBoolean(arenaPath + "force-restore", false); - softRestore = config.getBoolean(arenaPath + "soft-restore", false); - softRestoreDrops = config.getBoolean(arenaPath + "soft-restore-drops", false); - emptyInvJoin = config.getBoolean(arenaPath + "require-empty-inv-join", true); - emptyInvSpec = config.getBoolean(arenaPath + "require-empty-inv-spec", true); - hellhounds = config.getBoolean(arenaPath + "hellhounds", false); - pvp = config.getBoolean(arenaPath + "pvp-enabled", false); - monsterInfight = config.getBoolean(arenaPath + "monster-infight", false); - allowWarp = config.getBoolean(arenaPath + "allow-teleporting", false); - specOnDeath = config.getBoolean(arenaPath + "spectate-on-death", true); - shareInArena = config.getBoolean(arenaPath + "share-items-in-arena", true); - spoutSelect = config.getBoolean(arenaPath + "spout-class-select", true); - joinDistance = config.getInt(arenaPath + "max-join-distance", 0); - minPlayers = config.getInt(arenaPath + "min-players", 0); - maxPlayers = config.getInt(arenaPath + "max-players", 0); - waveDelay = config.getInt(arenaPath + "first-wave-delay", 5) * 20; - waveInterval = config.getInt(arenaPath + "wave-interval", 20) * 20; - specialModulo = config.getInt(arenaPath + "special-modulo", 4); - maxIdleTime = config.getInt(arenaPath + "max-idle-time", 0) * 20; - finalWave = config.getInt(arenaPath + "final-wave", 0); - - everyWaveMap = MAUtils.getArenaRewardMap(config, configName, "every"); - afterWaveMap = MAUtils.getArenaRewardMap(config, configName, "after"); - entryFee = MAUtils.getEntryFee(config, configName); - - p1 = MAUtils.getArenaCoord(config, world, configName, "p1"); - p2 = MAUtils.getArenaCoord(config, world, configName, "p2"); - l1 = MAUtils.getArenaCoord(config, world, configName, "l1"); - l2 = MAUtils.getArenaCoord(config, world, configName, "l2"); - arenaLoc = MAUtils.getArenaCoord(config, world, configName, "arena"); - lobbyLoc = MAUtils.getArenaCoord(config, world, configName, "lobby"); - spectatorLoc = MAUtils.getArenaCoord(config, world, configName, "spectator"); - 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); - recurrentWaves = WaveUtils.getWaves(this, config, WaveBranch.RECURRENT); - - classes = plugin.getAM().classes; - classItems = plugin.getAM().classItems; - classArmor = plugin.getAM().classArmor; - classPerms = plugin.getAM().classPerms; - - // Determine if the arena is properly set up. Then add the to arena list. - setup = MAUtils.verifyData(this); - lobbySetup = MAUtils.verifyLobby(this); - } + public abstract void load(Config config); - public void restoreRegion() - { - Collections.sort(repairables, new RepairableComparator()); - - for (Repairable r : repairables) - r.repair(); - } + public abstract void restoreRegion(); - public void serializeConfig() - { - String coords = "arenas." + configName() + ".coords."; - Configuration config = plugin.getMAConfig(); - - config.setProperty("arenas." + configName() + ".settings.enabled", enabled); - config.setProperty("arenas." + configName() + ".settings.protect", protect); - if (p1 != null) config.setProperty(coords + "p1", MAUtils.makeCoord(p1)); - if (p2 != null) config.setProperty(coords + "p2", MAUtils.makeCoord(p2)); - if (l1 != null) config.setProperty(coords + "l1", MAUtils.makeCoord(l1)); - if (l2 != null) config.setProperty(coords + "l2", MAUtils.makeCoord(l2)); - if (arenaLoc != null) config.setProperty(coords + "arena", MAUtils.makeCoord(arenaLoc)); - if (lobbyLoc != null) config.setProperty(coords + "lobby", MAUtils.makeCoord(lobbyLoc)); - if (spectatorLoc != null) config.setProperty(coords + "spectator", MAUtils.makeCoord(spectatorLoc)); - for (Map.Entry entry : spawnpoints.entrySet()) - config.setProperty(coords + "spawnpoints." + entry.getKey(), MAUtils.makeCoord(entry.getValue())); - for (Map.Entry entry : spawnpointsBoss.entrySet()) - config.setProperty(coords + "spawnpoints." + entry.getKey(), MAUtils.makeCoord(entry.getValue())); - - config.save(); - } + public abstract void serializeConfig(); - public void deserializeConfig() - { - Configuration config = plugin.getMAConfig(); - config.load(); - load(config); - } + public abstract void deserializeConfig(); - public boolean serializeRegion() - { - int x1 = (int) p1.getX(); - int y1 = (int) p1.getY(); - int z1 = (int) p1.getZ(); - int x2 = (int) p2.getX(); - int y2 = (int) p2.getY(); - int z2 = (int) p2.getZ(); - - HashSet set = new HashSet(); - int[] buffer; - for (int i = x1; i <= x2; i++) - { - for (int j = y1; j <= y2; j++) - { - for (int k = z1; k <= z2; k++) - { - buffer = new int[4]; - buffer[0] = i; - buffer[1] = j; - buffer[2] = k; - buffer[3] = world.getBlockAt(i,j,k).getTypeId(); - set.add(buffer); - } - } - } - - try - { - new File(plugin.getDataFolder() + File.separator + "regions").mkdir(); - File regionFile = new File(plugin.getDataFolder() + File.separator + "regions" + File.separator + configName() + ".tmp"); - if (regionFile.exists()) - regionFile.createNewFile(); - - FileOutputStream fos = new FileOutputStream(regionFile); - ObjectOutputStream oos = new ObjectOutputStream(fos); - oos.writeObject(set); - oos.close(); - } - catch (Exception e) - { - MobArena.warning("Could not create region file. The arena will not be started!"); - e.printStackTrace(); - return false; - } - return true; - } + public abstract boolean serializeRegion(); - @SuppressWarnings("unchecked") - public boolean deserializeRegion() - { - HashSet set = new HashSet(); - try - { - File regionFile = new File(plugin.getDataFolder() + File.separator + "regions" + File.separator + configName() + ".tmp"); - if (!regionFile.exists()) - return false; - - FileInputStream fis = new FileInputStream(regionFile); - ObjectInputStream ois = new ObjectInputStream(fis); - set = (HashSet) ois.readObject(); - ois.close(); - } - catch (Exception e) - { - MobArena.warning("Could not find region file. The arena cannot be restored!"); - e.printStackTrace(); - return false; - } - - for (int[] buffer : set) - world.getBlockAt(buffer[0], buffer[1], buffer[2]).setTypeId(buffer[3]); - - return true; - } + public abstract boolean deserializeRegion(); /** * Check if a location is inside of the cuboid region * that p1 and p2 span. */ - public boolean inRegion(Location loc) - { - if (!loc.getWorld().getName().equals(world.getName()) || !setup) - return false; - - int x = loc.getBlockX(); - int y = loc.getBlockY(); - int z = loc.getBlockZ(); - - // Check the lobby first. - if (lobbySetup) - { - if ((x >= l1.getBlockX() && x <= l2.getBlockX()) && - (z >= l1.getBlockZ() && z <= l2.getBlockZ()) && - (y >= l1.getBlockY() && y <= l2.getBlockY())) - return true; - } - - // Returns false if the location is outside of the region. - return ((x >= p1.getBlockX() && x <= p2.getBlockX()) && - (z >= p1.getBlockZ() && z <= p2.getBlockZ()) && - (y >= p1.getBlockY() && y <= p2.getBlockY())); - } + public abstract boolean inRegion(Location loc); /** * Check if a location is inside of the arena region, expanded * by 'radius' blocks. Used with explosions. */ - public boolean inRegionRadius(Location loc, int radius) - { - if (!loc.getWorld().getName().equals(world.getName()) || !setup) - return false; - - int x = loc.getBlockX(); - int y = loc.getBlockY(); - int z = loc.getBlockZ(); - - // Check the lobby first. - if (lobbySetup) - { - if ((x + radius >= l1.getBlockX() && x - radius <= l2.getBlockX()) && - (z + radius >= l1.getBlockZ() && z - radius <= l2.getBlockZ()) && - (y + radius >= l1.getBlockY() && y - radius <= l2.getBlockY())) - return true; - } - - return ((x + radius >= p1.getBlockX() && x - radius <= p2.getBlockX()) && - (z + radius >= p1.getBlockZ() && z - radius <= p2.getBlockZ()) && - (y + radius >= p1.getBlockY() && y - radius <= p2.getBlockY())); - } + public abstract boolean inRegionRadius(Location loc, int radius); @@ -1109,355 +228,73 @@ public class Arena // ////////////////////////////////////////////////////////////////////*/ - public boolean inArena(Player p) - { - return arenaPlayers.contains(p); - } + public abstract boolean inArena(Player p); - public boolean inLobby(Player p) - { - return lobbyPlayers.contains(p); - } + public abstract boolean inLobby(Player p); - public boolean isRunning() - { - return running; - } + public abstract boolean isRunning(); - public boolean isPvpEnabled() - { - return pvp; - } + public abstract boolean isPvpEnabled(); - public boolean isLightningEnabled() - { - return lightning; - } + public abstract boolean isLightningEnabled(); - public boolean isBossWave() - { - return bossWave != null; - } + public abstract boolean isBossWave(); - public String configName() - { - return MAUtils.nameArenaToConfig(name); - } + public abstract String configName(); - public String arenaName() - { - return name; - } + public abstract String arenaName(); - public MobArena getPlugin() - { - return plugin; - } + public abstract MobArena getPlugin(); - public World getWorld() - { - return world; - } + public abstract World getWorld(); - public Wave getWave() - { - return currentWave; - } + public abstract Wave getWave(); - public void setWave(Wave wave) - { - currentWave = wave; - } + public abstract void setWave(Wave wave); - public void setBossWave(BossWave bossWave) - { - this.bossWave = bossWave; - } + public abstract void setBossWave(BossWave bossWave); - public List getClasses() - { - return classes; - } + public abstract Set getClasses(); - public List getAllSpawnpoints() - { - ArrayList result = new ArrayList(spawnpoints.size() + spawnpointsBoss.size()); - result.addAll(spawnpoints.values()); - result.addAll(spawnpointsBoss.values()); - return result; - } + public abstract List getAllSpawnpoints(); - public List getSpawnpoints() - { - return new ArrayList(spawnpoints.values()); - } + public abstract List getSpawnpoints(); - public Location getBossSpawnpoint() - { - if (spawnpointsBoss.isEmpty()) - { - List points = WaveUtils.getValidSpawnpoints(this, getLivingPlayers()); - return points.get(MobArena.random.nextInt(points.size())); - } - - return new ArrayList(spawnpointsBoss.values()).get(MobArena.random.nextInt(spawnpointsBoss.size())); - } + public abstract Location getBossSpawnpoint(); - public int getPlayerCount() - { - return spawnThread.getPlayerCount(); - } + public abstract int getPlayerCount(); - public void addBlock(Block b) - { - blocks.add(b); - } + public abstract void addBlock(Block b); - public void addMonster(LivingEntity e) - { - monsters.add(e); - } + public abstract void addMonster(LivingEntity e); - public void addExplodingSheep(LivingEntity e) - { - explodingSheep.add(e); - } + public abstract void addExplodingSheep(LivingEntity e); - public List getAllPlayers() - { - List result = new LinkedList(); - result.addAll(arenaPlayers); - result.addAll(lobbyPlayers); - result.addAll(specPlayers); - return result; - } + public abstract List getAllPlayers(); - public List getLivingPlayers() - { - List result = new LinkedList(); - result.addAll(arenaPlayers); - return result; - } + public abstract List getLivingPlayers(); - public Set getArenaPlayers() - { - return arenaPlayers; - } + public abstract Set getArenaPlayers(); - public Collection getArenaPlayerSet() - { - return arenaPlayerMap.values(); - } + public abstract Collection getArenaPlayerSet(); - 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 abstract List getArenaPlayerStatistics(Comparator comparator); - public List getNonreadyPlayers() - { - List result = new LinkedList(); - result.addAll(lobbyPlayers); - result.removeAll(readyPlayers); - return result; - } + public abstract List getNonreadyPlayers(); - public Set getMonsters() - { - Set tmp = new HashSet(monsters); - tmp.addAll(explodingSheep); - return tmp; - } + public abstract Set getMonsters(); - public Set getPets() - { - return pets; - } + public abstract Set getPets(); - public void resetIdleTimer() - { - if (maxIdleTime <= 0 || !running) - return; - - // Reset the previousSize, cancel the previous timer, and start the new timer. - spawnThread.setPreviousSize(getMonsters().size()); - Bukkit.getServer().getScheduler().cancelTask(spawnThread.getTaskId()); - int id = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, - new Runnable() - { - public void run() - { - // Make sure to remove any dead/removed entities first. - List ms = new LinkedList(monsters); - for (Entity e : ms) - if (e.isDead()) - monsters.remove(e); - - // Compare the current size with the previous size. - if (monsters.size() < spawnThread.getPreviousSize() || spawnThread.getPreviousSize() == 0 || bossWave != null) - { - resetIdleTimer(); - return; - } - - // Clear all player inventories, and "kill" all players. - List ps = new LinkedList(arenaPlayers); - for (Player p : ps) - { - MAUtils.clearInventory(p); - MAUtils.tellPlayer(p, Msg.FORCE_END_IDLE); - playerDeath(p); - } - } - }, maxIdleTime); - spawnThread.setTaskId(id); - } + public abstract void resetIdleTimer(); - public void addTrunkAndLeaves(Block b) - { - final int x = b.getX(); - final int y = b.getY(); - final int z = b.getZ(); - - Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, - new Runnable() - { - public void run() - { - List result = new LinkedList(); - for (int i = x-2; i <= x+2; i++) - for (int j = y; j <= y+10; j++) - for (int k = z-2; k <= z+2; k++) - if (world.getBlockAt(i,j,k).getType() == Material.LOG || world.getBlockAt(i,j,k).getType() == Material.LEAVES) - result.add(world.getBlockAt(i,j,k)); - - if (running) blocks.addAll(result); - } - }, 10); - } + public abstract void addTrunkAndLeaves(Block b); - public boolean canAfford(Player p) - { - if (entryFee.isEmpty()) - return true; - - PlayerInventory inv = p.getInventory(); - for (ItemStack stack : entryFee) - { - // Economy money - if (stack.getTypeId() == MobArena.ECONOMY_MONEY_ID) - { - //if (plugin.Methods.hasMethod() && !plugin.Method.getAccount(p.getName()).hasEnough(stack.getAmount())) - if (plugin.Method != null && !(plugin.Method.getAccount(p.getName()).balance() >= stack.getAmount())) - return false; - } - // Normal stack - else - { - if (!inv.contains(stack.getTypeId(), stack.getAmount())) - return false; - } - } - - return true; - } + public abstract boolean canAfford(Player p); - public boolean takeFee(Player p) - { - if (entryFee.isEmpty()) - return true; - - PlayerInventory inv = p.getInventory(); - InventoryItem[] items = InventoryItem.parseItemStacks(inv.getContents()); - InventoryItem[] fee = InventoryItem.parseItemStacks(entryFee); - - // Take some economy money - for (InventoryItem item : InventoryItem.extractAllFromArray(MobArena.ECONOMY_MONEY_ID, fee)) - if (plugin.Method != null) - plugin.Method.getAccount(p.getName()).subtract(item.getAmount()); - - // Take any other items - for (InventoryItem item : fee) - InventoryItem.removeItemFromArray(item, items); - - // Turn everything back into ItemStacks - for (int i = 0; i < items.length; i++) - inv.setItem(i, items[i].toItemStack()); - - return true; - } + public abstract boolean takeFee(Player p); - public boolean canJoin(Player p) - { - if (!enabled) - MAUtils.tellPlayer(p, Msg.JOIN_ARENA_NOT_ENABLED); - else if (!setup || recurrentWaves.isEmpty()) - MAUtils.tellPlayer(p, Msg.JOIN_ARENA_NOT_SETUP); - else if (edit) - MAUtils.tellPlayer(p, Msg.JOIN_ARENA_EDIT_MODE); - else if (running && (notifyPlayers.contains(p) || notifyPlayers.add(p))) - MAUtils.tellPlayer(p, Msg.JOIN_ARENA_IS_RUNNING); - else if (arenaPlayers.contains(p) || lobbyPlayers.contains(p)) - MAUtils.tellPlayer(p, Msg.JOIN_ALREADY_PLAYING); - else if (!plugin.has(p, "mobarena.arenas." + configName())) - MAUtils.tellPlayer(p, Msg.JOIN_ARENA_PERMISSION); - else if (maxPlayers > 0 && lobbyPlayers.size() >= maxPlayers) - MAUtils.tellPlayer(p, Msg.JOIN_PLAYER_LIMIT_REACHED); - else if (joinDistance > 0 && !inRegionRadius(p.getLocation(), joinDistance)) - MAUtils.tellPlayer(p, Msg.JOIN_TOO_FAR); - else if (emptyInvJoin && !MAUtils.hasEmptyInventory(p)) - MAUtils.tellPlayer(p, Msg.JOIN_EMPTY_INV); - else if (!canAfford(p))// || !takeFee(p)) - MAUtils.tellPlayer(p, Msg.JOIN_FEE_REQUIRED, MAUtils.listToString(entryFee, plugin)); - else return true; - - return false; - } + public abstract boolean canJoin(Player p); - public boolean canSpec(Player p) - { - if (!enabled) - MAUtils.tellPlayer(p, Msg.JOIN_ARENA_NOT_ENABLED); - else if (!setup) - MAUtils.tellPlayer(p, Msg.JOIN_ARENA_NOT_SETUP); - else if (edit) - MAUtils.tellPlayer(p, Msg.JOIN_ARENA_EDIT_MODE); - else if (arenaPlayers.contains(p) || lobbyPlayers.contains(p)) - MAUtils.tellPlayer(p, Msg.SPEC_ALREADY_PLAYING); - else if (emptyInvSpec && !MAUtils.hasEmptyInventory(p)) - MAUtils.tellPlayer(p, Msg.SPEC_EMPTY_INV); - else if (joinDistance > 0 && !inRegionRadius(p.getLocation(), joinDistance)) - MAUtils.tellPlayer(p, Msg.JOIN_TOO_FAR); - else return true; - - return false; - } - - /** - * The "perfect equals method" cf. "Object-Oriented Design and Patterns" - * by Cay S. Horstmann. - */ - public boolean equals(Object other) - { - if (this == other) return true; - if (other == null) return false; - if (getClass() != other.getClass()) return false; - - // Arenas must have different names. - if (other instanceof Arena && ((Arena)other).name.equals(name)) - return true; - - return false; - } - - public String toString() - { - return ((enabled && setup) ? ChatColor.GREEN : ChatColor.GRAY) + configName(); - } + public abstract boolean canSpec(Player p); } diff --git a/src/com/garbagemule/MobArena/ArenaMaster.java b/src/com/garbagemule/MobArena/ArenaMaster.java index 33f5b97..601ffff 100644 --- a/src/com/garbagemule/MobArena/ArenaMaster.java +++ b/src/com/garbagemule/MobArena/ArenaMaster.java @@ -2,32 +2,28 @@ package com.garbagemule.MobArena; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import org.bukkit.util.config.Configuration; +//import org.bukkit.util.config.Configuration; //import com.garbagemule.ArenaPlugin.Master; -public class ArenaMaster //implements Master +public abstract class ArenaMaster //implements Master { - private MobArena plugin; - private Configuration config; protected Arena selectedArena; // Settings protected boolean enabled, updateNotify; // Classes - protected List classes; + protected Set classes; protected Map> classItems, classArmor; protected Map> classPerms; //protected Map>> classBonuses; @@ -44,131 +40,40 @@ public class ArenaMaster //implements Master - /** - * Default constructor. - */ - public ArenaMaster(MobArena instance) - { - plugin = instance; - config = plugin.getMAConfig(); - arenas = new LinkedList(); - arenaMap = new HashMap(); - } - - - /*///////////////////////////////////////////////////////////////////////// // // Arena getters // /////////////////////////////////////////////////////////////////////////*/ - public List getEnabledArenas() - { - List result = new LinkedList(); - for (Arena arena : arenas) - if (arena.enabled) - result.add(arena); - return result; - } + + public abstract List getEnabledArenas(); - public List getPermittedArenas(Player p) - { - List result = new LinkedList(); - for (Arena arena : arenas) - if (plugin.has(p, "mobarena.arenas." + arena.configName())) - result.add(arena); - return result; - } + public abstract List getPermittedArenas(Player p); - public Arena getArenaAtLocation(Location loc) - { - for (Arena arena : arenas) - if (arena.inRegion(loc)) - return arena; - return null; - } + public abstract Arena getArenaAtLocation(Location loc); - public List getArenasInWorld(World world) - { - List result = new LinkedList(); - for (Arena arena : arenas) - if (arena.world.equals(world)) - result.add(arena); - return result; - } + public abstract List getArenasInWorld(World world); - public List getAllPlayers() - { - List result = new LinkedList(); - for (Arena arena : arenas) - result.addAll(arena.getAllPlayers()); - return result; - } + public abstract List getAllPlayers(); - public List getAllPlayersInArena(String arenaName) - { - Arena arena = getArenaWithName(arenaName); - return (arena != null) ? arena.getLivingPlayers() : new LinkedList(); - } + public abstract List getAllPlayersInArena(String arenaName); - public List getAllLivingPlayers() - { - List result = new LinkedList(); - for (Arena arena : arenas) - result.addAll(arena.getLivingPlayers()); - return result; - } + public abstract List getAllLivingPlayers(); - public List getLivingPlayersInArena(String arenaName) - { - Arena arena = getArenaWithName(arenaName); - return (arena != null) ? arena.getLivingPlayers() : new LinkedList(); - } + public abstract List getLivingPlayersInArena(String arenaName); - public Arena getArenaWithPlayer(Player p) - { - return arenaMap.get(p); - } + public abstract Arena getArenaWithPlayer(Player p); - public Arena getArenaWithPlayer(String playerName) - { - return arenaMap.get(Bukkit.getServer().getPlayer(playerName)); - } + public abstract Arena getArenaWithPlayer(String playerName); - public Arena getArenaWithSpectator(Player p) - { - for (Arena arena : arenas) - { - if (arena.specPlayers.contains(p)) - return arena; - } - return null; - } + public abstract Arena getArenaWithSpectator(Player p); - public Arena getArenaWithMonster(Entity e) - { - for (Arena arena : arenas) - if (arena.monsters.contains(e)) - return arena; - return null; - } + public abstract Arena getArenaWithMonster(Entity e); - public Arena getArenaWithPet(Entity e) - { - for (Arena arena : arenas) - if (arena.pets.contains(e)) - return arena; - return null; - } + public abstract Arena getArenaWithPet(Entity e); - public Arena getArenaWithName(String configName) - { - for (Arena arena : arenas) - if (arena.configName().equals(configName)) - return arena; - return null; - } + public abstract Arena getArenaWithName(String configName); @@ -178,140 +83,26 @@ public class ArenaMaster //implements Master // /////////////////////////////////////////////////////////////////////////*/ - public void initialize() - { - config.load(); - loadSettings(); - loadClasses(); - loadArenas(); - config.save(); - } + public abstract void initialize(); /** * Load the global settings. */ - public void loadSettings() - { - if (config.getKeys("global-settings") == null) - { - config.setProperty("global-settings.enabled", true); - config.setProperty("global-settings.update-notification", true); - } - - enabled = config.getBoolean("global-settings.enabled", true); - updateNotify = config.getBoolean("global-settings.update-notification", true); - } + public abstract void loadSettings(); /** * Load all class-related stuff. */ - public void loadClasses() - { - classes = config.getKeys("classes"); - if (classes == null) - { - config.setProperty("classes.Archer.items", "wood_sword, bow, arrow:128, grilled_pork"); - config.setProperty("classes.Archer.armor", "298,299,300,301"); - config.setProperty("classes.Knight.items", "diamond_sword, grilled_pork:2"); - config.setProperty("classes.Knight.armor", "306,307,308,309"); - config.setProperty("classes.Tank.items", "iron_sword, grilled_pork:3, apple"); - config.setProperty("classes.Tank.armor", "310,311,312,313"); - config.setProperty("classes.Oddjob.items", "stone_sword, flint_and_steel, netherrack:2, wood_pickaxe, tnt:4, fishing_rod, apple, grilled_pork:3"); - config.setProperty("classes.Oddjob.armor", "298,299,300,301"); - config.setProperty("classes.Chef.items", "stone_sword, bread:6, grilled_pork:4, mushroom_soup, cake:3, cookie:12"); - config.setProperty("classes.Chef.armor", "314,315,316,317"); - classes = config.getKeys("classes"); - } - classItems = MAUtils.getClassItems(config, "items"); - classArmor = MAUtils.getClassItems(config, "armor"); - classPerms = MAUtils.getClassPerms(config); - } + public abstract void loadClasses(); /** * Load all arena-related stuff. */ - public void loadArenas() - { - arenas = new LinkedList(); - - if (config.getKeys("arenas") == null) - createArenaNode("default", Bukkit.getServer().getWorlds().get(0)); - - for (String configName : config.getKeys("arenas")) - { - String arenaPath = "arenas." + configName + "."; - String worldName = config.getString(arenaPath + "settings.world", null); - World world; - if (worldName == null || worldName.equals("")) - { - 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); - - Arena arena = new Arena(MAUtils.nameConfigToArena(configName), world); - arena.load(config); - arenas.add(arena); - } - - selectedArena = arenas.get(0); - } + public abstract void loadArenas(); - public Arena createArenaNode(String configName, World world) - { - config.setProperty("arenas." + configName + ".settings.world", world.getName()); - config.save(); - config.load(); - config.setProperty("arenas." + configName + ".settings.enabled", true); - config.save(); - config.load(); - config.setProperty("arenas." + configName + ".settings.protect", true); - config.save(); - config.load(); - config.setProperty("arenas." + configName + ".settings.entry-fee", ""); - config.save(); - config.load(); - config.setProperty("arenas." + configName + ".settings.logging", false); - config.setProperty("arenas." + configName + ".settings.clear-wave-before-next", false); - config.setProperty("arenas." + configName + ".settings.detonate-creepers", false); - config.setProperty("arenas." + configName + ".settings.detonate-damage", false); - config.setProperty("arenas." + configName + ".settings.lightning", true); - config.setProperty("arenas." + configName + ".settings.auto-equip-armor", true); - config.setProperty("arenas." + configName + ".settings.force-restore", false); - config.setProperty("arenas." + configName + ".settings.soft-restore", false); - config.setProperty("arenas." + configName + ".settings.soft-restore-drops", false); - config.setProperty("arenas." + configName + ".settings.require-empty-inv-join", true); - config.setProperty("arenas." + configName + ".settings.require-empty-inv-spec", true); - config.setProperty("arenas." + configName + ".settings.hellhounds", false); - config.setProperty("arenas." + configName + ".settings.pvp-enabled", false); - config.setProperty("arenas." + configName + ".settings.monster-infight", false); - config.setProperty("arenas." + configName + ".settings.allow-teleporting", false); - config.setProperty("arenas." + configName + ".settings.spectate-on-death", true); - config.setProperty("arenas." + configName + ".settings.share-items-in-arena", true); - config.save(); - config.load(); - config.setProperty("arenas." + configName + ".settings.player-limit", 0); - config.setProperty("arenas." + configName + ".settings.max-join-distance", 0); - config.save(); - config.load(); - config.setProperty("arenas." + configName + ".settings.repair-delay", 5); - config.setProperty("arenas." + configName + ".settings.first-wave-delay", 5); - config.setProperty("arenas." + configName + ".settings.wave-interval", 20); - config.setProperty("arenas." + configName + ".settings.special-modulo", 4); - config.setProperty("arenas." + configName + ".settings.max-idle-time", 0); - config.save(); - config.load(); - - Arena arena = new Arena(MAUtils.nameConfigToArena(configName), world); - arena.load(config); - return arena; - } + public abstract Arena createArenaNode(String configName, World world); - public void removeArenaNode(String configName) - { - config.removeProperty("arenas." + configName); - config.save(); - } + public abstract void removeArenaNode(String configName); @@ -325,73 +116,27 @@ public class ArenaMaster //implements Master * Update one, two or all three of global settings, classes * and arenas (arenas with deserialization). */ - public void update(boolean settings, boolean classes, boolean arenalist) - { - boolean tmp = enabled; - enabled = false; - - for (Arena arena : arenas) - arena.forceEnd(); - - config.load(); - if (settings) loadSettings(); - if (classes) loadClasses(); - if (arenalist) deserializeArenas(); - config.save(); - - enabled = tmp; - } + public abstract void update(boolean settings, boolean classes, boolean arenalist); /** * Serialize the global settings. */ - public void serializeSettings() - { - String settings = "global-settings."; - config.setProperty(settings + "enabled", enabled); - config.save(); - } + public abstract void serializeSettings(); /** * Serialize all arena configs. */ - public void serializeArenas() - { - for (Arena arena : arenas) - arena.serializeConfig(); - } + public abstract void serializeArenas(); /** * Deserialize all arena configs. Updates the arena list to * include only the current arenas (not ones added in the * actual file) that are also in the config-file. */ - public void deserializeArenas() - { - // Get only the arenas in the config. - List strings = config.getKeys("arenas"); - if (strings == null) - return; - - // Get their Arena objects. - List configArenas = new LinkedList(); - for (String s : strings) - if (getArenaWithName(s) != null) - configArenas.add(getArenaWithName(s)); - - // Remove all Arenas no longer in the config. - arenas.retainAll(configArenas); - - for (Arena arena : arenas) - arena.deserializeConfig(); - - // Make sure to update the selected arena to a valid one. - if (!arenas.contains(selectedArena) && arenas.size() >= 1) - selectedArena = arenas.get(0); - } + public abstract void deserializeArenas(); - public void updateSettings() { update(true, false, false); } - public void updateClasses() { update(false, true, false); } - public void updateArenas() { update(false, false, true); } - public void updateAll() { update(true, true, true); } + public abstract void updateSettings(); + public abstract void updateClasses(); + public abstract void updateArenas(); + public abstract void updateAll(); } diff --git a/src/com/garbagemule/MobArena/ArenaMasterStandard.java b/src/com/garbagemule/MobArena/ArenaMasterStandard.java new file mode 100644 index 0000000..90c0cbd --- /dev/null +++ b/src/com/garbagemule/MobArena/ArenaMasterStandard.java @@ -0,0 +1,397 @@ +package com.garbagemule.MobArena; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +//import org.bukkit.util.config.Configuration; + +import com.garbagemule.MobArena.util.Config; + +//import com.garbagemule.ArenaPlugin.Master; + +public class ArenaMasterStandard extends ArenaMaster +{ + private MobArena plugin; + //private Configuration config; + private Config config; + //protected Arena selectedArena; + + // Settings + //protected boolean enabled, updateNotify; + + // Classes + //protected Set classes; + //protected Map> classItems, classArmor; + //protected Map> classPerms; + //protected Map>> classBonuses; + //protected Map arenaMap; + + // Location map + //protected Map locations = new HashMap(); + + // Arena list + //protected List arenas; + + // Listeners + //protected Set listeners = new HashSet(); + + + + /** + * Default constructor. + */ + public ArenaMasterStandard(MobArenaPlugin instance) + { + plugin = (MobArena) instance; + config = plugin.getMAConfig(); + arenas = new LinkedList(); + arenaMap = new HashMap(); + } + + + + /*///////////////////////////////////////////////////////////////////////// + // + // Arena getters + // + /////////////////////////////////////////////////////////////////////////*/ + + public List getEnabledArenas() + { + List result = new LinkedList(); + for (Arena arena : arenas) + if (arena.enabled) + result.add(arena); + return result; + } + + public List getPermittedArenas(Player p) + { + List result = new LinkedList(); + for (Arena arena : arenas) + if (plugin.has(p, "mobarena.arenas." + arena.configName())) + result.add(arena); + return result; + } + + public Arena getArenaAtLocation(Location loc) + { + for (Arena arena : arenas) + if (arena.inRegion(loc)) + return arena; + return null; + } + + public List getArenasInWorld(World world) + { + List result = new LinkedList(); + for (Arena arena : arenas) + if (arena.world.equals(world)) + result.add(arena); + return result; + } + + public List getAllPlayers() + { + List result = new LinkedList(); + for (Arena arena : arenas) + result.addAll(arena.getAllPlayers()); + return result; + } + + public List getAllPlayersInArena(String arenaName) + { + Arena arena = getArenaWithName(arenaName); + return (arena != null) ? arena.getLivingPlayers() : new LinkedList(); + } + + public List getAllLivingPlayers() + { + List result = new LinkedList(); + for (Arena arena : arenas) + result.addAll(arena.getLivingPlayers()); + return result; + } + + public List getLivingPlayersInArena(String arenaName) + { + Arena arena = getArenaWithName(arenaName); + return (arena != null) ? arena.getLivingPlayers() : new LinkedList(); + } + + public Arena getArenaWithPlayer(Player p) + { + return arenaMap.get(p); + } + + public Arena getArenaWithPlayer(String playerName) + { + return arenaMap.get(Bukkit.getServer().getPlayer(playerName)); + } + + public Arena getArenaWithSpectator(Player p) + { + for (Arena arena : arenas) + { + if (arena.specPlayers.contains(p)) + return arena; + } + return null; + } + + public Arena getArenaWithMonster(Entity e) + { + for (Arena arena : arenas) + if (arena.monsters.contains(e)) + return arena; + return null; + } + + public Arena getArenaWithPet(Entity e) + { + for (Arena arena : arenas) + if (arena.pets.contains(e)) + return arena; + return null; + } + + public Arena getArenaWithName(String configName) + { + for (Arena arena : arenas) + if (arena.configName().equals(configName)) + return arena; + return null; + } + + + + /*///////////////////////////////////////////////////////////////////////// + // + // Initialization + // + /////////////////////////////////////////////////////////////////////////*/ + + public void initialize() + { + config.load(); + loadSettings(); + loadClasses(); + loadArenas(); + config.save(); + } + + /** + * Load the global settings. + */ + public void loadSettings() + { + if (config.getKeys("global-settings") == null) + { + config.setProperty("global-settings.enabled", true); + config.setProperty("global-settings.update-notification", true); + } + + enabled = config.getBoolean("global-settings.enabled", true); + updateNotify = config.getBoolean("global-settings.update-notification", true); + } + + /** + * Load all class-related stuff. + */ + public void loadClasses() + { + classes = config.getKeys("classes"); + if (classes == null) + { + config.setProperty("classes.Archer.items", "wood_sword, bow, arrow:128, grilled_pork"); + config.setProperty("classes.Archer.armor", "298,299,300,301"); + config.setProperty("classes.Knight.items", "diamond_sword, grilled_pork:2"); + config.setProperty("classes.Knight.armor", "306,307,308,309"); + config.setProperty("classes.Tank.items", "iron_sword, grilled_pork:3, apple"); + config.setProperty("classes.Tank.armor", "310,311,312,313"); + config.setProperty("classes.Oddjob.items", "stone_sword, flint_and_steel, netherrack:2, wood_pickaxe, tnt:4, fishing_rod, apple, grilled_pork:3"); + config.setProperty("classes.Oddjob.armor", "298,299,300,301"); + config.setProperty("classes.Chef.items", "stone_sword, bread:6, grilled_pork:4, mushroom_soup, cake:3, cookie:12"); + config.setProperty("classes.Chef.armor", "314,315,316,317"); + classes = config.getKeys("classes"); + } + classItems = MAUtils.getClassItems(config, "items"); + classArmor = MAUtils.getClassItems(config, "armor"); + classPerms = MAUtils.getClassPerms(config); + } + + /** + * Load all arena-related stuff. + */ + public void loadArenas() + { + arenas = new LinkedList(); + + if (config.getKeys("arenas") == null) + createArenaNode("default", Bukkit.getServer().getWorlds().get(0)); + + for (String configName : config.getKeys("arenas")) + { + String arenaPath = "arenas." + configName + "."; + String worldName = config.getString(arenaPath + "settings.world", null); + World world; + if (worldName == null || worldName.equals("")) + { + 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); + + Arena arena = new ArenaStandard(MAUtils.nameConfigToArena(configName), world); + arena.load(config); + arenas.add(arena); + } + + selectedArena = arenas.get(0); + } + + public Arena createArenaNode(String configName, World world) + { + config.setProperty("arenas." + configName + ".settings.world", world.getName()); + config.save(); + config.load(); + config.setProperty("arenas." + configName + ".settings.enabled", true); + config.save(); + config.load(); + config.setProperty("arenas." + configName + ".settings.protect", true); + config.save(); + config.load(); + config.setProperty("arenas." + configName + ".settings.entry-fee", ""); + config.save(); + config.load(); + config.setProperty("arenas." + configName + ".settings.logging", false); + config.setProperty("arenas." + configName + ".settings.clear-wave-before-next", false); + config.setProperty("arenas." + configName + ".settings.detonate-creepers", false); + config.setProperty("arenas." + configName + ".settings.detonate-damage", false); + config.setProperty("arenas." + configName + ".settings.lightning", true); + config.setProperty("arenas." + configName + ".settings.auto-equip-armor", true); + config.setProperty("arenas." + configName + ".settings.force-restore", false); + config.setProperty("arenas." + configName + ".settings.soft-restore", false); + config.setProperty("arenas." + configName + ".settings.soft-restore-drops", false); + config.setProperty("arenas." + configName + ".settings.require-empty-inv-join", true); + config.setProperty("arenas." + configName + ".settings.require-empty-inv-spec", true); + config.setProperty("arenas." + configName + ".settings.hellhounds", false); + config.setProperty("arenas." + configName + ".settings.pvp-enabled", false); + config.setProperty("arenas." + configName + ".settings.monster-infight", false); + config.setProperty("arenas." + configName + ".settings.allow-teleporting", false); + config.setProperty("arenas." + configName + ".settings.spectate-on-death", true); + config.setProperty("arenas." + configName + ".settings.share-items-in-arena", true); + config.save(); + config.load(); + config.setProperty("arenas." + configName + ".settings.player-limit", 0); + config.setProperty("arenas." + configName + ".settings.max-join-distance", 0); + config.save(); + config.load(); + config.setProperty("arenas." + configName + ".settings.repair-delay", 5); + config.setProperty("arenas." + configName + ".settings.first-wave-delay", 5); + config.setProperty("arenas." + configName + ".settings.wave-interval", 20); + config.setProperty("arenas." + configName + ".settings.special-modulo", 4); + config.setProperty("arenas." + configName + ".settings.max-idle-time", 0); + config.save(); + config.load(); + + Arena arena = new ArenaStandard(MAUtils.nameConfigToArena(configName), world); + arena.load(config); + return arena; + } + + public void removeArenaNode(String configName) + { + config.removeProperty("arenas." + configName); + config.save(); + } + + + + /*///////////////////////////////////////////////////////////////////////// + // + // Update and serialization methods + // + /////////////////////////////////////////////////////////////////////////*/ + + /** + * Update one, two or all three of global settings, classes + * and arenas (arenas with deserialization). + */ + public void update(boolean settings, boolean classes, boolean arenalist) + { + boolean tmp = enabled; + enabled = false; + + for (Arena arena : arenas) + arena.forceEnd(); + + config.load(); + if (settings) loadSettings(); + if (classes) loadClasses(); + if (arenalist) deserializeArenas(); + config.save(); + + enabled = tmp; + } + + /** + * Serialize the global settings. + */ + public void serializeSettings() + { + String settings = "global-settings."; + config.setProperty(settings + "enabled", enabled); + config.save(); + } + + /** + * Serialize all arena configs. + */ + public void serializeArenas() + { + for (Arena arena : arenas) + arena.serializeConfig(); + } + + /** + * Deserialize all arena configs. Updates the arena list to + * include only the current arenas (not ones added in the + * actual file) that are also in the config-file. + */ + public void deserializeArenas() + { + // Get only the arenas in the config. + Set strings = config.getKeys("arenas"); + if (strings == null) + return; + + // Get their Arena objects. + List configArenas = new LinkedList(); + for (String s : strings) + if (getArenaWithName(s) != null) + configArenas.add(getArenaWithName(s)); + + // Remove all Arenas no longer in the config. + arenas.retainAll(configArenas); + + for (Arena arena : arenas) + arena.deserializeConfig(); + + // Make sure to update the selected arena to a valid one. + if (!arenas.contains(selectedArena) && arenas.size() >= 1) + selectedArena = arenas.get(0); + } + + public void updateSettings() { update(true, false, false); } + public void updateClasses() { update(false, true, false); } + public void updateArenas() { update(false, false, true); } + public void updateAll() { update(true, true, true); } +} diff --git a/src/com/garbagemule/MobArena/ArenaStandard.java b/src/com/garbagemule/MobArena/ArenaStandard.java new file mode 100644 index 0000000..bb0d87e --- /dev/null +++ b/src/com/garbagemule/MobArena/ArenaStandard.java @@ -0,0 +1,1465 @@ +package com.garbagemule.MobArena; + +import java.io.File; +import java.io.FileInputStream; +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; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.PriorityBlockingQueue; + +import net.minecraft.server.WorldServer; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Chunk; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.block.ContainerBlock; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.entity.Creature; +import org.bukkit.entity.CreatureType; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Item; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Slime; +import org.bukkit.entity.Wolf; +import org.bukkit.event.entity.EntityRegainHealthEvent; +import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +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; +import com.garbagemule.MobArena.spout.Spouty; +import com.garbagemule.MobArena.util.Config; +import com.garbagemule.MobArena.util.Delays; +import com.garbagemule.MobArena.util.InventoryItem; +import com.garbagemule.MobArena.util.WaveUtils; +import com.garbagemule.MobArena.waves.BossWave; +import com.garbagemule.MobArena.waves.Wave; +import com.garbagemule.MobArena.waves.Wave.WaveBranch; + +public class ArenaStandard extends Arena +{ + private MobArena plugin; + /* + // Setup fields + protected String name; + protected World world; + 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, spoutSelect; + protected Location p1, p2, l1, l2, arenaLoc, lobbyLoc, spectatorLoc; + protected Map spawnpoints, spawnpointsBoss, containers; + protected String logging; + + // Wave/reward/entryfee fields + protected int spawnTaskId, sheepTaskId, waveDelay, waveInterval, specialModulo, spawnMonstersInt, maxIdleTime, finalWave; + protected MASpawnThread spawnThread; + protected Map> everyWaveMap, afterWaveMap; + protected Map classMap; + protected Map> classItems, classArmor; + protected Map> classPerms; + protected Map attachments; + protected List entryFee; + + // Player sets + protected Set arenaPlayers, lobbyPlayers, readyPlayers, specPlayers; + + // Wave stuff + protected TreeSet singleWaves, singleWavesInstance; + protected TreeSet recurrentWaves; + protected BossWave bossWave; + protected Wave currentWave; + + // Arena sets/maps + protected Set hasPaid, rewardedPlayers, notifyPlayers, randoms; + protected Set monsters, explodingSheep, plaguedPigs, madCows; + protected Set blocks; + protected Set pets; + protected Map petMap; + protected LinkedList repairables, containables; + + // Spawn overriding + protected int spawnMonsters; + protected boolean allowMonsters, allowAnimals; + + // Other settings + protected int minPlayers, maxPlayers, joinDistance; + protected List classes = new LinkedList(); + protected Map locations = new HashMap(); + protected Map healthMap = new HashMap(); + protected Map hungerMap = new HashMap(); + protected Map modeMap = new HashMap(); + + // Logging + protected ArenaLog log; + protected Map arenaPlayerMap; + protected Leaderboard leaderboard; + + protected MAListener eventListener; + + protected PriorityBlockingQueue repairQueue; + */ + + /** + * Primary constructor. Requires a name and a world. + */ + public ArenaStandard(String name, World world) + { + if (world == null) + throw new NullPointerException("[MobArena] ERROR! World for arena '" + name + "' does not exist!"); + + this.name = name; + this.world = world; + plugin = (MobArena) Bukkit.getServer().getPluginManager().getPlugin("MobArena"); + + arenaPlayers = new HashSet(); + lobbyPlayers = new HashSet(); + notifyPlayers = new HashSet(); + readyPlayers = new HashSet(); + specPlayers = new HashSet(); + rewardedPlayers = new HashSet(); + hasPaid = new HashSet(); + monsters = new HashSet(); + explodingSheep = new HashSet(); + plaguedPigs = new HashSet(); + madCows = new HashSet(); + blocks = new HashSet(); + pets = new HashSet(); + petMap = new HashMap(); + classMap = new HashMap(); + randoms = new HashSet(); + repairables = new LinkedList(); + containables = new LinkedList(); + attachments = new HashMap(); + arenaPlayerMap = new HashMap(); + + running = false; + edit = false; + + allowMonsters = world.getAllowMonsters(); + allowAnimals = world.getAllowAnimals(); + spawnMonsters = MAUtils.getSpawnMonsters(world); + + eventListener = new MAListener(this, plugin); + repairQueue = new PriorityBlockingQueue(100, new RepairableComparator()); + } + + public boolean startArena() + { + // Sanity-checks + if (running || lobbyPlayers.isEmpty() || !readyPlayers.containsAll(lobbyPlayers)) + return false; + if (!softRestore && forceRestore && !serializeRegion()) + return false; + + // Store all chest contents. + storeContainerContents(); + + // Populate arenaPlayers and clear the lobby. + arenaPlayers.addAll(lobbyPlayers); + lobbyPlayers.clear(); + readyPlayers.clear(); + + // Assign random classes. + for (Player p : randoms) + assignRandomClass(p); + if (arenaPlayers.isEmpty()) + return false; + + // Teleport players, give full health, initialize maps + for (Player p : arenaPlayers) + { + p.teleport(arenaLoc); + setHealth(p, 20); + p.setFoodLevel(10); + assignClassPermissions(p); + arenaPlayerMap.put(p, new ArenaPlayer(p, this, plugin)); + } + + // Copy the singleWaves Set for polling. + singleWavesInstance = new TreeSet(singleWaves); + + // Start spawning monsters (must happen before 'running = true;') + startSpawning(); + startBouncingSheep(); + + // Set the boolean. + running = true; + + // Spawn pets (must happen after 'running = true;') + spawnPets(); + + // Start logging + log = new ArenaLog(plugin, this); + log.start(); + + // Initialize leaderboards and start displaying info. + leaderboard.initialize(); + leaderboard.startTracking(); + + // Announce and notify. + MAUtils.tellAll(this, Msg.ARENA_START); + + for (MobArenaListener listener : plugin.getAM().listeners) + listener.onArenaStart(this); + + return true; + } + + public boolean endArena() + { + // Sanity-checks. + if (!running || !arenaPlayers.isEmpty()) + { + //System.out.println("Arena was not ended, playercount: " + arenaPlayers.size()); + return false; + } + //else System.out.println("Arena ending..."); + + // Set the boolean. + running = false; + + // Stop tracking leaderboards + leaderboard.stopTracking(); + leaderboard.update(); + + // Finish logging + log.end(); + if (logging != null) + { + log.saveSessionData(); + log.updateArenaTotals(); + } + log.clearSessionData(); + + // Stop spawning. + stopSpawning(); + + // Clean arena floor. + cleanup(); + + // Restore region. + if (softRestore) + restoreRegion(); + else if (forceRestore) + deserializeRegion(); + + // Restore chests + restoreContainerContents(); + + // Announce and clear sets. + MAUtils.tellAll(this, Msg.ARENA_END, true); + arenaPlayers.clear(); + arenaPlayerMap.clear(); + lobbyPlayers.clear(); + readyPlayers.clear(); + notifyPlayers.clear(); + rewardedPlayers.clear(); + classMap.clear(); + + // Notify listeners. + for (MobArenaListener listener : plugin.getAM().listeners) + listener.onArenaEnd(this); + + return true; + } + + public void forceStart() + { + if (running) + return; + + // Set operations. + Set tmp = new HashSet(); + tmp.addAll(lobbyPlayers); + tmp.removeAll(readyPlayers); + + // Force leave. + for (Player p : tmp) + { + plugin.getAM().arenaMap.remove(p); + playerLeave(p); + } + } + + public void forceEnd() + { + Bukkit.getServer().getScheduler().cancelTask(spawnTaskId); + Bukkit.getServer().getScheduler().cancelTask(sheepTaskId); + + for (Player p : getAllPlayers()) + playerLeave(p); + + for (Entity e : monsters) + if (e != null) e.remove(); + + if (bossWave != null) + bossWave.clear(); + + arenaPlayers.clear(); + lobbyPlayers.clear(); + readyPlayers.clear(); + + cleanup(); + + spawnTaskId = -1; + sheepTaskId = -1; + } + + public void playerJoin(Player p, Location loc) + { + storePlayerData(p, loc); + MAUtils.sitPets(p); + setHealth(p, 20); + p.setFoodLevel(10); + p.setGameMode(GameMode.SURVIVAL); + movePlayerToLobby(p); + + // Notify listeners. + for (MobArenaListener listener : plugin.getAM().listeners) + listener.onPlayerJoin(this, p); + + if (MobArena.hasSpout && spoutSelect) + Spouty.classSelectionScreen(plugin, this, p); + } + + public void playerReady(Player p) + { + readyPlayers.add(p); + + if (minPlayers > 0 && lobbyPlayers.size() < minPlayers) + { + MAUtils.tellPlayer(p, Msg.LOBBY_NOT_ENOUGH_PLAYERS, "" + minPlayers); + return; + } + + startArena(); + } + + public void playerLeave(Player p) + { + finishArenaPlayer(p, false); + movePlayerToEntry(p); + discardPlayer(p); + + // Notify listeners. + for (MobArenaListener listener : plugin.getAM().listeners) + listener.onPlayerLeave(this, p); + + // End arena if possible. + endArena(); + } + + public void playerDeath(Player p) + { + finishArenaPlayer(p, true); + + if (specOnDeath) + { + clearPlayer(p); + movePlayerToSpec(p); + } + else + { + movePlayerToEntry(p); + discardPlayer(p); + } + + if (running && spawnThread != null) + spawnThread.updateTargets(); + + MAUtils.tellAll(this, Msg.PLAYER_DIED, p.getName()); + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, + new Runnable() + { + public void run() + { + endArena(); + } + }); + + // Notify listeners. + for (MobArenaListener listener : plugin.getAM().listeners) + listener.onPlayerDeath(this, p); + } + + public void playerSpec(Player p, Location loc) + { + storePlayerData(p, loc); + MAUtils.sitPets(p); + movePlayerToSpec(p); + } + + private void spawnPets() + { + for (Map.Entry entry : petMap.entrySet()) + { + // Remove the bones from the inventory. + Player p = entry.getKey(); + p.getInventory().removeItem(new ItemStack(Material.BONE, entry.getValue())); + + // Spawn wolves, set owner and health, and add to pet set. + for (int i = 0; i < entry.getValue(); i++) + { + Wolf wolf = (Wolf) world.spawnCreature(p.getLocation(), CreatureType.WOLF); + wolf.setTamed(true); + wolf.setOwner(p); + wolf.setHealth(20); + if (hellhounds) + wolf.setFireTicks(32768); + pets.add(wolf); + } + } + } + + private void startSpawning() + { + // Set the spawn flags to enable monster spawning. + MAUtils.setSpawnFlags(plugin, world, 1, allowMonsters, allowAnimals); + + // Start the spawnThread. + spawnThread = new MASpawnThread(plugin, this); + spawnTaskId = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, spawnThread, waveDelay, (!waveClear) ? waveInterval : 60); + } + + private void stopSpawning() + { + // Stop the spawn thread. + if (spawnThread != null) + { + Bukkit.getServer().getScheduler().cancelTask(spawnThread.getTaskId()); + Bukkit.getServer().getScheduler().cancelTask(spawnTaskId); + Bukkit.getServer().getScheduler().cancelTask(sheepTaskId); + spawnTaskId = -1; + sheepTaskId = -1; + spawnThread = null; + currentWave = null; + } + else System.out.println("--------- THE SPAWNTHREAD IS NULL! ----------"); + + // Restore spawn flags. + MAUtils.setSpawnFlags(plugin, world, spawnMonsters, allowMonsters, allowAnimals); + } + + private void startBouncingSheep() + { + sheepTaskId = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, + new Runnable() + { + public void run() + { + if (explodingSheep.isEmpty()) return; + + for (LivingEntity e : new LinkedList(explodingSheep)) + { + if (e == null) continue; + + Creature c = (Creature) e; + LivingEntity target = c.getTarget(); + if (target != null && target instanceof Player && MAUtils.distanceSquared((Player) target, e.getLocation()) < 8D) + { + CraftEntity ce = (CraftEntity) e; + CraftWorld cw = (CraftWorld) e.getWorld(); + WorldServer ws = cw.getHandle(); + ws.createExplosion(ce.getHandle(), e.getLocation().getX(), e.getLocation().getY() + 1, e.getLocation().getZ(), 2f, false); + e.remove(); + } + + if (e.isDead()) + { + explodingSheep.remove(e); + continue; + } + + if (Math.abs(e.getVelocity().getY()) < 1) + e.setVelocity(e.getVelocity().setY(0.5)); + } + } + }, waveDelay, 20); + } + + private void updateChunk(Location loc) + { + if (!arenaPlayers.isEmpty() || !world.getName().equals(loc.getWorld().getName())) + return; + + Chunk chunk = world.getChunkAt(loc); + if (!world.isChunkLoaded(chunk)) + world.loadChunk(chunk); + else + world.refreshChunk(chunk.getX(), chunk.getZ()); + } + + public void playerKill(Player p) + { + if (p == null || log.players.get(p) == null) + return; + + arenaPlayerMap.get(p).getStats().kills++; + } + + public void restoreInvAndGiveRewardsDelayed(final Player p) + { + final List rewards = log != null && log.players.get(p) != null ? log.players.get(p).rewards : new LinkedList(); + final boolean hadRewards = rewardedPlayers.contains(p); + + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, + new Runnable() + { + public void run() + { + if (!emptyInvJoin) + MAUtils.restoreInventory(p); + + if (hadRewards) + return; + + MAUtils.giveRewards(p, rewards, plugin); + if (running) + rewardedPlayers.add(p); + } + }); + } + + public void restoreInvAndGiveRewards(final Player p) + { + if (!emptyInvJoin) + MAUtils.restoreInventory(p); + + if (rewardedPlayers.contains(p)) + return; + + final List rewards = (log != null && log.players.get(p) != null) ? + log.players.get(p).rewards : + new LinkedList(); + + MAUtils.giveRewards(p, rewards, plugin); + if (running) + rewardedPlayers.add(p); + } + + public void storePlayerData(Player p, Location loc) + { + plugin.getAM().arenaMap.put(p, this); + + if (!locations.containsKey(p)) + locations.put(p, loc); + + if (!healthMap.containsKey(p)) + healthMap.put(p, p.getHealth()); + + if (!hungerMap.containsKey(p)) + hungerMap.put(p, p.getFoodLevel()); + + if (!modeMap.containsKey(p)) + modeMap.put(p, p.getGameMode()); + } + + public void storeContainerContents() + { + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, + new Runnable() + { + public void run() + { + for (Location loc : containers.values()) + { + BlockState state = world.getBlockAt(loc).getState(); + if (state instanceof ContainerBlock) + containables.add(new RepairableContainer(state, false)); + } + } + }); + } + + public void restoreContainerContents() + { + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, + new Runnable() + { + public void run() + { + for (Repairable r : containables) + r.repair(); + } + }); + } + + public void movePlayerToLobby(Player p) + { + updateChunk(lobbyLoc); + lobbyPlayers.add(p); + p.teleport(lobbyLoc); + } + + public void movePlayerToSpec(Player p) + { + updateChunk(spectatorLoc); + specPlayers.add(p); + p.teleport(spectatorLoc); + } + + public void movePlayerToEntry(Player p) + { + Location entry = locations.get(p); + if (entry == null || p.isDead()) return; + + updateChunk(entry); + p.teleport(entry); + } + + private void clearPlayer(Player p) + { + if (healthMap.containsKey(p)) + { + int health = healthMap.remove(p); + setHealth(p, health); + } + + if (hungerMap.containsKey(p)) + p.setFoodLevel(hungerMap.remove(p)); + + if (modeMap.containsKey(p)) + p.setGameMode(modeMap.remove(p)); + + // Put out fire. + Delays.douse(plugin, p, 3); + + // Remove pets. + removePets(p); + + // readyPlayers before lobbyPlayers because of startArena sanity-checks + readyPlayers.remove(p); + specPlayers.remove(p); + arenaPlayers.remove(p); + lobbyPlayers.remove(p); + classMap.remove(p); + arenaPlayerMap.remove(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); + clearPlayer(p); + } + + /** + * Give the player back his inventory and record his last wave. + * Called when a player dies or leaves prematurely. + * @param p A player + * @param dead If the player died or not + */ + private void finishArenaPlayer(Player p, boolean dead) + { + if (!arenaPlayers.contains(p) && !lobbyPlayers.contains(p)) + return; + + removeClassPermissions(p); + MAUtils.clearInventory(p); + + if (dead) restoreInvAndGiveRewardsDelayed(p); + else restoreInvAndGiveRewards(p); + + ArenaPlayer ap = arenaPlayerMap.get(p); + if (ap != null) + ap.setDead(true); + } + + private void setHealth(Player p, int health) + { + // Grab the current health + int current = p.getHealth(); + + // If the health is 20, just leave it at that no matter what. + int regain = health == 20 ? 20 : health - current; + + // Set the health, and fire off the event. + p.setHealth(health); + EntityRegainHealthEvent event = new EntityRegainHealthEvent(p, regain, RegainReason.CUSTOM); + Bukkit.getPluginManager().callEvent(event); + } + + public void repairBlocks() + { + while (!repairQueue.isEmpty()) + repairQueue.poll().repair(); + } + + public void queueRepairable(Repairable r) + { + repairQueue.add(r); + } + + + + /*//////////////////////////////////////////////////////////////////// + // + // Items & Cleanup + // + ////////////////////////////////////////////////////////////////////*/ + + public void assignClass(Player p, String className) + { + petMap.remove(p); + randoms.remove(p); + classMap.put(p, className); + + MAUtils.clearInventory(p); + + // If random, don't give any items yet. + if (className.equalsIgnoreCase("random")) + { + randoms.add(p); + return; + } + + MAUtils.giveItems(p, classItems.get(className), autoEquip, plugin); + MAUtils.giveItems(p, classArmor.get(className), autoEquip, plugin); + + int pets = MAUtils.getPetAmount(p); + if (pets > 0) petMap.put(p, pets); + } + + public void assignRandomClass(Player p) + { + Random r = new Random(); + List classes = new LinkedList(plugin.getAM().classes); + + String className = classes.remove(r.nextInt(classes.size())); + while (!plugin.has(p, "mobarena.classes." + className)) + { + if (classes.isEmpty()) + { + MobArena.info("Player '" + p.getName() + "' has no class permissions!"); + playerLeave(p); + return; + } + className = classes.remove(r.nextInt(classes.size())); + } + + assignClass(p, className); + MAUtils.tellPlayer(p, Msg.LOBBY_CLASS_PICKED, className); + } + + public void assignClassPermissions(Player p) + { + Map perms = classPerms.get(classMap.get(p)); + if (perms == null || perms.isEmpty()) return; + + PermissionAttachment pa = p.addAttachment(plugin); + attachments.put(p,pa); + for (Map.Entry entry : perms.entrySet()) + pa.setPermission(entry.getKey(), entry.getValue()); + } + + public void removeClassPermissions(Player p) + { + if (attachments.get(p) == null) return; + + for (PermissionAttachment pa : attachments.values()) + if (pa != null) pa.remove(); + } + + private void cleanup() + { + removeMonsters(); + removeBlocks(); + removePets(); + removeEntities(); + monsters.clear(); + explodingSheep.clear(); + plaguedPigs.clear(); + madCows.clear(); + blocks.clear(); + pets.clear(); + } + + private void removeMonsters() + { + if (bossWave != null) + bossWave.clear(); + for (LivingEntity e : monsters) + if (e != null) e.remove(); + for (LivingEntity e : explodingSheep) + if (e != null) e.remove(); + for (LivingEntity e : plaguedPigs) + if (e != null) e.remove(); + for (LivingEntity e : madCows) + if (e != null) e.remove(); + } + + private void removeBlocks() + { + for (Block b : blocks) + b.setTypeId(0); + } + + private void removePets() + { + for (Wolf w : pets) + { + if (w == null) continue; + + w.setOwner(null); + w.remove(); + } + } + + private void removePets(Player p) + { + for (Wolf w : pets) + { + if (w == null || !(w.getOwner() instanceof Player) || !((Player) w.getOwner()).getName().equals(p.getName())) + continue; + + w.setOwner(null); + w.remove(); + } + petMap.remove(p); + } + + private void removeEntities() + { + if (p1 == null || p2 == null) return; + Chunk c1 = world.getChunkAt(p1); + Chunk c2 = world.getChunkAt(p2); + + for (int i = c1.getX(); i <= c2.getX(); i++) + for (int j = c1.getZ(); j <= c2.getZ(); j++) + for (Entity e : world.getChunkAt(i,j).getEntities()) + if ((e instanceof Item || e instanceof Slime) && inRegion(e.getLocation())) + if (e != null) e.remove(); + } + + + + /*//////////////////////////////////////////////////////////////////// + // + // Initialization & Checks + // + ////////////////////////////////////////////////////////////////////*/ + + public void load(Config config) + { + config.load(); + + String arenaPath = "arenas." + MAUtils.nameArenaToConfig(name) + ".settings."; + String configName = MAUtils.nameArenaToConfig(name); + + enabled = config.getBoolean(arenaPath + "enabled", true); + protect = config.getBoolean(arenaPath + "protect", true); + 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); + detDamage = config.getBoolean(arenaPath + "detonate-damage", false); + lightning = config.getBoolean(arenaPath + "lightning", true); + forceRestore = config.getBoolean(arenaPath + "force-restore", false); + softRestore = config.getBoolean(arenaPath + "soft-restore", false); + softRestoreDrops = config.getBoolean(arenaPath + "soft-restore-drops", false); + emptyInvJoin = config.getBoolean(arenaPath + "require-empty-inv-join", true); + emptyInvSpec = config.getBoolean(arenaPath + "require-empty-inv-spec", true); + hellhounds = config.getBoolean(arenaPath + "hellhounds", false); + pvp = config.getBoolean(arenaPath + "pvp-enabled", false); + monsterInfight = config.getBoolean(arenaPath + "monster-infight", false); + allowWarp = config.getBoolean(arenaPath + "allow-teleporting", false); + specOnDeath = config.getBoolean(arenaPath + "spectate-on-death", true); + shareInArena = config.getBoolean(arenaPath + "share-items-in-arena", true); + spoutSelect = config.getBoolean(arenaPath + "spout-class-select", true); + joinDistance = config.getInt(arenaPath + "max-join-distance", 0); + minPlayers = config.getInt(arenaPath + "min-players", 0); + maxPlayers = config.getInt(arenaPath + "max-players", 0); + waveDelay = config.getInt(arenaPath + "first-wave-delay", 5) * 20; + waveInterval = config.getInt(arenaPath + "wave-interval", 20) * 20; + specialModulo = config.getInt(arenaPath + "special-modulo", 4); + maxIdleTime = config.getInt(arenaPath + "max-idle-time", 0) * 20; + finalWave = config.getInt(arenaPath + "final-wave", 0); + + everyWaveMap = MAUtils.getArenaRewardMap(config, configName, "every"); + afterWaveMap = MAUtils.getArenaRewardMap(config, configName, "after"); + entryFee = MAUtils.getEntryFee(config, configName); + + p1 = MAUtils.getArenaCoord(config, world, configName, "p1"); + p2 = MAUtils.getArenaCoord(config, world, configName, "p2"); + l1 = MAUtils.getArenaCoord(config, world, configName, "l1"); + l2 = MAUtils.getArenaCoord(config, world, configName, "l2"); + arenaLoc = MAUtils.getArenaCoord(config, world, configName, "arena"); + lobbyLoc = MAUtils.getArenaCoord(config, world, configName, "lobby"); + spectatorLoc = MAUtils.getArenaCoord(config, world, configName, "spectator"); + 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); + recurrentWaves = WaveUtils.getWaves(this, config, WaveBranch.RECURRENT); + + classes = plugin.getAM().classes; + classItems = plugin.getAM().classItems; + classArmor = plugin.getAM().classArmor; + classPerms = plugin.getAM().classPerms; + + // Determine if the arena is properly set up. Then add the to arena list. + setup = MAUtils.verifyData(this); + lobbySetup = MAUtils.verifyLobby(this); + } + + public void restoreRegion() + { + Collections.sort(repairables, new RepairableComparator()); + + for (Repairable r : repairables) + r.repair(); + } + + public void serializeConfig() + { + String coords = "arenas." + configName() + ".coords."; + Config config = plugin.getMAConfig(); + + config.setProperty("arenas." + configName() + ".settings.enabled", enabled); + config.setProperty("arenas." + configName() + ".settings.protect", protect); + if (p1 != null) config.setProperty(coords + "p1", MAUtils.makeCoord(p1)); + if (p2 != null) config.setProperty(coords + "p2", MAUtils.makeCoord(p2)); + if (l1 != null) config.setProperty(coords + "l1", MAUtils.makeCoord(l1)); + if (l2 != null) config.setProperty(coords + "l2", MAUtils.makeCoord(l2)); + if (arenaLoc != null) config.setProperty(coords + "arena", MAUtils.makeCoord(arenaLoc)); + if (lobbyLoc != null) config.setProperty(coords + "lobby", MAUtils.makeCoord(lobbyLoc)); + if (spectatorLoc != null) config.setProperty(coords + "spectator", MAUtils.makeCoord(spectatorLoc)); + for (Map.Entry entry : spawnpoints.entrySet()) + config.setProperty(coords + "spawnpoints." + entry.getKey(), MAUtils.makeCoord(entry.getValue())); + for (Map.Entry entry : spawnpointsBoss.entrySet()) + config.setProperty(coords + "spawnpoints." + entry.getKey(), MAUtils.makeCoord(entry.getValue())); + + config.save(); + } + + public void deserializeConfig() + { + Config config = plugin.getMAConfig(); + config.load(); + load(config); + } + + public boolean serializeRegion() + { + int x1 = (int) p1.getX(); + int y1 = (int) p1.getY(); + int z1 = (int) p1.getZ(); + int x2 = (int) p2.getX(); + int y2 = (int) p2.getY(); + int z2 = (int) p2.getZ(); + + HashSet set = new HashSet(); + int[] buffer; + for (int i = x1; i <= x2; i++) + { + for (int j = y1; j <= y2; j++) + { + for (int k = z1; k <= z2; k++) + { + buffer = new int[4]; + buffer[0] = i; + buffer[1] = j; + buffer[2] = k; + buffer[3] = world.getBlockAt(i,j,k).getTypeId(); + set.add(buffer); + } + } + } + + try + { + new File(plugin.getDataFolder() + File.separator + "regions").mkdir(); + File regionFile = new File(plugin.getDataFolder() + File.separator + "regions" + File.separator + configName() + ".tmp"); + if (regionFile.exists()) + regionFile.createNewFile(); + + FileOutputStream fos = new FileOutputStream(regionFile); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(set); + oos.close(); + } + catch (Exception e) + { + MobArena.warning("Could not create region file. The arena will not be started!"); + e.printStackTrace(); + return false; + } + return true; + } + + @SuppressWarnings("unchecked") + public boolean deserializeRegion() + { + HashSet set = new HashSet(); + try + { + File regionFile = new File(plugin.getDataFolder() + File.separator + "regions" + File.separator + configName() + ".tmp"); + if (!regionFile.exists()) + return false; + + FileInputStream fis = new FileInputStream(regionFile); + ObjectInputStream ois = new ObjectInputStream(fis); + set = (HashSet) ois.readObject(); + ois.close(); + } + catch (Exception e) + { + MobArena.warning("Could not find region file. The arena cannot be restored!"); + e.printStackTrace(); + return false; + } + + for (int[] buffer : set) + world.getBlockAt(buffer[0], buffer[1], buffer[2]).setTypeId(buffer[3]); + + return true; + } + + /** + * Check if a location is inside of the cuboid region + * that p1 and p2 span. + */ + public boolean inRegion(Location loc) + { + if (!loc.getWorld().getName().equals(world.getName()) || !setup) + return false; + + int x = loc.getBlockX(); + int y = loc.getBlockY(); + int z = loc.getBlockZ(); + + // Check the lobby first. + if (lobbySetup) + { + if ((x >= l1.getBlockX() && x <= l2.getBlockX()) && + (z >= l1.getBlockZ() && z <= l2.getBlockZ()) && + (y >= l1.getBlockY() && y <= l2.getBlockY())) + return true; + } + + // Returns false if the location is outside of the region. + return ((x >= p1.getBlockX() && x <= p2.getBlockX()) && + (z >= p1.getBlockZ() && z <= p2.getBlockZ()) && + (y >= p1.getBlockY() && y <= p2.getBlockY())); + } + + /** + * Check if a location is inside of the arena region, expanded + * by 'radius' blocks. Used with explosions. + */ + public boolean inRegionRadius(Location loc, int radius) + { + if (!loc.getWorld().getName().equals(world.getName()) || !setup) + return false; + + int x = loc.getBlockX(); + int y = loc.getBlockY(); + int z = loc.getBlockZ(); + + // Check the lobby first. + if (lobbySetup) + { + if ((x + radius >= l1.getBlockX() && x - radius <= l2.getBlockX()) && + (z + radius >= l1.getBlockZ() && z - radius <= l2.getBlockZ()) && + (y + radius >= l1.getBlockY() && y - radius <= l2.getBlockY())) + return true; + } + + return ((x + radius >= p1.getBlockX() && x - radius <= p2.getBlockX()) && + (z + radius >= p1.getBlockZ() && z - radius <= p2.getBlockZ()) && + (y + radius >= p1.getBlockY() && y - radius <= p2.getBlockY())); + } + + + + /*//////////////////////////////////////////////////////////////////// + // + // Getters & Misc + // + ////////////////////////////////////////////////////////////////////*/ + + public boolean inArena(Player p) + { + return arenaPlayers.contains(p); + } + + public boolean inLobby(Player p) + { + return lobbyPlayers.contains(p); + } + + public boolean isRunning() + { + return running; + } + + public boolean isPvpEnabled() + { + return pvp; + } + + public boolean isLightningEnabled() + { + return lightning; + } + + public boolean isBossWave() + { + return bossWave != null; + } + + public String configName() + { + return MAUtils.nameArenaToConfig(name); + } + + public String arenaName() + { + return name; + } + + public MobArena getPlugin() + { + return plugin; + } + + public World getWorld() + { + return world; + } + + public Wave getWave() + { + return currentWave; + } + + public void setWave(Wave wave) + { + currentWave = wave; + } + + public void setBossWave(BossWave bossWave) + { + this.bossWave = bossWave; + } + + public Set getClasses() + { + return classes; + } + + public List getAllSpawnpoints() + { + ArrayList result = new ArrayList(spawnpoints.size() + spawnpointsBoss.size()); + result.addAll(spawnpoints.values()); + result.addAll(spawnpointsBoss.values()); + return result; + } + + public List getSpawnpoints() + { + return new ArrayList(spawnpoints.values()); + } + + public Location getBossSpawnpoint() + { + if (spawnpointsBoss.isEmpty()) + { + List points = WaveUtils.getValidSpawnpoints(this, getLivingPlayers()); + return points.get(MobArena.random.nextInt(points.size())); + } + + return new ArrayList(spawnpointsBoss.values()).get(MobArena.random.nextInt(spawnpointsBoss.size())); + } + + public int getPlayerCount() + { + return spawnThread.getPlayerCount(); + } + + public void addBlock(Block b) + { + blocks.add(b); + } + + public void addMonster(LivingEntity e) + { + monsters.add(e); + } + + public void addExplodingSheep(LivingEntity e) + { + explodingSheep.add(e); + } + + public List getAllPlayers() + { + List result = new LinkedList(); + result.addAll(arenaPlayers); + result.addAll(lobbyPlayers); + result.addAll(specPlayers); + return result; + } + + public List getLivingPlayers() + { + List result = new LinkedList(); + result.addAll(arenaPlayers); + return result; + } + + public Set getArenaPlayers() + { + 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(); + result.addAll(lobbyPlayers); + result.removeAll(readyPlayers); + return result; + } + + public Set getMonsters() + { + Set tmp = new HashSet(monsters); + tmp.addAll(explodingSheep); + return tmp; + } + + public Set getPets() + { + return pets; + } + + public void resetIdleTimer() + { + if (maxIdleTime <= 0 || !running) + return; + + // Reset the previousSize, cancel the previous timer, and start the new timer. + spawnThread.setPreviousSize(getMonsters().size()); + Bukkit.getServer().getScheduler().cancelTask(spawnThread.getTaskId()); + int id = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, + new Runnable() + { + public void run() + { + // Make sure to remove any dead/removed entities first. + List ms = new LinkedList(monsters); + for (Entity e : ms) + if (e.isDead()) + monsters.remove(e); + + // Compare the current size with the previous size. + if (monsters.size() < spawnThread.getPreviousSize() || spawnThread.getPreviousSize() == 0 || bossWave != null) + { + resetIdleTimer(); + return; + } + + // Clear all player inventories, and "kill" all players. + List ps = new LinkedList(arenaPlayers); + for (Player p : ps) + { + MAUtils.clearInventory(p); + MAUtils.tellPlayer(p, Msg.FORCE_END_IDLE); + playerDeath(p); + } + } + }, maxIdleTime); + spawnThread.setTaskId(id); + } + + public void addTrunkAndLeaves(Block b) + { + final int x = b.getX(); + final int y = b.getY(); + final int z = b.getZ(); + + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, + new Runnable() + { + public void run() + { + List result = new LinkedList(); + for (int i = x-2; i <= x+2; i++) + for (int j = y; j <= y+10; j++) + for (int k = z-2; k <= z+2; k++) + if (world.getBlockAt(i,j,k).getType() == Material.LOG || world.getBlockAt(i,j,k).getType() == Material.LEAVES) + result.add(world.getBlockAt(i,j,k)); + + if (running) blocks.addAll(result); + } + }, 10); + } + + public boolean canAfford(Player p) + { + if (entryFee.isEmpty()) + return true; + + PlayerInventory inv = p.getInventory(); + for (ItemStack stack : entryFee) + { + // Economy money + if (stack.getTypeId() == MobArena.ECONOMY_MONEY_ID) + { + //if (plugin.Methods.hasMethod() && !plugin.Method.getAccount(p.getName()).hasEnough(stack.getAmount())) + if (plugin.Method != null && !(plugin.Method.getAccount(p.getName()).balance() >= stack.getAmount())) + return false; + } + // Normal stack + else + { + if (!inv.contains(stack.getTypeId(), stack.getAmount())) + return false; + } + } + + return true; + } + + public boolean takeFee(Player p) + { + if (entryFee.isEmpty()) + return true; + + PlayerInventory inv = p.getInventory(); + InventoryItem[] items = InventoryItem.parseItemStacks(inv.getContents()); + InventoryItem[] fee = InventoryItem.parseItemStacks(entryFee); + + // Take some economy money + for (InventoryItem item : InventoryItem.extractAllFromArray(MobArena.ECONOMY_MONEY_ID, fee)) + if (plugin.Method != null) + plugin.Method.getAccount(p.getName()).subtract(item.getAmount()); + + // Take any other items + for (InventoryItem item : fee) + InventoryItem.removeItemFromArray(item, items); + + // Turn everything back into ItemStacks + for (int i = 0; i < items.length; i++) + inv.setItem(i, items[i].toItemStack()); + + return true; + } + + public boolean canJoin(Player p) + { + if (!enabled) + MAUtils.tellPlayer(p, Msg.JOIN_ARENA_NOT_ENABLED); + else if (!setup || recurrentWaves.isEmpty()) + MAUtils.tellPlayer(p, Msg.JOIN_ARENA_NOT_SETUP); + else if (edit) + MAUtils.tellPlayer(p, Msg.JOIN_ARENA_EDIT_MODE); + else if (running && (notifyPlayers.contains(p) || notifyPlayers.add(p))) + MAUtils.tellPlayer(p, Msg.JOIN_ARENA_IS_RUNNING); + else if (arenaPlayers.contains(p) || lobbyPlayers.contains(p)) + MAUtils.tellPlayer(p, Msg.JOIN_ALREADY_PLAYING); + else if (!plugin.has(p, "mobarena.arenas." + configName())) + MAUtils.tellPlayer(p, Msg.JOIN_ARENA_PERMISSION); + else if (maxPlayers > 0 && lobbyPlayers.size() >= maxPlayers) + MAUtils.tellPlayer(p, Msg.JOIN_PLAYER_LIMIT_REACHED); + else if (joinDistance > 0 && !inRegionRadius(p.getLocation(), joinDistance)) + MAUtils.tellPlayer(p, Msg.JOIN_TOO_FAR); + else if (emptyInvJoin && !MAUtils.hasEmptyInventory(p)) + MAUtils.tellPlayer(p, Msg.JOIN_EMPTY_INV); + else if (!canAfford(p))// || !takeFee(p)) + MAUtils.tellPlayer(p, Msg.JOIN_FEE_REQUIRED, MAUtils.listToString(entryFee, plugin)); + else return true; + + return false; + } + + public boolean canSpec(Player p) + { + if (!enabled) + MAUtils.tellPlayer(p, Msg.JOIN_ARENA_NOT_ENABLED); + else if (!setup) + MAUtils.tellPlayer(p, Msg.JOIN_ARENA_NOT_SETUP); + else if (edit) + MAUtils.tellPlayer(p, Msg.JOIN_ARENA_EDIT_MODE); + else if (arenaPlayers.contains(p) || lobbyPlayers.contains(p)) + MAUtils.tellPlayer(p, Msg.SPEC_ALREADY_PLAYING); + else if (emptyInvSpec && !MAUtils.hasEmptyInventory(p)) + MAUtils.tellPlayer(p, Msg.SPEC_EMPTY_INV); + else if (joinDistance > 0 && !inRegionRadius(p.getLocation(), joinDistance)) + MAUtils.tellPlayer(p, Msg.JOIN_TOO_FAR); + else return true; + + return false; + } + + /** + * The "perfect equals method" cf. "Object-Oriented Design and Patterns" + * by Cay S. Horstmann. + */ + public boolean equals(Object other) + { + if (this == other) return true; + if (other == null) return false; + if (getClass() != other.getClass()) return false; + + // Arenas must have different names. + if (other instanceof ArenaStandard && ((ArenaStandard)other).name.equals(name)) + return true; + + return false; + } + + public String toString() + { + return ((enabled && setup) ? ChatColor.GREEN : ChatColor.GRAY) + configName(); + } +} diff --git a/src/com/garbagemule/MobArena/MACommands.java b/src/com/garbagemule/MobArena/MACommands.java index bfe18ad..b2fce4c 100644 --- a/src/com/garbagemule/MobArena/MACommands.java +++ b/src/com/garbagemule/MobArena/MACommands.java @@ -73,6 +73,11 @@ public class MACommands implements CommandExecutor private MobArena plugin; private ArenaMaster am; + public MACommands() + { + + } + public MACommands(MobArena plugin, ArenaMaster am) { this.plugin = plugin; @@ -1029,7 +1034,7 @@ public class MACommands implements CommandExecutor } StringBuffer buffy = new StringBuffer(); - List spawnpoints = plugin.getMAConfig().getKeys("arenas." + am.selectedArena.configName() + ".coords.spawnpoints"); + Set spawnpoints = plugin.getMAConfig().getKeys("arenas." + am.selectedArena.configName() + ".coords.spawnpoints"); if (spawnpoints != null) { @@ -1101,7 +1106,7 @@ public class MACommands implements CommandExecutor } StringBuffer buffy = new StringBuffer(); - List containers = plugin.getMAConfig().getKeys("arenas." + am.selectedArena.configName() + ".coords.containers"); + Set containers = plugin.getMAConfig().getKeys("arenas." + am.selectedArena.configName() + ".coords.containers"); if (containers != null) { diff --git a/src/com/garbagemule/MobArena/MAUtils.java b/src/com/garbagemule/MobArena/MAUtils.java index 9fc223a..999818e 100644 --- a/src/com/garbagemule/MobArena/MAUtils.java +++ b/src/com/garbagemule/MobArena/MAUtils.java @@ -33,11 +33,12 @@ import org.bukkit.entity.Player; import org.bukkit.entity.Wolf; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; -import org.bukkit.util.config.Configuration; +//import org.bukkit.util.config.Configuration; import org.getspout.spoutapi.SpoutManager; import org.getspout.spoutapi.player.SpoutPlayer; import com.garbagemule.MobArena.MAMessages.Msg; +import com.garbagemule.MobArena.util.Config; import com.garbagemule.MobArena.util.EntityPosition; import com.garbagemule.MobArena.util.InventoryItem; @@ -136,7 +137,7 @@ public class MAUtils // ///////////////////////////////////////////////////////////////////// */ - public static Map getArenaContainers(Configuration config, World world, String arena) + public static Map getArenaContainers(Config config, World world, String arena) { Map containers = new HashMap(); String arenaPath = "arenas." + arena + ".coords.containers"; @@ -153,7 +154,7 @@ public class MAUtils /** * Grab all the spawnpoints for a specific arena. */ - public static Map getArenaSpawnpoints(Configuration config, World world, String arena) + public static Map getArenaSpawnpoints(Config config, World world, String arena) { Map spawnpoints = new HashMap(); String arenaPath = "arenas." + arena + ".coords.spawnpoints"; @@ -168,7 +169,7 @@ public class MAUtils return spawnpoints; } - public static Map getArenaBossSpawnpoints(Configuration config, World world, String arena) + public static Map getArenaBossSpawnpoints(Config config, World world, String arena) { Map spawnpoints = new HashMap(); String arenaPath = "arenas." + arena + ".coords.spawnpoints"; @@ -186,7 +187,7 @@ public class MAUtils /** * Returns a map of classnames mapped to lists of ItemStacks. */ - public static Map> getClassItems(Configuration config, String type) + public static Map> getClassItems(Config config, String type) { Map> result = new HashMap>(); @@ -196,11 +197,11 @@ public class MAUtils return result; } - public static Map> getClassPerms(Configuration config) + public static Map> getClassPerms(Config config) { Map> result = new HashMap>(); - List classes = config.getKeys("classes"); + Set classes = config.getKeys("classes"); if (classes == null) return result; for (String c : classes) @@ -224,7 +225,7 @@ public class MAUtils return result; } - public static List getEntryFee(Configuration config, String arena) + public static List getEntryFee(Config config, String arena) { return makeItemStackList(config.getString("arenas." + arena + ".settings.entry-fee", null)); } @@ -276,7 +277,7 @@ public class MAUtils * type of wave ("after" or "every") and the config-file. If * no keys exist in the config-file, an empty map is returned. */ - public static Map> getArenaRewardMap(Configuration config, String arena, String type) + public static Map> getArenaRewardMap(Config config, String arena, String type) { String arenaPath = "arenas." + arena + ".rewards.waves."; Map> result = new HashMap>(); @@ -297,7 +298,7 @@ public class MAUtils } } - List waves = config.getKeys(arenaPath + type); + Set waves = config.getKeys(arenaPath + type); if (waves == null) return result; for (String n : waves) @@ -313,7 +314,7 @@ public class MAUtils return result; } - public static List getAllowedCommands(Configuration config) + public static List getAllowedCommands(Config config) { String commands = config.getString("global-settings.allowed-commands"); if (commands == null) @@ -768,7 +769,7 @@ public class MAUtils /** * Create a Location object from the config-file. */ - public static Location getArenaCoord(Configuration config, World world, String arena, String coord) + public static Location getArenaCoord(Config config, World world, String arena, String coord) { //config.load(); String str = config.getString("arenas." + arena + ".coords." + coord); @@ -778,9 +779,9 @@ public class MAUtils } /** - * Save an arena location to the Configuration. + * Save an arena location to the Config. */ - public static void setArenaCoord(Configuration config, Arena arena, String coord, Location loc) + public static void setArenaCoord(Config config, Arena arena, String coord, Location loc) { if (coord.equals("arena") || coord.equals("lobby") || coord.equals("spectator")) loc.setY(loc.getY() + 1); @@ -795,7 +796,7 @@ public class MAUtils fixLobby(config, loc.getWorld(), arena); } - public static boolean delArenaCoord(Configuration config, Arena arena, String coord) + public static boolean delArenaCoord(Config config, Arena arena, String coord) { if (config.getString("arenas." + arena.configName() + ".coords." + coord) == null) return false; @@ -806,7 +807,7 @@ public class MAUtils return true; } - public static void fixRegion(Configuration config, World world, Arena arena) + public static void fixRegion(Config config, World world, Arena arena) { if (arena.p1 == null || arena.p2 == null) return; @@ -839,7 +840,7 @@ public class MAUtils arena.load(config); } - private static void fixLobby(Configuration config, World world, Arena arena) + private static void fixLobby(Config config, World world, Arena arena) { if (arena.l1 == null || arena.l2 == null) return; @@ -932,12 +933,12 @@ public class MAUtils return false; } - public static double getDouble(Configuration config, String path) + public static double getDouble(Config config, String path) { return getDouble(config, path, 0D); } - public static double getDouble(Configuration config, String path, double def) + public static double getDouble(Config config, String path, double def) { Object o = config.getProperty(path); if (o instanceof Double) @@ -947,12 +948,12 @@ public class MAUtils return def; } - public static int getInt(Configuration config, String path) + public static int getInt(Config config, String path) { return getInt(config, path, 0); } - public static int getInt(Configuration config, String path, int def) + public static int getInt(Config config, String path, int def) { Object o = config.getProperty(path); if (o instanceof Integer) @@ -1638,7 +1639,7 @@ public class MAUtils world.getBlockAt(entry.getKey().getLocation(world)).setTypeId(entry.getValue()); } - Configuration config = plugin.getMAConfig(); + Config config = plugin.getMAConfig(); config.removeProperty("arenas." + name); config.save(); diff --git a/src/com/garbagemule/MobArena/MobArena.java b/src/com/garbagemule/MobArena/MobArena.java index 253764b..84d243c 100644 --- a/src/com/garbagemule/MobArena/MobArena.java +++ b/src/com/garbagemule/MobArena/MobArena.java @@ -14,10 +14,11 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.PluginManager; -import org.bukkit.util.config.Configuration; +//import org.bukkit.util.config.Configuration; import com.garbagemule.MobArena.listeners.MagicSpellsListener; import com.garbagemule.MobArena.spout.Spouty; +import com.garbagemule.MobArena.util.Config; import com.garbagemule.MobArena.util.FileUtils; import com.garbagemule.register.payment.Method; import com.garbagemule.register.payment.Methods; @@ -26,9 +27,10 @@ import com.garbagemule.register.payment.Methods; * MobArena * @author garbagemule */ -public class MobArena extends JavaPlugin +public class MobArena extends JavaPlugin implements MobArenaPlugin { - private Configuration config; + //private Configuration config; + private Config config; private ArenaMaster am; // Economy stuff @@ -54,7 +56,7 @@ public class MobArena extends JavaPlugin desc = getDescription(); dir = getDataFolder(); arenaDir = new File(dir, "arenas"); - if (!dir.exists()) dir.mkdir(); + if (!dir.exists()) dir.mkdirs(); if (!arenaDir.exists()) arenaDir.mkdir(); // Create default files and initialize config-file @@ -71,8 +73,9 @@ public class MobArena extends JavaPlugin setupMagicSpells(); // Set up the ArenaMaster and the announcements - am = new ArenaMaster(this); + am = new ArenaMasterStandard(this); am.initialize(); + System.out.println(am.arenas); MAMessages.init(this); // Register event listeners @@ -99,7 +102,7 @@ public class MobArena extends JavaPlugin private void loadConfig() { File file = new File(dir, "config.yml"); - config = new Configuration(file); + config = new Config(file); config.load(); config.setHeader(getHeader()); } @@ -199,8 +202,10 @@ public class MobArena extends JavaPlugin pm.registerEvent(Event.Type.CUSTOM_EVENT, new MagicSpellsListener(this), Priority.Normal, this); } - public Configuration getMAConfig() { return config; } - public ArenaMaster getAM() { return am; } // More convenient. + public Config getMAConfig() { return config; } + public ArenaMaster getAM() { return am; } // More convenient. + + @Override public ArenaMaster getArenaMaster() { return am; } /*public HeroManager getHeroManager() diff --git a/src/com/garbagemule/MobArena/MobArenaPlugin.java b/src/com/garbagemule/MobArena/MobArenaPlugin.java new file mode 100644 index 0000000..c15256d --- /dev/null +++ b/src/com/garbagemule/MobArena/MobArenaPlugin.java @@ -0,0 +1,6 @@ +package com.garbagemule.MobArena; + +public interface MobArenaPlugin +{ + public ArenaMaster getArenaMaster(); +} diff --git a/src/com/garbagemule/MobArena/commands/CommandHandler.java b/src/com/garbagemule/MobArena/commands/CommandHandler.java new file mode 100644 index 0000000..ed2f642 --- /dev/null +++ b/src/com/garbagemule/MobArena/commands/CommandHandler.java @@ -0,0 +1,123 @@ +package com.garbagemule.MobArena.commands; + +import java.io.File; +import java.util.*; + +import org.bukkit.command.*; +import org.bukkit.entity.Player; + +import com.garbagemule.MobArena.*; +import com.garbagemule.MobArena.util.classparsing.*; + +public class CommandHandler implements CommandExecutor +{ + /* COMMAND_PATH is an incomplete package-name for all commands in MobArena, + * hence the trailing dot, and the COMMAND_TYPES array contains all the + * different types of commands (the sub-folders). Both are used in the + * loadCommands() method. */ + private static final String COMMAND_PATH = "com.garbagemule.MobArena.commands."; + private static final String[] COMMAND_TYPES = new String[]{"user", "admin", "setup"}; + + private MobArenaPlugin plugin; + private Map commands; + + public CommandHandler(MobArenaPlugin plugin) { + this.plugin = plugin; + this.commands = new HashMap(); + loadCommands(); + } + + @Override + public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { + if (args.length == 0) { + sender.sendMessage("You need arguments, pal!"); + return true; + } + + // Grab the command from the map, and if null, didn't work. + MACommand command = commands.get(args[0]); + if (command == null) { + System.out.println("Command '" + label + "' not recognized"); + return true; + } + + // Cast if sender is a Player, null otherwise. + Player p = (sender instanceof Player) ? (Player) sender : null; + + // If null, must be console. + if (p == null) { + if (!command.executeFromConsole(plugin, sender, args)) { + sender.sendMessage("Can't use that command from the console."); + } + return true; + } + + // Otherwise, check permissions + if (!p.hasPermission(command.getPermission())) { + sender.sendMessage("No permission"); + return true; + } + + // Execute! + command.execute(plugin, p, trimFirstArg(args)); + + return true; + } + + /** + * Since Java doesn't support pointer arithmetic, this method + * attempts to remove the first element of a String[] object + * by creating a new array of the same size -1 and copying all + * the elements over. + * @param args a String[] to trim + * @return a String[] with the same elements except for the very first + */ + private String[] trimFirstArg(String[] args) { + String[] result = new String[args.length - 1]; + for (int i = 0; i < result.length; i++) { + result[i] = args[i+1]; + } + return result; + } + + /** + * Load all of the MobArena commands from either the jar or the bin + * folder into the commands-map. Each one of a commands' names/aliases + * is added to the map, such that both "/ma join" and "/ma j" work, for + * instance. + */ + private void loadCommands() { + // Prepare a strategy for the class parser. + ClassIterationStrategy strategy = null; + File f = new File("plugins" + File.separator + "MobArena.jar"); + + try { + // If jar exists, use it - otherwise, use bin. + strategy = (f.exists()) ? new JarClassIterationStrategy(f) : + new DirClassIterationStrategy(new File("bin")); + + // Create a new ClassParser with the given strategy. + ClassParser parser = new ClassParser(strategy); + + // Iterate through all three folders, user/admin/setup + for (String type : COMMAND_TYPES) { + Collection> classes = parser.getClasses(COMMAND_PATH + type); + + for (Class c : classes) { + // Make sure the class is indeed an instance of MACommand + Object obj = c.newInstance(); + if (!(obj instanceof MACommand)) + continue; + + // Then cast, and add for each command name/alias + MACommand command = (MACommand) obj; + for (String name : command.getNames()) { + commands.put(name, command); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/com/garbagemule/MobArena/commands/MACommand.java b/src/com/garbagemule/MobArena/commands/MACommand.java new file mode 100644 index 0000000..b8b3400 --- /dev/null +++ b/src/com/garbagemule/MobArena/commands/MACommand.java @@ -0,0 +1,40 @@ +package com.garbagemule.MobArena.commands; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.garbagemule.MobArena.MobArenaPlugin; + +public interface MACommand +{ + /** + * Get an array of names/aliases for this command. + * Every command must have at least one name/alias to work. + * @return a String[] of names/aliases + */ + public String[] getNames(); + + /** + * Get the permission required to execute this command. + * If there is no permission required, the method returns + * the empty string. + * @return a permission or null + */ + public String getPermission(); + + /** + * Execute the implementing command with the input Player as the executor. + * @param sender The Player executing the command + * @param args A list of arguments + * @return true, if the command was executed successfully, false otherwise + */ + public boolean execute(MobArenaPlugin plugin, Player sender, String... args); + + /** + * Execute the implementing command with the console as the executor. + * @param sender The console executing the command + * @param args A list of arguments + * @return true, if the command was executed successfully, false otherwise + */ + public boolean executeFromConsole(MobArenaPlugin plugin, CommandSender sender, String... args); +} diff --git a/src/com/garbagemule/MobArena/commands/admin/EnableCommand.java b/src/com/garbagemule/MobArena/commands/admin/EnableCommand.java new file mode 100644 index 0000000..2d83d6c --- /dev/null +++ b/src/com/garbagemule/MobArena/commands/admin/EnableCommand.java @@ -0,0 +1,30 @@ +package com.garbagemule.MobArena.commands.admin; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.garbagemule.MobArena.*; +import com.garbagemule.MobArena.commands.*; + +public class EnableCommand implements MACommand +{ + @Override + public String[] getNames() { + return new String[] { "enable" }; + } + + @Override + public String getPermission() { + return "mobarena.admin.enable"; + } + + @Override + public boolean execute(MobArenaPlugin plugin, Player sender, String... args) { + return false; + } + + @Override + public boolean executeFromConsole(MobArenaPlugin plugin, CommandSender sender, String... args) { + return false; + } +} diff --git a/src/com/garbagemule/MobArena/commands/setup/SetRegionCommand.java b/src/com/garbagemule/MobArena/commands/setup/SetRegionCommand.java new file mode 100644 index 0000000..32e77e6 --- /dev/null +++ b/src/com/garbagemule/MobArena/commands/setup/SetRegionCommand.java @@ -0,0 +1,29 @@ +package com.garbagemule.MobArena.commands.setup; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import com.garbagemule.MobArena.commands.*; +import com.garbagemule.MobArena.*; + +public class SetRegionCommand implements MACommand +{ + @Override + public String[] getNames() { + return new String[] { "setregion" }; + } + + @Override + public String getPermission() { + return "mobarena.setup.setregion"; + } + + @Override + public boolean execute(MobArenaPlugin plugin, Player sender, String... args) { + return false; + } + + @Override + public boolean executeFromConsole(MobArenaPlugin plugin, CommandSender sender, String... args) { + return false; + } +} diff --git a/src/com/garbagemule/MobArena/commands/user/ArenaListCommand.java b/src/com/garbagemule/MobArena/commands/user/ArenaListCommand.java new file mode 100644 index 0000000..b2ac3a6 --- /dev/null +++ b/src/com/garbagemule/MobArena/commands/user/ArenaListCommand.java @@ -0,0 +1,53 @@ +package com.garbagemule.MobArena.commands.user; + +import java.util.List; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import com.garbagemule.MobArena.commands.*; +import com.garbagemule.MobArena.*; + +public class ArenaListCommand implements MACommand +{ + @Override + public String[] getNames() { + return new String[] { "arenas" , "list" }; + } + + @Override + public String getPermission() { + return "mobarena.use.arenalist"; + } + + @Override + public boolean execute(MobArenaPlugin plugin, Player sender, String... args) { + // Grab the arena master. + ArenaMaster am = plugin.getArenaMaster(); + + // Get the arenas. + List arenas = am.getEnabledArenas(); + + String msg = "Available arenas: "; + if (arenas.size() == 0) { + sender.sendMessage(msg + ""); + return true; + } + + // Enumerate arenas. + for (Arena a : arenas) { + msg += a.configName() + ", "; + } + + // Trim off the trailing comma. + msg = msg.substring(0, msg.length() - 2); + + // Send the message! + sender.sendMessage(msg); + return true; + } + + @Override + public boolean executeFromConsole(MobArenaPlugin plugin, CommandSender sender, String... args) { + return false; + } +} diff --git a/src/com/garbagemule/MobArena/commands/user/JoinCommand.java b/src/com/garbagemule/MobArena/commands/user/JoinCommand.java new file mode 100644 index 0000000..7da9ce2 --- /dev/null +++ b/src/com/garbagemule/MobArena/commands/user/JoinCommand.java @@ -0,0 +1,53 @@ +package com.garbagemule.MobArena.commands.user; + +import java.util.*; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import com.garbagemule.MobArena.commands.*; +import com.garbagemule.MobArena.*; + +public class JoinCommand implements MACommand +{ + @Override + public String[] getNames() { + return new String[] { "join" , "j" }; + } + + @Override + public String getPermission() { + return "mobarena.use.join"; + } + + @Override + public boolean execute(MobArenaPlugin plugin, Player sender, String... args) { + // Grab the arena master + ArenaMaster am = plugin.getArenaMaster(); + + // Get all enabled arenas. + List arenas = am.getEnabledArenas(); + + // If no arena was specified, and multiple arenas are available, notify. + if (args.length < 1 && arenas.size() > 1) { + sender.sendMessage("There are more than one arena. Pick one, damnit!"); + return false; + } + + // If only one arena, pick it no matter what, otherwise, look for name. + Arena arena = arenas.size() == 1 ? arenas.get(0) : am.getArenaWithName(args[0]); + + // If null, no arena was found. + if (arena == null) { + sender.sendMessage("The arena '" + args[0] + "' does not exist."); + return false; + } + + sender.sendMessage("You've joined arena '" + arena.configName() + "'!"); + return true; + } + + @Override + public boolean executeFromConsole(MobArenaPlugin plugin, CommandSender sender, String... args) { + return false; + } +} diff --git a/src/com/garbagemule/MobArena/commands/user/LeaveCommand.java b/src/com/garbagemule/MobArena/commands/user/LeaveCommand.java new file mode 100644 index 0000000..5e015d8 --- /dev/null +++ b/src/com/garbagemule/MobArena/commands/user/LeaveCommand.java @@ -0,0 +1,29 @@ +package com.garbagemule.MobArena.commands.user; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import com.garbagemule.MobArena.commands.*; +import com.garbagemule.MobArena.*; + +public class LeaveCommand implements MACommand +{ + @Override + public String[] getNames() { + return new String[] { "leave" , "l" }; + } + + @Override + public String getPermission() { + return "mobarena.use.leave"; + } + + @Override + public boolean execute(MobArenaPlugin plugin, Player sender, String... args) { + return true; + } + + @Override + public boolean executeFromConsole(MobArenaPlugin plugin, CommandSender sender, String... args) { + return false; + } +} diff --git a/src/com/garbagemule/MobArena/commands/user/NotReadyCommand.java b/src/com/garbagemule/MobArena/commands/user/NotReadyCommand.java new file mode 100644 index 0000000..f08a272 --- /dev/null +++ b/src/com/garbagemule/MobArena/commands/user/NotReadyCommand.java @@ -0,0 +1,29 @@ +package com.garbagemule.MobArena.commands.user; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import com.garbagemule.MobArena.commands.*; +import com.garbagemule.MobArena.*; + +public class NotReadyCommand implements MACommand +{ + @Override + public String[] getNames() { + return new String[] { "notready" , "check" }; + } + + @Override + public String getPermission() { + return "mobarena.use.notready"; + } + + @Override + public boolean execute(MobArenaPlugin plugin, Player sender, String... args) { + return true; + } + + @Override + public boolean executeFromConsole(MobArenaPlugin plugin, CommandSender sender, String... args) { + return false; + } +} diff --git a/src/com/garbagemule/MobArena/commands/user/PlayerListCommand.java b/src/com/garbagemule/MobArena/commands/user/PlayerListCommand.java new file mode 100644 index 0000000..ac656c8 --- /dev/null +++ b/src/com/garbagemule/MobArena/commands/user/PlayerListCommand.java @@ -0,0 +1,29 @@ +package com.garbagemule.MobArena.commands.user; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import com.garbagemule.MobArena.commands.*; +import com.garbagemule.MobArena.*; + +public class PlayerListCommand implements MACommand +{ + @Override + public String[] getNames() { + return new String[] { "who" , "players" }; + } + + @Override + public String getPermission() { + return "mobarena.use.playerlist"; + } + + @Override + public boolean execute(MobArenaPlugin plugin, Player sender, String... args) { + return true; + } + + @Override + public boolean executeFromConsole(MobArenaPlugin plugin, CommandSender sender, String... args) { + return false; + } +} diff --git a/src/com/garbagemule/MobArena/leaderboards/Leaderboard.java b/src/com/garbagemule/MobArena/leaderboards/Leaderboard.java index 9a9068e..d5eacba 100644 --- a/src/com/garbagemule/MobArena/leaderboards/Leaderboard.java +++ b/src/com/garbagemule/MobArena/leaderboards/Leaderboard.java @@ -10,13 +10,13 @@ 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 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; +import com.garbagemule.MobArena.util.Config; public class Leaderboard { @@ -54,7 +54,7 @@ public class Leaderboard * @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) + public Leaderboard(MobArena plugin, Arena arena, Config config) { this(plugin, arena); @@ -64,7 +64,7 @@ public class Leaderboard if (coords != null) { // Grab the top left sign. - topLeft = ConfigUtils.parseLocation(arena.getWorld(), coords); + topLeft = Config.parseLocation(arena.getWorld(), coords); // If it is a sign, validate. if (topLeft.getBlock().getState() instanceof Sign) diff --git a/src/com/garbagemule/MobArena/util/Config.java b/src/com/garbagemule/MobArena/util/Config.java new file mode 100644 index 0000000..c1275c6 --- /dev/null +++ b/src/com/garbagemule/MobArena/util/Config.java @@ -0,0 +1,177 @@ +package com.garbagemule.MobArena.util; + +import java.io.File; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; + +public class Config +{ + private YamlConfiguration config; + private File configFile; + + public Config(File configFile) { + this.config = new YamlConfiguration(); + this.configFile = configFile; + + config.options().indent(4); + } + + public boolean load() { + try { + config.load(configFile); + return true; + } + catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public boolean save() { + try { + config.save(configFile); + return true; + } + catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public void setHeader(String header) { + config.options().header(header); + } + + + + /////////////////////////////////////////////////////////////////////////// + // // + // GETTERS // + // // + /////////////////////////////////////////////////////////////////////////// + + public Object getProperty(String path) { + return config.get(path); + } + + public boolean getBoolean(String path) { + return config.getBoolean(path); + } + + public boolean getBoolean(String path, boolean def) { + return config.getBoolean(path, def); + } + + public int getInt(String path) { + return config.getInt(path); + } + + public int getInt(String path, int def) { + return config.getInt(path, def); + } + + public String getString(String path) { + String result = config.getString(path); + return result != null ? result : null; + } + + public String getString(String path, String def) { + return config.getString(path, def); + } + + public Set getKeys(String path) { + if (config.get(path) == null) + return null; + + ConfigurationSection section = config.getConfigurationSection(path); + return section.getKeys(false); + } + + @SuppressWarnings("unchecked") + public List getStringList(String path, List def) { + if (config.get(path) == null) + return def != null ? def : new LinkedList(); + + List list = config.getStringList(path); + return (List) list; + } + + + + /////////////////////////////////////////////////////////////////////////// + // // + // MUTATORS // + // // + /////////////////////////////////////////////////////////////////////////// + + public void set(String path, Object value) { + config.set(path, value); + } + + public void setProperty(String path, Object value) { + this.set(path, value); + } + + public void remove(String path) { + this.set(path, null); + } + + public void removeProperty(String path) { + this.remove(path); + } + + + + /////////////////////////////////////////////////////////////////////////// + // // + // UTILITY METHODS // + // // + /////////////////////////////////////////////////////////////////////////// + + 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 = getInteger(parts[0]); + Integer y = getInteger(parts[1]); + Integer z = getInteger(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 getInteger(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/FileUtils.java b/src/com/garbagemule/MobArena/util/FileUtils.java index 94ae6aa..6205495 100644 --- a/src/com/garbagemule/MobArena/util/FileUtils.java +++ b/src/com/garbagemule/MobArena/util/FileUtils.java @@ -9,10 +9,9 @@ import java.net.URL; import java.net.URLClassLoader; import java.net.URLConnection; import java.util.HashSet; -import java.util.List; import java.util.Set; -import org.bukkit.util.config.Configuration; +//import org.bukkit.util.config.Configuration; import com.garbagemule.MobArena.MobArena; @@ -41,10 +40,10 @@ public class FileUtils * Download all necessary libraries. * @param config The MobArena config-file */ - public static void fetchLibs(Configuration config) + public static void fetchLibs(Config config) { // Get all arenas - List arenas = config.getKeys("arenas"); + Set arenas = config.getKeys("arenas"); if (arenas == null) return; // Add all the logging types diff --git a/src/com/garbagemule/MobArena/util/WaveUtils.java b/src/com/garbagemule/MobArena/util/WaveUtils.java index c0e3a99..d2fc686 100644 --- a/src/com/garbagemule/MobArena/util/WaveUtils.java +++ b/src/com/garbagemule/MobArena/util/WaveUtils.java @@ -4,12 +4,13 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.List; +import java.util.Set; import java.util.TreeSet; import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; -import org.bukkit.util.config.Configuration; +//import org.bukkit.util.config.Configuration; import com.garbagemule.MobArena.Arena; import com.garbagemule.MobArena.MAUtils; @@ -80,7 +81,7 @@ public class WaveUtils /** * Grab and process all the waves in the config-file for the arena. */ - public static TreeSet getWaves(Arena arena, Configuration config, WaveBranch branch) + public static TreeSet getWaves(Arena arena, Config config, WaveBranch branch) { // Determine the branch type of the wave, and grab the appropriate comparator String b = branch.toString().toLowerCase(); @@ -88,7 +89,7 @@ public class WaveUtils // Grab the waves from the config-file String path = "arenas." + arena.configName() + ".waves." + b; // waves.yml, change to either "waves." + b, or simply b - List waves = config.getKeys(path); + Set waves = config.getKeys(path); // If there are any waves, process them if (waves != null) @@ -122,7 +123,7 @@ public class WaveUtils * Get a single wave based on the config-file, the path, and branch * @return A Wave object if it is well defined, null otherwise. */ - private static Wave getWave(Arena arena, Configuration config, String path, String name, WaveBranch branch) + private static Wave getWave(Arena arena, Config config, String path, String name, WaveBranch branch) { // Grab the wave type, if null or not well defined, return null WaveType type = WaveType.fromString(config.getString(path + "type")); @@ -177,13 +178,13 @@ public class WaveUtils * the node 'wave'. * Any other requirements are type-specific, and thus we check if the * type is well-defined. - * @param config Config-file Configuration + * @param config Config-file Config * @param path The absolute path of the wave * @param branch The branch of the wave * @param type The wave type * @return true, only if the entire wave-node is well-defined. */ - private static boolean isWaveWellDefined(Configuration config, String path, WaveBranch branch, WaveType type) + private static boolean isWaveWellDefined(Config config, String path, WaveBranch branch, WaveType type) { // This boolean is used in the "leaf methods" boolean wellDefined = true; @@ -254,13 +255,13 @@ public class WaveUtils * Check if a wave type in the config-file is well-defined. * The method calls the appropriate sub-method to check if the type * is well-defined. - * @param config Config-file Configuration + * @param config Config-file Config * @param path The absolute path of the wave * @param type The wave type * @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, boolean wellDefined) + private static boolean isTypeWellDefined(Config config, String path, WaveType type, boolean wellDefined) { if (type == WaveType.DEFAULT) return isDefaultWaveWellDefined(config, path, wellDefined); @@ -278,12 +279,12 @@ public class WaveUtils * 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 config Config-file Config * @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) + private static boolean isDefaultWaveWellDefined(Config config, String path, boolean wellDefined) { // OPTIONAL: Wave growth String growth = config.getString(path + "growth"); @@ -299,12 +300,12 @@ public class WaveUtils /** * Check if a special wave is well-defined. * The special waves have no unique nodes. - * @param config Config-file Configuration + * @param config Config-file Config * @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) + private static boolean isSpecialWaveWellDefined(Config config, String path, boolean wellDefined) { return isNormalWaveWellDefined(config, path, wellDefined); } @@ -314,15 +315,15 @@ public class WaveUtils * There are no REQUIRED nodes for default or special wave types, besides * the ones for the branch they belong to. * The only OPTIONAL node is (currently) 'monsters' - * @param config Config-file Configuration + * @param config Config-file Config * @param path The absolute path of the wave * @param wellDefined Pass-through boolean for "leaf methods". * @return true, wellDefined is true. */ - private static boolean isNormalWaveWellDefined(Configuration config, String path, boolean wellDefined) + private static boolean isNormalWaveWellDefined(Config config, String path, boolean wellDefined) { // OPTIONAL: Monsters - List monsters = config.getKeys(path + "monsters"); + Set monsters = config.getKeys(path + "monsters"); if (monsters != null) { for (String monster : monsters) @@ -341,12 +342,12 @@ public class WaveUtils /** * Check if a swarm wave is well defined - * @param config Config-file Configuration + * @param config Config-file Config * @param path The absolute path of the wave * @param wellDefined Pass-through boolean for "leaf methods". * @return true, wellDefined is true. */ - private static boolean isSwarmWaveWellDefined(Configuration config, String path, boolean wellDefined) + private static boolean isSwarmWaveWellDefined(Config config, String path, boolean wellDefined) { // REQUIRED: Monster type String monster = config.getString(path + "monster"); @@ -374,12 +375,12 @@ public class WaveUtils /** * Check if a boss wave is well defined. - * @param config Config-file Configuration + * @param config Config-file Config * @param path The absolute path of the wave * @param wellDefined Pass-through boolean for "leaf methods". * @return true, wellDefined is true. */ - private static boolean isBossWaveWellDefined(Configuration config, String path, boolean wellDefined) + private static boolean isBossWaveWellDefined(Config config, String path, boolean wellDefined) { // REQUIRED: Monster type String monster = config.getString(path + "monster"); diff --git a/src/com/garbagemule/MobArena/util/classparsing/ClassIterationStrategy.java b/src/com/garbagemule/MobArena/util/classparsing/ClassIterationStrategy.java new file mode 100644 index 0000000..b0baded --- /dev/null +++ b/src/com/garbagemule/MobArena/util/classparsing/ClassIterationStrategy.java @@ -0,0 +1,15 @@ +package com.garbagemule.MobArena.util.classparsing; + +import java.util.Collection; + +public interface ClassIterationStrategy +{ + /** + * Given a package, e.g. com.garbagemule.MobArena.commands.user, the + * concrete strategy will return a collection of qualified class names + * either from a directory or a jar file. + * @param packagePath path from which to extract classes + * @return a list of qualified class names or null + */ + public Collection getClassesFromPackage(String packagePath); +} diff --git a/src/com/garbagemule/MobArena/util/classparsing/ClassParser.java b/src/com/garbagemule/MobArena/util/classparsing/ClassParser.java new file mode 100644 index 0000000..e194614 --- /dev/null +++ b/src/com/garbagemule/MobArena/util/classparsing/ClassParser.java @@ -0,0 +1,46 @@ +package com.garbagemule.MobArena.util.classparsing; + +import java.util.*; + +public class ClassParser +{ + private ClassIterationStrategy strategy; + + public ClassParser(ClassIterationStrategy strategy) { + this.strategy = strategy; + } + + /** + * Using an iteration strategy provided in the constructor, this method tries + * to iterate through all classes within a given "package". + * @param packagePath a package path, e.g. com.garbagemule.MobArena.commands.user + * @return a list of Class objects + */ + public Collection> getClasses(String packagePath) { + Collection> result = new LinkedList>(); + + for (String classname : strategy.getClassesFromPackage(packagePath)) { + Class c = makeClass(classname); + + if (c != null) { + result.add(c); + } + } + + return result; + } + + /** + * Get a class using its qualified (full package) name. + * @param qualifiedName qualified name of a class + * @return a Class object, or null if the class could not be made. + */ + private static Class makeClass(String qualifiedName) { + try { + return Class.forName(qualifiedName); + } + catch (Exception e) { + return null; + } + } +} diff --git a/src/com/garbagemule/MobArena/util/classparsing/DirClassIterationStrategy.java b/src/com/garbagemule/MobArena/util/classparsing/DirClassIterationStrategy.java new file mode 100644 index 0000000..177ac31 --- /dev/null +++ b/src/com/garbagemule/MobArena/util/classparsing/DirClassIterationStrategy.java @@ -0,0 +1,52 @@ +package com.garbagemule.MobArena.util.classparsing; + +import java.io.*; +import java.util.*; + +public class DirClassIterationStrategy implements ClassIterationStrategy +{ + private File baseDir; + + /** + * Dir iterator. The input file must be a directory, whose + * contents are iterated over upon calling the implemented + * method. This dir could be bin/ or build/. + * @param file a directory + * @throws Exception + */ + public DirClassIterationStrategy(File baseDir) throws Exception { + this.baseDir = baseDir; + } + + @Override + public Collection getClassesFromPackage(String packagePath) { + // The resulting list. + Collection result = new LinkedList(); + + // Convert to an actual path. + String path = packageToPath(packagePath); + + // Make a new dir from it. + File dir = new File(baseDir, path); + + for (File f : dir.listFiles()) { + String name = f.getName(); + String absolutePath = f.getAbsolutePath(); + + if (absolutePath.contains(path) && name.endsWith(".class")) { + result.add( packagePath + "." + stripExtension(name) ); + } + } + + return result; + } + + private String stripExtension(String file) { + int dot = file.lastIndexOf("."); + return file.substring(0, dot); + } + + private String packageToPath(String path) { + return path.replace(".", File.separator); + } +} diff --git a/src/com/garbagemule/MobArena/util/classparsing/JarClassIterationStrategy.java b/src/com/garbagemule/MobArena/util/classparsing/JarClassIterationStrategy.java new file mode 100644 index 0000000..f7713b9 --- /dev/null +++ b/src/com/garbagemule/MobArena/util/classparsing/JarClassIterationStrategy.java @@ -0,0 +1,62 @@ +package com.garbagemule.MobArena.util.classparsing; + +import java.io.*; +import java.util.*; +import java.util.jar.*; + +public class JarClassIterationStrategy implements ClassIterationStrategy +{ + private JarFile jarFile; + + /** + * Jar iterator. The input file is turned into a JarFile object, + * which is later used to extract a list of entries to iterate + * over. The implemented method filters through the entries and + * returns any matches. + * @param file a jar file + * @throws Exception + */ + public JarClassIterationStrategy(File file) throws Exception { + this.jarFile = new JarFile(file); + } + + @Override + public Collection getClassesFromPackage(String packagePath) { + // The resulting list. + Collection result = new LinkedList(); + + // Convert to an actual path. + String path = packageToPath(packagePath); + + // Grab the entries from the jar file. + Enumeration entries = jarFile.entries(); + + /* Iterate through all the entries in the jar file, and + * if a file starts with the package path and ends with + * .class, we have a match, in which case we strip the + * extension and convert to a package representation. */ + while (entries.hasMoreElements()) { + String entry = entries.nextElement().getName(); + + if (entry.startsWith(path) && entry.endsWith(".class")) { + result.add( pathToPackage( stripExtension(entry) ) ); + } + } + + // Return the resulting list. + return result; + } + + private String stripExtension(String file) { + int dot = file.lastIndexOf("."); + return file.substring(0, dot); + } + + private String packageToPath(String path) { + return path.replace(".", "/"); + } + + private String pathToPackage(String path) { + return path.replace("/", "."); + } +} diff --git a/src/com/garbagemule/MobArena/waves/BossWave.java b/src/com/garbagemule/MobArena/waves/BossWave.java index ae6b70b..b9421a6 100644 --- a/src/com/garbagemule/MobArena/waves/BossWave.java +++ b/src/com/garbagemule/MobArena/waves/BossWave.java @@ -12,11 +12,12 @@ import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.entity.CraftEntity; import org.bukkit.entity.Creature; import org.bukkit.entity.LivingEntity; -import org.bukkit.util.config.Configuration; +//import org.bukkit.util.config.Configuration; import com.garbagemule.MobArena.Arena; import com.garbagemule.MobArena.MAUtils; import com.garbagemule.MobArena.MAMessages.Msg; +import com.garbagemule.MobArena.util.Config; import com.garbagemule.MobArena.util.WaveUtils; public class BossWave extends AbstractWave @@ -30,20 +31,20 @@ public class BossWave extends AbstractWave private boolean lowHealthAnnounced = false, abilityAnnounce; // Recurrent - public BossWave(Arena arena, String name, int wave, int frequency, int priority, Configuration config, String path) + public BossWave(Arena arena, String name, int wave, int frequency, int priority, Config config, String path) { super(arena, name, wave, frequency, priority); load(config, path); } // Single - public BossWave(Arena arena, String name, int wave, Configuration config, String path) + public BossWave(Arena arena, String name, int wave, Config config, String path) { super(arena, name, wave); load(config, path); } - private void load(Configuration config, String path) + private void load(Config config, String path) { setType(WaveType.BOSS); abilityTask = -1; diff --git a/src/com/garbagemule/MobArena/waves/DefaultWave.java b/src/com/garbagemule/MobArena/waves/DefaultWave.java index c357d2e..55eceef 100644 --- a/src/com/garbagemule/MobArena/waves/DefaultWave.java +++ b/src/com/garbagemule/MobArena/waves/DefaultWave.java @@ -6,24 +6,25 @@ import java.util.Map; import java.util.Random; import org.bukkit.Location; -import org.bukkit.util.config.Configuration; +//import org.bukkit.util.config.Configuration; import com.garbagemule.MobArena.Arena; import com.garbagemule.MobArena.MAUtils; import com.garbagemule.MobArena.MAMessages.Msg; +import com.garbagemule.MobArena.util.Config; import com.garbagemule.MobArena.util.WaveUtils; public class DefaultWave extends NormalWave { // Recurrent - public DefaultWave(Arena arena, String name, int wave, int frequency, int priority, Configuration config, String path) + public DefaultWave(Arena arena, String name, int wave, int frequency, int priority, Config config, String path) { super(arena, name, wave, frequency, priority, config, path); load(config, path, WaveType.DEFAULT); } // Single - public DefaultWave(Arena arena, String name, int wave, Configuration config, String path) + public DefaultWave(Arena arena, String name, int wave, Config config, String path) { super(arena, name, wave, config, path); load(config, path, WaveType.DEFAULT); diff --git a/src/com/garbagemule/MobArena/waves/NormalWave.java b/src/com/garbagemule/MobArena/waves/NormalWave.java index 8f40c2a..88722d0 100644 --- a/src/com/garbagemule/MobArena/waves/NormalWave.java +++ b/src/com/garbagemule/MobArena/waves/NormalWave.java @@ -1,13 +1,14 @@ package com.garbagemule.MobArena.waves; -import java.util.List; import java.util.Map; +import java.util.Set; import java.util.TreeMap; -import org.bukkit.util.config.Configuration; +//import org.bukkit.util.config.Configuration; import com.garbagemule.MobArena.Arena; import com.garbagemule.MobArena.MAUtils; +import com.garbagemule.MobArena.util.Config; import com.garbagemule.MobArena.util.WaveUtils; public abstract class NormalWave extends AbstractWave @@ -16,13 +17,13 @@ public abstract class NormalWave extends AbstractWave private Map probabilities = new TreeMap(); // Recurrent - public NormalWave(Arena arena, String name, int wave, int frequency, int priority, Configuration config, String path) + public NormalWave(Arena arena, String name, int wave, int frequency, int priority, Config config, String path) { super(arena, name, wave, frequency, priority); } // Single - public NormalWave(Arena arena, String name, int wave, Configuration config, String path) + public NormalWave(Arena arena, String name, int wave, Config config, String path) { super(arena, name, wave); } @@ -34,7 +35,7 @@ public abstract class NormalWave extends AbstractWave * @param path The absolute path of the wave * @param type DEFAULT or SPECIAL */ - public void load(Configuration config, String path, WaveType type) + public void load(Config config, String path, WaveType type) { // Set type and (for DEFAULT) growth. setType(type); @@ -43,7 +44,7 @@ public abstract class NormalWave extends AbstractWave // Load monsters int prob; - List monsters = config.getKeys(path + "monsters"); + Set monsters = config.getKeys(path + "monsters"); if (monsters != null && !monsters.isEmpty()) { for (String m : config.getKeys(path + "monsters")) diff --git a/src/com/garbagemule/MobArena/waves/SpecialWave.java b/src/com/garbagemule/MobArena/waves/SpecialWave.java index dc47bc6..47efa31 100644 --- a/src/com/garbagemule/MobArena/waves/SpecialWave.java +++ b/src/com/garbagemule/MobArena/waves/SpecialWave.java @@ -6,24 +6,25 @@ import java.util.Map; import java.util.Random; import org.bukkit.Location; -import org.bukkit.util.config.Configuration; +//import org.bukkit.util.config.Configuration; import com.garbagemule.MobArena.Arena; import com.garbagemule.MobArena.MAUtils; import com.garbagemule.MobArena.MAMessages.Msg; +import com.garbagemule.MobArena.util.Config; import com.garbagemule.MobArena.util.WaveUtils; public class SpecialWave extends NormalWave { // Recurrent - public SpecialWave(Arena arena, String name, int wave, int frequency, int priority, Configuration config, String path) + public SpecialWave(Arena arena, String name, int wave, int frequency, int priority, Config config, String path) { super(arena, name, wave, frequency, priority, config, path); load(config, path, WaveType.SPECIAL); } // Single - public SpecialWave(Arena arena, String name, int wave, Configuration config, String path) + public SpecialWave(Arena arena, String name, int wave, Config config, String path) { super(arena, name, wave, config, path); load(config, path, WaveType.SPECIAL); diff --git a/src/com/garbagemule/MobArena/waves/SwarmWave.java b/src/com/garbagemule/MobArena/waves/SwarmWave.java index ed2ec1f..bf9e1f9 100644 --- a/src/com/garbagemule/MobArena/waves/SwarmWave.java +++ b/src/com/garbagemule/MobArena/waves/SwarmWave.java @@ -4,11 +4,12 @@ import java.util.List; import org.bukkit.Location; import org.bukkit.entity.LivingEntity; -import org.bukkit.util.config.Configuration; +//import org.bukkit.util.config.Configuration; import com.garbagemule.MobArena.Arena; import com.garbagemule.MobArena.MAUtils; import com.garbagemule.MobArena.MAMessages.Msg; +import com.garbagemule.MobArena.util.Config; import com.garbagemule.MobArena.util.WaveUtils; public class SwarmWave extends AbstractWave @@ -17,20 +18,20 @@ public class SwarmWave extends AbstractWave private SwarmAmount amount; // Recurrent - public SwarmWave(Arena arena, String name, int wave, int frequency, int priority, Configuration config, String path) + public SwarmWave(Arena arena, String name, int wave, int frequency, int priority, Config config, String path) { super(arena, name, wave, frequency, priority); load(config, path); } // Single - public SwarmWave(Arena arena, String name, int wave, Configuration config, String path) + public SwarmWave(Arena arena, String name, int wave, Config config, String path) { super(arena, name, wave); load(config, path); } - private void load(Configuration config, String path) + private void load(Config config, String path) { // Set the wave type setType(WaveType.SWARM);