Forráskód Böngészése

Refactoring

Refactored EVERYTHING
lennartVH01 9 éve
szülő
commit
d90c1b332f

+ 8 - 36
config.yml

@@ -1,44 +1,11 @@
 # Abba Caving Plugin by lennartVH01
 
 # Game duration in seconds
-GameDuration: 1800
-
-# Countdown in seconds
-CountdownTime: 5
-
-# Times in game to notify players of the time left in seconds
-# Example: a NotifyTime of 120 will let all players know when there are 2 minutes left
-NotifyTimes:
-- 900
-- 300
-- 60
+Duration: 1800
 
 # Max players per game, users with permission AbbaCaving.joinFull can still join
 PlayerCap: 10
 
-
-
-
-# Configures if the items should be redistributed according to the settings below or that the redistribution is done by the admin
-# true -> Plugin automatically gives each player their cut
-# false -> only displays player scores in scoreboard
-RedistributeItems: true
-
-# If this is true, then the players who aren't in the Top will divide the total amount of items among themselves, If this is false, then every player's weight is added to the total weight
-FixPlayerWeight: false
-
-
-# Ratio of spoils given per player: 
-#   All: Amount to be spread over all participants
-#   Pot: Amount to be added to general Pot
-#   Top: first n players receive these chunks of total wins
-# Part of the winnings that go to each player
-WinWeights:
-  All: 1
-  Top:
-  - 7
-  - 2
-
 #Example Game with 10 players
 # All: 1
 # Top: 
@@ -70,8 +37,13 @@ ItemValues:
 
 # Enables the contraband scanner
 ScanContraband: true
-# Prohibited items, automatically includes entries in BlockValues
+
+# Prohibited items, automatically includes entries in ItemValues
 Contraband:
 - type: GOLDEN_APPLE
   damage: 0
-- type: POTION
+- type: POTION
+
+# Enables debugging
+# ONLY USE IF YOU KNOW WHAT YOU ARE DOING OR HAVE BEEN ASKED TO DO SO BY A DEVELOPER
+Debug: false

+ 69 - 27
lang.yml

@@ -1,34 +1,76 @@
 msg:
-    gameJoin:"Joined game \"%s\""
-    gameLeave:"Left game \"%s\""
-    playerJoin:"§a%s joined the abba game"
-    playerLeave:"§a%s left the abba game"
+    playerJoin: "&a%s joined the abba game"
+    playerLeave: "&a%s left the abba game"
+    
+    gameCountdown: "&aReady your picks!"
+    gameStart: "&aGO!"
+    gamePause: "&aThe game has been paused!"
+    gameEnd: "&aThe game has ended!\nTotal Items Collected:"
     
 error:
-    noPermission:"§cYou don't have permission to use this command!"
-    mustBeInGame:"§cYou must be ingame to use this command!"
-    gameNotFound:"§cGame %s not found!"
-    noGames:"§cNo Games found!"
+    noGames: "&cNo Games found!"
+    noPermission: "&cYou don't have permission to use this command!"
+    noPendingOperation: "&cNo pending operation!"
+    mustBeInGame: "&cYou must be ingame to use this command!"
+    gameNotFound: "&cGame %s not found!"
+    playerNotFound: "&cPlayer %s not found!"
+    worldNotFound: "&cWorld %s not found!"
     
-    gameFull:"§cThis game is full!"
-    gameClosed:"§cThis game is closed!"
-    noChest:"§cThere aren't enough chests!"
-    notWhitelisted:"§cYou aren't whitelisted for this game!"
-    blacklisted:"§cYou are blacklisted for this game!"
+    gameFull: "&cThis game is full!"
+    gameClosed: "&cThis game is closed!"
+    notWhitelisted: "&cYou aren't whitelisted for this game!"
+    blacklisted: "&cYou are blacklisted for this game!"
+    contraband: "&cYou cannot join the game with the following items: "
+    breakClaimedChest: "&cYou cannot break an occupied chest!"
     
 help:
-    join:"§aabba join [game]§f: Joins the Abba Match"
-    leave:"§aabba leave§f: Leaves current Abba Game"
-    info:"§aabba info [game]§f: Displays info about an Abba Match"
-    list:"§aabba list§f: Lists all Abba Matches"
-    calc:"§aabba calc§f: Calculates the score of your current inventory"
+    join: "&aabba join [game]&f: Joins the Abba Match"
+    leave: "&aabba leave&f: Leaves current Abba Game"
+    info: "&aabba info [game]&f: Displays info about an Abba Match"
+    list: "&aabba list&f: Lists all Abba Matches"
+    calc: "&aabba calc&f: Calculates the score of your current inventory"
+    
+    create: "&aabba create [game]&f: Creates an Abba Game"
+    remove: "&aabba remove <game>&f: Removes an Abba Game"
+    open: "&aabba open [game]&f: Allows players to join an Abba Game"
+    close: "&aabba close [game]&f: Prevents players from joining an Abba Game"
+    start: "&aabba start [game]&f: Starts an Abba Game"
+    calcscores: "&aabba calcscores&f: Use to calculate the scores and determine a winner at the end of a Match"
+    reload: "&aabba config <game> <timer|addchest> ...&f: Configures an Abba Game"
+    config: "&aabba reload&f: Reloads the config"
+    
+chest:
+    create: "Successfully created Chest"
+    remove: "Successfully removed Chest"
+command:
+    join:
+        success: "Joined game %s"
+    leave:
+        success: "Left game %s"
+    create:
+        success: "Game %s created successfully!"
+    remove:
+        success: "Game %s removed successfully"
+        confirm: "Are you sure? Use /abba confirm to confirm"
     
-    create:"§aabba create [game]§f: Creates an Abba Game"
-    remove:"§aabba remove <game>§f: Removes an Abba Game"
-    open:"§aabba open [game]§f: Allows players to join an Abba Game"
-    close:"§aabba close [game]§f: Prevents players from joining an Abba Game"
-    start:"§aabba start [game]§f: Starts an Abba Game"
-    calcscores:"§aabba calcscores§f: Use to calculate the scores and determine a winner at the end of a Match"
-    reload:"§aabba config <game> <timer|addchest> ...§f: Configures an Abba Game"
-    config:"§aabba reload§f: Reloads the config"
-    
+    open:
+        success: "Opened game %s"
+    close:
+        success: "Closed game %s"
+    start:
+        error:
+            running: "&cGame %s already running!"
+            finished: "&cGame %s already finished!"
+            contraband: "&cSome players are still carrying contraband! (hover to see items)"
+    pause:
+        success: "Game %s paused"
+        error: "&cGame %s isn't running!"
+    config:
+        help: "&aabba config <game> <timer|playercap> ..."
+        command:
+            timer:
+                help: "&aabba config <game> timer <newTime>"
+                success: "Timer updated"
+            playercap:
+                help: "&aabba config <game> playercap <newPlayerCap>"
+                success: "PlayerCap updated"

+ 4 - 9
plugin.yml

@@ -7,15 +7,10 @@ commands:
   abba:
     aliases: [ab, abbacaving]
     description: Abba hub command
-    permission: AbbaCaving.player
-    permission-message: You don't have permission to use this command!
-  abbaadmin:
-    aliases: [aa, abbaa]
-    description: Abba Admin Command
-    permission: AbbaCaving.admin
+    permission: AbbaCaving.basic
     permission-message: You don't have permission to use this command!
 permissions:
-  AbbaCaving.player:
+  AbbaCaving.basic:
     description: Gives access to basic commands
     default: true
   AbbaCaving.admin:
@@ -24,8 +19,8 @@ permissions:
   AbbaCaving.joinFull:
     description: Allows to join full games
     default: op
-  AbbaCaving.registerChest:
-    description: Allows registering of chests to an Abba Game
+  AbbaCaving.joinClosed:
+    description: Allows to join closed games
     default: op
   AbbaCaving.allowContraband:
     description: Users with this permission will not be scanned for contraband

+ 0 - 308
src/me/lennartVH01/AbbaAdminCommand.java

@@ -1,308 +0,0 @@
-package me.lennartVH01;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Set;
-
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.World;
-import org.bukkit.block.Block;
-import org.bukkit.block.Chest;
-import org.bukkit.block.Sign;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.command.TabCompleter;
-import org.bukkit.entity.Player;
-
-public class AbbaAdminCommand implements CommandExecutor, TabCompleter{
-	public final String[] abbaSubCommands = new String[]{"calcscores", "close", "config", "create", "open", "reload", "remove", "start"};
-	
-	public Main plugin;
-	
-	public AbbaAdminCommand(Main plugin){
-		this.plugin = plugin;
-	}
-	
-	@Override
-	public boolean onCommand(CommandSender sender, Command cmd, String cmdLabel, String[] args){
-		if(args.length == 0){
-			return false;
-		}
-		switch(args[0].toLowerCase()){
-		case "create":
-			if(args.length <= 5 && !(sender instanceof Player)){
-				System.out.println("Must be ingame or specify world and coordinates");
-				return false;
-			}
-			String gameName;
-			Location gameSpawn = null;
-			
-			// set gameName
-			if(args.length >= 2){
-				gameName = args[1];
-			}else{
-				DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
-				gameName = "Abba" + dateFormat.format(new Date());
-				
-			}
-			
-			// set gameSpawn
-			if(args.length >= 5){
-				double spawnX, spawnY, spawnZ;
-				try{
-					spawnX = Double.parseDouble(args[2]);
-					spawnY = Double.parseDouble(args[3]);
-					spawnZ = Double.parseDouble(args[4]);
-				}catch(NumberFormatException e){
-					return false;
-				}
-				if(args.length >= 6){
-					World w = plugin.getServer().getWorld(args[5]);
-					if(w != null){
-						
-						gameSpawn = new Location(w, spawnX, spawnY, spawnZ);
-						
-					}else{
-						sender.sendMessage("§4Unknown world: \"" + args[5] + "\"");
-						return false;
-					}
-				}
-			}else{
-				if(sender instanceof Player){
-					gameSpawn = ((Player) sender).getLocation();
-				}else{
-					return false;
-				}
-			}
-			
-			
-			
-			while(AbbaTools.getAbbaGame(gameName) != null){
-				gameName += "_";
-			}
-			//create game
-			AbbaTools.create(gameName, gameSpawn);
-			sender.sendMessage("Successfully created game \"" + gameName + "\"");
-			return true;
-			
-			
-			
-		case "remove":
-			if(args.length >= 2){
-				if(AbbaTools.removeAbbaGame(args[1])){
-					sender.sendMessage("Successfully removed game \"" + args[1] + "\"");
-					return true;
-				}else{
-					sender.sendMessage(String.format(Messages.errorGameNotFound, args[1]));
-					return false;
-				}
-			}else{
-				sender.sendMessage("Usage: /abba remove <game>");
-				return false;
-			}
-			
-		case "open":
-			AbbaGame game;
-			if(args.length >= 2){
-				game = AbbaTools.getAbbaGame(args[1]);
-				if(game == null){
-					sender.sendMessage(String.format(Messages.errorGameNotFound, args[1]));
-					return false;
-				}
-			}else{
-				game = AbbaTools.getAbbaGame();
-				if(game == null){
-					sender.sendMessage("§cNo game found");
-					return false;
-				}
-			}
-			game.setOpen(true);
-			sender.sendMessage("Opened game \"" + args[1] + "\"");
-			return true;
-		case "close":
-			AbbaGame aGame;
-			if(args.length >= 2){
-				aGame = AbbaTools.getAbbaGame(args[1]);
-				if(aGame == null){
-					sender.sendMessage(String.format(Messages.errorGameNotFound, args[1]));
-					return false;
-				}
-			}else{
-				aGame = AbbaTools.getAbbaGame();
-				if(aGame == null){
-					sender.sendMessage("§cNo game found");
-					return false;
-				}
-			}
-			aGame.setOpen(false);
-			sender.sendMessage("Closed game \"" + args[1] + "\"");
-			return true;
-			
-		case "start":
-			AbbaGame abbaGame;
-			if(args.length >= 2){
-				abbaGame = AbbaTools.getAbbaGame(args[1]);
-				if(abbaGame == null){
-					sender.sendMessage(String.format(Messages.errorGameNotFound, args[1]));
-					return false;
-				}
-			}else{
-				abbaGame = AbbaTools.getAbbaGame();
-				if(abbaGame == null){
-					sender.sendMessage("§cNo games found");
-					return false;
-				}
-			}
-			switch(abbaGame.getState()){
-			case WAITING:
-				List<String> badPlayerNames = abbaGame.start();
-				if(badPlayerNames.size() != 0){
-					sender.sendMessage("§cCannot start game! The following players are carrying contraband:");
-					for(String name:badPlayerNames){
-						sender.sendMessage("§c - " + name);
-					}
-					return false;
-				}
-				return true;
-			case PAUSED:
-				sender.sendMessage("§cGame paused!");
-				return false;
-			case COUNTDOWN:  //countdown and running both do the same
-			case RUNNING:
-				sender.sendMessage("§cGame already running!");
-				return false;
-			case FINISHED:
-			case CONCLUDED:
-				sender.sendMessage("§cGame finished!");
-				return false;
-			}
-			return false;
-		case "calcscores":
-			AbbaGame abaGame;
-			if(args.length >= 2){
-				abaGame = AbbaTools.getAbbaGame(args[1]);
-			}else{
-				abaGame = AbbaTools.getAbbaGame();
-			}
-			if(abaGame.getState() == AbbaGame.GameState.FINISHED){
-				abaGame.calcScores();
-				return true;
-			}else{
-				sender.sendMessage("§cGame not finished yet!");
-				return false;
-			}
-			
-		case "reload":
-			sender.sendMessage("Reloading config...");
-			plugin.reloadConfig();
-			sender.sendMessage("Reload Complete.");
-			return true;
-			
-			
-			
-		case "config":
-			if(args.length >= 2){
-				if(args.length >= 3){
-					AbbaGame abGame = AbbaTools.getAbbaGame(args[1]);
-					if(abGame == null){
-						sender.sendMessage(Messages.errorGameNotFound);
-					}
-					switch(args[2].toLowerCase()){
-					case "timer":
-						
-						if(args.length >= 4){
-							int newTime;
-						
-							try{
-								newTime = Integer.parseInt(args[3]);
-							}catch(NumberFormatException e){
-								sender.sendMessage("§cPlease specify a number when you use this command");
-								return false;
-							}
-							if(newTime <= 0){
-								sender.sendMessage("§cPlease specify a stricktly positive number");
-								return false;
-							}
-							if(abGame.getState() == AbbaGame.GameState.RUNNING || abGame.getState() == AbbaGame.GameState.PAUSED){
-								abGame.setEndTime(System.currentTimeMillis() + newTime * 1000);
-							}else{
-								abGame.setDuration(newTime);
-							}
-							sender.sendMessage("Time has been updated!");
-							return true;
-							
-						}else{
-							sender.sendMessage("§cPlease specify new time");
-							return false;
-						}
-					case "addchest":
-						if(sender instanceof Player){
-							Block blockInFront = ((Player) sender).getTargetBlock((Set<Material>) null, 5);
-							if(BlockUtils.isSign(blockInFront)){
-								Block blockNextTo = BlockUtils.getAttachedBlock(blockInFront);
-								if(BlockUtils.isChest(blockNextTo)){
-									if(AbbaTools.getAbbaGame(args[1]).addChest((Chest) blockNextTo.getState(), (Sign) blockInFront.getState())){
-										sender.sendMessage("Chest created");
-										return true;
-									}else{
-										sender.sendMessage("§cChest already in a game!");
-										return false;
-									}
-								}
-								
-								
-								sender.sendMessage("§cPut a sign next to the chest!");
-								return false;
-							}else{
-								sender.sendMessage("§cYou must look at a chest to register it!");
-								return false;
-							}
-						}else{
-							sender.sendMessage("§cMust be ingame to register chests!");
-							return false;
-						}
-					default:
-						sender.sendMessage("§cChoose an option!");
-						return false;
-					}
-				}else{
-					sender.sendMessage("§cChoose an option!");
-					return false;
-				}
-			}else{
-				sender.sendMessage(Messages.helpConfig);
-				return false;
-			}
-			
-		}
-		return false;
-	}
-	
-	@Override
-	public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args){
-		List<String> cmds = new ArrayList<String>();
-		switch(args.length){
-		case 1:
-			for(String s:abbaSubCommands){
-				if(s.startsWith(args[0])){
-					cmds.add(s);
-				}
-			}
-			break;
-		case 2:
-			for(AbbaGame game:AbbaTools.getGames()){
-				if(game.getName().toLowerCase().startsWith(args[1].toLowerCase())){
-					cmds.add(game.getName());
-				}
-			}
-		}
-		return cmds;
-	}
-	
-	
-}

