first commit

This commit is contained in:
Garbage Mule 2011-05-30 07:11:25 +02:00
commit 6628a74836
14 changed files with 1631 additions and 0 deletions

View File

@ -0,0 +1,421 @@
package com.garbagemule.MobArena;
import java.io.File;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import org.bukkit.World;
import org.bukkit.Server;
import org.bukkit.Material;
import org.bukkit.Location;
import org.bukkit.ChatColor;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.util.config.Configuration;
import org.bukkit.event.Event;
import org.bukkit.plugin.EventExecutor;
public class ArenaManager
{
// Convenience variables.
protected static MobArena plugin = null;
protected static Server server = null;
protected static World world = null;
protected static Location arenaLoc = null;
protected static Location lobbyLoc = null;
protected static Location spectatorLoc = null;
protected static boolean isRunning = false;
protected static boolean isSetup = false;
// Location variables for the arena region.
protected static Location p1 = null;
protected static Location p2 = null;
// Configuration
protected static Configuration config = null;
// Spawn locations list and monster distribution fields.
protected static List<Location> spawnpoints = new ArrayList<Location>();
protected static int dZombies, dSkeletons, dSpiders, dCreepers;
// Set and Maps for storing players, their locations, items, armor, etc.
protected static Set<Player> playerSet = new HashSet<Player>();
protected static Set<Player> readySet = new HashSet<Player>();
protected static Map<Player,String> rewardMap = new HashMap<Player,String>();
protected static Map<Player,Location> locationMap = new HashMap<Player,Location>();
// Maps for storing class items and armor.
protected static List<String> classes = new ArrayList<String>();
protected static Map<Player,String> classMap = new HashMap<Player,String>();
protected static Map<String,String> classItemMap = new HashMap<String,String>();
protected static Map<String,String> classArmorMap = new HashMap<String,String>();
// Maps for rewards.
protected static Map<Integer,String> everyWaveMap = new HashMap<Integer,String>();
protected static Map<Integer,String> afterWaveMap = new HashMap<Integer,String>();
// Entities and blocks on MobArena floor.
protected static Set<LivingEntity> monsterSet = new HashSet<LivingEntity>();
protected static Set<Block> blockSet = new HashSet<Block>();
/* ///////////////////////////////////////////////////////////////////// //
INITIALIZATION AND UPDATE METHODS
// ///////////////////////////////////////////////////////////////////// */
/**
* Initializes the ArenaManager.
*/
public static void init(MobArena instance)
{
// If instance == null, simply update location variables.
if (instance != null)
{
// General variables.
config = MAUtils.getConfig();
plugin = instance;
server = plugin.getServer();
world = MAUtils.getWorld();
// Class list and maps.
classes = MAUtils.getClasses();
classItemMap = MAUtils.getClassItems("items");
classArmorMap = MAUtils.getClassItems("armor");
// Waves and rewards.
everyWaveMap = MAUtils.getWaveMap("every");
afterWaveMap = MAUtils.getWaveMap("after");
// Monster distribution coefficients.
dZombies = MAUtils.getDistribution("zombies");
dSkeletons = MAUtils.getDistribution("skeletons");
dSpiders = MAUtils.getDistribution("spiders");
dCreepers = MAUtils.getDistribution("creepers");
}
// Convenience variables.
arenaLoc = MAUtils.getCoords("arena");
lobbyLoc = MAUtils.getCoords("lobby");
spectatorLoc = MAUtils.getCoords("spectator");
p1 = MAUtils.getCoords("p1");
p2 = MAUtils.getCoords("p2");
spawnpoints = MAUtils.getSpawnPoints();
// Set the boolean if all variables are valid.
ArenaManager.isSetup = MAUtils.verifyData();
}
/**
* Updates all relevant variables.
*/
public static void updateVariables()
{
init(null);
}
/* ///////////////////////////////////////////////////////////////////// //
ARENA METHODS
// ///////////////////////////////////////////////////////////////////// */
/**
* Starts the current MobArena session.
*/
public static void startArena()
{
isRunning = true;
for (Player p : playerSet)
{
p.teleport(arenaLoc);
rewardMap.put(p,"");
}
MASpawnThread thread = new MASpawnThread();
plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin,thread,100,400);
tellAll("Let the slaughter begin!");
}
/**
* Ends the current MobArena session.
* Clears the arena floor, gives all the players their rewards,
* and stops the spawning of monsters.
*/
public static void endArena()
{
isRunning = false;
server.getScheduler().cancelTasks(plugin);
killMonsters();
clearBlocks();
giveRewards();
// TO-DO: Fix this, maybe add a Set<Player> dead
tellAll("Arena finished.");
}
/**
* Attempts to let a player join the arena session.
* Players must have an empty inventory to join the arena. Their
* location will be stored for when they leave.
*/
public static void playerJoin(Player p)
{
if (!isSetup)
{
tellPlayer(p, "MobArena has not been set up yet!");
return;
}
if (playerSet.contains(p))
{
tellPlayer(p, "You are already playing!");
return;
}
if (isRunning)
{
tellPlayer(p, "Arena in progress. Type /marena spectate to watch.");
return;
}
if (!MAUtils.hasEmptyInventory(p))
{
tellPlayer(p, "You must empty your inventory to join the arena.");
return;
}
playerSet.add(p);
if (!locationMap.keySet().contains(p))
{
locationMap.put(p, p.getLocation());
}
p.teleport(lobbyLoc);
tellPlayer(p, "You joined the arena. Have fun!");
}
/**
* Attempts to remove a player from the arena session.
* The player is teleported back to his previous location, and
* is removed from all the sets and maps.
*/
public static void playerLeave(Player p)
{
if (!locationMap.keySet().contains(p))
{
tellPlayer(p, "You are not in the arena.");
return;
}
MAUtils.clearInventory(p);
if (playerSet.contains(p))
playerSet.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();
tellPlayer(p, "You left the arena. Thanks for playing!");
}
/**
* Adds a joined arena player to the set of ready players.
*/
public static void playerReady(Player p)
{
readySet.add(p);
if (readySet.equals(playerSet))
{
readySet.clear();
startArena();
}
}
/**
* Removes a dead player from the arena session.
* The player is teleported safely back to the spectator area,
* and their health is restored. All sets and maps are updated.
* If this was the last player alive, the arena session ends.
*/
public static void playerDeath(Player p)
{
p.teleport(spectatorLoc);
MAUtils.clearInventory(p);
p.setHealth(20);
tellAll(p.getName() + " died!");
if (playerSet.contains(p))
playerSet.remove(p);
if (classMap.keySet().contains(p))
classMap.remove(p);
if (isRunning && playerSet.isEmpty())
endArena();
}
/**
* Lets a player spectate the current arena session.
*/
public static void playerSpectate(Player p)
{
if (!playerSet.contains(p))
{
p.teleport(spectatorLoc);
tellPlayer(p, "Enjoy the show!");
}
else
{
tellPlayer(p, "Can't spectate when in the arena!");
}
}
/**
* Prints the list of players currently in the arena session.
*/
public static void playerList(Player p)
{
if (playerSet.isEmpty())
{
tellPlayer(p, "There is no one in the arena right now.");
return;
}
String list = "";
for (Player player : playerSet)
{
list += player.getName() + ", ";
}
list = list.substring(0,list.length()-2);
tellPlayer(p, "Survivors: " + list);
}
/* ///////////////////////////////////////////////////////////////////// //
CLEANUP METHODS
// ///////////////////////////////////////////////////////////////////// */
/**
* Kills all monsters currently on the arena floor.
*/
public static void killMonsters()
{
// Remove all monsters, then clear the Set.
for (LivingEntity entity : monsterSet)
{
if (!entity.isDead())
entity.remove();
}
monsterSet.clear();
}
/**
* Removes all the blocks on the arena floor.
*/
public static void clearBlocks()
{
// Remove all blocks, then clear the Set.
for (Block b : blockSet)
{
b.setType(Material.AIR);
}
blockSet.clear();
}
/* ///////////////////////////////////////////////////////////////////// //
CLASS AND REWARD METHODS
// ///////////////////////////////////////////////////////////////////// */
/**
* Assigns a class to the player.
*/
public static void assignClass(Player p, String className)
{
classMap.put(p, className);
giveClassItems(p);
}
/**
* Grant a player their class-specific items.
*/
public static void giveClassItems(Player p)
{
String className = classMap.get(p);
String classItems = classItemMap.get(className);
String classArmor = classArmorMap.get(className);
MAUtils.giveItems(p, classItems, classArmor);
}
/**
* Gives all the players the rewards they earned.
*/
public static void giveRewards()
{
for (Player p : rewardMap.keySet())
{
String r = rewardMap.get(p);
if (r.equals("")) continue;
tellPlayer(p, "You're gonna get some shit now, so be happy!");
MAUtils.giveItems(p, r);
}
rewardMap.clear();
}
/* ///////////////////////////////////////////////////////////////////// //
MISC METHODS
// ///////////////////////////////////////////////////////////////////// */
/**
* Sends a message to a player.
*/
public static void tellPlayer(Player p, String msg)
{
p.sendMessage(ChatColor.GREEN + "[MobArena] " + ChatColor.WHITE + msg);
}
/**
* Sends a message to all players in the arena.
*/
public static void tellAll(String msg)
{
for (Player p : playerSet)
{
tellPlayer(p, msg);
}
}
}

