|
@@ -1,50 +1,371 @@
|
|
|
package me.lennartVH01.game;
|
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Iterator;
|
|
|
import java.util.List;
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+import me.lennartVH01.Config;
|
|
|
+import me.lennartVH01.Messages;
|
|
|
+import me.lennartVH01.Permission;
|
|
|
+import me.lennartVH01.util.ChatUtil;
|
|
|
+import net.minecraft.server.v1_9_R2.ChatComponentText;
|
|
|
import net.minecraft.server.v1_9_R2.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 interface AbbaGame{
|
|
|
+public class 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 StackTester[] 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 AbbaGame(JavaPlugin plugin, String name, Location spawn, int duration, int playerCap, ContrabandScanner scanner, StackTester[] 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);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ 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++){
|
|
|
+ if(totalItems[i] > 0)
|
|
|
+ msgBuilder.append("{\"translate\":\"" + ChatUtil.getName(itemValues[i].asItemStack()) + "\"},\": " + totalItems[i] + "\n\",");
|
|
|
+ }
|
|
|
+ if(msgBuilder.length() > 1){
|
|
|
+ msgBuilder.replace(msgBuilder.length() - 3, msgBuilder.length() - 1, "\"]");
|
|
|
+ broadcast(ChatUtil.fromRawJSON(msgBuilder.toString()));
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ for(int i = 0; i < scores.size(); i++){
|
|
|
+ AbbaScore score = scores.get(i);
|
|
|
+ Score scoreboardScore = objective.getScore(score.player.getName());
|
|
|
+ scoreboardScore.setScore(1);
|
|
|
+ scoreboardScore.setScore(score.total);
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
|
|
|
- public boolean join(Player p);
|
|
|
- public void leave(Player p);
|
|
|
- public void leaveAll();
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void leave(final Player p){
|
|
|
+ players.remove(p);
|
|
|
+ playerLeaveCleanup(p);
|
|
|
+ }
|
|
|
+ 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()));
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
//SETTERS GETTERS
|
|
|
- //public void setState(GameState state);
|
|
|
- public GameState getState();
|
|
|
- public void setPlayerCap(int playerCap);
|
|
|
- public int getPlayerCap();
|
|
|
- public List<Player> getPlayers();
|
|
|
+ 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.replace(messageBuilder.length() - 6, messageBuilder.length(), "]");
|
|
|
+ //messageBuilder.setCharAt(messageBuilder.length() - 1, ']');
|
|
|
+ messageBuilder.append("}},\"\\n\",");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(!canStart){
|
|
|
+ messageBuilder.replace(messageBuilder.length() - 6, messageBuilder.length(), "]");
|
|
|
+ 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:
|
|
|
+ sender.sendMessage(Messages.commandStartErrorFinished);
|
|
|
+ return false;
|
|
|
+ default:
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ 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(ItemStack stack: p.getInventory()){
|
|
|
+ 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].getValue() * score.count[i];
|
|
|
+ totalItems[i] += score.count[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ scores.sort((s1, s2) -> {
|
|
|
+ return s2.total - s1.total;
|
|
|
+ });
|
|
|
+ return scores;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
|
|
|
- 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 broadcast(IChatBaseComponent message);
|
|
|
- public void tpAll(Location loc);
|
|
|
+ public void setOpen(boolean open){this.open = open;}
|
|
|
+ public boolean isOpen(){return false;}
|
|
|
+ public boolean hasRoom(){return false;}
|
|
|
+ public int getPlayerCount(){return players.size();}
|
|
|
|
|
|
- public boolean start(CommandSender sender);
|
|
|
- public boolean pause(CommandSender sender);
|
|
|
+ public GameState getState(){return state;}
|
|
|
|
|
|
- public void destroy();
|
|
|
+ public void setPlayerCap(int playerCap) {this.playerCap = playerCap;}
|
|
|
+ public int getPlayerCap(){return playerCap;}
|
|
|
+ public List<Player> getPlayers(){return players;}
|
|
|
|
|
|
+ public String getName(){return name;}
|
|
|
+ public Location getSpawn(){return spawn;}
|
|
|
+ public int getDuration(){return duration;}
|
|
|
+ public void setTimeLeft(int timeLeft){if(state == GameState.WAITING || state == GameState.COUNTDOWN) this.duration = timeLeft; else this.timeLeft = timeLeft;}
|
|
|
+ public int getTimeLeft(){return timeLeft;}
|
|
|
+
|
|
|
+ public void broadcast(final String message){for(Player p:players) p.sendMessage(message);}
|
|
|
+ public void broadcast(final IChatBaseComponent message){for(Player p:players) ChatUtil.send(p, message);}
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
public enum GameState {
|
|
|
WAITING,
|
|
@@ -54,5 +375,4 @@ public interface AbbaGame{
|
|
|
FINISHED
|
|
|
|
|
|
}
|
|
|
-
|
|
|
}
|