+ 0 - 168
src/me/lennartVH01/AbbaCommand.java

@@ -1,168 +0,0 @@
-package me.lennartVH01;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.bukkit.GameMode;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.command.TabCompleter;
-import org.bukkit.entity.Player;
-
-public class AbbaCommand implements CommandExecutor, TabCompleter{
-	public final String[] abbaSubCommands = new String[]{"calc", "info", "join", "leave", "list"};
-	
-	
-	@Override
-	public boolean onCommand(CommandSender sender, Command cmd, String cmdLabel, String[] args){
-		if(args.length == 0){
-			return false;
-		}
-		
-		switch(args[0].toLowerCase()){
-		case "join":
-			if(sender instanceof Player){
-				Player p = (Player) sender;
-				AbbaGame game;
-				
-				if(args.length >= 2){
-					game = AbbaTools.getAbbaGame(args[1]);
-				}else{
-					game = AbbaTools.getAbbaGame();
-				}
-				if(game == null){
-					sender.sendMessage("§cGame not found!");
-					return false;
-				}
-				AbbaGame oldGame = AbbaTools.getAbbaGame(p);
-				if(oldGame != null){
-					p.sendMessage("Left game \"" + oldGame.getName() + "\"");
-					
-				}
-				
-				AbbaGame.JoinResult result = AbbaTools.join(p, game);
-				switch(result){
-				case SUCCESS:
-					break;
-				case FAIL_CLOSED:
-					sender.sendMessage(Messages.errorGameClosed);
-					return false;
-				case FAIL_FULL:
-					sender.sendMessage(Messages.errorGameFull);
-					return false;
-				case FAIL_NOCHEST:
-					sender.sendMessage(Messages.errorNoChest);
-					return false;
-				case FAIL_WHITELIST:
-					sender.sendMessage(Messages.errorNotWhitelisted);
-					return false;
-				case FAIL_CONTRABAND:
-					return false;
-				}
-				p.sendMessage(String.format(Messages.gameJoinMessage, game.getName()));
-				game.messageAll(String.format(Messages.playerJoinMessage, p.getName()));
-				
-				p.teleport(game.getSpawn());
-				p.setGameMode(GameMode.SURVIVAL);
-				return true;
-			}else{
-				sender.sendMessage(Messages.errorMustBeInGame);
-				return false;
-			}
-			
-			
-			
-		case "leave":
-			if(sender instanceof Player){
-				Player p = (Player) sender;
-				AbbaGame game = AbbaTools.leave(p.getUniqueId());
-				if(game != null){
-					p.sendMessage(String.format(Messages.gameLeaveMessage, game.getName()));
-					game.messageAll(String.format(Messages.playerLeaveMessage, p.getName()));
-					return true;
-				}else{
-					p.sendMessage("§cYou aren't in a game right now!");
-					return false;
-				}
-			}else{
-				sender.sendMessage(Messages.errorMustBeInGame);
-				return false;
-			}
-			
-		case "list":
-			sender.sendMessage("Games:");
-			for(AbbaGame g:AbbaTools.getGames()){
-				if(g.isOpen()){
-					sender.sendMessage("- §a" + g.getName() + " (" + g.getPlayerCount() + "/" + g.getMaxPlayers() + ")");
-				}else{
-					sender.sendMessage("- §7§o" + g.getName() + " (" + g.getPlayerCount() + "/" + g.getMaxPlayers() + ")");
-				}
-			}
-			return true;
-		case "info":
-			AbbaGame game = null;
-			if(args.length >= 2){
-				game = AbbaTools.getAbbaGame(args[1]);
-				if(game == null){
-					sender.sendMessage(String.format(Messages.errorGameNotFound, args[1]));
-					return false;
-				}
-			}else{
-				if(sender instanceof Player){
-					game = AbbaTools.getAbbaGame((Player) sender);
-				}
-				if(game == null){
-					game = AbbaTools.getAbbaGame();
-				}
-				if(game == null){
-					sender.sendMessage(Messages.errorNoGames);
-					return false;
-				}
-			}
-			sender.sendMessage("Game \"" + game.getName() + "\" " + (game.isOpen() ? "§aOpen":"§cClosed"));
-			return true;
-		case "calc":
-			Player calcPlayer;
-			
-			if(sender instanceof Player){
-				calcPlayer = (Player) sender;
-			}else{
-				sender.sendMessage(Messages.helpCalc);
-				return false;
-			}
-			
-			CalculatedScore score = AbbaTools.calcScore(calcPlayer.getInventory());
-			for(int i = 0; i < score.size(); i++){
-				if(score.getItemCount(i) != 0)
-					sender.sendMessage(score.getItemCount(i) + "x" + score.getItemStack(i).getType().toString() + ": " + score.getItemPoints(i));
-			}
-			sender.sendMessage("§aTotal Score: " + score.total);
-			return true;
-		}
-		return false;
-	}
-	
-	@Override
-	public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args){
-		List<String> cmds = new ArrayList<String>();
-		switch(args.length){
-		case 1:
-			for(String s:abbaSubCommands){
-				if(s.startsWith(args[0])){
-					cmds.add(s);
-				}
-			}
-			break;
-		case 2:
-			for(AbbaGame game:AbbaTools.getGames()){
-				if(game.getName().toLowerCase().startsWith(args[1].toLowerCase())){
-					cmds.add(game.getName());
-				}
-			}
-		}
-		return cmds;
-	}
-	
-	
-}

+ 0 - 617
src/me/lennartVH01/AbbaGame.java