View File

@ -0,0 +1,58 @@
package com.garbagemule.MobArena;
import org.bukkit.event.block.BlockListener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.BlockDamageEvent;
/**
* This listener serves as a protection class. Blocks within
* the arena region cannot be destroyed, and blocks can only
* be placed by a participant in the current arena session.
* Any placed blocks will be removed by the cleanup method in
* ArenaManager when the session ends.
*/
public class MABlockListener extends BlockListener
{
private MobArena plugin;
public MABlockListener(MobArena instance)
{
plugin = instance;
}
public void onBlockDamage(BlockDamageEvent event)
{
if (!ArenaManager.isSetup)
return;
if (MAUtils.inRegion(event.getBlock().getLocation()))
event.setCancelled(true);
}
public void onBlockBreak(BlockBreakEvent event)
{
if (!ArenaManager.isSetup)
return;
if (MAUtils.inRegion(event.getBlock().getLocation()))
event.setCancelled(true);
}
public void onBlockPlace(BlockPlaceEvent event)
{
if (!ArenaManager.isSetup)
return;
if (MAUtils.inRegion(event.getBlock().getLocation()))
{
if (ArenaManager.isRunning && ArenaManager.playerSet.contains(event.getPlayer()))
{
ArenaManager.blockSet.add(event.getBlock());
return;
}
event.setCancelled(true);
}
}
}

