diff --git a/MobArena.jar b/MobArena.jar index 94fd344..405fb89 100644 Binary files a/MobArena.jar and b/MobArena.jar differ diff --git a/src/com/garbagemule/MobArena/Arena.java b/src/com/garbagemule/MobArena/Arena.java index ba29169..e39566b 100644 --- a/src/com/garbagemule/MobArena/Arena.java +++ b/src/com/garbagemule/MobArena/Arena.java @@ -16,6 +16,7 @@ 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; @@ -74,18 +75,13 @@ public class Arena protected Map> classItems, classArmor; protected List entryFee; - // NEW IMPLEMENTATION - // - // // Player sets protected Set arenaPlayers, lobbyPlayers, readyPlayers, specPlayers; + // Wave stuff protected TreeSet singleWaves, singleWavesInstance; protected TreeSet recurrentWaves; protected BossWave bossWave; - // - // - // NEW IMPLEMENTATION // Arena sets/maps protected Set hasPaid, rewardedPlayers, notifyPlayers, randoms; @@ -93,8 +89,7 @@ public class Arena protected Set blocks; protected Set pets; protected Map petMap; - //protected List repairList; - protected LinkedList repairables; + protected LinkedList repairables, containers; // Spawn overriding protected int spawnMonsters; @@ -111,6 +106,8 @@ public class Arena protected MAListener eventListener; + protected PriorityBlockingQueue repairQueue; + /** * Primary constructor. Requires a name and a world. */ @@ -139,8 +136,8 @@ public class Arena petMap = new HashMap(); classMap = new HashMap(); randoms = new HashSet(); - //repairList = new LinkedList(); repairables = new LinkedList(); + containers = new LinkedList(); running = false; edit = false; @@ -150,6 +147,7 @@ public class Arena spawnMonsters = ((net.minecraft.server.World) ((CraftWorld) world).getHandle()).spawnMonsters; eventListener = new MAListener(this, plugin); + repairQueue = new PriorityBlockingQueue(100, new RepairableComparator()); } public boolean startArena() @@ -160,7 +158,8 @@ public class Arena if (!softRestore && forceRestore && !serializeRegion()) return false; - saveContainerContents(); + // Store all chest contents. + storeContainerContents(); // Populate arenaPlayers and clear the lobby. arenaPlayers.addAll(lobbyPlayers); @@ -178,7 +177,6 @@ public class Arena { p.teleport(arenaLoc); p.setHealth(20); - //rewardMap.put(p, new LinkedList()); } // Spawn pets. @@ -231,15 +229,13 @@ public class Arena cleanup(); // Restore region. - /* - if (softRestore) - for (int[] buffer : repairList) - world.getBlockAt(buffer[0], buffer[1], buffer[2]).setTypeIdAndData(buffer[3], (byte) buffer[4], false); - */ if (softRestore) restoreRegion(); else if (forceRestore) deserializeRegion(); + + // Restore chests + restoreContainerContents(); // Announce and clear sets. MAUtils.tellAll(this, Msg.ARENA_END.get(), true); @@ -490,6 +486,9 @@ public class Arena { public void run() { + if (!p.isOnline()) + return; + if (!emptyInvJoin) MAUtils.restoreInventory(p); @@ -514,25 +513,34 @@ public class Arena healthMap.put(p, p.getHealth()); } - public void saveContainerContents() + public void storeContainerContents() { Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { public void run() { - long start = System.nanoTime(); - LinkedList list = new LinkedList(); for (int x = p1.getBlockX(); x <= p2.getBlockX(); x++) for (int y = p1.getBlockY(); y <= p2.getBlockY(); y++) for (int z = p1.getBlockZ(); z <= p2.getBlockZ(); z++) { - BlockState bs = world.getBlockAt(x,y,z).getState(); - if (bs instanceof ContainerBlock) - list.add(new RepairableContainer(bs)); + BlockState state = world.getBlockAt(x,y,z).getState(); + if (state instanceof ContainerBlock) + containers.add(new RepairableContainer(state, false)); } - list.clear(); - System.out.println("Iteration took: " + (System.nanoTime() - start) + " ns"); + } + }); + } + + public void restoreContainerContents() + { + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, + new Runnable() + { + public void run() + { + for (Repairable r : containers) + r.repair(); } }); } @@ -561,7 +569,6 @@ public class Arena } private void clearPlayer(Player p) - //private void resetPlayer(Player p) { if (healthMap.containsKey(p)) p.setHealth(healthMap.remove(p)); @@ -587,7 +594,6 @@ public class Arena { locations.remove(p); plugin.getAM().arenaMap.remove(p); - //resetPlayer(p); clearPlayer(p); } @@ -608,6 +614,22 @@ public class Arena log.players.get(p).lastWave = spawnThread.getWave() - 1; } + public void repairBlocks() + { + //long start = System.nanoTime(); + //System.out.println(start + " - Attempting to repair things..."); + while (!repairQueue.isEmpty()) + { + repairQueue.poll().repair(); + } + //System.out.println(start + " - Repair finished!"); + } + + public void queueRepairable(Repairable r) + { + repairQueue.add(r); + } + /*//////////////////////////////////////////////////////////////////// @@ -789,18 +811,6 @@ public class Arena // NEW WAVES singleWaves = WaveUtils.getWaves(this, config, WaveBranch.SINGLE); recurrentWaves = WaveUtils.getWaves(this, config, WaveBranch.RECURRENT); - - /* - System.out.println(); - System.out.println("ARENA: " + configName); - System.out.println("- Single waves"); - for (Wave w : singleWaves) - System.out.println(" - " + w); - System.out.println("- Reccurent waves"); - for (Wave w : recurrentWaves) - System.out.println(" - " + w); - System.out.println(); - */ classes = plugin.getAM().classes; classItems = plugin.getAM().classItems; @@ -1048,7 +1058,7 @@ public class Arena if (result != null) return result; - return spawnpoints.values().iterator().next(); + return WaveUtils.getValidSpawnpoints(this, arenaPlayers).iterator().next(); } public int getPlayerCount() diff --git a/src/com/garbagemule/MobArena/ArenaListener.java b/src/com/garbagemule/MobArena/ArenaListener.java index 877ae02..e55211c 100644 --- a/src/com/garbagemule/MobArena/ArenaListener.java +++ b/src/com/garbagemule/MobArena/ArenaListener.java @@ -37,23 +37,4 @@ public interface ArenaListener public void onPlayerKick(PlayerKickEvent event); public void onPlayerTeleport(PlayerTeleportEvent event); public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event); - - /* - public abstract void onBlockBreak(BlockBreakEvent event); - public abstract void onBlockPlace(BlockPlaceEvent event); - public abstract void onCreatureSpawn(CreatureSpawnEvent event); - public abstract void onEntityExplode(EntityExplodeEvent event); - public abstract void onEntityCombust(EntityCombustEvent event); - public abstract void onEntityTarget(EntityTargetEvent event); - public abstract void onEntityRegainHealth(EntityRegainHealthEvent event); - public abstract void onEntityDeath(EntityDeathEvent event); - public abstract void onEntityDamage(EntityDamageEvent event); - public abstract void onPlayerDropItem(PlayerDropItemEvent event); - public abstract void onPlayerBucketEmpty(PlayerBucketEmptyEvent event); - public abstract void onPlayerInteract(PlayerInteractEvent event); - public abstract void onPlayerQuit(PlayerQuitEvent event); - public abstract void onPlayerKick(PlayerKickEvent event); - public abstract void onPlayerTeleport(PlayerTeleportEvent event); - public abstract void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event); - */ } diff --git a/src/com/garbagemule/MobArena/MACommands.java b/src/com/garbagemule/MobArena/MACommands.java index 488d2a4..602dbaa 100644 --- a/src/com/garbagemule/MobArena/MACommands.java +++ b/src/com/garbagemule/MobArena/MACommands.java @@ -1043,7 +1043,7 @@ public class MACommands implements CommandExecutor } MAUtils.setArenaCoord(plugin.getConfig(), am.selectedArena, "spawnpoints." + arg1, p.getLocation()); - MAUtils.tellPlayer(sender, "Sspawnpoint " + arg1 + " added for arena \"" + am.selectedArena.configName() + "\""); + MAUtils.tellPlayer(sender, "Spawnpoint " + arg1 + " added for arena \"" + am.selectedArena.configName() + "\""); return true; } diff --git a/src/com/garbagemule/MobArena/MAListener.java b/src/com/garbagemule/MobArena/MAListener.java index c2a44d2..eeba802 100644 --- a/src/com/garbagemule/MobArena/MAListener.java +++ b/src/com/garbagemule/MobArena/MAListener.java @@ -1,13 +1,10 @@ package com.garbagemule.MobArena; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.block.ContainerBlock; import org.bukkit.block.Sign; @@ -42,13 +39,12 @@ import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.material.Attachable; +import org.bukkit.material.Bed; +import org.bukkit.material.Door; +import org.bukkit.material.Redstone; import com.garbagemule.MobArena.MAMessages.Msg; -import com.garbagemule.MobArena.repairable.Repairable; -import com.garbagemule.MobArena.repairable.RepairableBlock; -import com.garbagemule.MobArena.repairable.RepairableComparator; -import com.garbagemule.MobArena.repairable.RepairableContainer; -import com.garbagemule.MobArena.repairable.RepairableSign; +import com.garbagemule.MobArena.repairable.*; public class MAListener implements ArenaListener { @@ -66,14 +62,6 @@ public class MAListener implements ArenaListener if (!arena.inRegion(event.getBlock().getLocation()) || arena.edit || (!arena.protect && arena.running)) return; - BlockState statez = event.getBlock().getState(); - - if (statez.getData() instanceof Attachable) - { - System.out.println(statez.getData()); - event.setCancelled(true); - } - Block b = event.getBlock(); if (arena.blocks.remove(b) || b.getType() == Material.TNT) return; @@ -81,14 +69,19 @@ public class MAListener implements ArenaListener if (arena.softRestore && arena.running) { BlockState state = b.getState(); - + + Repairable r = null; if (state instanceof ContainerBlock) - arena.repairables.add(new RepairableContainer(state)); + r = new RepairableContainer(state); else if (state instanceof Sign) - arena.repairables.add(new RepairableSign(state)); + r = new RepairableSign(state); + else if (state.getData() instanceof Attachable) + r = new RepairableAttachable(state); else - arena.repairables.add(new RepairableBlock(state)); - + r = new RepairableBlock(state); + + arena.repairables.add(r); + if (!arena.softRestoreDrops) b.setTypeId(0); @@ -154,32 +147,41 @@ public class MAListener implements ArenaListener // Uncancel, just in case. event.setCancelled(false); - // Initialize the repair list. - final List toRepair = new LinkedList(); - // Handle all the blocks in the block list. for (Block b : event.blockList()) { BlockState state = b.getState(); + if (state.getData() instanceof Door && ((Door) state.getData()).isTopHalf()) + state = b.getRelative(BlockFace.DOWN).getState(); + else if (state.getData() instanceof Bed && ((Bed) state.getData()).isHeadOfBed()) + state = b.getRelative(((Bed) state.getData()).getFacing().getOppositeFace()).getState(); + // Create a Repairable from the block. Repairable r = null; if (state instanceof ContainerBlock) r = new RepairableContainer(state); else if (state instanceof Sign) r = new RepairableSign(state); + else if (state.getData() instanceof Bed) + r = new RepairableBed(state); + else if (state.getData() instanceof Door) + r = new RepairableDoor(state); + else if (state.getData() instanceof Attachable || state.getData() instanceof Redstone) + r = new RepairableAttachable(state); else r = new RepairableBlock(state); + // Cakes and liquids should just get removed. If player-placed block, drop as item. Material mat = state.getType(); - if (mat == Material.WOODEN_DOOR || mat == Material.IRON_DOOR_BLOCK || mat == Material.FIRE || mat == Material.CAKE_BLOCK || mat == Material.WATER || mat == Material.LAVA) + if (mat == Material.CAKE_BLOCK || mat == Material.WATER || mat == Material.LAVA) arena.blocks.remove(b); else if (arena.blocks.remove(b)) arena.world.dropItemNaturally(b.getLocation(), new ItemStack(state.getTypeId(), 1)); else if (arena.softRestore) arena.repairables.add(r); else - toRepair.add(r); + arena.queueRepairable(r); } // If the arena isn't protected, or soft-restore is on, return. @@ -192,101 +194,10 @@ public class MAListener implements ArenaListener { public void run() { - Collections.sort(toRepair, new RepairableComparator()); - - for (Repairable r : toRepair) - r.repair(); + arena.repairBlocks(); } }, arena.repairDelay); } - - /* - public void onEntityExplodez(EntityExplodeEvent event) - { - if (!arena.monsters.contains(event.getEntity()) && !arena.inRegionRadius(event.getLocation(), 10)) - return; - - event.setYield(0); - arena.monsters.remove(event.getEntity()); - - // If the arena isn't running - if (!arena.running || arena.repairDelay == 0) - { - event.setCancelled(true); - return; - } - - // If there is a sign in the blocklist, cancel - for (Block b : event.blockList()) - { - if (!(b.getType() == Material.SIGN_POST || b.getType() == Material.WALL_SIGN)) - continue; - - event.setCancelled(true); - return; - } - - // Uncancel, just in case. - event.setCancelled(false); - - int[] buffer; - final HashMap blockMap = new HashMap(); - for (Block b : event.blockList()) - { - Material mat = b.getType(); - - if (mat == Material.LAVA) b.setType(Material.STATIONARY_LAVA); - else if (mat == Material.WATER) b.setType(Material.STATIONARY_WATER); - - if (mat == Material.WOODEN_DOOR || mat == Material.IRON_DOOR_BLOCK || mat == Material.FIRE || mat == Material.CAKE_BLOCK || mat == Material.WATER || mat == Material.LAVA) - { - arena.blocks.remove(b); - } - else if (arena.blocks.remove(b)) - { - arena.world.dropItemNaturally(b.getLocation(), new ItemStack(b.getTypeId(), 1)); - } - else if (arena.softRestore) - { - buffer = new int[5]; - buffer[0] = b.getX(); - buffer[1] = b.getY(); - buffer[2] = b.getZ(); - buffer[3] = b.getTypeId(); - buffer[4] = (int) b.getData(); - arena.repairList.add(buffer); - blockMap.put(b, b.getTypeId() + (b.getData() * 1000)); - } - else - { - blockMap.put(b, b.getTypeId() + (b.getData() * 1000)); - } - } - - if (!arena.protect || arena.softRestore) - return; - - Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, - new Runnable() - { - public void run() - { - long start = System.nanoTime(); - for (Map.Entry entry : blockMap.entrySet()) - { - Block b = entry.getKey(); - int type = entry.getValue(); - - b.getLocation().getBlock().setTypeId(type % 1000); - - if (type > 1000) - b.getLocation().getBlock().setData((byte) (type / 1000)); - } - System.out.println("Repair took: " + (System.nanoTime() - start) + " ns"); - } - }, arena.repairDelay); - } - */ public void onEntityDeath(EntityDeathEvent event) { @@ -607,7 +518,6 @@ public class MAListener implements ArenaListener if (!arena.enabled || (!arena.arenaPlayers.contains(p) && !arena.lobbyPlayers.contains(p))) return; - plugin.getAM().arenaMap.remove(p); arena.playerLeave(p); } @@ -617,7 +527,6 @@ public class MAListener implements ArenaListener if (!arena.enabled || (!arena.arenaPlayers.contains(p) && !arena.lobbyPlayers.contains(p))) return; - plugin.getAM().arenaMap.remove(p); arena.playerLeave(p); } diff --git a/src/com/garbagemule/MobArena/MAMessages.java b/src/com/garbagemule/MobArena/MAMessages.java index 03caf4a..c3a57f1 100644 --- a/src/com/garbagemule/MobArena/MAMessages.java +++ b/src/com/garbagemule/MobArena/MAMessages.java @@ -29,6 +29,7 @@ public class MAMessages JOIN_EMPTY_INV("You must empty your inventory to join the arena."), JOIN_PLAYER_LIMIT_REACHED("The player limit of this arena has been reached."), JOIN_STORE_INV_FAIL("Failed to store inventory. Try again."), + JOIN_EXISTING_INV_RESTORED("Your old inventory items have been restored."), JOIN_PLAYER_JOINED("You joined the arena. Have fun!"), LEAVE_NOT_PLAYING("You are not in the arena."), LEAVE_PLAYER_LEFT("You left the arena. Thanks for playing!"), diff --git a/src/com/garbagemule/MobArena/MAUtils.java b/src/com/garbagemule/MobArena/MAUtils.java index 1927013..73b8706 100644 --- a/src/com/garbagemule/MobArena/MAUtils.java +++ b/src/com/garbagemule/MobArena/MAUtils.java @@ -336,19 +336,21 @@ public class MAUtils public static boolean storeInventory(Player p) { - // Grab the contents. - ItemStack[] armor = p.getInventory().getArmorContents(); - ItemStack[] items = p.getInventory().getContents(); - + // Set up the files and paths String invPath = "plugins" + sep + "MobArena" + sep + "inventories"; new File(invPath).mkdir(); File backupFile = new File(invPath + sep + p.getName() + ".inv"); + // If a backup file already exists, restore the inventory first + if (backupFile.exists() && !restoreInventory(p)) + return false; + + // Grab the inventory contents. + ItemStack[] armor = p.getInventory().getArmorContents(); + ItemStack[] items = p.getInventory().getContents(); + try { - if (backupFile.exists() && !restoreInventory(p)) - return false; - backupFile.createNewFile(); MAInventoryItem[] inv = new MAInventoryItem[armor.length + items.length]; diff --git a/src/com/garbagemule/MobArena/MobArena.java b/src/com/garbagemule/MobArena/MobArena.java index f68b7b1..dacad15 100644 --- a/src/com/garbagemule/MobArena/MobArena.java +++ b/src/com/garbagemule/MobArena/MobArena.java @@ -1,7 +1,6 @@ package com.garbagemule.MobArena; import java.io.File; -import java.util.List; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -41,7 +40,6 @@ public class MobArena extends JavaPlugin // Global variables public static PluginDescriptionFile desc; public static File dir, arenaDir; - public static List permissionOps; public static final double MIN_PLAYER_DISTANCE = 256.0; public static final int ECONOMY_MONEY_ID = -29; @@ -85,13 +83,6 @@ public class MobArena extends JavaPlugin arena.forceEnd(); am.arenaMap.clear(); - // Permissions & Economy - if (Methods != null && Methods.hasMethod()) - { - Methods = null; - info("Payment method was disabled. No longer accepting payments."); - } - info("disabled."); } @@ -132,7 +123,6 @@ public class MobArena extends JavaPlugin pm.registerEvent(Event.Type.ENTITY_DEATH, entityListener, Priority.Lowest, this); // Lowest because of Tombstone pm.registerEvent(Event.Type.ENTITY_REGAIN_HEALTH, entityListener, Priority.Normal, this); pm.registerEvent(Event.Type.ENTITY_EXPLODE, entityListener, Priority.Highest, this); - pm.registerEvent(Event.Type.EXPLOSION_PRIME, entityListener, Priority.Normal, this); pm.registerEvent(Event.Type.ENTITY_COMBUST, entityListener, Priority.Normal, this); pm.registerEvent(Event.Type.ENTITY_TARGET, entityListener, Priority.Normal, this); pm.registerEvent(Event.Type.CREATURE_SPAWN, entityListener, Priority.Highest, this); @@ -142,22 +132,16 @@ public class MobArena extends JavaPlugin // Permissions stuff public boolean has(Player p, String s) { - return hasSuperPerms(p, s) || hasNijikoPerms(p, s) || hasOpPerms(p, s); - } - - public boolean hasSuperPerms(Player p, String s) - { - return p.hasPermission(s); - } - - public boolean hasNijikoPerms(Player p, String s) - { - return permissionHandler != null && permissionHandler.has(p, s); - } - - public boolean hasOpPerms (Player p, String node) - { - return permissionOps == null || permissionOps.contains(node) == false || p.isOp(); + // First check for NijikoPerms + if (permissionHandler != null) + return permissionHandler.has(p, s); + + // If the permission is set, check if player has permission + if (p.isPermissionSet(s)) + return p.hasPermission(s); + + // Otherwise, only allow commands that aren't admin/setup commands. + return !s.matches("^.*\\.setup\\..*$") && !s.matches("^.*\\.admin\\..*$"); } // Console printing diff --git a/src/com/garbagemule/MobArena/repairable/Repairable.java b/src/com/garbagemule/MobArena/repairable/Repairable.java index 3af3be1..067f08c 100644 --- a/src/com/garbagemule/MobArena/repairable/Repairable.java +++ b/src/com/garbagemule/MobArena/repairable/Repairable.java @@ -11,10 +11,12 @@ public interface Repairable// extends Serializable public void repair(); public BlockState getState(); - public World getWorld(); + public Material getType(); public int getId(); public byte getData(); + + public World getWorld(); public int getX(); public int getY(); public int getZ(); diff --git a/src/com/garbagemule/MobArena/repairable/RepairableAttachable.java b/src/com/garbagemule/MobArena/repairable/RepairableAttachable.java new file mode 100644 index 0000000..678b49f --- /dev/null +++ b/src/com/garbagemule/MobArena/repairable/RepairableAttachable.java @@ -0,0 +1,35 @@ +package com.garbagemule.MobArena.repairable; + +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.material.Attachable; + +public class RepairableAttachable extends RepairableBlock +{ + private int x, y, z; + + public RepairableAttachable(BlockState state) + { + super(state); + + BlockState attached; + if (state.getData() instanceof Attachable) + attached = state.getBlock().getRelative(((Attachable) state.getData()).getAttachedFace()).getState(); + else + attached = state.getBlock().getRelative(BlockFace.DOWN).getState(); + + x = attached.getX(); + y = attached.getY(); + z = attached.getZ(); + } + + public void repair() + { + Block b = getWorld().getBlockAt(x,y,z); + if (b.getTypeId() == 0) + b.setTypeId(1); + + super.repair(); + } +} diff --git a/src/com/garbagemule/MobArena/repairable/RepairableBed.java b/src/com/garbagemule/MobArena/repairable/RepairableBed.java new file mode 100644 index 0000000..db1a642 --- /dev/null +++ b/src/com/garbagemule/MobArena/repairable/RepairableBed.java @@ -0,0 +1,24 @@ +package com.garbagemule.MobArena.repairable; + +import org.bukkit.block.BlockState; +import org.bukkit.material.Bed; + +public class RepairableBed extends RepairableBlock +{ + private BlockState other; + + public RepairableBed(BlockState state) + { + super(state); + other = state.getBlock().getRelative(((Bed) state.getData()).getFacing()).getState(); + } + + public void repair() + { + if (getWorld().getBlockAt(getX(), getY(), getZ()).getState().getData() instanceof Bed) + return; + + super.repair(); + other.getBlock().setTypeIdAndData(getId(), (byte) (getData() + 8), false); + } +} diff --git a/src/com/garbagemule/MobArena/repairable/RepairableBlock.java b/src/com/garbagemule/MobArena/repairable/RepairableBlock.java index c7ef73b..83a3de9 100644 --- a/src/com/garbagemule/MobArena/repairable/RepairableBlock.java +++ b/src/com/garbagemule/MobArena/repairable/RepairableBlock.java @@ -32,7 +32,7 @@ public class RepairableBlock implements Repairable */ public void repair() { - getWorld().getBlockAt(x,y,z).setTypeIdAndData(id, data, false); + world.getBlockAt(x,y,z).setTypeIdAndData(id, data, false); } public BlockState getState() @@ -45,68 +45,70 @@ public class RepairableBlock implements Repairable return world; } - public void setWorld(World world) - { - this.world = world; - } - public Material getType() { return type; } - public void setType(Material type) - { - this.type = type; - } - public int getId() { return id; } - public void setId(int id) - { - this.id = id; - } - public byte getData() { return data; } - public void setData(byte data) - { - this.data = data; - } - public int getX() { return x; } - public void setX(int x) - { - this.x = x; - } - public int getY() { return y; } - public void setY(int y) - { - this.y = y; - } - public int getZ() { return z; } + /* + public void setWorld(World world) + { + this.world = world; + } + + public void setType(Material type) + { + this.type = type; + } + + public void setId(int id) + { + this.id = id; + } + + public void setData(byte data) + { + this.data = data; + } + + public void setX(int x) + { + this.x = x; + } + + public void setY(int y) + { + this.y = y; + } + public void setZ(int z) { this.z = z; } + */ } diff --git a/src/com/garbagemule/MobArena/repairable/RepairableComparator.java b/src/com/garbagemule/MobArena/repairable/RepairableComparator.java index 0a1ed94..56db9a8 100644 --- a/src/com/garbagemule/MobArena/repairable/RepairableComparator.java +++ b/src/com/garbagemule/MobArena/repairable/RepairableComparator.java @@ -2,7 +2,9 @@ package com.garbagemule.MobArena.repairable; import java.util.Comparator; +import org.bukkit.Material; import org.bukkit.material.Attachable; +import org.bukkit.material.Bed; import org.bukkit.material.Door; import org.bukkit.material.MaterialData; import org.bukkit.material.Redstone; @@ -25,7 +27,9 @@ public class RepairableComparator implements Comparator private boolean restoreLast(Repairable r) { + Material t = r.getType(); MaterialData m = r.getState().getData(); - return (m instanceof Attachable || m instanceof Redstone || m instanceof Door); + + return (m instanceof Attachable || m instanceof Redstone || m instanceof Door || m instanceof Bed || t == Material.STATIONARY_LAVA || t == Material.STATIONARY_WATER || t == Material.FIRE); } } diff --git a/src/com/garbagemule/MobArena/repairable/RepairableContainer.java b/src/com/garbagemule/MobArena/repairable/RepairableContainer.java index 74b0c8a..958fb25 100644 --- a/src/com/garbagemule/MobArena/repairable/RepairableContainer.java +++ b/src/com/garbagemule/MobArena/repairable/RepairableContainer.java @@ -9,13 +9,19 @@ public class RepairableContainer extends RepairableBlock { private ItemStack[] contents; - public RepairableContainer(BlockState state) + public RepairableContainer(BlockState state, boolean clear) { super(state); Inventory inv = ((ContainerBlock) state).getInventory(); - contents = inv.getContents(); - inv.clear(); + contents = inv.getContents().clone(); + + if (clear) inv.clear(); + } + + public RepairableContainer(BlockState state) + { + this(state, true); } /** diff --git a/src/com/garbagemule/MobArena/repairable/RepairableDoor.java b/src/com/garbagemule/MobArena/repairable/RepairableDoor.java new file mode 100644 index 0000000..c6fe66e --- /dev/null +++ b/src/com/garbagemule/MobArena/repairable/RepairableDoor.java @@ -0,0 +1,36 @@ +package com.garbagemule.MobArena.repairable; + +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.material.Door; + +public class RepairableDoor extends RepairableAttachable//RepairableBlock +{ + private BlockState other; + private int x, y, z; + + public RepairableDoor(BlockState state) + { + super(state); + other = state.getBlock().getRelative(BlockFace.UP).getState(); + + BlockState attached = state.getBlock().getRelative(BlockFace.DOWN).getState(); + x = attached.getX(); + y = attached.getY(); + z = attached.getZ(); + } + + public void repair() + { + if (getWorld().getBlockAt(getX(), getY(), getZ()).getState().getData() instanceof Door) + return; + + Block b = getWorld().getBlockAt(x,y,z); + if (b.getTypeId() == 0) + b.setTypeId(1); + + super.repair(); + other.getBlock().setTypeIdAndData(getId(), (byte) (getData() + 8), false); + } +} diff --git a/src/com/garbagemule/MobArena/repairable/RepairableSign.java b/src/com/garbagemule/MobArena/repairable/RepairableSign.java index 7081500..87ef956 100644 --- a/src/com/garbagemule/MobArena/repairable/RepairableSign.java +++ b/src/com/garbagemule/MobArena/repairable/RepairableSign.java @@ -3,7 +3,7 @@ package com.garbagemule.MobArena.repairable; import org.bukkit.block.BlockState; import org.bukkit.block.Sign; -public class RepairableSign extends RepairableBlock +public class RepairableSign extends RepairableAttachable { private String[] lines = new String[4]; diff --git a/src/com/garbagemule/MobArena/util/FileUtils.java b/src/com/garbagemule/MobArena/util/FileUtils.java index 30a4f03..2fbfa2d 100644 --- a/src/com/garbagemule/MobArena/util/FileUtils.java +++ b/src/com/garbagemule/MobArena/util/FileUtils.java @@ -4,7 +4,9 @@ import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; +import java.lang.reflect.Method; import java.net.URL; +import java.net.URLClassLoader; import java.net.URLConnection; import java.util.HashSet; import java.util.List; @@ -16,23 +18,158 @@ import com.garbagemule.MobArena.MobArena; public class FileUtils { - public static enum Libs + public static enum Library { - xml("jdom.jar", "http://mirrors.ibiblio.org/pub/mirrors/maven2/org/jdom/jdom/1.1/jdom-1.1.jar"); + XML("jdom.jar", "http://mirrors.ibiblio.org/pub/mirrors/maven2/org/jdom/jdom/1.1/jdom-1.1.jar", "http://garbagemule.binhoster.com/Minecraft/MobArena/jdom-1.1.jar");//"org.jdom.Content"); - public String url, filename; - private Libs(String filename, String url) + public String filename, url, backup; + + private Library(String filename, String url, String backup) { this.filename = filename; this.url = url; + this.backup = backup; + } + + public static Library fromString(String string) + { + return WaveUtils.getEnumFromString(Library.class, string); + } + } + + /** + * Download all necessary libraries. + * @param config The MobArena config-file + */ + public static void fetchLibs(Configuration config) + { + // Get all arenas + List arenas = config.getKeys("arenas"); + if (arenas == null) return; + + // Add all the logging types + Set libs = new HashSet(); + for (String a : arenas) + { + String type = config.getString("arenas." + a + ".settings.logging", "").toLowerCase(); + + Library lib = Library.fromString(type.toUpperCase()); + if (lib != null) + libs.add(lib); } - public static Libs getLib(String filename) + // Download all libraries + for (Library lib : libs) + if (!libraryExists(lib)) + fetchLib(lib); + } + + /** + * Download a given library. + * @param lib The Library to download + */ + private static synchronized void fetchLib(Library lib) + { + MobArena.info("Downloading library '" + lib.filename + "' for log-method '" + lib.name().toLowerCase() + "'..."); + + URLConnection con = null; + InputStream in = null; + OutputStream out = null; + + // Open a connection + try { - for (Libs l : Libs.values()) - if (l.filename.equals(filename)) - return l; - return null; + con = new URL(lib.url).openConnection(); + con.setConnectTimeout(2000); + con.setUseCaches(true); + } + catch (Exception e) + { + if (lib.backup == null) + { + e.printStackTrace(); + System.out.println("Connection issues"); + return; + } + + try + { + con = new URL(lib.backup).openConnection(); + con.setConnectTimeout(2000); + con.setUseCaches(true); + } + catch (Exception e2) + { + e2.printStackTrace(); + System.out.println("Connection issues"); + return; + } + } + + try + { + File libdir = new File(MobArena.dir, "lib"); + libdir.mkdir(); + File file = new File(libdir, lib.filename); + + long startTime = System.currentTimeMillis(); + + // Set up the streams + in = con.getInputStream(); + out = new FileOutputStream(file); + if (in == null || out == null) return; + + byte[] buffer = new byte[65536]; + int length = 0; + + // Write the library to disk + while ((length = in.read(buffer)) > 0) + out.write(buffer, 0, length); + + // Announce successful download + MobArena.info(lib.filename + " downloaded in " + ((System.currentTimeMillis()-startTime)/1000.0) + " seconds."); + + addLibraryToClassLoader(file); + } + catch (Exception e) + { + e.printStackTrace(); + MobArena.warning("Couldn't download library: " + lib.filename); + } + finally + { + try + { + if (in != null) in.close(); + if (out != null) out.close(); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + } + + private static boolean libraryExists(Library lib) + { + return new File(MobArena.dir + File.separator + "lib", lib.filename).exists(); + } + + private static void addLibraryToClassLoader(File file) + { + try + { + // Grab the class loader and its addURL method + URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader(); + Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{ URL.class }); + addURL.setAccessible(true); + + // Add the library + addURL.invoke(cl, new Object[]{file.toURI().toURL()}); + } + catch (Exception e) + { + e.printStackTrace(); } } @@ -76,136 +213,4 @@ public class FileUtils MobArena.warning("Problem creating file '" + filename + "'!"); } } - - /** - * Download all necessary libraries. - * @param config The MobArena config-file - */ - public static void fetchLibs(Configuration config) - { - // Get all arenas - List arenas = config.getKeys("arenas"); - if (arenas == null) return; - - // Add all the logging types - Set libs = new HashSet(); - for (String a : arenas) - { - String type = config.getString("arenas." + a + ".settings.logging", "").toLowerCase(); - if (type.equals("xml")) - libs.add(type); - } - - // Download all libraries - for (String lib : libs) - { - if (download(Libs.valueOf(lib))) - continue; - - // If a library couldn't be downloaded, default to false. - for (String a : arenas) - { - if (!config.getString("arenas." + a + ".settings.logging", "").equalsIgnoreCase(lib)) - continue; - - MobArena.warning("Unrecognized format for arena '" + a + "': " + lib + ". Logging disabled."); - config.setProperty("arenas." + a + ".logging", "false"); - } - } - } - - private static synchronized boolean download(Libs lib) - { - if (lib == null) return false; - - InputStream in = null; - OutputStream out = null; - - try - { - URLConnection con = new URL(lib.url).openConnection(); - con.setUseCaches(false); - - // Library folder: plugin/MobArena/lib - File libdir = new File(MobArena.dir, "lib"); - libdir.mkdir(); - - // Create the file if it doesn't exist, if it does, return - File file = new File(libdir, lib.filename); - if (file.exists()) return true; - - long startTime = System.currentTimeMillis(); - MobArena.info("Downloading library: " + lib.filename + "..."); - - // Set up the streams - in = con.getInputStream(); - out = new FileOutputStream(file); - if (in == null || out == null) return false; - - byte[] buffer = new byte[65536]; - int length = 0; - - // Write the library to disk - while ((length = in.read(buffer)) > 0) - out.write(buffer, 0, length); - - MobArena.info(lib.filename + " downloaded in " + ((System.currentTimeMillis()-startTime)/1000.0) + " seconds."); - } - catch (Exception e) - { - e.printStackTrace(); - MobArena.warning("Couldn't download library: " + lib.filename); - return false; - } - finally - { - try - { - if (in != null) in.close(); - if (out != null) out.close(); - } - catch (Exception e) { e.printStackTrace(); } - } - return true; - } - - public static File getMostRecent(String folder) - { - return getMostRecent(new File(folder)); - } - - public static File getMostRecent(File dir) - { - if (!dir.exists()) dir.mkdir(); - if (!dir.isDirectory()) return null; - - long mostRecent = 0; - File result = null; - - for (File file : dir.listFiles()) - { - if (file.isDirectory() || file.lastModified() > mostRecent) - continue; - - result = file; - mostRecent = file.lastModified(); - } - - return result; - } - - public static Configuration parseXML(File file) - { - return null; - } - - public static Configuration parseCSV(File file) - { - return null; - } - - public static Configuration parsePlainText(File file) - { - return null; - } } diff --git a/src/com/garbagemule/MobArena/util/WaveUtils.java b/src/com/garbagemule/MobArena/util/WaveUtils.java index eae6358..9321a8c 100644 --- a/src/com/garbagemule/MobArena/util/WaveUtils.java +++ b/src/com/garbagemule/MobArena/util/WaveUtils.java @@ -21,11 +21,11 @@ public class WaveUtils /** * Get all the spawnpoints that have players nearby. */ - public static List getValidSpawnpoints(Collection spawnpoints, Collection players) + public static List getValidSpawnpoints(Arena arena, Collection players) { List result = new ArrayList(); - for (Location s : spawnpoints) + for (Location s : arena.getAllSpawnpoints()) { for (Player p : players) { @@ -47,7 +47,10 @@ public class WaveUtils // If no players are in range, just use all the spawnpoints. if (result.isEmpty()) - result.addAll(spawnpoints); + { + MobArena.warning("Spawnpoints of arena '" + arena.configName() + "' may be too far apart!"); + result.addAll(arena.getAllSpawnpoints()); + } // Else, return the valid spawnpoints. return result; @@ -383,6 +386,16 @@ public class WaveUtils } } + // OPTIONAL: Ability-interval + int abilityDelay = config.getInt(path + "ability-interval", 3); + if (abilityDelay <= 0) + { + MobArena.warning("Boss ability-delay must be greater than 0, " + path); + wellDefined = false; + } + + // OPTIONAL: Ability-announce + // TODO: OPTIONAL: Adds // Unsure about config-file implementation... diff --git a/src/com/garbagemule/MobArena/util/data/Totals.java b/src/com/garbagemule/MobArena/util/data/Totals.java index 50be9e8..ec04d91 100644 --- a/src/com/garbagemule/MobArena/util/data/Totals.java +++ b/src/com/garbagemule/MobArena/util/data/Totals.java @@ -35,7 +35,6 @@ public class Totals updateDuration(totals, "general-info.longest-session-duration", log.getDurationLong(), false); // Classes - //updateInt(totals, "classes.overall-distribution.total-count", log.players.keySet().size(), true); for (String c : log.arena.getClasses()) { // Array {kills, dmgDone, dmgTaken} diff --git a/src/com/garbagemule/MobArena/waves/BossWave.java b/src/com/garbagemule/MobArena/waves/BossWave.java index 31c6243..f0f4a6b 100644 --- a/src/com/garbagemule/MobArena/waves/BossWave.java +++ b/src/com/garbagemule/MobArena/waves/BossWave.java @@ -26,9 +26,8 @@ public class BossWave extends AbstractWave private List abilities; private Set adds; private BossHealth bossHealth; - private int healthAmount; - private List taskList; - private boolean lowHealthAnnounced = false; + private int healthAmount, abilityTask, abilityInterval; + private boolean lowHealthAnnounced = false, abilityAnnounce; // Recurrent public BossWave(Arena arena, String name, int wave, int frequency, int priority, Configuration config, String path) @@ -47,7 +46,7 @@ public class BossWave extends AbstractWave private void load(Configuration config, String path) { setType(WaveType.BOSS); - taskList = new LinkedList(); + abilityTask = -1; abilities = new LinkedList(); // Get monster and health @@ -55,6 +54,8 @@ public class BossWave extends AbstractWave bossHealth = WaveUtils.getEnumFromString(BossHealth.class, config.getString(path + "health"), BossHealth.MEDIUM); // Get abilities + abilityInterval = config.getInt(path + "ability-interval", 3) * 20; + abilityAnnounce = config.getBoolean(path + "ability-announce", true); String abilities = config.getString(path + "abilities"); if (abilities != null) { @@ -83,45 +84,48 @@ public class BossWave extends AbstractWave healthAmount = bossHealth.getAmount(getArena().getPlayerCount()); startAbilityTasks(); - System.out.println(this); } private void startAbilityTasks() { final int abilityCount = abilities.size(); - int i = 1; - for (final BossAbility ability : abilities) - { - // Schedule the task - int abilityTask = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(getArena().getPlugin(), - new Runnable() + // If there are no abilities, don't start the timer. + if (abilityCount == 0) + return; + + abilityTask = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(getArena().getPlugin(), + new Runnable() + { + private int counter = 0; + + public void run() { - public void run() - { - // Announce ability + // Grab the next ability + BossAbility ability = abilities.get(counter % abilityCount); + + // Announce it + if (abilityAnnounce) MAUtils.tellAll(getArena(), Msg.WAVE_BOSS_ABILITY.get(ability.toString())); - - // Activate! - ability.run(getArena(), bossCreature); - } - }, 50*i, 50*abilityCount); - - // Add the task to the task list for cancelling later, and increment counter - taskList.add(abilityTask); - i++; - } + + // Activate! + ability.run(getArena(), bossCreature); + + // Increment counter + counter++; + } + }, 100, abilityInterval); } - public void cancelAbilityTasks() + public void cancelAbilityTask() { - for (Integer i : taskList) - Bukkit.getServer().getScheduler().cancelTask(i); + if (abilityTask != -1) + Bukkit.getServer().getScheduler().cancelTask(abilityTask); } public void clear() { - cancelAbilityTasks(); + cancelAbilityTask(); getArena().setBossWave(null); CraftEntity ce = (CraftEntity) bossCreature; diff --git a/src/com/garbagemule/MobArena/waves/DefaultWave.java b/src/com/garbagemule/MobArena/waves/DefaultWave.java index 70a059b..d647ef9 100644 --- a/src/com/garbagemule/MobArena/waves/DefaultWave.java +++ b/src/com/garbagemule/MobArena/waves/DefaultWave.java @@ -40,14 +40,13 @@ public class DefaultWave extends NormalWave MAUtils.tellAll(getArena(), Msg.WAVE_DEFAULT.get(""+wave)); // Get the valid spawnpoints, and initialize counter - List validSpawnpoints = WaveUtils.getValidSpawnpoints(getArena().getSpawnpoints(), getArena().getLivingPlayers()); + List validSpawnpoints = WaveUtils.getValidSpawnpoints(getArena(), getArena().getLivingPlayers()); // Initialize the total amount of mobs to spawn int totalToSpawn = getGrowth().getAmount(wave, getArena().getPlayerCount()); // Spawn all the monsters spawnAll(getMonstersToSpawn(totalToSpawn), validSpawnpoints); - System.out.println(this); } private Map getMonstersToSpawn(int totalToSpawn) diff --git a/src/com/garbagemule/MobArena/waves/SpecialWave.java b/src/com/garbagemule/MobArena/waves/SpecialWave.java index ff41325..c7c10ed 100644 --- a/src/com/garbagemule/MobArena/waves/SpecialWave.java +++ b/src/com/garbagemule/MobArena/waves/SpecialWave.java @@ -35,11 +35,10 @@ public class SpecialWave extends NormalWave MAUtils.tellAll(getArena(), Msg.WAVE_SPECIAL.get(""+wave)); // Get the valid spawnpoints, and initialize counter - List validSpawnpoints = WaveUtils.getValidSpawnpoints(getArena().getSpawnpoints(), getArena().getLivingPlayers()); + List validSpawnpoints = WaveUtils.getValidSpawnpoints(getArena(), getArena().getLivingPlayers()); // Spawn all the monsters spawnAll(getMonstersToSpawn(getArena().getPlayerCount()), validSpawnpoints); - System.out.println(this); } private Map getMonstersToSpawn(int playerCount) diff --git a/src/com/garbagemule/MobArena/waves/SwarmWave.java b/src/com/garbagemule/MobArena/waves/SwarmWave.java index 11faf88..7a31c9d 100644 --- a/src/com/garbagemule/MobArena/waves/SwarmWave.java +++ b/src/com/garbagemule/MobArena/waves/SwarmWave.java @@ -48,11 +48,10 @@ public class SwarmWave extends AbstractWave MAUtils.tellAll(getArena(), Msg.WAVE_SWARM.get(""+wave)); // Get the valid spawnpoints, and initialize counter - List validSpawnpoints = WaveUtils.getValidSpawnpoints(getArena().getSpawnpoints(), getArena().getLivingPlayers()); + List validSpawnpoints = WaveUtils.getValidSpawnpoints(getArena(), getArena().getLivingPlayers()); // Spawn the hellians! spawnAll(monster, amount.getAmount(getArena().getPlayerCount()), validSpawnpoints); - System.out.println(this); } public void spawnAll(MACreature monster, int amount, List spawnpoints) diff --git a/src/com/garbagemule/MobArena/waves/Wave.java b/src/com/garbagemule/MobArena/waves/Wave.java index d009570..e148289 100644 --- a/src/com/garbagemule/MobArena/waves/Wave.java +++ b/src/com/garbagemule/MobArena/waves/Wave.java @@ -66,7 +66,6 @@ public interface Wave { public void run(Arena arena, LivingEntity boss) { - System.out.println("Shooting arrow"); boss.shootArrow(); } }, @@ -74,7 +73,6 @@ public interface Wave { public void run(Arena arena, LivingEntity boss) { - System.out.println("Shooting fireball"); Location bLoc = boss.getLocation(); Location loc = bLoc.add(bLoc.getDirection().normalize().multiply(2).toLocation(boss.getWorld(), bLoc.getYaw(), bLoc.getPitch())); Fireball fireball = boss.getWorld().spawn(loc, Fireball.class); @@ -85,7 +83,6 @@ public interface Wave { public void run(Arena arena, LivingEntity boss) { - System.out.println("Fire aura"); for (Player p : getNearbyPlayers(arena, boss, 5)) p.setFireTicks(20); } @@ -94,7 +91,6 @@ public interface Wave { public void run(Arena arena, LivingEntity boss) { - System.out.println("Lightning aura."); Location base = boss.getLocation(); Location ne = base.getBlock().getRelative( 2, 0, 2).getLocation(); Location nw = base.getBlock().getRelative(-2, 0, 2).getLocation(); @@ -123,7 +119,6 @@ public interface Wave { public void run(final Arena arena, LivingEntity boss) { - System.out.println("Root target"); final LivingEntity target = getTarget(boss); if (target == null) return; @@ -174,7 +169,6 @@ public interface Wave { public void run(Arena arena, LivingEntity boss) { - System.out.println("Throw nearby"); for (Player p : getNearbyPlayers(arena, boss, 5)) { Location bLoc = boss.getLocation(); @@ -188,7 +182,6 @@ public interface Wave { public void run(Arena arena, LivingEntity boss) { - System.out.println("Throw distant"); for (Player p : getDistantPlayers(arena, boss, 8)) { Location bLoc = boss.getLocation(); @@ -202,7 +195,6 @@ public interface Wave { public void run(Arena arena, LivingEntity boss) { - System.out.println("Fetch target"); LivingEntity target = getTarget(boss); if (target != null) target.teleport(boss); } @@ -211,7 +203,6 @@ public interface Wave { public void run(Arena arena, LivingEntity boss) { - System.out.println("Fetch nearby"); for (Player p : getNearbyPlayers(arena, boss, 5)) p.teleport(boss); } @@ -220,7 +211,6 @@ public interface Wave { public void run(Arena arena, LivingEntity boss) { - System.out.println("Fetch distant"); for (Player p : getDistantPlayers(arena, boss, 8)) p.teleport(boss); }