@@ -1,617 +0,0 @@
-package me.lennartVH01;
-
-
-
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.UUID;
-
-import org.bukkit.Bukkit;
-import org.bukkit.Location;
-import org.bukkit.block.Block;
-import org.bukkit.block.Chest;
-import org.bukkit.block.Sign;
-import org.bukkit.configuration.serialization.ConfigurationSerializable;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.scoreboard.DisplaySlot;
-import org.bukkit.scoreboard.Objective;
-import org.bukkit.scoreboard.Score;
-import org.bukkit.scoreboard.Scoreboard;
-
-
-
-public class AbbaGame implements ConfigurationSerializable{
-	private static Comparator<Tuple2<UUID, CalculatedScore>> scoreComparer = new Comparator<Tuple2<UUID, CalculatedScore>>() {
-
-		@Override
-		public int compare(Tuple2<UUID, CalculatedScore> arg0, Tuple2<UUID, CalculatedScore> arg1) {
-			return arg1.getArg2().getTotal() - arg0.getArg2().getTotal();
-		}
-		
-	};
-	
-	
-	private static Main plugin;
-	public int taskId;
-	public boolean open = false;
-	public GameState state = GameState.WAITING;
-	public String name;
-	public Location spawn;
-	public long endTime;
-	public int duration;
-	public int playerCap;
-	public List<UUID> players;
-	public List<Tuple2<UUID, CalculatedScore>> endStats = new ArrayList<Tuple2<UUID, CalculatedScore>>();
-	
-	AbbaChestPlayerList chestList;
-	
-	
-	public Map<UUID, List<ItemStack>> leftovers = new HashMap<UUID, List<ItemStack>>();
-	public List<ItemStack> collectedItems = new ArrayList<ItemStack>();
-	
-	private Scoreboard scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
-	private Objective abbaObjective = scoreboard.registerNewObjective("AbbaStats", "dummy");
-	private Score timer = abbaObjective.getScore("Time Remaining");
-	
-	public static void initialize(Main plugin){
-		AbbaGame.plugin = plugin;
-	}
-	public AbbaGame(String name, Location spawn, int duration, int playerCap){
-		this.name = name;
-		this.spawn = spawn;
-		this.duration = duration;
-		this.playerCap = playerCap;
-		if(playerCap == -1){
-			players = new ArrayList<UUID>();
-		}else{
-			players = new ArrayList<UUID>(playerCap);
-		}
-		abbaObjective.setDisplaySlot(DisplaySlot.SIDEBAR);
-		
-		chestList = new AbbaChestPlayerList(playerCap);
-		
-		for(ValueItemPair pair:AbbaTools.itemPairs){
-			ItemStack stack = pair.getItemStack().clone();
-			stack.setAmount(0);
-			collectedItems.add(stack);
-		}
-	}
-	
-	
-	public void destroy(){
-		for(AbbaChest chestSignPair:chestList.getChests()){
-			Sign s = chestSignPair.getSign();
-			s.setLine(0, "");
-			//s.setLine(1, "");
-			//s.setLine(2, "");
-			s.update();
-		}
-		for(int i = players.size() - 1; i >= 0; i--){	//loop array backwards for speed
-			removePlayer(players.get(i));
-			//probably tp people to spawn or something
-			
-		}
-		stopClock();
-	}
-	
-	public List<String> start() {
-		
-		List<String> contrabandHolders = new ArrayList<String>();
-		for(UUID id:players){
-			Player p = plugin.getServer().getPlayer(id);
-			if(AbbaTools.hasContraband(p.getInventory())){
-				contrabandHolders.add(p.getName());
-			}
-		}
-		if(contrabandHolders.size() != 0){
-			return contrabandHolders;
-		}
-		// TODO Add stuff like tp people to cave if neccecary
-		if(state == GameState.WAITING){
-			endTime = System.currentTimeMillis() + 5000;
-			state = GameState.COUNTDOWN;
-			for(UUID id:players){
-				Player p = plugin.getServer().getPlayer(id);
-				p.sendMessage("§cGame starting!");
-			}
-		}else if(state == GameState.PAUSED){
-			endTime = System.currentTimeMillis() + 1000 * duration;
-			state = GameState.RUNNING;
-			for(UUID id:players){
-				plugin.getServer().getPlayer(id).sendMessage("§cGame continuing!");
-			}
-			startClock(0);
-		}
-		
-		
-		
-		startClock(20);
-		
-		return contrabandHolders; //should be empty
-	}
-	public void pause(){
-		//TODO Implement pausing
-		stopClock();
-		state = GameState.PAUSED;
-		duration = (int) ((endTime - System.currentTimeMillis())/1000);
-	}
-	
-	
-	private void startClock(long delay){
-		taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
-			
-			@Override
-			public void run() {
-				switch(state){
-				case COUNTDOWN:
-					if((endTime - System.currentTimeMillis())/1000 <= 0){
-						state = GameState.RUNNING;
-						endTime = System.currentTimeMillis() + duration * 1000;
-						timer.setScore(duration);
-						
-						for(UUID id:players){
-							Player p = plugin.getServer().getPlayer(id);
-							p.sendMessage("§cGOGOGO!");
-							p.setScoreboard(scoreboard);
-						}
-						//do stuff when countdown is finished here
-						
-					}else{
-						String message = "§c" + (endTime - System.currentTimeMillis())/1000;
-						for(UUID id:players){
-							plugin.getServer().getPlayer(id).sendMessage(message);
-						}
-					}
-					
-					
-					
-					break;
-				case RUNNING:
-					int timeRemaining = (int) (endTime - System.currentTimeMillis())/1000;
-					if(timeRemaining > 0){
-						timer.setScore(timeRemaining);
-					}else{
-						//end game
-						stopClock();
-						state = GameState.FINISHED;
-						scoreboard.resetScores("Time Remaining");
-						
-						for(UUID id:players){
-							Player p = plugin.getServer().getPlayer(id);
-							p.sendMessage("Game ended!");
-							p.teleport(spawn);
-							
-							
-							
-						}
-						
-					}
-					
-					break;
-				default:
-					break;
-				
-				}
-				
-			}
-		}, delay, 20);
-	}
-	private void stopClock(){
-		Bukkit.getScheduler().cancelTask(taskId);
-	}
-	
-	public void calcScores() {
-		for(AbbaChest abbaChest:chestList.getOccupiedChests()){
-			UUID id = abbaChest.getOwnerId();
-			
-			Chest chest = abbaChest.getChest();
-			Sign sign = abbaChest.getSign();
-			
-			Player p = plugin.getServer().getPlayer(id);
-			
-			Score score = abbaObjective.getScore(p.getName());
-			CalculatedScore stat = AbbaTools.calcScore(chest.getInventory());
-			score.setScore(stat.getTotal());
-			sign.setLine(2, "" + stat.getTotal());
-			endStats.add(new Tuple2<UUID, CalculatedScore>(p.getUniqueId(), stat));
-			
-			ItemStack[] stacks = chest.getInventory().getStorageContents();
-			
-			for(ItemStack item:stacks){
-				for(ItemStack total:collectedItems){
-					if(total.isSimilar(item)){
-						total.setAmount(total.getAmount() + item.getAmount());
-						chest.getInventory().remove(item);
-						continue;
-					}
-				}
-			}
-		}
-		endStats.sort(scoreComparer);
-		
-		if(!plugin.getConfig().getBoolean("RedistributeItems")){
-			return;
-		}
-		// If configured to do so, the plugin will spread all the goodies around
-		
-		List<Integer> LeaderBoardWeights = plugin.getConfig().getIntegerList("WinWeights.Top");
-		int AllPlayerWeight = plugin.getConfig().getInt("WinWeights.All");
-		int totalWeight = 0;
-		for(int i = 0; i < Math.min(LeaderBoardWeights.size(), players.size()); i++){
-			totalWeight += LeaderBoardWeights.get(i);
-		}
-		if(players.size() > LeaderBoardWeights.size()){
-			totalWeight += (players.size() - LeaderBoardWeights.size()) * AllPlayerWeight;
-		}
-		
-		for(int i = 0; i < Math.min(LeaderBoardWeights.size(), players.size()); i++){
-			Inventory chestInv = chestList.get(endStats.get(i).arg1).getChest().getInventory();
-			
-			List<ItemStack> leftoverList = new ArrayList<ItemStack>();
-			leftovers.put(endStats.get(i).arg1, leftoverList);
-			for(ItemStack stack: collectedItems){
-				ItemStack newStack = stack.clone();
-				newStack.setAmount((int) Math.ceil(stack.getAmount() * LeaderBoardWeights.get(i) / totalWeight));
-				stack.setAmount(stack.getAmount() - newStack.getAmount());
-				
-				if(newStack.getAmount() != 0){
-					leftoverList.addAll(chestInv.addItem(newStack).values());
-				}
-				
-				
-				
-			}
-			totalWeight -= LeaderBoardWeights.get(i);
-			
-		}
-		int playerChestSize = chestList.getOccupiedChests().size();
-		for(int i = LeaderBoardWeights.size(); i < playerChestSize; i++){
-			Inventory chestInv = chestList.get(endStats.get(i).arg1).getChest().getInventory();
-			List<ItemStack> leftoverList = new ArrayList<ItemStack>();
-			leftovers.put(endStats.get(i).arg1, leftoverList);
-			for(ItemStack stack: collectedItems){
-				int newAmount = (int) (stack.getAmount() / (playerChestSize - LeaderBoardWeights.size()));
-				int left = stack.getAmount() % (playerChestSize - LeaderBoardWeights.size());
-				if(i - LeaderBoardWeights.size() < left){
-					newAmount++;
-				}
-				ItemStack newStack = stack.clone();
-				newStack.setAmount(newAmount);
-				
-				leftoverList.addAll(chestInv.addItem(newStack).values());
-			}
-		}
-	}
-	
-	
-	public boolean addChest(Chest chest, Sign sign){
-		if(chestList.contains(chest)){
-			return false;
-		}
-		chestList.addEmptyChest(new AbbaChest(chest, sign));
-		sign.setLine(0, "§9[" + name + "]");
-		sign.update();
-		
-		return true;
-	}
-	
-	
-	public void setOpen(boolean open){
-		this.open = open;
-	}
-	public boolean isOpen(){
-		return open;
-	}
-	public boolean hasRoom(){
-		return (playerCap == -1 || players.size() < playerCap);
-	}
-	public int getPlayerCount(){
-		return players.size();
-	}
-	public int getMaxPlayers(){
-		if(playerCap == -1 || chestList.size() < playerCap){
-			return chestList.size();
-		}else{
-			return playerCap;
-		}
-	}
-	public String getName(){
-		return name;
-	}
-	public Location getSpawn(){
-		return spawn;
-	}
-	
-	
-	
-	
-	
-	public JoinResult addPlayer(Player p){
-		if(!Permission.hasPermission(p, Permission.JOIN_FULL) && players.size() >= playerCap){
-			return JoinResult.FAIL_FULL;
-		}
-		if(players.size() >= chestList.size()){
-			return JoinResult.FAIL_NOCHEST;
-		}
-		if(!open && !Permission.hasPermission(p, Permission.JOIN_CLOSED)){
-			return JoinResult.FAIL_CLOSED;
-		}
-		//TODO Add stuff here for whitelist aswell
-		
-		List<ItemStack> contraband = AbbaTools.getContraband(p.getInventory());
-		if(contraband.size() >= 1){
-			p.sendMessage("You cannot join with any of the following items:");
-			for(ItemStack stack:contraband){
-				p.sendMessage(" - " + stack.getType().toString().toLowerCase());
-			}
-			return JoinResult.FAIL_CONTRABAND;
-		}
-		AbbaChest claimedChest = chestList.claimChest(p.getUniqueId());
-		players.add(p.getUniqueId());
-		
-		
-		claimedChest.getSign().setLine(1, p.getName());
-		claimedChest.getSign().update();
-		
-		
-		return JoinResult.SUCCESS;
-	}
-	public void removePlayer(UUID id) {
-		players.remove(id);
-		plugin.getServer().getPlayer(id).setScoreboard(plugin.getServer().getScoreboardManager().getMainScoreboard());
-		AbbaChest aChest = chestList.freeChest(id);
-		
-		aChest.getSign().setLine(1, "");
-		aChest.getSign().update();
-	}
-	public void messageAll(String msg){
-		for(UUID id:players){
-			plugin.getServer().getPlayer(id).sendMessage(msg);
-		}
-	}
-
-	public GameState getState(){
-		return state;
-	}
-
-	public long getEndTime() {
-		return endTime;
-	}
-	
-	
-	
-	public void setDuration(int duration) {
-		this.duration = duration;
-		
-	}
-
-	public void setEndTime(long newEndTime) {
-		endTime = newEndTime;
-		
-	}
-	
-	// ==SERIALIZATION==
-	
-	//TODO Make dis serializable
-	
-	@Override
-	public Map<String, Object> serialize() {
-		Map<String, Object> abbaMap = new HashMap<String, Object>();
-		abbaMap.put("Name", name);
-		abbaMap.put("Spawn", spawn);
-		
-		abbaMap.put("Open", open);
-		switch(state){
-		case WAITING:
-		case COUNTDOWN:
-			abbaMap.put("State", "WAITING");
-			break;
-		case RUNNING:
-		case PAUSED:
-			abbaMap.put("State", "PAUSED");
-			break;
-		case FINISHED:
-			abbaMap.put("State", "FINISHED");
-			break;
-		case CONCLUDED:
-			abbaMap.put("State", "CONCLUDED");
-			break;
-		}
-		
-		abbaMap.put("Duration", duration);
-		abbaMap.put("PlayerCap", playerCap);
-		
-		List<String> playerChestList = new ArrayList<String>();
-		for(AbbaChest aChest:chestList.getOccupiedChests()){
-			playerChestList.add(String.format("%d;%d;%d;%s", aChest.getSign().getX(), aChest.getSign().getY(), aChest.getSign().getZ(), aChest.getOwnerId().toString()));
-		}
-		for(AbbaChest aChest:chestList.getFreeChests()){
-			playerChestList.add(String.format("%d;%d;%d", aChest.getSign().getX(), aChest.getSign().getY(), aChest.getSign().getZ()));
-		}
-		abbaMap.put("Chests", playerChestList);
-		//TODO SERIALIZE PLAYERS
-		
-		
-		
-		return abbaMap;
-	}
-	
-	@SuppressWarnings("unchecked")
-	public static AbbaGame deserialize(Map<String, Object> inputMap){
-		AbbaGame game = new AbbaGame((String) inputMap.get("Name"), (Location) inputMap.get("Spawn"), (int) inputMap.get("Duration"), (int) inputMap.get("PlayerCap"));
-		
-		game.setOpen((boolean) inputMap.get("Open"));
-		
-		for(String input:(List<String>) inputMap.get("Chests")){
-			String[] args = input.split(";");
-			Block sign = game.spawn.getWorld().getBlockAt(Integer.parseInt(args[0]), Integer.parseInt(args[1]), Integer.parseInt(args[2]));
-			
-			AbbaChest aChest = game.new AbbaChest((Chest) BlockUtils.getAttachedBlock(sign), (Sign) sign);
-			if(args.length >= 4){
-				UUID id = UUID.fromString(args[3]);
-				game.chestList.addEmptyChest(aChest);
-				game.chestList.claimChest(id);
-				game.players.add(id);
-				
-			}
-		}
-		
-		switch((String) inputMap.get("State")){
-		
-		case "PAUSED":
-			game.state = GameState.PAUSED;
-			break;
-		case "FINISHED":
-			game.state = GameState.FINISHED;
-			break;
-		case "CONCLUDED":
-			game.state = GameState.CONCLUDED;
-			break;
-		default:	// WAITING also refers back to this state
-			game.state = GameState.WAITING;
-		}
-		
-		
-		
-		
-		return game;
-	}
-	public void setPlayerCap(int playerCap) {
-		this.playerCap = playerCap;
-	}
-	public int getPlayerCap(){
-		return playerCap;
-	}
-	public List<UUID> getPlayerIDs() {
-		return players;
-	}
-	
-	public enum JoinResult{
-		SUCCESS,
-		FAIL_FULL,
-		FAIL_CLOSED,
-		FAIL_WHITELIST,
-		FAIL_NOCHEST,
-		FAIL_CONTRABAND
-		
-	}
-	
-	public enum GameState {
-		WAITING, 
-		COUNTDOWN,
-		RUNNING, 
-		PAUSED, 
-		FINISHED,
-		CONCLUDED
-		
-	}
-	
-	
-	
-	public class AbbaChest{
-		private Chest chest;
-		private Sign sign;
-		private UUID ownerId;
-		public AbbaChest(Chest chest, Sign sign){
-			this.chest = chest;
-			this.sign = sign;
-		}
-		public Chest getChest(){return chest;}
-		public void setChest(Chest chest){this.chest = chest;}
-		public Sign getSign(){return sign;}
-		public void setSign(Sign sign){this.sign = sign;}
-		public UUID getOwnerId(){return ownerId;}
-		public void setOwnerId(UUID ownerId){this.ownerId = ownerId;}
-	}
-	
-	
-	public class AbbaChestPlayerList{
-		private int playerLength = 0;
-		private List<AbbaChest> chests;
-		//creates An ArrayList with two "sublists, each building toward eachother"
-		public AbbaChestPlayerList(int initialSize){
-			chests = new ArrayList<AbbaChest>(initialSize);
-		}
-		
-		
-		public int size() {
-			return chests.size();
-		}
-
-
-		public AbbaChest claimChest(UUID id){
-			AbbaChest chest = chests.get(playerLength);
-			chest.setOwnerId(id);
-			playerLength++;
-			return chest;
-		}
-		public AbbaChest freeChest(UUID id){
-			for(int i = 0; i < playerLength; i++){
-				AbbaChest chest = chests.get(i);
-				if(chest.getOwnerId().equals(id)){
-					chest.setOwnerId(null);
-					playerLength--;
-					Collections.swap(chests, i, playerLength);
-					return chest;
-				}
-			}
-			return null;
-		}
-		public void remove(AbbaChest chest){
-			chests.remove(chest);
-		}
-		public void addEmptyChest(AbbaChest c){
-			chests.add(c);
-		}
-		public List<AbbaChest> getOccupiedChests(){
-			return chests.subList(0, playerLength);
-		}
-		public List<AbbaChest> getFreeChests(){
-			return chests.subList(playerLength, chests.size());
-		}
-		public List<AbbaChest> getChests(){
-			return chests;
-		}
-		public AbbaChest get(int i){
-			return chests.get(i);
-		}
-		public AbbaChest get(UUID id){
-			for(int i = 0; i < playerLength; i++){
-				if(chests.get(i).getOwnerId().equals(id)){
-					return chests.get(i);
-				}
-			}
-			return null;
-		}
-		public boolean contains(AbbaChest abbaChest){
-			for(AbbaChest aChest:chests){
-				if(aChest.equals(abbaChest)){
-					return true;
-				}
-			}
-			return false;
-		}
-		public boolean contains(Chest chest){
-			for(AbbaChest aChest:chests){
-				if(chest.equals(aChest.getChest())){
-					return true;
-				}
-			}
-			return false;
-		}
-		public boolean contains(Sign sign){
-			for(AbbaChest aChest:chests){
-				if(sign.equals(aChest.getSign())){
-					return true;
-				}
-			}
-			return false;
-		}
-	}
-}

+ 0 - 199
src/me/lennartVH01/AbbaTools.java