View File

@ -0,0 +1,175 @@
package com.garbagemule.MobArena;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.CommandExecutor;
public class MACommands implements CommandExecutor
{
/**
* Handles all command parsing.
* Unrecognized commands return false, giving the sender a list of
* valid commands (from plugin.yml).
*/
public boolean onCommand(CommandSender sender, Command command, String commandLabel, String[] args)
{
// Only accept commands from players.
if ((sender == null) || !(sender instanceof Player))
{
System.out.println("Only players can use these commands, silly.");
return true;
}
// Cast the sender to a Player object.
Player p = (Player) sender;
/* If more than one argument, must be an advanced command.
* Only allow operators to access these commands. */
if (args.length > 1)
{
if (p.isOp())
return advancedCommands(p, args);
ArenaManager.tellPlayer(p, "Must be operator for advanced commands.");
return true;
}
// If not exactly one argument, must be an invalid command.
if (args.length != 1)
return false;
// Exactly one argument, return whatever simpleCommands returns.
return basicCommands(p, args[0].toLowerCase());
}
/**
* Handles basic commands.
*/
private boolean basicCommands(Player p, String cmd)
{
if (cmd.equals("join") || cmd.equals("j"))
{
ArenaManager.playerJoin(p);
return true;
}
if (cmd.equalsIgnoreCase("leave") || cmd.equalsIgnoreCase("l"))
{
ArenaManager.playerLeave(p);
return true;
}
if (cmd.equalsIgnoreCase("list") || cmd.equalsIgnoreCase("who"))
{
ArenaManager.playerList(p);
return true;
}
if (cmd.equalsIgnoreCase("spectate") || cmd.equalsIgnoreCase("spec"))
{
ArenaManager.playerSpectate(p);
return true;
}
return false;
}
/**
* Handles advanced commands, mainly for setting up the arena.
*/
private boolean advancedCommands(Player p, String[] args)
{
String cmd = args[0].toLowerCase();
String arg = args[1].toLowerCase();
// ma setwarp arena/lobby/spectator
if (cmd.equals("setwarp"))
{
if (!arg.equals("arena") && !arg.equals("lobby") && !arg.equals("spectator"))
return false;
// Write the coordinate data to the config-file.
MAUtils.setCoords(arg, p.getLocation());
ArenaManager.tellPlayer(p, "Warp point \"" + arg + "\" set.");
return true;
}
// ma addspawn <name>
if (cmd.equals("addspawn"))
{
// The name must start with a letter, followed by any letter(s) or number(s).
if (!arg.matches("[a-z]+([[0-9][a-z]])*"))
{
ArenaManager.tellPlayer(p, "Name must consist of only letters a-z and numbers 0-9");
return true;
}
// Write the coordinate data to the config-file.
MAUtils.setCoords("spawnpoints." + arg, p.getLocation());
ArenaManager.tellPlayer(p, "Spawn point with name \"" + arg + "\" added.");
return true;
}
// ma delspawn <name>
if (cmd.equals("delspawn"))
{
// The name must start with a letter, followed by any letter(s) or number(s).
if (!arg.matches("[a-z]+([[0-9][a-z]])*"))
{
ArenaManager.tellPlayer(p, "Name must consist of only letters a-z and numbers 0-9");
return true;
}
// If the spawnpoint does not exist, notify the player.
if (MAUtils.getCoords("spawnpoints." + arg) == null)
{
ArenaManager.tellPlayer(p, "Couldn't find spawnpoint \"" + arg + "\".");
return true;
}
MAUtils.delCoords("spawnpoints." + arg);
ArenaManager.tellPlayer(p, "Spawn point with name \"" + arg + "\" removed.");
return true;
}
// ma setregionpoint p1/p2
if (cmd.equalsIgnoreCase("setregion"))
{
if (arg.equals("p1") || arg.equals("p2"))
{
MAUtils.setCoords(arg, p.getLocation());
MAUtils.fixCoords();
ArenaManager.tellPlayer(p, "Region point \"" + arg + "\" set.");
return true;
}
ArenaManager.tellPlayer(p, "/ma setregionpoint p1, or /ma setregionpoint p2");
return true;
}
// ma expandregion up/down/out <number>
if (cmd.equalsIgnoreCase("expandregion"))
{
if (arg.equals("up") || arg.equals("down") || arg.equals("out"))
{
if (args.length != 3 || !args[2].matches("[0-9]+"))
return false;
int i = Integer.parseInt(args[2]);
MAUtils.expandRegion(arg, i);
ArenaManager.tellPlayer(p, "Region expanded " + arg + " by " + i + " blocks.");
return true;
}
ArenaManager.tellPlayer(p, "Region point \"" + arg + "\" set.");
return true;
}
return false;
}
}

