Update for Spigot and mavenize.
This commit is contained in:
@@ -0,0 +1,334 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
|
||||
public class ArenaClass
|
||||
{
|
||||
private String configName, lowercaseName;
|
||||
private ItemStack helmet, chestplate, leggings, boots;
|
||||
private List<ItemStack> items, armor;
|
||||
private Map<String,Boolean> perms;
|
||||
private Map<String,Boolean> lobbyperms;
|
||||
private boolean unbreakableWeapons, unbreakableArmor;
|
||||
private double price;
|
||||
private Location classchest;
|
||||
|
||||
/**
|
||||
* Create a new, empty arena class with the given name.
|
||||
* @param name the class name as it appears in the config-file
|
||||
*/
|
||||
public ArenaClass(String name, double price, boolean unbreakableWeapons, boolean unbreakableArmor) {
|
||||
this.configName = name;
|
||||
this.lowercaseName = name.toLowerCase();
|
||||
|
||||
this.items = new ArrayList<ItemStack>();
|
||||
this.armor = new ArrayList<ItemStack>(4);
|
||||
this.perms = new HashMap<String,Boolean>();
|
||||
this.lobbyperms = new HashMap<String,Boolean>();
|
||||
|
||||
this.unbreakableWeapons = unbreakableWeapons;
|
||||
this.unbreakableArmor = unbreakableArmor;
|
||||
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the arena class as it appears in the config-file.
|
||||
* @return the class name as it appears in the config-file
|
||||
*/
|
||||
public String getConfigName() {
|
||||
return configName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lowercase class name.
|
||||
* @return the lowercase class name
|
||||
*/
|
||||
public String getLowercaseName() {
|
||||
return lowercaseName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Material type of the first item in the items list.
|
||||
* If the items list is empty, the method returns Material.STONE
|
||||
* @return the type of the first item, or STONE if the list is empty
|
||||
*/
|
||||
public Material getLogo() {
|
||||
if (items.isEmpty()) {
|
||||
return Material.STONE;
|
||||
}
|
||||
return items.get(0).getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the helmet slot for the class.
|
||||
* @param helmet an item
|
||||
*/
|
||||
public void setHelmet(ItemStack helmet) {
|
||||
this.helmet = helmet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the chestplate slot for the class.
|
||||
* @param chestplate an item
|
||||
*/
|
||||
public void setChestplate(ItemStack chestplate) {
|
||||
this.chestplate = chestplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the leggings slot for the class.
|
||||
* @param leggings an item
|
||||
*/
|
||||
public void setLeggings(ItemStack leggings) {
|
||||
this.leggings = leggings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the boots slot for the class.
|
||||
* @param boots an item
|
||||
*/
|
||||
public void setBoots(ItemStack boots) {
|
||||
this.boots = boots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to the items list.
|
||||
* @param stack an item
|
||||
*/
|
||||
public void addItem(ItemStack stack) {
|
||||
if (stack == null) return;
|
||||
|
||||
if (stack.getAmount() > 64) {
|
||||
while (stack.getAmount() > 64) {
|
||||
items.add(new ItemStack(stack.getType(), 64));
|
||||
stack.setAmount(stack.getAmount() - 64);
|
||||
}
|
||||
}
|
||||
items.add(stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the current items list with a new list of all the items in the given list.
|
||||
* This method uses the addItem() method for each item to ensure consistency.
|
||||
* @param stacks a list of items
|
||||
*/
|
||||
public void setItems(List<ItemStack> stacks) {
|
||||
this.items = new ArrayList<ItemStack>(stacks.size());
|
||||
for (ItemStack stack : stacks) {
|
||||
addItem(stack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the current armor list with the given list.
|
||||
* @param armor a list of items
|
||||
*/
|
||||
public void setArmor(List<ItemStack> armor) {
|
||||
this.armor = armor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grants all of the class items and armor to the given player.
|
||||
* The normal items will be added to the inventory normally, while the
|
||||
* armor items will be verified as armor items and placed in their
|
||||
* appropriate slots. If any specific armor slots are specified, they
|
||||
* will overwrite any items in the armor list.
|
||||
* @param p a player
|
||||
*/
|
||||
public void grantItems(Player p) {
|
||||
PlayerInventory inv = p.getInventory();
|
||||
|
||||
// Fork over the items.
|
||||
for (ItemStack stack : items) {
|
||||
inv.addItem(stack);
|
||||
}
|
||||
|
||||
// Check for legacy armor-node items
|
||||
if (!armor.isEmpty()) {
|
||||
for (ItemStack piece : armor) {
|
||||
ArmorType type = ArmorType.getType(piece);
|
||||
if (type == null) continue;
|
||||
|
||||
switch (type) {
|
||||
case HELMET:
|
||||
inv.setHelmet(piece);
|
||||
break;
|
||||
case CHESTPLATE:
|
||||
inv.setChestplate(piece);
|
||||
break;
|
||||
case LEGGINGS:
|
||||
inv.setLeggings(piece);
|
||||
break;
|
||||
case BOOTS:
|
||||
inv.setBoots(piece);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check type specifics.
|
||||
if (helmet != null) inv.setHelmet(helmet);
|
||||
if (chestplate != null) inv.setChestplate(chestplate);
|
||||
if (leggings != null) inv.setLeggings(leggings);
|
||||
if (boots != null) inv.setBoots(boots);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a permission value to the class.
|
||||
* @param perm the permission
|
||||
* @param value the value
|
||||
*/
|
||||
public void addPermission(String perm, boolean value) {
|
||||
perms.put(perm, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an unmodifiable map of permissions and values for the class.
|
||||
* @return a map of permissions and values
|
||||
*/
|
||||
public Map<String,Boolean> getPermissions() {
|
||||
return Collections.unmodifiableMap(perms);
|
||||
}
|
||||
|
||||
public void addLobbyPermission(String perm, boolean value) {
|
||||
lobbyperms.put(perm, value);
|
||||
}
|
||||
|
||||
public Map<String,Boolean> getLobbyPermissions() {
|
||||
return Collections.unmodifiableMap(lobbyperms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grant the given player all the permissions of the class.
|
||||
* All permissions will be attached to a PermissionAttachment object, which
|
||||
* will be returned to the caller.
|
||||
* @param plugin a MobArena instance
|
||||
* @param p a player
|
||||
* @return the PermissionAttachment with all the permissions
|
||||
*/
|
||||
public PermissionAttachment grantPermissions(MobArena plugin, Player p) {
|
||||
if (perms.isEmpty()) return null;
|
||||
|
||||
PermissionAttachment pa = p.addAttachment(plugin);
|
||||
grantPerms(pa, perms, p);
|
||||
return pa;
|
||||
}
|
||||
|
||||
public PermissionAttachment grantLobbyPermissions(MobArena plugin, Player p) {
|
||||
if (lobbyperms.isEmpty()) return null;
|
||||
|
||||
PermissionAttachment pa = p.addAttachment(plugin);
|
||||
grantPerms(pa, lobbyperms, p);
|
||||
return pa;
|
||||
}
|
||||
|
||||
private void grantPerms(PermissionAttachment pa, Map<String,Boolean> map, Player p) {
|
||||
for (Entry<String,Boolean> entry : map.entrySet()) {
|
||||
try {
|
||||
pa.setPermission(entry.getKey(), entry.getValue());
|
||||
}
|
||||
catch (Exception e) {
|
||||
String perm = entry.getKey() + ":" + entry.getValue();
|
||||
String player = p.getName();
|
||||
|
||||
Messenger.warning("[PERM00] Failed to attach permission '" + perm + "' to player '" + player + " with class " + this.configName
|
||||
+ "'.\nPlease verify that your class permissions are well-formed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Location getClassChest() {
|
||||
return classchest;
|
||||
}
|
||||
|
||||
public void setClassChest(Location loc) {
|
||||
classchest = loc;
|
||||
}
|
||||
|
||||
public boolean hasUnbreakableWeapons() {
|
||||
return unbreakableWeapons;
|
||||
}
|
||||
|
||||
public boolean hasUnbreakableArmor() {
|
||||
return unbreakableArmor;
|
||||
}
|
||||
|
||||
public double getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by isWeapon() to determine if an ItemStack is a weapon type.
|
||||
*/
|
||||
private static int[] weaponTypes = {256,257,258,259,261,267,268,269,270,271,272,273,274,275,276,277,278,279,283,284,285,286,290,291,292,293,294,346,398};
|
||||
|
||||
/**
|
||||
* Returns true, if the ItemStack appears to be a weapon, in which case
|
||||
* the addItem() method will set the weapon durability to the absolute
|
||||
* maximum, as to give them "infinite" durability.
|
||||
* @param stack an ItemStack
|
||||
* @return true, if the item is a weapon
|
||||
*/
|
||||
public static boolean isWeapon(ItemStack stack) {
|
||||
if (stack == null) return false;
|
||||
return Arrays.binarySearch(weaponTypes, stack.getTypeId()) > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by the grantItems() method to determine the armor type of a given
|
||||
* ItemStack. Armor pieces are auto-equipped.
|
||||
* Note: This enum is only necessary for backward-compatibility with the
|
||||
* 'armor'-node.
|
||||
*/
|
||||
public enum ArmorType {
|
||||
HELMET (298,302,306,310,314),
|
||||
CHESTPLATE (299,303,307,311,315),
|
||||
LEGGINGS (300,304,308,312,316),
|
||||
BOOTS (301,305,309,313,317);
|
||||
|
||||
private int[] types;
|
||||
|
||||
private ArmorType(int... types) {
|
||||
this.types = types;
|
||||
}
|
||||
|
||||
public static ArmorType getType(ItemStack stack) {
|
||||
int id = stack.getTypeId();
|
||||
|
||||
for (ArmorType armorType : ArmorType.values()) {
|
||||
for (int type : armorType.types) {
|
||||
if (id == type) {
|
||||
return armorType;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) return false;
|
||||
if (this == o) return true;
|
||||
if (!this.getClass().equals(o.getClass())) return false;
|
||||
|
||||
ArenaClass other = (ArenaClass) o;
|
||||
return other.lowercaseName.equals(this.lowercaseName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return lowercaseName.hashCode();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,661 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
import static com.garbagemule.MobArena.util.config.ConfigUtils.makeSection;
|
||||
import static com.garbagemule.MobArena.util.config.ConfigUtils.parseLocation;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaClass.ArmorType;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.util.ItemParser;
|
||||
import com.garbagemule.MobArena.util.TextUtils;
|
||||
import com.garbagemule.MobArena.util.config.ConfigUtils;
|
||||
|
||||
public class ArenaMasterImpl implements ArenaMaster
|
||||
{
|
||||
private MobArena plugin;
|
||||
private FileConfiguration config;
|
||||
|
||||
private List<Arena> arenas;
|
||||
private Map<Player, Arena> arenaMap;
|
||||
private Arena selectedArena;
|
||||
|
||||
private Map<String, ArenaClass> classes;
|
||||
|
||||
private Set<String> allowedCommands;
|
||||
|
||||
private boolean enabled;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public ArenaMasterImpl(MobArena plugin) {
|
||||
this.plugin = plugin;
|
||||
this.config = plugin.getConfig();
|
||||
|
||||
this.arenas = new ArrayList<Arena>();
|
||||
this.arenaMap = new HashMap<Player, Arena>();
|
||||
|
||||
this.classes = new HashMap<String, ArenaClass>();
|
||||
|
||||
this.allowedCommands = new HashSet<String>();
|
||||
|
||||
this.enabled = config.getBoolean("global-settings.enabled", true);
|
||||
}
|
||||
|
||||
/*
|
||||
* /////////////////////////////////////////////////////////////////////////
|
||||
* // // NEW METHODS IN REFACTORING //
|
||||
* /////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
public MobArena getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean value) {
|
||||
enabled = value;
|
||||
config.set("global-settings.enabled", enabled);
|
||||
}
|
||||
|
||||
public boolean notifyOnUpdates() {
|
||||
return config.getBoolean("global-settings.update-notification", false);
|
||||
}
|
||||
|
||||
public List<Arena> getArenas() {
|
||||
return arenas;
|
||||
}
|
||||
|
||||
public Map<String, ArenaClass> getClasses() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
public void addPlayer(Player p, Arena arena) {
|
||||
arenaMap.put(p, arena);
|
||||
}
|
||||
|
||||
public Arena removePlayer(Player p) {
|
||||
return arenaMap.remove(p);
|
||||
}
|
||||
|
||||
public void resetArenaMap() {
|
||||
arenaMap.clear();
|
||||
}
|
||||
|
||||
public boolean isAllowed(String command) {
|
||||
return allowedCommands.contains(command);
|
||||
}
|
||||
|
||||
/*
|
||||
* /////////////////////////////////////////////////////////////////////////
|
||||
* // // Arena getters //
|
||||
* /////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
public List<Arena> getEnabledArenas() {
|
||||
return getEnabledArenas(arenas);
|
||||
}
|
||||
|
||||
public List<Arena> getEnabledArenas(List<Arena> arenas) {
|
||||
List<Arena> result = new ArrayList<Arena>(arenas.size());
|
||||
for (Arena arena : arenas)
|
||||
if (arena.isEnabled())
|
||||
result.add(arena);
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Arena> getPermittedArenas(Player p) {
|
||||
List<Arena> result = new ArrayList<Arena>(arenas.size());
|
||||
for (Arena arena : arenas)
|
||||
if (plugin.has(p, "mobarena.arenas." + arena.configName()))
|
||||
result.add(arena);
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Arena> getEnabledAndPermittedArenas(Player p) {
|
||||
List<Arena> result = new ArrayList<Arena>(arenas.size());
|
||||
for (Arena arena : arenas)
|
||||
if (arena.isEnabled() && plugin.has(p, "mobarena.arenas." + arena.configName()))
|
||||
result.add(arena);
|
||||
return result;
|
||||
}
|
||||
|
||||
public Arena getArenaAtLocation(Location loc) {
|
||||
for (Arena arena : arenas)
|
||||
if (arena.getRegion().contains(loc))
|
||||
return arena;
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<Arena> getArenasInWorld(World world) {
|
||||
List<Arena> result = new ArrayList<Arena>(arenas.size());
|
||||
for (Arena arena : arenas)
|
||||
if (arena.getWorld().equals(world))
|
||||
result.add(arena);
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Player> getAllPlayers() {
|
||||
List<Player> result = new ArrayList<Player>(arenas.size());
|
||||
for (Arena arena : arenas)
|
||||
result.addAll(arena.getAllPlayers());
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Player> getAllPlayersInArena(String arenaName) {
|
||||
Arena arena = getArenaWithName(arenaName);
|
||||
return (arena != null) ? new ArrayList<Player>(arena.getPlayersInArena()) : new ArrayList<Player>();
|
||||
}
|
||||
|
||||
public List<Player> getAllLivingPlayers() {
|
||||
List<Player> result = new ArrayList<Player>();
|
||||
for (Arena arena : arenas)
|
||||
result.addAll(arena.getPlayersInArena());
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Player> getLivingPlayersInArena(String arenaName) {
|
||||
Arena arena = getArenaWithName(arenaName);
|
||||
return (arena != null) ? new ArrayList<Player>(arena.getPlayersInArena()) : new ArrayList<Player>();
|
||||
}
|
||||
|
||||
public Arena getArenaWithPlayer(Player p) {
|
||||
return arenaMap.get(p);
|
||||
}
|
||||
|
||||
public Arena getArenaWithPlayer(String playerName) {
|
||||
return arenaMap.get(plugin.getServer().getPlayer(playerName));
|
||||
}
|
||||
|
||||
public Arena getArenaWithSpectator(Player p) {
|
||||
for (Arena arena : arenas) {
|
||||
if (arena.getSpectators().contains(p))
|
||||
return arena;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Arena getArenaWithMonster(Entity e) {
|
||||
for (Arena arena : arenas)
|
||||
if (arena.getMonsterManager().getMonsters().contains(e))
|
||||
return arena;
|
||||
return null;
|
||||
}
|
||||
|
||||
public Arena getArenaWithPet(Entity e) {
|
||||
for (Arena arena : arenas)
|
||||
if (arena.hasPet(e))
|
||||
return arena;
|
||||
return null;
|
||||
}
|
||||
|
||||
public Arena getArenaWithName(String configName) {
|
||||
return getArenaWithName(this.arenas, configName);
|
||||
}
|
||||
|
||||
public Arena getArenaWithName(Collection<Arena> arenas, String configName) {
|
||||
for (Arena arena : arenas)
|
||||
if (arena.configName().equals(configName))
|
||||
return arena;
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* /////////////////////////////////////////////////////////////////////////
|
||||
* // // Initialization //
|
||||
* /////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
public void initialize() {
|
||||
loadSettings();
|
||||
loadClasses();
|
||||
loadArenas();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the global settings.
|
||||
*/
|
||||
public void loadSettings() {
|
||||
ConfigurationSection section = plugin.getConfig().getConfigurationSection("global-settings");
|
||||
ConfigUtils.addMissingRemoveObsolete(plugin, "global-settings.yml", section);
|
||||
|
||||
// Grab the commands string
|
||||
String cmds = section.getString("allowed-commands", "");
|
||||
|
||||
// Split by commas
|
||||
String[] parts = cmds.split(",");
|
||||
|
||||
// Add in the /ma command.
|
||||
allowedCommands.add("/ma");
|
||||
|
||||
// Add in each command
|
||||
for (String part : parts) {
|
||||
allowedCommands.add(part.trim().toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all class-related stuff.
|
||||
*/
|
||||
public void loadClasses() {
|
||||
ConfigurationSection section = makeSection(plugin.getConfig(), "classes");
|
||||
ConfigUtils.addIfEmpty(plugin, "classes.yml", section);
|
||||
|
||||
|
||||
// Establish the map.
|
||||
classes = new HashMap<String, ArenaClass>();
|
||||
Set<String> classNames = section.getKeys(false);
|
||||
|
||||
// Load each individual class.
|
||||
for (String className : classNames) {
|
||||
loadClass(className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for loading a single class.
|
||||
*/
|
||||
private ArenaClass loadClass(String classname) {
|
||||
ConfigurationSection section = config.getConfigurationSection("classes." + classname);
|
||||
String lowercase = classname.toLowerCase();
|
||||
|
||||
// If the section doesn't exist, the class doesn't either.
|
||||
if (section == null) {
|
||||
Messenger.severe("Failed to load class '" + classname + "'.");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if weapons and armor for this class should be unbreakable
|
||||
boolean weps = section.getBoolean("unbreakable-weapons", true);
|
||||
boolean arms = section.getBoolean("unbreakable-armor", true);
|
||||
|
||||
// Grab the class price, if any
|
||||
double price = -1D;
|
||||
String priceString = section.getString("price", null);
|
||||
if (priceString != null) {
|
||||
ItemStack priceItem = ItemParser.parseItem(priceString);
|
||||
if (priceItem != null && priceItem.getTypeId() == MobArena.ECONOMY_MONEY_ID) {
|
||||
price = (priceItem.getAmount() + (priceItem.getDurability() / 100D));
|
||||
} else {
|
||||
Messenger.warning("The price for class '" + classname + "' could not be parsed!");
|
||||
Messenger.warning("- expected e.g. '$10', found '" + priceString + "'");
|
||||
}
|
||||
}
|
||||
|
||||
// Create an ArenaClass with the config-file name.
|
||||
ArenaClass arenaClass = new ArenaClass(classname, price, weps, arms);
|
||||
|
||||
// Parse the items-node
|
||||
List<String> items = section.getStringList("items");
|
||||
if (items == null || items.isEmpty()) {
|
||||
String str = section.getString("items", "");
|
||||
List<ItemStack> stacks = ItemParser.parseItems(str);
|
||||
arenaClass.setItems(stacks);
|
||||
} else {
|
||||
List<ItemStack> stacks = new ArrayList<ItemStack>();
|
||||
for (String item : items) {
|
||||
ItemStack stack = ItemParser.parseItem(item);
|
||||
if (stack != null) {
|
||||
stacks.add(stack);
|
||||
}
|
||||
}
|
||||
arenaClass.setItems(stacks);
|
||||
}
|
||||
|
||||
// And the legacy armor-node
|
||||
String armor = section.getString("armor", "");
|
||||
if (!armor.equals("")) {
|
||||
List<ItemStack> stacks = ItemParser.parseItems(armor);
|
||||
arenaClass.setArmor(stacks);
|
||||
}
|
||||
|
||||
// Get armor strings
|
||||
String head = section.getString("helmet", null);
|
||||
String chest = section.getString("chestplate", null);
|
||||
String legs = section.getString("leggings", null);
|
||||
String feet = section.getString("boots", null);
|
||||
|
||||
// Parse to ItemStacks
|
||||
ItemStack helmet = ItemParser.parseItem(head);
|
||||
ItemStack chestplate = ItemParser.parseItem(chest);
|
||||
ItemStack leggings = ItemParser.parseItem(legs);
|
||||
ItemStack boots = ItemParser.parseItem(feet);
|
||||
|
||||
// Set in ArenaClass
|
||||
arenaClass.setHelmet(helmet);
|
||||
arenaClass.setChestplate(chestplate);
|
||||
arenaClass.setLeggings(leggings);
|
||||
arenaClass.setBoots(boots);
|
||||
|
||||
// Per-class permissions
|
||||
loadClassPermissions(arenaClass, section);
|
||||
loadClassLobbyPermissions(arenaClass, section);
|
||||
|
||||
// Register the permission.
|
||||
registerPermission("mobarena.classes." + lowercase, PermissionDefault.TRUE).addParent("mobarena.classes", true);
|
||||
|
||||
// Check for class chests
|
||||
Location cc = parseLocation(section, "classchest", null);
|
||||
arenaClass.setClassChest(cc);
|
||||
|
||||
// Finally add the class to the classes map.
|
||||
classes.put(lowercase, arenaClass);
|
||||
return arenaClass;
|
||||
}
|
||||
|
||||
private void loadClassPermissions(ArenaClass arenaClass, ConfigurationSection section) {
|
||||
List<String> perms = section.getStringList("permissions");
|
||||
if (perms.isEmpty()) return;
|
||||
|
||||
for (String perm : perms) {
|
||||
// If the permission starts with - or ^, it must be revoked.
|
||||
boolean value = true;
|
||||
if (perm.startsWith("-") || perm.startsWith("^")) {
|
||||
perm = perm.substring(1).trim();
|
||||
value = false;
|
||||
}
|
||||
arenaClass.addPermission(perm, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadClassLobbyPermissions(ArenaClass arenaClass, ConfigurationSection section) {
|
||||
List<String> perms = section.getStringList("lobby-permissions");
|
||||
if (perms.isEmpty()) return;
|
||||
|
||||
for (String perm : perms) {
|
||||
// If the permission starts with - or ^, it must be revoked.
|
||||
boolean value = true;
|
||||
if (perm.startsWith("-") || perm.startsWith("^")) {
|
||||
perm = perm.substring(1).trim();
|
||||
value = false;
|
||||
}
|
||||
arenaClass.addLobbyPermission(perm, value);
|
||||
}
|
||||
}
|
||||
|
||||
public ArenaClass createClassNode(String classname, PlayerInventory inv, boolean safe) {
|
||||
String path = "classes." + classname;
|
||||
if (safe && config.getConfigurationSection(path) != null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create the node.
|
||||
config.set(path, "");
|
||||
|
||||
// Grab the section, create if missing
|
||||
ConfigurationSection section = config.getConfigurationSection(path);
|
||||
if (section == null) section = config.createSection(path);
|
||||
|
||||
// Take the current items and armor.
|
||||
section.set("items", ItemParser.parseString(inv.getContents()));
|
||||
section.set("armor", ItemParser.parseString(inv.getArmorContents()));
|
||||
|
||||
// If the helmet isn't a real helmet, set it explicitly.
|
||||
ItemStack helmet = inv.getHelmet();
|
||||
if (helmet != null && ArmorType.getType(helmet) != ArmorType.HELMET) {
|
||||
section.set("helmet", ItemParser.parseString(helmet));
|
||||
}
|
||||
|
||||
// Save changes.
|
||||
plugin.saveConfig();
|
||||
|
||||
// Load the class
|
||||
return loadClass(classname);
|
||||
}
|
||||
|
||||
public void removeClassNode(String classname) {
|
||||
String lowercase = classname.toLowerCase();
|
||||
if (!classes.containsKey(lowercase))
|
||||
throw new IllegalArgumentException("Class does not exist!");
|
||||
|
||||
// Remove the class from the config-file and save it.
|
||||
config.set("classes." + classname, null);
|
||||
plugin.saveConfig();
|
||||
|
||||
// Remove the class from the map.
|
||||
classes.remove(lowercase);
|
||||
|
||||
unregisterPermission("mobarena.arenas." + lowercase);
|
||||
}
|
||||
|
||||
public boolean addClassPermission(String classname, String perm) {
|
||||
return addRemoveClassPermission(classname, perm, true);
|
||||
}
|
||||
|
||||
public boolean removeClassPermission(String classname, String perm) {
|
||||
return addRemoveClassPermission(classname, perm, false);
|
||||
}
|
||||
|
||||
private boolean addRemoveClassPermission(String classname, String perm, boolean add) {
|
||||
classname = TextUtils.camelCase(classname);
|
||||
String path = "classes." + classname;
|
||||
if (config.getConfigurationSection(path) == null)
|
||||
return false;
|
||||
|
||||
// Grab the class section
|
||||
ConfigurationSection section = config.getConfigurationSection(path);
|
||||
|
||||
// Get any previous nodes
|
||||
List<String> nodes = section.getStringList("permissions");
|
||||
if (nodes.contains(perm) && add) {
|
||||
return false;
|
||||
}
|
||||
else if (nodes.contains(perm) && !add) {
|
||||
nodes.remove(perm);
|
||||
}
|
||||
else if (!nodes.contains(perm) && add) {
|
||||
removeContradictions(nodes, perm);
|
||||
nodes.add(perm);
|
||||
}
|
||||
else if (!nodes.contains(perm) && !add) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Replace the set.
|
||||
section.set("permissions", nodes);
|
||||
plugin.saveConfig();
|
||||
|
||||
// Reload the class.
|
||||
loadClass(classname);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes any nodes that would contradict the permission, e.g. if the node
|
||||
* 'mobarena.use' is in the set, and the perm node is '-mobarena.use', the
|
||||
* '-mobarena.use' node is removed as to not contradict the new
|
||||
* 'mobarena.use' node.
|
||||
*/
|
||||
private void removeContradictions(List<String> nodes, String perm) {
|
||||
if (perm.startsWith("^") || perm.startsWith("-")) {
|
||||
nodes.remove(perm.substring(1).trim());
|
||||
}
|
||||
else {
|
||||
nodes.remove("^" + perm);
|
||||
nodes.remove("-" + perm);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all arena-related stuff.
|
||||
*/
|
||||
public void loadArenas() {
|
||||
ConfigurationSection section = makeSection(config, "arenas");
|
||||
Set<String> arenanames = section.getKeys(false);
|
||||
|
||||
// If no arenas were found, create a default node.
|
||||
if (arenanames == null || arenanames.isEmpty()) {
|
||||
createArenaNode(section, "default", plugin.getServer().getWorlds().get(0), false);
|
||||
}
|
||||
|
||||
arenas = new ArrayList<Arena>();
|
||||
for (World w : Bukkit.getServer().getWorlds()) {
|
||||
loadArenasInWorld(w.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public void loadArenasInWorld(String worldName) {
|
||||
Set<String> arenaNames = config.getConfigurationSection("arenas").getKeys(false);
|
||||
if (arenaNames == null || arenaNames.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (String arenaName : arenaNames) {
|
||||
Arena arena = getArenaWithName(arenaName);
|
||||
if (arena != null) continue;
|
||||
|
||||
String arenaWorld = config.getString("arenas." + arenaName + ".settings.world", "");
|
||||
if (!arenaWorld.equals(worldName)) continue;
|
||||
|
||||
loadArena(arenaName);
|
||||
}
|
||||
}
|
||||
|
||||
public void unloadArenasInWorld(String worldName) {
|
||||
Set<String> arenaNames = config.getConfigurationSection("arenas").getKeys(false);
|
||||
if (arenaNames == null || arenaNames.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (String arenaName : arenaNames) {
|
||||
Arena arena = getArenaWithName(arenaName);
|
||||
if (arena == null) continue;
|
||||
|
||||
String arenaWorld = arena.getWorld().getName();
|
||||
if (!arenaWorld.equals(worldName)) continue;
|
||||
|
||||
arena.forceEnd();
|
||||
arenas.remove(arena);
|
||||
}
|
||||
}
|
||||
|
||||
// Load an already existing arena node
|
||||
private Arena loadArena(String arenaname) {
|
||||
ConfigurationSection section = makeSection(config, "arenas." + arenaname);
|
||||
ConfigurationSection settings = makeSection(section, "settings");
|
||||
String worldName = settings.getString("world", "");
|
||||
World world;
|
||||
|
||||
if (!worldName.equals("")) {
|
||||
world = plugin.getServer().getWorld(worldName);
|
||||
if (world == null) {
|
||||
Messenger.warning("World '" + worldName + "' for arena '" + arenaname + "' was not found...");
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
world = plugin.getServer().getWorlds().get(0);
|
||||
Messenger.warning("Could not find the world for arena '" + arenaname + "'. Using default world ('" + world.getName() + "')! Check the config-file!");
|
||||
}
|
||||
|
||||
ConfigUtils.addMissingRemoveObsolete(plugin, "settings.yml", settings);
|
||||
ConfigUtils.addIfEmpty(plugin, "waves.yml", makeSection(section, "waves"));
|
||||
|
||||
Arena arena = new ArenaImpl(plugin, section, arenaname, world);
|
||||
registerPermission("mobarena.arenas." + arenaname.toLowerCase(), PermissionDefault.TRUE);
|
||||
arenas.add(arena);
|
||||
plugin.getLogger().info("Loaded arena '" + arenaname + "'");
|
||||
return arena;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reloadArena(String name) {
|
||||
Arena arena = getArenaWithName(name);
|
||||
if (arena == null) return false;
|
||||
|
||||
arena.forceEnd();
|
||||
arenas.remove(arena);
|
||||
|
||||
plugin.reloadConfig();
|
||||
config = plugin.getConfig();
|
||||
|
||||
loadArena(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create and load a new arena node
|
||||
@Override
|
||||
public Arena createArenaNode(String arenaName, World world) {
|
||||
ConfigurationSection section = makeSection(config, "arenas");
|
||||
return createArenaNode(section, arenaName, world, true);
|
||||
}
|
||||
|
||||
// Create a new arena node, and (optionally) load it
|
||||
private Arena createArenaNode(ConfigurationSection arenas, String arenaName, World world, boolean load) {
|
||||
if (arenas.contains(arenaName)) {
|
||||
throw new IllegalArgumentException("Arena already exists!");
|
||||
}
|
||||
ConfigurationSection section = makeSection(arenas, arenaName);
|
||||
|
||||
// Add missing settings and remove obsolete ones
|
||||
ConfigUtils.addMissingRemoveObsolete(plugin, "settings.yml", makeSection(section, "settings"));
|
||||
section.set("settings.world", world.getName());
|
||||
ConfigUtils.addIfEmpty(plugin, "waves.yml", makeSection(section, "waves"));
|
||||
ConfigUtils.addIfEmpty(plugin, "rewards.yml", makeSection(section, "rewards"));
|
||||
plugin.saveConfig();
|
||||
|
||||
// Load the arena
|
||||
return (load ? loadArena(arenaName) : null);
|
||||
}
|
||||
|
||||
public void removeArenaNode(Arena arena) {
|
||||
arenas.remove(arena);
|
||||
unregisterPermission("mobarena.arenas." + arena.configName());
|
||||
|
||||
config.set("arenas." + arena.configName(), null);
|
||||
plugin.saveConfig();
|
||||
}
|
||||
|
||||
public void reloadConfig() {
|
||||
boolean wasEnabled = isEnabled();
|
||||
if (wasEnabled) setEnabled(false);
|
||||
for (Arena a : arenas) {
|
||||
a.forceEnd();
|
||||
}
|
||||
plugin.reloadConfig();
|
||||
config = plugin.getConfig();
|
||||
initialize();
|
||||
if (wasEnabled) setEnabled(true);
|
||||
}
|
||||
|
||||
public void saveConfig() {
|
||||
plugin.saveConfig();
|
||||
}
|
||||
|
||||
private Permission registerPermission(String permString, PermissionDefault value) {
|
||||
PluginManager pm = plugin.getServer().getPluginManager();
|
||||
|
||||
Permission perm = pm.getPermission(permString);
|
||||
if (perm == null) {
|
||||
perm = new Permission(permString);
|
||||
perm.setDefault(value);
|
||||
pm.addPermission(perm);
|
||||
}
|
||||
return perm;
|
||||
}
|
||||
|
||||
private void unregisterPermission(String s) {
|
||||
plugin.getServer().getPluginManager().removePermission(s);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaPlayerStatistics;
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public class ArenaPlayer
|
||||
{
|
||||
private Player player;
|
||||
|
||||
private ArenaClass arenaClass;
|
||||
private ArenaPlayerStatistics stats;
|
||||
private boolean isDead;
|
||||
|
||||
//private List<ItemStack> rewards;
|
||||
//private List<Block> blocks;
|
||||
|
||||
public ArenaPlayer(Player player, Arena arena, MobArena plugin) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public ArenaClass getArenaClass() {
|
||||
return arenaClass;
|
||||
}
|
||||
|
||||
public void setArenaClass(ArenaClass arenaClass) {
|
||||
this.arenaClass = arenaClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the player is "dead", i.e. died or not.
|
||||
* @return true, if the player is either a spectator or played and died, false otherwise
|
||||
*/
|
||||
public boolean isDead() {
|
||||
return isDead;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the player's death status.
|
||||
* @param value true, if the player is dead, false otherwise
|
||||
*/
|
||||
public void setDead(boolean value) {
|
||||
isDead = value;
|
||||
}
|
||||
|
||||
public void resetStats() {
|
||||
if (stats != null) {
|
||||
stats.reset();
|
||||
return;
|
||||
}
|
||||
stats = new ArenaPlayerStatistics(this);
|
||||
}
|
||||
|
||||
public ArenaPlayerStatistics getStats() {
|
||||
return stats;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaPlayer;
|
||||
import com.garbagemule.MobArena.ArenaPlayerStatistics;
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.util.MutableInt;
|
||||
|
||||
public class ArenaPlayerStatistics
|
||||
{
|
||||
private ArenaPlayer player;
|
||||
private String playerName, className;
|
||||
private Map<String, MutableInt> ints;
|
||||
|
||||
public ArenaPlayerStatistics(ArenaPlayer player) {
|
||||
this.player = player;
|
||||
this.playerName = player.getPlayer().getName();
|
||||
this.className = player.getArenaClass().getLowercaseName();
|
||||
reset();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
if (ints == null) {
|
||||
ints = new HashMap<String, MutableInt>();
|
||||
}
|
||||
|
||||
ints.clear();
|
||||
|
||||
ints.put("kills", new MutableInt());
|
||||
ints.put("dmgDone", new MutableInt());
|
||||
ints.put("dmgTaken", new MutableInt());
|
||||
ints.put("swings", new MutableInt());
|
||||
ints.put("hits", new MutableInt());
|
||||
ints.put("lastWave", new MutableInt());
|
||||
}
|
||||
|
||||
public ArenaPlayerStatistics(Player p, Arena arena, MobArena plugin) {
|
||||
this(new ArenaPlayer(p, arena, plugin));
|
||||
}
|
||||
|
||||
public ArenaPlayer getArenaPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public String getPlayerName() {
|
||||
return playerName;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
public int getInt(String s) {
|
||||
return ints.get(s).value();
|
||||
}
|
||||
|
||||
public void inc(String s) {
|
||||
ints.get(s).inc();
|
||||
}
|
||||
|
||||
public void add(String s, double amount) {
|
||||
ints.get(s).add(amount);
|
||||
}
|
||||
|
||||
public static Comparator<ArenaPlayerStatistics> killComparator() {
|
||||
return new Comparator<ArenaPlayerStatistics>() {
|
||||
public int compare(ArenaPlayerStatistics s1, ArenaPlayerStatistics s2) {
|
||||
int s1kills = s1.getInt("kills");
|
||||
int s2kills = s2.getInt("kills");
|
||||
|
||||
if (s1kills == s2kills)
|
||||
return 0;
|
||||
|
||||
return (s1kills > s2kills ? -1 : 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Comparator<ArenaPlayerStatistics> waveComparator() {
|
||||
return new Comparator<ArenaPlayerStatistics>() {
|
||||
public int compare(ArenaPlayerStatistics s1, ArenaPlayerStatistics s2) {
|
||||
int result = compareWaves(s1, s2);
|
||||
if (result != 0)
|
||||
return result;
|
||||
|
||||
return compareKills(s1, s2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Comparator<ArenaPlayerStatistics> dmgDoneComparator() {
|
||||
return new Comparator<ArenaPlayerStatistics>() {
|
||||
public int compare(ArenaPlayerStatistics s1, ArenaPlayerStatistics s2) {
|
||||
int s1dmgDone = s1.getInt("dmgDone");
|
||||
int s2dmgDone = s2.getInt("dmgDone");
|
||||
|
||||
if (s1dmgDone == s2dmgDone)
|
||||
return 0;
|
||||
|
||||
return (s1dmgDone > s2dmgDone ? -1 : 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static int compareKills(ArenaPlayerStatistics s1, ArenaPlayerStatistics s2) {
|
||||
int s1kills = s1.getInt("kills");
|
||||
int s2kills = s2.getInt("kills");
|
||||
|
||||
if (s1kills == s2kills)
|
||||
return 0;
|
||||
|
||||
return (s1kills > s2kills ? -1 : 1);
|
||||
}
|
||||
|
||||
private static int compareWaves(ArenaPlayerStatistics s1, ArenaPlayerStatistics s2) {
|
||||
int s1wave = s1.getInt("lastWave");
|
||||
int s2wave = s2.getInt("lastWave");
|
||||
|
||||
if (s1wave == s2wave)
|
||||
return 0;
|
||||
|
||||
return (s1wave > s2wave ? -1 : 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.util.MutableInt;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class ClassLimitManager
|
||||
{
|
||||
private HashMap<ArenaClass,MutableInt> classLimits;
|
||||
private HashMap<ArenaClass, HashSet<String>> classesInUse;
|
||||
private ConfigurationSection limits;
|
||||
private Map<String,ArenaClass> classes;
|
||||
|
||||
public ClassLimitManager(Arena arena, Map<String,ArenaClass> classes, ConfigurationSection limits) {
|
||||
this.limits = limits;
|
||||
this.classes = classes;
|
||||
this.classLimits = new HashMap<ArenaClass,MutableInt>();
|
||||
this.classesInUse = new HashMap<ArenaClass, HashSet<String>>();
|
||||
|
||||
loadLimitMap(arena.getPlugin());
|
||||
initInUseMap();
|
||||
}
|
||||
|
||||
private void loadLimitMap(Plugin plugin) {
|
||||
// If the config-section is empty, create and populate it.
|
||||
if (limits.getKeys(false).isEmpty()) {
|
||||
for (ArenaClass ac : classes.values()) {
|
||||
limits.set(ac.getConfigName(), -1);
|
||||
}
|
||||
plugin.saveConfig();
|
||||
}
|
||||
|
||||
// Populate the limits map using the values in the config-file.
|
||||
for (ArenaClass ac : classes.values()) {
|
||||
classLimits.put(ac, new MutableInt(limits.getInt(ac.getConfigName(), -1)));
|
||||
}
|
||||
}
|
||||
|
||||
private void initInUseMap() {
|
||||
// Initialize the in-use map with zeros.
|
||||
for (ArenaClass ac : classes.values()) {
|
||||
classesInUse.put(ac, new HashSet<String>());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the class a player is changing to
|
||||
* @param ac the new ArenaClass
|
||||
*/
|
||||
public void playerPickedClass(ArenaClass ac, Player p) {
|
||||
classesInUse.get(ac).add(p.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the class a player left
|
||||
* @param ac the current/old ArenaClass
|
||||
*/
|
||||
public void playerLeftClass(ArenaClass ac, Player p) {
|
||||
if (ac != null) {
|
||||
classesInUse.get(ac).remove(p.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a player can pick a specific class
|
||||
* @param ac the ArenaClass to check
|
||||
* @return true/false
|
||||
*/
|
||||
public boolean canPlayerJoinClass(ArenaClass ac) {
|
||||
if (classLimits.get(ac) == null) {
|
||||
limits.set(ac.getConfigName(), -1);
|
||||
classLimits.put(ac, new MutableInt(-1));
|
||||
classesInUse.put(ac, new HashSet<String>());
|
||||
}
|
||||
|
||||
if (classLimits.get(ac).value() <= -1)
|
||||
return true;
|
||||
|
||||
return classesInUse.get(ac).size() < classLimits.get(ac).value();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a set of Player Names who have picked an ArenaClass
|
||||
* @param ac the ArenaClass in question
|
||||
* @return the Player Names who have picked the provided ArenaClass
|
||||
*/
|
||||
public HashSet<String> getPlayersWithClass(ArenaClass ac) {
|
||||
return classesInUse.get(ac);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the classes in use map and reinitialize it for the next match
|
||||
*/
|
||||
public void clearClassesInUse() {
|
||||
classesInUse.clear();
|
||||
initInUseMap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,349 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.garbagemule.MobArena.events.ArenaCompleteEvent;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.garbagemule.MobArena.events.NewWaveEvent;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.region.ArenaRegion;
|
||||
import com.garbagemule.MobArena.waves.*;
|
||||
import com.garbagemule.MobArena.waves.enums.WaveType;
|
||||
import com.garbagemule.MobArena.waves.types.BossWave;
|
||||
import com.garbagemule.MobArena.waves.types.SupplyWave;
|
||||
import com.garbagemule.MobArena.waves.types.UpgradeWave;
|
||||
|
||||
public class MASpawnThread implements Runnable
|
||||
{
|
||||
private MobArena plugin;
|
||||
private Arena arena;
|
||||
private ArenaRegion region;
|
||||
private RewardManager rewardManager;
|
||||
private WaveManager waveManager;
|
||||
private MonsterManager monsterManager;
|
||||
|
||||
private int playerCount, monsterLimit;
|
||||
private boolean waveClear, bossClear, preBossClear, wavesAsLevel;
|
||||
|
||||
/**
|
||||
* Create a new monster spawner for the input arena.
|
||||
* Note that the arena's WaveManager is reset
|
||||
* @param plugin a MobArena instance
|
||||
* @param arena an arena
|
||||
*/
|
||||
public MASpawnThread(MobArena plugin, Arena arena) {
|
||||
this.plugin = plugin;
|
||||
this.arena = arena;
|
||||
this.region = arena.getRegion();
|
||||
this.rewardManager = arena.getRewardManager();
|
||||
this.waveManager = arena.getWaveManager();
|
||||
this.monsterManager = arena.getMonsterManager();
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the spawner, so all systems and settings are
|
||||
* ready for a new session.
|
||||
*/
|
||||
public void reset() {
|
||||
waveManager.reset();
|
||||
playerCount = arena.getPlayersInArena().size();
|
||||
monsterLimit = arena.getSettings().getInt("monster-limit", 100);
|
||||
waveClear = arena.getSettings().getBoolean("clear-wave-before-next", false);
|
||||
bossClear = arena.getSettings().getBoolean("clear-boss-before-next", false);
|
||||
preBossClear = arena.getSettings().getBoolean("clear-wave-before-boss", false);
|
||||
wavesAsLevel = arena.getSettings().getBoolean("display-waves-as-level", false);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// If the arena isn't running or if there are no players in it.
|
||||
if (!arena.isRunning() || arena.getPlayersInArena().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear out all dead monsters in the monster set.
|
||||
removeDeadMonsters();
|
||||
removeCheatingPlayers();
|
||||
|
||||
// In case some players were removed, check again.
|
||||
if (!arena.isRunning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab the wave number.
|
||||
int nextWave = waveManager.getWaveNumber() + 1;
|
||||
|
||||
// Check if wave needs to be cleared first. If so, return!
|
||||
if (!isWaveClear()) {
|
||||
arena.scheduleTask(this, 60);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire off the event. If cancelled, try again in 3 seconds.
|
||||
NewWaveEvent event = new NewWaveEvent(arena, waveManager.getNext(), nextWave);
|
||||
plugin.getServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
arena.scheduleTask(this, 60);
|
||||
return;
|
||||
}
|
||||
|
||||
// Grant rewards (if any) for the wave about to spawn
|
||||
grantRewards(nextWave);
|
||||
|
||||
// Check if this is the final wave, in which case, end instead of spawn
|
||||
if (nextWave > 1 && (nextWave - 1) == waveManager.getFinalWave()) {
|
||||
// Fire the complete event
|
||||
ArenaCompleteEvent complete = new ArenaCompleteEvent(arena);
|
||||
plugin.getServer().getPluginManager().callEvent(complete);
|
||||
|
||||
// Then force leave everyone
|
||||
List<Player> players = new ArrayList<Player>(arena.getPlayersInArena());
|
||||
for (Player p : players) {
|
||||
arena.playerLeave(p);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Spawn the next wave.
|
||||
spawnWave(nextWave);
|
||||
|
||||
// Update stats
|
||||
updateStats(nextWave);
|
||||
|
||||
// Reschedule the spawner for the next wave.
|
||||
arena.scheduleTask(this, arena.getSettings().getInt("wave-interval", 3) * 20);
|
||||
}
|
||||
|
||||
private void spawnWave(int wave) {
|
||||
Wave w = waveManager.next();
|
||||
|
||||
w.announce(arena, wave);
|
||||
|
||||
arena.getScoreboard().updateWave(wave);
|
||||
|
||||
// Set the players' level to the wave number
|
||||
if (wavesAsLevel) {
|
||||
for (Player p : arena.getPlayersInArena()) {
|
||||
p.setLevel(wave);
|
||||
p.setExp(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (w.getType() == WaveType.UPGRADE) {
|
||||
handleUpgradeWave(w);
|
||||
return;
|
||||
}
|
||||
|
||||
Map<MACreature, Integer> monsters = w.getMonstersToSpawn(wave, playerCount, arena);
|
||||
List<Location> spawnpoints = w.getSpawnpoints(arena);
|
||||
|
||||
World world = arena.getWorld();
|
||||
int totalSpawnpoints = spawnpoints.size();
|
||||
int index = 0;
|
||||
double mul = w.getHealthMultiplier();
|
||||
|
||||
for (Map.Entry<MACreature, Integer> entry : monsters.entrySet()) {
|
||||
for (int i = 0; i < entry.getValue(); i++, index++) {
|
||||
// Check if monster limit has been reached.
|
||||
if (monsterManager.getMonsters().size() >= monsterLimit) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab a spawnpoint
|
||||
Location spawnpoint = spawnpoints.get(index % totalSpawnpoints);
|
||||
|
||||
// Spawn the monster
|
||||
LivingEntity e = entry.getKey().spawn(arena, world, spawnpoint);
|
||||
|
||||
// Add it to the arena.
|
||||
monsterManager.addMonster(e);
|
||||
|
||||
// Set the health.
|
||||
e.resetMaxHealth(); // Avoid conflicts/enormous multiplications from other plugins handling Mob health
|
||||
int health = (int) Math.max(1D, e.getMaxHealth() * mul);
|
||||
try {
|
||||
e.setMaxHealth(health);
|
||||
e.setHealth(health);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// Spigot... *facepalm*
|
||||
Messenger.severe("Can't set health to " + health + ", using default health. If you are running Spigot, set 'maxHealth' higher in your Spigot settings.");
|
||||
Messenger.severe(ex.getLocalizedMessage());
|
||||
if (w.getType() == WaveType.BOSS) {
|
||||
((BossWave) w).setBossName("SPIGOT ERROR");
|
||||
} else {
|
||||
e.setCustomName("SPIGOT ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
// Switch on the type.
|
||||
switch (w.getType()){
|
||||
case BOSS:
|
||||
BossWave bw = (BossWave) w;
|
||||
double maxHealth = bw.getMaxHealth(playerCount);
|
||||
MABoss boss = monsterManager.addBoss(e, maxHealth);
|
||||
boss.setReward(bw.getReward());
|
||||
boss.setDrops(bw.getDrops());
|
||||
bw.addMABoss(boss);
|
||||
bw.activateAbilities(arena);
|
||||
e.addPotionEffects(bw.getPotions());
|
||||
if (bw.getBossName() != null) {
|
||||
e.setCustomName(bw.getBossName());
|
||||
e.setCustomNameVisible(true);
|
||||
}
|
||||
break;
|
||||
case SWARM:
|
||||
health = (int) (mul < 1D ? e.getMaxHealth() * mul : 1);
|
||||
health = Math.max(1, health);
|
||||
e.setHealth(Math.min(health, e.getMaxHealth()));
|
||||
break;
|
||||
case SUPPLY:
|
||||
SupplyWave sw = (SupplyWave) w;
|
||||
monsterManager.addSupplier(e, sw.getDropList());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleUpgradeWave(Wave w) {
|
||||
UpgradeWave uw = (UpgradeWave) w;
|
||||
|
||||
for (Player p : arena.getPlayersInArena()) {
|
||||
String className = arena.getArenaPlayer(p).getArenaClass().getLowercaseName();
|
||||
uw.grantItems(arena, p, className);
|
||||
uw.grantItems(arena, p, "all");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the wave is clear for new spawns.
|
||||
* If clear-boss-before-next: true, bosses must be dead.
|
||||
* If clear-wave-before-next: true, all monsters must be dead.
|
||||
* @return true, if the wave is "clear" for new spawns.
|
||||
*/
|
||||
private boolean isWaveClear() {
|
||||
// Check for monster limit
|
||||
if (monsterManager.getMonsters().size() >= monsterLimit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for boss clear
|
||||
if (bossClear && !monsterManager.getBossMonsters().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for wave and pre boss clear
|
||||
if (waveClear && !monsterManager.getMonsters().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for pre boss clear
|
||||
if (preBossClear && waveManager.getNext().getType() == WaveType.BOSS && !monsterManager.getMonsters().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for final wave
|
||||
if (!monsterManager.getMonsters().isEmpty() && waveManager.getWaveNumber() == waveManager.getFinalWave()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void removeDeadMonsters() {
|
||||
List<Entity> tmp = new ArrayList<Entity>(monsterManager.getMonsters());
|
||||
for (Entity e : tmp) {
|
||||
if (e == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.isDead() || !region.contains(e.getLocation())) {
|
||||
monsterManager.remove(e);
|
||||
e.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeCheatingPlayers() {
|
||||
List<Player> players = new ArrayList<Player>(arena.getPlayersInArena());
|
||||
for (Player p : players) {
|
||||
if (region.contains(p.getLocation())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Messenger.tell(p, "Leaving so soon?");
|
||||
p.getInventory().clear();
|
||||
arena.playerLeave(p);
|
||||
}
|
||||
}
|
||||
|
||||
private void grantRewards(int wave) {
|
||||
for (Map.Entry<Integer, List<ItemStack>> entry : arena.getEveryWaveEntrySet()) {
|
||||
if (wave % entry.getKey() == 0) {
|
||||
addReward(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
List<ItemStack> after = arena.getAfterWaveReward(wave);
|
||||
if (after != null) {
|
||||
addReward(after);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStats(int wave) {
|
||||
for (ArenaPlayer ap : arena.getArenaPlayerSet()) {
|
||||
if (arena.getPlayersInArena().contains(ap.getPlayer())) {
|
||||
ap.getStats().inc("lastWave");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ////////////////////////////////////////////////////////////////////
|
||||
* //
|
||||
* // Getters/setters
|
||||
* //
|
||||
* ////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
public int getPlayerCount() {
|
||||
return playerCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewards all players with an item from the input String.
|
||||
*/
|
||||
private void addReward(List<ItemStack> rewards) {
|
||||
for (Player p : arena.getPlayersInArena()) {
|
||||
ItemStack reward = MAUtils.getRandomReward(rewards);
|
||||
rewardManager.addReward(p, reward);
|
||||
|
||||
if (reward == null) {
|
||||
Messenger.tell(p, "ERROR! Problem with rewards. Notify server host!");
|
||||
Messenger.warning("Could not add null reward. Please check the config-file!");
|
||||
}
|
||||
else if (reward.getTypeId() == MobArena.ECONOMY_MONEY_ID) {
|
||||
if (plugin.giveMoney(p, reward)) { // Money already awarded here, not needed at end of match as well
|
||||
Messenger.tell(p, Msg.WAVE_REWARD, plugin.economyFormat(reward));
|
||||
}
|
||||
else {
|
||||
Messenger.warning("Tried to add money, but no economy plugin detected!");
|
||||
}
|
||||
}
|
||||
else {
|
||||
Messenger.tell(p, Msg.WAVE_REWARD, MAUtils.toCamelCase(reward.getType().toString()) + ":" + reward.getAmount());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,487 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Wolf;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.region.ArenaRegion;
|
||||
import com.garbagemule.MobArena.util.EntityPosition;
|
||||
import com.garbagemule.MobArena.util.ItemParser;
|
||||
import com.garbagemule.MobArena.util.TextUtils;
|
||||
|
||||
public class MAUtils
|
||||
{
|
||||
public static final String sep = File.separator;
|
||||
|
||||
|
||||
|
||||
/* ///////////////////////////////////////////////////////////////////// //
|
||||
|
||||
INITIALIZATION METHODS
|
||||
|
||||
// ///////////////////////////////////////////////////////////////////// */
|
||||
|
||||
/**
|
||||
* 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,List<ItemStack>> getArenaRewardMap(MobArena plugin, ConfigurationSection config, String arena, String type)
|
||||
{
|
||||
//String arenaPath = "arenas." + arena + ".rewards.waves.";
|
||||
Map<Integer,List<ItemStack>> result = new HashMap<Integer,List<ItemStack>>();
|
||||
|
||||
String typePath = "rewards.waves." + type;
|
||||
if (!config.contains(typePath)) return result;
|
||||
|
||||
//Set<String> waves = config.getKeys(arenaPath + type);
|
||||
Set<String> waves = config.getConfigurationSection(typePath).getKeys(false);
|
||||
if (waves == null) return result;
|
||||
|
||||
for (String n : waves)
|
||||
{
|
||||
if (!n.matches("[0-9]+"))
|
||||
continue;
|
||||
|
||||
int wave = Integer.parseInt(n);
|
||||
String path = typePath + "." + wave;
|
||||
String rewards = config.getString(path);
|
||||
|
||||
result.put(wave, ItemParser.parseItems(rewards));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ///////////////////////////////////////////////////////////////////// //
|
||||
|
||||
INVENTORY AND REWARD METHODS
|
||||
|
||||
// ///////////////////////////////////////////////////////////////////// */
|
||||
|
||||
/* Helper method for grabbing a random reward */
|
||||
public static ItemStack getRandomReward(List<ItemStack> rewards)
|
||||
{
|
||||
if (rewards.isEmpty())
|
||||
return null;
|
||||
|
||||
Random ran = new Random();
|
||||
return rewards.get(ran.nextInt(rewards.size()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ///////////////////////////////////////////////////////////////////// //
|
||||
|
||||
PET CLASS METHODS
|
||||
|
||||
// ///////////////////////////////////////////////////////////////////// */
|
||||
|
||||
/**
|
||||
* Makes all nearby wolves sit if their owner is the given player.
|
||||
*/
|
||||
public static void sitPets(Player p)
|
||||
{
|
||||
if (p == null)
|
||||
return;
|
||||
|
||||
List<Entity> entities = p.getNearbyEntities(80, 40, 80);
|
||||
for (Entity e : entities)
|
||||
{
|
||||
if (!(e instanceof Wolf))
|
||||
continue;
|
||||
|
||||
Wolf w = (Wolf) e;
|
||||
if (w.isTamed() && w.getOwner() != null && w.getOwner().equals(p))
|
||||
w.setSitting(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ///////////////////////////////////////////////////////////////////// //
|
||||
|
||||
MISC METHODS
|
||||
|
||||
// ///////////////////////////////////////////////////////////////////// */
|
||||
|
||||
|
||||
public static Player getClosestPlayer(MobArena plugin, Entity e, Arena arena) {
|
||||
// Set up the comparison variable and the result.
|
||||
double current = Double.POSITIVE_INFINITY;
|
||||
Player result = null;
|
||||
|
||||
/* Iterate through the ArrayList, and update current and result every
|
||||
* time a squared distance smaller than current is found. */
|
||||
List<Player> players = new ArrayList<Player>(arena.getPlayersInArena());
|
||||
for (Player p : players) {
|
||||
if (!arena.getWorld().equals(p.getWorld())) {
|
||||
Messenger.info("Player '" + p.getName() + "' is not in the right world. Kicking...");
|
||||
p.kickPlayer("[MobArena] Cheater! (Warped out of the arena world.)");
|
||||
Messenger.tell(p, "You warped out of the arena world.");
|
||||
continue;
|
||||
}
|
||||
|
||||
double dist = distanceSquared(plugin, p, e.getLocation());
|
||||
if (dist < current && dist < 256D) {
|
||||
current = dist;
|
||||
result = p;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double distanceSquared(MobArena plugin, Player p, Location l) {
|
||||
try {
|
||||
return p.getLocation().distanceSquared(l);
|
||||
}
|
||||
catch (Exception e) {
|
||||
p.kickPlayer("Banned for life! No, but stop trying to cheat in MobArena!");
|
||||
if (plugin != null) {
|
||||
Messenger.warning(p.getName() + " tried to cheat in MobArena and has been kicked.");
|
||||
}
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a config-name to a proper spaced and capsed arena name.
|
||||
* The input String is split around all underscores, and every part
|
||||
* of the String array is properly capsed.
|
||||
*/
|
||||
public static String nameConfigToArena(String name)
|
||||
{
|
||||
String[] parts = name.split("_");
|
||||
if (parts.length == 1) {
|
||||
return toCamelCase(parts[0]);
|
||||
}
|
||||
|
||||
String separator = " ";
|
||||
StringBuffer buffy = new StringBuffer(name.length());
|
||||
for (String part : parts) {
|
||||
buffy.append(toCamelCase(part));
|
||||
buffy.append(separator);
|
||||
}
|
||||
buffy.replace(buffy.length()-1, buffy.length(), "");
|
||||
|
||||
return buffy.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the input String with a capital first letter, and all the
|
||||
* other letters become lower case.
|
||||
*/
|
||||
public static String toCamelCase(String name) {
|
||||
return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a list into a space-separated string-representation of the list.
|
||||
*/
|
||||
public static <E> String listToString(Collection<E> list, boolean none, MobArena plugin)
|
||||
{
|
||||
if (list == null || list.isEmpty()) {
|
||||
return (none ? Msg.MISC_NONE.toString() : "");
|
||||
}
|
||||
|
||||
StringBuffer buffy = new StringBuffer();
|
||||
int trimLength = 0;
|
||||
|
||||
E type = list.iterator().next();
|
||||
if (type instanceof Player) {
|
||||
for (E e : list) {
|
||||
buffy.append(((Player) e).getName());
|
||||
buffy.append(" ");
|
||||
}
|
||||
}
|
||||
else if (type instanceof ItemStack) {
|
||||
trimLength = 2;
|
||||
ItemStack stack;
|
||||
for (E e : list) {
|
||||
stack = (ItemStack) e;
|
||||
if (stack.getTypeId() == MobArena.ECONOMY_MONEY_ID) {
|
||||
String formatted = plugin.economyFormat(stack);
|
||||
if (formatted != null) {
|
||||
buffy.append(formatted);
|
||||
buffy.append(", ");
|
||||
}
|
||||
else {
|
||||
Messenger.warning("Tried to do some money stuff, but no economy plugin was detected!");
|
||||
return buffy.toString();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
buffy.append(stack.getType().toString().toLowerCase());
|
||||
buffy.append(":");
|
||||
buffy.append(stack.getAmount());
|
||||
buffy.append(", ");
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (E e : list) {
|
||||
buffy.append(e.toString());
|
||||
buffy.append(" ");
|
||||
}
|
||||
}
|
||||
return buffy.toString().substring(0, buffy.length() - trimLength);
|
||||
}
|
||||
public static <E> String listToString(Collection<E> list, JavaPlugin plugin) { return listToString(list, true, (MobArena) plugin); }
|
||||
|
||||
/**
|
||||
* Returns a String-list version of a comma-separated list.
|
||||
*/
|
||||
public static List<String> stringToList(String list)
|
||||
{
|
||||
List<String> result = new LinkedList<String>();
|
||||
if (list == null) return result;
|
||||
|
||||
String[] parts = list.trim().split(",");
|
||||
|
||||
for (String part : parts)
|
||||
result.add(part.trim());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stand back, I'm going to try science!
|
||||
*/
|
||||
public static boolean doooooItHippieMonster(Location loc, int radius, String name, MobArena plugin)
|
||||
{
|
||||
// Try to restore the old patch first.
|
||||
undoItHippieMonster(name, plugin, false);
|
||||
|
||||
// Grab the Configuration and ArenaMaster
|
||||
ArenaMaster am = plugin.getArenaMaster();
|
||||
|
||||
// Create the arena node in the config-file.
|
||||
World world = loc.getWorld();
|
||||
Arena arena = am.createArenaNode(name, world);
|
||||
|
||||
// Get the hippie bounds.
|
||||
int x1 = (int)loc.getX() - radius;
|
||||
int x2 = (int)loc.getX() + radius;
|
||||
int y1 = (int)loc.getY() - 9;
|
||||
int y2 = (int)loc.getY() - 1;
|
||||
int z1 = (int)loc.getZ() - radius;
|
||||
int z2 = (int)loc.getZ() + radius;
|
||||
|
||||
int lx1 = x1;
|
||||
int lx2 = x1 + am.getClasses().size() + 3;
|
||||
int ly1 = y1-6;
|
||||
int ly2 = y1-2;
|
||||
int lz1 = z1;
|
||||
int lz2 = z1 + 6;
|
||||
|
||||
// Save the precious patch
|
||||
HashMap<EntityPosition,Integer> preciousPatch = new HashMap<EntityPosition,Integer>();
|
||||
Location lo;
|
||||
int id;
|
||||
for (int i = x1; i <= x2; i++)
|
||||
{
|
||||
for (int j = ly1; j <= y2; j++)
|
||||
{
|
||||
for (int k = z1; k <= z2; k++)
|
||||
{
|
||||
lo = world.getBlockAt(i,j,k).getLocation();
|
||||
id = world.getBlockAt(i,j,k).getTypeId();
|
||||
preciousPatch.put(new EntityPosition(lo),id);
|
||||
}
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
new File("plugins" + sep + "MobArena" + sep + "agbackup").mkdir();
|
||||
FileOutputStream fos = new FileOutputStream("plugins" + sep + "MobArena" + sep + "agbackup" + sep + name + ".tmp");
|
||||
ObjectOutputStream oos = new ObjectOutputStream(fos);
|
||||
oos.writeObject(preciousPatch);
|
||||
oos.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
Messenger.warning("Couldn't create backup file. Aborting auto-generate...");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Build some monster walls.
|
||||
for (int i = x1; i <= x2; i++)
|
||||
{
|
||||
for (int j = y1; j <= y2; j++)
|
||||
{
|
||||
world.getBlockAt(i,j,z1).setTypeId(24);
|
||||
world.getBlockAt(i,j,z2).setTypeId(24);
|
||||
}
|
||||
}
|
||||
for (int k = z1; k <= z2; k++)
|
||||
{
|
||||
for (int j = y1; j <= y2; j++)
|
||||
{
|
||||
world.getBlockAt(x1,j,k).setTypeId(24);
|
||||
world.getBlockAt(x2,j,k).setTypeId(24);
|
||||
}
|
||||
}
|
||||
|
||||
// Add some hippie light.
|
||||
for (int i = x1; i <= x2; i++)
|
||||
{
|
||||
world.getBlockAt(i,y1+2,z1).setTypeId(89);
|
||||
world.getBlockAt(i,y1+2,z2).setTypeId(89);
|
||||
}
|
||||
for (int k = z1; k <= z2; k++)
|
||||
{
|
||||
world.getBlockAt(x1,y1+2,k).setTypeId(89);
|
||||
world.getBlockAt(x2,y1+2,k).setTypeId(89);
|
||||
}
|
||||
|
||||
// Build a monster floor, and some Obsidian foundation.
|
||||
for (int i = x1; i <= x2; i++)
|
||||
{
|
||||
for (int k = z1; k <= z2; k++)
|
||||
{
|
||||
world.getBlockAt(i,y1,k).setTypeId(24);
|
||||
world.getBlockAt(i,y1-1,k).setTypeId(49);
|
||||
}
|
||||
}
|
||||
|
||||
// Make a hippie roof.
|
||||
for (int i = x1; i <= x2; i++)
|
||||
{
|
||||
for (int k = z1; k <= z2; k++)
|
||||
world.getBlockAt(i,y2,k).setTypeId(20);
|
||||
}
|
||||
|
||||
// Monster bulldoze
|
||||
for (int i = x1+1; i < x2; i++)
|
||||
for (int j = y1+1; j < y2; j++)
|
||||
for (int k = z1+1; k < z2; k++)
|
||||
world.getBlockAt(i,j,k).setTypeId(0);
|
||||
|
||||
// Build a hippie lobby
|
||||
for (int i = lx1; i <= lx2; i++) // Walls
|
||||
{
|
||||
for (int j = ly1; j <= ly2; j++)
|
||||
{
|
||||
world.getBlockAt(i,j,lz1).setTypeId(24);
|
||||
world.getBlockAt(i,j,lz2).setTypeId(24);
|
||||
}
|
||||
}
|
||||
for (int k = lz1; k <= lz2; k++) // Walls
|
||||
{
|
||||
for (int j = ly1; j <= ly2; j++)
|
||||
{
|
||||
world.getBlockAt(lx1,j,k).setTypeId(24);
|
||||
world.getBlockAt(lx2,j,k).setTypeId(24);
|
||||
}
|
||||
}
|
||||
for (int k = lz1; k <= lz2; k++) // Lights
|
||||
{
|
||||
world.getBlockAt(lx1,ly1+2,k).setTypeId(89);
|
||||
world.getBlockAt(lx2,ly1+2,k).setTypeId(89);
|
||||
world.getBlockAt(lx1,ly1+3,k).setTypeId(89);
|
||||
world.getBlockAt(lx2,ly1+3,k).setTypeId(89);
|
||||
}
|
||||
for (int i = lx1; i <= lx2; i++) // Floor
|
||||
{
|
||||
for (int k = lz1; k <= lz2; k++)
|
||||
world.getBlockAt(i,ly1,k).setTypeId(24);
|
||||
}
|
||||
for (int i = x1+1; i < lx2; i++) // Bulldoze
|
||||
for (int j = ly1+1; j <= ly2; j++)
|
||||
for (int k = lz1+1; k < lz2; k++)
|
||||
world.getBlockAt(i,j,k).setTypeId(0);
|
||||
|
||||
// Place the hippie signs
|
||||
//Iterator<String> iterator = am.getClasses().iterator();
|
||||
Iterator<String> iterator = am.getClasses().keySet().iterator();
|
||||
for (int i = lx1+2; i <= lx2-2; i++) // Signs
|
||||
{
|
||||
world.getBlockAt(i,ly1+1,lz2-1).setTypeIdAndData(63, (byte)0x8, false);
|
||||
Sign sign = (Sign) world.getBlockAt(i,ly1+1,lz2-1).getState();
|
||||
sign.setLine(0, TextUtils.camelCase((String)iterator.next()));
|
||||
sign.update();
|
||||
}
|
||||
world.getBlockAt(lx2-2,ly1+1,lz1+2).setType(Material.IRON_BLOCK);
|
||||
|
||||
// Set up the monster points.
|
||||
ArenaRegion region = arena.getRegion();
|
||||
region.set("p1", new Location(world, x1, ly1, z1));
|
||||
region.set("p2", new Location(world, x2, y2+1, z2));
|
||||
|
||||
region.set("arena", new Location(world, loc.getX(), y1+1, loc.getZ()));
|
||||
region.set("lobby", new Location(world, x1+2, ly1+1, z1+2));
|
||||
region.set("spectator", new Location(world, loc.getX(), y2+1, loc.getZ()));
|
||||
|
||||
region.addSpawn("s1", new Location(world, x1+3, y1+2, z1+3));
|
||||
region.addSpawn("s2", new Location(world, x1+3, y1+2, z2-3));
|
||||
region.addSpawn("s3", new Location(world, x2-3, y1+2, z1+3));
|
||||
region.addSpawn("s4", new Location(world, x2-3, y1+2, z2-3));
|
||||
region.save();
|
||||
|
||||
am.reloadConfig();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This fixes everything!
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static boolean undoItHippieMonster(String name, MobArena plugin, boolean error)
|
||||
{
|
||||
File file = new File("plugins" + sep + "MobArena" + sep + "agbackup" + sep + name + ".tmp");
|
||||
HashMap<EntityPosition,Integer> preciousPatch;
|
||||
try
|
||||
{
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
ObjectInputStream ois = new ObjectInputStream(fis);
|
||||
preciousPatch = (HashMap<EntityPosition,Integer>) ois.readObject();
|
||||
ois.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (error) Messenger.warning("Couldn't find backup file for arena '" + name + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
World world = plugin.getServer().getWorld(preciousPatch.keySet().iterator().next().getWorld());
|
||||
|
||||
for (Map.Entry<EntityPosition,Integer> entry : preciousPatch.entrySet())
|
||||
{
|
||||
world.getBlockAt(entry.getKey().getLocation(world)).setTypeId(entry.getValue());
|
||||
}
|
||||
|
||||
plugin.getConfig().set("arenas." + name, null);
|
||||
plugin.saveConfig();
|
||||
|
||||
file.delete();
|
||||
|
||||
plugin.getArenaMaster().reloadConfig();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public class Messenger
|
||||
{
|
||||
private static final Logger log = Logger.getLogger("Minecraft");
|
||||
|
||||
private static final String prefix = "[MobArena] ";
|
||||
|
||||
private Messenger() {}
|
||||
|
||||
public static boolean tell(CommandSender p, String msg) {
|
||||
// If the input sender is null or the string is empty, return.
|
||||
if (p == null || msg.equals("")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, send the message with the [MobArena] tag.
|
||||
p.sendMessage(ChatColor.GREEN + "[MobArena] " + ChatColor.RESET + msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean tell(CommandSender p, Msg msg, String s) {
|
||||
return tell(p, msg.format(s));
|
||||
}
|
||||
|
||||
public static boolean tell(CommandSender p, Msg msg) {
|
||||
return tell(p, msg.toString());
|
||||
}
|
||||
|
||||
public static void announce(Arena arena, String msg) {
|
||||
List<Player> players = new ArrayList<Player>();
|
||||
players.addAll(arena.getPlayersInArena());
|
||||
players.addAll(arena.getPlayersInLobby());
|
||||
players.addAll(arena.getSpectators());
|
||||
for (Player p : players) {
|
||||
tell(p, msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static void announce(Arena arena, Msg msg, String s) {
|
||||
announce(arena, msg.format(s));
|
||||
}
|
||||
|
||||
public static void announce(Arena arena, Msg msg) {
|
||||
announce(arena, msg.toString());
|
||||
}
|
||||
|
||||
public static void info(String msg) {
|
||||
log.info(prefix + msg);
|
||||
}
|
||||
|
||||
public static void warning(String msg) {
|
||||
log.warning(prefix + msg);
|
||||
}
|
||||
|
||||
public static void severe(String msg) {
|
||||
log.severe(prefix + msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import net.milkbowl.vault.economy.Economy;
|
||||
import net.milkbowl.vault.economy.EconomyResponse;
|
||||
import net.milkbowl.vault.economy.EconomyResponse.ResponseType;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.bukkit.plugin.ServicesManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.garbagemule.MobArena.commands.CommandHandler;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.listeners.MAGlobalListener;
|
||||
import com.garbagemule.MobArena.listeners.MagicSpellsListener;
|
||||
import com.garbagemule.MobArena.metrics.Metrics;
|
||||
import com.garbagemule.MobArena.util.VersionChecker;
|
||||
import com.garbagemule.MobArena.util.config.ConfigUtils;
|
||||
import com.garbagemule.MobArena.util.inventory.InventoryManager;
|
||||
import com.garbagemule.MobArena.waves.ability.AbilityManager;
|
||||
|
||||
/**
|
||||
* MobArena
|
||||
* @author garbagemule
|
||||
*/
|
||||
public class MobArena extends JavaPlugin
|
||||
{
|
||||
private ArenaMaster arenaMaster;
|
||||
private CommandHandler commandHandler;
|
||||
|
||||
// Inventories from disconnects
|
||||
private Set<String> inventoriesToRestore;
|
||||
|
||||
// Vault
|
||||
private Economy economy;
|
||||
|
||||
private File configFile;
|
||||
private FileConfiguration config;
|
||||
|
||||
public static final double MIN_PLAYER_DISTANCE_SQUARED = 225D;
|
||||
public static final int ECONOMY_MONEY_ID = -29;
|
||||
public static Random random = new Random();
|
||||
|
||||
public void onEnable() {
|
||||
// Initialize config-file
|
||||
configFile = new File(getDataFolder(), "config.yml");
|
||||
config = new YamlConfiguration();
|
||||
reloadConfig();
|
||||
|
||||
// Set the header and save
|
||||
getConfig().options().header(getHeader());
|
||||
saveConfig();
|
||||
|
||||
// Initialize announcements-file
|
||||
loadAnnouncementsFile();
|
||||
|
||||
// Load boss abilities
|
||||
loadAbilities();
|
||||
|
||||
// Set up soft dependencies
|
||||
setupVault();
|
||||
setupMagicSpells();
|
||||
|
||||
// Set up the ArenaMaster
|
||||
arenaMaster = new ArenaMasterImpl(this);
|
||||
arenaMaster.initialize();
|
||||
|
||||
// Register any inventories to restore.
|
||||
registerInventories();
|
||||
|
||||
// Register event listeners
|
||||
registerListeners();
|
||||
|
||||
// Go go Metrics
|
||||
startMetrics();
|
||||
|
||||
// Announce enable!
|
||||
Messenger.info("v" + this.getDescription().getVersion() + " enabled.");
|
||||
|
||||
// Check for updates
|
||||
if (getConfig().getBoolean("global-settings.update-notification", false)) {
|
||||
VersionChecker.checkForUpdates(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
// Force all arenas to end.
|
||||
if (arenaMaster == null) return;
|
||||
for (Arena arena : arenaMaster.getArenas()) {
|
||||
arena.forceEnd();
|
||||
}
|
||||
arenaMaster.resetArenaMap();
|
||||
VersionChecker.shutdown();
|
||||
|
||||
Messenger.info("disabled.");
|
||||
}
|
||||
|
||||
public File getPluginFile() {
|
||||
return getFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileConfiguration getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadConfig() {
|
||||
// Check if the config-file exists
|
||||
if (!configFile.exists()) {
|
||||
Messenger.info("No config-file found, creating default...");
|
||||
saveDefaultConfig();
|
||||
}
|
||||
|
||||
// Check for tab characters in config-file
|
||||
BufferedReader in = null;
|
||||
try {
|
||||
in = new BufferedReader(new FileReader(new File(getDataFolder(), "config.yml")));
|
||||
int row = 0;
|
||||
String line;
|
||||
while ((line = in.readLine()) != null) {
|
||||
row++;
|
||||
if (line.indexOf('\t') != -1) {
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
buffy.append("Found tab in config-file on line ").append(row).append(".");
|
||||
buffy.append('\n').append("NEVER use tabs! ALWAYS use spaces!");
|
||||
buffy.append('\n').append(line);
|
||||
buffy.append('\n');
|
||||
for (int i = 0; i < line.indexOf('\t'); i++) {
|
||||
buffy.append(' ');
|
||||
}
|
||||
buffy.append('^');
|
||||
throw new IllegalArgumentException(buffy.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// Actually reload the config-file
|
||||
config.load(configFile);
|
||||
} catch (InvalidConfigurationException e) {
|
||||
throw new RuntimeException("\n\n>>>\n>>> There is an error in your config-file! Handle it!\n>>> Here is what snakeyaml says:\n>>>\n\n" + e.getMessage());
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new IllegalStateException("Config-file could not be created for some reason! <o>");
|
||||
} catch (IOException e) {
|
||||
// Error reading the file, just re-throw
|
||||
Messenger.severe("There was an error reading the config-file:\n" + e.getMessage());
|
||||
} finally {
|
||||
// Java 6 <3
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
// Swallow
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveConfig() {
|
||||
try {
|
||||
config.save(configFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadAnnouncementsFile() {
|
||||
// Create if missing
|
||||
File file = new File(getDataFolder(), "announcements.yml");
|
||||
try {
|
||||
if (file.createNewFile()) {
|
||||
Messenger.info("announcements.yml created.");
|
||||
YamlConfiguration yaml = Msg.toYaml();
|
||||
yaml.save(file);
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Otherwise, load the announcements from the file
|
||||
try {
|
||||
YamlConfiguration yaml = new YamlConfiguration();
|
||||
yaml.load(file);
|
||||
ConfigUtils.addMissingRemoveObsolete(file, Msg.toYaml(), yaml);
|
||||
Msg.load(yaml);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void registerListeners() {
|
||||
// Bind the /ma, /mobarena commands to MACommands.
|
||||
commandHandler = new CommandHandler(this);
|
||||
getCommand("ma").setExecutor(commandHandler);
|
||||
getCommand("mobarena").setExecutor(commandHandler);
|
||||
|
||||
PluginManager pm = this.getServer().getPluginManager();
|
||||
pm.registerEvents(new MAGlobalListener(this, arenaMaster), this);
|
||||
}
|
||||
|
||||
// Permissions stuff
|
||||
public boolean has(Player p, String s) {
|
||||
return p.hasPermission(s);
|
||||
}
|
||||
|
||||
public boolean has(CommandSender sender, String s) {
|
||||
if (sender instanceof ConsoleCommandSender) {
|
||||
return true;
|
||||
}
|
||||
return has((Player) sender, s);
|
||||
}
|
||||
|
||||
private void setupVault() {
|
||||
Plugin vaultPlugin = this.getServer().getPluginManager().getPlugin("Vault");
|
||||
if (vaultPlugin == null) {
|
||||
Messenger.warning("Vault was not found. Economy rewards will not work!");
|
||||
return;
|
||||
}
|
||||
|
||||
ServicesManager manager = this.getServer().getServicesManager();
|
||||
RegisteredServiceProvider<Economy> e = manager.getRegistration(net.milkbowl.vault.economy.Economy.class);
|
||||
|
||||
if (e != null) {
|
||||
economy = e.getProvider();
|
||||
Messenger.info("Vault found; economy rewards enabled.");
|
||||
} else {
|
||||
Messenger.warning("Vault found, but no economy plugin detected. Economy rewards will not work!");
|
||||
}
|
||||
}
|
||||
|
||||
private void setupMagicSpells() {
|
||||
Plugin spells = this.getServer().getPluginManager().getPlugin("MagicSpells");
|
||||
if (spells == null) return;
|
||||
|
||||
Messenger.info("MagicSpells found, loading config-file.");
|
||||
this.getServer().getPluginManager().registerEvents(new MagicSpellsListener(this), this);
|
||||
}
|
||||
|
||||
private void loadAbilities() {
|
||||
File dir = new File(this.getDataFolder(), "abilities");
|
||||
if (!dir.exists()) dir.mkdir();
|
||||
|
||||
AbilityManager.loadCoreAbilities();
|
||||
AbilityManager.loadCustomAbilities(dir);
|
||||
}
|
||||
|
||||
private void startMetrics() {
|
||||
try {
|
||||
Metrics m = new Metrics(this);
|
||||
m.start();
|
||||
} catch (Exception e) {
|
||||
Messenger.warning("y u disable stats :(");
|
||||
}
|
||||
}
|
||||
|
||||
public ArenaMaster getArenaMaster() {
|
||||
return arenaMaster;
|
||||
}
|
||||
|
||||
public CommandHandler getCommandHandler() {
|
||||
return commandHandler;
|
||||
}
|
||||
|
||||
private String getHeader() {
|
||||
String sep = System.getProperty("line.separator");
|
||||
return "MobArena v" + this.getDescription().getVersion() + " - Config-file" + sep +
|
||||
"Read the Wiki for details on how to set up this file: http://goo.gl/F5TTc" + sep +
|
||||
"Note: You -must- use spaces instead of tabs!";
|
||||
}
|
||||
|
||||
private void registerInventories() {
|
||||
this.inventoriesToRestore = new HashSet<String>();
|
||||
|
||||
File dir = new File(getDataFolder(), "inventories");
|
||||
if (!dir.exists()) {
|
||||
dir.mkdir();
|
||||
return;
|
||||
}
|
||||
|
||||
for (File f : dir.listFiles()) {
|
||||
if (f.getName().endsWith(".inv")) {
|
||||
inventoriesToRestore.add(f.getName().substring(0, f.getName().indexOf(".")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void restoreInventory(Player p) {
|
||||
if (!inventoriesToRestore.contains(p.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (InventoryManager.restoreFromFile(this, p)) {
|
||||
inventoriesToRestore.remove(p.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean giveMoney(Player p, ItemStack item) {
|
||||
if (economy != null) {
|
||||
EconomyResponse result = economy.depositPlayer(p.getName(), getAmount(item));
|
||||
return (result.type == ResponseType.SUCCESS);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean takeMoney(Player p, ItemStack item) {
|
||||
return takeMoney(p, getAmount(item));
|
||||
}
|
||||
|
||||
public boolean takeMoney(Player p, double amount) {
|
||||
if (economy != null) {
|
||||
EconomyResponse result = economy.withdrawPlayer(p.getName(), amount);
|
||||
return (result.type == ResponseType.SUCCESS);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasEnough(Player p, ItemStack item) {
|
||||
return hasEnough(p, getAmount(item));
|
||||
}
|
||||
|
||||
public boolean hasEnough(Player p, double amount) {
|
||||
return economy == null || (economy.getBalance(p.getName()) >= amount);
|
||||
}
|
||||
|
||||
public String economyFormat(ItemStack item) {
|
||||
return economyFormat(getAmount(item));
|
||||
}
|
||||
|
||||
public String economyFormat(double amount) {
|
||||
return economy == null ? null : economy.format(amount);
|
||||
}
|
||||
|
||||
private double getAmount(ItemStack item) {
|
||||
double major = item.getAmount();
|
||||
double minor = item.getDurability() / 100D;
|
||||
return major + minor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public class MobArenaHandler
|
||||
{
|
||||
private MobArena plugin;
|
||||
|
||||
/**
|
||||
* Primary constructor.
|
||||
* The field 'plugin' is initalized, if the server is running MobArena.
|
||||
*/
|
||||
public MobArenaHandler() {
|
||||
plugin = (MobArena) Bukkit.getServer().getPluginManager().getPlugin("MobArena");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////
|
||||
|
||||
REGION/LOCATION METHODS
|
||||
|
||||
//////////////////////////////////////////////////////////////////*/
|
||||
|
||||
/**
|
||||
* Check if a Location is inside of any arena region.
|
||||
* @param loc A location.
|
||||
* @return true, if the Location is inside of any arena region.
|
||||
*/
|
||||
public boolean inRegion(Location loc) {
|
||||
for (Arena arena : plugin.getArenaMaster().getArenas()) {
|
||||
if (arena.getRegion().contains(loc)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Location is inside of a specific arena region (by arena object).
|
||||
* @param arena An Arena object
|
||||
* @param loc A location
|
||||
* @return true, if the Location is inside of the arena region.
|
||||
*/
|
||||
public boolean inRegion(Arena arena, Location loc) {
|
||||
return (arena != null && arena.getRegion().contains(loc));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Location is inside of a specific arena region (by arena name).
|
||||
* @param arenaName The name of an arena
|
||||
* @param loc A location
|
||||
* @return true, if the Location is inside of the arena region.
|
||||
*/
|
||||
public boolean inRegion(String arenaName, Location loc) {
|
||||
Arena arena = plugin.getArenaMaster().getArenaWithName(arenaName);
|
||||
if (arena == null)
|
||||
throw new NullPointerException("There is no arena with that name");
|
||||
|
||||
return arena.getRegion().contains(loc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Location is inside of the region of an arena that is currently running.
|
||||
* @param loc A location.
|
||||
* @return true, if the Location is inside of the region of an arena that is currently running.
|
||||
*/
|
||||
public boolean inRunningRegion(Location loc) {
|
||||
return inRegion(loc, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Location is inside of the region of an arena that is currently enabled.
|
||||
* @param loc A location.
|
||||
* @return true, if the Location is inside of the region of an arena that is currently enabled.
|
||||
*/
|
||||
public boolean inEnabledRegion(Location loc) {
|
||||
return inRegion(loc, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private helper method for inRunningRegion and inEnabledRegion
|
||||
* @param loc A location
|
||||
* @param enabled if true, the method will check if the arena is enabled
|
||||
* @param running if true, the method will check if the arena is running, overrides enabled
|
||||
* @return true, if the location is inside of the region of an arena that is currently enabled/running, depending on the parameters.
|
||||
*/
|
||||
private boolean inRegion(Location loc, boolean enabled, boolean running) {
|
||||
// If the plugin doesn't exist, always return false.
|
||||
if (plugin.getArenaMaster() == null) return false;
|
||||
|
||||
// Return true if location is within just one arena's region.
|
||||
for (Arena arena : plugin.getArenaMaster().getArenas()) {
|
||||
if (arena.getRegion().contains(loc)) {
|
||||
if ((running && arena.isRunning()) || (enabled && arena.isEnabled())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////
|
||||
|
||||
PLAYER/MONSTER/PET METHODS
|
||||
|
||||
//////////////////////////////////////////////////////////////////*/
|
||||
|
||||
/**
|
||||
* Check if a player is in a MobArena arena (by Player).
|
||||
* @param player The player
|
||||
* @return true, if the player is in an arena
|
||||
*/
|
||||
public boolean isPlayerInArena(Player player) {
|
||||
return (plugin.getArenaMaster().getArenaWithPlayer(player) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a player is in a MobArena arena (by name).
|
||||
* @param playerName The name of the player
|
||||
* @return true, if the player is in an arena
|
||||
*/
|
||||
public boolean isPlayerInArena(String playerName) {
|
||||
return (plugin.getArenaMaster().getArenaWithPlayer(playerName) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MobArena class of a given player.
|
||||
* @param player The player
|
||||
* @return The class name of the player if the player is in the arena, null otherwise
|
||||
*/
|
||||
public String getPlayerClass(Player player) {
|
||||
Arena arena = plugin.getArenaMaster().getArenaWithPlayer(player);
|
||||
if (arena == null) return null;
|
||||
|
||||
return getPlayerClass(arena, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MobArena class of a given player in a given arena.
|
||||
* This method is faster than the above method, granted the Arena object is known.
|
||||
* @param arena The MobArena arena to check in
|
||||
* @param player The player to look up
|
||||
* @return The class name of the player, if the player is in the arena, null otherwise
|
||||
*/
|
||||
public String getPlayerClass(Arena arena, Player player) {
|
||||
ArenaPlayer ap = arena.getArenaPlayer(player);
|
||||
if (ap == null) return null;
|
||||
|
||||
ArenaClass ac = ap.getArenaClass();
|
||||
if (ac == null) return null;
|
||||
|
||||
return ac.getLowercaseName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a monster is in a MobArena arena.
|
||||
* @param entity The monster entity
|
||||
* @return true, if the monster is in an arena
|
||||
*/
|
||||
public boolean isMonsterInArena(LivingEntity entity) {
|
||||
return plugin.getArenaMaster().getArenaWithMonster(entity) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a pet is in a MobArena arena.
|
||||
* @param wolf The pet wolf
|
||||
* @return true, if the pet is in an arena
|
||||
*/
|
||||
public boolean isPetInArena(LivingEntity wolf) {
|
||||
return plugin.getArenaMaster().getArenaWithPet(wolf) != null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////
|
||||
|
||||
ARENA GETTERS
|
||||
|
||||
//////////////////////////////////////////////////////////////////*/
|
||||
|
||||
/**
|
||||
* Get an Arena object at the given location.
|
||||
* @param loc A location
|
||||
* @return an Arena object, or null
|
||||
*/
|
||||
public Arena getArenaAtLocation(Location loc) {
|
||||
return plugin.getArenaMaster().getArenaAtLocation(loc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Arena object that the given player is currently in.
|
||||
* @param p A player
|
||||
* @return an Arena object, or null
|
||||
*/
|
||||
public Arena getArenaWithPlayer(Player p) {
|
||||
return plugin.getArenaMaster().getArenaWithPlayer(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Arena object that the given pet is currently in.
|
||||
* @param wolf A pet wolf
|
||||
* @return an Arena object, or null
|
||||
*/
|
||||
public Arena getArenaWithPet(Entity wolf) {
|
||||
return plugin.getArenaMaster().getArenaWithPet(wolf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Arena object that the given monster is currently in.
|
||||
* @param monster A monster
|
||||
* @return an Arena object, or null
|
||||
*/
|
||||
public Arena getArenaWithMonster(Entity monster) {
|
||||
return plugin.getArenaMaster().getArenaWithMonster(monster);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Wolf;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.garbagemule.MobArena.waves.MABoss;
|
||||
|
||||
public class MonsterManager
|
||||
{
|
||||
private Set<LivingEntity> monsters, sheep, golems;
|
||||
private Set<Wolf> pets;
|
||||
private Map<LivingEntity,MABoss> bosses;
|
||||
private Map<LivingEntity,List<ItemStack>> suppliers;
|
||||
private Set<LivingEntity> mounts;
|
||||
|
||||
public MonsterManager() {
|
||||
this.monsters = new HashSet<LivingEntity>();
|
||||
this.sheep = new HashSet<LivingEntity>();
|
||||
this.golems = new HashSet<LivingEntity>();
|
||||
this.pets = new HashSet<Wolf>();
|
||||
this.bosses = new HashMap<LivingEntity,MABoss>();
|
||||
this.suppliers = new HashMap<LivingEntity,List<ItemStack>>();
|
||||
this.mounts = new HashSet<LivingEntity>();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
monsters.clear();
|
||||
sheep.clear();
|
||||
golems.clear();
|
||||
pets.clear();
|
||||
bosses.clear();
|
||||
suppliers.clear();
|
||||
mounts.clear();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
removeAll(monsters);
|
||||
removeAll(sheep);
|
||||
removeAll(golems);
|
||||
removeAll(pets);
|
||||
removeAll(bosses.keySet());
|
||||
removeAll(suppliers.keySet());
|
||||
removeAll(mounts);
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
private void removeAll(Collection<? extends LivingEntity> collection) {
|
||||
for (LivingEntity e : collection) {
|
||||
if (e != null) {
|
||||
e.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(Entity e) {
|
||||
if (monsters.remove(e)) {
|
||||
sheep.remove(e);
|
||||
golems.remove(e);
|
||||
pets.remove(e);
|
||||
suppliers.remove(e);
|
||||
MABoss boss = bosses.remove(e);
|
||||
if (boss != null) {
|
||||
boss.setDead(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Set<LivingEntity> getMonsters() {
|
||||
return monsters;
|
||||
}
|
||||
|
||||
public void addMonster(LivingEntity e) {
|
||||
monsters.add(e);
|
||||
}
|
||||
|
||||
public boolean removeMonster(Entity e) {
|
||||
return monsters.remove(e);
|
||||
}
|
||||
|
||||
public Set<LivingEntity> getExplodingSheep() {
|
||||
return sheep;
|
||||
}
|
||||
|
||||
public void addExplodingSheep(LivingEntity e) {
|
||||
sheep.add(e);
|
||||
}
|
||||
|
||||
public boolean removeExplodingSheep(LivingEntity e) {
|
||||
return sheep.remove(e);
|
||||
}
|
||||
|
||||
public Set<LivingEntity> getGolems() {
|
||||
return golems;
|
||||
}
|
||||
|
||||
public void addGolem(LivingEntity e) {
|
||||
golems.add(e);
|
||||
}
|
||||
|
||||
public boolean removeGolem(LivingEntity e) {
|
||||
return golems.remove(e);
|
||||
}
|
||||
|
||||
public Set<Wolf> getPets() {
|
||||
return pets;
|
||||
}
|
||||
|
||||
public void addPet(Wolf w) {
|
||||
pets.add(w);
|
||||
}
|
||||
|
||||
public boolean hasPet(Entity e) {
|
||||
return pets.contains(e);
|
||||
}
|
||||
|
||||
public void removePets(Player p) {
|
||||
for (Wolf w : pets) {
|
||||
if (w == null || !(w.getOwner() instanceof Player) || !((Player) w.getOwner()).getName().equals(p.getName()))
|
||||
continue;
|
||||
|
||||
w.setOwner(null);
|
||||
w.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public void addMount(LivingEntity e) {
|
||||
mounts.add(e);
|
||||
}
|
||||
|
||||
public boolean hasMount(Entity e) {
|
||||
return mounts.contains(e);
|
||||
}
|
||||
|
||||
public boolean removeMount(Entity e) {
|
||||
return mounts.remove(e);
|
||||
}
|
||||
|
||||
public void removeMounts() {
|
||||
for (LivingEntity e : mounts) {
|
||||
e.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public void addSupplier(LivingEntity e, List<ItemStack> drops) {
|
||||
suppliers.put(e, drops);
|
||||
}
|
||||
|
||||
public List<ItemStack> getLoot(Entity e) {
|
||||
return suppliers.get(e);
|
||||
}
|
||||
|
||||
public MABoss addBoss(LivingEntity e, double maxHealth) {
|
||||
MABoss b = new MABoss(e, maxHealth);
|
||||
bosses.put(e, b);
|
||||
return b;
|
||||
}
|
||||
|
||||
public MABoss removeBoss(LivingEntity e) {
|
||||
return bosses.remove(e);
|
||||
}
|
||||
|
||||
public MABoss getBoss(LivingEntity e) {
|
||||
return bosses.get(e);
|
||||
}
|
||||
|
||||
public Set<LivingEntity> getBossMonsters() {
|
||||
return bosses.keySet();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
public enum Msg {
|
||||
ARENA_START("Let the slaughter begin!"),
|
||||
ARENA_END("Arena finished."),
|
||||
ARENA_DOES_NOT_EXIST("That arena does not exist. Type &e/ma arenas&r for a list."),
|
||||
ARENA_END_GLOBAL("Arena &e%&r finished! Type &e/ma j %&r to join a new game!"),
|
||||
ARENA_JOIN_GLOBAL("Arena &e%&r is about to start! Type &e/ma j %&r to join!"),
|
||||
ARENA_LBOARD_NOT_FOUND("That arena does not have a leaderboard set up."),
|
||||
ARENA_AUTO_START("Arena will auto-start in &c%&r seconds."),
|
||||
ARENA_START_DELAY("Arena can start in &e%&r seconds."),
|
||||
JOIN_NOT_ENABLED("MobArena is not enabled."),
|
||||
JOIN_IN_OTHER_ARENA("You are already in an arena! Leave that one first."),
|
||||
JOIN_ARENA_NOT_ENABLED("This arena is not enabled."),
|
||||
JOIN_ARENA_NOT_SETUP("This arena has not been set up yet."),
|
||||
JOIN_ARENA_EDIT_MODE("This arena is in edit mode."),
|
||||
JOIN_ARENA_PERMISSION("You don't have permission to join this arena."),
|
||||
JOIN_FEE_REQUIRED("Insufficient funds. Price: &c%&r"),
|
||||
JOIN_FEE_PAID("Price to join was: &c%&r"),
|
||||
JOIN_ARENA_IS_RUNNING("This arena is already in progress."),
|
||||
JOIN_ALREADY_PLAYING("You are already playing!"),
|
||||
JOIN_ARG_NEEDED("You must specify an arena."),
|
||||
JOIN_NO_PERMISSION("You don't have permission to join any arenas."),
|
||||
JOIN_TOO_FAR("You are too far away from the arena to join/spectate."),
|
||||
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_NOT_READY("You did not ready up in time! Next time, ready up by clicking an iron block."),
|
||||
LEAVE_PLAYER_LEFT("You left the arena. Thanks for playing!"),
|
||||
PLAYER_DIED("&c%&r died!"),
|
||||
GOLEM_DIED("A friendly Golem has died!"),
|
||||
SPEC_PLAYER_SPECTATE("Enjoy the show!"),
|
||||
SPEC_FROM_ARENA("Enjoy the rest of the show!"),
|
||||
SPEC_NOT_RUNNING("This arena isn't running."),
|
||||
SPEC_EMPTY_INV("Empty your inventory first!"),
|
||||
SPEC_ALREADY_PLAYING("Can't spectate when in the arena!"),
|
||||
NOT_READY_PLAYERS("Not ready: &c%&r"),
|
||||
FORCE_START_RUNNING("Arena has already started."),
|
||||
FORCE_START_NOT_READY("Can't force start, no players are ready."),
|
||||
FORCE_START_STARTED("Forced arena start."),
|
||||
FORCE_END_EMPTY("No one is in the arena."),
|
||||
FORCE_END_ENDED("Forced arena end."),
|
||||
FORCE_END_IDLE("You weren't quick enough!"),
|
||||
REWARDS_GIVE("Here are all of your rewards!"),
|
||||
LOBBY_DROP_ITEM("No sharing allowed at this time!"),
|
||||
LOBBY_PLAYER_READY("You have been flagged as ready!"),
|
||||
LOBBY_PICK_CLASS("You must first pick a class!"),
|
||||
LOBBY_CLASS_FULL("This class can no longer be selected, class limit reached!"),
|
||||
LOBBY_NOT_ENOUGH_PLAYERS("Not enough players to start. Need at least &c%&r players."),
|
||||
LOBBY_RIGHT_CLICK("Punch the sign. Don't right-click."),
|
||||
LOBBY_CLASS_PICKED("You have chosen &e%&r as your class!"),
|
||||
LOBBY_CLASS_RANDOM("You will get a random class on arena start."),
|
||||
LOBBY_CLASS_PERMISSION("You don't have permission to use this class!"),
|
||||
LOBBY_CLASS_PRICE("This class costs &c%&r (paid on arena start)."),
|
||||
LOBBY_CLASS_TOO_EXPENSIVE("You can't afford that class (&c%&r)"),
|
||||
LOBBY_NO_SUCH_CLASS("There is no class named &c%&r."),
|
||||
WARP_TO_ARENA("Warping to the arena not allowed!"),
|
||||
WARP_FROM_ARENA("Warping from the arena not allowed!"),
|
||||
WAVE_DEFAULT("Wave &b#%&r!"),
|
||||
WAVE_SPECIAL("Wave &b#%&r! [SPECIAL]"),
|
||||
WAVE_SWARM("Wave &b#%&r! [SWARM]"),
|
||||
WAVE_SUPPLY("Wave &b#%&r! [SUPPLY]"),
|
||||
WAVE_UPGRADE("Wave &b#%&r! [UPGRADE]"),
|
||||
WAVE_BOSS("Wave &b#%&r! [BOSS]"),
|
||||
WAVE_BOSS_ABILITY("Boss used ability: &c%&r!"),
|
||||
WAVE_BOSS_LOW_HEALTH("Boss is almost dead!"),
|
||||
WAVE_REWARD("You just earned a reward: &e%&r"),
|
||||
MISC_LIST_PLAYERS("Live players: &a%&r"),
|
||||
MISC_LIST_ARENAS("Available arenas: %"),
|
||||
MISC_COMMAND_NOT_ALLOWED("You can't use that command in the arena!"),
|
||||
MISC_NO_ACCESS("You don't have access to this command."),
|
||||
MISC_NOT_FROM_CONSOLE("You can't use this command from the console."),
|
||||
MISC_HELP("For a list of commands, type &e/ma help&r"),
|
||||
MISC_MULTIPLE_MATCHES("Did you mean one of these commands?"),
|
||||
MISC_NO_MATCHES("Command not found. Type &e/ma help&r"),
|
||||
MISC_MA_LEAVE_REMINDER("Remember to use &e/ma leave&r when you are done."),
|
||||
MISC_NONE("&6<none>&r");
|
||||
|
||||
private String value;
|
||||
|
||||
private Msg(String value) {
|
||||
set(value);
|
||||
}
|
||||
|
||||
void set(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return ChatColor.translateAlternateColorCodes('&', value);
|
||||
}
|
||||
|
||||
public String format(String s) {
|
||||
return (s == null) ? "" : toString().replace("%", s);
|
||||
}
|
||||
|
||||
static void load(ConfigurationSection config) {
|
||||
for (Msg msg : values()) {
|
||||
// ARENA_END_GLOBAL => arena-end-global
|
||||
String key = msg.name().toLowerCase().replace("_","-");
|
||||
msg.set(config.getString(key, ""));
|
||||
}
|
||||
}
|
||||
|
||||
static YamlConfiguration toYaml() {
|
||||
YamlConfiguration yaml = new YamlConfiguration();
|
||||
for (Msg msg : values()) {
|
||||
// ARENA_END_GLOBAL => arena-end-global
|
||||
String key = msg.name().replace("_","-").toLowerCase();
|
||||
yaml.set(key, msg.value);
|
||||
}
|
||||
return yaml;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
public class PlayerData
|
||||
{
|
||||
private Player player;
|
||||
|
||||
private double health;
|
||||
private int food, level;
|
||||
private float exp;
|
||||
private GameMode mode = null;
|
||||
private Location entry = null;
|
||||
private Collection<PotionEffect> potions;
|
||||
|
||||
public PlayerData(Player player, Location loc) {
|
||||
this.player = player;
|
||||
this.mode = player.getGameMode();
|
||||
this.potions = player.getActivePotionEffects();
|
||||
this.entry = loc;
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the information that is restored, when a player
|
||||
* dies in the arena, that is, health, food level, and
|
||||
* experience. Used when a player re-joins an arena while
|
||||
* already being a spectator.
|
||||
*/
|
||||
public void update() {
|
||||
this.health = player.getHealth();
|
||||
this.food = player.getFoodLevel();
|
||||
this.level = player.getLevel();
|
||||
this.exp = player.getExp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores health, food level, and experience as per the
|
||||
* currently stored values of this object. Used when a
|
||||
* player leaves the arena.
|
||||
*/
|
||||
public void restoreData() {
|
||||
player.setFoodLevel(food);
|
||||
player.setLevel(level);
|
||||
player.setExp(exp);
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public double health() {
|
||||
return health;
|
||||
}
|
||||
|
||||
public void setHealth(int health) {
|
||||
this.health = health;
|
||||
}
|
||||
|
||||
public int food() {
|
||||
return food;
|
||||
}
|
||||
|
||||
public void setFood(int food) {
|
||||
this.food = food;
|
||||
}
|
||||
|
||||
public int level() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public void setLevel(int level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public float exp() {
|
||||
return exp;
|
||||
}
|
||||
|
||||
public void setExp(int exp) {
|
||||
this.exp = exp;
|
||||
}
|
||||
|
||||
public GameMode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public Collection<PotionEffect> getPotionEffects() {
|
||||
return potions;
|
||||
}
|
||||
|
||||
public void setMode(GameMode mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public Location entry() {
|
||||
return entry;
|
||||
}
|
||||
|
||||
public void setEntry(Location entry) {
|
||||
this.entry = entry;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public class RewardManager
|
||||
{
|
||||
@SuppressWarnings("unused")
|
||||
private MobArena plugin;
|
||||
@SuppressWarnings("unused")
|
||||
private Arena arena;
|
||||
private Map<Player,List<ItemStack>> players;
|
||||
private Set<Player> rewarded;
|
||||
|
||||
public RewardManager(Arena arena) {
|
||||
this.plugin = arena.getPlugin();
|
||||
this.arena = arena;
|
||||
this.players = new HashMap<Player,List<ItemStack>>();
|
||||
this.rewarded = new HashSet<Player>();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
players.clear();
|
||||
rewarded.clear();
|
||||
}
|
||||
|
||||
public void addReward(Player p, ItemStack stack) {
|
||||
if (!players.containsKey(p)) {
|
||||
players.put(p, new ArrayList<ItemStack>());
|
||||
}
|
||||
players.get(p).add(stack);
|
||||
}
|
||||
|
||||
public List<ItemStack> getRewards(Player p) {
|
||||
List<ItemStack> rewards = players.get(p);
|
||||
return (rewards == null ? new ArrayList<ItemStack>(1) : Collections.unmodifiableList(rewards));
|
||||
}
|
||||
|
||||
public void grantRewards(Player p) {
|
||||
if (rewarded.contains(p)) return;
|
||||
|
||||
List<ItemStack> rewards = players.get(p);
|
||||
if (rewards == null) return;
|
||||
|
||||
for (ItemStack stack : rewards) {
|
||||
if (stack == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stack.getTypeId() == MobArena.ECONOMY_MONEY_ID) {
|
||||
// plugin.giveMoney(p, stack.getAmount()); - removed to fix double money rewards
|
||||
continue;
|
||||
}
|
||||
|
||||
p.getInventory().addItem(stack);
|
||||
}
|
||||
rewarded.add(p);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scoreboard.DisplaySlot;
|
||||
import org.bukkit.scoreboard.Objective;
|
||||
import org.bukkit.scoreboard.Score;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public class ScoreboardManager {
|
||||
private static final String DISPLAY_NAME = ChatColor.GREEN + "Kills " + ChatColor.AQUA + "Wave ";
|
||||
|
||||
private Arena arena;
|
||||
private Scoreboard scoreboard;
|
||||
private Objective kills;
|
||||
|
||||
/**
|
||||
* Create a new scoreboard for the given arena.
|
||||
* @param arena an arena
|
||||
*/
|
||||
ScoreboardManager(Arena arena) {
|
||||
this.arena = arena;
|
||||
scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a player to the scoreboard by setting the player's scoreboard
|
||||
* and giving him an initial to-be-reset non-zero score.
|
||||
* @param player a player
|
||||
*/
|
||||
void addPlayer(Player player) {
|
||||
/* Set the player's scoreboard and give them an initial non-zero
|
||||
* score. This is necessary due to either Minecraft or Bukkit
|
||||
* not wanting to show non-zero scores initially. */
|
||||
player.setScoreboard(scoreboard);
|
||||
kills.getScore(player).setScore(8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a player from the scoreboard by setting the player's scoreboard
|
||||
* to the main server scoreboard.
|
||||
* @param player a player
|
||||
*/
|
||||
void removePlayer(Player player) {
|
||||
player.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a kill to the player's score. Called when a player kills a mob.
|
||||
* @param player a player
|
||||
*/
|
||||
void addKill(Player player) {
|
||||
Score score = kills.getScore(player);
|
||||
score.setScore(score.getScore() + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal a player death.
|
||||
* @param player a player
|
||||
*/
|
||||
void death(Player player) {
|
||||
String name = ChatColor.GRAY + player.getName();
|
||||
if (name.length() > 16) {
|
||||
name = name.substring(0, 15);
|
||||
}
|
||||
|
||||
int value = kills.getScore(player).getScore();
|
||||
scoreboard.resetScores(player);
|
||||
|
||||
/* In case the player has no kills, they will not show up on the
|
||||
* scoreboard unless they are first given a different score.
|
||||
* If zero kills, the score is set to 8 (which looks a bit like
|
||||
* 0), and then in the next tick, it's set to 0. Otherwise, the
|
||||
* score is just set to its current value.
|
||||
*/
|
||||
final Score fake = kills.getScore(Bukkit.getOfflinePlayer(name));
|
||||
if (value == 0) {
|
||||
fake.setScore(8);
|
||||
arena.scheduleTask(new Runnable() {
|
||||
public void run() {
|
||||
fake.setScore(0);
|
||||
}
|
||||
}, 1);
|
||||
} else {
|
||||
fake.setScore(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the scoreboard to display the given wave number.
|
||||
* @param wave a wave number
|
||||
*/
|
||||
void updateWave(int wave) {
|
||||
kills.setDisplayName(DISPLAY_NAME + wave);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the scoreboard by resetting the kills objective and
|
||||
* setting all player scores to 0.
|
||||
*/
|
||||
void initialize() {
|
||||
/* Initialization involves first unregistering the kill counter if
|
||||
* it was already registered, and then setting it back up.
|
||||
* It is necessary to delay the reset of the player scores, and the
|
||||
* reset is necessary because of non-zero crappiness. */
|
||||
resetKills();
|
||||
arena.scheduleTask(new Runnable() {
|
||||
public void run() {
|
||||
for (Player p : arena.getPlayersInArena()) {
|
||||
kills.getScore(p).setScore(0);
|
||||
}
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
|
||||
private void resetKills() {
|
||||
if (kills != null) {
|
||||
kills.unregister();
|
||||
}
|
||||
kills = scoreboard.registerNewObjective("kills", "ma-kills");
|
||||
kills.setDisplaySlot(DisplaySlot.SIDEBAR);
|
||||
updateWave(0);
|
||||
}
|
||||
|
||||
static class NullScoreboardManager extends ScoreboardManager {
|
||||
NullScoreboardManager(Arena arena) {
|
||||
super(arena);
|
||||
}
|
||||
void addPlayer(Player player) {}
|
||||
void removePlayer(Player player) {}
|
||||
void addKill(Player player) {}
|
||||
void death(Player player) {}
|
||||
void updateWave(int wave) {}
|
||||
void initialize() {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.garbagemule.MobArena.commands;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
public interface Command
|
||||
{
|
||||
/**
|
||||
* Execute the command using the given arguments.
|
||||
* <p>
|
||||
* If the method returns false, the command handler will print the usage
|
||||
* message (usage + description) for the command, and as such, if the
|
||||
* execution was successful in any way, the method should return true.
|
||||
* Note that "successful in any way" means if the execution managed to
|
||||
* complete in the sense that it itself prints a message to the sender,
|
||||
* or otherwise executed properly, not if the intent of the command
|
||||
* wasn't fulfilled. Typically, this means that false is only returned
|
||||
* if the command was executed with a set of arguments that did not
|
||||
* match the usage message.
|
||||
*
|
||||
* @param am an ArenaMaster instance
|
||||
* @param sender the sender
|
||||
* @param args array of arguments
|
||||
* @return true, if the command succeeded in any way, false if the
|
||||
* command handler should print the usage message to the sender
|
||||
*/
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args);
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package com.garbagemule.MobArena.commands;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.user.*;
|
||||
import com.garbagemule.MobArena.commands.admin.*;
|
||||
import com.garbagemule.MobArena.commands.setup.*;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import org.bukkit.conversations.Conversable;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class CommandHandler implements CommandExecutor
|
||||
{
|
||||
private MobArena plugin;
|
||||
private ArenaMaster am;
|
||||
|
||||
private Map<String,Command> commands;
|
||||
|
||||
public CommandHandler(MobArena plugin) {
|
||||
this.plugin = plugin;
|
||||
this.am = plugin.getArenaMaster();
|
||||
|
||||
registerCommands();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, org.bukkit.command.Command bcmd, String label, String[] args) {
|
||||
// Grab the base and arguments.
|
||||
String base = (args.length > 0 ? args[0] : "");
|
||||
String last = (args.length > 0 ? args[args.length - 1] : "");
|
||||
|
||||
// If the player is in a convo (Setup Mode), bail
|
||||
if (sender instanceof Conversable && ((Conversable) sender).isConversing()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If there's no base argument, show a helpful message.
|
||||
if (base.equals("")) {
|
||||
Messenger.tell(sender, Msg.MISC_HELP);
|
||||
return true;
|
||||
}
|
||||
|
||||
// The help command is a little special
|
||||
if (base.equals("?") || base.equals("help")) {
|
||||
showHelp(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get all commands that match the base.
|
||||
List<Command> matches = getMatchingCommands(base);
|
||||
|
||||
// If there's more than one match, display them.
|
||||
if (matches.size() > 1) {
|
||||
Messenger.tell(sender, Msg.MISC_MULTIPLE_MATCHES);
|
||||
for (Command cmd : matches) {
|
||||
showUsage(cmd, sender, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// If there are no matches at all, notify.
|
||||
if (matches.size() == 0) {
|
||||
Messenger.tell(sender, Msg.MISC_NO_MATCHES);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Grab the only match.
|
||||
Command command = matches.get(0);
|
||||
CommandInfo info = command.getClass().getAnnotation(CommandInfo.class);
|
||||
|
||||
// First check if the sender has permission.
|
||||
if (!plugin.has(sender, info.permission())) {
|
||||
Messenger.tell(sender, Msg.MISC_NO_ACCESS);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if the last argument is a ?, in which case, display usage and description
|
||||
if (last.equals("?") || last.equals("help")) {
|
||||
showUsage(command, sender, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, execute the command!
|
||||
String[] params = trimFirstArg(args);
|
||||
if (!command.execute(am, sender, params)) {
|
||||
showUsage(command, sender, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all commands that match a given string.
|
||||
* @param arg the given string
|
||||
* @return a list of commands whose patterns match the given string
|
||||
*/
|
||||
private List<Command> getMatchingCommands(String arg) {
|
||||
List<Command> result = new ArrayList<Command>();
|
||||
|
||||
// Grab the commands that match the argument.
|
||||
for (Entry<String,Command> entry : commands.entrySet()) {
|
||||
if (arg.matches(entry.getKey())) {
|
||||
result.add(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the usage and description messages of a command to a player.
|
||||
* The usage will only be shown, if the player has permission for the command.
|
||||
* @param cmd a Command
|
||||
* @param sender a CommandSender
|
||||
*/
|
||||
private void showUsage(Command cmd, CommandSender sender, boolean prefix) {
|
||||
CommandInfo info = cmd.getClass().getAnnotation(CommandInfo.class);
|
||||
if (!plugin.has(sender, info.permission())) return;
|
||||
|
||||
sender.sendMessage((prefix ? "Usage: " : "") + info.usage() + " " + ChatColor.YELLOW + info.desc());
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the first argument of a string. This is because the very first
|
||||
* element of the arguments array will be the command itself.
|
||||
* @param args an array of length n
|
||||
* @return the same array minus the first element, and thus of length n-1
|
||||
*/
|
||||
private String[] trimFirstArg(String[] args) {
|
||||
return Arrays.copyOfRange(args, 1, args.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all the available MobArena commands for the CommandSender.
|
||||
* @param sender a player or the console
|
||||
*/
|
||||
private void showHelp(CommandSender sender) {
|
||||
StringBuilder user = new StringBuilder();
|
||||
StringBuilder admin = new StringBuilder();
|
||||
StringBuilder setup = new StringBuilder();
|
||||
|
||||
for (Command cmd : commands.values()) {
|
||||
CommandInfo info = cmd.getClass().getAnnotation(CommandInfo.class);
|
||||
if (!plugin.has(sender, info.permission())) continue;
|
||||
|
||||
StringBuilder buffy;
|
||||
if (info.permission().startsWith("mobarena.admin")) {
|
||||
buffy = admin;
|
||||
} else if (info.permission().startsWith("mobarena.setup")) {
|
||||
buffy = setup;
|
||||
} else {
|
||||
buffy = user;
|
||||
}
|
||||
buffy.append("\n")
|
||||
.append(ChatColor.RESET).append(info.usage()).append(" ")
|
||||
.append(ChatColor.YELLOW).append(info.desc());
|
||||
}
|
||||
|
||||
if (admin.length() == 0 && setup.length() == 0) {
|
||||
Messenger.tell(sender, "Available commands: " + user.toString());
|
||||
} else {
|
||||
Messenger.tell(sender, "User commands: " + user.toString());
|
||||
if (admin.length() > 0) Messenger.tell(sender, "Admin commands: " + admin.toString());
|
||||
if (setup.length() > 0) Messenger.tell(sender, "Setup commands: " + setup.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all the commands directly.
|
||||
* This could also be done with a somewhat dirty classloader/resource reader
|
||||
* method, but this is neater, albeit more manual work.
|
||||
*/
|
||||
private void registerCommands() {
|
||||
commands = new LinkedHashMap<String,Command>();
|
||||
|
||||
// mobarena.use
|
||||
register(JoinCommand.class);
|
||||
register(LeaveCommand.class);
|
||||
register(SpecCommand.class);
|
||||
register(ArenaListCommand.class);
|
||||
register(PlayerListCommand.class);
|
||||
register(NotReadyCommand.class);
|
||||
register(PickClassCommand.class);
|
||||
|
||||
// mobarena.admin
|
||||
register(EnableCommand.class);
|
||||
register(DisableCommand.class);
|
||||
register(ForceCommand.class);
|
||||
register(KickCommand.class);
|
||||
register(RestoreCommand.class);
|
||||
|
||||
// mobarena.setup
|
||||
register(ConfigCommand.class);
|
||||
register(SetupCommand.class);
|
||||
register(SettingCommand.class);
|
||||
|
||||
register(AddArenaCommand.class);
|
||||
register(RemoveArenaCommand.class);
|
||||
register(EditArenaCommand.class);
|
||||
register(CheckDataCommand.class);
|
||||
|
||||
register(RemoveSpawnpointCommand.class);
|
||||
register(CheckSpawnsCommand.class);
|
||||
register(RemoveContainerCommand.class);
|
||||
|
||||
register(ListClassesCommand.class);
|
||||
register(SetClassCommand.class);
|
||||
register(SetClassPriceCommand.class);
|
||||
register(RemoveClassCommand.class);
|
||||
register(ClassChestCommand.class);
|
||||
register(ListClassPermsCommand.class);
|
||||
register(AddClassPermCommand.class);
|
||||
register(RemoveClassPermCommand.class);
|
||||
|
||||
register(RemoveLeaderboardCommand.class);
|
||||
register(AutoGenerateCommand.class);
|
||||
register(AutoDegenerateCommand.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a command.
|
||||
* The Command's CommandInfo annotation is queried to find its pattern
|
||||
* string, which is used to map the commands.
|
||||
* @param c a Command
|
||||
*/
|
||||
public void register(Class<? extends Command> c) {
|
||||
CommandInfo info = c.getAnnotation(CommandInfo.class);
|
||||
if (info == null) return;
|
||||
|
||||
try {
|
||||
commands.put(info.pattern(), c.newInstance());
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.garbagemule.MobArena.commands;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CommandInfo
|
||||
{
|
||||
/**
|
||||
* The actual name of the command. Not really used anywhere.
|
||||
*/
|
||||
public String name();
|
||||
|
||||
/**
|
||||
* A regex pattern that allows minor oddities and alternatives to the command name.
|
||||
*/
|
||||
public String pattern();
|
||||
|
||||
/**
|
||||
* The usage message, i.e. how the command should be used.
|
||||
*/
|
||||
public String usage();
|
||||
|
||||
/**
|
||||
* A description of what the command does.
|
||||
*/
|
||||
public String desc();
|
||||
|
||||
/**
|
||||
* The permission required to execute this command.
|
||||
*/
|
||||
public String permission();
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.garbagemule.MobArena.commands;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import com.garbagemule.MobArena.Msg;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.util.TextUtils;
|
||||
|
||||
public class Commands
|
||||
{
|
||||
public static boolean isPlayer(CommandSender sender) {
|
||||
return (sender instanceof Player);
|
||||
}
|
||||
|
||||
public static Arena getArenaToJoinOrSpec(ArenaMaster am, Player p, String arg1) {
|
||||
// Check if MobArena is enabled first.
|
||||
if (!am.isEnabled()) {
|
||||
Messenger.tell(p, Msg.JOIN_NOT_ENABLED);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Then check if we have permission at all.
|
||||
List<Arena> arenas = am.getPermittedArenas(p);
|
||||
if (arenas.isEmpty()) {
|
||||
Messenger.tell(p, Msg.JOIN_NO_PERMISSION);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Then check if we have any enabled arenas.
|
||||
arenas = am.getEnabledArenas(arenas);
|
||||
if (arenas.isEmpty()) {
|
||||
Messenger.tell(p, Msg.JOIN_NOT_ENABLED);
|
||||
return null;
|
||||
}
|
||||
|
||||
// The arena to join.
|
||||
Arena arena = null;
|
||||
|
||||
// Branch on whether there's an argument or not.
|
||||
if (arg1 != null) {
|
||||
arena = am.getArenaWithName(arg1);
|
||||
if (arena == null) {
|
||||
Messenger.tell(p, Msg.ARENA_DOES_NOT_EXIST);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!arenas.contains(arena)) {
|
||||
Messenger.tell(p, Msg.JOIN_ARENA_NOT_ENABLED);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (arenas.size() > 1) {
|
||||
Messenger.tell(p, Msg.JOIN_ARG_NEEDED);
|
||||
Messenger.tell(p, Msg.MISC_LIST_ARENAS.format(TextUtils.listToString(arenas)));
|
||||
return null;
|
||||
}
|
||||
arena = arenas.get(0);
|
||||
}
|
||||
|
||||
// If player is in a boat/minecart, eject!
|
||||
if (p.isInsideVehicle()) {
|
||||
p.leaveVehicle();
|
||||
}
|
||||
|
||||
// If player is in a bed, unbed!
|
||||
if (p.isSleeping()) {
|
||||
p.kickPlayer("Banned for life... Nah, just don't join from a bed ;)");
|
||||
return null;
|
||||
}
|
||||
|
||||
return arena;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.garbagemule.MobArena.commands.admin;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "disable",
|
||||
pattern = "disable|off",
|
||||
usage = "/ma disable (<arena>|all)",
|
||||
desc = "disable MobArena or individual arenas",
|
||||
permission = "mobarena.admin.enable"
|
||||
)
|
||||
public class DisableCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Grab the argument, if any.
|
||||
String arg1 = (args.length > 0 ? args[0] : "");
|
||||
|
||||
if (arg1.equals("all")) {
|
||||
for (Arena arena : am.getArenas()) {
|
||||
disable(arena, sender);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!arg1.equals("")) {
|
||||
Arena arena = am.getArenaWithName(arg1);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, Msg.ARENA_DOES_NOT_EXIST);
|
||||
return true;
|
||||
}
|
||||
disable(arena, sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
am.setEnabled(false);
|
||||
am.saveConfig();
|
||||
Messenger.tell(sender, "MobArena " + ChatColor.RED + "disabled");
|
||||
return true;
|
||||
}
|
||||
|
||||
private void disable(Arena arena, CommandSender sender) {
|
||||
arena.setEnabled(false);
|
||||
arena.getPlugin().saveConfig();
|
||||
Messenger.tell(sender, "Arena '" + arena.configName() + "' " + ChatColor.RED + "disabled");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.garbagemule.MobArena.commands.admin;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "enable",
|
||||
pattern = "enable|on",
|
||||
usage = "/ma enable",
|
||||
desc = "enable MobArena or individual arenas",
|
||||
permission = "mobarena.admin.enable"
|
||||
)
|
||||
public class EnableCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Grab the argument, if any.
|
||||
String arg1 = (args.length > 0 ? args[0] : "");
|
||||
|
||||
if (arg1.equals("all")) {
|
||||
for (Arena arena : am.getArenas()) {
|
||||
enable(arena, sender);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!arg1.equals("")) {
|
||||
Arena arena = am.getArenaWithName(arg1);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, Msg.ARENA_DOES_NOT_EXIST);
|
||||
return true;
|
||||
}
|
||||
enable(arena, sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
am.setEnabled(true);
|
||||
am.saveConfig();
|
||||
Messenger.tell(sender, "MobArena " + ChatColor.GREEN + "enabled");
|
||||
return true;
|
||||
}
|
||||
|
||||
private void enable(Arena arena, CommandSender sender) {
|
||||
arena.setEnabled(true);
|
||||
arena.getPlugin().saveConfig();
|
||||
Messenger.tell(sender, "Arena '" + arena.configName() + "' " + ChatColor.GREEN + "enabled");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.garbagemule.MobArena.commands.admin;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "force",
|
||||
pattern = "force",
|
||||
usage = "/ma force start|end (<arena>)",
|
||||
desc = "force start or end an arena",
|
||||
permission = "mobarena.admin.force"
|
||||
)
|
||||
public class ForceCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Require at least one argument
|
||||
if (args.length < 1) return false;
|
||||
|
||||
// Grab the argument, if any.
|
||||
String arg1 = (args.length > 0 ? args[0] : "");
|
||||
String arg2 = (args.length > 1 ? args[1] : "");
|
||||
|
||||
if (arg1.equals("end")) {
|
||||
// With no arguments, end all.
|
||||
if (arg2.equals("")) {
|
||||
for (Arena arena : am.getArenas()) {
|
||||
arena.forceEnd();
|
||||
}
|
||||
Messenger.tell(sender, Msg.FORCE_END_ENDED);
|
||||
am.resetArenaMap();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, grab the arena in question.
|
||||
Arena arena = am.getArenaWithName(arg2);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, Msg.ARENA_DOES_NOT_EXIST);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (arena.getAllPlayers().isEmpty()) {
|
||||
Messenger.tell(sender, Msg.FORCE_END_EMPTY);
|
||||
return true;
|
||||
}
|
||||
|
||||
// And end it!
|
||||
arena.forceEnd();
|
||||
Messenger.tell(sender, Msg.FORCE_END_ENDED);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (arg1.equals("start")) {
|
||||
// Require argument.
|
||||
if (arg2.equals("")) return false;
|
||||
|
||||
// Grab the arena.
|
||||
Arena arena = am.getArenaWithName(arg2);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, Msg.ARENA_DOES_NOT_EXIST);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (arena.isRunning()) {
|
||||
Messenger.tell(sender, Msg.FORCE_START_RUNNING);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (arena.getReadyPlayersInLobby().isEmpty()) {
|
||||
Messenger.tell(sender, Msg.FORCE_START_NOT_READY);
|
||||
return true;
|
||||
}
|
||||
|
||||
// And start it!
|
||||
arena.forceStart();
|
||||
Messenger.tell(sender, Msg.FORCE_START_STARTED);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.garbagemule.MobArena.commands.admin;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "kick",
|
||||
pattern = "kick|kcik",
|
||||
usage = "/ma kick <player>",
|
||||
desc = "kick a player from an arena",
|
||||
permission = "mobarena.admin.kick"
|
||||
)
|
||||
public class KickCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Require a player name
|
||||
if (args.length != 1) return false;
|
||||
|
||||
Arena arena = am.getArenaWithPlayer(args[0]);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, "That player is not in an arena.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Grab the Player object.
|
||||
Player bp = am.getPlugin().getServer().getPlayer(args[0]);
|
||||
|
||||
// Force leave.
|
||||
arena.playerLeave(bp);
|
||||
Messenger.tell(sender, "Player '" + args[0] + "' was kicked from arena '" + arena.configName() + "'.");
|
||||
Messenger.tell(bp, "You were kicked by " + sender.getName() + ".");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.garbagemule.MobArena.commands.admin;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.util.inventory.InventoryManager;
|
||||
|
||||
@CommandInfo(
|
||||
name = "restore",
|
||||
pattern = "restore",
|
||||
usage = "/ma restore <player>",
|
||||
desc = "restore a player's inventory",
|
||||
permission = "mobarena.admin.restore"
|
||||
)
|
||||
public class RestoreCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Require a player name
|
||||
if (args.length != 1) return false;
|
||||
|
||||
if (am.getArenaWithPlayer(args[0]) != null) {
|
||||
Messenger.tell(sender, "Player is currently in an arena.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (InventoryManager.restoreFromFile(am.getPlugin(), am.getPlugin().getServer().getPlayer(args[0]))) {
|
||||
Messenger.tell(sender, "Restored " + args[0] + "'s inventory!");
|
||||
} else {
|
||||
Messenger.tell(sender, "Failed to restore " + args[0] + "'s inventory.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "addarena",
|
||||
pattern = "(add|new)arena",
|
||||
usage = "/ma addarena <arena>",
|
||||
desc = "add a new arena",
|
||||
permission = "mobarena.setup.addarena"
|
||||
)
|
||||
public class AddArenaCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
if (!Commands.isPlayer(sender)) {
|
||||
Messenger.tell(sender, Msg.MISC_NOT_FROM_CONSOLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Require an arena name
|
||||
if (args.length != 1) return false;
|
||||
|
||||
// Cast the sender.
|
||||
Player p = (Player) sender;
|
||||
|
||||
Arena arena = am.getArenaWithName(args[0]);
|
||||
if (arena != null) {
|
||||
Messenger.tell(sender, "An arena with that name already exists.");
|
||||
return true;
|
||||
}
|
||||
am.createArenaNode(args[0], p.getWorld());
|
||||
Messenger.tell(sender, "New arena with name '" + args[0] + "' created!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.util.TextUtils;
|
||||
|
||||
@CommandInfo(
|
||||
name = "addclassperm",
|
||||
pattern = "add(class)?perm(.*)",
|
||||
usage = "/ma addclassperm <classname> <permission>",
|
||||
desc = "add a per-class permission",
|
||||
permission = "mobarena.setup.classes"
|
||||
)
|
||||
public class AddClassPermCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Require classname and permission
|
||||
if (args.length != 2) return false;
|
||||
|
||||
// Grab the arena class
|
||||
ArenaClass arenaClass = am.getClasses().get(args[0]);
|
||||
if (arenaClass == null) {
|
||||
Messenger.tell(sender, "The class '" + TextUtils.camelCase(args[0]) + "' does not exist.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to add the permission.
|
||||
if (am.addClassPermission(args[0], args[1])) {
|
||||
Messenger.tell(sender, "Added permission '" + args[1] + "' to class '" + TextUtils.camelCase(args[0]) + "'.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// If it wasn't added, notify.
|
||||
Messenger.tell(sender, "Permission '" + args[1] + "' was NOT added to class '" + TextUtils.camelCase(args[0]) + "'.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "autodegenerate",
|
||||
pattern = "auto(\\-)?degenerate",
|
||||
usage = "/ma autodegenerate <arena>",
|
||||
desc = "autodegenerate an existing arena",
|
||||
permission = "mobarena.setup.autodegenerate"
|
||||
)
|
||||
public class AutoDegenerateCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Require an arena name
|
||||
if (args.length != 1) return false;
|
||||
|
||||
// We have to make sure at least one arena exists before degenerating
|
||||
if (am.getArenas().size() < 2) {
|
||||
Messenger.tell(sender, "At least one arena must exist!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if arena exists.
|
||||
Arena arena = am.getArenaWithName(args[0]);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, Msg.ARENA_DOES_NOT_EXIST);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!MAUtils.undoItHippieMonster(args[0], am.getPlugin(), true)) {
|
||||
Messenger.tell(sender, "Could not degenerate arena.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Messenger.tell(sender, "Arena with name '" + args[0] + "' degenerated.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "autogenerate",
|
||||
pattern = "auto(\\-)?generate",
|
||||
usage = "/ma autogenerate <arena>",
|
||||
desc = "autogenerate a new arena",
|
||||
permission = "mobarena.setup.autogenerate"
|
||||
)
|
||||
public class AutoGenerateCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
if (!Commands.isPlayer(sender)) {
|
||||
Messenger.tell(sender, Msg.MISC_NOT_FROM_CONSOLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Require an arena name
|
||||
if (args.length != 1) return false;
|
||||
|
||||
// Cast the sender.
|
||||
Player p = (Player) sender;
|
||||
|
||||
// Check if arena already exists.
|
||||
Arena arena = am.getArenaWithName(args[0]);
|
||||
if (arena != null) {
|
||||
Messenger.tell(sender, "An arena with that name already exists.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!MAUtils.doooooItHippieMonster(p.getLocation(), 13, args[0], am.getPlugin())) {
|
||||
Messenger.tell(sender, "Could not auto-generate arena.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Messenger.tell(sender, "Arena with name '" + args[0] + "' generated.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "checkdata",
|
||||
pattern = "checkdata",
|
||||
usage = "/ma checkdata <arena>",
|
||||
desc = "check if all required points are set up",
|
||||
permission = "mobarena.setup.checkdata"
|
||||
)
|
||||
public class CheckDataCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
Arena arena;
|
||||
if (args.length == 0) {
|
||||
if (am.getArenas().size() > 1) {
|
||||
Messenger.tell(sender, "There are multiple arenas.");
|
||||
return true;
|
||||
} else {
|
||||
arena = am.getArenas().get(0);
|
||||
}
|
||||
} else {
|
||||
arena = am.getArenaWithName(args[0]);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, "There is no arena named " + args[0]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
arena.getRegion().checkData(am.getPlugin(), sender, true, true, true, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import com.garbagemule.MobArena.Msg;
|
||||
import com.garbagemule.MobArena.commands.Command;
|
||||
import com.garbagemule.MobArena.commands.CommandInfo;
|
||||
import com.garbagemule.MobArena.commands.Commands;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@CommandInfo(
|
||||
name = "checkspawns",
|
||||
pattern = "checkspawn(point)?s",
|
||||
usage = "/ma checkspawns <arena>",
|
||||
desc = "show spawnpoints that cover your location",
|
||||
permission = "mobarena.setup.checkspawns"
|
||||
)
|
||||
public class CheckSpawnsCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
if (!Commands.isPlayer(sender)) {
|
||||
Messenger.tell(sender, Msg.MISC_NOT_FROM_CONSOLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
Arena arena;
|
||||
if (args.length == 0) {
|
||||
if (am.getArenas().size() > 1) {
|
||||
Messenger.tell(sender, "There are multiple arenas.");
|
||||
return true;
|
||||
} else {
|
||||
arena = am.getArenas().get(0);
|
||||
}
|
||||
} else {
|
||||
arena = am.getArenaWithName(args[0]);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, "There is no arena named " + args[0]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (arena.getRegion().getSpawnpoints().isEmpty()) {
|
||||
Messenger.tell(sender, "There are no spawnpoints in the selected arena.");
|
||||
return true;
|
||||
}
|
||||
Player p = (Player) sender;
|
||||
arena.getRegion().checkSpawns(p);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaClass;
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import com.garbagemule.MobArena.Msg;
|
||||
import com.garbagemule.MobArena.commands.Command;
|
||||
import com.garbagemule.MobArena.commands.CommandInfo;
|
||||
import com.garbagemule.MobArena.commands.Commands;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.util.config.ConfigUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import static com.garbagemule.MobArena.util.config.ConfigUtils.setLocation;
|
||||
|
||||
@CommandInfo(
|
||||
name = "classchest",
|
||||
pattern = "classchest",
|
||||
usage = "/ma classchest <class>",
|
||||
desc = "link a chest to a class",
|
||||
permission = "mobarena.setup.classchest"
|
||||
)
|
||||
public class ClassChestCommand implements Command {
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
if (!Commands.isPlayer(sender)) {
|
||||
Messenger.tell(sender, Msg.MISC_NOT_FROM_CONSOLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Require a class name
|
||||
if (args.length != 1) return false;
|
||||
|
||||
ArenaClass ac = am.getClasses().get(args[0].toLowerCase());
|
||||
if (ac == null) {
|
||||
Messenger.tell(sender, "Class not found.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Player p = (Player) sender;
|
||||
Block b = p.getTargetBlock(new HashSet<Material>(), 10);
|
||||
|
||||
switch (b.getType()) {
|
||||
case CHEST:
|
||||
case ENDER_CHEST:
|
||||
case TRAPPED_CHEST:
|
||||
break;
|
||||
default:
|
||||
Messenger.tell(sender, "You must look at a chest.");
|
||||
return true;
|
||||
}
|
||||
|
||||
setLocation(am.getPlugin().getConfig(), "classes." + ac.getConfigName() + ".classchest", b.getLocation());
|
||||
am.saveConfig();
|
||||
Messenger.tell(sender, "Class chest updated for class " + ac.getConfigName());
|
||||
am.loadClasses();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "config",
|
||||
pattern = "config|cfg",
|
||||
usage = "/ma config reload|save",
|
||||
desc = "reload or save the config-file",
|
||||
permission = "mobarena.setup.config"
|
||||
)
|
||||
public class ConfigCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Require reload/save
|
||||
if (args.length != 1) return false;
|
||||
|
||||
if (args[0].equals("reload")) {
|
||||
try {
|
||||
am.reloadConfig();
|
||||
Messenger.tell(sender, "Config reloaded.");
|
||||
} catch (Exception e) {
|
||||
Messenger.tell(sender, ChatColor.RED + "ERROR:" + ChatColor.RESET + "\n" + e.getMessage());
|
||||
Messenger.tell(sender, "MobArena has been " + ChatColor.RED + "disabled" + ChatColor.RESET + ".");
|
||||
Messenger.tell(sender, "Fix the config-file, then reload it again, and then type " + ChatColor.YELLOW + "/ma enable" + ChatColor.RESET + " to re-enable MobArena.");
|
||||
}
|
||||
} else if (args[0].equals("save")) {
|
||||
am.saveConfig();
|
||||
Messenger.tell(sender, "Config saved.");
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "editarena",
|
||||
pattern = "edit(arena)?",
|
||||
usage = "/ma editarena <arena> (true|false)",
|
||||
desc = "set edit mode of an arena",
|
||||
permission = "mobarena.setup.editarena"
|
||||
)
|
||||
public class EditArenaCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
boolean value;
|
||||
Arena arena;
|
||||
if (args.length == 0) {
|
||||
if (am.getArenas().size() > 1) {
|
||||
Messenger.tell(sender, "There are multiple arenas.");
|
||||
return true;
|
||||
}
|
||||
arena = am.getArenas().get(0);
|
||||
value = !arena.inEditMode();
|
||||
} else if (args.length == 1) {
|
||||
if (args[0].matches("on|off|true|false")) {
|
||||
if (am.getArenas().size() > 1) {
|
||||
Messenger.tell(sender, "There are multiple arenas.");
|
||||
return true;
|
||||
}
|
||||
arena = am.getArenas().get(0);
|
||||
value = args[0].matches("on|true");
|
||||
} else {
|
||||
arena = am.getArenaWithName(args[0]);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, "There is no arena named " + args[0]);
|
||||
return true;
|
||||
}
|
||||
value = !arena.inEditMode();
|
||||
}
|
||||
} else {
|
||||
arena = am.getArenaWithName(args[0]);
|
||||
value = args[1].matches("on|true");
|
||||
}
|
||||
arena.setEditMode(value);
|
||||
Messenger.tell(sender, "Edit mode for arena '" + arena.configName() + "': " + ((arena.inEditMode()) ? ChatColor.GREEN + "true" : ChatColor.RED + "false"));
|
||||
if (arena.inEditMode()) Messenger.tell(sender, "Remember to turn it back off after editing!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.util.TextUtils;
|
||||
|
||||
@CommandInfo(
|
||||
name = "listclassperms",
|
||||
pattern = "(list)?classperm(.*)s",
|
||||
usage = "/ma listclassperms <classname>",
|
||||
desc = "list per-class permissions",
|
||||
permission = "mobarena.setup.classes"
|
||||
)
|
||||
public class ListClassPermsCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Require a class name
|
||||
if (args.length != 1) return false;
|
||||
|
||||
ArenaClass arenaClass = am.getClasses().get(args[0]);
|
||||
String className = TextUtils.camelCase(args[0]);
|
||||
|
||||
if (arenaClass == null) {
|
||||
Messenger.tell(sender, "The class '" + className + "' does not exist.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Messenger.tell(sender, "Permissions for '" + className + "':");
|
||||
Map<String,Boolean> perms = arenaClass.getPermissions();
|
||||
if (perms.isEmpty()) {
|
||||
Messenger.tell(sender, "<none>");
|
||||
return true;
|
||||
}
|
||||
|
||||
for (Entry<String,Boolean> entry : arenaClass.getPermissions().entrySet()) {
|
||||
String perm = entry.getKey();
|
||||
if (!entry.getValue()) {
|
||||
perm = "^" + perm;
|
||||
}
|
||||
Messenger.tell(sender, "- " + perm);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "listclasses",
|
||||
pattern = "(list)?classes(.)*",
|
||||
usage = "/ma listclasses",
|
||||
desc = "list all current classes",
|
||||
permission = "mobarena.setup.classes"
|
||||
)
|
||||
public class ListClassesCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
Messenger.tell(sender, "Current classes:");
|
||||
Set<String> classes = am.getClasses().keySet();
|
||||
if (classes == null || classes.isEmpty()) {
|
||||
Messenger.tell(sender, "<none>");
|
||||
return true;
|
||||
}
|
||||
|
||||
for (String c : classes) {
|
||||
Messenger.tell(sender, "- " + c);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "removearena",
|
||||
pattern = "(del(.)*|r(e)?m(ove)?)arena",
|
||||
usage = "/ma removearena <arena>",
|
||||
desc = "remove an arena",
|
||||
permission = "mobarena.setup.removearena"
|
||||
)
|
||||
public class RemoveArenaCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Require an arena name
|
||||
if (args.length != 1) return false;
|
||||
|
||||
if (am.getArenas().size() == 1) {
|
||||
Messenger.tell(sender, "At least one arena must exist.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Arena arena = am.getArenaWithName(args[0]);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, "There is no arena with that name.");
|
||||
return true;
|
||||
}
|
||||
am.removeArenaNode(arena);
|
||||
Messenger.tell(sender, "Arena '" + arena.configName() + "' deleted.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.util.TextUtils;
|
||||
|
||||
@CommandInfo(
|
||||
name = "removeclass",
|
||||
pattern = "(del(.)*|r(e)?m(ove)?)class",
|
||||
usage = "/ma removeclass <classname>",
|
||||
desc = "remove the given class",
|
||||
permission = "mobarena.setup.classes"
|
||||
)
|
||||
public class RemoveClassCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Require a class name
|
||||
if (args.length != 1) return false;
|
||||
|
||||
// Find the class
|
||||
ArenaClass arenaClass = am.getClasses().get(args[0]);
|
||||
String className = TextUtils.camelCase(args[0]);
|
||||
if (arenaClass == null) {
|
||||
Messenger.tell(sender, "The class '" + className + "' does not exist.");
|
||||
return true;
|
||||
}
|
||||
|
||||
am.removeClassNode(className);
|
||||
Messenger.tell(sender, "Removed class '" + className + "'.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.util.TextUtils;
|
||||
|
||||
@CommandInfo(
|
||||
name = "removeclassperm",
|
||||
pattern = "(del(.)*|r(e)?m(ove)?)(class)?perm(.*)",
|
||||
usage = "/ma removeclassperm <classname> <permission>",
|
||||
desc = "remove a per-class permission",
|
||||
permission = "mobarena.setup.classes"
|
||||
)
|
||||
public class RemoveClassPermCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Require class name and permission
|
||||
if (args.length != 2) return false;
|
||||
|
||||
// Grab the arena class
|
||||
ArenaClass arenaClass = am.getClasses().get(args[0]);
|
||||
if (arenaClass == null) {
|
||||
Messenger.tell(sender, "The class '" + TextUtils.camelCase(args[0]) + "' does not exist.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove the permission.
|
||||
if (am.removeClassPermission(args[0], args[1])) {
|
||||
Messenger.tell(sender, "Removed permission '" + args[1] + "' from class '" + TextUtils.camelCase(args[0]) + "'.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// If it wasn't removed, notify.
|
||||
Messenger.tell(sender, "Permission '" + args[1] + "' was NOT removed from class '" + TextUtils.camelCase(args[0]) + "'.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "removecontainer",
|
||||
pattern = "(del(.)*|r(e)?m(ove)?)(container|chest)",
|
||||
usage = "/ma removecontainer <arena> <chest>",
|
||||
desc = "remove a container from the selected arena",
|
||||
permission = "mobarena.setup.containers"
|
||||
)
|
||||
public class RemoveContainerCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
if (args.length < 1) return false;
|
||||
|
||||
Arena arena;
|
||||
String chest;
|
||||
if (args.length == 1) {
|
||||
if (am.getArenas().size() > 1) {
|
||||
Messenger.tell(sender, "There are multiple arenas.");
|
||||
return true;
|
||||
}
|
||||
arena = am.getArenas().get(0);
|
||||
chest = args[0];
|
||||
} else {
|
||||
arena = am.getArenaWithName(args[0]);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, "There is no arena named " + args[0]);
|
||||
return true;
|
||||
}
|
||||
chest = args[1];
|
||||
}
|
||||
|
||||
if (arena.getRegion().removeChest(chest)) {
|
||||
Messenger.tell(sender, "Container " + chest + " removed for arena '" + arena.configName() + "'");
|
||||
} else {
|
||||
Messenger.tell(sender, "Could not find the container " + chest + " for the arena '" + arena.configName() + "'");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import com.garbagemule.MobArena.Msg;
|
||||
import com.garbagemule.MobArena.commands.Command;
|
||||
import com.garbagemule.MobArena.commands.CommandInfo;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "removeleaderboard",
|
||||
pattern = "(del(.)*|r(e)?m(ove)?)leaderboard",
|
||||
usage = "/ma removeleaderboard <arena>",
|
||||
desc = "remove the selected arena's leaderboard",
|
||||
permission = "mobarena.setup.leaderboards"
|
||||
)
|
||||
public class RemoveLeaderboardCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
Arena arena;
|
||||
if (args.length == 0) {
|
||||
if (am.getArenas().size() > 1) {
|
||||
Messenger.tell(sender, "There are multiple arenas.");
|
||||
return true;
|
||||
}
|
||||
arena = am.getArenas().get(0);
|
||||
} else {
|
||||
arena = am.getArenaWithName(args[0]);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, "There is no arena named " + args[0]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (arena.getRegion().getLeaderboard() != null) {
|
||||
arena.getRegion().set("leaderboard", null);
|
||||
Messenger.tell(sender, "Leaderboard for " + arena.configName() + " successfully removed!");
|
||||
} else {
|
||||
Messenger.tell(sender, Msg.ARENA_LBOARD_NOT_FOUND);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "delspawn",
|
||||
pattern = "(del(.)*|r(e)?m(ove)?)spawn(point)?",
|
||||
usage = "/ma delspawn <arena> <point>",
|
||||
desc = "delete a spawnpoint",
|
||||
permission = "mobarena.setup.spawnpoints"
|
||||
)
|
||||
public class RemoveSpawnpointCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
if (args.length < 1) return false;
|
||||
|
||||
Arena arena;
|
||||
String point;
|
||||
if (args.length == 1) {
|
||||
if (am.getArenas().size() > 1) {
|
||||
Messenger.tell(sender, "There are multiple arenas.");
|
||||
return true;
|
||||
}
|
||||
arena = am.getArenas().get(0);
|
||||
point = args[0];
|
||||
} else {
|
||||
arena = am.getArenaWithName(args[0]);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, "There is no arena named " + args[0]);
|
||||
return true;
|
||||
}
|
||||
point = args[1];
|
||||
}
|
||||
|
||||
if (arena.getRegion().removeSpawn(point)) {
|
||||
Messenger.tell(sender, "Spawnpoint " + point + " removed for arena '" + arena.configName() + "'");
|
||||
} else {
|
||||
Messenger.tell(sender, "Could not find the spawnpoint " + point + " for the arena '" + arena.configName() + "'");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.util.TextUtils;
|
||||
|
||||
@CommandInfo(
|
||||
name = "setclass",
|
||||
pattern = "setclass|saveclass",
|
||||
usage = "/ma setclass (safe) <classname>",
|
||||
desc = "save your inventory as a class",
|
||||
permission = "mobarena.setup.classes"
|
||||
)
|
||||
public class SetClassCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
if (!Commands.isPlayer(sender)) {
|
||||
Messenger.tell(sender, Msg.MISC_NOT_FROM_CONSOLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Require at least a class name
|
||||
if (args.length < 1) return false;
|
||||
|
||||
// Grab the argument, if any.
|
||||
String arg1 = (args.length > 0 ? args[0] : "");
|
||||
String arg2 = (args.length > 1 ? args[1] : "");
|
||||
|
||||
// Cast the sender.
|
||||
Player p = (Player) sender;
|
||||
|
||||
// Check if we're overwriting.
|
||||
boolean safe = arg1.equals("safe");
|
||||
if (safe && arg2.equals("")) return false;
|
||||
|
||||
// If so, use arg2, otherwise, use arg1
|
||||
String className = TextUtils.camelCase(safe ? arg2 : arg1);
|
||||
|
||||
// Create the class.
|
||||
ArenaClass arenaClass = am.createClassNode(className, p.getInventory(), safe);
|
||||
|
||||
// If the class is null, it was not created.
|
||||
if (arenaClass == null) {
|
||||
Messenger.tell(p, "That class already exists!");
|
||||
Messenger.tell(p, "To overwrite, omit the 'safe' parameter.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, yay!
|
||||
Messenger.tell(p, "Class '" + className + "' set with your current inventory.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaClass;
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import com.garbagemule.MobArena.Msg;
|
||||
import com.garbagemule.MobArena.commands.Command;
|
||||
import com.garbagemule.MobArena.commands.CommandInfo;
|
||||
import com.garbagemule.MobArena.commands.Commands;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.util.TextUtils;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@CommandInfo(
|
||||
name = "setclassprice",
|
||||
pattern = "set(class)?price|fee",
|
||||
usage = "/ma setclassprice <classname> $<price>",
|
||||
desc = "set the price of a class",
|
||||
permission = "mobarena.setup.classes"
|
||||
)
|
||||
public class SetClassPriceCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Require at least a class name
|
||||
if (args.length < 1) return false;
|
||||
|
||||
// Grab the argument, if any.
|
||||
String arg1 = args[0];
|
||||
String arg2 = (args.length > 1 ? args[1] : "");
|
||||
|
||||
// Grab the class.
|
||||
ArenaClass ac = am.getClasses().get(arg1);
|
||||
if (ac == null) {
|
||||
Messenger.tell(sender, "No class named '" + arg1 + "'.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Config-file value to set, and message to print
|
||||
String value;
|
||||
String msg;
|
||||
|
||||
if (!arg2.equals("")) {
|
||||
// Strip the dollar sign, if it's there
|
||||
if (arg2.startsWith("$")) {
|
||||
arg2 = arg2.substring(1);
|
||||
}
|
||||
|
||||
// Not a valid number? Bail!
|
||||
if (!arg2.matches("([1-9]\\d*)|(\\d*.\\d\\d?)")) {
|
||||
Messenger.tell(sender, "Could not parse price '" + arg2 + "'. Expected e.g. $10 or $2.50 or $.25");
|
||||
return true;
|
||||
}
|
||||
double price = Double.parseDouble(arg2);
|
||||
|
||||
value = "$" + arg2;
|
||||
msg = "Price for class '" + ac.getConfigName() + "' was set to " + am.getPlugin().economyFormat(price);
|
||||
} else {
|
||||
value = null;
|
||||
msg = "Price for class '" + ac.getConfigName() + "' was removed. The class is now free!";
|
||||
}
|
||||
|
||||
// Set the value, save and reload config
|
||||
am.getPlugin().getConfig().set("classes." + ac.getConfigName() + ".price", value);
|
||||
am.getPlugin().saveConfig();
|
||||
am.loadClasses();
|
||||
Messenger.tell(sender, msg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import com.garbagemule.MobArena.commands.Command;
|
||||
import com.garbagemule.MobArena.commands.CommandInfo;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@CommandInfo(
|
||||
name = "setting",
|
||||
pattern = "sett(ing)?",
|
||||
usage = "/ma setting <arena> (<setting> (<value>))",
|
||||
desc = "show or change arena settings",
|
||||
permission = "mobarena.setup.setting"
|
||||
)
|
||||
public class SettingCommand implements Command {
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Require at least an arena
|
||||
if (args.length < 1) return false;
|
||||
|
||||
// Find the arena first
|
||||
Arena arena = am.getArenaWithName(args[0]);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, "There's no arena with the name '" + args[0] + "'.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we have no more args, just show all settings
|
||||
if (args.length == 1) {
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
buffy.append("Settings for ").append(ChatColor.GREEN).append(args[0]).append(ChatColor.RESET).append(":");
|
||||
for (Map.Entry<String,Object> entry : arena.getSettings().getValues(false).entrySet()) {
|
||||
buffy.append("\n").append(ChatColor.RESET);
|
||||
buffy.append(ChatColor.AQUA).append(entry.getKey()).append(ChatColor.RESET).append(": ");
|
||||
buffy.append(ChatColor.YELLOW).append(entry.getValue());
|
||||
}
|
||||
Messenger.tell(sender, buffy.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, find the setting
|
||||
Object val = arena.getSettings().get(args[1], null);
|
||||
if (val == null) {
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
buffy.append(ChatColor.RED).append(" is not a valid setting.");
|
||||
buffy.append("Type ").append(ChatColor.YELLOW).append("/ma setting ").append(args[0]);
|
||||
buffy.append(ChatColor.RESET).append(" to see all settings.");
|
||||
Messenger.tell(sender, buffy.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
// If there are no more args, show the value
|
||||
if (args.length == 2) {
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
buffy.append(ChatColor.AQUA).append(args[1]).append(ChatColor.RESET).append(": ");
|
||||
buffy.append(ChatColor.YELLOW).append(val);
|
||||
Messenger.tell(sender, buffy.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, determine the value of the setting
|
||||
if (val instanceof Boolean) {
|
||||
if (!args[2].matches("on|off|yes|no|true|false")) {
|
||||
Messenger.tell(sender, "Expected a boolean value for that setting");
|
||||
return true;
|
||||
}
|
||||
boolean value = args[2].matches("on|yes|true");
|
||||
args[2] = String.valueOf(value);
|
||||
arena.getSettings().set(args[1], value);
|
||||
} else if (val instanceof Number) {
|
||||
try {
|
||||
arena.getSettings().set(args[1], Integer.parseInt(args[2]));
|
||||
} catch (NumberFormatException e) {
|
||||
Messenger.tell(sender, "Expected a numeric value for that setting.");
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
arena.getSettings().set(args[1], args[2]);
|
||||
}
|
||||
|
||||
// Save config-file and reload arena
|
||||
am.saveConfig();
|
||||
am.reloadArena(args[0]);
|
||||
|
||||
// Notify the sender
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
buffy.append("Setting ").append(ChatColor.AQUA).append(args[1]).append(ChatColor.RESET);
|
||||
buffy.append(" for arena ").append(ChatColor.GREEN).append(args[0]).append(ChatColor.RESET);
|
||||
buffy.append(" set to ").append(ChatColor.YELLOW).append(args[2]).append(ChatColor.RESET);
|
||||
buffy.append("!");
|
||||
Messenger.tell(sender, buffy.toString());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,771 @@
|
||||
package com.garbagemule.MobArena.commands.setup;
|
||||
|
||||
import static com.garbagemule.MobArena.Messenger.*;
|
||||
import com.garbagemule.MobArena.Msg;
|
||||
import com.garbagemule.MobArena.commands.Command;
|
||||
import com.garbagemule.MobArena.commands.CommandInfo;
|
||||
import com.garbagemule.MobArena.commands.Commands;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.region.ArenaRegion;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.conversations.*;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.*;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.server.PluginDisableEvent;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@CommandInfo(
|
||||
name = "setup",
|
||||
pattern = "setup",
|
||||
usage = "/ma setup <arena>",
|
||||
desc = "enter setup mode for an arena",
|
||||
permission = "mobarena.setup.setup"
|
||||
)
|
||||
public class SetupCommand implements Command, Listener {
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
if (!Commands.isPlayer(sender)) {
|
||||
tell(sender, Msg.MISC_NOT_FROM_CONSOLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the arena
|
||||
Arena arena;
|
||||
if (args.length == 0) {
|
||||
List<Arena> arenas = am.getArenas();
|
||||
if (arenas.size() > 1) {
|
||||
return false;
|
||||
}
|
||||
arena = arenas.get(0);
|
||||
} else {
|
||||
arena = am.getArenaWithName(args[0]);
|
||||
if (arena == null) {
|
||||
tell(sender, "There is no arena with the name " + ChatColor.RED + args[0] + ChatColor.RESET + ".");
|
||||
tell(sender, "Type " + ChatColor.YELLOW + "/ma addarena " + args[0] + ChatColor.RESET + " to create it!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Player player = (Player) sender;
|
||||
|
||||
// Create the setup object
|
||||
Setup setup = new Setup(player, arena);
|
||||
|
||||
// Register it as an event listener
|
||||
am.getPlugin().getServer().getPluginManager().registerEvents(setup, am.getPlugin());
|
||||
|
||||
// Set up the conversation
|
||||
Conversation convo = new Conversation(am.getPlugin(), player, setup);
|
||||
setup.convo = convo;
|
||||
convo.addConversationAbandonedListener(setup);
|
||||
convo.setLocalEchoEnabled(false);
|
||||
convo.begin();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The internal Setup class has three roles; it is the prompt and the
|
||||
* abandon listener for the Conversation initiated by the setup command,
|
||||
* but it is also an event listener for the interact event, to handle
|
||||
* the Toolbox events.
|
||||
*/
|
||||
private class Setup implements Prompt, ConversationAbandonedListener, Listener {
|
||||
private Player player;
|
||||
private Arena arena;
|
||||
private Conversation convo;
|
||||
|
||||
private boolean enabled;
|
||||
private boolean allowFlight;
|
||||
private boolean flying;
|
||||
private ItemStack[] armor;
|
||||
private ItemStack[] items;
|
||||
|
||||
private List<String> missing;
|
||||
private String next;
|
||||
|
||||
public Setup(Player player, Arena arena) {
|
||||
this.player = player;
|
||||
this.arena = arena;
|
||||
|
||||
// Store player and arena state
|
||||
this.enabled = arena.isEnabled();
|
||||
this.allowFlight = player.getAllowFlight();
|
||||
this.flying = player.isFlying();
|
||||
this.armor = player.getInventory().getArmorContents();
|
||||
this.items = player.getInventory().getContents();
|
||||
|
||||
// Change state
|
||||
arena.setEnabled(false);
|
||||
player.setAllowFlight(true);
|
||||
player.setFlying(true);
|
||||
player.getInventory().clear();
|
||||
player.getInventory().setContents(getToolbox());
|
||||
player.getInventory().setHeldItemSlot(0);
|
||||
|
||||
this.missing = new ArrayList<String>();
|
||||
this.next = color(String.format(
|
||||
"Setup Mode for arena &a%s&r. Type &e?&r for help.",
|
||||
"&a" + arena.configName() + "&r"
|
||||
));
|
||||
|
||||
ArenaRegion region = arena.getRegion();
|
||||
if (!region.isSetup()){
|
||||
// Region points
|
||||
if (!region.isDefined()) {
|
||||
missing.add("p1");
|
||||
missing.add("p2");
|
||||
}
|
||||
|
||||
// Arena, lobby, and spectator warps
|
||||
if (region.getArenaWarp() == null) missing.add("arena");
|
||||
if (region.getLobbyWarp() == null) missing.add("lobby");
|
||||
if (region.getSpecWarp() == null) missing.add("spectator");
|
||||
|
||||
// Spawnpoints
|
||||
if (region.getSpawnpoints().isEmpty()) {
|
||||
missing.add("spawnpoints");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ====================================================================
|
||||
// Toolbox handler
|
||||
// ====================================================================
|
||||
|
||||
private ItemStack[] getToolbox() {
|
||||
// Arena region tool
|
||||
ItemStack areg = makeTool(
|
||||
Material.GOLD_AXE, AREG_NAME,
|
||||
color("Set &ep1"),
|
||||
color("Set &ep2")
|
||||
);
|
||||
// Warps tool
|
||||
ItemStack warps = makeTool(
|
||||
Material.GOLD_HOE, WARPS_NAME,
|
||||
color("&eSet &rselected warp"),
|
||||
color("&eCycle &rbetween warps")
|
||||
);
|
||||
// Spawns tool
|
||||
ItemStack spawns = makeTool(
|
||||
Material.GOLD_SWORD, SPAWNS_NAME,
|
||||
color("&eAdd &rspawnpoint on block"),
|
||||
color("&eRemove &rspawnpoint on block")
|
||||
);
|
||||
// Chests tool
|
||||
ItemStack chests = makeTool(
|
||||
Material.GOLD_SPADE, CHESTS_NAME,
|
||||
color("&eAdd &rcontainer"),
|
||||
color("&eRemove &rcontainer")
|
||||
);
|
||||
// Lobby region tool
|
||||
ItemStack lreg = makeTool(
|
||||
Material.GOLD_AXE, LREG_NAME,
|
||||
color("Set &el1"),
|
||||
color("Set &el2")
|
||||
);
|
||||
// Round 'em up.
|
||||
return new ItemStack[] {
|
||||
null, areg, warps, spawns, chests, null, lreg
|
||||
};
|
||||
}
|
||||
|
||||
private ItemStack makeTool(Material mat, String name, String left, String right) {
|
||||
ItemStack tool = new ItemStack(mat);
|
||||
ItemMeta meta = tool.getItemMeta();
|
||||
meta.setDisplayName(name);
|
||||
meta.setLore(Arrays.asList(
|
||||
color("&9Left&r: &r" + left),
|
||||
color("&cRight&r: &r" + right)
|
||||
));
|
||||
tool.setItemMeta(meta);
|
||||
return tool;
|
||||
}
|
||||
|
||||
private boolean isTool(ItemStack item) {
|
||||
if (item == null || item.getTypeId() == 0) return false;
|
||||
|
||||
String name = item.getItemMeta().getDisplayName();
|
||||
if (name == null) return false;
|
||||
|
||||
// Just check the names of each tool
|
||||
return name.equals(AREG_NAME)
|
||||
|| name.equals(LREG_NAME)
|
||||
|| name.equals(WARPS_NAME)
|
||||
|| name.equals(SPAWNS_NAME)
|
||||
|| name.equals(CHESTS_NAME)
|
||||
|| name.equals(MANUAL_NAME);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDisable(PluginDisableEvent event) {
|
||||
if (event.getPlugin().getName().equals(arena.getPlugin().getName()) && player.isConversing()) {
|
||||
player.abandonConversation(convo);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
if (event.getPlayer().equals(player) && player.isConversing()) {
|
||||
player.abandonConversation(convo);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBreak(BlockBreakEvent event) {
|
||||
Player p = event.getPlayer();
|
||||
if (!p.equals(player)) return;
|
||||
|
||||
ItemStack tool = p.getItemInHand();
|
||||
if (!isTool(tool)) return;
|
||||
|
||||
event.setCancelled(true);
|
||||
tool.setDurability((short) 0);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDrop(PlayerDropItemEvent event) {
|
||||
Player p = event.getPlayer();
|
||||
if (!p.equals(player)) return;
|
||||
|
||||
event.setCancelled(true);
|
||||
tell(p, "You can't drop the toolbox items.");
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onInteract(PlayerInteractEvent event) {
|
||||
Player p = event.getPlayer();
|
||||
if (!p.equals(player)) return;
|
||||
|
||||
ItemStack tool = p.getItemInHand();
|
||||
if (!isTool(tool)) return;
|
||||
|
||||
String name = tool.getItemMeta().getDisplayName();
|
||||
if (name.equals(AREG_NAME)) {
|
||||
if (!arena(event)) return;
|
||||
} else if (name.equals(LREG_NAME)) {
|
||||
if (!lobby(event)) return;
|
||||
} else if (name.equals(WARPS_NAME)) {
|
||||
if (!warps(event)) return;
|
||||
} else if (name.equals(SPAWNS_NAME)) {
|
||||
if (!spawns(event)) return;
|
||||
} else if (name.equals(CHESTS_NAME)) {
|
||||
if (!chests(event)) return;
|
||||
}
|
||||
|
||||
event.setUseItemInHand(Event.Result.DENY);
|
||||
event.setCancelled(true);
|
||||
|
||||
player.sendRawMessage(getPromptText(null));
|
||||
}
|
||||
|
||||
private boolean arena(PlayerInteractEvent event) {
|
||||
if (!event.hasBlock()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Location loc = event.getClickedBlock().getLocation();
|
||||
region(event.getAction(), "p1", "p2", loc);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean lobby(PlayerInteractEvent event) {
|
||||
if (!event.hasBlock()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Location loc = event.getClickedBlock().getLocation();
|
||||
region(event.getAction(), "l1", "l2", loc);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean region(Action action, String lower, String upper, Location loc) {
|
||||
switch (action) {
|
||||
case LEFT_CLICK_BLOCK: regions(lower, loc); return true;
|
||||
case RIGHT_CLICK_BLOCK: regions(upper, loc); return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean warps(PlayerInteractEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case LEFT_CLICK_BLOCK:
|
||||
Location loc = event.getClickedBlock().getLocation();
|
||||
loc.setYaw(player.getLocation().getYaw());
|
||||
loc.setPitch(0);
|
||||
fix(loc);
|
||||
String warp = warpArray[warpIndex];
|
||||
warps(warp, loc);
|
||||
return true;
|
||||
case RIGHT_CLICK_BLOCK:
|
||||
case RIGHT_CLICK_AIR:
|
||||
warpIndex++;
|
||||
if (warpIndex == warpArray.length) {
|
||||
warpIndex = 0;
|
||||
}
|
||||
next = formatYellow("Current warp: %s", warpArray[warpIndex]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean spawns(PlayerInteractEvent event) {
|
||||
if (!event.hasBlock()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Location l = event.getClickedBlock().getLocation();
|
||||
fix(l);
|
||||
switch (event.getAction()) {
|
||||
case LEFT_CLICK_BLOCK: spawns(l, true); return true;
|
||||
case RIGHT_CLICK_BLOCK: spawns(l, false); return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean chests(PlayerInteractEvent event) {
|
||||
if (!event.hasBlock()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Block b = event.getClickedBlock();
|
||||
switch (event.getAction()) {
|
||||
case LEFT_CLICK_BLOCK: chests(b, true); return true;
|
||||
case RIGHT_CLICK_BLOCK: chests(b, false); return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void fix(Location loc) {
|
||||
loc.setX(loc.getBlockX() + 0.5D);
|
||||
loc.setY(loc.getBlockY() + 1);
|
||||
loc.setZ(loc.getBlockZ() + 0.5D);
|
||||
}
|
||||
|
||||
private int warpIndex = 0;
|
||||
private String[] warpArray = new String[] {"arena", "lobby", "spectator", "exit"};
|
||||
|
||||
private static final String AREG_NAME = "Arena Region";
|
||||
private static final String LREG_NAME = "Lobby Region";
|
||||
private static final String WARPS_NAME = "Warps";
|
||||
private static final String SPAWNS_NAME = "Spawnpoints";
|
||||
private static final String CHESTS_NAME = "Containers";
|
||||
private static final String MANUAL_NAME = "Manual";
|
||||
|
||||
|
||||
// ====================================================================
|
||||
// Conversation end handler (items, state, etc.)
|
||||
// ====================================================================
|
||||
|
||||
@Override
|
||||
public void conversationAbandoned(ConversationAbandonedEvent event) {
|
||||
// Unregister listener
|
||||
HandlerList.unregisterAll(this);
|
||||
|
||||
// Restore player and arena state
|
||||
arena.setEnabled(enabled);
|
||||
arena.getRegion().save();
|
||||
arena.getRegion().reloadAll();
|
||||
player.getInventory().setContents(items);
|
||||
player.getInventory().setArmorContents(armor);
|
||||
|
||||
// setAllowFlight(false) also handles setFlying(false)
|
||||
player.setAllowFlight(allowFlight);
|
||||
if (allowFlight) {
|
||||
player.setFlying(flying);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ====================================================================
|
||||
// Prompt methods
|
||||
// ====================================================================
|
||||
|
||||
@Override
|
||||
public String getPromptText(ConversationContext context) {
|
||||
return ChatColor.GREEN + "[MobArena] " + ChatColor.RESET + next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean blocksForInput(ConversationContext context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Prompt acceptInput(ConversationContext context, String s) {
|
||||
// Check regexes at the bottom of the file
|
||||
return s.matches(HELP) ? help()
|
||||
: s.matches(MISSING) ? missing()
|
||||
: s.matches(EXPAND) ? expand(s)
|
||||
: s.matches(EXPHELP) ? expandOptions()
|
||||
: s.matches(SHOW) ? show(context, s)
|
||||
: s.matches(SHOWHELP) ? showOptions()
|
||||
: s.matches(DONE) ? done()
|
||||
: invalidInput();
|
||||
}
|
||||
|
||||
|
||||
// ====================================================================
|
||||
// Input handlers
|
||||
// ====================================================================
|
||||
|
||||
/**
|
||||
* Help
|
||||
*/
|
||||
private Prompt help() {
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
buffy.append("\nAvailable input:");
|
||||
buffy.append("\n&r&e exp &7expand a region");
|
||||
buffy.append("\n&r&e show &7show a region, warp, or point");
|
||||
buffy.append("\n&r&e miss &7show missing warps and points");
|
||||
buffy.append("\n&r&e done &7exit out of Setup Mode");
|
||||
buffy.append("\n&r&7Read &bitem tooltips&r&7 for info about each tool.");
|
||||
next = color(buffy.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Regions
|
||||
*/
|
||||
private Prompt regions(String s, Location loc) {
|
||||
// Change worlds if needed
|
||||
if (!inArenaWorld()) {
|
||||
String msg = String.format(
|
||||
"Changed world of arena %s from %s to %s.",
|
||||
ChatColor.GREEN + arena.configName() + ChatColor.RESET,
|
||||
ChatColor.YELLOW + arena.getWorld().getName() + ChatColor.RESET,
|
||||
ChatColor.YELLOW + loc.getWorld().getName() + ChatColor.RESET
|
||||
);
|
||||
arena.setWorld(loc.getWorld());
|
||||
tell(player, msg);
|
||||
}
|
||||
arena.getRegion().set(s, loc);
|
||||
next = formatYellow("Region point %s was set.", s);
|
||||
missing.remove(s);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand
|
||||
*/
|
||||
private Prompt expand(String s) {
|
||||
String[] parts = s.split(" ");
|
||||
|
||||
boolean lobby = parts[1].equalsIgnoreCase("lr");
|
||||
int amount = Integer.parseInt(parts[2]);
|
||||
|
||||
if (parts[3].equalsIgnoreCase("up")) {
|
||||
if (lobby) {
|
||||
arena.getRegion().expandLobbyUp(amount);
|
||||
} else {
|
||||
arena.getRegion().expandUp(amount);
|
||||
}
|
||||
} else if (parts[3].equalsIgnoreCase("down")) {
|
||||
if (lobby) {
|
||||
arena.getRegion().expandLobbyDown(amount);
|
||||
} else {
|
||||
arena.getRegion().expandDown(amount);
|
||||
}
|
||||
} else {
|
||||
if (lobby) {
|
||||
arena.getRegion().expandLobbyOut(amount);
|
||||
} else {
|
||||
arena.getRegion().expandOut(amount);
|
||||
}
|
||||
}
|
||||
next = color(String.format("Expanded &e%s&r region &e%s&r by &e%s&r blocks.", (lobby ? "lobby" : "arena"), parts[3], parts[2]));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Warps
|
||||
*/
|
||||
private Prompt warps(String s, Location loc) {
|
||||
if (s.equals("spec")) s = "spectator";
|
||||
|
||||
// World change stuff for the arena warp
|
||||
if (s.equals("arena") && !arena.getRegion().contains(loc)) {
|
||||
if (!arena.getWorld().getName().equals(loc.getWorld().getName())) {
|
||||
World tmp = arena.getWorld();
|
||||
arena.setWorld(loc.getWorld());
|
||||
if (arena.getRegion().contains(loc)) {
|
||||
String msg = String.format(
|
||||
"Changed world of arena %s from %s to %s.",
|
||||
ChatColor.GREEN + arena.configName() + ChatColor.RESET,
|
||||
ChatColor.YELLOW + tmp.getName() + ChatColor.RESET,
|
||||
ChatColor.YELLOW + loc.getWorld().getName() + ChatColor.RESET
|
||||
);
|
||||
tell(player, msg);
|
||||
} else {
|
||||
arena.setWorld(tmp);
|
||||
next = "You must be inside the arena region.";
|
||||
return this;
|
||||
}
|
||||
} else {
|
||||
next = "You must be inside the arena region.";
|
||||
return this;
|
||||
}
|
||||
}
|
||||
missing.remove(s);
|
||||
arena.getRegion().set(s, loc);
|
||||
next = formatYellow("Warp point %s was set.", s);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns
|
||||
*/
|
||||
private Prompt spawns(Location l, boolean add) {
|
||||
String point = getName(l);
|
||||
if (add) {
|
||||
if (!arena.getRegion().contains(l)) {
|
||||
next = "You must be inside the arena region.";
|
||||
} else {
|
||||
arena.getRegion().addSpawn(point, l);
|
||||
next = formatYellow("Spawnpoint %s added.", point);
|
||||
missing.remove("spawnpoints");
|
||||
}
|
||||
} else {
|
||||
if (arena.getRegion().removeSpawn(point)) {
|
||||
next = formatYellow("Spawnpoint %s removed.", point);
|
||||
if (arena.getRegion().getSpawnpoints().size() == 0) {
|
||||
missing.add("spawnpoints");
|
||||
}
|
||||
} else {
|
||||
next = formatYellow("No spawnpoint named %s.", point);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chests
|
||||
*/
|
||||
private Prompt chests(Block b, boolean add) {
|
||||
if (b != null) {
|
||||
if (!(b.getState() instanceof InventoryHolder)) {
|
||||
next = "You must be looking at a container.";
|
||||
} else if (!arena.getRegion().contains(b.getLocation())) {
|
||||
next = "You must be inside the arena region.";
|
||||
} else {
|
||||
String point = getName(b.getLocation());
|
||||
if (add) {
|
||||
arena.getRegion().addChest(point, b.getLocation());
|
||||
next = formatYellow("Container %s added.", point);
|
||||
} else if (arena.getRegion().removeChest(point)) {
|
||||
next = formatYellow("Container %s removed.", point);
|
||||
} else {
|
||||
next = formatYellow("No container named %s.", point);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show things.
|
||||
*/
|
||||
private Prompt show(ConversationContext context, String s) {
|
||||
ArenaRegion region = arena.getRegion();
|
||||
String toShow = s.split(" ")[1].trim();
|
||||
|
||||
// Regions
|
||||
if (toShow.equalsIgnoreCase("r") || toShow.equalsIgnoreCase("regions")) {
|
||||
if (region.isDefined()) {
|
||||
region.showRegion(player);
|
||||
if (region.isLobbyDefined()) {
|
||||
region.showLobbyRegion(player);
|
||||
next = formatYellow("Showing both %s.", "regions");
|
||||
} else {
|
||||
next = formatYellow("Showing %s (lobby region not defined).", "arena region");
|
||||
}
|
||||
} else if (region.isLobbyDefined()) {
|
||||
region.showLobbyRegion(player);
|
||||
next = formatYellow("Showing %s (arena region not defined).", "lobby region");
|
||||
} else {
|
||||
next = "No regions have been defined yet.";
|
||||
}
|
||||
return this;
|
||||
} else if (toShow.equalsIgnoreCase("ar")) {
|
||||
if (region.isDefined()) {
|
||||
next = formatYellow("Showing %s.", "arena region");
|
||||
region.showRegion(player);
|
||||
} else {
|
||||
next = "The region has not been defined yet.";
|
||||
}
|
||||
return this;
|
||||
} else if (toShow.equalsIgnoreCase("lr")) {
|
||||
if (region.isLobbyDefined()) {
|
||||
next = formatYellow("Showing %s.", "lobby region");
|
||||
region.showLobbyRegion(player);
|
||||
} else {
|
||||
next = "The lobby region has not been defined yet.";
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Warps
|
||||
if (toShow.matches("arena|lobby|spec(tator)?|exit")) {
|
||||
next = formatYellow("Showing %s warp.", toShow);
|
||||
Location loc;
|
||||
loc = toShow.equals("arena") ? region.getArenaWarp() :
|
||||
toShow.equals("lobby") ? region.getLobbyWarp() :
|
||||
toShow.equals("spec") ? region.getSpecWarp() :
|
||||
toShow.equals("spectator") ? region.getSpecWarp() :
|
||||
toShow.equals("exit") ? region.getExitWarp() : null;
|
||||
region.showBlock(player, loc, 35, (byte) 14);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Spawnpoints
|
||||
if (toShow.matches("sp(awn(point)?s?)?")) {
|
||||
next = formatYellow("Showing %s.", "spawnpoints");
|
||||
region.showSpawns(player);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Chests
|
||||
if (toShow.matches("c((hest(s)?)?|on(tainer(s)?)?)")) {
|
||||
next = formatYellow("Showing %s.", "containers");
|
||||
region.showChests(player);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Show the "show help", if invalid thing
|
||||
return acceptInput(context, "show ?");
|
||||
}
|
||||
|
||||
/**
|
||||
* Missing points and warps
|
||||
*/
|
||||
private Prompt missing() {
|
||||
if (missing.isEmpty()) {
|
||||
next = "All required points and warps have been set!";
|
||||
} else {
|
||||
next = "Missing points and warps: " + getMissing();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand options
|
||||
*/
|
||||
private Prompt expandOptions() {
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
buffy.append("\nUsage: &eexp <region> <amount> <direction>");
|
||||
|
||||
buffy.append("\n\n&r&7Variable details:");
|
||||
buffy.append("\n&r&7 region: &rar&7 (arena region) or &rlr&7 (lobby region)");
|
||||
buffy.append("\n&r&7 amount: number of blocks to expand by");
|
||||
buffy.append("\n&r&7 direction: &rup&7, &rdown&7, or &routs&7");
|
||||
|
||||
buffy.append("\n\n&r&7Examples:");
|
||||
buffy.append("\n&r exp ar 5 up &7expand arena region up by 5");
|
||||
buffy.append("\n&r exp lr 10 out &7expand lobby region out by 10");
|
||||
next = color(buffy.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show options
|
||||
*/
|
||||
private Prompt showOptions() {
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
buffy.append("\nUsage: &eshow <thing>");
|
||||
|
||||
buffy.append("\n\n&r&7Possible things to show:");
|
||||
buffy.append("\n&r&7 regions: &rar&7 (arena region) or &rlr&7 (lobby region) or &rr&7 (both)");
|
||||
buffy.append("\n&r&7 warps: &rarena&7, &rlobby&7, &rspec&7, or &rexit");
|
||||
buffy.append("\n&r&7 points: &rspawns&7 or &rchests&7");
|
||||
|
||||
buffy.append("\n\n&r&7Examples:");
|
||||
buffy.append("\n&r show spawns &7show spawnpoints");
|
||||
buffy.append("\n&r show ar &7show arena region");
|
||||
next = color(buffy.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Done!
|
||||
*/
|
||||
private Prompt done() {
|
||||
if (missing.isEmpty()) {
|
||||
tell(player, "Setup complete! Arena is ready to be used!");
|
||||
} else {
|
||||
tell(player, "Setup incomplete. Missing points and warps: " + getMissing());
|
||||
}
|
||||
return Prompt.END_OF_CONVERSATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalid input
|
||||
*/
|
||||
private Prompt invalidInput() {
|
||||
next = formatYellow("Invalid input. Type %s for help", "?");
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// ====================================================================
|
||||
// Auxiliary methods
|
||||
// ====================================================================
|
||||
|
||||
private String getMissing() {
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
for (String m : missing) {
|
||||
buffy.append("\n").append(m);
|
||||
}
|
||||
return buffy.toString();
|
||||
}
|
||||
|
||||
private String color(String s) {
|
||||
return ChatColor.translateAlternateColorCodes('&', s);
|
||||
}
|
||||
|
||||
private boolean inArenaWorld() {
|
||||
return player.getWorld().getName().equals(arena.getWorld().getName());
|
||||
}
|
||||
|
||||
private void tell(Conversable whom, String msg) {
|
||||
whom.sendRawMessage(ChatColor.GREEN + "[MobArena] " + ChatColor.RESET + msg);
|
||||
}
|
||||
|
||||
private String formatYellow(String msg, String arg) {
|
||||
return String.format(msg, ChatColor.YELLOW + arg + ChatColor.RESET);
|
||||
}
|
||||
|
||||
private String getName(Location l) {
|
||||
return l.getBlockX() + "," + l.getBlockY() + "," + l.getBlockZ();
|
||||
}
|
||||
|
||||
|
||||
// ====================================================================
|
||||
// Regular expressions for the input
|
||||
// ====================================================================
|
||||
|
||||
private static final String HELP = "[?]|h(elp)?";
|
||||
private static final String MISSING = "miss(ing)?";
|
||||
private static final String EXPAND = "exp(and)? (a|l)r [1-9][0-9]* (up|down|out)";
|
||||
private static final String EXPHELP = "exp(and)?";
|
||||
private static final String SHOW = "show (r|ar|lr|arena|lobby|spec(tator)?|exit|sp(awn(point)?s?)?|c((hest(s)?)?|on(tainer(s)?)?))";
|
||||
private static final String SHOWHELP = "show";
|
||||
private static final String DONE = "done|quit|stop|end";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.garbagemule.MobArena.commands.user;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "arenalist",
|
||||
pattern = "arenas|arenal.*|lista.*",
|
||||
usage = "/ma arenas",
|
||||
desc = "lists all available arenas",
|
||||
permission = "mobarena.use.arenalist"
|
||||
)
|
||||
public class ArenaListCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
List<Arena> arenas;
|
||||
|
||||
if (Commands.isPlayer(sender)) {
|
||||
Player p = (Player) sender;
|
||||
arenas = am.getPermittedArenas(p);
|
||||
} else {
|
||||
arenas = am.getArenas();
|
||||
}
|
||||
|
||||
String list = MAUtils.listToString(arenas, am.getPlugin());
|
||||
Messenger.tell(sender, Msg.MISC_LIST_ARENAS.format(list));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.garbagemule.MobArena.commands.user;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "join",
|
||||
pattern = "j|jo.*|j.*n",
|
||||
usage = "/ma join (<arena>)",
|
||||
desc = "join an arena",
|
||||
permission = "mobarena.use.join"
|
||||
)
|
||||
public class JoinCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
if (!Commands.isPlayer(sender)) {
|
||||
Messenger.tell(sender, Msg.MISC_NOT_FROM_CONSOLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Cast the sender, grab the argument, if any.
|
||||
Player p = (Player) sender;
|
||||
String arg1 = (args.length > 0 ? args[0] : null);
|
||||
|
||||
// Run some rough sanity checks, and grab the arena to join.
|
||||
Arena toArena = Commands.getArenaToJoinOrSpec(am, p, arg1);
|
||||
if (toArena == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Deny joining from other arenas
|
||||
Arena fromArena = am.getArenaWithPlayer(p);
|
||||
if (fromArena != null && (fromArena.inArena(p) || fromArena.inLobby(p))) {
|
||||
Messenger.tell(p, Msg.JOIN_ALREADY_PLAYING);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Per-arena sanity checks
|
||||
if (!toArena.canJoin(p)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Force leave previous arena
|
||||
if (fromArena != null) fromArena.playerLeave(p);
|
||||
|
||||
// Join the arena!
|
||||
return toArena.playerJoin(p, p.getLocation());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.garbagemule.MobArena.commands.user;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "leave",
|
||||
pattern = "l|le((.*))?",
|
||||
usage = "/ma leave",
|
||||
desc = "leave the arena",
|
||||
permission = "mobarena.use.leave"
|
||||
)
|
||||
public class LeaveCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
if (!Commands.isPlayer(sender)) {
|
||||
Messenger.tell(sender, Msg.MISC_NOT_FROM_CONSOLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Cast the sender.
|
||||
Player p = (Player) sender;
|
||||
|
||||
Arena arena = am.getArenaWithPlayer(p);
|
||||
if (arena == null) {
|
||||
arena = am.getArenaWithSpectator(p);
|
||||
if (arena == null) {
|
||||
Messenger.tell(p, Msg.LEAVE_NOT_PLAYING);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (arena.playerLeave(p)) {
|
||||
Messenger.tell(p, Msg.LEAVE_PLAYER_LEFT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.garbagemule.MobArena.commands.user;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "notready",
|
||||
pattern = "notr.*|ready",
|
||||
usage = "/ma notready (<arena>)",
|
||||
desc = "see which players aren't ready",
|
||||
permission = "mobarena.use.notready"
|
||||
)
|
||||
public class NotReadyCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Grab the argument, if any
|
||||
String arg1 = (args.length > 0 ? args[0] : "");
|
||||
|
||||
// The arena to query.
|
||||
Arena arena = null;
|
||||
|
||||
if (!arg1.equals("")) {
|
||||
arena = am.getArenaWithName(arg1);
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, Msg.ARENA_DOES_NOT_EXIST);
|
||||
return false;
|
||||
}
|
||||
} else if (Commands.isPlayer(sender)) {
|
||||
Player p = (Player) sender;
|
||||
arena = am.getArenaWithPlayer(p);
|
||||
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, Msg.LEAVE_NOT_PLAYING);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
String list = MAUtils.listToString(arena.getNonreadyPlayers(), am.getPlugin());
|
||||
Messenger.tell(sender, Msg.MISC_LIST_PLAYERS.format(list));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package com.garbagemule.MobArena.commands.user;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaClass;
|
||||
import com.garbagemule.MobArena.ClassLimitManager;
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import com.garbagemule.MobArena.Msg;
|
||||
import com.garbagemule.MobArena.commands.Command;
|
||||
import com.garbagemule.MobArena.commands.CommandInfo;
|
||||
import com.garbagemule.MobArena.commands.Commands;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.util.TextUtils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@CommandInfo(
|
||||
name = "class",
|
||||
pattern = "(pick)?class",
|
||||
usage = "/ma class <class>",
|
||||
desc = "pick a class",
|
||||
permission = "mobarena.use.class"
|
||||
)
|
||||
public class PickClassCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
if (!Commands.isPlayer(sender)) {
|
||||
Messenger.tell(sender, Msg.MISC_NOT_FROM_CONSOLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Require a class name
|
||||
if (args.length != 1) return false;
|
||||
|
||||
// Cast the sender
|
||||
Player p = (Player) sender;
|
||||
|
||||
// Make sure the player is in an arena
|
||||
Arena arena = am.getArenaWithPlayer(p);
|
||||
if (arena == null) return true;
|
||||
|
||||
// Make sure the player is in the lobby
|
||||
if (!arena.inLobby(p)) {
|
||||
Messenger.tell(p, Msg.MISC_NO_ACCESS);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Grab the ArenaClass, if it exists
|
||||
String lowercase = args[0].toLowerCase();
|
||||
ArenaClass ac = am.getClasses().get(lowercase);
|
||||
if (ac == null) {
|
||||
Messenger.tell(p, Msg.LOBBY_NO_SUCH_CLASS, lowercase);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for permission.
|
||||
if (!am.getPlugin().has(p, "mobarena.classes." + lowercase) && !lowercase.equals("random")) {
|
||||
Messenger.tell(p, Msg.LOBBY_CLASS_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Grab the old ArenaClass, if any, same => ignore
|
||||
ArenaClass oldAC = arena.getArenaPlayer(p).getArenaClass();
|
||||
if (ac.equals(oldAC)) return true;
|
||||
|
||||
// If the new class is full, inform the player.
|
||||
ClassLimitManager clm = arena.getClassLimitManager();
|
||||
if (!clm.canPlayerJoinClass(ac)) {
|
||||
Messenger.tell(p, Msg.LOBBY_CLASS_FULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check price, balance, and inform
|
||||
double price = ac.getPrice();
|
||||
if (price > 0D) {
|
||||
if (!am.getPlugin().hasEnough(p, price)) {
|
||||
Messenger.tell(p, Msg.LOBBY_CLASS_TOO_EXPENSIVE, am.getPlugin().economyFormat(price));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, leave the old class, and pick the new!
|
||||
clm.playerLeftClass(oldAC, p);
|
||||
clm.playerPickedClass(ac, p);
|
||||
|
||||
if (!lowercase.equalsIgnoreCase("random")) {
|
||||
if (arena.getSettings().getBoolean("use-class-chests", false)) {
|
||||
Location loc = ac.getClassChest();
|
||||
if (loc != null) {
|
||||
Block blockChest = loc.getBlock();
|
||||
InventoryHolder holder = (InventoryHolder) blockChest.getState();
|
||||
ItemStack[] contents = holder.getInventory().getContents();
|
||||
// Guard against double-chests for now
|
||||
if (contents.length > 36) {
|
||||
ItemStack[] newContents = new ItemStack[36];
|
||||
System.arraycopy(contents, 0, newContents, 0, 36);
|
||||
contents = newContents;
|
||||
}
|
||||
arena.assignClassGiveInv(p, lowercase, contents);
|
||||
p.getInventory().setContents(contents);
|
||||
Messenger.tell(p, Msg.LOBBY_CLASS_PICKED, TextUtils.camelCase(lowercase));
|
||||
if (price > 0D) {
|
||||
Messenger.tell(p, Msg.LOBBY_CLASS_PRICE, am.getPlugin().economyFormat(price));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// No linked chest? Fall through to config-file
|
||||
}
|
||||
arena.assignClass(p, lowercase);
|
||||
Messenger.tell(p, Msg.LOBBY_CLASS_PICKED, TextUtils.camelCase(lowercase));
|
||||
if (price > 0D) {
|
||||
Messenger.tell(p, Msg.LOBBY_CLASS_PRICE, am.getPlugin().economyFormat(price));
|
||||
}
|
||||
} else {
|
||||
arena.addRandomPlayer(p);
|
||||
Messenger.tell(p, Msg.LOBBY_CLASS_RANDOM);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.garbagemule.MobArena.commands.user;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "playerlist",
|
||||
pattern = "player.*|listp.*",
|
||||
usage = "/ma players (<arena>)",
|
||||
desc = "lists players in an arena",
|
||||
permission = "mobarena.use.playerlist"
|
||||
)
|
||||
public class PlayerListCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
// Grab the argument, if any.
|
||||
String arg1 = (args.length > 0 ? args[0] : "");
|
||||
|
||||
String list = null;
|
||||
if (!arg1.equals("")) {
|
||||
Arena arena = am.getArenaWithName(arg1);
|
||||
|
||||
if (arena == null) {
|
||||
Messenger.tell(sender, Msg.ARENA_DOES_NOT_EXIST);
|
||||
return false;
|
||||
}
|
||||
|
||||
list = MAUtils.listToString(arena.getPlayersInArena(), am.getPlugin());
|
||||
} else {
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
List<Player> players = new LinkedList<Player>();
|
||||
|
||||
for (Arena arena : am.getArenas()) {
|
||||
players.addAll(arena.getPlayersInArena());
|
||||
}
|
||||
|
||||
buffy.append(MAUtils.listToString(players, am.getPlugin()));
|
||||
list = buffy.toString();
|
||||
}
|
||||
|
||||
Messenger.tell(sender, Msg.MISC_LIST_PLAYERS.format(list));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.garbagemule.MobArena.commands.user;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.*;
|
||||
import com.garbagemule.MobArena.commands.*;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
|
||||
@CommandInfo(
|
||||
name = "spec",
|
||||
pattern = "s|spec.*",
|
||||
usage = "/ma spec (<arena>)",
|
||||
desc = "spec an arena",
|
||||
permission = "mobarena.use.spec"
|
||||
)
|
||||
public class SpecCommand implements Command
|
||||
{
|
||||
@Override
|
||||
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
|
||||
if (!Commands.isPlayer(sender)) {
|
||||
Messenger.tell(sender, Msg.MISC_NOT_FROM_CONSOLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cast the sender, grab the argument, if any.
|
||||
Player p = (Player) sender;
|
||||
String arg1 = (args.length > 0 ? args[0] : null);
|
||||
|
||||
// Run some rough sanity checks, and grab the arena to spec.
|
||||
Arena toArena = Commands.getArenaToJoinOrSpec(am, p, arg1);
|
||||
if (toArena == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Deny spectating from other arenas
|
||||
Arena fromArena = am.getArenaWithPlayer(p);
|
||||
if (fromArena != null && (fromArena.inArena(p) || fromArena.inLobby(p))) {
|
||||
Messenger.tell(p, Msg.SPEC_ALREADY_PLAYING);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Per-arena sanity checks
|
||||
if (!toArena.canSpec(p)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Force leave previous arena
|
||||
if (fromArena != null) fromArena.playerLeave(p);
|
||||
|
||||
// Spec the arena!
|
||||
toArena.playerSpec(p, p.getLocation());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.garbagemule.MobArena.events;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class ArenaCompleteEvent extends Event {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private Arena arena;
|
||||
private Set<Player> survivors;
|
||||
|
||||
public ArenaCompleteEvent(Arena arena) {
|
||||
this.arena = arena;
|
||||
this.survivors = new HashSet<Player>();
|
||||
this.survivors.addAll(arena.getPlayersInArena());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the arena the event happened in.
|
||||
*
|
||||
* @return an arena
|
||||
*/
|
||||
public Arena getArena() {
|
||||
return arena;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set of players who survived until the final wave.
|
||||
*
|
||||
* @return a set of winners
|
||||
*/
|
||||
public Set<Player> getSurvivors() {
|
||||
return survivors;
|
||||
}
|
||||
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.garbagemule.MobArena.events;
|
||||
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public class ArenaEndEvent extends Event implements Cancellable
|
||||
{
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private Arena arena;
|
||||
private boolean cancelled;
|
||||
|
||||
public ArenaEndEvent(Arena arena) {
|
||||
this.arena = arena;
|
||||
this.cancelled = false;
|
||||
}
|
||||
|
||||
public Arena getArena() {
|
||||
return arena;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.garbagemule.MobArena.events;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
/**
|
||||
* Called when an arena player kills a mob or another player.
|
||||
*/
|
||||
public class ArenaKillEvent extends Event {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private Arena arena;
|
||||
private Player killer;
|
||||
private Entity victim;
|
||||
|
||||
public ArenaKillEvent(Arena arena, Player killer, Entity victim) {
|
||||
this.arena = arena;
|
||||
this.killer = killer;
|
||||
this.victim = victim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the arena the event happened in.
|
||||
*
|
||||
* @return an arena
|
||||
*/
|
||||
public Arena getArena() {
|
||||
return arena;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the killer.
|
||||
*
|
||||
* @return the killer
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return killer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the victim.
|
||||
*
|
||||
* @return the victim
|
||||
*/
|
||||
public Entity getVictim() {
|
||||
return victim;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.garbagemule.MobArena.events;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public class ArenaPlayerDeathEvent extends Event
|
||||
{
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private Player player;
|
||||
private Arena arena;
|
||||
private boolean last;
|
||||
|
||||
public ArenaPlayerDeathEvent(Player player, Arena arena, boolean last) {
|
||||
this.player = player;
|
||||
this.arena = arena;
|
||||
this.last = last;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public Arena getArena() {
|
||||
return arena;
|
||||
}
|
||||
|
||||
public boolean wasLastPlayerStanding() {
|
||||
return last;
|
||||
}
|
||||
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.garbagemule.MobArena.events;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public class ArenaPlayerJoinEvent extends Event implements Cancellable
|
||||
{
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private Player player;
|
||||
private Arena arena;
|
||||
private boolean cancelled;
|
||||
|
||||
public ArenaPlayerJoinEvent(Player player, Arena arena) {
|
||||
this.player = player;
|
||||
this.arena = arena;
|
||||
this.cancelled = false;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public Arena getArena() {
|
||||
return arena;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.garbagemule.MobArena.events;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public class ArenaPlayerLeaveEvent extends Event implements Cancellable
|
||||
{
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private Player player;
|
||||
private Arena arena;
|
||||
private boolean cancelled;
|
||||
|
||||
public ArenaPlayerLeaveEvent(Player player, Arena arena) {
|
||||
this.player = player;
|
||||
this.arena = arena;
|
||||
this.cancelled = false;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public Arena getArena() {
|
||||
return arena;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.garbagemule.MobArena.events;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public class ArenaPlayerReadyEvent extends Event implements Cancellable
|
||||
{
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private Player player;
|
||||
private Arena arena;
|
||||
private boolean cancelled;
|
||||
|
||||
public ArenaPlayerReadyEvent(Player player, Arena arena) {
|
||||
this.player = player;
|
||||
this.arena = arena;
|
||||
this.cancelled = false;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public Arena getArena() {
|
||||
return arena;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.garbagemule.MobArena.events;
|
||||
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public class ArenaStartEvent extends Event implements Cancellable
|
||||
{
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private Arena arena;
|
||||
private boolean cancelled;
|
||||
|
||||
public ArenaStartEvent(Arena arena) {
|
||||
this.arena = arena;
|
||||
this.cancelled = false;
|
||||
}
|
||||
|
||||
public Arena getArena() {
|
||||
return arena;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.garbagemule.MobArena.events;
|
||||
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.waves.Wave;
|
||||
|
||||
public class NewWaveEvent extends Event implements Cancellable
|
||||
{
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private Arena arena;
|
||||
private boolean cancelled;
|
||||
|
||||
private Wave wave;
|
||||
private int waveNo;
|
||||
|
||||
public NewWaveEvent(Arena arena, Wave wave, int waveNo) {
|
||||
this.arena = arena;
|
||||
this.wave = wave;
|
||||
this.waveNo = waveNo;
|
||||
}
|
||||
|
||||
public Wave getWave() {
|
||||
return wave;
|
||||
}
|
||||
|
||||
public int getWaveNumber() {
|
||||
return waveNo;
|
||||
}
|
||||
|
||||
public Arena getArena() {
|
||||
return arena;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
package com.garbagemule.MobArena.framework;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaClass;
|
||||
import com.garbagemule.MobArena.ArenaListener;
|
||||
import com.garbagemule.MobArena.ArenaPlayer;
|
||||
import com.garbagemule.MobArena.ClassLimitManager;
|
||||
import com.garbagemule.MobArena.MASpawnThread;
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import com.garbagemule.MobArena.MonsterManager;
|
||||
import com.garbagemule.MobArena.RewardManager;
|
||||
import com.garbagemule.MobArena.ScoreboardManager;
|
||||
import com.garbagemule.MobArena.leaderboards.Leaderboard;
|
||||
import com.garbagemule.MobArena.region.ArenaRegion;
|
||||
import com.garbagemule.MobArena.repairable.Repairable;
|
||||
import com.garbagemule.MobArena.util.inventory.InventoryManager;
|
||||
import com.garbagemule.MobArena.util.timer.AutoStartTimer;
|
||||
import com.garbagemule.MobArena.waves.WaveManager;
|
||||
|
||||
public interface Arena
|
||||
{
|
||||
/*/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// NEW METHODS IN REFACTORING
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public ConfigurationSection getSettings();
|
||||
|
||||
public World getWorld();
|
||||
|
||||
public void setWorld(World world);
|
||||
|
||||
public boolean isEnabled();
|
||||
|
||||
public void setEnabled(boolean value);
|
||||
|
||||
public boolean isProtected();
|
||||
|
||||
public void setProtected(boolean value);
|
||||
|
||||
public boolean isRunning();
|
||||
|
||||
public boolean inEditMode();
|
||||
|
||||
public void setEditMode(boolean value);
|
||||
|
||||
public int getMinPlayers();
|
||||
|
||||
public int getMaxPlayers();
|
||||
|
||||
public List<ItemStack> getEntryFee();
|
||||
|
||||
public Set<Map.Entry<Integer,List<ItemStack>>> getEveryWaveEntrySet();
|
||||
|
||||
public List<ItemStack> getAfterWaveReward(int wave);
|
||||
|
||||
public Set<Player> getPlayersInArena();
|
||||
|
||||
public Set<Player> getPlayersInLobby();
|
||||
|
||||
public Set<Player> getReadyPlayersInLobby();
|
||||
|
||||
public Set<Player> getSpectators();
|
||||
|
||||
public MASpawnThread getSpawnThread();
|
||||
|
||||
public WaveManager getWaveManager();
|
||||
|
||||
public Location getPlayerEntry(Player p);
|
||||
|
||||
public ArenaListener getEventListener();
|
||||
|
||||
public void setLeaderboard(Leaderboard leaderboard);
|
||||
|
||||
public ArenaPlayer getArenaPlayer(Player p);
|
||||
|
||||
public Set<Block> getBlocks();
|
||||
|
||||
public void addBlock(Block b);
|
||||
|
||||
public boolean removeBlock(Block b);
|
||||
|
||||
public boolean hasPet(Entity e);
|
||||
|
||||
public void addRepairable(Repairable r);
|
||||
|
||||
public ArenaRegion getRegion();
|
||||
|
||||
public InventoryManager getInventoryManager();
|
||||
|
||||
public RewardManager getRewardManager();
|
||||
|
||||
public MonsterManager getMonsterManager();
|
||||
|
||||
public ClassLimitManager getClassLimitManager();
|
||||
|
||||
public void revivePlayer(Player p);
|
||||
|
||||
public ScoreboardManager getScoreboard();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void scheduleTask(Runnable r, int delay);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public boolean startArena();
|
||||
|
||||
public boolean endArena();
|
||||
|
||||
public void forceStart();
|
||||
|
||||
public void forceEnd();
|
||||
|
||||
public boolean playerJoin(Player p, Location loc);
|
||||
|
||||
public void playerReady(Player p);
|
||||
|
||||
public boolean playerLeave(Player p);
|
||||
|
||||
public void playerDeath(Player p);
|
||||
|
||||
public void playerRespawn(Player p);
|
||||
|
||||
public Location getRespawnLocation(Player p);
|
||||
|
||||
public void playerSpec(Player p, Location loc);
|
||||
|
||||
public void storePlayerData(Player p, Location loc);
|
||||
|
||||
public void storeContainerContents();
|
||||
|
||||
public void restoreContainerContents();
|
||||
|
||||
public void movePlayerToLobby(Player p);
|
||||
|
||||
public void movePlayerToSpec(Player p);
|
||||
|
||||
public void movePlayerToEntry(Player p);
|
||||
|
||||
public void discardPlayer(Player p);
|
||||
|
||||
public void repairBlocks();
|
||||
|
||||
public void queueRepairable(Repairable r);
|
||||
|
||||
|
||||
|
||||
/*////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Items & Cleanup
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public void assignClass(Player p, String className);
|
||||
|
||||
public void assignClassGiveInv(Player p, String className, ItemStack[] contents);
|
||||
|
||||
public void addRandomPlayer(Player p);
|
||||
|
||||
public void assignRandomClass(Player p);
|
||||
|
||||
public void assignClassPermissions(Player p);
|
||||
|
||||
public void removeClassPermissions(Player p);
|
||||
|
||||
public void addPermission(Player p, String perm, boolean value);
|
||||
|
||||
|
||||
|
||||
/*////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Initialization & Checks
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public void restoreRegion();
|
||||
|
||||
|
||||
|
||||
/*////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Getters & Misc
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public boolean inArena(Player p);
|
||||
|
||||
public boolean inLobby(Player p);
|
||||
|
||||
public boolean inSpec(Player p);
|
||||
|
||||
public boolean isDead(Player p);
|
||||
|
||||
public String configName();
|
||||
|
||||
public String arenaName();
|
||||
|
||||
public MobArena getPlugin();
|
||||
|
||||
public Map<String,ArenaClass> getClasses();
|
||||
|
||||
public int getPlayerCount();
|
||||
|
||||
public List<Player> getAllPlayers();
|
||||
|
||||
public Collection<ArenaPlayer> getArenaPlayerSet();
|
||||
|
||||
public List<Player> getNonreadyPlayers();
|
||||
|
||||
public boolean canAfford(Player p);
|
||||
|
||||
public boolean takeFee(Player p);
|
||||
|
||||
public boolean refund(Player p);
|
||||
|
||||
public boolean canJoin(Player p);
|
||||
|
||||
public boolean canSpec(Player p);
|
||||
|
||||
public boolean hasIsolatedChat();
|
||||
|
||||
public Player getLastPlayerStanding();
|
||||
|
||||
public AutoStartTimer getAutoStartTimer();
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.garbagemule.MobArena.framework;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaClass;
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public interface ArenaMaster
|
||||
{
|
||||
/*/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// NEW METHODS IN REFACTORING
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
|
||||
public MobArena getPlugin();
|
||||
|
||||
public boolean isEnabled();
|
||||
|
||||
public void setEnabled(boolean value);
|
||||
|
||||
public boolean notifyOnUpdates();
|
||||
|
||||
public List<Arena> getArenas();
|
||||
|
||||
public Map<String,ArenaClass> getClasses();
|
||||
|
||||
public void addPlayer(Player p, Arena arena);
|
||||
|
||||
public Arena removePlayer(Player p);
|
||||
|
||||
public void resetArenaMap();
|
||||
|
||||
|
||||
|
||||
/*/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Getters
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
|
||||
public List<Arena> getEnabledArenas();
|
||||
|
||||
public List<Arena> getEnabledArenas(List<Arena> arenas);
|
||||
|
||||
public List<Arena> getPermittedArenas(Player p);
|
||||
|
||||
public List<Arena> getEnabledAndPermittedArenas(Player p);
|
||||
|
||||
public Arena getArenaAtLocation(Location loc);
|
||||
|
||||
public List<Arena> getArenasInWorld(World world);
|
||||
|
||||
public List<Player> getAllPlayers();
|
||||
|
||||
public List<Player> getAllPlayersInArena(String arenaName);
|
||||
|
||||
public List<Player> getAllLivingPlayers();
|
||||
|
||||
public List<Player> getLivingPlayersInArena(String arenaName);
|
||||
|
||||
public Arena getArenaWithPlayer(Player p);
|
||||
|
||||
public Arena getArenaWithPlayer(String playerName);
|
||||
|
||||
public Arena getArenaWithSpectator(Player p);
|
||||
|
||||
public Arena getArenaWithMonster(Entity e);
|
||||
|
||||
public Arena getArenaWithPet(Entity e);
|
||||
|
||||
public Arena getArenaWithName(String configName);
|
||||
|
||||
public Arena getArenaWithName(Collection<Arena> arenas, String configName);
|
||||
|
||||
public boolean isAllowed(String command);
|
||||
|
||||
|
||||
|
||||
/*/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Initialization
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public void initialize();
|
||||
|
||||
/**
|
||||
* Load the global settings.
|
||||
*/
|
||||
public void loadSettings();
|
||||
|
||||
/**
|
||||
* Load all class-related stuff.
|
||||
*/
|
||||
public void loadClasses();
|
||||
|
||||
public ArenaClass createClassNode(String className, PlayerInventory inv, boolean safe);
|
||||
|
||||
public void removeClassNode(String className);
|
||||
|
||||
public boolean addClassPermission(String className, String perm);
|
||||
|
||||
public boolean removeClassPermission(String className, String perm);
|
||||
|
||||
/**
|
||||
* Load all arena-related stuff.
|
||||
*/
|
||||
public void loadArenas();
|
||||
|
||||
public void loadArenasInWorld(String worldName);
|
||||
|
||||
public void unloadArenasInWorld(String worldName);
|
||||
|
||||
public boolean reloadArena(String name);
|
||||
|
||||
public Arena createArenaNode(String configName, World world);
|
||||
|
||||
public void removeArenaNode(Arena arena);
|
||||
|
||||
|
||||
|
||||
/*/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update and serialization methods
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public void reloadConfig();
|
||||
|
||||
public void saveConfig();
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.garbagemule.MobArena.leaderboards;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.block.Sign;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaPlayerStatistics;
|
||||
|
||||
public abstract class AbstractLeaderboardColumn implements LeaderboardColumn
|
||||
{
|
||||
protected String statname;
|
||||
private Sign header;
|
||||
private List<Sign> signs;
|
||||
|
||||
public AbstractLeaderboardColumn(String statname, Sign header, List<Sign> signs) {
|
||||
this.statname = statname;
|
||||
this.header = header;
|
||||
this.signs = signs;
|
||||
}
|
||||
|
||||
public void update(List<ArenaPlayerStatistics> stats) {
|
||||
// Make sure the stats will fit on the signs.
|
||||
int range = Math.min(stats.size(), signs.size()*4);
|
||||
|
||||
for (int i = 0; i < range; i++) {
|
||||
// Grab the right sign.
|
||||
Sign s = signs.get(i/4);
|
||||
|
||||
// Call the template method.
|
||||
String value = getLine(stats.get(i));
|
||||
|
||||
// And set the line
|
||||
s.setLine(i % 4, value);
|
||||
s.update();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract String getLine(ArenaPlayerStatistics stats);
|
||||
|
||||
public void clear() {
|
||||
for (Sign s : signs) {
|
||||
s.setLine(0, "");
|
||||
s.setLine(1, "");
|
||||
s.setLine(2, "");
|
||||
s.setLine(3, "");
|
||||
s.update();
|
||||
}
|
||||
}
|
||||
|
||||
public Sign getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public List<Sign> getSigns() {
|
||||
return signs;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.garbagemule.MobArena.leaderboards;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.block.Sign;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaPlayerStatistics;
|
||||
|
||||
public class ClassLeaderboardColumn extends AbstractLeaderboardColumn
|
||||
{
|
||||
public ClassLeaderboardColumn(String statname, Sign header, List<Sign> signs) {
|
||||
super(statname, header, signs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLine(ArenaPlayerStatistics stats) {
|
||||
return stats.getClassName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.garbagemule.MobArena.leaderboards;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.block.Sign;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaPlayerStatistics;
|
||||
|
||||
public class IntLeaderboardColumn extends AbstractLeaderboardColumn
|
||||
{
|
||||
public IntLeaderboardColumn(String statname, Sign header, List<Sign> signs) {
|
||||
super(statname, header, signs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLine(ArenaPlayerStatistics stats) {
|
||||
return "" + stats.getInt(statname);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
package com.garbagemule.MobArena.leaderboards;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.Sign;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaPlayer;
|
||||
import com.garbagemule.MobArena.ArenaPlayerStatistics;
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public class Leaderboard
|
||||
{
|
||||
private MobArena plugin;
|
||||
private Arena arena;
|
||||
|
||||
private Location topLeft;
|
||||
private Sign topLeftSign;
|
||||
private BlockFace direction;
|
||||
private int rows, cols, trackingId;
|
||||
|
||||
private List<LeaderboardColumn> boards;
|
||||
private List<ArenaPlayerStatistics> stats;
|
||||
|
||||
private boolean isValid;
|
||||
|
||||
/**
|
||||
* Private constructor.
|
||||
* Creates a new leaderboard with no signs or locations or anything.
|
||||
* @param plugin MobArena instance.
|
||||
* @param arena The arena to which this leaderboard belongs.
|
||||
*/
|
||||
private Leaderboard(MobArena plugin, Arena arena)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
this.arena = arena;
|
||||
this.boards = new ArrayList<LeaderboardColumn>();
|
||||
this.stats = new ArrayList<ArenaPlayerStatistics>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Location constructor.
|
||||
* Used to create a leaderboard on-the-fly from the location from the SignChangeEvent.
|
||||
* @param plugin MobArena instance.
|
||||
* @param arena The arena to which this leaderboard belongs.
|
||||
* @param topLeft The location at which the main leaderboard sign exists.
|
||||
*/
|
||||
public Leaderboard(MobArena plugin, Arena arena, Location topLeft)
|
||||
{
|
||||
this(plugin, arena);
|
||||
|
||||
if (topLeft == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(topLeft.getBlock().getState() instanceof Sign)) {
|
||||
Messenger.warning("The leaderboard-node for arena '" + arena.configName() + "' does not point to a sign!");
|
||||
return;
|
||||
}
|
||||
|
||||
this.topLeft = topLeft;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grab all adjacent signs and register the individual columns.
|
||||
*/
|
||||
public void initialize()
|
||||
{
|
||||
if (!isGridWellFormed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
initializeBoards();
|
||||
initializeStats();
|
||||
clear();
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
for (LeaderboardColumn column : boards)
|
||||
column.clear();
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
Collections.sort(stats, ArenaPlayerStatistics.waveComparator());
|
||||
|
||||
for (LeaderboardColumn column : boards)
|
||||
column.update(stats);
|
||||
}
|
||||
|
||||
public void startTracking()
|
||||
{
|
||||
trackingId = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin,
|
||||
new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
update();
|
||||
}
|
||||
}, 100, 100);
|
||||
}
|
||||
|
||||
public void stopTracking()
|
||||
{
|
||||
plugin.getServer().getScheduler().cancelTask(trackingId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the leaderboards grid is well-formed.
|
||||
* @return true, if the grid is well-formed, false otherwise.
|
||||
*/
|
||||
private boolean isGridWellFormed()
|
||||
{
|
||||
if (topLeft == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockState state = topLeft.getBlock().getState();
|
||||
|
||||
if (!(state instanceof Sign))
|
||||
{
|
||||
Messenger.severe("Leaderboards for '" + arena.configName() + "' could not be established!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grab the top left sign and set up a copy for parsing.
|
||||
this.topLeftSign = (Sign) state;
|
||||
Sign current = this.topLeftSign;
|
||||
|
||||
// Calculate matrix dimensions.
|
||||
this.direction = getRightDirection(current);
|
||||
this.rows = getSignCount(current, BlockFace.DOWN);
|
||||
this.cols = getSignCount(current, direction);
|
||||
|
||||
// Require at least 2x2 to be valid
|
||||
if (rows <= 1 || cols <= 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the left-most sign in the current row.
|
||||
Sign first = getAdjacentSign(current, BlockFace.DOWN);
|
||||
|
||||
for (int i = 1; i < rows; i++)
|
||||
{
|
||||
// Back to the first sign of the row.
|
||||
current = first;
|
||||
for (int j = 1; j < cols; j++)
|
||||
{
|
||||
// Grab the sign to the right, if not a sign, grid is ill-formed.
|
||||
current = getAdjacentSign(current, direction);
|
||||
if (current == null) return false;
|
||||
}
|
||||
|
||||
// Hop down to the next row.
|
||||
first = getAdjacentSign(first, BlockFace.DOWN);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the leaderboards.
|
||||
* Requires: The grid MUST be valid!
|
||||
*/
|
||||
private void initializeBoards()
|
||||
{
|
||||
boards.clear();
|
||||
Sign header = this.topLeftSign;
|
||||
Sign current;
|
||||
|
||||
do
|
||||
{
|
||||
// Strip the sign of any colors.
|
||||
String name = ChatColor.stripColor(header.getLine(2));
|
||||
|
||||
// Grab the stat to track.
|
||||
Stats stat = Stats.getByFullName(name);
|
||||
if (stat == null) continue;
|
||||
|
||||
// Create the list of signs
|
||||
List<Sign> signs = new ArrayList<Sign>();
|
||||
current = header;
|
||||
for (int i = 1; i < rows; i++)
|
||||
{
|
||||
current = getAdjacentSign(current, BlockFace.DOWN);
|
||||
signs.add(current);
|
||||
}
|
||||
|
||||
// Create the column.
|
||||
LeaderboardColumn column = null;
|
||||
|
||||
// Switch on the type of stat
|
||||
switch (stat) {
|
||||
case PLAYER_NAME:
|
||||
column = new PlayerLeaderboardColumn(stat.getShortName(), header, signs);
|
||||
break;
|
||||
case CLASS_NAME:
|
||||
column = new ClassLeaderboardColumn(stat.getShortName(), header, signs);
|
||||
break;
|
||||
default:
|
||||
column = new IntLeaderboardColumn(stat.getShortName(), header, signs);
|
||||
break;
|
||||
}
|
||||
|
||||
this.boards.add(column);
|
||||
}
|
||||
while ((header = getAdjacentSign(header, direction)) != null);
|
||||
}
|
||||
|
||||
private void initializeStats()
|
||||
{
|
||||
stats.clear();
|
||||
for (ArenaPlayer ap : arena.getArenaPlayerSet())
|
||||
stats.add(ap.getStats());
|
||||
}
|
||||
|
||||
private int getSignCount(Sign s, BlockFace direction)
|
||||
{
|
||||
int i = 1;
|
||||
|
||||
BlockState state = s.getBlock().getState();
|
||||
while ((state = state.getBlock().getRelative(direction).getState()) instanceof Sign)
|
||||
i++;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
private Sign getAdjacentSign(Sign s, BlockFace direction)
|
||||
{
|
||||
BlockState state = s.getBlock().getRelative(direction).getState();
|
||||
if (state instanceof Sign)
|
||||
return (Sign) state;
|
||||
return null;
|
||||
}
|
||||
|
||||
private BlockFace getRightDirection(Sign s)
|
||||
{
|
||||
byte data = s.getRawData();
|
||||
|
||||
if (data == 2) return BlockFace.WEST;//BlockFace.NORTH;
|
||||
if (data == 3) return BlockFace.EAST;//BlockFace.SOUTH;
|
||||
if (data == 4) return BlockFace.SOUTH;//BlockFace.WEST;
|
||||
if (data == 5) return BlockFace.NORTH;//BlockFace.EAST;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isValid()
|
||||
{
|
||||
return isValid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.garbagemule.MobArena.leaderboards;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.block.Sign;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaPlayerStatistics;
|
||||
|
||||
public interface LeaderboardColumn
|
||||
{
|
||||
/**
|
||||
* Update all the signs in this column to the current values
|
||||
* of the player stat associated with this column.
|
||||
*/
|
||||
public void update(List<ArenaPlayerStatistics> stats);
|
||||
|
||||
/**
|
||||
* Get the String representation of the stat in question.
|
||||
* The line is calculated by simply calling the appropriate
|
||||
* getter on the ArenaPlayerStatistics object.
|
||||
* @param stats an ArenaPlayerStatistics object
|
||||
* @return the String representation of the stat in question
|
||||
*/
|
||||
public String getLine(ArenaPlayerStatistics stats);
|
||||
|
||||
/**
|
||||
* Clear the text on all the signs in the column.
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Get the top sign of the column.
|
||||
* The top sign displays the stat name.
|
||||
* @return the top sign of the column
|
||||
*/
|
||||
public Sign getHeader();
|
||||
|
||||
/**
|
||||
* Get all signs in the column (minus the header).
|
||||
* @return all signs in the column (minus the header)
|
||||
*/
|
||||
public List<Sign> getSigns();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.garbagemule.MobArena.leaderboards;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.block.Sign;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaPlayerStatistics;
|
||||
|
||||
public class PlayerLeaderboardColumn extends AbstractLeaderboardColumn
|
||||
{
|
||||
public PlayerLeaderboardColumn(String statname, Sign header, List<Sign> signs) {
|
||||
super(statname, header, signs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLine(ArenaPlayerStatistics stats) {
|
||||
return stats.getPlayerName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.garbagemule.MobArena.leaderboards;
|
||||
|
||||
public enum Stats
|
||||
{
|
||||
PLAYER_NAME("Players", "playerName"),
|
||||
CLASS_NAME("Class", "class"),
|
||||
KILLS("Kills", "kills"),
|
||||
DAMAGE_DONE("Damage Done", "dmgDone"),
|
||||
DAMAGE_TAKEN("Damage Taken", "dmgTaken"),
|
||||
SWINGS("Swings", "swings"),
|
||||
HITS("Hits", "hits"),
|
||||
LAST_WAVE("Last Wave", "lastWave");
|
||||
|
||||
private String name, shortName;
|
||||
|
||||
private Stats(String name, String shortName) {
|
||||
this.name = name;
|
||||
this.shortName = shortName;
|
||||
}
|
||||
|
||||
public String getShortName() {
|
||||
return shortName;
|
||||
}
|
||||
|
||||
public String getFullName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static Stats getByFullName(String name) {
|
||||
for (Stats s : Stats.values())
|
||||
if (s.name.equals(name))
|
||||
return s;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Stats getByShortName(String name) {
|
||||
for (Stats s : Stats.values()) {
|
||||
if (s.shortName.equalsIgnoreCase(name)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
package com.garbagemule.MobArena.listeners;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.*;
|
||||
import org.bukkit.event.entity.*;
|
||||
import org.bukkit.event.hanging.HangingBreakEvent;
|
||||
import org.bukkit.event.player.*;
|
||||
import org.bukkit.event.vehicle.VehicleExitEvent;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.framework.ArenaMaster;
|
||||
import com.garbagemule.MobArena.leaderboards.Stats;
|
||||
import com.garbagemule.MobArena.util.VersionChecker;
|
||||
import com.garbagemule.MobArena.util.inventory.InventoryManager;
|
||||
|
||||
/**
|
||||
* The point of this class is to simply redirect all events to each arena's
|
||||
* own listener(s).
|
||||
* This means only one actual listener need be registered in Bukkit, and thus
|
||||
* less overhead. Of course, this requires a little bit of "hackery" here
|
||||
* and there.
|
||||
*/
|
||||
public class MAGlobalListener implements Listener
|
||||
{
|
||||
private MobArena plugin;
|
||||
private ArenaMaster am;
|
||||
|
||||
public MAGlobalListener(MobArena plugin, ArenaMaster am) {
|
||||
this.plugin = plugin;
|
||||
this.am = am;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// BLOCK EVENTS //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//TODO watch block physics, piston extend, and piston retract events
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void blockBreak(BlockBreakEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onBlockBreak(event);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void hangingBreak(HangingBreakEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onHangingBreak(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void blockBurn(BlockBurnEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onBlockBurn(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void blockForm(BlockFormEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onBlockForm(event);
|
||||
}
|
||||
|
||||
// // TODO: See ArenaListener.onBlockFromTo()
|
||||
// @EventHandler(priority = EventPriority.NORMAL)
|
||||
// public void blockFromTo(BlockFromToEvent event) {
|
||||
// for (Arena arena : am.getArenas())
|
||||
// arena.getEventListener().onBlockFromTo(event);
|
||||
// }
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void blockIgnite(BlockIgniteEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onBlockIgnite(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void blockPlace(BlockPlaceEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onBlockPlace(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void signChange(SignChangeEvent event) {
|
||||
if (!event.getPlayer().hasPermission("mobarena.setup.leaderboards")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!event.getLine(0).startsWith("[MA]")) {
|
||||
return;
|
||||
}
|
||||
|
||||
String text = event.getLine(0).substring((4));
|
||||
Arena arena;
|
||||
Stats stat;
|
||||
|
||||
if ((arena = am.getArenaWithName(text)) != null) {
|
||||
arena.getEventListener().onSignChange(event);
|
||||
setSignLines(event, ChatColor.GREEN + "MobArena", ChatColor.YELLOW + arena.arenaName(), ChatColor.AQUA + "Players", "---------------");
|
||||
}
|
||||
else if ((stat = Stats.getByShortName(text)) != null) {
|
||||
setSignLines(event, ChatColor.GREEN + "", "", ChatColor.AQUA + stat.getFullName(), "---------------");
|
||||
Messenger.tell(event.getPlayer(), "Stat sign created.");
|
||||
}
|
||||
}
|
||||
|
||||
private void setSignLines(SignChangeEvent event, String s1, String s2, String s3, String s4) {
|
||||
event.setLine(0, s1);
|
||||
event.setLine(1, s2);
|
||||
event.setLine(2, s3);
|
||||
event.setLine(3, s4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// ENTITY EVENTS //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void creatureSpawn(CreatureSpawnEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onCreatureSpawn(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onEntityChangeBlock(EntityChangeBlockEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onEntityChangeBlock(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void entityCombust(EntityCombustEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onEntityCombust(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void entityDamage(EntityDamageEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onEntityDamage(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void entityDeath(EntityDeathEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onEntityDeath(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void entityExplode(EntityExplodeEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onEntityExplode(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void entityRegainHealth(EntityRegainHealthEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onEntityRegainHealth(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void entityFoodLevelChange(FoodLevelChangeEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onFoodLevelChange(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void entityTarget(EntityTargetEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onEntityTarget(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void entityTeleport(EntityTeleportEvent event) {
|
||||
for (Arena arena : am.getArenas()) {
|
||||
arena.getEventListener().onEntityTeleport(event);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void potionSplash(PotionSplashEvent event) {
|
||||
for (Arena arena : am.getArenas()) {
|
||||
arena.getEventListener().onPotionSplash(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// PLAYER EVENTS //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void playerAnimation(PlayerAnimationEvent event) {
|
||||
if (!am.isEnabled()) return;
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onPlayerAnimation(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void playerBucketEmpty(PlayerBucketEmptyEvent event) {
|
||||
if (!am.isEnabled()) return;
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onPlayerBucketEmpty(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void playerChat(AsyncPlayerChatEvent event) {
|
||||
if (!am.isEnabled()) return;
|
||||
|
||||
Arena arena = am.getArenaWithPlayer(event.getPlayer());
|
||||
if (arena == null || !arena.hasIsolatedChat()) return;
|
||||
|
||||
event.getRecipients().retainAll(arena.getAllPlayers());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void playerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
||||
if (!am.isEnabled()) return;
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onPlayerCommandPreprocess(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void playerDropItem(PlayerDropItemEvent event) {
|
||||
if (!am.isEnabled()) return;
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onPlayerDropItem(event);
|
||||
}
|
||||
|
||||
// HIGHEST => after SignShop
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void playerInteract(PlayerInteractEvent event) {
|
||||
if (!am.isEnabled()) return;
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onPlayerInteract(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void playerJoin(PlayerJoinEvent event) {
|
||||
InventoryManager.restoreFromFile(plugin, event.getPlayer());
|
||||
if (!am.notifyOnUpdates() || !event.getPlayer().isOp()) return;
|
||||
|
||||
VersionChecker.checkForUpdates(plugin, event.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void playerKick(PlayerKickEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onPlayerKick(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void playerQuit(PlayerQuitEvent event) {
|
||||
for (Arena arena : am.getArenas())
|
||||
arena.getEventListener().onPlayerQuit(event);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void playerRespawn(PlayerRespawnEvent event) {
|
||||
for (Arena arena : am.getArenas()) {
|
||||
if (arena.getEventListener().onPlayerRespawn(event)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
plugin.restoreInventory(event.getPlayer());
|
||||
}
|
||||
|
||||
public enum TeleportResponse {
|
||||
ALLOW, REJECT, IDGAF
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void playerTeleport(PlayerTeleportEvent event) {
|
||||
if (!am.isEnabled()) return;
|
||||
|
||||
boolean allow = true;
|
||||
for (Arena arena : am.getArenas()) {
|
||||
TeleportResponse r = arena.getEventListener().onPlayerTeleport(event);
|
||||
|
||||
// If just one arena allows, uncancel and stop.
|
||||
switch (r) {
|
||||
case ALLOW:
|
||||
event.setCancelled(false);
|
||||
return;
|
||||
case REJECT:
|
||||
allow = false;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// Only cancel if at least one arena has rejected the teleport.
|
||||
if (!allow) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void playerPreLogin(PlayerLoginEvent event) {
|
||||
for (Arena arena : am.getArenas()) {
|
||||
arena.getEventListener().onPlayerPreLogin(event);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void vehicleExit(VehicleExitEvent event) {
|
||||
for (Arena arena : am.getArenas()) {
|
||||
arena.getEventListener().onVehicleExit(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// WORLD EVENTS //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void worldLoadEvent(WorldLoadEvent event) {
|
||||
am.loadArenasInWorld(event.getWorld().getName());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void worldUnloadEvent(WorldUnloadEvent event) {
|
||||
am.unloadArenasInWorld(event.getWorld().getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.garbagemule.MobArena.listeners;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.waves.enums.*;
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
|
||||
import com.nisovin.magicspells.events.SpellCastEvent;
|
||||
|
||||
public class MagicSpellsListener implements Listener
|
||||
{
|
||||
private MobArena plugin;
|
||||
private List<String> disabled, disabledOnBoss, disabledOnSwarm;
|
||||
|
||||
public MagicSpellsListener(MobArena plugin)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
|
||||
// Set up the MagicSpells config-file.
|
||||
File file = new File(plugin.getDataFolder(), "magicspells.yml");
|
||||
if (!file.exists()) {
|
||||
plugin.saveResource("magicspells.yml", false);
|
||||
Messenger.info("magicspells.yml created.");
|
||||
}
|
||||
try {
|
||||
FileConfiguration config = new YamlConfiguration();
|
||||
config.load(file);
|
||||
setupSpells(config);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onSpellCast(SpellCastEvent event)
|
||||
{
|
||||
Arena arena = plugin.getArenaMaster().getArenaWithPlayer(event.getCaster());
|
||||
if (arena == null || !arena.isRunning()) return;
|
||||
|
||||
String spell = event.getSpell().getName();
|
||||
WaveType type = (arena.getWaveManager().getCurrent() != null) ? arena.getWaveManager().getCurrent().getType() : null;
|
||||
|
||||
if (disabled.contains(spell) ||
|
||||
(type == WaveType.BOSS && disabledOnBoss.contains(spell)) ||
|
||||
(type == WaveType.SWARM && disabledOnSwarm.contains(spell))) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupSpells(ConfigurationSection config)
|
||||
{
|
||||
this.disabled = config.getStringList("disabled-spells");
|
||||
this.disabledOnBoss = config.getStringList("disabled-on-bosses");
|
||||
this.disabledOnSwarm = config.getStringList("disabled-on-swarms");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,651 @@
|
||||
/*
|
||||
* Copyright 2011-2013 Tyler Blair. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and contributors and should not be interpreted as representing official policies,
|
||||
* either expressed or implied, of anybody else.
|
||||
*/
|
||||
package com.garbagemule.MobArena.metrics;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* <p> The metrics class obtains data about a plugin and submits statistics about it to the metrics backend. </p> <p>
|
||||
* Public methods provided by this class: </p>
|
||||
* <code>
|
||||
* Graph createGraph(String name); <br/>
|
||||
* void addCustomData(BukkitMetrics.Plotter plotter); <br/>
|
||||
* void start(); <br/>
|
||||
* </code>
|
||||
*/
|
||||
public class Metrics {
|
||||
|
||||
/**
|
||||
* The current revision number
|
||||
*/
|
||||
private final static int REVISION = 6;
|
||||
/**
|
||||
* The base url of the metrics domain
|
||||
*/
|
||||
private static final String BASE_URL = "http://mcstats.org";
|
||||
/**
|
||||
* The url used to report a server's status
|
||||
*/
|
||||
private static final String REPORT_URL = "/report/%s";
|
||||
/**
|
||||
* The separator to use for custom data. This MUST NOT change unless you are hosting your own version of metrics and
|
||||
* want to change it.
|
||||
*/
|
||||
private static final String CUSTOM_DATA_SEPARATOR = "~~";
|
||||
/**
|
||||
* Interval of time to ping (in minutes)
|
||||
*/
|
||||
private static final int PING_INTERVAL = 10;
|
||||
/**
|
||||
* The plugin this metrics submits for
|
||||
*/
|
||||
private final Plugin plugin;
|
||||
/**
|
||||
* All of the custom graphs to submit to metrics
|
||||
*/
|
||||
private final Set<Graph> graphs = Collections.synchronizedSet(new HashSet<Graph>());
|
||||
/**
|
||||
* The default graph, used for addCustomData when you don't want a specific graph
|
||||
*/
|
||||
private final Graph defaultGraph = new Graph("Default");
|
||||
/**
|
||||
* The plugin configuration file
|
||||
*/
|
||||
private final YamlConfiguration configuration;
|
||||
/**
|
||||
* The plugin configuration file
|
||||
*/
|
||||
private final File configurationFile;
|
||||
/**
|
||||
* Unique server id
|
||||
*/
|
||||
private final String guid;
|
||||
/**
|
||||
* Debug mode
|
||||
*/
|
||||
private final boolean debug;
|
||||
/**
|
||||
* Lock for synchronization
|
||||
*/
|
||||
private final Object optOutLock = new Object();
|
||||
/**
|
||||
* The scheduled task
|
||||
*/
|
||||
private volatile BukkitTask task = null;
|
||||
|
||||
public Metrics(final Plugin plugin) throws IOException {
|
||||
if (plugin == null) {
|
||||
throw new IllegalArgumentException("Plugin cannot be null");
|
||||
}
|
||||
|
||||
this.plugin = plugin;
|
||||
|
||||
// load the config
|
||||
configurationFile = getConfigFile();
|
||||
configuration = YamlConfiguration.loadConfiguration(configurationFile);
|
||||
|
||||
// add some defaults
|
||||
configuration.addDefault("opt-out", false);
|
||||
configuration.addDefault("guid", UUID.randomUUID().toString());
|
||||
configuration.addDefault("debug", false);
|
||||
|
||||
// Do we need to create the file?
|
||||
if (configuration.get("guid", null) == null) {
|
||||
configuration.options().header("http://mcstats.org").copyDefaults(true);
|
||||
configuration.save(configurationFile);
|
||||
}
|
||||
|
||||
// Load the guid then
|
||||
guid = configuration.getString("guid");
|
||||
debug = configuration.getBoolean("debug", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics
|
||||
* website. Plotters can be added to the graph object returned.
|
||||
*
|
||||
* @param name The name of the graph
|
||||
* @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given
|
||||
*/
|
||||
public Graph createGraph(final String name) {
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("Graph name cannot be null");
|
||||
}
|
||||
|
||||
// Construct the graph object
|
||||
final Graph graph = new Graph(name);
|
||||
|
||||
// Now we can add our graph
|
||||
graphs.add(graph);
|
||||
|
||||
// and return back
|
||||
return graph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend
|
||||
*
|
||||
* @param graph The name of the graph
|
||||
*/
|
||||
public void addGraph(final Graph graph) {
|
||||
if (graph == null) {
|
||||
throw new IllegalArgumentException("Graph cannot be null");
|
||||
}
|
||||
|
||||
graphs.add(graph);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a custom data plotter to the default graph
|
||||
*
|
||||
* @param plotter The plotter to use to plot custom data
|
||||
*/
|
||||
public void addCustomData(final Plotter plotter) {
|
||||
if (plotter == null) {
|
||||
throw new IllegalArgumentException("Plotter cannot be null");
|
||||
}
|
||||
|
||||
// Add the plotter to the graph o/
|
||||
defaultGraph.addPlotter(plotter);
|
||||
|
||||
// Ensure the default graph is included in the submitted graphs
|
||||
graphs.add(defaultGraph);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start measuring statistics. This will immediately create an async repeating task as the plugin and send the
|
||||
* initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200
|
||||
* ticks.
|
||||
*
|
||||
* @return True if statistics measuring is running, otherwise false.
|
||||
*/
|
||||
public boolean start() {
|
||||
synchronized (optOutLock) {
|
||||
// Did we opt out?
|
||||
if (isOptOut()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is metrics already running?
|
||||
if (task != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Begin hitting the server with glorious data
|
||||
task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() {
|
||||
|
||||
private boolean firstPost = true;
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
// This has to be synchronized or it can collide with the disable method.
|
||||
synchronized (optOutLock) {
|
||||
// Disable Task, if it is running and the server owner decided to opt-out
|
||||
if (isOptOut() && task != null) {
|
||||
task.cancel();
|
||||
task = null;
|
||||
// Tell all plotters to stop gathering information.
|
||||
for (Graph graph : graphs) {
|
||||
graph.onOptOut();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We use the inverse of firstPost because if it is the first time we are posting,
|
||||
// it is not a interval ping, so it evaluates to FALSE
|
||||
// Each time thereafter it will evaluate to TRUE, i.e PING!
|
||||
postPlugin(!firstPost);
|
||||
|
||||
// After the first post we set firstPost to false
|
||||
// Each post thereafter will be a ping
|
||||
firstPost = false;
|
||||
} catch (IOException e) {
|
||||
if (debug) {
|
||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 0, PING_INTERVAL * 1200);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the server owner denied plugin metrics?
|
||||
*
|
||||
* @return true if metrics should be opted out of it
|
||||
*/
|
||||
public boolean isOptOut() {
|
||||
synchronized (optOutLock) {
|
||||
try {
|
||||
// Reload the metrics file
|
||||
configuration.load(getConfigFile());
|
||||
} catch (IOException ex) {
|
||||
if (debug) {
|
||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
||||
}
|
||||
return true;
|
||||
} catch (InvalidConfigurationException ex) {
|
||||
if (debug) {
|
||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return configuration.getBoolean("opt-out", false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void enable() throws IOException {
|
||||
// This has to be synchronized or it can collide with the check in the task.
|
||||
synchronized (optOutLock) {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (isOptOut()) {
|
||||
configuration.set("opt-out", false);
|
||||
configuration.save(configurationFile);
|
||||
}
|
||||
|
||||
// Enable Task, if it is not running
|
||||
if (task == null) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void disable() throws IOException {
|
||||
// This has to be synchronized or it can collide with the check in the task.
|
||||
synchronized (optOutLock) {
|
||||
// Check if the server owner has already set opt-out, if not, set it.
|
||||
if (!isOptOut()) {
|
||||
configuration.set("opt-out", true);
|
||||
configuration.save(configurationFile);
|
||||
}
|
||||
|
||||
// Disable Task, if it is running
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
task = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the File object of the config file that should be used to store data such as the GUID and opt-out status
|
||||
*
|
||||
* @return the File object for the config file
|
||||
*/
|
||||
public File getConfigFile() {
|
||||
// I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use
|
||||
// is to abuse the plugin object we already have
|
||||
// plugin.getDataFolder() => base/plugins/PluginA/
|
||||
// pluginsFolder => base/plugins/
|
||||
// The base is not necessarily relative to the startup directory.
|
||||
File pluginsFolder = plugin.getDataFolder().getParentFile();
|
||||
|
||||
// return => base/plugins/PluginMetrics/config.yml
|
||||
return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method that posts a plugin to the metrics website
|
||||
*/
|
||||
private void postPlugin(final boolean isPing) throws IOException {
|
||||
// Server software specific section
|
||||
PluginDescriptionFile description = plugin.getDescription();
|
||||
String pluginName = description.getName();
|
||||
boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled
|
||||
String pluginVersion = description.getVersion();
|
||||
String serverVersion = Bukkit.getVersion();
|
||||
int playersOnline = Bukkit.getServer().getOnlinePlayers().size();
|
||||
|
||||
// END server software specific section -- all code below does not use any code outside of this class / Java
|
||||
|
||||
// Construct the post data
|
||||
final StringBuilder data = new StringBuilder();
|
||||
|
||||
// The plugin's description file containg all of the plugin data such as name, version, author, etc
|
||||
data.append(encode("guid")).append('=').append(encode(guid));
|
||||
encodeDataPair(data, "version", pluginVersion);
|
||||
encodeDataPair(data, "server", serverVersion);
|
||||
encodeDataPair(data, "players", Integer.toString(playersOnline));
|
||||
encodeDataPair(data, "revision", String.valueOf(REVISION));
|
||||
|
||||
// New data as of R6
|
||||
String osname = System.getProperty("os.name");
|
||||
String osarch = System.getProperty("os.arch");
|
||||
String osversion = System.getProperty("os.version");
|
||||
String java_version = System.getProperty("java.version");
|
||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
// normalize os arch .. amd64 -> x86_64
|
||||
if (osarch.equals("amd64")) {
|
||||
osarch = "x86_64";
|
||||
}
|
||||
|
||||
encodeDataPair(data, "osname", osname);
|
||||
encodeDataPair(data, "osarch", osarch);
|
||||
encodeDataPair(data, "osversion", osversion);
|
||||
encodeDataPair(data, "cores", Integer.toString(coreCount));
|
||||
encodeDataPair(data, "online-mode", Boolean.toString(onlineMode));
|
||||
encodeDataPair(data, "java_version", java_version);
|
||||
|
||||
// If we're pinging, append it
|
||||
if (isPing) {
|
||||
encodeDataPair(data, "ping", "true");
|
||||
}
|
||||
|
||||
// Acquire a lock on the graphs, which lets us make the assumption we also lock everything
|
||||
// inside of the graph (e.g plotters)
|
||||
synchronized (graphs) {
|
||||
final Iterator<Graph> iter = graphs.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
final Graph graph = iter.next();
|
||||
|
||||
for (Plotter plotter : graph.getPlotters()) {
|
||||
// The key name to send to the metrics server
|
||||
// The format is C-GRAPHNAME-PLOTTERNAME where separator - is defined at the top
|
||||
// Legacy (R4) submitters use the format Custom%s, or CustomPLOTTERNAME
|
||||
final String key = String.format("C%s%s%s%s", CUSTOM_DATA_SEPARATOR, graph.getName(), CUSTOM_DATA_SEPARATOR, plotter.getColumnName());
|
||||
|
||||
// The value to send, which for the foreseeable future is just the string
|
||||
// value of plotter.getValue()
|
||||
final String value = Integer.toString(plotter.getValue());
|
||||
|
||||
// Add it to the http post data :)
|
||||
encodeDataPair(data, key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the url
|
||||
URL url = new URL(BASE_URL + String.format(REPORT_URL, encode(pluginName)));
|
||||
|
||||
// Connect to the website
|
||||
URLConnection connection;
|
||||
|
||||
// Mineshafter creates a socks proxy, so we can safely bypass it
|
||||
// It does not reroute POST requests so we need to go around it
|
||||
if (isMineshafterPresent()) {
|
||||
connection = url.openConnection(Proxy.NO_PROXY);
|
||||
} else {
|
||||
connection = url.openConnection();
|
||||
}
|
||||
|
||||
connection.setDoOutput(true);
|
||||
|
||||
// Write the data
|
||||
final OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
|
||||
writer.write(data.toString());
|
||||
writer.flush();
|
||||
|
||||
// Now read the response
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
final String response = reader.readLine();
|
||||
|
||||
// close resources
|
||||
writer.close();
|
||||
reader.close();
|
||||
|
||||
if (response == null || response.startsWith("ERR")) {
|
||||
throw new IOException(response); //Throw the exception
|
||||
} else {
|
||||
// Is this the first update this hour?
|
||||
if (response.contains("OK This is your first update this hour")) {
|
||||
synchronized (graphs) {
|
||||
final Iterator<Graph> iter = graphs.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
final Graph graph = iter.next();
|
||||
|
||||
for (Plotter plotter : graph.getPlotters()) {
|
||||
plotter.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if mineshafter is present. If it is, we need to bypass it to send POST requests
|
||||
*
|
||||
* @return true if mineshafter is installed on the server
|
||||
*/
|
||||
private boolean isMineshafterPresent() {
|
||||
try {
|
||||
Class.forName("mineshafter.MineServer");
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Encode a key/value data pair to be used in a HTTP post request. This INCLUDES a & so the first key/value pair
|
||||
* MUST be included manually, e.g:</p>
|
||||
* <code>
|
||||
* StringBuffer data = new StringBuffer();
|
||||
* data.append(encode("guid")).append('=').append(encode(guid));
|
||||
* encodeDataPair(data, "version", description.getVersion());
|
||||
* </code>
|
||||
*
|
||||
* @param buffer the stringbuilder to append the data pair onto
|
||||
* @param key the key value
|
||||
* @param value the value
|
||||
*/
|
||||
private static void encodeDataPair(final StringBuilder buffer, final String key, final String value) throws UnsupportedEncodingException {
|
||||
buffer.append('&').append(encode(key)).append('=').append(encode(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode text as UTF-8
|
||||
*
|
||||
* @param text the text to encode
|
||||
* @return the encoded text, as UTF-8
|
||||
*/
|
||||
private static String encode(final String text) throws UnsupportedEncodingException {
|
||||
return URLEncoder.encode(text, "UTF-8");
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom graph on the website
|
||||
*/
|
||||
public static class Graph {
|
||||
|
||||
/**
|
||||
* The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is
|
||||
* rejected
|
||||
*/
|
||||
private final String name;
|
||||
/**
|
||||
* The set of plotters that are contained within this graph
|
||||
*/
|
||||
private final Set<Plotter> plotters = new LinkedHashSet<Plotter>();
|
||||
|
||||
private Graph(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the graph's name
|
||||
*
|
||||
* @return the Graph's name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a plotter to the graph, which will be used to plot entries
|
||||
*
|
||||
* @param plotter the plotter to add to the graph
|
||||
*/
|
||||
public void addPlotter(final Plotter plotter) {
|
||||
plotters.add(plotter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a plotter from the graph
|
||||
*
|
||||
* @param plotter the plotter to remove from the graph
|
||||
*/
|
||||
public void removePlotter(final Plotter plotter) {
|
||||
plotters.remove(plotter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an <b>unmodifiable</b> set of the plotter objects in the graph
|
||||
*
|
||||
* @return an unmodifiable {@link java.util.Set} of the plotter objects
|
||||
*/
|
||||
public Set<Plotter> getPlotters() {
|
||||
return Collections.unmodifiableSet(plotters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object object) {
|
||||
if (!(object instanceof Graph)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Graph graph = (Graph) object;
|
||||
return graph.name.equals(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the server owner decides to opt-out of BukkitMetrics while the server is running.
|
||||
*/
|
||||
protected void onOptOut() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface used to collect custom data for a plugin
|
||||
*/
|
||||
public static abstract class Plotter {
|
||||
|
||||
/**
|
||||
* The plot's name
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Construct a plotter with the default plot name
|
||||
*/
|
||||
public Plotter() {
|
||||
this("Default");
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a plotter with a specific plot name
|
||||
*
|
||||
* @param name the name of the plotter to use, which will show up on the website
|
||||
*/
|
||||
public Plotter(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current value for the plotted point. Since this function defers to an external function it may or may
|
||||
* not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called
|
||||
* from any thread so care should be taken when accessing resources that need to be synchronized.
|
||||
*
|
||||
* @return the current value for the point to be plotted.
|
||||
*/
|
||||
public abstract int getValue();
|
||||
|
||||
/**
|
||||
* Get the column name for the plotted point
|
||||
*
|
||||
* @return the plotted point's column name
|
||||
*/
|
||||
public String getColumnName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the website graphs have been updated
|
||||
*/
|
||||
public void reset() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getColumnName().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object object) {
|
||||
if (!(object instanceof Plotter)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Plotter plotter = (Plotter) object;
|
||||
return plotter.name.equals(name) && plotter.getValue() == getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,725 @@
|
||||
package com.garbagemule.MobArena.region;
|
||||
|
||||
import com.garbagemule.MobArena.MAUtils;
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.util.Enums;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.garbagemule.MobArena.util.config.ConfigUtils.*;
|
||||
|
||||
public class ArenaRegion
|
||||
{
|
||||
private Arena arena;
|
||||
private World world;
|
||||
|
||||
private Location lastP1, lastP2, lastL1, lastL2;
|
||||
private Location p1, p2, l1, l2, arenaWarp, lobbyWarp, specWarp, exitWarp, leaderboard;
|
||||
private Map<String,Location> spawnpoints, containers;
|
||||
|
||||
private boolean setup, lobbySetup;
|
||||
|
||||
private ConfigurationSection coords;
|
||||
private ConfigurationSection spawns;
|
||||
private ConfigurationSection chests;
|
||||
|
||||
public ArenaRegion(ConfigurationSection section, Arena arena) {
|
||||
this.arena = arena;
|
||||
refreshWorld();
|
||||
|
||||
this.coords = makeSection(section, "coords");
|
||||
this.spawns = makeSection(coords, "spawnpoints");
|
||||
this.chests = makeSection(coords, "containers");
|
||||
|
||||
reloadAll();
|
||||
}
|
||||
|
||||
public void refreshWorld() {
|
||||
this.world = arena.getWorld();
|
||||
}
|
||||
|
||||
public void reloadAll() {
|
||||
reloadRegion();
|
||||
reloadWarps();
|
||||
reloadLeaderboards();
|
||||
reloadSpawnpoints();
|
||||
reloadChests();
|
||||
|
||||
verifyData();
|
||||
}
|
||||
|
||||
public void reloadRegion() {
|
||||
p1 = parseLocation(coords, "p1", world);
|
||||
p2 = parseLocation(coords, "p2", world);
|
||||
//fixRegion();
|
||||
|
||||
l1 = parseLocation(coords, "l1", world);
|
||||
l2 = parseLocation(coords, "l2", world);
|
||||
//fixLobbyRegion();
|
||||
}
|
||||
|
||||
public void reloadWarps() {
|
||||
arenaWarp = parseLocation(coords, "arena", world);
|
||||
lobbyWarp = parseLocation(coords, "lobby", world);
|
||||
specWarp = parseLocation(coords, "spectator", world);
|
||||
exitWarp = parseLocation(coords, "exit", null);
|
||||
}
|
||||
|
||||
public void reloadLeaderboards() {
|
||||
// try-catch for backwards compatibility
|
||||
try {
|
||||
leaderboard = parseLocation(coords, "leaderboard", null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
leaderboard = parseLocation(coords, "leaderboard", world);
|
||||
}
|
||||
if (leaderboard != null && leaderboard.getWorld() == null) {
|
||||
leaderboard.setWorld(world);
|
||||
}
|
||||
}
|
||||
|
||||
public void reloadSpawnpoints() {
|
||||
spawnpoints = new HashMap<String,Location>();
|
||||
Set<String> keys = spawns.getKeys(false);
|
||||
if (keys != null) {
|
||||
for (String spwn : keys) {
|
||||
spawnpoints.put(spwn, parseLocation(spawns, spwn, world));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void reloadChests() {
|
||||
containers = new HashMap<String,Location>();
|
||||
Set<String> keys = chests.getKeys(false);
|
||||
if (keys != null) {
|
||||
for (String chst : keys) {
|
||||
containers.put(chst, parseLocation(chests, chst, world));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void verifyData() {
|
||||
setup = (p1 != null &&
|
||||
p2 != null &&
|
||||
arenaWarp != null &&
|
||||
lobbyWarp != null &&
|
||||
specWarp != null &&
|
||||
!spawnpoints.isEmpty());
|
||||
|
||||
lobbySetup = (l1 != null &&
|
||||
l2 != null);
|
||||
}
|
||||
|
||||
public void checkData(MobArena plugin, CommandSender s, boolean ready, boolean region, boolean warps, boolean spawns) {
|
||||
// Verify data first
|
||||
verifyData();
|
||||
|
||||
// Prepare the list
|
||||
List<String> list = new ArrayList<String>();
|
||||
|
||||
// Region points
|
||||
if (region) {
|
||||
if (p1 == null) list.add("p1");
|
||||
if (p2 == null) list.add("p2");
|
||||
if (!list.isEmpty()) {
|
||||
Messenger.tell(s, "Missing region points: " + MAUtils.listToString(list, plugin));
|
||||
list.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Warps
|
||||
if (warps) {
|
||||
if (arenaWarp == null) list.add("arena");
|
||||
if (lobbyWarp == null) list.add("lobby");
|
||||
if (specWarp == null) list.add("spectator");
|
||||
if (!list.isEmpty()) {
|
||||
Messenger.tell(s, "Missing warps: " + MAUtils.listToString(list, plugin));
|
||||
list.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Spawnpoints
|
||||
if (spawns) {
|
||||
if (spawnpoints.isEmpty()) {
|
||||
Messenger.tell(s, "Missing spawnpoints");
|
||||
}
|
||||
}
|
||||
|
||||
// Ready?
|
||||
if (ready && setup) {
|
||||
Messenger.tell(s, "Arena is ready to be used!");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDefined() {
|
||||
return (p1 != null && p2 != null);
|
||||
}
|
||||
|
||||
public boolean isLobbyDefined() {
|
||||
return (l1 != null && l2 != null);
|
||||
}
|
||||
|
||||
public boolean isSetup() {
|
||||
return setup;
|
||||
}
|
||||
|
||||
public boolean isLobbySetup() {
|
||||
return lobbySetup;
|
||||
}
|
||||
|
||||
public boolean isWarp(Location l) {
|
||||
return (l.equals(arenaWarp) ||
|
||||
l.equals(lobbyWarp) ||
|
||||
l.equals(specWarp) ||
|
||||
l.equals(exitWarp));
|
||||
}
|
||||
|
||||
public boolean contains(Location l) {
|
||||
if (!l.getWorld().getName().equals(world.getName()) || !isDefined()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int x = l.getBlockX();
|
||||
int y = l.getBlockY();
|
||||
int z = l.getBlockZ();
|
||||
|
||||
// Check the lobby first.
|
||||
if (lobbySetup) {
|
||||
if ((x >= l1.getBlockX() && x <= l2.getBlockX()) &&
|
||||
(z >= l1.getBlockZ() && z <= l2.getBlockZ()) &&
|
||||
(y >= l1.getBlockY() && y <= l2.getBlockY()))
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns false if the location is outside of the region.
|
||||
return ((x >= p1.getBlockX() && x <= p2.getBlockX()) &&
|
||||
(z >= p1.getBlockZ() && z <= p2.getBlockZ()) &&
|
||||
(y >= p1.getBlockY() && y <= p2.getBlockY()));
|
||||
}
|
||||
|
||||
public boolean contains(Location l, int radius) {
|
||||
if (!l.getWorld().getName().equals(world.getName()) || !isDefined()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int x = l.getBlockX();
|
||||
int y = l.getBlockY();
|
||||
int z = l.getBlockZ();
|
||||
|
||||
if (lobbySetup) {
|
||||
if ((x + radius >= l1.getBlockX() && x - radius <= l2.getBlockX()) &&
|
||||
(z + radius >= l1.getBlockZ() && z - radius <= l2.getBlockZ()) &&
|
||||
(y + radius >= l1.getBlockY() && y - radius <= l2.getBlockY()))
|
||||
return true;
|
||||
}
|
||||
|
||||
return ((x + radius >= p1.getBlockX() && x - radius <= p2.getBlockX()) &&
|
||||
(z + radius >= p1.getBlockZ() && z - radius <= p2.getBlockZ()) &&
|
||||
(y + radius >= p1.getBlockY() && y - radius <= p2.getBlockY()));
|
||||
}
|
||||
|
||||
// Region expand
|
||||
public void expandUp(int amount) {
|
||||
int x = p2.getBlockX();
|
||||
int y = Math.min(p2.getWorld().getMaxHeight(), p2.getBlockY() + amount);
|
||||
int z = p2.getBlockZ();
|
||||
setSaveReload(coords, "p2", p2.getWorld(), x ,y ,z);
|
||||
}
|
||||
|
||||
public void expandDown(int amount) {
|
||||
int x = p1.getBlockX();
|
||||
int y = Math.max(0, p1.getBlockY() - amount);
|
||||
int z = p1.getBlockZ();
|
||||
setSaveReload(coords, "p1", p1.getWorld(), x ,y ,z);
|
||||
}
|
||||
|
||||
public void expandP1(int dx, int dz) {
|
||||
int x = p1.getBlockX() - dx;
|
||||
int y = p1.getBlockY();
|
||||
int z = p1.getBlockZ() - dz;
|
||||
setSaveReload(coords, "p1", p1.getWorld(), x ,y ,z);
|
||||
}
|
||||
|
||||
public void expandP2(int dx, int dz) {
|
||||
int x = p2.getBlockX() + dx;
|
||||
int y = p2.getBlockY();
|
||||
int z = p2.getBlockZ() + dz;
|
||||
setSaveReload(coords, "p2", p2.getWorld(), x ,y ,z);
|
||||
}
|
||||
|
||||
public void expandOut(int amount) {
|
||||
expandP1(amount, amount);
|
||||
expandP2(amount, amount);
|
||||
}
|
||||
|
||||
// Lobby expand
|
||||
public void expandLobbyUp(int amount) {
|
||||
int x = l2.getBlockX();
|
||||
int y = Math.min(l2.getWorld().getMaxHeight(), l2.getBlockY() + amount);
|
||||
int z = l2.getBlockZ();
|
||||
setSaveReload(coords, "l2", l2.getWorld(), x ,y ,z);
|
||||
}
|
||||
|
||||
public void expandLobbyDown(int amount) {
|
||||
int x = l1.getBlockX();
|
||||
int y = Math.max(0, l1.getBlockY() - amount);
|
||||
int z = l1.getBlockZ();
|
||||
setSaveReload(coords, "l1", l1.getWorld(), x ,y ,z);
|
||||
}
|
||||
|
||||
public void expandL1(int dx, int dz) {
|
||||
int x = l1.getBlockX() - dx;
|
||||
int y = l1.getBlockY();
|
||||
int z = l1.getBlockZ() - dz;
|
||||
setSaveReload(coords, "l1", l1.getWorld(), x ,y ,z);
|
||||
}
|
||||
|
||||
public void expandL2(int dx, int dz) {
|
||||
int x = l2.getBlockX() + dx;
|
||||
int y = l2.getBlockY();
|
||||
int z = l2.getBlockZ() + dz;
|
||||
setSaveReload(coords, "l2", l2.getWorld(), x ,y ,z);
|
||||
}
|
||||
|
||||
public void expandLobbyOut(int amount) {
|
||||
expandL1(amount, amount);
|
||||
expandL2(amount, amount);
|
||||
}
|
||||
|
||||
private void setSaveReload(ConfigurationSection section, String key, World w, double x, double y, double z) {
|
||||
Location loc = new Location(w, x, y, z);
|
||||
setLocation(section, key, loc);
|
||||
save();
|
||||
reloadRegion();
|
||||
}
|
||||
|
||||
public void fixRegion() {
|
||||
fix("p1", "p2");
|
||||
}
|
||||
|
||||
public void fixLobbyRegion() {
|
||||
fix("l1", "l2");
|
||||
}
|
||||
|
||||
private void fix(String location1, String location2) {
|
||||
Location loc1 = parseLocation(coords, location1, world);
|
||||
Location loc2 = parseLocation(coords, location2, world);
|
||||
|
||||
if (loc1 == null || loc2 == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean modified = false;
|
||||
|
||||
if (loc1.getX() > loc2.getX()) {
|
||||
double tmp = loc1.getX();
|
||||
loc1.setX(loc2.getX());
|
||||
loc2.setX(tmp);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (loc1.getZ() > loc2.getZ()) {
|
||||
double tmp = loc1.getZ();
|
||||
loc1.setZ(loc2.getZ());
|
||||
loc2.setZ(tmp);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (loc1.getY() > loc2.getY()) {
|
||||
double tmp = loc1.getY();
|
||||
loc1.setY(loc2.getY());
|
||||
loc2.setY(tmp);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (!arena.getWorld().getName().equals(world.getName())) {
|
||||
arena.setWorld(world);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (!modified) {
|
||||
return;
|
||||
}
|
||||
|
||||
setLocation(coords, location1, loc1);
|
||||
setLocation(coords, location2, loc2);
|
||||
save();
|
||||
}
|
||||
|
||||
public List<Chunk> getChunks() {
|
||||
List<Chunk> result = new ArrayList<Chunk>();
|
||||
|
||||
if (p1 == null || p2 == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
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++) {
|
||||
result.add(world.getChunkAt(i,j));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Location getArenaWarp() {
|
||||
return arenaWarp;
|
||||
}
|
||||
|
||||
public Location getLobbyWarp() {
|
||||
return lobbyWarp;
|
||||
}
|
||||
|
||||
public Location getSpecWarp() {
|
||||
return specWarp;
|
||||
}
|
||||
|
||||
public Location getExitWarp() {
|
||||
return exitWarp;
|
||||
}
|
||||
|
||||
public Location getSpawnpoint(String name) {
|
||||
return spawnpoints.get(name);
|
||||
}
|
||||
|
||||
public Collection<Location> getSpawnpoints() {
|
||||
return spawnpoints.values();
|
||||
}
|
||||
|
||||
public List<Location> getSpawnpointList() {
|
||||
return new ArrayList<Location>(spawnpoints.values());
|
||||
}
|
||||
|
||||
public Collection<Location> getContainers() {
|
||||
return containers.values();
|
||||
}
|
||||
|
||||
public Location getLeaderboard() {
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
public void set(RegionPoint point, Location loc) {
|
||||
// Act based on the point
|
||||
switch (point) {
|
||||
case P1:
|
||||
case P2:
|
||||
case L1:
|
||||
case L2: setPoint(point, loc); return;
|
||||
case ARENA:
|
||||
case LOBBY:
|
||||
case EXIT:
|
||||
case SPECTATOR: setWarp(point, loc); return;
|
||||
case LEADERBOARD: setLeaderboard(loc); return;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid region point!");
|
||||
}
|
||||
|
||||
private void setPoint(RegionPoint point, Location l) {
|
||||
// Lower and upper locations
|
||||
RegionPoint r1, r2;
|
||||
Location lower, upper;
|
||||
|
||||
/* Initialize the bounds.
|
||||
*
|
||||
* To allow users to set a region point without paying attention to
|
||||
* the 'fixed' points, we continuously store the previously stored
|
||||
* location for the given point. These location references are only
|
||||
* ever overwritten when using the set commands, and remain fully
|
||||
* decoupled from the 'fixed' points.
|
||||
*
|
||||
* Effectively, the config-file and region store 'fixed' locations
|
||||
* that allow fast membership tests, but the region also stores the
|
||||
* 'unfixed' locations for a more intuitive setup process.
|
||||
*/
|
||||
switch (point) {
|
||||
case P1:
|
||||
lastP1 = l.clone();
|
||||
lower = lastP1.clone();
|
||||
upper = (lastP2 != null ? lastP2.clone() : p2);
|
||||
r1 = RegionPoint.P1; r2 = RegionPoint.P2;
|
||||
break;
|
||||
case P2:
|
||||
lastP2 = l.clone();
|
||||
lower = (lastP1 != null ? lastP1.clone() : p1);
|
||||
upper = lastP2.clone();
|
||||
r1 = RegionPoint.P1; r2 = RegionPoint.P2;
|
||||
break;
|
||||
case L1:
|
||||
lastL1 = l.clone();
|
||||
lower = lastL1.clone();
|
||||
upper = (lastL2 != null ? lastL2.clone() : l2);
|
||||
r1 = RegionPoint.L1; r2 = RegionPoint.L2;
|
||||
break;
|
||||
case L2:
|
||||
lastL2 = l.clone();
|
||||
lower = (lastL1 != null ? lastL1.clone() : l1);
|
||||
upper = lastL2.clone();
|
||||
r1 = RegionPoint.L1; r2 = RegionPoint.L2;
|
||||
break;
|
||||
default:
|
||||
lower = upper = null;
|
||||
r1 = r2 = null;
|
||||
}
|
||||
|
||||
// Min-max if both locations are non-null
|
||||
if (lower != null && upper != null) {
|
||||
double tmp;
|
||||
if (lower.getX() > upper.getX()) {
|
||||
tmp = lower.getX();
|
||||
lower.setX(upper.getX());
|
||||
upper.setX(tmp);
|
||||
}
|
||||
if (lower.getY() > upper.getY()) {
|
||||
tmp = lower.getY();
|
||||
lower.setY(upper.getY());
|
||||
upper.setY(tmp);
|
||||
}
|
||||
if (lower.getZ() > upper.getZ()) {
|
||||
tmp = lower.getZ();
|
||||
lower.setZ(upper.getZ());
|
||||
upper.setZ(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the coords and save
|
||||
if (lower != null) setLocation(coords, r1.name().toLowerCase(), lower);
|
||||
if (upper != null) setLocation(coords, r2.name().toLowerCase(), upper);
|
||||
save();
|
||||
|
||||
// Reload regions and verify data
|
||||
reloadRegion();
|
||||
verifyData();
|
||||
}
|
||||
|
||||
public void set(String point, Location loc) {
|
||||
// Get the region point enum
|
||||
RegionPoint rp = Enums.getEnumFromString(RegionPoint.class, point);
|
||||
if (rp == null) throw new IllegalArgumentException("Invalid region point '" + point + "'");
|
||||
|
||||
// Then delegate
|
||||
set(rp, loc);
|
||||
}
|
||||
|
||||
public void setWarp(RegionPoint point, Location l) {
|
||||
// Set the point and save
|
||||
setLocation(coords, point.toString(), l);
|
||||
save();
|
||||
|
||||
// Then reload warps
|
||||
reloadWarps();
|
||||
}
|
||||
|
||||
public void setLeaderboard(Location l) {
|
||||
// Set the point and save
|
||||
setLocation(coords, "leaderboard", l);
|
||||
save();
|
||||
|
||||
// Then reload the leaderboards
|
||||
reloadLeaderboards();
|
||||
}
|
||||
|
||||
public void addSpawn(String name, Location loc) {
|
||||
// Add the spawn and save
|
||||
setLocation(spawns, name, loc);
|
||||
save();
|
||||
|
||||
// Reload spawnpoints and verify data
|
||||
reloadSpawnpoints();
|
||||
verifyData();
|
||||
}
|
||||
|
||||
public boolean removeSpawn(String name) {
|
||||
// Check if the spawnpoint exists
|
||||
if (spawns.getString(name) == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Null the spawnpoint and save
|
||||
setLocation(spawns, name, null);
|
||||
save();
|
||||
|
||||
// Reload spawnpoints and verify data
|
||||
reloadSpawnpoints();
|
||||
verifyData();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addChest(String name, Location loc) {
|
||||
// Add the chest location and save
|
||||
setLocation(chests, name, loc);
|
||||
save();
|
||||
|
||||
// Reload the chests
|
||||
reloadChests();
|
||||
}
|
||||
|
||||
public boolean removeChest(String name) {
|
||||
// Check if the chest exists
|
||||
if (chests.getString(name) == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Null the chest and save
|
||||
setLocation(chests, name, null);
|
||||
save();
|
||||
|
||||
// Reload the chests
|
||||
reloadChests();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
arena.getPlugin().saveConfig();
|
||||
}
|
||||
|
||||
public void showRegion(Player p) {
|
||||
if (!isDefined()) {
|
||||
return;
|
||||
}
|
||||
showBlocks(p, getFramePoints(p1, p2));
|
||||
}
|
||||
|
||||
public void showLobbyRegion(Player p) {
|
||||
if (!isLobbyDefined()) {
|
||||
return;
|
||||
}
|
||||
showBlocks(p, getFramePoints(l1, l2));
|
||||
}
|
||||
|
||||
public void showSpawns(Player p) {
|
||||
if (spawnpoints.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
showBlocks(p, spawnpoints.values());
|
||||
}
|
||||
|
||||
public void showChests(Player p) {
|
||||
if (containers.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
showBlocks(p, containers.values());
|
||||
}
|
||||
|
||||
public void checkSpawns(Player p) {
|
||||
if (spawnpoints.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find all the spawnpoints that cover the location
|
||||
Map<String,Location> map = new HashMap<String,Location>();
|
||||
for (Map.Entry<String,Location> entry : spawnpoints.entrySet()) {
|
||||
if (p.getLocation().distanceSquared(entry.getValue()) < MobArena.MIN_PLAYER_DISTANCE_SQUARED) {
|
||||
map.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (map.isEmpty()) {
|
||||
Messenger.tell(p, "No spawnpoints cover your location!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify the player
|
||||
Messenger.tell(p, "The following points cover your location:");
|
||||
for (Map.Entry<String,Location> entry : map.entrySet()) {
|
||||
Location l = entry.getValue();
|
||||
String coords = l.getBlockX() + "," + l.getBlockY() + "," + l.getBlockZ();
|
||||
p.sendMessage(ChatColor.AQUA + entry.getKey() + ChatColor.WHITE + " : " + coords);
|
||||
}
|
||||
|
||||
// And show the blocks
|
||||
showBlocks(p, map.values());
|
||||
}
|
||||
|
||||
public void showBlock(final Player p, final Location loc, final int id, final byte data) {
|
||||
arena.scheduleTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
p.sendBlockChange(loc, id, data);
|
||||
arena.scheduleTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!p.isOnline()) return;
|
||||
|
||||
Block b = loc.getBlock();
|
||||
p.sendBlockChange(loc, b.getTypeId(), b.getData());
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
private void showBlocks(final Player p, final Collection<Location> points) {
|
||||
arena.scheduleTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Grab all the blocks, and send block change events.
|
||||
final Map<Location,BlockState> blocks = new HashMap<Location,BlockState>();
|
||||
for (Location l : points) {
|
||||
Block b = l.getBlock();
|
||||
blocks.put(l, b.getState());
|
||||
p.sendBlockChange(l, 35, (byte) 14);
|
||||
}
|
||||
arena.scheduleTask(new Runnable() {
|
||||
public void run() {
|
||||
// If the player isn't online, just forget it.
|
||||
if (!p.isOnline()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send block "restore" events.
|
||||
for (Map.Entry<Location,BlockState> entry : blocks.entrySet()) {
|
||||
Location l = entry.getKey();
|
||||
BlockState b = entry.getValue();
|
||||
int id = b.getTypeId();
|
||||
byte data = b.getRawData();
|
||||
|
||||
p.sendBlockChange(l, id, data);
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
private List<Location> getFramePoints(Location loc1, Location loc2) {
|
||||
List<Location> result = new ArrayList<Location>();
|
||||
int x1 = loc1.getBlockX(); int y1 = loc1.getBlockY(); int z1 = loc1.getBlockZ();
|
||||
int x2 = loc2.getBlockX(); int y2 = loc2.getBlockY(); int z2 = loc2.getBlockZ();
|
||||
|
||||
for (int i = x1; i <= x2; i++) {
|
||||
result.add(world.getBlockAt(i, y1, z1).getLocation());
|
||||
result.add(world.getBlockAt(i, y1, z2).getLocation());
|
||||
result.add(world.getBlockAt(i, y2, z1).getLocation());
|
||||
result.add(world.getBlockAt(i, y2, z2).getLocation());
|
||||
}
|
||||
|
||||
for (int j = y1; j <= y2; j++) {
|
||||
result.add(world.getBlockAt(x1, j, z1).getLocation());
|
||||
result.add(world.getBlockAt(x1, j, z2).getLocation());
|
||||
result.add(world.getBlockAt(x2, j, z1).getLocation());
|
||||
result.add(world.getBlockAt(x2, j, z2).getLocation());
|
||||
}
|
||||
|
||||
for (int k = z1; k <= z2; k++) {
|
||||
result.add(world.getBlockAt(x1, y1, k).getLocation());
|
||||
result.add(world.getBlockAt(x1, y2, k).getLocation());
|
||||
result.add(world.getBlockAt(x2, y1, k).getLocation());
|
||||
result.add(world.getBlockAt(x2, y2, k).getLocation());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.garbagemule.MobArena.region;
|
||||
|
||||
public enum RegionPoint {
|
||||
P1,
|
||||
P2,
|
||||
L1,
|
||||
L2,
|
||||
ARENA,
|
||||
LOBBY,
|
||||
SPECTATOR,
|
||||
EXIT,
|
||||
LEADERBOARD;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.garbagemule.MobArena.region;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public class RegionSerializer
|
||||
{
|
||||
//private UUID worldUID;
|
||||
private int x1, y1, z1, x2, y2, z2;
|
||||
private long width, height, length;
|
||||
|
||||
private int[][][] blocks;
|
||||
private byte[][][] data;
|
||||
|
||||
//private transient World world;
|
||||
|
||||
public RegionSerializer(World world, Location p1, Location p2) {
|
||||
//this.worldUID = world.getUID();
|
||||
|
||||
this.x1 = p1.getBlockX();
|
||||
this.y1 = p1.getBlockY();
|
||||
this.z1 = p1.getBlockZ();
|
||||
|
||||
this.x2 = p2.getBlockX();
|
||||
this.y2 = p2.getBlockY();
|
||||
this.z2 = p2.getBlockZ();
|
||||
|
||||
this.width = (x2 - x1) + 1;
|
||||
this.height = (y2 - y1) + 1;
|
||||
this.length = (z2 - z1) + 1;
|
||||
|
||||
int w = (int) width;
|
||||
int h = (int) height;
|
||||
int l = (int) length;
|
||||
|
||||
this.blocks = new int[w][h][l];
|
||||
this.data = new byte[w][h][l];
|
||||
}
|
||||
|
||||
public void serialize(Arena arena) {
|
||||
Serializer s = new Serializer(arena);
|
||||
s.start();
|
||||
}
|
||||
|
||||
public void deserialize(Arena arena) {
|
||||
Deserializer d = new Deserializer(arena);
|
||||
d.start();
|
||||
}
|
||||
|
||||
private class Serializer implements Runnable
|
||||
{
|
||||
private Arena arena;
|
||||
private long total;
|
||||
|
||||
public Serializer(Arena arena) {
|
||||
this.arena = arena;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
// Disable the arena while serializing.
|
||||
arena.setEnabled(false);
|
||||
|
||||
// Start serializing!
|
||||
total = 0;
|
||||
arena.scheduleTask(this, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
int y = (int) (total / (width*length));
|
||||
int z = (int) ((total % (width*length)) / width);
|
||||
int x = (int) ((total % (width*length)) % width);
|
||||
|
||||
long max = width*height*length;
|
||||
int amount = (int) Math.min(20, (max - total));
|
||||
|
||||
for (int i = 0; i < amount; i++) {
|
||||
Block b = arena.getWorld().getBlockAt(x,y,z);
|
||||
blocks[x][y][z] = b.getTypeId();
|
||||
data[x][y][z] = b.getData();
|
||||
|
||||
x = (int) ((x+1) % width);
|
||||
y = (int) ((y+1) % height);
|
||||
z = (int) ((z+1) % length);
|
||||
}
|
||||
|
||||
total += amount;
|
||||
|
||||
if (total == max) {
|
||||
arena.setEnabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
arena.scheduleTask(this, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private class Deserializer implements Runnable
|
||||
{
|
||||
private Arena arena;
|
||||
private long total;
|
||||
|
||||
public Deserializer(Arena arena) {
|
||||
this.arena = arena;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
// Disable the arena while serializing.
|
||||
arena.setEnabled(false);
|
||||
|
||||
// Start serializing!
|
||||
total = 0;
|
||||
arena.scheduleTask(this, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
int y = (int) (total / (width*length));
|
||||
int z = (int) ((total % (width*length)) / width);
|
||||
int x = (int) ((total % (width*length)) % width);
|
||||
|
||||
long max = width*height*length;
|
||||
int amount = (int) Math.min(20, (max - total));
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
Block b = arena.getWorld().getBlockAt(x,y,z);
|
||||
b.setTypeIdAndData(blocks[x][y][z], data[x][y][z], false);
|
||||
}
|
||||
|
||||
total += amount;
|
||||
|
||||
if (total == max) {
|
||||
arena.setEnabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
arena.scheduleTask(this, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.garbagemule.MobArena.repairable;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.BlockState;
|
||||
|
||||
public interface Repairable
|
||||
{
|
||||
public void repair();
|
||||
|
||||
public BlockState getState();
|
||||
|
||||
public Material getType();
|
||||
public int getId();
|
||||
public byte getData();
|
||||
|
||||
public World getWorld();
|
||||
public int getX();
|
||||
public int getY();
|
||||
public int getZ();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
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();
|
||||
|
||||
state.getBlock().setTypeId(1);
|
||||
}
|
||||
|
||||
public void repair()
|
||||
{
|
||||
Block b = getWorld().getBlockAt(x,y,z);
|
||||
if (b.getTypeId() == 0)
|
||||
b.setTypeId(1);
|
||||
|
||||
super.repair();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.garbagemule.MobArena.repairable;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.BlockState;
|
||||
|
||||
public class RepairableBlock implements Repairable
|
||||
{
|
||||
private BlockState state;
|
||||
private World world;
|
||||
private int id, x, y, z;
|
||||
private Material type;
|
||||
private byte data;
|
||||
|
||||
public RepairableBlock(BlockState state)
|
||||
{
|
||||
this.state = state;
|
||||
|
||||
world = state.getWorld();
|
||||
|
||||
x = state.getX();
|
||||
y = state.getY();
|
||||
z = state.getZ();
|
||||
|
||||
id = state.getTypeId();
|
||||
type = state.getType();
|
||||
data = state.getRawData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Repairs the block by setting the type and data
|
||||
*/
|
||||
public void repair()
|
||||
{
|
||||
world.getBlockAt(x,y,z).setTypeIdAndData(id, data, false);
|
||||
}
|
||||
|
||||
public BlockState getState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
public World getWorld()
|
||||
{
|
||||
return world;
|
||||
}
|
||||
|
||||
public Material getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public byte getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
public int getX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getZ()
|
||||
{
|
||||
return z;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
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;
|
||||
|
||||
public class RepairableComparator implements Comparator<Repairable>
|
||||
{
|
||||
public int compare(Repairable r1, Repairable r2)
|
||||
{
|
||||
if (restoreLast(r1))
|
||||
{
|
||||
if (restoreLast(r2))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
else if (restoreLast(r2))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private boolean restoreLast(Repairable r)
|
||||
{
|
||||
Material t = r.getType();
|
||||
MaterialData m = r.getState().getData();
|
||||
|
||||
return (m instanceof Attachable || m instanceof Redstone || m instanceof Door || m instanceof Bed || t == Material.STATIONARY_LAVA || t == Material.STATIONARY_WATER || t == Material.FIRE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.garbagemule.MobArena.repairable;
|
||||
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class RepairableContainer extends RepairableBlock
|
||||
{
|
||||
private ItemStack[] contents;
|
||||
|
||||
public RepairableContainer(BlockState state, boolean clear) {
|
||||
super(state);
|
||||
|
||||
// Grab the inventory of the block
|
||||
Inventory inv = ((InventoryHolder) state).getInventory();
|
||||
ItemStack[] stacks = inv.getContents();
|
||||
|
||||
// Manual copy is necessary due to "reduce to 0" bug in Bukkit
|
||||
contents = new ItemStack[stacks.length];
|
||||
for (int i = 0; i < contents.length; i++) {
|
||||
contents[i] = (stacks[i] != null) ? stacks[i].clone() : null;
|
||||
}
|
||||
|
||||
// Clear the inventory if prompted
|
||||
if (clear) inv.clear();
|
||||
}
|
||||
|
||||
public RepairableContainer(BlockState state) {
|
||||
this(state, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repairs the container block by adding all the contents back in.
|
||||
*/
|
||||
public void repair() {
|
||||
super.repair();
|
||||
|
||||
// Grab the inventory
|
||||
InventoryHolder cb = (InventoryHolder) getWorld().getBlockAt(getX(),getY(),getZ()).getState();
|
||||
Inventory chestInv = cb.getInventory();
|
||||
|
||||
chestInv.setContents(contents);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.garbagemule.MobArena.repairable;
|
||||
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.Sign;
|
||||
|
||||
public class RepairableSign extends RepairableAttachable
|
||||
{
|
||||
private String[] lines = new String[4];
|
||||
|
||||
public RepairableSign(BlockState state)
|
||||
{
|
||||
super(state);
|
||||
|
||||
Sign s = (Sign) state;
|
||||
lines = s.getLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Repairs the sign block by restoring all the lines
|
||||
*/
|
||||
public void repair()
|
||||
{
|
||||
super.repair();
|
||||
|
||||
Sign s = (Sign) getWorld().getBlockAt(getX(),getY(),getZ()).getState();
|
||||
s.setLine(0, lines[0]);
|
||||
s.setLine(1, lines[1]);
|
||||
s.setLine(2, lines[2]);
|
||||
s.setLine(3, lines[3]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.garbagemule.MobArena.time;
|
||||
|
||||
public enum Time
|
||||
{
|
||||
DAWN(23000),
|
||||
SUNRISE(23500),
|
||||
MORNING(23900),
|
||||
MIDDAY(6000),
|
||||
NOON(6000),
|
||||
DAY(8000),
|
||||
AFTERNOON(11000),
|
||||
EVENING(12000),
|
||||
SUNSET(12600),
|
||||
DUSK(13300),
|
||||
NIGHT(14000),
|
||||
MIDNIGHT(18000);
|
||||
|
||||
private int time;
|
||||
|
||||
private Time(int time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public int getTime() {
|
||||
return time;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.garbagemule.MobArena.time;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface TimeStrategy
|
||||
{
|
||||
/**
|
||||
* Set the time enum used by setPlayerTime()
|
||||
* @param time a Time enum
|
||||
*/
|
||||
public void setTime(Time time);
|
||||
|
||||
/**
|
||||
* Set the local client time for the player.
|
||||
* @param p a player
|
||||
*/
|
||||
public void setPlayerTime(Player p);
|
||||
|
||||
/**
|
||||
* Reset the local client time for the player to the server time
|
||||
* @param p a player
|
||||
*/
|
||||
public void resetPlayerTime(Player p);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.garbagemule.MobArena.time;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class TimeStrategyLocked implements TimeStrategy
|
||||
{
|
||||
private Time time;
|
||||
|
||||
public TimeStrategyLocked(Time time) {
|
||||
setTime(time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTime(Time time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerTime(Player p) {
|
||||
p.setPlayerTime(time.getTime(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetPlayerTime(Player p) {
|
||||
p.resetPlayerTime();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.garbagemule.MobArena.time;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class TimeStrategyNull implements TimeStrategy
|
||||
{
|
||||
@Override
|
||||
public void setTime(Time time) {}
|
||||
|
||||
@Override
|
||||
public void setPlayerTime(Player p) {}
|
||||
|
||||
@Override
|
||||
public void resetPlayerTime(Player p) {}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.garbagemule.MobArena.util;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
|
||||
public class Delays
|
||||
{
|
||||
public static void douse(MobArena plugin, final Player p, long delay) {
|
||||
if (!plugin.isEnabled()) return;
|
||||
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||
public void run() {
|
||||
if (p.isOnline()) {
|
||||
p.setFireTicks(0);
|
||||
}
|
||||
}
|
||||
}, delay);
|
||||
}
|
||||
|
||||
public static void revivePlayer(MobArena plugin, final Arena arena, final Player p) {
|
||||
if (!plugin.isEnabled()) return;
|
||||
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||
public void run() {
|
||||
if (p.isOnline()) {
|
||||
arena.revivePlayer(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.garbagemule.MobArena.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.bukkit.Location;
|
||||
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;
|
||||
private double z;
|
||||
private String world;
|
||||
private float yaw;
|
||||
private float pitch;
|
||||
|
||||
public EntityPosition(double x, double y, double z, String world, float yaw, float pitch) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.world = world;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
public EntityPosition(Location location) {
|
||||
this.x = location.getX();
|
||||
this.y = location.getY();
|
||||
this.z = location.getZ();
|
||||
this.world = location.getWorld().getName();
|
||||
this.yaw = location.getYaw();
|
||||
this.pitch = location.getPitch();
|
||||
}
|
||||
|
||||
public Location getLocation(World world) {
|
||||
return new Location(world, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public void setPitch(float pitch) {
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
public String getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public void setWorld(String world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setX(double x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public void setY(double y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return yaw;
|
||||
}
|
||||
|
||||
public void setYaw(float yaw) {
|
||||
this.yaw = yaw;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public void setZ(double z) {
|
||||
this.z = z;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.garbagemule.MobArena.util;
|
||||
|
||||
public class Enums
|
||||
{
|
||||
/**
|
||||
* Get the enum value of a string, null if it doesn't exist.
|
||||
*/
|
||||
public static <T extends Enum<T>> T getEnumFromString(Class<T> c, String string) {
|
||||
if (c != null && string != null) {
|
||||
try {
|
||||
return Enum.valueOf(c, string.trim().toUpperCase());
|
||||
}
|
||||
catch(IllegalArgumentException ex) {}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the enum value of a string, null if it doesn't exist.
|
||||
*/
|
||||
public static <T extends Enum<T>> T getEnumFromStringCaseSensitive(Class<T> c, String string) {
|
||||
if (c != null && string != null) {
|
||||
try {
|
||||
return Enum.valueOf(c, string);
|
||||
}
|
||||
catch(IllegalArgumentException ex) {}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
package com.garbagemule.MobArena.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||
import org.bukkit.material.MaterialData;
|
||||
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
|
||||
public class ItemParser
|
||||
{
|
||||
private static final int WOOL_ID = Material.WOOL.getId();
|
||||
private static final int DYE_ID = Material.INK_SACK.getId();
|
||||
|
||||
public static String parseString(ItemStack... stacks) {
|
||||
String result = "";
|
||||
|
||||
// Parse each stack
|
||||
for (ItemStack stack : stacks) {
|
||||
if (stack == null || stack.getTypeId() == 0) continue;
|
||||
|
||||
result += ", " + parseString(stack);
|
||||
}
|
||||
|
||||
// Trim off the leading ', ' if it is there
|
||||
if (!result.equals("")) {
|
||||
result = result.substring(2);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String parseString(ItemStack stack) {
|
||||
if (stack.getTypeId() == 0) return null;
|
||||
|
||||
// <item> part
|
||||
String type = stack.getType().toString().toLowerCase();
|
||||
|
||||
// <data> part
|
||||
MaterialData md = stack.getData();
|
||||
short data = (md != null ? md.getData() : 0);
|
||||
|
||||
// Take wool into account
|
||||
if (stack.getType() == Material.WOOL) {
|
||||
data = (byte) (15 - data);
|
||||
}
|
||||
|
||||
// Take potions into account
|
||||
else if (stack.getType() == Material.POTION) {
|
||||
data = stack.getDurability();
|
||||
}
|
||||
|
||||
// <amount> part
|
||||
int amount = stack.getAmount();
|
||||
|
||||
// Enchantments
|
||||
Map<Enchantment,Integer> enchants = null;
|
||||
if (stack.getType() == Material.ENCHANTED_BOOK) {
|
||||
EnchantmentStorageMeta esm = (EnchantmentStorageMeta) stack.getItemMeta();
|
||||
enchants = esm.getStoredEnchants();
|
||||
} else {
|
||||
enchants = stack.getEnchantments();
|
||||
}
|
||||
String enchantments = "";
|
||||
for (Entry<Enchantment,Integer> entry : enchants.entrySet()) {
|
||||
int id = entry.getKey().getId();
|
||||
int lvl = entry.getValue();
|
||||
|
||||
// <eid>:<level>;
|
||||
enchantments += ";" + id + ":" + lvl;
|
||||
}
|
||||
|
||||
// Trim off the leading ';' if it is there
|
||||
if (!enchantments.equals("")) {
|
||||
enchantments = enchantments.substring(1);
|
||||
}
|
||||
|
||||
// <item>
|
||||
String result = type;
|
||||
|
||||
// <item>(:<data>)
|
||||
if (data != 0) {
|
||||
result += ":" + data;
|
||||
}
|
||||
|
||||
// <item>((:<data>):<amount>) - force if there is data
|
||||
if (amount > 1 || data != 0) {
|
||||
result += ":" + amount;
|
||||
}
|
||||
|
||||
// <item>((:<data>):<amount>) (<eid>:<level>(;<eid>:<level>(; ... )))
|
||||
if (!enchantments.equals("")) {
|
||||
result += " " + enchantments;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<ItemStack> parseItems(String s) {
|
||||
if (s == null) {
|
||||
return new ArrayList<ItemStack>(1);
|
||||
}
|
||||
|
||||
String[] items = s.split(",");
|
||||
List<ItemStack> result = new ArrayList<ItemStack>(items.length);
|
||||
|
||||
for (String item : items) {
|
||||
ItemStack stack = parseItem(item.trim());
|
||||
if (stack != null) {
|
||||
result.add(stack);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ItemStack parseItem(String item) {
|
||||
if (item == null || item.equals(""))
|
||||
return null;
|
||||
|
||||
// Check if the item has enchantments.
|
||||
String[] space = item.split(" ");
|
||||
String[] parts = (space.length == 2 ? space[0].split(":") : item.split(":"));
|
||||
|
||||
ItemStack result = null;
|
||||
|
||||
switch (parts.length) {
|
||||
case 1:
|
||||
result = singleItem(parts[0]);
|
||||
break;
|
||||
case 2:
|
||||
result = withAmount(parts[0], parts[1]);
|
||||
break;
|
||||
case 3:
|
||||
result = withDataAndAmount(parts[0], parts[1], parts[2]);
|
||||
break;
|
||||
}
|
||||
if (result == null || result.getTypeId() == 0) {
|
||||
Messenger.warning("Failed to parse item: " + item);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (space.length == 2) {
|
||||
addEnchantments(result, space[1]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ItemStack singleItem(String item) {
|
||||
if (item.matches("\\$(([1-9]\\d*)|(\\d*.\\d\\d?))")) {
|
||||
double amount = Double.parseDouble(item.substring(1));
|
||||
|
||||
int major = (int) amount;
|
||||
int minor = ((int) (amount * 100D)) % 100;
|
||||
return new ItemStack(MobArena.ECONOMY_MONEY_ID, major, (short) minor);
|
||||
}
|
||||
int id = getTypeId(item);
|
||||
return new ItemStack(id);
|
||||
}
|
||||
|
||||
private static ItemStack withAmount(String item, String amount) {
|
||||
int id = getTypeId(item);
|
||||
int a = getAmount(amount);
|
||||
return new ItemStack(id,a);
|
||||
}
|
||||
|
||||
private static ItemStack withDataAndAmount(String item, String data, String amount) {
|
||||
int id = getTypeId(item);
|
||||
short d = getData(data, id);
|
||||
int a = getAmount(amount);
|
||||
return new ItemStack(id,a,d);
|
||||
}
|
||||
|
||||
private static int getTypeId(String item) {
|
||||
if (item.matches("(-)?[0-9]*")) {
|
||||
return Integer.parseInt(item);
|
||||
}
|
||||
Material m = Enums.getEnumFromString(Material.class, item);
|
||||
return (m != null ? m.getId() : 0);
|
||||
}
|
||||
|
||||
private static short getData(String data, int id) {
|
||||
// Wool and ink are special
|
||||
if (id == WOOL_ID) {
|
||||
DyeColor dye = Enums.getEnumFromString(DyeColor.class, data);
|
||||
if (dye == null) dye = DyeColor.getByWoolData(Byte.parseByte(data));
|
||||
return dye.getWoolData();
|
||||
} else if (id == DYE_ID) {
|
||||
DyeColor dye = Enums.getEnumFromString(DyeColor.class, data);
|
||||
if (dye == null) dye = DyeColor.getByDyeData(Byte.parseByte(data));
|
||||
return dye.getDyeData();
|
||||
}
|
||||
return (data.matches("(-)?[0-9]+") ? Short.parseShort(data) : 0);
|
||||
}
|
||||
|
||||
private static int getAmount(String amount) {
|
||||
if (amount.matches("(-)?[1-9][0-9]*")) {
|
||||
return Integer.parseInt(amount);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static void addEnchantments(ItemStack stack, String list) {
|
||||
String[] parts = list.split(";");
|
||||
|
||||
for (String ench : parts) {
|
||||
addEnchantment(stack, ench.trim());
|
||||
}
|
||||
}
|
||||
|
||||
private static void addEnchantment(ItemStack stack, String ench) {
|
||||
String[] parts = ench.split(":");
|
||||
if (parts.length != 2 || !(parts[0].matches("[0-9]*") && parts[1].matches("[0-9]*"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
int id = Integer.parseInt(parts[0]);
|
||||
int lvl = Integer.parseInt(parts[1]);
|
||||
|
||||
Enchantment e = Enchantment.getById(id);
|
||||
if (e == null) {// || !e.canEnchantItem(stack) || lvl > e.getMaxLevel() || lvl < e.getStartLevel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stack.getType() == Material.ENCHANTED_BOOK) {
|
||||
EnchantmentStorageMeta esm = (EnchantmentStorageMeta) stack.getItemMeta();
|
||||
esm.addStoredEnchant(e, lvl, true);
|
||||
stack.setItemMeta(esm);
|
||||
} else {
|
||||
stack.addUnsafeEnchantment(e, lvl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.garbagemule.MobArena.util;
|
||||
|
||||
public class MutableInt
|
||||
{
|
||||
private int value;
|
||||
|
||||
/**
|
||||
* Create a new MutableInt with the given value.
|
||||
* @param value the initial value of the MutableInt
|
||||
*/
|
||||
public MutableInt(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MutableInt with value 0.
|
||||
*/
|
||||
public MutableInt() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given amount to the internal int value.
|
||||
* @param amount the amount to add
|
||||
*/
|
||||
public void add(double amount) {
|
||||
this.value += amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract the given amount from the internal int value.
|
||||
* @param amount the amount to subtract
|
||||
*/
|
||||
public void sub(int amount) {
|
||||
this.value -= amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the value and return it.
|
||||
* This is essentially the same as calling add(1), followed by value().
|
||||
* @return the value after incrementing by one
|
||||
*/
|
||||
public int inc() {
|
||||
return ++this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement the value and return it.
|
||||
* This is essentially the same as calling sub(1), followed by value().
|
||||
* @return the value after decrementing by one
|
||||
*/
|
||||
public int dec() {
|
||||
return --this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of the MutableInt.
|
||||
* @return the current value
|
||||
*/
|
||||
public int value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "" + value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.garbagemule.MobArena.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
|
||||
public class PotionEffectParser
|
||||
{
|
||||
private static final int TICKS_PER_SECOND = 20;
|
||||
private static final int DEFAULT_POTION_AMPLIFIER = 0;
|
||||
private static final int DEFAULT_POTION_DURATION = Integer.MAX_VALUE;
|
||||
|
||||
public static List<PotionEffect> parsePotionEffects(String s) {
|
||||
if (s == null || s.isEmpty())
|
||||
return null;
|
||||
|
||||
List<PotionEffect> potions = new ArrayList<PotionEffect>();
|
||||
for (String potion : s.split(",")) {
|
||||
PotionEffect eff = parsePotionEffect(potion.trim());
|
||||
if (eff != null) {
|
||||
potions.add(eff);
|
||||
}
|
||||
}
|
||||
|
||||
return potions;
|
||||
}
|
||||
|
||||
public static PotionEffect parsePotionEffect(String p) {
|
||||
if (p == null || p.isEmpty())
|
||||
return null;
|
||||
|
||||
String[] parts = p.split(":");
|
||||
PotionEffect result = null;
|
||||
|
||||
switch (parts.length) {
|
||||
case 1:
|
||||
result = parseSingle(parts[0]);
|
||||
break;
|
||||
case 2:
|
||||
result = withAmplifier(parts[0], parts[1]);
|
||||
break;
|
||||
case 3:
|
||||
result = withAmplifierAndDuration(parts[0], parts[1], parts[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
Messenger.warning("Failed to parse potion effect: " + p);
|
||||
return null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static PotionEffect parseSingle(String type) {
|
||||
PotionEffectType effect = getType(type);
|
||||
|
||||
if (effect == null) {
|
||||
return null;
|
||||
} else {
|
||||
return new PotionEffect(effect, DEFAULT_POTION_DURATION, DEFAULT_POTION_AMPLIFIER);
|
||||
}
|
||||
}
|
||||
|
||||
private static PotionEffect withAmplifier(String type, String amplifier) {
|
||||
PotionEffectType effect = getType(type);
|
||||
int amp = getAmplification(amplifier);
|
||||
|
||||
if (effect == null || amp == -1) {
|
||||
return null;
|
||||
} else {
|
||||
return new PotionEffect(effect, DEFAULT_POTION_DURATION, amp);
|
||||
}
|
||||
}
|
||||
|
||||
private static PotionEffect withAmplifierAndDuration(String type, String amplifier, String duration) {
|
||||
PotionEffectType effect = getType(type);
|
||||
int amp = getAmplification(amplifier);
|
||||
int dur = getDuration(duration);
|
||||
|
||||
if (effect == null || dur == -1 || amp == -1) {
|
||||
return null;
|
||||
} else {
|
||||
return new PotionEffect(effect, dur * TICKS_PER_SECOND, amp);
|
||||
}
|
||||
}
|
||||
|
||||
private static PotionEffectType getType(String type) {
|
||||
PotionEffectType effect = null;
|
||||
|
||||
if (type.matches("[0-9]+")) {
|
||||
effect = PotionEffectType.getById(Integer.parseInt(type));
|
||||
} else {
|
||||
effect = PotionEffectType.getByName(type.toUpperCase());
|
||||
}
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
private static int getDuration(String duration) {
|
||||
int dur = -1;
|
||||
|
||||
if (duration.matches("[0-9]+")) {
|
||||
dur = Integer.parseInt(duration);
|
||||
}
|
||||
|
||||
return dur;
|
||||
}
|
||||
|
||||
private static int getAmplification(String amplifier) {
|
||||
int amp = -1;
|
||||
|
||||
if (amplifier.matches("[0-9]+")) {
|
||||
amp = Integer.parseInt(amplifier);
|
||||
}
|
||||
|
||||
return amp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.garbagemule.MobArena.util;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.Msg;
|
||||
|
||||
public class TextUtils
|
||||
{
|
||||
/**
|
||||
* Add character padding on the right side of a String.
|
||||
* @param s String to add padding to
|
||||
* @param length Total amount of characters in the returned String
|
||||
* @param pad The padding character
|
||||
* @return A padded String with the input length
|
||||
*/
|
||||
public static String padRight(String s, int length, char pad)
|
||||
{
|
||||
StringBuffer buffy = new StringBuffer();
|
||||
buffy.append(s);
|
||||
for (int i = s.length(); i < length; i++)
|
||||
buffy.append(pad);
|
||||
return buffy.toString();
|
||||
}
|
||||
public static String padRight(String s, int length) { return padRight(s, length, ' '); }
|
||||
public static String padRight(int s, int length) { return padRight(Integer.toString(s), length, ' '); }
|
||||
public static String padRight(double s, int length) { return padRight(Double.toString(s), length, ' '); }
|
||||
|
||||
/**
|
||||
* Add character padding on the left side of a String.
|
||||
* @param s String to add padding to
|
||||
* @param length Total amount of characters in the returned String
|
||||
* @param pad The padding character
|
||||
* @return A padded String with the input length
|
||||
*/
|
||||
public static String padLeft(String s, int length, char pad)
|
||||
{
|
||||
StringBuffer buffy = new StringBuffer();
|
||||
for (int i = 0; i < length - s.length(); i++)
|
||||
buffy.append(pad);
|
||||
buffy.append(s);
|
||||
return buffy.toString();
|
||||
}
|
||||
public static String padLeft(String s, int length) { return padLeft(s, length, ' '); }
|
||||
public static String padLeft(int s, int length) { return padLeft(Integer.toString(s), length, ' '); }
|
||||
public static String padLeft(double s, int length) { return padLeft(Double.toString(s), length, ' '); }
|
||||
|
||||
/**
|
||||
* Truncate the input string to be at most the input length
|
||||
* @param s The string to truncate
|
||||
* @param length The maximum length
|
||||
* @return A truncated string with length 15, or the input string
|
||||
*/
|
||||
public static String truncate(String s, int length)
|
||||
{
|
||||
if (s.length() <= length)
|
||||
return s;
|
||||
return s.substring(0, length);
|
||||
}
|
||||
public static String truncate(String s) { return truncate(s, 15); }
|
||||
|
||||
public static String camelCase(String s) {
|
||||
if (s == null || s.length() < 2)
|
||||
return null;
|
||||
|
||||
String firstLetter = s.substring(0,1).toUpperCase();
|
||||
return firstLetter + s.substring(1).toLowerCase();
|
||||
}
|
||||
|
||||
public static String playerListToString(Collection<? extends Player> list) {
|
||||
if (list.isEmpty()) {
|
||||
return Msg.MISC_NONE.toString();
|
||||
}
|
||||
|
||||
StringBuffer buffy = new StringBuffer();
|
||||
for (Player p : list) {
|
||||
buffy.append(", " + p.getName());
|
||||
}
|
||||
return buffy.substring(2);
|
||||
}
|
||||
|
||||
public static String listToString(Collection<? extends Object> list) {
|
||||
if (list.isEmpty()) {
|
||||
return Msg.MISC_NONE.toString();
|
||||
}
|
||||
|
||||
StringBuffer buffy = new StringBuffer();
|
||||
for (Object o : list) {
|
||||
buffy.append(", " + o.toString());
|
||||
}
|
||||
return buffy.substring(2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.garbagemule.MobArena.util;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class TimeUtils
|
||||
{
|
||||
/**
|
||||
* Turn the input long into a string on the form (D:)HH:MM:SS, where the
|
||||
* day-part is only added if the number of days is greater than or equal
|
||||
* to 1, i.e. a long value of 86,399,999.
|
||||
* @param ms time in milliseconds
|
||||
* @return string-representation of the input long
|
||||
*/
|
||||
public static String toTime(long ms) {
|
||||
long total = ms / 1000;
|
||||
long secs = total % 60;
|
||||
long mins = total % 3600 / 60;
|
||||
long hours = total / 3600 % 24;
|
||||
long days = total / 3600 / 24;
|
||||
String time = (days > 0 ? days + ":" : "") +
|
||||
(hours < 10 ? "0" + hours : hours) + ":" +
|
||||
(mins < 10 ? "0" + mins : mins) + ":" +
|
||||
(secs < 10 ? "0" + secs : secs);
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a new java.util.Date with the input long and toString()s it.
|
||||
* @param ms time in milliseconds
|
||||
* @return java.util.Date toString() of the input long
|
||||
*/
|
||||
public static String toDateTime(long ms) {
|
||||
return new Date(ms).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two string-representations of time and returns the resulting time.
|
||||
* @param t1 a time-string
|
||||
* @param t2 another time-string
|
||||
* @return the sum of the time-strings
|
||||
*/
|
||||
public static String addTimes(String t1, String t2) {
|
||||
String[] parts1 = t1.split(":");
|
||||
String[] parts2 = t2.split(":");
|
||||
|
||||
long secs1 = extractSeconds(parts1);
|
||||
long secs2 = extractSeconds(parts2);
|
||||
|
||||
long mins1 = extractMinutes(parts1);
|
||||
long mins2 = extractMinutes(parts2);
|
||||
|
||||
long hours1 = extractHours(parts1);
|
||||
long hours2 = extractHours(parts2);
|
||||
|
||||
long days1 = extractDays(parts1);
|
||||
long days2 = extractDays(parts2);
|
||||
|
||||
long time = (secs1 + secs2 + mins1 + mins2 + hours1 + hours2 + days1 + days2) * 1000;
|
||||
|
||||
return toTime(time);
|
||||
}
|
||||
|
||||
private static long extractSeconds(String[] parts) {
|
||||
int length = parts.length;
|
||||
if (length < 1) {
|
||||
return 0L;
|
||||
}
|
||||
return Long.parseLong(parts[length - 1]);
|
||||
}
|
||||
|
||||
private static long extractMinutes(String[] parts) {
|
||||
int length = parts.length;
|
||||
if (length < 2) {
|
||||
return 0L;
|
||||
}
|
||||
return Long.parseLong(parts[length - 2]) * 60;
|
||||
}
|
||||
|
||||
private static long extractHours(String[] parts) {
|
||||
int length = parts.length;
|
||||
if (length < 3) {
|
||||
return 0L;
|
||||
}
|
||||
return Long.parseLong(parts[length - 3]) * 3600;
|
||||
}
|
||||
|
||||
private static long extractDays(String[] parts) {
|
||||
int length = parts.length;
|
||||
if (length < 4) {
|
||||
return 0L;
|
||||
}
|
||||
return Long.parseLong(parts[length - 4]) * 24 * 3600;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,513 @@
|
||||
/*
|
||||
* Updater for Bukkit.
|
||||
*
|
||||
* This class provides the means to safely and easily update a plugin, or check to see if it is updated using dev.bukkit.org
|
||||
*/
|
||||
package com.garbagemule.MobArena.util;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
/**
|
||||
* Check dev.bukkit.org to find updates for a given plugin, and download the updates if needed.
|
||||
* <p/>
|
||||
* <b>VERY, VERY IMPORTANT</b>: Because there are no standards for adding auto-update toggles in your plugin's config, this system provides NO CHECK WITH YOUR CONFIG to make sure the user has allowed auto-updating.
|
||||
* <br>
|
||||
* It is a <b>BUKKIT POLICY</b> that you include a boolean value in your config that prevents the auto-updater from running <b>AT ALL</b>.
|
||||
* <br>
|
||||
* If you fail to include this option in your config, your plugin will be <b>REJECTED</b> when you attempt to submit it to dev.bukkit.org.
|
||||
* <p/>
|
||||
* An example of a good configuration option would be something similar to 'auto-update: true' - if this value is set to false you may NOT run the auto-updater.
|
||||
* <br>
|
||||
* If you are unsure about these rules, please read the plugin submission guidelines: http://goo.gl/8iU5l
|
||||
*
|
||||
* @author Gravity
|
||||
* @version 2.0
|
||||
*/
|
||||
public class Updater {
|
||||
|
||||
private Plugin plugin;
|
||||
private UpdateType type;
|
||||
private String versionName;
|
||||
private String versionLink;
|
||||
private String versionType;
|
||||
private String versionGameVersion;
|
||||
|
||||
private boolean announce; // Whether to announce file downloads
|
||||
|
||||
private URL url; // Connecting to RSS
|
||||
private File file; // The plugin's file
|
||||
private Thread thread; // Updater thread
|
||||
|
||||
private int id = -1; // Project's Curse ID
|
||||
private String apiKey = null; // BukkitDev ServerMods API key
|
||||
private static final String TITLE_VALUE = "name"; // Gets remote file's title
|
||||
private static final String LINK_VALUE = "downloadUrl"; // Gets remote file's download link
|
||||
private static final String TYPE_VALUE = "releaseType"; // Gets remote file's release type
|
||||
private static final String VERSION_VALUE = "gameVersion"; // Gets remote file's build version
|
||||
private static final String QUERY = "/servermods/files?projectIds="; // Path to GET
|
||||
private static final String HOST = "https://api.curseforge.com"; // Slugs will be appended to this to get to the project's RSS feed
|
||||
|
||||
private static final String[] NO_UPDATE_TAG = { "-DEV", "-PRE", "-SNAPSHOT" }; // If the version number contains one of these, don't update.
|
||||
private static final int BYTE_SIZE = 1024; // Used for downloading files
|
||||
private YamlConfiguration config; // Config file
|
||||
private String updateFolder;// The folder that downloads will be placed in
|
||||
private Updater.UpdateResult result = Updater.UpdateResult.SUCCESS; // Used for determining the outcome of the update process
|
||||
|
||||
/**
|
||||
* Gives the dev the result of the update process. Can be obtained by called getResult().
|
||||
*/
|
||||
public enum UpdateResult {
|
||||
/**
|
||||
* The updater found an update, and has readied it to be loaded the next time the server restarts/reloads.
|
||||
*/
|
||||
SUCCESS,
|
||||
/**
|
||||
* The updater did not find an update, and nothing was downloaded.
|
||||
*/
|
||||
NO_UPDATE,
|
||||
/**
|
||||
* The server administrator has disabled the updating system
|
||||
*/
|
||||
DISABLED,
|
||||
/**
|
||||
* The updater found an update, but was unable to download it.
|
||||
*/
|
||||
FAIL_DOWNLOAD,
|
||||
/**
|
||||
* For some reason, the updater was unable to contact dev.bukkit.org to download the file.
|
||||
*/
|
||||
FAIL_DBO,
|
||||
/**
|
||||
* When running the version check, the file on DBO did not contain the a version in the format 'vVersion' such as 'v1.0'.
|
||||
*/
|
||||
FAIL_NOVERSION,
|
||||
/**
|
||||
* The id provided by the plugin running the updater was invalid and doesn't exist on DBO.
|
||||
*/
|
||||
FAIL_BADID,
|
||||
/**
|
||||
* The server administrator has improperly configured their API key in the configuration
|
||||
*/
|
||||
FAIL_APIKEY,
|
||||
/**
|
||||
* The updater found an update, but because of the UpdateType being set to NO_DOWNLOAD, it wasn't downloaded.
|
||||
*/
|
||||
UPDATE_AVAILABLE
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the dev to specify the type of update that will be run.
|
||||
*/
|
||||
public enum UpdateType {
|
||||
/**
|
||||
* Run a version check, and then if the file is out of date, download the newest version.
|
||||
*/
|
||||
DEFAULT,
|
||||
/**
|
||||
* Don't run a version check, just find the latest update and download it.
|
||||
*/
|
||||
NO_VERSION_CHECK,
|
||||
/**
|
||||
* Get information about the version and the download size, but don't actually download anything.
|
||||
*/
|
||||
NO_DOWNLOAD
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the updater
|
||||
*
|
||||
* @param plugin The plugin that is checking for an update.
|
||||
* @param id The dev.bukkit.org id of the project
|
||||
* @param file The file that the plugin is running from, get this by doing this.getFile() from within your main class.
|
||||
* @param type Specify the type of update this will be. See {@link UpdateType}
|
||||
* @param announce True if the program should announce the progress of new updates in console
|
||||
*/
|
||||
public Updater(Plugin plugin, int id, File file, UpdateType type, boolean announce) {
|
||||
this.plugin = plugin;
|
||||
this.type = type;
|
||||
this.announce = announce;
|
||||
this.file = file;
|
||||
this.id = id;
|
||||
this.updateFolder = plugin.getServer().getUpdateFolder();
|
||||
|
||||
final File pluginFile = plugin.getDataFolder().getParentFile();
|
||||
final File updaterFile = new File(pluginFile, "Updater");
|
||||
final File updaterConfigFile = new File(updaterFile, "config.yml");
|
||||
|
||||
if (!updaterFile.exists()) {
|
||||
updaterFile.mkdir();
|
||||
}
|
||||
if (!updaterConfigFile.exists()) {
|
||||
try {
|
||||
updaterConfigFile.createNewFile();
|
||||
} catch (final IOException e) {
|
||||
plugin.getLogger().severe("The updater could not create a configuration in " + updaterFile.getAbsolutePath());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
this.config = YamlConfiguration.loadConfiguration(updaterConfigFile);
|
||||
|
||||
this.config.options().header("This configuration file affects all plugins using the Updater system (version 2+ - http://forums.bukkit.org/threads/96681/ )" + '\n'
|
||||
+ "If you wish to use your API key, read http://wiki.bukkit.org/ServerMods_API and place it below." + '\n'
|
||||
+ "Some updating systems will not adhere to the disabled value, but these may be turned off in their plugin's configuration.");
|
||||
this.config.addDefault("api-key", "PUT_API_KEY_HERE");
|
||||
this.config.addDefault("disable", false);
|
||||
|
||||
if (this.config.get("api-key", null) == null) {
|
||||
this.config.options().copyDefaults(true);
|
||||
try {
|
||||
this.config.save(updaterConfigFile);
|
||||
} catch (final IOException e) {
|
||||
plugin.getLogger().severe("The updater could not save the configuration in " + updaterFile.getAbsolutePath());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.config.getBoolean("disable")) {
|
||||
this.result = UpdateResult.DISABLED;
|
||||
return;
|
||||
}
|
||||
|
||||
String key = this.config.getString("api-key");
|
||||
if (key.equalsIgnoreCase("PUT_API_KEY_HERE") || key.equals("")) {
|
||||
key = null;
|
||||
}
|
||||
|
||||
this.apiKey = key;
|
||||
|
||||
try {
|
||||
this.url = new URL(Updater.HOST + Updater.QUERY + id);
|
||||
} catch (final MalformedURLException e) {
|
||||
plugin.getLogger().severe("The project ID provided for updating, " + id + " is invalid.");
|
||||
this.result = UpdateResult.FAIL_BADID;
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
this.thread = new Thread(new UpdateRunnable());
|
||||
this.thread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result of the update process.
|
||||
*/
|
||||
public Updater.UpdateResult getResult() {
|
||||
this.waitForThread();
|
||||
return this.result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest version's release type (release, beta, or alpha).
|
||||
*/
|
||||
public String getLatestType() {
|
||||
this.waitForThread();
|
||||
return this.versionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest version's game version.
|
||||
*/
|
||||
public String getLatestGameVersion() {
|
||||
this.waitForThread();
|
||||
return this.versionGameVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest version's name.
|
||||
*/
|
||||
public String getLatestName() {
|
||||
this.waitForThread();
|
||||
return this.versionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest version's file link.
|
||||
*/
|
||||
public String getLatestFileLink() {
|
||||
this.waitForThread();
|
||||
return this.versionLink;
|
||||
}
|
||||
|
||||
/**
|
||||
* As the result of Updater output depends on the thread's completion, it is necessary to wait for the thread to finish
|
||||
* before allowing anyone to check the result.
|
||||
*/
|
||||
private void waitForThread() {
|
||||
if ((this.thread != null) && this.thread.isAlive()) {
|
||||
try {
|
||||
this.thread.join();
|
||||
} catch (final InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an update from dev.bukkit.org into the server's update folder.
|
||||
*/
|
||||
private void saveFile(File folder, String file, String u) {
|
||||
if (!folder.exists()) {
|
||||
folder.mkdir();
|
||||
}
|
||||
BufferedInputStream in = null;
|
||||
FileOutputStream fout = null;
|
||||
try {
|
||||
// Download the file
|
||||
final URL url = new URL(u);
|
||||
final int fileLength = url.openConnection().getContentLength();
|
||||
in = new BufferedInputStream(url.openStream());
|
||||
fout = new FileOutputStream(folder.getAbsolutePath() + "/" + file);
|
||||
|
||||
final byte[] data = new byte[Updater.BYTE_SIZE];
|
||||
int count;
|
||||
if (this.announce) {
|
||||
this.plugin.getLogger().info("About to download a new update: " + this.versionName);
|
||||
}
|
||||
long downloaded = 0;
|
||||
while ((count = in.read(data, 0, Updater.BYTE_SIZE)) != -1) {
|
||||
downloaded += count;
|
||||
fout.write(data, 0, count);
|
||||
final int percent = (int) ((downloaded * 100) / fileLength);
|
||||
if (this.announce && ((percent % 10) == 0)) {
|
||||
this.plugin.getLogger().info("Downloading update: " + percent + "% of " + fileLength + " bytes.");
|
||||
}
|
||||
}
|
||||
//Just a quick check to make sure we didn't leave any files from last time...
|
||||
for (final File xFile : new File(this.plugin.getDataFolder().getParent(), this.updateFolder).listFiles()) {
|
||||
if (xFile.getName().endsWith(".zip")) {
|
||||
xFile.delete();
|
||||
}
|
||||
}
|
||||
// Check to see if it's a zip file, if it is, unzip it.
|
||||
final File dFile = new File(folder.getAbsolutePath() + "/" + file);
|
||||
if (dFile.getName().endsWith(".zip")) {
|
||||
// Unzip
|
||||
this.unzip(dFile.getCanonicalPath());
|
||||
}
|
||||
if (this.announce) {
|
||||
this.plugin.getLogger().info("Finished updating.");
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
this.plugin.getLogger().warning("The auto-updater tried to download a new update, but was unsuccessful.");
|
||||
this.result = Updater.UpdateResult.FAIL_DOWNLOAD;
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (fout != null) {
|
||||
fout.close();
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of Zip-File-Extractor, modified by Gravity for use with Bukkit
|
||||
*/
|
||||
private void unzip(String file) {
|
||||
try {
|
||||
final File fSourceZip = new File(file);
|
||||
final String zipPath = file.substring(0, file.length() - 4);
|
||||
ZipFile zipFile = new ZipFile(fSourceZip);
|
||||
Enumeration<? extends ZipEntry> e = zipFile.entries();
|
||||
while (e.hasMoreElements()) {
|
||||
ZipEntry entry = e.nextElement();
|
||||
File destinationFilePath = new File(zipPath, entry.getName());
|
||||
destinationFilePath.getParentFile().mkdirs();
|
||||
if (entry.isDirectory()) {
|
||||
continue;
|
||||
} else {
|
||||
final BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
|
||||
int b;
|
||||
final byte buffer[] = new byte[Updater.BYTE_SIZE];
|
||||
final FileOutputStream fos = new FileOutputStream(destinationFilePath);
|
||||
final BufferedOutputStream bos = new BufferedOutputStream(fos, Updater.BYTE_SIZE);
|
||||
while ((b = bis.read(buffer, 0, Updater.BYTE_SIZE)) != -1) {
|
||||
bos.write(buffer, 0, b);
|
||||
}
|
||||
bos.flush();
|
||||
bos.close();
|
||||
bis.close();
|
||||
final String name = destinationFilePath.getName();
|
||||
if (name.endsWith(".jar") && this.pluginFile(name)) {
|
||||
destinationFilePath.renameTo(new File(this.plugin.getDataFolder().getParent(), this.updateFolder + "/" + name));
|
||||
}
|
||||
}
|
||||
entry = null;
|
||||
destinationFilePath = null;
|
||||
}
|
||||
e = null;
|
||||
zipFile.close();
|
||||
zipFile = null;
|
||||
|
||||
// Move any plugin data folders that were included to the right place, Bukkit won't do this for us.
|
||||
for (final File dFile : new File(zipPath).listFiles()) {
|
||||
if (dFile.isDirectory()) {
|
||||
if (this.pluginFile(dFile.getName())) {
|
||||
final File oFile = new File(this.plugin.getDataFolder().getParent(), dFile.getName()); // Get current dir
|
||||
final File[] contents = oFile.listFiles(); // List of existing files in the current dir
|
||||
for (final File cFile : dFile.listFiles()) // Loop through all the files in the new dir
|
||||
{
|
||||
boolean found = false;
|
||||
for (final File xFile : contents) // Loop through contents to see if it exists
|
||||
{
|
||||
if (xFile.getName().equals(cFile.getName())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Move the new file into the current dir
|
||||
cFile.renameTo(new File(oFile.getCanonicalFile() + "/" + cFile.getName()));
|
||||
} else {
|
||||
// This file already exists, so we don't need it anymore.
|
||||
cFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dFile.delete();
|
||||
}
|
||||
new File(zipPath).delete();
|
||||
fSourceZip.delete();
|
||||
} catch (final IOException ex) {
|
||||
this.plugin.getLogger().warning("The auto-updater tried to unzip a new update file, but was unsuccessful.");
|
||||
this.result = Updater.UpdateResult.FAIL_DOWNLOAD;
|
||||
ex.printStackTrace();
|
||||
}
|
||||
new File(file).delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the name of a jar is one of the plugins currently installed, used for extracting the correct files out of a zip.
|
||||
*/
|
||||
private boolean pluginFile(String name) {
|
||||
for (final File file : new File("plugins").listFiles()) {
|
||||
if (file.getName().equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the program should continue by evaluation whether the plugin is already updated, or shouldn't be updated
|
||||
*/
|
||||
private boolean versionCheck(String title) {
|
||||
if (this.type != UpdateType.NO_VERSION_CHECK) {
|
||||
final String version = this.plugin.getDescription().getVersion();
|
||||
if (title.split(" v").length == 2) {
|
||||
final String remoteVersion = title.split(" v")[1].split(" ")[0]; // Get the newest file's version number
|
||||
|
||||
if (this.hasTag(version) || version.equalsIgnoreCase(remoteVersion)) {
|
||||
// We already have the latest version, or this build is tagged for no-update
|
||||
this.result = Updater.UpdateResult.NO_UPDATE;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// The file's name did not contain the string 'vVersion'
|
||||
final String authorInfo = this.plugin.getDescription().getAuthors().size() == 0 ? "" : " (" + this.plugin.getDescription().getAuthors().get(0) + ")";
|
||||
this.plugin.getLogger().warning("The author of this plugin" + authorInfo + " has misconfigured their Auto Update system");
|
||||
this.plugin.getLogger().warning("File versions should follow the format 'PluginName vVERSION'");
|
||||
this.plugin.getLogger().warning("Please notify the author of this error.");
|
||||
this.result = Updater.UpdateResult.FAIL_NOVERSION;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate whether the version number is marked showing that it should not be updated by this program
|
||||
*/
|
||||
private boolean hasTag(String version) {
|
||||
for (final String string : Updater.NO_UPDATE_TAG) {
|
||||
if (version.contains(string)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean read() {
|
||||
try {
|
||||
final URLConnection conn = this.url.openConnection();
|
||||
conn.setConnectTimeout(5000);
|
||||
|
||||
if (this.apiKey != null) {
|
||||
conn.addRequestProperty("X-API-Key", this.apiKey);
|
||||
}
|
||||
conn.addRequestProperty("User-Agent", "Updater (by Gravity)");
|
||||
|
||||
conn.setDoOutput(true);
|
||||
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
final String response = reader.readLine();
|
||||
|
||||
final JSONArray array = (JSONArray) JSONValue.parse(response);
|
||||
|
||||
if (array.size() == 0) {
|
||||
this.plugin.getLogger().warning("The updater could not find any files for the project id " + this.id);
|
||||
this.result = UpdateResult.FAIL_BADID;
|
||||
return false;
|
||||
}
|
||||
|
||||
this.versionName = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.TITLE_VALUE);
|
||||
this.versionLink = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.LINK_VALUE);
|
||||
this.versionType = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.TYPE_VALUE);
|
||||
this.versionGameVersion = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.VERSION_VALUE);
|
||||
|
||||
return true;
|
||||
} catch (final IOException e) {
|
||||
if (e.getMessage().contains("HTTP response code: 403")) {
|
||||
this.plugin.getLogger().warning("dev.bukkit.org rejected the API key provided in plugins/Updater/config.yml");
|
||||
this.plugin.getLogger().warning("Please double-check your configuration to ensure it is correct.");
|
||||
this.result = UpdateResult.FAIL_APIKEY;
|
||||
} else {
|
||||
this.plugin.getLogger().warning("The updater could not contact dev.bukkit.org for updating.");
|
||||
this.plugin.getLogger().warning("If you have not recently modified your configuration and this is the first time you are seeing this message, the site may be experiencing temporary downtime.");
|
||||
this.result = UpdateResult.FAIL_DBO;
|
||||
}
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class UpdateRunnable implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (Updater.this.url != null) {
|
||||
// Obtain the results of the project's file feed
|
||||
if (Updater.this.read()) {
|
||||
if (Updater.this.versionCheck(Updater.this.versionName)) {
|
||||
if ((Updater.this.versionLink != null) && (Updater.this.type != UpdateType.NO_DOWNLOAD)) {
|
||||
String name = Updater.this.file.getName();
|
||||
// If it's a zip file, it shouldn't be downloaded as the plugin's name
|
||||
if (Updater.this.versionLink.endsWith(".zip")) {
|
||||
final String[] split = Updater.this.versionLink.split("/");
|
||||
name = split[split.length - 1];
|
||||
}
|
||||
Updater.this.saveFile(new File(Updater.this.plugin.getDataFolder().getParent(), Updater.this.updateFolder), name, Updater.this.versionLink);
|
||||
} else {
|
||||
Updater.this.result = UpdateResult.UPDATE_AVAILABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.garbagemule.MobArena.util;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.Messenger;
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import com.garbagemule.MobArena.util.Updater.UpdateResult;
|
||||
import com.garbagemule.MobArena.util.Updater.UpdateType;
|
||||
|
||||
public class VersionChecker
|
||||
{
|
||||
static Updater updater;
|
||||
|
||||
public static void checkForUpdates(final MobArena plugin, final Player player) {
|
||||
if (updater == null) {
|
||||
updater = new Updater(plugin, 31265, plugin.getPluginFile(), UpdateType.NO_DOWNLOAD, false);
|
||||
}
|
||||
|
||||
// Async for anti-lag
|
||||
final Updater cache = updater;
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
||||
public void run() {
|
||||
if (cache.getResult() == UpdateResult.UPDATE_AVAILABLE) {
|
||||
final String latest = getLatestVersionString();
|
||||
final String current = plugin.getDescription().getVersion();
|
||||
|
||||
if (latest == null || current == null) {
|
||||
String msg = "Update checker failed. Please check manually!";
|
||||
message(plugin, player, msg);
|
||||
}
|
||||
|
||||
else if (isUpdateAvailable(latest, current)) {
|
||||
String msg1 = "MobArena v" + latest + " is now available!";
|
||||
String msg2 = "Your version: v" + current;
|
||||
message(plugin, player, msg1, msg2);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String getLatestVersionString() {
|
||||
String latestName = updater.getLatestName();
|
||||
if (!latestName.matches("MobArena v.*")) {
|
||||
return null;
|
||||
}
|
||||
return latestName.substring("MobArena v".length());
|
||||
}
|
||||
|
||||
private static boolean isUpdateAvailable(String latestVersion, String currentVersion) {
|
||||
// Split into major.minor(.patch(.build))
|
||||
String[] latestParts = latestVersion.split("\\.");
|
||||
String[] currentParts = currentVersion.split("\\.");
|
||||
|
||||
// Figure out how many numbers to compare
|
||||
int parts = Math.max(latestParts.length, currentParts.length);
|
||||
|
||||
// Check each part
|
||||
for (int i = 0; i < parts; i++) {
|
||||
int latest = getPart(latestParts, i);
|
||||
int current = getPart(currentParts, i);
|
||||
|
||||
// Return early if current is more recent
|
||||
if (current > latest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// And also if latest is more recent
|
||||
if (latest > current) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we're completely up-to-date!
|
||||
return false;
|
||||
}
|
||||
|
||||
private static int getPart(String[] parts, int i) {
|
||||
// Out of bounds or not an int? Bail with 0.
|
||||
if (i >= parts.length || !parts[i].matches("[0-9]+")) {
|
||||
return 0;
|
||||
}
|
||||
return Integer.parseInt(parts[i]);
|
||||
}
|
||||
|
||||
private static void message(MobArena plugin, final Player player, final String... messages) {
|
||||
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
|
||||
public void run() {
|
||||
for (String message : messages) {
|
||||
if (player == null) {
|
||||
Messenger.info(message);
|
||||
} else if (player.isOnline()) {
|
||||
Messenger.tell(player, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, (player == null) ? 0 : 60); // Message player after login spam
|
||||
}
|
||||
|
||||
public static void shutdown() {
|
||||
updater = null;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user