@@ -1,199 +0,0 @@
-package me.lennartVH01;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import me.lennartVH01.AbbaGame.JoinResult;
-
-import org.bukkit.Location;
-import org.bukkit.block.Chest;
-import org.bukkit.block.Sign;
-import org.bukkit.configuration.file.FileConfiguration;
-import org.bukkit.entity.Player;
-import org.bukkit.event.block.BlockBreakEvent;
-import org.bukkit.event.block.SignChangeEvent;
-import org.bukkit.event.inventory.InventoryOpenEvent;
-import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.ItemStack;
-
-
-
-
-public class AbbaTools{
-	public static Main plugin;
-	public static List<ValueItemPair> itemPairs;
-	public static List<ItemStack> contraband;
-	private static List<AbbaGame> games = new ArrayList<AbbaGame>();
-	
-	private static Map<UUID, AbbaGame> playerGameMap = new HashMap<UUID, AbbaGame>();
-	//private static Map<Location, AbbaGame> chestGameMap = new HashMap<Location, AbbaGame>();
-	
-	
-	
-	public static void initialize(Main plugin, List<ValueItemPair> valueItemPairs, List<ItemStack> contraband) {
-		AbbaTools.plugin = plugin;
-		itemPairs = valueItemPairs;
-		AbbaTools.contraband = contraband;
-	}
-	
-	
-	
-	public static void create(String name, Location spawn){
-		FileConfiguration config = plugin.getConfig();
-		AbbaGame game = new AbbaGame(name, spawn, config.getInt("GameDuration"), config.getInt("PlayerCap"));
-		games.add(game);
-	}
-	public static boolean removeAbbaGame(String name){
-		AbbaGame game = getAbbaGame(name);
-		return removeAbbaGame(game);
-	}
-		
-	public static boolean removeAbbaGame(AbbaGame game){
-		if(game == null){
-			return false;
-		}
-		
-		for(UUID id:game.getPlayerIDs()){
-			playerGameMap.remove(id);// remove people from game Map
-		}
-		game.destroy();				// remove people from internal game Map
-		games.remove(game);
-		return true;
-	}
-	public static AbbaGame getAbbaGame(String name){
-		for(AbbaGame game:games){
-			if(game.name.equalsIgnoreCase(name)){
-				return game;
-			}
-		}
-		
-		return null;
-	}
-	public static AbbaGame getAbbaGame(){
-		if(games.size() >= 1){
-			return games.get(0);
-		}else{
-			return null;
-		}
-	}
-	public static AbbaGame getAbbaGame(Player p){
-		return playerGameMap.get(p.getUniqueId());
-	}
-	
-	public static AbbaGame leave(UUID id){
-		AbbaGame game = playerGameMap.remove(plugin.getServer().getPlayer(id).getUniqueId());
-		if(game != null){
-			game.removePlayer(id);
-			return game;
-		}
-		return null;
-	}
-	public static AbbaGame.JoinResult join(Player p, AbbaGame game){
-		leave(p.getUniqueId());
-		
-		JoinResult result = game.addPlayer(p);
-		if(result == JoinResult.SUCCESS){
-			playerGameMap.put(p.getUniqueId(), game);
-		}
-		return result;
-		
-	}
-	public static boolean isInGame(Player p){
-		return playerGameMap.containsKey(p.getUniqueId());
-	}
-	
-	
-	public static List<ItemStack> getContraband(Inventory i){
-		List<ItemStack> totalContraband = new ArrayList<ItemStack>();
-		if(!plugin.getConfig().getBoolean("ScanContraband")){
-			return totalContraband;
-		}
-		for(ItemStack detectionStack:contraband){
-			for(ItemStack testStack:i.getStorageContents()){
-				if(detectionStack.isSimilar(testStack)){
-					totalContraband.add(detectionStack);
-					break;	//breaks out of inner loop to go to next detect stack to get 
-				}
-			}
-		}
-		return totalContraband;
-	}
-	public static boolean hasContraband(Inventory i){
-		if(!plugin.getConfig().getBoolean("ScanContraband")){
-			return false;
-		}
-		for(ItemStack detectionStack:contraband){
-			for(ItemStack testStack:i.getStorageContents()){
-				if(detectionStack.isSimilar(testStack)){
-					return true;
-				}
-			}
-		}
-		return false;
-	}
-	
-	
-	
-	public static CalculatedScore calcScore(Inventory inv){
-		CalculatedScore points = new CalculatedScore(itemPairs);
-		
-		//might not be the most efficient, should probably use a HashMap for the itemPairs array
-		for(int i = 0; i < itemPairs.size(); i++){
-			ValueItemPair itemPair = itemPairs.get(i);
-			ItemStack compStack = itemPair.getItemStack();
-			int pointValue = itemPair.getValue();
-			for(ItemStack invStack:inv.getStorageContents()){
-				if(compStack.isSimilar(invStack)){
-					points.add(i, invStack.getAmount(), pointValue);
-				}
-			}
-		}
-		
-		return points;
-	}
-	public static List<AbbaGame> getGames() {
-		return games;
-	}
-	public static void onChestOpen(InventoryOpenEvent e){
-		
-	}
-	public static void onSignBreak(BlockBreakEvent e){
-		
-	}
-	public static void onSignPlace(SignChangeEvent e){
-		if(e.getPlayer().hasPermission(Permission.REGISTER_CHEST.toString())){
-			if(e.getLine(0).equalsIgnoreCase("[abba]")){
-				AbbaGame game;
-				if(e.getLine(1).equals("")){
-					game = getAbbaGame();
-				}else{
-					game = getAbbaGame(e.getLine(1));
-				}
-				if(game != null){
-					if(game.addChest((Chest) BlockUtils.getAttachedBlock(e.getBlock()), (Sign) e.getBlock())){
-						e.setLine(0, "§9[Abba]");
-					}
-				}
-			}
-		}
-	}
-	
-	
-	public static void deserialize(List<AbbaGame> gameList){
-		
-		for(AbbaGame game:gameList){
-			if(game != null){
-				games.add(game);
-				for(UUID id:game.getPlayerIDs()){
-					playerGameMap.put(id, game);
-				}
-			}
-		}
-	}
-	
-	
-	
-}

+ 0 - 17
src/me/lennartVH01/BlockUtils.java

@@ -1,17 +0,0 @@
-package me.lennartVH01;
-
-import org.bukkit.Material;
-import org.bukkit.block.Block;
-import org.bukkit.block.Chest;
-
-public class BlockUtils {
-	public static boolean isChest(Block block){
-		return block.getState() instanceof Chest;
-	}
-	public static boolean isSign(Block block){
-		return block.getType() == Material.SIGN_POST || block.getType() == Material.WALL_SIGN;
-	}
-	public static Block getAttachedBlock(Block b){
-		return b.getRelative(((org.bukkit.material.Sign) b.getState().getData()).getAttachedFace());
-	}
-}

+ 0 - 48
src/me/lennartVH01/CalculatedScore.java

@@ -1,48 +0,0 @@
-package me.lennartVH01;
-
-import java.util.List;
-
-import org.bukkit.inventory.ItemStack;
-
-public class CalculatedScore {
-	public int total = 0;
-	public ItemStack[] items;
-	public int[] itemCount;
-	public int[] itemPoints;
-	
-	public CalculatedScore(List<ValueItemPair> itemPairs){
-		int size = itemPairs.size();
-		items = new ItemStack[size];
-		itemCount = new int[size];
-		itemPoints = new int[size];
-		for(int i = 0; i < itemPairs.size(); i++){
-			items[i] = itemPairs.get(i).getItemStack();
-		}
-	}
-
-
-	public void add(int i, int amount, int itemValue) {
-		itemPoints[i] += amount * itemValue;
-		itemCount[i] += amount;
-		total += amount * itemValue;
-	}
-
-
-	public int getTotal() {
-		return total;
-	}
-	public ItemStack getItemStack(int i){
-		return items[i];
-	}
-	public int getItemCount(int i){
-		return itemCount[i];
-	}
-	public int getItemPoints(int i){
-		return itemPoints[i];
-	}
-
-
-	public int size() {
-		return itemCount.length;
-	}
-}

+ 623 - 0
src/me/lennartVH01/CommandHandler.java