View File

@ -0,0 +1,24 @@
package com.garbagemule.MobArena;
import org.bukkit.event.entity.EntityListener;
import org.bukkit.event.entity.EntityExplodeEvent;
/**
* Very simple listener for preventing Creeper explosions from
* damaging the blocks of the arena.
*/
public class MACreeperListener extends EntityListener
{
private MobArena plugin;
public MACreeperListener(MobArena instance)
{
plugin = instance;
}
public void onEntityExplode(EntityExplodeEvent event)
{
if (MAUtils.inRegion(event.getLocation()))
event.setCancelled(true);
}
}

View File

@ -0,0 +1,44 @@
package com.garbagemule.MobArena;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityListener;
import org.bukkit.event.entity.EntityDamageEvent;
/**
* This listener acts as a type of death-listener.
* When a player is sufficiently low on health, and the next
* damaging blow will kill them, they are teleported to the
* spectator area, they have their hearts replenished, and all
* their items are stripped from them.
* By the end of the arena session, the rewards are given.
*/
// 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)
{
if (!ArenaManager.isRunning)
return;
if (!(event.getEntity() instanceof Player))
return;
Player p = (Player) event.getEntity();
if (!ArenaManager.playerSet.contains(p))
return;
if (p.getHealth() > event.getDamage())
return;
event.setCancelled(true);
ArenaManager.playerDeath(p);
}
}

View File

@ -0,0 +1,34 @@
package com.garbagemule.MobArena;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerBucketEmptyEvent;
/**
* This listener prevents players from sharing class-specific
* items (read: cheating) before the arena session starts.
*/
// TO-DO: Merge with MASignListener and MAReadyListener into MALobbyListener
public class MADropListener extends PlayerListener
{
private MobArena plugin;
public MADropListener(MobArena instance)
{
plugin = instance;
}
public void onPlayerDropItem(PlayerDropItemEvent event)
{
Player p = event.getPlayer();
if (ArenaManager.playerSet.contains(p))
{
if (ArenaManager.isRunning)
return;
ArenaManager.tellPlayer(p, "No sharing before the arena starts!");
event.setCancelled(true);
}
}
}

View File

@ -0,0 +1,41 @@
package com.garbagemule.MobArena;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerInteractEvent;
/**
* This listener flags players as ready, if they are in the arena
* session, and hit an iron block (id: 42).
*/
// TO-DO: Merge with MASignListener and MADropListener into MALobbyListener
// TO-DO: Let server host decide which type of block is the "readyblock".
public class MAReadyListener extends PlayerListener
{
private MobArena plugin;
public MAReadyListener(MobArena instance)
{
plugin = instance;
}
public void onPlayerInteract(PlayerInteractEvent event)
{
Player p = event.getPlayer();
if (ArenaManager.playerSet.contains(p))
{
if ((event.hasBlock()) && (event.getClickedBlock().getTypeId() == 42))
{
if (ArenaManager.classMap.containsKey(p))
{
ArenaManager.tellPlayer(p, "You have been flagged as ready!");
ArenaManager.playerReady(p);
}
else
{
ArenaManager.tellPlayer(p, "You must first pick a class!");
}
}
}
}
}

View File

@ -0,0 +1,62 @@
package com.garbagemule.MobArena;
import org.bukkit.block.Sign;
import org.bukkit.event.Event.Result;
import org.bukkit.event.block.Action;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerInteractEvent;
/**
* This listener handles the class assignments. When a player in
* the arena session hits a class sign, they will be given their
* class-specific items.
*/
// TO-DO: Merge with MAReadyListener and MADropListener into MALobbyListener
public class MASignListener extends PlayerListener
{
private MobArena plugin;
public MASignListener(MobArena instance)
{
plugin = instance;
}
public void onPlayerInteract(PlayerInteractEvent event)
{
// Only do these checks if the arena isn't running.
if (!ArenaManager.isRunning)
{
Action a = event.getAction();
Player p = event.getPlayer();
// Check if player is trying to use an item.
// TO-DO: Find a way to allow right-click. Perhaps just remove the return;
if ((a == Action.RIGHT_CLICK_AIR) || (a == Action.RIGHT_CLICK_BLOCK))
{
if (ArenaManager.playerSet.contains(p))
event.setUseItemInHand(Result.DENY);
return;
}
// Check if the clicked block is one of the class signs.
if ((event.hasBlock()) && (event.getClickedBlock().getState() instanceof Sign))
{
// Cast the block to a sign to get the text on it.
Sign sign = (Sign) event.getClickedBlock().getState();
if (ArenaManager.playerSet.contains(p))
{
// Check if the first line of the sign is a class name.
String className = sign.getLine(0);
if (ArenaManager.classes.contains(className))
{
// Set the player's class.
ArenaManager.assignClass(p, className);
ArenaManager.tellPlayer(p, "You have chosen " + className + " as your class!");
}
}
}
}
}
}

