diff --git a/MobArena.jar b/MobArena.jar index f135763..87b4720 100644 Binary files a/MobArena.jar and b/MobArena.jar differ diff --git a/bin/plugin.yml b/bin/plugin.yml index 6e9a539..67c25a8 100644 --- a/bin/plugin.yml +++ b/bin/plugin.yml @@ -1,6 +1,6 @@ name: MobArena main: com.garbagemule.MobArena.MobArena -version: 0.89.2 +version: 0.90 commands: ma: description: Base command for MobArena diff --git a/src/com/garbagemule/MobArena/ArenaManager.java b/src/com/garbagemule/MobArena/ArenaManager.java index 2d9481b..4ee1c11 100644 --- a/src/com/garbagemule/MobArena/ArenaManager.java +++ b/src/com/garbagemule/MobArena/ArenaManager.java @@ -3,19 +3,23 @@ package com.garbagemule.MobArena; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.bukkit.ChatColor; +import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Server; import org.bukkit.World; import org.bukkit.block.Block; +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.util.config.Configuration; public class ArenaManager @@ -31,7 +35,9 @@ public class ArenaManager protected static boolean isSetup = false; protected static boolean isEnabled = true; protected static boolean isProtected = true; - protected static boolean checkUpdates = true; + protected static int spawnTaskId = -1; + protected static int waveDelay, waveInterval, specialModulo, repairDelay; + protected static boolean checkUpdates, lightning; // Location variables for the arena region. protected static Location p1 = null; @@ -46,13 +52,13 @@ public class ArenaManager protected static int dPoweredCreepers, dPigZombies, dSlimes, dMonsters, dAngryWolves, dGiants, dGhasts; - // Set and Maps for storing players, their locations, items, armor, etc. + // Sets and Maps for storing players, their locations, and their rewards. protected static Set playerSet = new HashSet(); protected static Set readySet = new HashSet(); protected static Map rewardMap = new HashMap(); protected static Map locationMap = new HashMap(); - // Maps for storing class items and armor. + // Maps for storing player classes, class items and armor. protected static List classes = new ArrayList(); protected static Map classMap = new HashMap(); protected static Map classItemMap = new HashMap(); @@ -65,7 +71,6 @@ public class ArenaManager // Entities, blocks and items on MobArena floor. protected static Set monsterSet = new HashSet(); protected static Set blockSet = new HashSet(); - protected static Set dropSet = new HashSet(); @@ -84,10 +89,12 @@ public class ArenaManager if (instance != null) { // General variables. - config = MAUtils.getConfig(); - plugin = instance; - server = plugin.getServer(); - world = MAUtils.getWorld(); + config = MAUtils.getConfig(); + plugin = instance; + server = plugin.getServer(); + world = MAUtils.getWorld(); + lightning = MAUtils.getBoolean("settings.lightning", true); + repairDelay = MAUtils.getInt("settings.repairdelay", 5); // Class list and maps. classes = MAUtils.getClasses(); @@ -95,6 +102,9 @@ public class ArenaManager classArmorMap = MAUtils.getClassItems("armor"); // Waves and rewards. + waveDelay = MAUtils.getInt("settings.firstwavedelay", 5) * 20; + waveInterval = MAUtils.getInt("settings.waveinterval", 20) * 20; + specialModulo = MAUtils.getInt("settings.specialmodulo", 4); everyWaveMap = MAUtils.getWaveMap("every"); afterWaveMap = MAUtils.getWaveMap("after"); @@ -121,7 +131,7 @@ public class ArenaManager p1 = MAUtils.getCoords("p1"); p2 = MAUtils.getCoords("p2"); spawnpoints = MAUtils.getSpawnPoints(); - checkUpdates = MAUtils.getUpdateNotification(); + checkUpdates = MAUtils.getBoolean("settings.updatenotification", true); // Set the boolean if all variables are valid. ArenaManager.isSetup = MAUtils.verifyData(); @@ -149,6 +159,7 @@ public class ArenaManager public static void startArena() { isRunning = true; + readySet.clear(); for (Player p : playerSet) { @@ -157,7 +168,7 @@ public class ArenaManager } MASpawnThread thread = new MASpawnThread(); - server.getScheduler().scheduleSyncRepeatingTask(plugin,thread,100,400); + spawnTaskId = server.getScheduler().scheduleSyncRepeatingTask(plugin,thread,(long)waveDelay,(long)waveInterval); tellAll("Let the slaughter begin!"); } @@ -168,12 +179,13 @@ public class ArenaManager * and stops the spawning of monsters. */ public static void endArena() - { + { isRunning = false; - server.getScheduler().cancelTasks(plugin); + server.getScheduler().cancelTask(spawnTaskId); + killMonsters(); clearBlocks(); - clearDrops(); + clearEntities(); giveRewards(); // TO-DO: Fix this, maybe add a Set dead @@ -204,7 +216,7 @@ public class ArenaManager } if (isRunning) { - tellPlayer(p, "Arena in progress. Type /marena spectate to watch."); + tellPlayer(p, "Arena in progress. Type /ma spec to watch."); return; } if (!MAUtils.hasEmptyInventory(p)) @@ -231,30 +243,27 @@ public class ArenaManager * is removed from all the sets and maps. */ public static void playerLeave(Player p) - { + { if (!locationMap.containsKey(p)) { tellPlayer(p, "You are not in the arena."); return; } - if (playerSet.contains(p)) - { - playerSet.remove(p); + // This must occur before playerSet.remove(p) to avoid teleport block. + p.teleport(locationMap.get(p)); + locationMap.remove(p); + readySet.remove(p); + classMap.remove(p); + + if (playerSet.remove(p)) MAUtils.clearInventory(p); - } - - //if (readySet.contains(p)) - readySet.remove(p); - - //if (classMap.keySet().contains(p)) - classMap.remove(p); - - // This must occur after playerSet.remove(p) to avoid teleport block. - p.teleport(locationMap.remove(p)); if (isRunning && playerSet.isEmpty()) endArena(); + + if (!readySet.isEmpty() && readySet.equals(playerSet)) + startArena(); tellPlayer(p, "You left the arena. Thanks for playing!"); } @@ -267,10 +276,7 @@ public class ArenaManager readySet.add(p); if (readySet.equals(playerSet)) - { - readySet.clear(); startArena(); - } } /** @@ -360,6 +366,57 @@ public class ArenaManager tellPlayer(p, "Not ready: " + list.substring(0, list.length() - 2)); } + /** + * Forcefully starts the arena, causing all players in the + * playerSet who aren't ready to leave, and starting the + * arena for everyone else. + */ + public static void forceStart(Player p) + { + if (ArenaManager.isRunning) + { + ArenaManager.tellPlayer(p, "Arena has already started."); + return; + } + if (ArenaManager.readySet.isEmpty()) + { + ArenaManager.tellPlayer(p, "Can't force start, no players are ready."); + return; + } + + Iterator iterator = ArenaManager.playerSet.iterator(); + while (iterator.hasNext()) + { + Player player = iterator.next(); + if (!ArenaManager.readySet.contains(player)) + ArenaManager.playerLeave(player); + } + + ArenaManager.tellPlayer(p, "Forced arena start."); + } + + /** + * Forcefully ends the arena, causing all players to leave and + * all relevant sets and maps to be cleared. + */ + public static void forceEnd(Player p) + { + if (ArenaManager.playerSet.isEmpty()) + { + ArenaManager.tellPlayer(p, "No one is in the arena."); + return; + } + + Iterator iterator = ArenaManager.playerSet.iterator(); + while (iterator.hasNext()) + ArenaManager.playerLeave(iterator.next()); + + // Just for good measure. + endArena(); + + ArenaManager.tellPlayer(p, "Forced arena end."); + } + /* ///////////////////////////////////////////////////////////////////// // @@ -372,7 +429,7 @@ public class ArenaManager * Kills all monsters currently on the arena floor. */ public static void killMonsters() - { + { // Remove all monsters, then clear the Set. for (LivingEntity e : monsterSet) { @@ -389,24 +446,28 @@ public class ArenaManager { // Remove all blocks, then clear the Set. for (Block b : blockSet) - { b.setType(Material.AIR); - } + blockSet.clear(); } /** - * Removes all items on the arena floor. + * Removes all items and slimes in the arena region. */ - public static void clearDrops() + public static void clearEntities() { - // Remove all blocks, then clear the Set. - for (Item i : dropSet) - { - i.remove(); - } + Chunk c1 = world.getChunkAt(p1); + Chunk c2 = world.getChunkAt(p2); - dropSet.clear(); + /* Yes, ugly nesting, but it's necessary. This bit + * removes all the entities in the arena region without + * bloatfully iterating through all entities in the + * world. Much faster on large servers especially. */ + 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)) + e.remove(); } @@ -468,6 +529,9 @@ public class ArenaManager */ public static void tellPlayer(Player p, String msg) { + if (p == null) + return; + p.sendMessage(ChatColor.GREEN + "[MobArena] " + ChatColor.WHITE + msg); } @@ -476,9 +540,14 @@ public class ArenaManager */ public static void tellAll(String msg) { - for (Player p : playerSet) - { - tellPlayer(p, msg); - } + 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 p : world.getChunkAt(i,j).getEntities()) + if (p instanceof Player) + tellPlayer((Player)p, msg); + } } \ No newline at end of file diff --git a/src/com/garbagemule/MobArena/EntityPosition.java b/src/com/garbagemule/MobArena/EntityPosition.java index d2fdd63..5ee96bb 100644 --- a/src/com/garbagemule/MobArena/EntityPosition.java +++ b/src/com/garbagemule/MobArena/EntityPosition.java @@ -8,6 +8,7 @@ import org.bukkit.World; * NOTE: I (garbagemule) DID NOT WRITE THIS CLASS (notice the author below) * @author creadri */ +@SuppressWarnings("serial") public class EntityPosition implements Serializable{ private double x; private double y; diff --git a/src/com/garbagemule/MobArena/MABlockListener.java b/src/com/garbagemule/MobArena/MABlockListener.java index 98dda83..bf2cf46 100644 --- a/src/com/garbagemule/MobArena/MABlockListener.java +++ b/src/com/garbagemule/MobArena/MABlockListener.java @@ -5,7 +5,7 @@ import org.bukkit.block.Block; import org.bukkit.event.block.BlockListener; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.block.BlockDamageEvent; +//import org.bukkit.event.block.BlockDamageEvent; /** * This listener serves as a protection class. Blocks within @@ -15,14 +15,12 @@ import org.bukkit.event.block.BlockDamageEvent; * ArenaManager when the session ends. */ public class MABlockListener extends BlockListener -{ - private MobArena plugin; - +{ public MABlockListener(MobArena instance) { - plugin = instance; } + /* Removed for testing purposes. public void onBlockDamage(BlockDamageEvent event) { if (!ArenaManager.isSetup || !ArenaManager.isProtected) @@ -33,24 +31,37 @@ public class MABlockListener extends BlockListener if (ArenaManager.blockSet.contains(b)) return; + System.out.println("This is block damage."); + if (MAUtils.inRegion(b.getLocation())) event.setCancelled(true); } - + */ + + /** + * Prevents blocks from breaking if block protection is on. + */ public void onBlockBreak(BlockBreakEvent event) - { + { if (!ArenaManager.isSetup || !ArenaManager.isProtected) return; Block b = event.getBlock(); - if (ArenaManager.blockSet.contains(b)) + if (ArenaManager.blockSet.remove(b) || b.getType() == Material.TNT) return; + System.out.println("This is block break."); + if (MAUtils.inRegion(b.getLocation())) event.setCancelled(true); } + /** + * Adds player-placed blocks to a set for removal and item + * drop purposes. If the block is placed within the arena + * region, cancel the event if protection is on. + */ public void onBlockPlace(BlockPlaceEvent event) { if (!ArenaManager.isSetup || !ArenaManager.isProtected) @@ -58,15 +69,21 @@ public class MABlockListener extends BlockListener Block b = event.getBlock(); - if (MAUtils.inRegion(b.getLocation())) + if (!MAUtils.inRegion(b.getLocation())) + return; + + if (ArenaManager.isRunning && ArenaManager.playerSet.contains(event.getPlayer())) { - if (ArenaManager.isRunning && ArenaManager.playerSet.contains(event.getPlayer())) - { - ArenaManager.blockSet.add(b); - return; - } - - event.setCancelled(true); + ArenaManager.blockSet.add(b); + Material type = b.getType(); + + // Make sure to add the top parts of doors. + if (type == Material.WOODEN_DOOR || type == Material.IRON_DOOR_BLOCK) + ArenaManager.blockSet.add(b.getRelative(0,1,0)); + + return; } + + event.setCancelled(true); } } \ No newline at end of file diff --git a/src/com/garbagemule/MobArena/MACommands.java b/src/com/garbagemule/MobArena/MACommands.java index c5fe46b..0665e35 100644 --- a/src/com/garbagemule/MobArena/MACommands.java +++ b/src/com/garbagemule/MobArena/MACommands.java @@ -1,16 +1,11 @@ package com.garbagemule.MobArena; import java.util.Arrays; -import java.util.Iterator; -import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.CommandExecutor; -import org.bukkit.entity.Creature; -import org.bukkit.entity.CreatureType; -import org.bukkit.entity.LivingEntity; public class MACommands implements CommandExecutor { @@ -131,20 +126,24 @@ public class MACommands implements CommandExecutor return true; } - // ma force end + // ma force [start|end] if (cmd.equals("force")) { - if (!arg.equals("end")) + // Start arena. + if (arg.equals("start")) { - ArenaManager.tellPlayer(p, "/ma force end"); + ArenaManager.forceStart(p); + return true; + } + + // End the arena. + if (arg.equals("end")) + { + ArenaManager.forceEnd(p); return true; } - // End the arena. - Iterator iterator = ArenaManager.playerSet.iterator(); - while (iterator.hasNext()) - ArenaManager.playerLeave(iterator.next()); - ArenaManager.tellPlayer(p, "Forced arena end."); + ArenaManager.tellPlayer(p, "/ma force [start|end]"); return true; } @@ -275,7 +274,7 @@ public class MACommands implements CommandExecutor return true; } - // ma protect true/false + // ma protect [true|false] if (cmd.equals("protect")) { if (!arg.equals("true") && !arg.equals("false")) @@ -301,7 +300,8 @@ public class MACommands implements CommandExecutor return true; } } - + + // ma undo it hippie monster if (cmd.equals("undo")) { if (args.length != 4) diff --git a/src/com/garbagemule/MobArena/MADamageListener.java b/src/com/garbagemule/MobArena/MADamageListener.java index c6734b0..910977e 100644 --- a/src/com/garbagemule/MobArena/MADamageListener.java +++ b/src/com/garbagemule/MobArena/MADamageListener.java @@ -17,12 +17,9 @@ import org.bukkit.event.entity.CreatureSpawnEvent; */ // TO-DO: Perhaps implement TeamFluff's respawn-packet-code. public class MADamageListener extends EntityListener -{ - private MobArena plugin; - +{ public MADamageListener(MobArena instance) { - plugin = instance; } public void onEntityDamage(EntityDamageEvent event) @@ -76,7 +73,7 @@ public class MADamageListener extends EntityListener /** * Prevents monsters from spawning inside the arena unless - * it's running, and adds mini-slimes to the monsterSet. + * it's running. */ public void onCreatureSpawn(CreatureSpawnEvent event) { @@ -86,18 +83,7 @@ public class MADamageListener extends EntityListener if (!(event.getEntity() instanceof LivingEntity)) return; - System.out.println("This is the spawn command"); - - LivingEntity e = (LivingEntity) event.getEntity(); - - if (ArenaManager.isRunning) - { - if (!ArenaManager.monsterSet.contains(e)) - ArenaManager.monsterSet.add(e); - } - else - { + if (!ArenaManager.isRunning) event.setCancelled(true); - } } } \ No newline at end of file diff --git a/src/com/garbagemule/MobArena/MADisabledCommands.java b/src/com/garbagemule/MobArena/MADisabledCommands.java index cd29808..55dacc2 100644 --- a/src/com/garbagemule/MobArena/MADisabledCommands.java +++ b/src/com/garbagemule/MobArena/MADisabledCommands.java @@ -1,6 +1,5 @@ package com.garbagemule.MobArena; -import java.util.Arrays; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerListener; import org.bukkit.event.player.PlayerCommandPreprocessEvent; diff --git a/src/com/garbagemule/MobArena/MADisconnectListener.java b/src/com/garbagemule/MobArena/MADisconnectListener.java index c44a98b..56e3059 100644 --- a/src/com/garbagemule/MobArena/MADisconnectListener.java +++ b/src/com/garbagemule/MobArena/MADisconnectListener.java @@ -1,10 +1,7 @@ package com.garbagemule.MobArena; -import java.util.List; -import java.util.Arrays; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerListener; -import org.bukkit.event.player.PlayerEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerJoinEvent; @@ -16,11 +13,8 @@ import org.bukkit.event.player.PlayerJoinEvent; */ public class MADisconnectListener extends PlayerListener { - private MobArena plugin; - public MADisconnectListener(MobArena instance) { - plugin = instance; } public void onPlayerQuit(PlayerQuitEvent event) diff --git a/src/com/garbagemule/MobArena/MALobbyListener.java b/src/com/garbagemule/MobArena/MALobbyListener.java index 3b8e57c..e0bf885 100644 --- a/src/com/garbagemule/MobArena/MALobbyListener.java +++ b/src/com/garbagemule/MobArena/MALobbyListener.java @@ -1,13 +1,14 @@ package com.garbagemule.MobArena; +import org.bukkit.block.Block; import org.bukkit.block.Sign; import org.bukkit.entity.Player; import org.bukkit.event.Event.Result; import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerBucketEmptyEvent; import org.bukkit.event.player.PlayerListener; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerDropItemEvent; -import org.bukkit.event.player.PlayerPickupItemEvent; /** * This listener prevents players from sharing class-specific @@ -15,12 +16,9 @@ import org.bukkit.event.player.PlayerPickupItemEvent; */ // TO-DO: Merge with MASignListener and MAReadyListener into MALobbyListener public class MALobbyListener extends PlayerListener -{ - private MobArena plugin; - +{ public MALobbyListener(MobArena instance) { - plugin = instance; } /** @@ -34,15 +32,31 @@ public class MALobbyListener extends PlayerListener return; if (ArenaManager.isRunning) - { - ArenaManager.dropSet.add(event.getItemDrop()); return; - } ArenaManager.tellPlayer(p, "No sharing before the arena starts!"); event.setCancelled(true); } + /** + * Adds liquid blocks to the blockset when players empty their buckets. + */ + public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) + { + if (!ArenaManager.playerSet.contains(event.getPlayer())) + return; + + if (!ArenaManager.isRunning) + { + event.getBlockClicked().getFace(event.getBlockFace()).setTypeId(0); + event.setCancelled(true); + return; + } + + Block liquid = event.getBlockClicked().getFace(event.getBlockFace()); + ArenaManager.blockSet.add(liquid); + } + /** * Checks if the player hits an iron block or a sign, or if the player * is trying to use an item. @@ -57,6 +71,15 @@ public class MALobbyListener extends PlayerListener if (!ArenaManager.playerSet.contains(p)) return; + + Action a = event.getAction(); + + // Check if player is trying to use an item. + if ((a == Action.RIGHT_CLICK_AIR) || (a == Action.RIGHT_CLICK_BLOCK)) + { + event.setUseItemInHand(Result.DENY); + event.setCancelled(true); + } // Iron block if (event.hasBlock() && event.getClickedBlock().getTypeId() == 42) @@ -76,6 +99,12 @@ public class MALobbyListener extends PlayerListener // Sign if (event.hasBlock() && event.getClickedBlock().getState() instanceof Sign) { + if (a == Action.RIGHT_CLICK_BLOCK) + { + ArenaManager.tellPlayer(p, "Punch the sign. Don't right-click."); + return; + } + // Cast the block to a sign to get the text on it. Sign sign = (Sign) event.getClickedBlock().getState(); @@ -89,16 +118,5 @@ public class MALobbyListener extends PlayerListener ArenaManager.tellPlayer(p, "You have chosen " + className + " as your class!"); return; } - - // Trying to use stuff - Action a = event.getAction(); - - // Check if player is trying to use an item. - if ((a == Action.RIGHT_CLICK_AIR) || (a == Action.RIGHT_CLICK_BLOCK)) - { - if (ArenaManager.playerSet.contains(p)) - event.setUseItemInHand(Result.DENY); - return; - } } } \ No newline at end of file diff --git a/src/com/garbagemule/MobArena/MAMonsterListener.java b/src/com/garbagemule/MobArena/MAMonsterListener.java index 9869501..b6f25a0 100644 --- a/src/com/garbagemule/MobArena/MAMonsterListener.java +++ b/src/com/garbagemule/MobArena/MAMonsterListener.java @@ -3,6 +3,7 @@ package com.garbagemule.MobArena; import java.util.HashMap; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.inventory.ItemStack; import org.bukkit.event.entity.EntityListener; import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.entity.EntityCombustEvent; @@ -23,39 +24,65 @@ public class MAMonsterListener extends EntityListener plugin = instance; } - // Creeper explosions + /** + * Handles all explosion events, also from TNT. + */ public void onEntityExplode(EntityExplodeEvent event) { /* This could be done by simply cancelling the event, but that * also cancels the explosion animation. This is a workaround. */ - if (MAUtils.inRegion(event.getLocation())) + if (!MAUtils.inRegion(event.getLocation())) + return; + + // Don't drop any blocks from the explosion. + event.setYield(0); + + // Store the blocks and their values in the map. + final HashMap blockMap = new HashMap(); + + for (Block b : event.blockList()) { - // Don't drop any blocks. - event.setYield(0); - - // Store the blocks and their values. - final HashMap blockMap = new HashMap(); - for (Block b : event.blockList()) + // Doors are wonky, so don't store them. Just smile and wave, and remove from set. + if (b.getType() == Material.WOODEN_DOOR || b.getType() == Material.IRON_DOOR_BLOCK || b.getType() == Material.CAKE_BLOCK) { - if (b.getType() == Material.CAKE_BLOCK) - blockMap.put(b, 0); - else - blockMap.put(b, b.getTypeId()); + ArenaManager.blockSet.remove(b); + continue; } - // Wait a couple of ticks, then rebuild the blocks. - ArenaManager.server.getScheduler().scheduleSyncDelayedTask(plugin, - new Runnable() - { - public void run() - { - for (Block b : blockMap.keySet()) - { - b.getLocation().getBlock().setTypeId(blockMap.get(b)); - } - } - }, 5); + // If a block is in the blockSet, make sure it drops "naturally" so Oddjob doesn't cry. + if (ArenaManager.blockSet.remove(b)) + { + ArenaManager.world.dropItemNaturally(b.getLocation(), new ItemStack(b.getTypeId(), 1)); + continue; + } + + // If a block has extra data, store it as a fourth digit (thousand). + int type = b.getTypeId() + (b.getData() * 1000); + blockMap.put(b, type); } + + // Wait a couple of ticks, then rebuild the blocks. + ArenaManager.server.getScheduler().scheduleSyncDelayedTask(plugin, + new Runnable() + { + public void run() + { + for (Block b : blockMap.keySet()) + { + int type = blockMap.get(b); + + // Modulo 1000 to get the actual type id. + b.getLocation().getBlock().setTypeId(type % 1000); + + /* If the type ID is greater than 1000, it means the block + * has extra data (stairs, levers, etc.). We subtract the + * block type data by dividing by 1000. Integer division + * always rounds by truncation. */ + if (type > 1000) + b.getLocation().getBlock().setData((byte) (type / 1000)); + } + } + }, ArenaManager.repairDelay); } // Zombie/skeleton combustion from the sun. diff --git a/src/com/garbagemule/MobArena/MASpawnThread.java b/src/com/garbagemule/MobArena/MASpawnThread.java index 0e7b8f2..b026c54 100644 --- a/src/com/garbagemule/MobArena/MASpawnThread.java +++ b/src/com/garbagemule/MobArena/MASpawnThread.java @@ -1,7 +1,5 @@ package com.garbagemule.MobArena; -import java.util.List; -import java.util.ArrayList; import java.util.Random; import org.bukkit.Location; import org.bukkit.entity.Wolf; @@ -12,8 +10,6 @@ import org.bukkit.entity.Creature; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.CreatureType; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.PlayerInventory; /** * Core class for handling wave spawning. @@ -28,7 +24,7 @@ import org.bukkit.inventory.PlayerInventory; // TO-DO: Allow additional "default" waves. public class MASpawnThread implements Runnable { - private int wave, ran, noOfSpawnPoints, noOfPlayers; + private int wave, ran, noOfSpawnPoints, noOfPlayers, modulo; private int dZombies, dSkeletons, dSpiders, dCreepers, dWolves; private int dPoweredCreepers, dPigZombies, dSlimes, dMonsters, dAngryWolves, dGiants, dGhasts; private Random random; @@ -36,6 +32,9 @@ public class MASpawnThread implements Runnable public MASpawnThread() { + modulo = ArenaManager.specialModulo; + if (modulo <= 0) modulo = -32768; + noOfPlayers = ArenaManager.playerSet.size(); noOfSpawnPoints = ArenaManager.spawnpoints.size(); wave = 1; @@ -89,8 +88,7 @@ public class MASpawnThread implements Runnable } // Check if this is a special wave. - // TO-DO: Get this value from the config-file. - if (wave % 4 == 0) + if (wave % modulo == 0) { ArenaManager.tellAll("Get ready for wave #" + wave + "! [SPECIAL]"); specialWave(); @@ -132,9 +130,6 @@ public class MASpawnThread implements Runnable LivingEntity e = ArenaManager.world.spawnCreature(loc,mob); ArenaManager.monsterSet.add(e); - //if (mob == CreatureType.WOLF) - // ((Wolf)e).setAngry(true); - // Grab a random target. Creature c = (Creature) e; c.setTarget(getClosestPlayer(e)); @@ -165,42 +160,33 @@ public class MASpawnThread implements Runnable else return; // 5 on purpose - Ghasts act weird in Overworld. - switch (mob) - //switch (random.nextInt(5)) + switch(mob) { case CREEPER: - //mob = CreatureType.CREEPER; count = noOfPlayers * 3; break; case PIG_ZOMBIE: - //mob = CreatureType.PIG_ZOMBIE; count = noOfPlayers * 2; break; case SLIME: - //mob = CreatureType.SLIME; count = noOfPlayers * 4; slime = true; break; case MONSTER: - //mob = CreatureType.MONSTER; count = noOfPlayers + 1; break; case WOLF: - //mob = CreatureType.WOLF; count = noOfPlayers * 3; wolf = true; break; case GIANT: - //mob = CreatureType.GIANT; count = 1; break; case GHAST: - //mob = CreatureType.GHAST; count = 2; ghast = true; break; default: - //mob = CreatureType.CHICKEN; count = 50; break; } @@ -229,6 +215,9 @@ public class MASpawnThread implements Runnable c.setTarget(getClosestPlayer(e)); } + if (!ArenaManager.lightning) + return; + // Lightning, just for effect ;) for (Location spawn : ArenaManager.spawnpoints) { diff --git a/src/com/garbagemule/MobArena/MATeleportListener.java b/src/com/garbagemule/MobArena/MATeleportListener.java index ee281b1..c0a7cc2 100644 --- a/src/com/garbagemule/MobArena/MATeleportListener.java +++ b/src/com/garbagemule/MobArena/MATeleportListener.java @@ -8,33 +8,49 @@ import org.bukkit.event.player.PlayerTeleportEvent; /** * This listener prevents players from warping out of the arena, if * they are in the arena session. + * Also prevents players from warping into the arena during a session. */ // TO-DO: Fix the bug that causes the message when people get stuck in walls. public class MATeleportListener extends PlayerListener { - private MobArena plugin; - public MATeleportListener(MobArena instance) { - plugin = instance; } public void onPlayerTeleport(PlayerTeleportEvent event) { Player p = event.getPlayer(); - if (!ArenaManager.playerSet.contains(p)) - return; - Location to = event.getTo(); - if (ArenaManager.arenaLoc.equals(to) || - ArenaManager.lobbyLoc.equals(to) || - ArenaManager.spectatorLoc.equals(to)) + // If the player teleports from outside of the arena.. + if (!ArenaManager.playerSet.contains(p)) { + if (!MAUtils.inRegion(to)) + return; + + if (!ArenaManager.isRunning) + return; + + if (ArenaManager.spectatorLoc.equals(to)) + return; + + // ..into the region during a battle; cancel + ArenaManager.tellPlayer(p, "Can't warp to the arena during battle!"); + ArenaManager.tellPlayer(p, "Type /ma spec to watch."); + event.setCancelled(true); return; } - ArenaManager.tellPlayer(p, "Can't warp in arena! To leave, type /ma leave"); + // Otherwise, only warp if to is in the locationMap, or a valid warp + if (ArenaManager.locationMap.get(p).equals(to) || + ArenaManager.arenaLoc.equals(to) || + ArenaManager.lobbyLoc.equals(to) || + ArenaManager.spectatorLoc.equals(to)) + return; + + // If warp isn't valid, notify the player + ArenaManager.tellPlayer(p, "Warping not allowed in the arena!"); + ArenaManager.tellPlayer(p, "Type /ma leave to leave"); event.setCancelled(true); } } \ No newline at end of file diff --git a/src/com/garbagemule/MobArena/MAUtils.java b/src/com/garbagemule/MobArena/MAUtils.java index e8b18d6..b855c3e 100644 --- a/src/com/garbagemule/MobArena/MAUtils.java +++ b/src/com/garbagemule/MobArena/MAUtils.java @@ -1,6 +1,5 @@ package com.garbagemule.MobArena; -import java.net.URL; import java.net.URI; import java.net.HttpURLConnection; import java.io.File; @@ -8,15 +7,13 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.util.Scanner; -import java.util.Arrays; import java.util.List; import java.util.LinkedList; import java.util.Map; import java.util.HashMap; import java.util.Random; +import java.util.Iterator; import org.bukkit.block.Sign; -import org.bukkit.block.BlockFace; import org.bukkit.World; import org.bukkit.Material; import org.bukkit.Location; @@ -78,7 +75,7 @@ public class MAUtils public static void giveItems(boolean reward, Player p, String... strings) { // Variables used. - ItemStack stack, current; + ItemStack stack; int id, amount; PlayerInventory inv; @@ -170,61 +167,6 @@ public class MAUtils // ///////////////////////////////////////////////////////////////////// */ - /** - * Replaces all tabs with 4 spaces in config.yml - - public static void fixConfigFile() - { - new File("plugins/MobArena").mkdir(); - File configFile = new File("plugins/MobArena/config.yml"); - - try - { - if(!configFile.exists()) - { - configFile.createNewFile(); - } - else - { - // Create an inputstream from the file - FileInputStream fis = new FileInputStream(configFile); - - // Read the file into a byte array, and make a String out of it. - byte[] bytes = new byte[(int)configFile.length()]; - fis.read(bytes); - String input = new String(bytes); - - // Close the stream. - fis.close(); - - // Replace all tabs with 4 spaces. - String output = ""; - for (char c : input.toCharArray()) - { - if (c == '\t') - output += " "; - else - output += c; - } - - // Create an outputstream from the file. - FileOutputStream fos = new FileOutputStream(configFile); - - // Write all the bytes to it. - for (byte b : output.getBytes()) - fos.write(b); - - // Close the stream. - fos.close(); - } - } - catch(Exception e) - { - System.out.println("[MobArena] ERROR: Config file could not be created."); - } - } - */ - /** * Creates a Configuration object from the config.yml file. */ @@ -249,25 +191,13 @@ public class MAUtils return new Configuration(configFile); } - public static boolean getUpdateNotification() - { - Configuration c = ArenaManager.config; - c.load(); - - boolean result = c.getBoolean("updatenotification", false); - c.setProperty("updatenotification", result); - c.save(); - - return result; - } - public static List getDisabledCommands() { Configuration c = ArenaManager.config; c.load(); - String commands = c.getString("disabledcommands", "kill"); - c.setProperty("disabledcommands", commands); + String commands = c.getString("settings.disabledcommands", "/kill"); + c.setProperty("settings.disabledcommands", commands); c.save(); List result = new LinkedList(); @@ -286,8 +216,8 @@ public class MAUtils Configuration c = ArenaManager.config; c.load(); - String world = c.getString("world", ArenaManager.server.getWorlds().get(0).getName()); - c.setProperty("world", world); + String world = c.getString("settings.world", ArenaManager.server.getWorlds().get(0).getName()); + c.setProperty("settings.world", world); c.save(); return ArenaManager.server.getWorld(world); @@ -306,11 +236,11 @@ public class MAUtils { c.setProperty("classes.Archer.items", "wood_sword, bow, arrow:128, grilled_pork"); c.setProperty("classes.Archer.armor", "298,299,300,301"); - c.setProperty("classes.Knight.items", "diamond_sword, grilled_pork"); + c.setProperty("classes.Knight.items", "diamond_sword, grilled_pork:2"); c.setProperty("classes.Knight.armor", "306,307,308,309"); - c.setProperty("classes.Tank.items", "iron_sword, grilled_pork:2"); + c.setProperty("classes.Tank.items", "iron_sword, grilled_pork:3, apple"); c.setProperty("classes.Tank.armor", "310,311,312,313"); - c.setProperty("classes.Oddjob.items", "stone_sword, flint_and_steel, netherrack:2, wood_pickaxe, wood_door, fishing_rod, apple, grilled_pork:3"); + c.setProperty("classes.Oddjob.items", "stone_sword, flint_and_steel, netherrack:2, wood_pickaxe, tnt:4, fishing_rod, apple, grilled_pork:3"); c.setProperty("classes.Oddjob.armor", "298,299,300,301"); c.setProperty("classes.Chef.items", "stone_sword, bread:6, grilled_pork:4, mushroom_soup, cake:3, cookie:12"); c.setProperty("classes.Chef.armor", "314,315,316,317"); @@ -436,7 +366,7 @@ public class MAUtils if (c.getInt("waves." + type + "." + monster, -1) == -1) { int dist = 10; - if (monster.equals("giants") || monster.equals("ghasts") || monster.equals("slimes")) + if (monster.equals("giants") || monster.equals("ghasts")) dist = 0; c.setProperty("waves." + type + "." + monster, dist); @@ -446,6 +376,36 @@ public class MAUtils return c.getInt("waves." + type + "." + monster, 0); } + /** + * Grabs an integer from the config-file. + */ + public static int getInt(String path, int def) + { + Configuration c = ArenaManager.config; + c.load(); + + int result = c.getInt(path, def); + c.setProperty(path, result); + + c.save(); + return result; + } + + /** + * Grabs a boolean from the config-file. + */ + public static boolean getBoolean(String path, boolean def) + { + Configuration c = ArenaManager.config; + c.load(); + + boolean result = c.getBoolean(path, def); + c.setProperty(path, result); + + c.save(); + return result; + } + /* ///////////////////////////////////////////////////////////////////// // @@ -842,7 +802,7 @@ public class MAUtils ArenaManager.world.getBlockAt(i,j,k).setTypeId(0); // Place the hippie signs - java.util.Iterator iterator = ArenaManager.classes.iterator(); + Iterator iterator = ArenaManager.classes.iterator(); for (int i = lx1+2; i <= lx2-2; i++) // Signs { ArenaManager.world.getBlockAt(i,ly1+1,lz2-1).setTypeIdAndData(63, (byte)0x8, false); @@ -874,7 +834,7 @@ public class MAUtils { FileInputStream fis = new FileInputStream("plugins/MobArena/precious.tmp"); ObjectInputStream ois = new ObjectInputStream(fis); - preciousPatch = (HashMap) ois.readObject(); + preciousPatch = (HashMap) ois.readObject(); ois.close(); } catch (Exception e) diff --git a/src/com/garbagemule/MobArena/MobArena.java b/src/com/garbagemule/MobArena/MobArena.java index a3b0899..6713315 100644 --- a/src/com/garbagemule/MobArena/MobArena.java +++ b/src/com/garbagemule/MobArena/MobArena.java @@ -1,8 +1,6 @@ package com.garbagemule.MobArena; import java.util.List; -import java.util.Iterator; -import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.Event.Priority; import org.bukkit.event.block.BlockListener; @@ -59,12 +57,13 @@ public class MobArena extends JavaPlugin pm.registerEvent(Event.Type.PLAYER_COMMAND_PREPROCESS, commandListener, Priority.Monitor, this); pm.registerEvent(Event.Type.PLAYER_INTERACT, lobbyListener, Priority.Normal, this); pm.registerEvent(Event.Type.PLAYER_DROP_ITEM, lobbyListener, Priority.Normal, this); + pm.registerEvent(Event.Type.PLAYER_BUCKET_EMPTY, lobbyListener, Priority.Normal, this); pm.registerEvent(Event.Type.PLAYER_TELEPORT, teleportListener, Priority.Normal, this); pm.registerEvent(Event.Type.PLAYER_QUIT, discListener, Priority.Normal, this); pm.registerEvent(Event.Type.PLAYER_KICK, discListener, Priority.Normal, this); pm.registerEvent(Event.Type.PLAYER_JOIN, discListener, Priority.Normal, this); pm.registerEvent(Event.Type.BLOCK_BREAK, blockListener, Priority.Normal, this); - pm.registerEvent(Event.Type.BLOCK_DAMAGE, blockListener, Priority.Normal, this); + //pm.registerEvent(Event.Type.BLOCK_DAMAGE, blockListener, Priority.Normal, this); pm.registerEvent(Event.Type.BLOCK_PLACE, blockListener, Priority.Normal, this); pm.registerEvent(Event.Type.ENTITY_DAMAGE, damageListener, Priority.Normal, this); pm.registerEvent(Event.Type.ENTITY_DEATH, damageListener, Priority.Normal, this); @@ -77,10 +76,8 @@ public class MobArena extends JavaPlugin public void onDisable() { - Iterator iterator = ArenaManager.playerSet.iterator(); - while (iterator.hasNext()) - ArenaManager.playerLeave(iterator.next()); - System.out.println("WAIT! WHAT ARE YOU DOING?!"); + + ArenaManager.forceEnd(null); } } \ No newline at end of file