@@ -0,0 +1,623 @@
+package me.lennartVH01;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.text.DateFormat;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.text.SimpleDateFormat;
+import java.util.UUID;
+
+
+
+
+
+
+
+
+
+import me.lennartVH01.game.BasicAbbaGame;
+import me.lennartVH01.game.ContrabandScanner;
+import me.lennartVH01.game.GameManager;
+import me.lennartVH01.game.AbbaGame;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.TabCompleter;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.java.JavaPlugin;
+
+
+
+public class CommandHandler implements CommandExecutor, TabCompleter{
+	private JavaPlugin plugin;
+	private Map<String, CommandFunc> commands = new HashMap<String, CommandFunc>();
+	private Map<UUID, BoolRunnable> playerCooldowns = new HashMap<UUID, BoolRunnable>();
+	private static UUID serverUUID = UUID.randomUUID();
+	
+	public CommandHandler(JavaPlugin plugin){
+		this.plugin = plugin;
+		
+		commands.put("join", joinCmd);
+		commands.put("leave", leaveCmd);
+		commands.put("info", infoCmd);
+		commands.put("list", listCmd);
+		commands.put("confirm", confirmCmd);
+		
+		commands.put("create", createCmd);
+		commands.put("remove", removeCmd);
+		commands.put("open", openCmd);
+		commands.put("close", closeCmd);
+		commands.put("start", startCmd);
+		commands.put("pause", pauseCmd);
+		commands.put("reload", reloadCmd);
+		commands.put("config", configCmd);
+	}
+	
+	private CommandFunc joinCmd = new CommandFunc(){
+		@Override public boolean hasPermission(CommandSender sender){return Permission.BASIC.has(sender);}
+		@Override public boolean run(CommandSender sender, String[] args){
+			
+			if(sender instanceof Player){
+				Player p = (Player) sender;
+				AbbaGame game;
+				
+				if(args.length >= 2){
+					game = GameManager.getGame(args[1]);
+					if(game != null){
+						return GameManager.join(p, game);
+					}else{
+						sender.sendMessage(String.format(Messages.errorGameNotFound, args[1]));
+						return false;
+					}
+				}else{
+					game = GameManager.getGame();
+					if(game != null){
+						return GameManager.join(p, game);
+					}else{
+						sender.sendMessage(Messages.errorNoGames);
+						return false;
+					}
+				}
+			}else{
+				sender.sendMessage(Messages.errorMustBeInGame);
+				return false;
+			}
+		}
+		@Override public List<String> tabComplete(CommandSender sender, String[] args){
+			if(args.length == 2)
+				return GameManager.getGamesAbbreviated(args[1]);
+			else
+				return Collections.emptyList();
+		}
+	};
+	private CommandFunc leaveCmd = new CommandFunc(){
+		@Override public boolean hasPermission(CommandSender sender){return Permission.BASIC.has(sender);}
+		@Override public boolean run(CommandSender sender, String[] args){
+			
+			if(sender instanceof Player){
+				Player p = (Player) sender;
+				AbbaGame game = GameManager.leave(p);
+				if(game != null){
+					return true;
+				}else{
+					p.sendMessage(Messages.errorMustBeInGame);
+					return false;
+				}
+			}else{
+				sender.sendMessage(Messages.errorMustBeInGame);
+				return false;
+			}
+		}
+		@Override public List<String> tabComplete(CommandSender sender, String[] args){
+			return Collections.emptyList();
+		}
+	};
+	private CommandFunc infoCmd = new CommandFunc(){
+		@Override public boolean hasPermission(CommandSender sender){return Permission.BASIC.has(sender);}
+		@Override public boolean run(CommandSender sender, String[] args){
+			
+			AbbaGame game = getGame(args, sender);
+			if(game == null)
+				return false;
+			String message = (game.isOpen() ? "§a" : "§c") + "[" + game.getName() + "] (" + game.getPlayerCount() + "/" + game.getPlayerCap() + ")" + game.getState().toString() + "\nPlayers:";
+			for(Player p:game.getPlayers()){
+				message += "\n" + p.getName();
+			}
+			sender.sendMessage(message);
+			return true;
+		}
+		@Override public List<String> tabComplete(CommandSender sender, String[] args){
+			if(args.length == 2)
+				return GameManager.getGamesAbbreviated(args[1]);
+			else
+				return Collections.emptyList();
+		}
+	};
+	private CommandFunc listCmd = new CommandFunc(){
+		@Override public boolean hasPermission(CommandSender sender){return Permission.BASIC.has(sender);}
+		@Override public boolean run(CommandSender sender, String[] args){
+			sender.sendMessage("Games:");
+			for(AbbaGame g:GameManager.getGames()){
+				if(g.isOpen()){
+					sender.sendMessage("- §a" + g.getName() + " (" + g.getPlayerCount() + "/" + g.getPlayerCap() + ")");
+				}else{
+					sender.sendMessage("- §7§o" + g.getName() + " (" + g.getPlayerCount() + "/" + g.getPlayerCap() + ")");
+				}
+			}
+			return true;
+		}
+		@Override public List<String> tabComplete(CommandSender sender, String[] args){
+			return Collections.emptyList();
+			
+		}
+	};
+	
+	private CommandFunc confirmCmd = new CommandFunc(){
+		@Override public boolean hasPermission(CommandSender sender){return Permission.BASIC.has(sender);}
+		@Override public boolean run(CommandSender sender, String[] args){
+			BoolRunnable code;
+			if(sender instanceof Player){
+				code = playerCooldowns.get(((Player) sender).getUniqueId());
+			}else{
+				code = playerCooldowns.get(serverUUID);
+			}
+			
+			if(code != null){
+				return code.run();
+			}else{
+				sender.sendMessage(Messages.errorNoPendingOperation);
+				return false;
+			}
+		}
+		@Override public List<String> tabComplete(CommandSender sender, String[] args){
+			return Collections.emptyList();
+		}
+	};
+	
+	
+	private CommandFunc createCmd = new CommandFunc(){
+		@Override public boolean hasPermission(CommandSender sender){return Permission.ADMIN.has(sender);}
+		@Override public boolean run(CommandSender sender, String[] args){
+			if(args.length <= 5 && !(sender instanceof Player)){
+				System.out.println(Messages.errorMustBeInGame);
+				return false;
+			}
+			String gameName;
+			Location gameSpawn = null;
+			
+			// set gameName
+			if(args.length >= 2){
+				gameName = args[1];
+			}else{
+				DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+				gameName = "Abba" + dateFormat.format(new Date());
+				
+			}
+			
+			// set gameSpawn
+			if(args.length >= 5){
+				double spawnX, spawnY, spawnZ;
+				try{
+					spawnX = Double.parseDouble(args[2]);
+					spawnY = Double.parseDouble(args[3]);
+					spawnZ = Double.parseDouble(args[4]);
+				}catch(NumberFormatException e){
+					return false;
+				}
+				if(args.length >= 6){
+					World w = Bukkit.getWorld(args[5]);
+					if(w != null){
+						
+						gameSpawn = new Location(w, spawnX, spawnY, spawnZ);
+						
+					}else{
+						sender.sendMessage(String.format(Messages.errorWorldNotFound, args[5]));
+						return false;
+					}
+				}
+			}else{
+				if(sender instanceof Player){
+					gameSpawn = ((Player) sender).getLocation();
+				}else{
+					return false;
+				}
+			}
+			
+			
+			
+			while(GameManager.getGame(gameName) != null){
+				gameName += "_";
+			}
+			//create game
+			AbbaGame game = new BasicAbbaGame(plugin, gameName, gameSpawn, Config.defaultDuration, Config.defaultPlayerCap, new ContrabandScanner(Config.contraband), Config.itemValues);
+			GameManager.registerGame(game);
+			sender.sendMessage(String.format(Messages.commandCreateSuccess, gameName));
+			//sender.sendMessage(String.format(Messages.commandCreateSuccess, gameName));
+			return true;
+		}
+		@Override public List<String> tabComplete(CommandSender sender, String[] args){
+			List<String> suggestions = new ArrayList<String>();
+			switch(args.length){
+			case 3:
+				if(args[2].isEmpty())
+					suggestions.add("" + ((Player) sender).getLocation().getBlockX());
+				break;
+			case 4:
+				if(args[3].isEmpty())
+					suggestions.add("" + ((Player) sender).getLocation().getBlockY());
+				break;
+			case 5:
+				if(args[4].isEmpty())
+					suggestions.add("" + ((Player) sender).getLocation().getBlockZ());
+				break;
+			case 6:
+				for(World world:Bukkit.getWorlds())
+					if(world.getName().toLowerCase().startsWith(args[5].toLowerCase()))
+						suggestions.add(world.getName());
+				break;
+			}
+			return suggestions;
+		}
+	};
+	
+	private CommandFunc removeCmd = new CommandFunc(){
+		@Override public boolean hasPermission(CommandSender sender){return Permission.ADMIN.has(sender);}
+		@Override public boolean run(CommandSender sender, String[] args){
+			if(args.length >= 2){
+				AbbaGame game = GameManager.getGame(args[1]);
+				if(game != null){
+					BoolRunnable commandRemoveRunnable = () -> {
+						if(GameManager.removeGame(game)){
+							sender.sendMessage(String.format(Messages.commandRemoveSuccess, game.getName()));
+							return true;
+						}else{
+							sender.sendMessage(String.format(Messages.errorGameNotFound, game.getName()));
+							return false;
+						}
+					};
+					if(args.length >= 3 && args[2].toLowerCase().equals("force")){
+						return commandRemoveRunnable.run();
+					}
+					
+					if(sender instanceof Player){
+						registerCooldown(((Player) sender).getUniqueId(), commandRemoveRunnable, 200);
+					}else{
+						registerCooldown(serverUUID, commandRemoveRunnable, 200);
+					}
+					sender.sendMessage(Messages.commandRemoveConfirm);
+					return true;
+				}else{
+					sender.sendMessage(String.format(Messages.errorGameNotFound, args[1]));
+					return false;
+				}
+				
+			}else{
+				sender.sendMessage(Messages.helpRemove);
+				return false;
+			}
+		}
+		@Override public List<String> tabComplete(CommandSender sender, String[] args){
+			if(args.length == 2)
+				return GameManager.getGamesAbbreviated(args[1]);
+			else if(args.length == 3 && "force".startsWith(args[2].toLowerCase())){
+				List<String> suggestions = new ArrayList<String>(1);
+				suggestions.add("force");
+				return suggestions;
+			}
+			
+			return Collections.emptyList();
+		}
+	};
+	private CommandFunc openCmd = new CommandFunc(){
+		@Override public boolean hasPermission(CommandSender sender){return Permission.ADMIN.has(sender);}
+		@Override public boolean run(CommandSender sender, String[] args){
+			AbbaGame game = null;
+			if(args.length >= 2){
+				game = GameManager.getGame(args[1]);
+				if(game == null){
+					sender.sendMessage(String.format(Messages.errorGameNotFound, args[1]));
+					return false;
+				}
+			}else{
+				if(sender instanceof Player)
+					game = GameManager.getGame((Player) sender);
+				if(game == null)
+					game = GameManager.getGame();
+				if(game == null){
+					sender.sendMessage(Messages.errorNoGames);
+					return false;
+				}
+			}
+			game.setOpen(true);
+			sender.sendMessage(String.format(Messages.commandOpenSuccess, game.getName()));
+			return true;
+		}
+
+		@Override public List<String> tabComplete(CommandSender sender, String[] args){
+			if(args.length == 2)
+				return GameManager.getGamesAbbreviated(args[1]);
+			else
+				return Collections.emptyList();
+		}
+		
+	};
+	
+	private CommandFunc closeCmd = new CommandFunc(){
+		@Override public boolean hasPermission(CommandSender sender){return Permission.ADMIN.has(sender);}
+		@Override public boolean run(CommandSender sender, String[] args){
+			AbbaGame game = getGame(args, sender);
+			if(game == null)
+				return false;
+			game.setOpen(false);
+			sender.sendMessage(String.format(Messages.commandCloseSuccess, game.getName()));
+			return true;
+		}
+
+		@Override public List<String> tabComplete(CommandSender sender, String[] args){
+			List<String> suggestions = new ArrayList<String>(1);
+			if(args.length == 2)
+				suggestions.addAll(GameManager.getGamesAbbreviated(args[1]));
+			return suggestions;
+		}
+		
+	};
+	
+	private CommandFunc reloadCmd = new CommandFunc(){
+		@Override public boolean hasPermission(CommandSender sender){return Permission.ADMIN.has(sender);}
+		@Override public boolean run(CommandSender sender, String[] args) {
+			sender.sendMessage("Reloading config...");
+			plugin.reloadConfig();
+			sender.sendMessage("Reload Complete.");
+			return true;
+		}
+
+		@Override public List<String> tabComplete(CommandSender sender, String[] args) {
+			return Collections.emptyList();
+		}
+		
+	};
+	private CommandFunc startCmd = new CommandFunc(){
+		@Override public boolean hasPermission(CommandSender sender){return Permission.ADMIN.has(sender);}
+		@Override public boolean run(CommandSender sender, String[] args) {
+			AbbaGame game = getGame(args, sender);
+			if(game == null)
+				return false;
+			
+			return game.start(sender);
+		}
+		
+		@Override public List<String> tabComplete(CommandSender sender, String[] args) {
+			if(args.length == 2)
+				return GameManager.getGamesAbbreviated(args[1]);
+			else
+				return Collections.emptyList();
+		}
+	};
+	private CommandFunc pauseCmd = new CommandFunc(){
+		@Override public boolean hasPermission(CommandSender sender){return Permission.ADMIN.has(sender);}
+		@Override public boolean run(CommandSender sender, String[] args) {
+			AbbaGame game = getGame(args, sender);
+			if(game == null)
+				return false;
+			
+			return game.pause(sender);
+		}
+
+		@Override public List<String> tabComplete(CommandSender sender, String[] args) {
+			if(args.length == 2)
+				return GameManager.getGamesAbbreviated(args[1]);
+			else
+				return Collections.emptyList();
+		}
+	};
+	
+	
+	private CommandFunc configCmd = new CommandFunc(){
+		private Map<String, CommandFunc> subCommands = new HashMap<String, CommandFunc>();
+		
+		
+		
+		//subcommands
+		private CommandFunc timerCmd = new CommandFunc(){
+			@Override public boolean hasPermission(CommandSender sender){return Permission.ADMIN.has(sender);}
+			@Override public boolean run(CommandSender sender, String[] args){
+				if(args.length >= 4){
+					AbbaGame game = GameManager.getGame(args[1]);
+					if(game == null){
+						sender.sendMessage(String.format(Messages.errorGameNotFound, args[1]));
+						return false;
+					}
+					int newTime;
+					
+					try{
+						newTime = Integer.parseInt(args[3]);
+					}catch(NumberFormatException e){
+						sender.sendMessage(Messages.commandConfigTimerHelp);
+						return false;
+					}
+					if(newTime <= 0){
+						sender.sendMessage(Messages.commandConfigTimerHelp);
+						return false;
+					}
+					game.setTimeLeft(newTime);
+					sender.sendMessage(Messages.commandConfigTimerSuccess);
+					return true;
+					
+				}else{
+					sender.sendMessage(Messages.commandConfigTimerHelp);
+					return false;
+				}
+			}
+			
+			@Override public List<String> tabComplete(CommandSender sender, String[] args){
+				return Collections.emptyList();
+			}
+		};
+		
+		private CommandFunc playerCapCmd = new CommandFunc(){
+			@Override public boolean hasPermission(CommandSender sender){return Permission.ADMIN.has(sender);}
+			@Override public boolean run(CommandSender sender, String[] args){
+				if(args.length >= 4){
+					AbbaGame game = GameManager.getGame(args[1]);
+					if(game == null){
+						sender.sendMessage(String.format(Messages.errorGameNotFound, args[1]));
+						return false;
+					}
+					int newPlayerCap;
+					
+					try{
+						newPlayerCap = Integer.parseInt(args[3]);
+					}catch(NumberFormatException e){
+						sender.sendMessage(Messages.commandConfigPlayercapHelp);
+						return false;
+					}
+					if(newPlayerCap < 0){
+						newPlayerCap = -1;
+					}
+					game.setPlayerCap(newPlayerCap);
+					sender.sendMessage(Messages.commandConfigPlayercapSuccess);
+					return true;
+					
+				}else{
+					sender.sendMessage(Messages.commandConfigPlayercapHelp);
+					return false;
+				}
+			}
+			
+			@Override public List<String> tabComplete(CommandSender sender, String[] args){
+				return Collections.emptyList();
+			}
+		};
+		
+		{
+			subCommands.put("timer", timerCmd);
+			subCommands.put("playercap", playerCapCmd);
+			//TODO Other config subcommands
+		}
+		
+		
+		@Override public boolean hasPermission(CommandSender sender){
+			for(CommandFunc command:subCommands.values()){
+				if(command.hasPermission(sender))
+					return true;
+			}
+			return false;
+		}
+		@Override public boolean run(CommandSender sender, String[] args){
+			if(args.length <= 2){
+				sender.sendMessage(Messages.commandConfigHelp);
+				return false;
+			}
+			CommandFunc command = subCommands.get(args[2].toLowerCase());
+			if(command != null){
+				if(command.hasPermission(sender)){
+					return command.run(sender, args);
+				}else{
+					sender.sendMessage(Messages.errorNoPermission);
+					return false;
+				}	
+			}else{
+				sender.sendMessage(Messages.commandConfigHelp);
+				return false;
+			}
+		}
+		
+		@Override public List<String> tabComplete(CommandSender sender, String[] args) {
+			if(args.length == 2)
+				return GameManager.getGamesAbbreviated(args[1]);
+			else if(args.length == 3){
+				List<String> suggestions = new ArrayList<String>();
+				subCommands.forEach((name, command) -> {
+					if(name.startsWith(args[2].toLowerCase()) && command.hasPermission(sender))
+						suggestions.add(name);
+				});
+				return suggestions;
+			}else if(args.length >= 4){
+				CommandFunc command = subCommands.get(args[3]);
+				if(command != null && command.hasPermission(sender))
+					return command.tabComplete(sender, args);
+				else
+					return Collections.emptyList();
+			}else
+				return Collections.emptyList();
+		}
+	};
+	
+	
+	
+	
+	@Override
+	public boolean onCommand(CommandSender sender, Command cmd, String alias, String[] args){
+		CommandFunc command = commands.get(args[0]);
+		if(command != null){
+			if(command.hasPermission(sender)){
+				return command.run(sender, args);
+			}else{
+				sender.sendMessage(Messages.errorNoPermission);
+				return false;
+			}	
+		}
+		return false;
+	}
+	
+	@Override
+	public List<String> onTabComplete(CommandSender sender, Command cmd, String alias, String[] args){
+		if(args.length == 1){
+			List<String> suggestions = new ArrayList<String>();
+			commands.forEach((name, command) -> {
+				if(name.startsWith(args[0]) && command.hasPermission(sender))
+					suggestions.add(name);
+			});
+			
+			
+			return suggestions;
+		}else{
+			CommandFunc command = commands.get(args[0]);
+			if(command.hasPermission(sender)){
+				return command.tabComplete(sender, args);
+			}else{
+				return Collections.emptyList();
+			}
+		}
+	}
+	
+	private static interface CommandFunc{
+		public boolean hasPermission(CommandSender sender);
+		public boolean run(CommandSender sender, String[] args);
+		public List<String> tabComplete(CommandSender sender, String[] args);
+	}
+	@FunctionalInterface
+	private static interface BoolRunnable{
+		public boolean run();
+	}
+	
+	private void registerCooldown(UUID id, BoolRunnable code, int cooldown){
+		playerCooldowns.put(id, code);
+		Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, () -> playerCooldowns.remove(id), cooldown);
+	}
+	private AbbaGame getGame(String[] args, CommandSender sender){
+		AbbaGame game = null;
+		if(args.length >= 2){
+			game = GameManager.getGame(args[1]);
+			if(game == null)
+				sender.sendMessage(String.format(Messages.errorGameNotFound, args[1]));
+			return game;
+		}
+		else if(sender instanceof Player)
+			game = GameManager.getGame((Player) sender);
+		
+		if(game == null)
+			game = GameManager.getGame();
+		if(game == null){
+			sender.sendMessage(Messages.errorNoGames);
+		}
+		return game;
+	}
+}

+ 46 - 0
src/me/lennartVH01/Config.java

@@ -0,0 +1,46 @@
+package me.lennartVH01;
+
+import java.util.List;
+import java.util.Map;
+
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.inventory.ItemStack;
+
+public class Config{
+	private Config(){}
+	
+	public static ItemStack[] itemValues;
+	public static ItemStack[] contraband;
+	
+	public static int defaultDuration;
+	public static int defaultPlayerCap;
+	
+	public static boolean scanContraband;
+	
+	@SuppressWarnings("unchecked")
+	public static void reload(FileConfiguration config){
+		Permission.debug = config.getBoolean("Debug");
+		
+		defaultDuration = config.getInt("Duration");
+		defaultPlayerCap = config.getInt("PlayerCap");
+		scanContraband = config.getBoolean("ScanContraband");
+		
+		List<Map<?, ?>> itemValueMapList = config.getMapList("ItemValues");
+		List<Map<?, ?>> contrabandMapList = config.getMapList("Contraband");
+		
+		itemValues = new ItemStack[itemValueMapList.size()];
+		contraband = new ItemStack[itemValueMapList.size() + contrabandMapList.size()];
+		
+		
+		for(int i = 0; i < contrabandMapList.size(); i++){
+			contraband[i] = ItemStack.deserialize((Map<String, Object>) contrabandMapList.get(i));
+		}
+		for(int i = 0; i < itemValueMapList.size(); i++){
+			ItemStack stack = ItemStack.deserialize((Map<String, Object>) itemValueMapList.get(i));
+			itemValues[i] = stack;
+			contraband[contrabandMapList.size() + i] = stack;
+		}
+		
+		
+	}
+}

+ 0 - 46
src/me/lennartVH01/EventListener.java

@@ -1,46 +0,0 @@
-package me.lennartVH01;
-
-import org.bukkit.block.Block;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.block.BlockBreakEvent;
-import org.bukkit.event.block.SignChangeEvent;
-import org.bukkit.event.inventory.InventoryOpenEvent;
-import org.bukkit.event.inventory.InventoryType;
-import org.bukkit.event.player.PlayerQuitEvent;
-import org.bukkit.event.player.PlayerTeleportEvent;
-
-public class EventListener implements Listener{
-	public static Main plugin;
-	public static void initialize(Main pl) {
-		plugin = pl;
-		
-	}
-	@EventHandler
-	public void onPlayerQuit(PlayerQuitEvent e){
-		AbbaTools.leave(e.getPlayer().getUniqueId());
-	}
-	public void onPlayerTeleport(PlayerTeleportEvent e){
-		AbbaTools.leave(e.getPlayer().getUniqueId());
-	}
-	
-	@EventHandler(ignoreCancelled = true)
-	public void onChestOpen(InventoryOpenEvent e){
-		if(e.getInventory().getType() == InventoryType.CHEST){
-			AbbaTools.onChestOpen(e);
-		}
-	}
-	
-	@EventHandler(ignoreCancelled = true)
-	public void onSignPlace(SignChangeEvent e){
-		AbbaTools.onSignPlace(e);
-	}
-	
-	@EventHandler(ignoreCancelled = true)
-	public void onSignBreak(BlockBreakEvent e){
-		Block brokenBlock = e.getBlock();
-		if(BlockUtils.isSign(brokenBlock)){
-			AbbaTools.onSignBreak(e);
-		}
-	}
-}