View File

@ -0,0 +1,181 @@
package com.garbagemule.MobArena;
import java.util.List;
import java.util.Random;
import org.bukkit.Location;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Player;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.CreatureType;
/**
* Core class for handling wave spawning.
* Currently, every 4th wave is a special wave, and all other waves
* are default waves. The distribution coefficients are used to spread
* out the distribution of each default monster however the server
* host chooses. It is possible to create default waves that consist of
* only one type of monster, or ones that have no creepers, for example.
*/
// TO-DO: Allow custom special wave modulus.
// TO-DO: Allow custom special wave monsters.
// TO-DO: Allow additional "default" waves.
// TO-DO:
public class MASpawnThread implements Runnable
{
private int wave, noOfSpawnPoints, noOfPlayers;
private int dZombies, dSkeletons, dSpiders, dCreepers;
private Random random;
public MASpawnThread()
{
noOfSpawnPoints = ArenaManager.spawnpoints.size();
noOfPlayers = ArenaManager.playerSet.size();
wave = 1;
random = new Random();
// Set up the distribution variables for the random spawner.
dZombies = ArenaManager.dZombies;
dSkeletons = dZombies + ArenaManager.dSkeletons;
dSpiders = dSkeletons + ArenaManager.dSpiders;
dCreepers = dSpiders + ArenaManager.dCreepers;
}
public void run()
{
String reward;
String currentRewards;
// Check if we need to grant more rewards with the recurrent waves.
for (Integer i : ArenaManager.everyWaveMap.keySet())
{
if (wave % i != 0)
continue;
for (Player p : ArenaManager.playerSet)
{
currentRewards = ArenaManager.rewardMap.get(p);
reward = MAUtils.getRandomReward(ArenaManager.everyWaveMap.get(i));
currentRewards += reward + ",";
ArenaManager.rewardMap.put(p, currentRewards);
ArenaManager.tellPlayer(p, "You just earned a reward: " + reward);
}
}
// Same deal, this time with the one-time waves.
if (ArenaManager.afterWaveMap.containsKey(wave))
{
for (Player p : ArenaManager.playerSet)
{
currentRewards = ArenaManager.rewardMap.get(p);
reward = MAUtils.getRandomReward(ArenaManager.afterWaveMap.get(wave));
currentRewards += reward + ",";
ArenaManager.rewardMap.put(p, currentRewards);
ArenaManager.tellPlayer(p, "You just earned a reward: " + reward);
}
}
// Check if this is a special wave.
// TO-DO: Get this value from the config-file.
if (wave % 4 == 0)
{
ArenaManager.tellAll("Get ready for wave #" + wave + "! [SPECIAL]");
specialWave();
}
else
{
ArenaManager.tellAll("Get ready for wave #" + wave + "!");
defaultWave();
}
wave++;
}
/**
* Spawns a default wave of monsters.
*/
private void defaultWave()
{
Location loc;
int ran;
for (int i = 0; i < wave+noOfPlayers; i++)
{
loc = ArenaManager.spawnpoints.get(random.nextInt(noOfSpawnPoints));
ran = random.nextInt(dCreepers);
CreatureType mob;
/* Because of the nature of the if-elseif-else statement,
* we're able to evaluate the random number in this way.
* If dSpiders = 0, then dSpiders = dSkeletons, which
* means if the random number is below that value, we will
* spawn a skeleton and break out of the statement. */
if (ran < dZombies) mob = CreatureType.ZOMBIE;
else if (ran < dSkeletons) mob = CreatureType.SKELETON;
else if (ran < dSpiders) mob = CreatureType.SPIDER;
else if (ran < dCreepers) mob = CreatureType.CREEPER;
else continue;
LivingEntity e = ArenaManager.world.spawnCreature(loc,mob);
ArenaManager.monsterSet.add(e);
}
}
/**
* Spawns a special wave of monsters.
*/
private void specialWave()
{
Location loc;
CreatureType mob;
int count;
boolean lightning = false;
boolean slime = false;
switch (random.nextInt(4))
{
case 0:
mob = CreatureType.CREEPER;
count = noOfPlayers * 3;
lightning = true;
break;
case 1:
mob = CreatureType.PIG_ZOMBIE;
count = noOfPlayers * 2;
break;
case 2:
mob = CreatureType.SLIME;
count = noOfPlayers * 5;
slime = true;
break;
case 3:
mob = CreatureType.MONSTER;
count = Math.max(2, noOfPlayers);
break;
case 4:
mob = CreatureType.GHAST;
count = Math.max(1, noOfPlayers - 2);
break;
default:
mob = CreatureType.CHICKEN;
count = 50;
break;
}
for (int i = 0; i < count; i++)
{
loc = ArenaManager.spawnpoints.get(random.nextInt(noOfSpawnPoints));
LivingEntity e = ArenaManager.world.spawnCreature(loc,mob);
if (lightning)
{
ArenaManager.world.strikeLightningEffect(loc);
e.setFireTicks(0);
e.setHealth(20);
}
if (slime) ((Slime)e).setSize(2);
ArenaManager.monsterSet.add(e);
}
}
}

View File

@ -0,0 +1,40 @@
package com.garbagemule.MobArena;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerTeleportEvent;
/**
* This listener prevents players from warping out of the arena, if
* they are in the arena 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))
{
Location to = event.getTo();
if (ArenaManager.arenaLoc.equals(to) ||
ArenaManager.lobbyLoc.equals(to) ||
ArenaManager.spectatorLoc.equals(to))
{
return;
}
ArenaManager.tellPlayer(p, "Can't warp in arena! To leave, type /marena leave");
event.setCancelled(true);
}
}
}

View File

@ -0,0 +1,486 @@
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.List;
import java.util.LinkedList;
import java.util.Map;
import java.util.HashMap;
import java.util.Random;
import org.bukkit.World;
import org.bukkit.Material;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.util.config.Configuration;
public class MAUtils
{
/* ///////////////////////////////////////////////////////////////////// //
INVENTORY AND REWARD METHODS
// ///////////////////////////////////////////////////////////////////// */
/* Clears the players inventory and armor slots. */
public static PlayerInventory clearInventory(Player p)
{
PlayerInventory inv = p.getInventory();
inv.clear();
inv.setHelmet(null);
inv.setChestplate(null);
inv.setLeggings(null);
inv.setBoots(null);
return inv;
}
/* Checks if all inventory and armor slots are empty. */
public static boolean hasEmptyInventory(Player player)
{
ItemStack[] inventory = player.getInventory().getContents();
ItemStack[] armor = player.getInventory().getArmorContents();
// For inventory, check for null
for (ItemStack stack : inventory)
if (stack != null) return false;
// For armor, check for id 0, or AIR
for (ItemStack stack : armor)
if (stack.getTypeId() != 0) return false;
return true;
}
/* Gives all the items in the input string(s) to the player */
public static void giveItems(Player p, String... strings)
{
// Variables used.
ItemStack stack;
int index, id, amount;
PlayerInventory inv = clearInventory(p);
for (String s : strings)
{
/* Trim the list, remove possible trailing commas, split by
* commas, and start the item loop. */
s = s.trim();
if (s.endsWith(","))
s = s.substring(0, s.length()-1);
String[] items = s.split(",");
// For every item in the list
for (String i : items)
{
/* Take into account possible amount, and if there is
* one, set the amount variable to that amount, else 1. */
i = i.trim();
String[] item = i.split(":");
if (item.length == 2 && item[1].matches("[0-9]+"))
amount = Integer.parseInt(item[1]);
else
amount = 1;
// Create ItemStack with appropriate constructor.
if (item[0].matches("[0-9]+"))
{
id = Integer.parseInt(item[0]);
stack = new ItemStack(id, amount);
}
else
{
stack = makeItemStack(item[0], amount);
if (stack == null) continue;
}
// Put the item in the first empty inventory slot.
index = inv.firstEmpty();
inv.setItem(index,stack);
}
}
}
/* Helper method for grabbing a random reward */
public static String getRandomReward(String rewardlist)
{
Random ran = new Random();
String[] rewards = rewardlist.split(",");
String item = rewards[ran.nextInt(rewards.length)];
return item.trim();
}
/* Helper method for making an ItemStack out of a string */
private static ItemStack makeItemStack(String s, int amount)
{
Material mat;
try
{
mat = Material.valueOf(s.toUpperCase());
return new ItemStack(mat, amount);
}
catch (Exception e)
{
System.out.println("[MobArena] ERROR! Could not create item " + s + ". Check config.yml");
return null;
}
}
/* ///////////////////////////////////////////////////////////////////// //
INITIALIZATION METHODS
// ///////////////////////////////////////////////////////////////////// */
/**
* Creates a Configuration object from the config.yml file.
*/
public static Configuration getConfig()
{
new File("plugins/MobArena").mkdir();
File configFile = new File("plugins/MobArena/config.yml");
if(!configFile.exists())
{
try
{
configFile.createNewFile();
}
catch(Exception e)
{
System.out.println("[MobArena] ERROR: Config file could not be created.");
return null;
}
}
return new Configuration(configFile);
}
/**
* Grabs the world from the config-file, or the "default" world
* from the list of worlds in the server object.
*/
public static World getWorld()
{
Configuration c = ArenaManager.config;
c.load();
String world = c.getString("world");
if (world == null)
return ArenaManager.server.getWorlds().get(0);
return ArenaManager.server.getWorld(world);
}
/**
* Grabs the list of classes from the config-file. If no list is
* found, generate a set of default classes.
*/
public static List<String> getClasses()
{
Configuration c = ArenaManager.config;
c.load();
if (c.getKeys("classes") == null)
{
c.setProperty("classes.Archer.items", "wood_sword, bow, arrow:64, arrow:64, grilled_pork");
c.setProperty("classes.Archer.armor", "298,299,300,301");
c.setProperty("classes.Knight.items", "diamond_sword, grilled_pork");
c.setProperty("classes.Knight.armor", "306,307,308,309");
c.setProperty("classes.Tank.items", "iron_sword, grilled_pork:2");
c.setProperty("classes.Tank.armor", "310,311,312,313");
c.setProperty("classes.Oddjob.items", "stone_sword, flint_and_steal, netherrack:2, wood_door, 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");
c.save();
}
return c.getKeys("classes");
}
/**
* Generates a map of class names and class items based on the
* type of items ("items" or "armor") and the config-file.
* Will explode if the classes aren't well-defined.
*/
public static Map<String,String> getClassItems(String type)
{
Configuration c = ArenaManager.config;
c.load();
Map<String,String> result = new HashMap<String,String>();
// Assuming well-defined classes.
List<String> classes = c.getKeys("classes");
for (String s : classes)
{
result.put(s, c.getString("classes." + s + "." + type, null));
}
return result;
}
/**
* Generates a map of wave numbers and rewards based on the
* 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<Integer,String> getWaveMap(String type)
{
Configuration c = ArenaManager.config;
c.load();
// Set up variables and resulting map.
Map<Integer,String> result = new HashMap<Integer,String>();
int wave;
String rewards;
/* Check if the keys exist in the config-file, if not,
* simply return the empty map. */
List<String> waves = c.getKeys("rewards.waves." + type);
if (waves == null)
return result;
// Else, put all the rewards in the map.
for (String n : waves)
{
if (!n.matches("[0-9]+"))
continue;
wave = Integer.parseInt(n);
rewards = c.getString("rewards.waves." + type + "." + n);
result.put(wave,rewards);
}
// And return the resulting map.
return result;
}
/**
* Grabs all the spawnpoints from the config-file. IF no points
* are found, an empty list is returned.
*/
public static List<Location> getSpawnPoints()
{
Configuration c = ArenaManager.config;
c.load();
List<String> spawnpoints = c.getKeys("coords.spawnpoints");
if (spawnpoints == null)
return new LinkedList<Location>();
List<Location> result = new LinkedList<Location>();
for (String s : spawnpoints)
{
Location loc = getCoords("spawnpoints." + s);
if (loc != null)
result.add(loc);
}
return result;
}
/**
* Grabs the distribution coefficients from the config-file. If
* no coefficients are found, defaults (10) are added.
*/
public static int getDistribution(String monster)
{
Configuration c = ArenaManager.config;
c.load();
if (c.getInt("waves.default." + monster, -1) == -1)
{
c.setProperty("waves.default." + monster, 10);
c.save();
}
return c.getInt("waves.default." + monster, -1);
}
/* ///////////////////////////////////////////////////////////////////// //
REGION AND SETUP METHODS
// ///////////////////////////////////////////////////////////////////// */
/**
* Checks if the Location object is within the arena region.
*/
public static boolean inRegion(Location loc)
{
Location p1 = ArenaManager.p1;
Location p2 = ArenaManager.p2;
// Return false if the location is outside of the region.
if ((loc.getX() < p1.getX()) || (loc.getX() > p2.getX()))
return false;
if ((loc.getZ() < p1.getZ()) || (loc.getZ() > p2.getZ()))
return false;
if ((loc.getY() < p1.getY()) || (loc.getY() > p2.getY()))
return false;
return true;
}
/**
* Writes coordinate information to the config-file.
*/
public static void setCoords(String name, Location loc)
{
Configuration c = ArenaManager.config;
c.load();
c.setProperty("coords." + name + ".world", loc.getWorld().getName());
c.setProperty("coords." + name + ".x", loc.getX());
c.setProperty("coords." + name + ".y", loc.getY());
c.setProperty("coords." + name + ".z", loc.getZ());
c.setProperty("coords." + name + ".yaw", loc.getYaw());
c.setProperty("coords." + name + ".pitch", loc.getPitch());
c.save();
ArenaManager.updateVariables();
}
/**
* Removes coordinate information from the config-file.
*/
public static void delCoords(String name)
{
Configuration c = ArenaManager.config;
c.load();
c.removeProperty(name);
c.save();
ArenaManager.updateVariables();
}
/**
* Grabs coordinate information from the config-file.
*/
public static Location getCoords(String name)
{
Configuration c = ArenaManager.config;
c.load();
// Return null if coords aren't in the config file.
if (c.getKeys("coords." + name) == null)
return null;
double x = c.getDouble("coords." + name + ".x", 0);
double y = c.getDouble("coords." + name + ".y", 0);
double z = c.getDouble("coords." + name + ".z", 0);
return new Location(ArenaManager.world, x, y, z);
}
/**
* Maintains the invariant that p1's coordinates are of lower
* values than their respective counter-parts of p2. Makes the
* inRegion()-method much faster/easier.
*/
public static void fixCoords()
{
Location p1 = getCoords("p1");
Location p2 = getCoords("p2");
double tmp;
if (p1 == null || p2 == null)
return;
if (p1.getX() > p2.getX())
{
tmp = p1.getX();
p1.setX(p2.getX());
p2.setX(tmp);
}
if (p1.getY() > p2.getY())
{
tmp = p1.getY();
p1.setY(p2.getY());
p2.setY(tmp);
}
if (p1.getZ() > p2.getZ())
{
tmp = p1.getZ();
p1.setZ(p2.getZ());
p2.setZ(tmp);
}
setCoords("p1", p1);
setCoords("p2", p2);
}
/**
* Expands the arena region either upwards, downwards, or
* outwards (meaning on both the X and Z axes).
*/
public static void expandRegion(String direction, int i)
{
Location p1 = ArenaManager.p1;
Location p2 = ArenaManager.p2;
if (direction.equals("up"))
p2.setY(p2.getY() + i);
else if (direction.equals("down"))
p1.setY(p1.getY() - i);
else if (direction.equals("out"))
{
p1.setX(p1.getX() - i);
p1.setZ(p1.getZ() - i);
p2.setX(p2.getX() + i);
p2.setZ(p2.getZ() + i);
}
setCoords("p1", p1);
setCoords("p2", p2);
fixCoords();
}
/* ///////////////////////////////////////////////////////////////////// //
VERIFICATION METHODS
// ///////////////////////////////////////////////////////////////////// */
/**
* Verifies that all important variables are declared. Returns true
* if, and only if, the warppoints, region, distribution coefficients,
* classes and spawnpoints are all set up.
*/
public static boolean verifyData()
{
return ((ArenaManager.arenaLoc != null) &&
(ArenaManager.lobbyLoc != null) &&
(ArenaManager.spectatorLoc != null) &&
(ArenaManager.p1 != null) &&
(ArenaManager.p2 != null) &&
(ArenaManager.dZombies != -1) &&
(ArenaManager.dSkeletons != -1) &&
(ArenaManager.dSpiders != -1) &&
(ArenaManager.dCreepers != -1) &&
(ArenaManager.classes.size() > 0) &&
(ArenaManager.spawnpoints.size() > 0));
}
}