+ 20 - 88
src/me/lennartVH01/Main.java

@@ -1,121 +1,53 @@
 package me.lennartVH01;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.List;
 import java.io.File;
-import java.io.IOException;
-import org.bukkit.Material;
+
+import me.lennartVH01.game.GameManager;
+import me.lennartVH01.util.ChatUtil;
+
 import org.bukkit.command.CommandExecutor;
 import org.bukkit.command.TabCompleter;
-import org.bukkit.configuration.file.FileConfiguration;
 import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.configuration.serialization.ConfigurationSerialization;
-import org.bukkit.inventory.ItemStack;
 import org.bukkit.plugin.java.JavaPlugin;
 
 public class Main extends JavaPlugin{
-	
-	private static HashSet<Material> transparentBlocks = new HashSet<Material>();
-	static{
-		transparentBlocks.add(Material.AIR);
-		transparentBlocks.add(Material.SIGN);
-		transparentBlocks.add(Material.SIGN_POST);
-		transparentBlocks.add(Material.WALL_SIGN);
+	public static void main(String[] args){
+		String penis = "{\"text\":\"Json Test\",\"color\":\"green\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"SQUID\"}}";
+		System.out.println(ChatUtil.fromRawJSON(penis).toString());
 	}
-	
-	
-	
-	
-	
-	public static Main plugin;
-	
-	public FileConfiguration config;
-	
-	
-	
-	
 	@Override
 	public void onEnable(){
+		//copy files from jar to data folder
+		saveDefaultConfig();
 		saveResource("lang.yml", false);
-		Messages.reload(YamlConfiguration.loadConfiguration(new File(getDataFolder(), "lang.yml")));
-		AbbaCommand abbaCmd = new AbbaCommand();
-		this.getCommand("abba").setExecutor((CommandExecutor) abbaCmd);
-		this.getCommand("abba").setTabCompleter((TabCompleter) abbaCmd);
-		AbbaAdminCommand abbaAdminCmd = new AbbaAdminCommand(this);
-		this.getCommand("abbaadmin").setExecutor((CommandExecutor) abbaAdminCmd);
-		this.getCommand("abbaadmin").setTabCompleter((TabCompleter) abbaAdminCmd);
-		
-		
-		EventListener.initialize(this);
-		AbbaGame.initialize(this);
-		ConfigurationSerialization.registerClass(AbbaGame.class);
-		
-		config = this.getConfig();
-		// Event handler
-		
-		getServer().getPluginManager().registerEvents(new EventListener(), this);
 		
+		Config.reload(getConfig());
+		Messages.reload(YamlConfiguration.loadConfiguration(new File(getDataFolder(), "lang.yml")));
 		
-		//Config
-		this.saveDefaultConfig();
-		
-		
-		
-		// get Item Point Values
-		List<Map<?,?>> itemPointMaps = config.getMapList("ItemValues");
-		List<ValueItemPair> valueItemPairs = new ArrayList<ValueItemPair>();
-		List<ItemStack> contrabandList = new ArrayList<ItemStack>();
-		for(Map<?,?> itemMapGeneric:itemPointMaps){
-			
-			//Put the torches and pitchforks away, config.getMapList() *should* return Map<String, Object> anyways
-			@SuppressWarnings("unchecked")
-			Map<String, Object> itemMap = (Map<String, Object>) itemMapGeneric;
-			
-			if(itemMap.get("Value") == null)
-				continue;
-			int value = (int) itemMap.remove("Value");
-			ItemStack stack = ItemStack.deserialize(itemMap);
-			contrabandList.add(stack);
-			stack.setAmount(0);
-			valueItemPairs.add(new ValueItemPair(stack, value));
-		}
-		List<Map<?,?>> contrabandMap = config.getMapList("Contraband");
-		
-		for(Map<?,?> itemMapGeneric:contrabandMap){
-			//I did it agian :D
-			@SuppressWarnings("unchecked")
-			Map<String, Object> itemMap = (Map<String, Object>) itemMapGeneric;
-			
-			contrabandList.add(ItemStack.deserialize(itemMap));
-		}
 		
-		AbbaTools.initialize(this, valueItemPairs, contrabandList);
+		CommandHandler abbaCmd = new CommandHandler(this);
+		this.getCommand("abba").setExecutor((CommandExecutor) abbaCmd);
+		this.getCommand("abba").setTabCompleter((TabCompleter) abbaCmd);
 		
-		FileConfiguration persist = YamlConfiguration.loadConfiguration(new File(getDataFolder(), "persist.yml"));
+		getServer().getPluginManager().registerEvents(new SignEventHandler(), this);
 		
-		//I can see the rage in thy eyes
-		@SuppressWarnings("unchecked")
-		List<AbbaGame> abbaList = (List<AbbaGame>) persist.getList("Games");
-		if(abbaList != null){
-			AbbaTools.deserialize((List<AbbaGame>) abbaList); 
-		}
 	}
 	@Override
 	public void onDisable(){
-		File persistFile = new File(getDataFolder(), "persist.yml");
+		GameManager.cleanup();
+		
+		/*File persistFile = new File(getDataFolder(), "persist.yml");
 		
 		
 		FileConfiguration persist = new YamlConfiguration();
 		
-		persist.set("Games", AbbaTools.getGames());
+		persist.set("Games", abbaFactory.getGames());
 		
 		
 		try{
 			persist.save(persistFile);
 		}catch(IOException e){
 			System.out.println("[ERROR] Could not save to persist.yml! Reason:" + e.getMessage());
-		}
+		}*/
 	}
 }

+ 124 - 53
src/me/lennartVH01/Messages.java

@@ -1,36 +1,38 @@
 package me.lennartVH01;
 
+import net.md_5.bungee.api.ChatColor;
+
 import org.bukkit.configuration.file.FileConfiguration;
 
-public class Messages {
-	/*public static String errorNoPermission = "§cYou don't have permission to use this command!";
-	public static String errorMustBeInGame = "§cYou must be ingame to use this command!";
-	public static String errorGameNotFound = "§cGame %s not found!";
-	*/
-	//public static String basicHelpMessage = "Usage:\n - §aabba join§f: Joins the Abba Match\n - §aabba leave§f: Leaves current Abba Game\n - §aabba info§f: Displays info about an Abba Match\n - §aabba list§f: Lists all Abba Matches\n - §aabba calc§f: Calculates the score of your current inventory";
-	//public static String adminHelpMessage = "Usage:\n - §aabbaadmin create [game]§f: Creates an Abba Game\n - §aabbaadmin remove <game>§f: Removes an Abba Game\n - §aabbaadmin open [game]§f: Allows players to join an Abba Game\n - §aabbaadmin close [game]§f: Prevents players from joining an Abba Game\n - §aabbaadmin start [game]§f: Starts an Abba Game\n - §aabbaadmin calcscores§f: Use to calculate the scores and determine a winner at the end of a Match\n - §aabbaadmin config <game> <timer|addchest> ...§f: Configures an Abba Game\n - §aabbaadmin reload§f: Reloads the config";
-	/*
-	public static String errorGameFull = "§cThis game is full!";
-	public static String errorGameClosed = "§cThis game is closed!";
-	public static String errorNoChest = "§cThere aren't enough chests!";
-	public static String errorNotWhitelisted = "§cYou aren't whitelisted for this game!";
-	public static String errorBlacklisted = "§cYou are blacklisted for this game!";
-	*/
-	public static String gameJoinMessage;
-	public static String gameLeaveMessage;
-	public static String playerJoinMessage;
-	public static String playerLeaveMessage;
+public class Messages{
+	private Messages(){}
+	
+	public static String playerJoin;
+	public static String playerLeave;
+
+	public static String gameStart;
+	public static String gameCountdown;
+	public static String gamePause;
+	public static String gameEnded;
 	
 	public static String errorNoGames;
 	public static String errorNoPermission;
+	public static String errorNoPendingOperation;
 	public static String errorMustBeInGame;
 	public static String errorGameNotFound;
+	public static String errorGameNotFinished;
+	public static String errorPlayerNotFound;
+	public static String errorWorldNotFound;
 	
 	public static String errorGameFull;
 	public static String errorGameClosed;
-	public static String errorNoChest;
 	public static String errorNotWhitelisted;
 	public static String errorBlacklisted;
+	public static String errorContraband;
+	
+	public static String errorBreakClaimedChest;
+	public static String chestCreateSuccess;
+	public static String chestRemoveSuccess;
 	
 	public static String helpJoin;
 	public static String helpLeave;
@@ -38,7 +40,6 @@ public class Messages {
 	public static String helpList;
 	public static String helpCalc;
 	
-	//admin cmds
 	public static String helpCreate;
 	public static String helpRemove;
 	public static String helpOpen;
@@ -48,39 +49,109 @@ public class Messages {
 	public static String helpReload;
 	public static String helpConfig;
 	
+	public static String commandJoinSuccess;
+	public static String commandLeaveSuccess;
+	
+	public static String commandCreateSuccess;
+	
+	public static String commandRemoveSuccess;
+	public static String commandRemoveConfirm;
+	
+	public static String commandOpenSuccess;
+	public static String commandCloseSuccess;
+	
+	public static String commandStartErrorRunning;
+	public static String commandStartErrorFinished;
+	public static String commandStartErrorContraband;
+	
+	public static String commandPauseSuccess;
+	public static String commandPauseErrorGameNotRunning;
+	
+	public static String commandConfigHelp;
+	public static String commandConfigTimerHelp;
+	public static String commandConfigTimerSuccess;
+	public static String commandConfigPlayercapHelp;
+	public static String commandConfigPlayercapSuccess;
+	
+	
+	
+	private static FileConfiguration langFile;
 	public static void reload(FileConfiguration langFile){
-		gameJoinMessage = langFile.getString("msg.gameJoin");
-		gameLeaveMessage = langFile.getString("msg.gameLeave");
-		playerJoinMessage = langFile.getString("msg.playerJoin");
-		playerLeaveMessage = langFile.getString("msg.playerLeave");
-		
-		
-		errorNoPermission = langFile.getString("error.noPermission");
-		errorMustBeInGame = langFile.getString("error.mustBeInGame");
-		errorGameNotFound = langFile.getString("error.mustBeInGame");
-		errorNoGames = langFile.getString("error.noGames");
-		
-		errorGameFull = langFile.getString("error.gameFull");
-		errorGameClosed = langFile.getString("error.gameClosed");
-		errorNoChest = langFile.getString("error.noChest");
-		errorNotWhitelisted = langFile.getString("error.notWhitelisted");
-		errorBlacklisted = langFile.getString("error.blacklisted");
-		
-		helpJoin = langFile.getString("help.join");
-		helpLeave = langFile.getString("help.leave");
-		helpInfo = langFile.getString("help.info");
-		helpList = langFile.getString("help.list");
-		helpCalc = langFile.getString("help.calc");
-		
-		helpCreate = langFile.getString("help.create");
-		helpRemove = langFile.getString("help.remove");
-		helpOpen = langFile.getString("help.open");
-		helpClose = langFile.getString("help.close");
-		helpStart = langFile.getString("help.start");
-		helpCalcScores = langFile.getString("help.calcscores");
-		helpReload = langFile.getString("help.reload");
-		helpConfig = langFile.getString("help.config");
-		
-		//TODO
+		Messages.langFile = langFile;
+		
+		playerJoin = load("msg.playerJoin");
+		playerLeave = load("msg.playerLeave");
+		
+		gameCountdown = load("msg.gameCountdown");
+		gameStart = load("msg.gameStart");
+		gamePause = load("msg.gamePause");
+		gameEnded = load("msg.gameEnd");
+		
+		errorNoGames = load("error.noGames");
+		errorNoPermission = load("error.noPermission");
+		errorNoPendingOperation = load("error.noPendingOperation");
+		errorMustBeInGame = load("error.mustBeInGame");
+		errorGameNotFound = load("error.gameNotFound");
+		errorPlayerNotFound = load("error.playerNotFound");
+		errorWorldNotFound = load("error.worldNotFound");
+		
+		errorGameFull = load("error.gameFull");
+		errorGameClosed = load("error.gameClosed");
+		errorNotWhitelisted = load("error.notWhitelisted");
+		errorBlacklisted = load("error.blacklisted");
+		errorContraband = load("error.contraband");
+		
+		errorBreakClaimedChest = load("error.breakClaimedChest");
+		chestCreateSuccess = load("chest.create");
+		chestRemoveSuccess = load("chest.remove");
+		
+		helpJoin = load("help.join");
+		helpLeave = load("help.leave");
+		helpInfo = load("help.info");
+		helpList = load("help.list");
+		helpCalc = load("help.calc");
+		
+		helpCreate = load("help.create");
+		helpRemove = load("help.remove");
+		helpOpen = load("help.open");
+		helpClose = load("help.close");
+		helpStart = load("help.start");
+		helpCalcScores = load("help.calcscores");
+		helpReload = load("help.reload");
+		helpConfig = load("help.config");
+		
+		commandJoinSuccess = load("command.join.success");
+		commandLeaveSuccess = load("command.leave.success");
+		
+		commandCreateSuccess = load("command.create.success");
+		
+		commandRemoveSuccess = load("command.remove.success");
+		commandRemoveConfirm = load("command.remove.confirm");
+		
+		commandOpenSuccess = load("command.open.success");
+		commandCloseSuccess = load("command.close.success");
+		
+		commandStartErrorRunning = load("command.start.error.running");
+		commandStartErrorFinished = load("command.start.error.finished");
+		commandStartErrorContraband = load("command.start.error.contraband");
+		
+		commandPauseSuccess = load("command.pause.success");
+		commandPauseErrorGameNotRunning = load("command.pause.error");
+		
+		
+		commandConfigHelp = load("command.config.help");
+		commandConfigTimerHelp = load("command.config.command.timer.help");
+		commandConfigTimerSuccess = load("command.config.command.timer.success");
+		commandConfigPlayercapHelp = load("command.config.command.playercap.help");
+		commandConfigPlayercapSuccess = load("command.config.command.playercap.success");
+		
+	}
+	private static String load(String path){
+		String input = langFile.getString(path);
+		if(input == null || input.isEmpty()){
+			System.out.println("ERROR COULDN'T FIND " + path);
+			return "";
+		}
+		return ChatColor.translateAlternateColorCodes('&', input);
 	}
 }

+ 13 - 19
src/me/lennartVH01/Permission.java

@@ -1,27 +1,21 @@
 package me.lennartVH01;
 
-import org.bukkit.command.CommandSender;
+import org.bukkit.permissions.Permissible;
 
 
 
-public enum Permission{
+public class Permission{
+	public static boolean debug = false;
+	private String perm;
+	private Permission(String perm){this.perm = perm;}
+	public boolean has(Permissible p){
+		return p.hasPermission(perm) || debug;
+	}
 	
-	JOIN_FULL("AbbaCaving.joinFull"),
-	JOIN_CLOSED("AbbaCaving.joinClosed"),
-	JOIN_WHITELISTED("AbbaCaving.joinWhilelisted"),
-	REGISTER_CHEST("AbbaCaving.registerChest");
+	public static Permission JOIN_FULL = new Permission("AbbaCaving.joinFull");
+	public static Permission JOIN_CLOSED = new Permission("AbbaCaving.joinClosed");
+	public static Permission JOIN_WHITELISTED = new Permission("AbbaCaving.joinWhilelisted");
 	
-	private final String permission;
-	private Permission(String permission){
-		this.permission = permission;
-	}
-	public static boolean hasPermission(CommandSender sender, Permission perm){
-		return hasPermission(sender, perm.permission);
-	}
-	public static boolean hasPermission(CommandSender sender, String perm){
-		return sender.hasPermission(perm);
-	}
-	public String toString(){
-		return permission;
-	}
+	public static Permission BASIC = new Permission("AbbaCaving.basic");
+	public static Permission ADMIN = new Permission("AbbaCaving.admin");
 }

+ 13 - 0
src/me/lennartVH01/SignEventHandler.java

@@ -0,0 +1,13 @@
+package me.lennartVH01;
+
+import me.lennartVH01.game.GameManager;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerQuitEvent;
+
+public class SignEventHandler implements Listener{
+	@EventHandler
+	public static void onPlayerQuit(PlayerQuitEvent e){
+		GameManager.leave(e.getPlayer());
+	}
+}

+ 0 - 22
src/me/lennartVH01/Tuple2.java

@@ -1,22 +0,0 @@
-package me.lennartVH01;
-
-public class Tuple2<S,U>{
-	S arg1;
-	U arg2;
-	public Tuple2(S arg1, U arg2){
-		this.arg1 = arg1;
-		this.arg2 = arg2;
-	}
-	public S getArg1() {
-		return arg1;
-	}
-	public void setArg1(S arg1) {
-		this.arg1 = arg1;
-	}
-	public U getArg2() {
-		return arg2;
-	}
-	public void setArg2(U arg2) {
-		this.arg2 = arg2;
-	}
-}

+ 0 - 30
src/me/lennartVH01/Tuple3.java

@@ -1,30 +0,0 @@
-package me.lennartVH01;
-
-public class Tuple3<S, U, V>{
-	S arg1;
-	U arg2;
-	V arg3;
-	public Tuple3(S arg1, U arg2, V arg3){
-		this.arg1 = arg1;
-		this.arg2 = arg2;
-		this.arg3 = arg3;
-	}
-	public S getArg1() {
-		return arg1;
-	}
-	public void setArg1(S arg1) {
-		this.arg1 = arg1;
-	}
-	public U getArg2() {
-		return arg2;
-	}
-	public void setArg2(U arg2) {
-		this.arg2 = arg2;
-	}
-	public V getArg3() {
-		return arg3;
-	}
-	public void setArg3(V arg3) {
-		this.arg3 = arg3;
-	}
-}

+ 0 - 25
src/me/lennartVH01/ValueItemPair.java

@@ -1,25 +0,0 @@
-package me.lennartVH01;
-
-import org.bukkit.inventory.ItemStack;
-
-public class ValueItemPair {
-	public ItemStack itemStack;
-	public int value;
-	public ValueItemPair(ItemStack itemStack, int value){
-		this.itemStack = itemStack;
-		this.value = value;
-	}
-	public ItemStack getItemStack() {
-		return itemStack;
-	}
-	public void setItemStack(ItemStack itemStack) {
-		this.itemStack = itemStack;
-	}
-	public int getValue() {
-		return value;
-	}
-	public void setValue(int value) {
-		this.value = value;
-	}
-	
-}

+ 54 - 0
src/me/lennartVH01/game/AbbaGame.java

@@ -0,0 +1,54 @@
+package me.lennartVH01.game;
+
+import java.util.List;
+
+
+import org.bukkit.Location;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.serialization.ConfigurationSerializable;
+import org.bukkit.entity.Player;
+
+public interface AbbaGame extends ConfigurationSerializable{
+	
+	
+	public boolean join(Player p);
+	public void leave(Player p);
+	public void leaveAll();
+	
+	//SETTERS GETTERS
+	//public void setState(GameState state);
+	public GameState getState();
+	public void setPlayerCap(int playerCap);
+	public int getPlayerCap();
+	public List<Player> getPlayers();
+	
+	public void setOpen(boolean open);
+	public boolean isOpen();
+	public boolean hasRoom();
+	public int getPlayerCount();
+	public String getName();
+	public Location getSpawn();
+	public int getDuration();
+	public void setTimeLeft(int newTime);
+	public int getTimeLeft();
+	
+	public void broadcast(String message);
+	public void tpAll(Location loc);
+	
+	public boolean start(CommandSender sender);
+	public boolean pause(CommandSender sender);
+	
+	public void destroy();
+	
+	
+	public enum GameState {
+		WAITING, 
+		COUNTDOWN,
+		RUNNING, 
+		PAUSED, 
+		FINISHED,
+		CONCLUDED
+		
+	}
+	
+}

+ 381 - 0
src/me/lennartVH01/game/BasicAbbaGame.java

@@ -0,0 +1,381 @@
+package me.lennartVH01.game;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import me.lennartVH01.Config;
+import me.lennartVH01.Messages;
+import me.lennartVH01.Permission;
+import me.lennartVH01.util.ChatUtil;
+import net.minecraft.server.v1_9_R1.ChatComponentText;
+import net.minecraft.server.v1_9_R1.IChatBaseComponent;
+
+import org.bukkit.Bukkit;
+import org.bukkit.GameMode;
+import org.bukkit.Location;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.scoreboard.DisplaySlot;
+import org.bukkit.scoreboard.Objective;
+import org.bukkit.scoreboard.Score;
+import org.bukkit.scoreboard.Scoreboard;
+
+public class BasicAbbaGame implements AbbaGame{
+	private static final String TIMER_SCORE_NAME = "Timer";
+	
+	
+	
+	
+	private final Clock clock;
+	
+	private GameState state = GameState.WAITING;
+	private boolean open = false;
+	
+	private int playerCap;
+	private int timeLeft;
+	private int duration;
+	private String name;
+	private Location spawn;
+	
+	
+	private ContrabandScanner scanner;
+	private ItemStack[] itemValues;
+	
+	private List<Player> players;
+	
+	private Scoreboard scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
+	private Objective objective = scoreboard.registerNewObjective("AbbaCaving", "dummy");
+	private Score timerScore = objective.getScore(TIMER_SCORE_NAME);
+	
+	
+	public BasicAbbaGame(JavaPlugin plugin, String name, Location spawn, int duration, int playerCap, ContrabandScanner scanner, ItemStack[] itemValues){
+		clock = new Clock(plugin);
+		this.name = name;
+		this.spawn = spawn;
+		this.duration = duration;
+		this.playerCap = playerCap;
+		this.scanner = scanner;
+		this.itemValues = itemValues;
+		if(playerCap == -1){
+			players = new ArrayList<Player>();
+		}else{
+			players = new ArrayList<Player>(playerCap);
+		}
+	}
+	@Override public void destroy(){
+		clock.turnOff();
+		leaveAll();
+	}
+	
+	//Clock code
+	private void clockTickCountdown(){
+		if(timeLeft <= 0){
+			timeLeft = duration;
+			startGame();
+		}else{
+			broadcast("§c" + timeLeft);
+			timeLeft--;
+		}
+	}
+	private void clockTickRunning(){
+		if(timeLeft <= 0)
+			endGame();
+		else{
+			timerScore.setScore(timeLeft);
+			timeLeft--;
+		}
+	}
+	private void startGame(){
+		clock.turnOff();
+		
+		objective.setDisplayName("Abba Caving");
+		objective.setDisplaySlot(DisplaySlot.SIDEBAR);
+		
+		broadcast(Messages.gameStart);
+		
+		
+		
+		state = GameState.RUNNING;
+		clock.turnOn(0, 20, this::clockTickRunning);
+	}
+	private void endGame(){
+		clock.turnOff();
+		tpAll(spawn);
+		broadcast(Messages.gameEnded);
+		state = GameState.FINISHED;
+		
+		scoreboard.resetScores(TIMER_SCORE_NAME);
+		objective.setDisplayName("Scores");
+		objective.setDisplaySlot(DisplaySlot.SIDEBAR);
+		
+		List<AbbaScore> scores = tally();
+		
+		int[] totalItems = new int[itemValues.length];
+		
+		for(AbbaScore score:scores){
+			for(int i = 0; i < itemValues.length; i++){
+				totalItems[i] += score.count[i];
+			}
+		}
+		StringBuilder msgBuilder = new StringBuilder();
+		for(int i = 0; i < itemValues.length; i++){
+			msgBuilder.append(ChatUtil.getName(itemValues[i]) + ": " + totalItems[i]);
+		}
+		
+		
+		
+		for(int i = 0; i < scores.size(); i++){
+			AbbaScore score = scores.get(i);
+			objective.getScore(score.player.getName()).setScore(score.total);
+			
+		}
+	}
+	
+	
+	
+	@Override
+	public boolean join(final Player p){
+		if(!Permission.JOIN_CLOSED.has(p) && !open){
+			p.sendMessage(Messages.errorGameClosed);
+			return false;
+		}
+		if(playerCap >= 0 && !Permission.JOIN_FULL.has(p) && players.size() >= playerCap){
+			p.sendMessage(Messages.errorGameFull);
+			return false;
+		}
+		if(Config.scanContraband){
+			List<ItemStack> illegalItems = scanner.getContraband(p.getInventory());
+			if(!illegalItems.isEmpty()){
+				p.sendMessage(Messages.errorContraband);
+				for(ItemStack stack:illegalItems){
+					IChatBaseComponent chatStack = ChatUtil.stackToChat(stack);
+					IChatBaseComponent chatText = new ChatComponentText("§c - ");
+					chatText.addSibling(chatStack);
+					
+					ChatUtil.send(p, chatText);
+					
+				}
+				return false;
+			}
+		}
+		
+		
+		//SUCCESS
+		
+		broadcast(String.format(Messages.playerJoin, p.getName()));
+		p.sendMessage(String.format(Messages.commandJoinSuccess, this.getName()));
+		
+		players.add(p);
+		p.setScoreboard(scoreboard);
+		
+		p.teleport(spawn);
+		p.setGameMode(GameMode.SURVIVAL);
+		
+		return true;
+	}
+	
+	@Override public void leave(final Player p){
+		players.remove(p);
+		playerLeaveCleanup(p);
+	}
+	@Override public void leaveAll(){
+		for(Iterator<Player> iter = players.iterator(); iter.hasNext(); ){
+			Player p = iter.next();
+			playerLeaveCleanup(p);
+			iter.remove();
+		}
+	}
+	private void playerLeaveCleanup(Player p){
+		p.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard());
+		
+		broadcast(String.format(Messages.playerLeave, p.getName()));
+		p.sendMessage(String.format(Messages.commandLeaveSuccess, this.getName()));
+	}
+	
+	
+	
+	
+	//TODO SERIALIZATION
+	@Override
+	public Map<String, Object> serialize(){
+		return null;
+		
+	}
+	public static AbbaGame deserialize(Map<String, Object> inputMap){
+		return null;
+	}
+	
+	
+	//SETTERS GETTERS
+	@Override public boolean start(final CommandSender sender){
+		switch(state){
+		case WAITING:
+			boolean canStart = true;
+			if(sender instanceof Player){
+				StringBuilder messageBuilder = new StringBuilder("[");
+				for(Player p:players){
+					List<ItemStack> contraband = scanner.getContraband(p.getInventory());
+					if(!contraband.isEmpty()){
+						if(canStart){
+							canStart = false;
+							sender.sendMessage(Messages.commandStartErrorContraband);
+						}
+						messageBuilder.append("{\"text\":\"" + p.getName() + "\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":[");
+						for(int i = 0; i < contraband.size(); i++){
+							messageBuilder.append("{\"translate\":\"" + ChatUtil.getName(contraband.get(i)) + "\"},\"\\n\",");
+							
+						}
+						messageBuilder.setCharAt(messageBuilder.length() - 1, ']');
+						messageBuilder.append("}},");
+					}
+				}
+				if(!canStart){
+					messageBuilder.delete(messageBuilder.length() - 9, messageBuilder.length() - 4);
+					messageBuilder.setCharAt(messageBuilder.length() - 1, ']');
+					System.out.println(messageBuilder.toString());
+					ChatUtil.send((Player) sender, ChatUtil.fromRawJSON(messageBuilder.toString()));
+				}
+			}else{
+				for(Player p:players){
+					if(scanner.hasContraband(p.getInventory())){
+						if(canStart){
+							canStart = false;
+							sender.sendMessage(Messages.commandStartErrorContraband);
+						}
+						sender.sendMessage(p.getName());
+					}
+				}
+			}
+			if(canStart){
+				broadcast(Messages.gameCountdown);
+				state = GameState.COUNTDOWN;
+				timeLeft = 5;
+				clock.turnOn(20, 20, this::clockTickCountdown);
+				return true;
+			}
+			return false;
+		case PAUSED:
+			startGame();
+			return true;
+		case COUNTDOWN:
+		case RUNNING:
+			sender.sendMessage(Messages.commandStartErrorRunning);
+			return false;
+		case FINISHED:
+		case CONCLUDED:
+			sender.sendMessage(Messages.commandStartErrorFinished);
+			return false;
+		default:
+			return false;
+		}
+	}
+	@Override public boolean pause(final CommandSender sender){
+		clock.turnOff();
+		switch(state){
+		case COUNTDOWN:
+			timeLeft = duration;
+			state = GameState.WAITING;
+			for(Player p:players){
+				p.sendMessage(Messages.gamePause);
+			}
+			sender.sendMessage(String.format(Messages.commandPauseSuccess, name));
+			return true;
+		case RUNNING:
+			sender.sendMessage(String.format(Messages.commandPauseSuccess, name));
+			state = GameState.PAUSED;
+			broadcast(Messages.gamePause);
+			return true;
+		default:
+			sender.sendMessage(Messages.commandPauseErrorGameNotRunning);
+			return false;
+		}
+	}
+	
+	private List<AbbaScore> tally(){
+		List<AbbaScore> scores = new ArrayList<AbbaScore>(players.size());
+		int[] totalItems = new int[itemValues.length];
+		for(Player p:players){
+			AbbaScore score = new AbbaScore(p, itemValues.length);
+			
+			
+			for(Iterator<ItemStack> iter = p.getInventory().iterator(); iter.hasNext();){
+				ItemStack stack = iter.next();
+				for(int i = 0; i < itemValues.length; i++){
+					if(itemValues[i].isSimilar(stack)){
+						score.count[i] += stack.getAmount();
+						break;
+					}
+				}
+				scores.add(score);
+			}
+			
+			for(int i = 0; i < itemValues.length; i++){
+				score.total += itemValues[i].getAmount() * score.count[i];
+				totalItems[i] += score.count[i];
+			}
+		}
+		
+		scores.sort((s1, s2) -> {
+			return s2.total - s1.total;
+		});
+		return scores;
+	}
+	
+	
+	
+	
+	@Override public void setOpen(boolean open){this.open = open;}
+	@Override public boolean isOpen(){return false;}
+	@Override public boolean hasRoom(){return false;}
+	@Override public int getPlayerCount(){return players.size();}
+	
+	@Override public GameState getState(){return state;}
+	
+	@Override public void setPlayerCap(int playerCap) {this.playerCap = playerCap;}
+	@Override public int getPlayerCap(){return playerCap;}
+	@Override public List<Player> getPlayers(){return players;}
+	
+	@Override public String getName(){return name;}
+	@Override public Location getSpawn(){return spawn;}
+	@Override public int getDuration(){return duration;}
+	@Override public void setTimeLeft(int timeLeft){if(state == GameState.WAITING)this.duration = timeLeft; else this.timeLeft = timeLeft;}
+	@Override public int getTimeLeft(){return timeLeft;}
+	
+	@Override public void broadcast(final String message){for(Player p:players) p.sendMessage(message);}
+	@Override public void tpAll(final Location loc){for(Player p:players) p.teleport(loc);}
+	
+	private static class Clock{
+		private JavaPlugin plugin;
+		private int taskId;
+		private boolean clockEnabled = false;
+		
+		public Clock(JavaPlugin plugin){
+			this.plugin = plugin;
+		}
+		public void turnOn(long delay, long interval, Runnable code){
+			if(clockEnabled)
+				turnOff();
+			taskId = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, code, delay, interval);
+			clockEnabled = true;
+		}
+		public void turnOff(){
+			if(clockEnabled){
+				plugin.getServer().getScheduler().cancelTask(taskId);
+				clockEnabled = false;
+			}
+		}
+	}
+	private static class AbbaScore{
+		public final int[] count;
+		public final Player player;
+		public int total;
+		
+		public AbbaScore(Player player, int size){
+			count = new int[size];
+			this.player = player;
+		}
+	}
+}

+ 41 - 0
src/me/lennartVH01/game/CalculatedScore.java

@@ -0,0 +1,41 @@
+package me.lennartVH01.game;
+
+import org.bukkit.inventory.ItemStack;
+
+public class CalculatedScore{
+	public int total = 0;
+	public ItemStack[] itemValues;
+	public int[] itemCount;
+	public int[] itemPoints;
+	
+	public CalculatedScore(ItemStack[] itemValues){
+		int size = itemValues.length;
+		this.itemValues = itemValues;
+		itemCount = new int[size];
+		itemPoints = new int[size];
+	}
+	
+	public void add(int i, int amount){
+		itemPoints[i] += amount * itemValues[i].getAmount();
+		itemCount[i] += amount;
+		total += amount * itemValues[i].getAmount();
+	}
+	
+	public int getTotal(){
+		return total;
+	}
+	public ItemStack getItemStack(int i){
+		return itemValues[i];
+	}
+	public int getItemCount(int i){
+		return itemCount[i];
+	}
+	public int getItemPoints(int i){
+		return itemPoints[i];
+	}
+	
+	
+	public int size(){
+		return itemCount.length;
+	}
+}

+ 45 - 0
src/me/lennartVH01/game/ContrabandScanner.java

@@ -0,0 +1,45 @@
+package me.lennartVH01.game;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+
+
+
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+
+public class ContrabandScanner{
+	private ItemStack[] illegalItems;
+	
+	
+	
+	public ContrabandScanner(ItemStack[] illegalItems){
+		this.illegalItems = illegalItems;
+	}
+	
+	public List<ItemStack> getContraband(Inventory inv){
+		List<ItemStack> totalContraband = new ArrayList<ItemStack>();
+		for(ItemStack detectionStack:illegalItems){
+			for(ItemStack stack:inv){
+				if(detectionStack.isSimilar(stack)){
+					totalContraband.add(stack);
+					break;
+				}
+			}
+		}
+		return totalContraband;
+	}
+	
+	public boolean hasContraband(Inventory inv){
+		for(ItemStack detectionStack:illegalItems){
+			for(ItemStack stack:inv){
+				if(detectionStack.isSimilar(stack)){
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+}

+ 85 - 0
src/me/lennartVH01/game/GameManager.java

@@ -0,0 +1,85 @@
+package me.lennartVH01.game;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.Listener;
+
+import me.lennartVH01.Messages;
+
+public class GameManager implements Listener{
+	private GameManager(){} //private constructor, singleton
+	private static List<AbbaGame> games = new ArrayList<AbbaGame>();
+	private static Map<UUID, AbbaGame> playerGames = new HashMap<UUID, AbbaGame>();
+	
+	public static void registerGame(AbbaGame game){
+		games.add(game);
+	}
+	public static boolean removeGame(String name){
+		return removeGame(getGame(name));
+	}
+	public static boolean removeGame(AbbaGame game){
+		if(game == null)
+			return false;
+		games.remove(game);
+		game.destroy();
+		return true;
+	}
+	
+	public static boolean join(Player p, AbbaGame game){
+		leave(p);
+		
+		if(game.join(p)){
+			playerGames.put(p.getUniqueId(), game);
+			return true;
+		}else
+			return false;
+	}
+	public static AbbaGame leave(Player p){
+		AbbaGame game = playerGames.remove(p.getUniqueId());
+		if(game != null){
+			game.leave(p);
+		}
+		return game;
+	}
+	public static AbbaGame getGame(){
+		if(games.isEmpty()){
+			return null;
+		}else{
+			return games.get(0);
+		}
+	}
+	public static AbbaGame getGame(String name){
+		for(AbbaGame game:games){
+			if(name.equals(game.getName()))
+				return game;
+		}
+		return null;
+	}
+	public static AbbaGame getGame(Player p){
+		return playerGames.get(p.getUniqueId());
+	}
+	public static List<String> getGamesAbbreviated(String shortenedName){
+		List<String> gameNames = new ArrayList<String>();
+		for(AbbaGame game:games){
+			String name = game.getName();
+			if(name.toLowerCase().startsWith(shortenedName.toLowerCase()))
+				gameNames.add(name);
+		}
+		return gameNames;
+	}
+	
+	public static List<AbbaGame> getGames(){
+		return games;
+	}
+	
+	public static void cleanup(){
+		for(AbbaGame game:games){
+			game.destroy();
+		}
+	}
+}

+ 105 - 0
src/me/lennartVH01/game/TesterStackFactory.java

@@ -0,0 +1,105 @@
+package me.lennartVH01.game;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
+
+
+public class TesterStackFactory{
+	/*private static final Pattern testableStackPattern = Pattern.compile("(\\w+)\\((\\d+)\\)"); // material_name(damage): amount
+	
+	public static StackTestable[] deserialize(List<Object> inputList){
+		StackTestable[] testStacks = new StackTestable[inputList.size()];
+		
+		for(int i = 0; i < inputList.size(); i++){
+			Object entry = inputList.get(i);
+
+			String name;
+			Object data = null;
+			if(entry instanceof String){
+				testStacks[i] = new MaterialTestStack(Material.getMaterial((String) entry));
+				continue;
+			}else if(entry instanceof Map){
+				if(((Map) entry).size() == 1){
+					Map.Entry itemEntry = (Map.Entry) ((Map) entry).entrySet().iterator().next();
+					name = (String) itemEntry.getKey();
+					data = itemEntry.getValue();
+				}else{
+					continue;
+				}
+			}else{
+				continue;
+			}
+			
+			
+			short damage = -1;
+			int amount = -1;
+			Matcher match = testableStackPattern.matcher(name);
+			Material material = Material.getMaterial(match.group(1));
+			if(match.group(2) != null){
+				damage = Short.parseShort(match.group(2));
+			}
+			if(data == null || data instanceof Integer){
+				amount = (Integer) data;
+			}else if(data instanceof Map){
+				
+			}
+		}
+	}
+	
+	
+	private interface StackTestable{
+		public boolean compare(ItemStack testStack);
+		public ItemStack asItemStack();
+	}
+	private static class MaterialTestStack implements StackTestable{
+		private final Material material;
+		private final ItemStack stack;
+		public MaterialTestStack(Material material){
+			this(material, 0);
+		}
+		public MaterialTestStack(Material material, int amount){
+			this.material = material;
+			this.stack = new ItemStack(material, amount);
+		}
+		
+		@Override public boolean compare(ItemStack testStack){
+			return material == testStack.getType();
+		}
+		@Override public ItemStack asItemStack(){return stack;}
+	}
+	private static class MaterialDamageTestStack implements StackTestable{
+		private final Material material;
+		private final short damage;
+		private final ItemStack stack;
+		public MaterialDamageTestStack(Material material, short damage){
+			this(material, damage, 0);
+		}
+		public MaterialDamageTestStack(Material material, short damage, int amount){
+			this.material = material;
+			this.damage = damage;
+			this.stack = new ItemStack(material, amount, damage);
+		}
+		
+		@Override public boolean compare(ItemStack testStack){
+			return material == testStack.getType() && testStack.getDurability() == damage;
+		}
+		@Override public ItemStack asItemStack(){return stack;}
+	}
+	private static class ItemStackTestStack implements StackTestable{
+		private final ItemStack stack;
+		public ItemStackTestStack(ItemStack testStack){
+			this.stack = testStack;
+		}
+		
+		@Override public boolean compare(ItemStack testStack){
+			return stack.isSimilar(testStack);
+		}
+		@Override public ItemStack asItemStack(){return stack;}
+	}*/
+}

+ 35 - 0
src/me/lennartVH01/util/BlockUtil.java

@@ -0,0 +1,35 @@
+package me.lennartVH01.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.block.Chest;
+
+public class BlockUtil {
+	public static final BlockFace[] SIGN_ATTACH_DIRECTIONS = new BlockFace[]{BlockFace.UP, BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST};
+	
+	
+	public static boolean isChest(Block block){
+		return block.getState() instanceof Chest;
+	}
+	public static boolean isSign(Block block){
+		return block.getState().getData() instanceof org.bukkit.material.Sign;
+	}
+	
+	public static Block getAttachedBlock(Block b){
+		return b.getRelative(((org.bukkit.material.Sign) b.getState().getData()).getAttachedFace());
+	}
+	public static List<org.bukkit.block.Sign> getAttachedSigns(Block block){
+		List<org.bukkit.block.Sign> signs = new ArrayList<org.bukkit.block.Sign>(5);
+		
+		for(BlockFace face:SIGN_ATTACH_DIRECTIONS){
+			Block b = block.getRelative(face);
+			if(b.getState() instanceof org.bukkit.material.Sign && face == ((org.bukkit.material.Sign) block.getState().getData()).getAttachedFace().getOppositeFace()){
+				signs.add((org.bukkit.block.Sign) b.getState());
+			}
+		}
+		return signs;
+	}
+}

+ 24 - 0
src/me/lennartVH01/util/ChatUtil.java

@@ -0,0 +1,24 @@
+package me.lennartVH01.util;
+
+import net.minecraft.server.v1_9_R1.IChatBaseComponent;
+import net.minecraft.server.v1_9_R1.PacketPlayOutChat;
+
+import org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_9_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+
+public class ChatUtil {
+	public static void send(Player player, IChatBaseComponent chat) {
+		((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutChat(chat));
+	}
+	public static IChatBaseComponent stackToChat(org.bukkit.inventory.ItemStack stack){
+		return CraftItemStack.asNMSCopy(stack).B();
+		
+	}
+	public static IChatBaseComponent fromRawJSON(String json){
+		return IChatBaseComponent.ChatSerializer.a(json);
+	}
+	public static String getName(org.bukkit.inventory.ItemStack stack){
+		return CraftItemStack.asNMSCopy(stack).getItem().getName() + ".name";
+	}
+}

+ 2 - 2
src/me/lennartVH01/ItemUtils.java → src/me/lennartVH01/util/ItemUtil.java

@@ -1,9 +1,9 @@
-package me.lennartVH01;
+package me.lennartVH01.util;
 
 import java.util.Map;
 
 
-public class ItemUtils {
+public class ItemUtil {
 	public static boolean isMapInMap(Map<String, Object> testMap, Map<String, Object> elderMap){
 		for(String key:elderMap.keySet()){
 			Object o = testMap.get(key);

+ 10 - 0
src/me/lennartVH01/util/Tuple2.java

@@ -0,0 +1,10 @@
+package me.lennartVH01.util;
+
+public class Tuple2<S,U>{
+	public S arg1;
+	public U arg2;
+	public Tuple2(S arg1, U arg2){
+		this.arg1 = arg1;
+		this.arg2 = arg2;
+	}
+}

+ 12 - 0
src/me/lennartVH01/util/Tuple3.java

@@ -0,0 +1,12 @@
+package me.lennartVH01.util;
+
+public class Tuple3<S, U, V>{
+	public S arg1;
+	public U arg2;
+	public V arg3;
+	public Tuple3(S arg1, U arg2, V arg3){
+		this.arg1 = arg1;
+		this.arg2 = arg2;
+		this.arg3 = arg3;
+	}
+}

+ 15 - 0
src/me/lennartVH01/util/ValuedObject.java

@@ -0,0 +1,15 @@
+package me.lennartVH01.util;
+
+public class ValuedObject<T> {
+	int value;
+	T object;
+	
+	public ValuedObject(int value, T object){
+		this.value = value;
+		this.object = object;
+	}
+	public void setValue(int value){this.value = value;}
+	public int getValue(){return value;}
+	public void setObject(T object){this.object = object;}
+	public T getObject(){return object;}
+}