View File

@ -0,0 +1,65 @@
package com.garbagemule.MobArena;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Priority;
import org.bukkit.event.block.BlockListener;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.entity.EntityListener;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.PluginManager;
/**
* MobArena
*
* @author garbagemule
*/
public class MobArena extends JavaPlugin
{
public MobArena()
{
}
public void onEnable()
{
PluginDescriptionFile pdfFile = this.getDescription();
System.out.println(pdfFile.getName() + " v" + pdfFile.getVersion() + " enabled." );
// Initialize convenience variables in ArenaManager.
ArenaManager.init(this);
// Bind the /ma and /marena commands to MACommands.
getCommand("ma").setExecutor(new MACommands());
getCommand("marena").setExecutor(new MACommands());
// Create event listeners.
PluginManager pm = getServer().getPluginManager();
PlayerListener signListener = new MASignListener(this);
PlayerListener dropListener = new MADropListener(this);
PlayerListener readyListener = new MAReadyListener(this);
PlayerListener teleportListener = new MATeleportListener(this);
BlockListener blockListener = new MABlockListener(this);
EntityListener creeperListener = new MACreeperListener(this);
EntityListener damageListener = new MADamageListener(this);
// TO-DO: PlayerListener to check for player logout during battle.
// TO-DO: PlayerListener to check for kills/deaths.
// Register events.
pm.registerEvent(Event.Type.PLAYER_INTERACT, signListener, Priority.Normal, this);
pm.registerEvent(Event.Type.PLAYER_DROP_ITEM, dropListener, Priority.Normal, this);
pm.registerEvent(Event.Type.PLAYER_INTERACT, readyListener, Priority.Normal, this);
pm.registerEvent(Event.Type.PLAYER_TELEPORT, teleportListener, 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_PLACE, blockListener, Priority.Normal, this);
pm.registerEvent(Event.Type.ENTITY_EXPLODE, creeperListener, Priority.Normal, this);
pm.registerEvent(Event.Type.ENTITY_DAMAGE, damageListener, Priority.Normal, this);
System.out.println(pdfFile.getName() + " v" + pdfFile.getVersion() + " initialized." );
}
public void onDisable()
{
System.out.println("WAIT! WHAT ARE YOU DOING?!");
}
}

Binary file not shown.

Binary file not shown.