BasicAbbaGame.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. package me.lennartVH01.game;
  2. import java.util.ArrayList;
  3. import java.util.Iterator;
  4. import java.util.List;
  5. import java.util.Map;
  6. import me.lennartVH01.Config;
  7. import me.lennartVH01.Messages;
  8. import me.lennartVH01.Permission;
  9. import me.lennartVH01.util.ChatUtil;
  10. import net.minecraft.server.v1_9_R1.ChatComponentText;
  11. import net.minecraft.server.v1_9_R1.IChatBaseComponent;
  12. import org.bukkit.Bukkit;
  13. import org.bukkit.GameMode;
  14. import org.bukkit.Location;
  15. import org.bukkit.command.CommandSender;
  16. import org.bukkit.entity.Player;
  17. import org.bukkit.inventory.ItemStack;
  18. import org.bukkit.plugin.java.JavaPlugin;
  19. import org.bukkit.scoreboard.DisplaySlot;
  20. import org.bukkit.scoreboard.Objective;
  21. import org.bukkit.scoreboard.Score;
  22. import org.bukkit.scoreboard.Scoreboard;
  23. public class BasicAbbaGame implements AbbaGame{
  24. private static final String TIMER_SCORE_NAME = "Timer";
  25. private final Clock clock;
  26. private GameState state = GameState.WAITING;
  27. private boolean open = false;
  28. private int playerCap;
  29. private int timeLeft;
  30. private int duration;
  31. private String name;
  32. private Location spawn;
  33. private ContrabandScanner scanner;
  34. private ItemStack[] itemValues;
  35. private List<Player> players;
  36. private Scoreboard scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
  37. private Objective objective = scoreboard.registerNewObjective("AbbaCaving", "dummy");
  38. private Score timerScore = objective.getScore(TIMER_SCORE_NAME);
  39. public BasicAbbaGame(JavaPlugin plugin, String name, Location spawn, int duration, int playerCap, ContrabandScanner scanner, ItemStack[] itemValues){
  40. clock = new Clock(plugin);
  41. this.name = name;
  42. this.spawn = spawn;
  43. this.duration = duration;
  44. this.playerCap = playerCap;
  45. this.scanner = scanner;
  46. this.itemValues = itemValues;
  47. if(playerCap == -1){
  48. players = new ArrayList<Player>();
  49. }else{
  50. players = new ArrayList<Player>(playerCap);
  51. }
  52. }
  53. @Override public void destroy(){
  54. clock.turnOff();
  55. leaveAll();
  56. }
  57. //Clock code
  58. private void clockTickCountdown(){
  59. if(timeLeft <= 0){
  60. timeLeft = duration;
  61. startGame();
  62. }else{
  63. broadcast("§c" + timeLeft);
  64. timeLeft--;
  65. }
  66. }
  67. private void clockTickRunning(){
  68. if(timeLeft <= 0)
  69. endGame();
  70. else{
  71. timerScore.setScore(timeLeft);
  72. timeLeft--;
  73. }
  74. }
  75. private void startGame(){
  76. clock.turnOff();
  77. objective.setDisplayName("Abba Caving");
  78. objective.setDisplaySlot(DisplaySlot.SIDEBAR);
  79. broadcast(Messages.gameStart);
  80. state = GameState.RUNNING;
  81. clock.turnOn(0, 20, this::clockTickRunning);
  82. }
  83. private void endGame(){
  84. clock.turnOff();
  85. tpAll(spawn);
  86. broadcast(Messages.gameEnded);
  87. state = GameState.FINISHED;
  88. scoreboard.resetScores(TIMER_SCORE_NAME);
  89. objective.setDisplayName("Scores");
  90. objective.setDisplaySlot(DisplaySlot.SIDEBAR);
  91. List<AbbaScore> scores = tally();
  92. int[] totalItems = new int[itemValues.length];
  93. for(AbbaScore score:scores){
  94. for(int i = 0; i < itemValues.length; i++){
  95. totalItems[i] += score.count[i];
  96. }
  97. }
  98. StringBuilder msgBuilder = new StringBuilder();
  99. for(int i = 0; i < itemValues.length; i++){
  100. msgBuilder.append(ChatUtil.getName(itemValues[i]) + ": " + totalItems[i]);
  101. }
  102. for(int i = 0; i < scores.size(); i++){
  103. AbbaScore score = scores.get(i);
  104. objective.getScore(score.player.getName()).setScore(score.total);
  105. }
  106. }
  107. @Override
  108. public boolean join(final Player p){
  109. if(!Permission.JOIN_CLOSED.has(p) && !open){
  110. p.sendMessage(Messages.errorGameClosed);
  111. return false;
  112. }
  113. if(playerCap >= 0 && !Permission.JOIN_FULL.has(p) && players.size() >= playerCap){
  114. p.sendMessage(Messages.errorGameFull);
  115. return false;
  116. }
  117. if(Config.scanContraband){
  118. List<ItemStack> illegalItems = scanner.getContraband(p.getInventory());
  119. if(!illegalItems.isEmpty()){
  120. p.sendMessage(Messages.errorContraband);
  121. for(ItemStack stack:illegalItems){
  122. IChatBaseComponent chatStack = ChatUtil.stackToChat(stack);
  123. IChatBaseComponent chatText = new ChatComponentText("§c - ");
  124. chatText.addSibling(chatStack);
  125. ChatUtil.send(p, chatText);
  126. }
  127. return false;
  128. }
  129. }
  130. //SUCCESS
  131. broadcast(String.format(Messages.playerJoin, p.getName()));
  132. p.sendMessage(String.format(Messages.commandJoinSuccess, this.getName()));
  133. players.add(p);
  134. p.setScoreboard(scoreboard);
  135. p.teleport(spawn);
  136. p.setGameMode(GameMode.SURVIVAL);
  137. return true;
  138. }
  139. @Override public void leave(final Player p){
  140. players.remove(p);
  141. playerLeaveCleanup(p);
  142. }
  143. @Override public void leaveAll(){
  144. for(Iterator<Player> iter = players.iterator(); iter.hasNext(); ){
  145. Player p = iter.next();
  146. playerLeaveCleanup(p);
  147. iter.remove();
  148. }
  149. }
  150. private void playerLeaveCleanup(Player p){
  151. p.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard());
  152. broadcast(String.format(Messages.playerLeave, p.getName()));
  153. p.sendMessage(String.format(Messages.commandLeaveSuccess, this.getName()));
  154. }
  155. //TODO SERIALIZATION
  156. @Override
  157. public Map<String, Object> serialize(){
  158. return null;
  159. }
  160. public static AbbaGame deserialize(Map<String, Object> inputMap){
  161. return null;
  162. }
  163. //SETTERS GETTERS
  164. @Override public boolean start(final CommandSender sender){
  165. switch(state){
  166. case WAITING:
  167. boolean canStart = true;
  168. if(sender instanceof Player){
  169. StringBuilder messageBuilder = new StringBuilder("[");
  170. for(Player p:players){
  171. List<ItemStack> contraband = scanner.getContraband(p.getInventory());
  172. if(!contraband.isEmpty()){
  173. if(canStart){
  174. canStart = false;
  175. sender.sendMessage(Messages.commandStartErrorContraband);
  176. }
  177. messageBuilder.append("{\"text\":\"" + p.getName() + "\",\"hoverEvent\":{\"action\":\"show_text\",\"value\":[");
  178. for(int i = 0; i < contraband.size(); i++){
  179. messageBuilder.append("{\"translate\":\"" + ChatUtil.getName(contraband.get(i)) + "\"},\"\\n\",");
  180. }
  181. messageBuilder.setCharAt(messageBuilder.length() - 1, ']');
  182. messageBuilder.append("}},");
  183. }
  184. }
  185. if(!canStart){
  186. messageBuilder.delete(messageBuilder.length() - 9, messageBuilder.length() - 4);
  187. messageBuilder.setCharAt(messageBuilder.length() - 1, ']');
  188. System.out.println(messageBuilder.toString());
  189. ChatUtil.send((Player) sender, ChatUtil.fromRawJSON(messageBuilder.toString()));
  190. }
  191. }else{
  192. for(Player p:players){
  193. if(scanner.hasContraband(p.getInventory())){
  194. if(canStart){
  195. canStart = false;
  196. sender.sendMessage(Messages.commandStartErrorContraband);
  197. }
  198. sender.sendMessage(p.getName());
  199. }
  200. }
  201. }
  202. if(canStart){
  203. broadcast(Messages.gameCountdown);
  204. state = GameState.COUNTDOWN;
  205. timeLeft = 5;
  206. clock.turnOn(20, 20, this::clockTickCountdown);
  207. return true;
  208. }
  209. return false;
  210. case PAUSED:
  211. startGame();
  212. return true;
  213. case COUNTDOWN:
  214. case RUNNING:
  215. sender.sendMessage(Messages.commandStartErrorRunning);
  216. return false;
  217. case FINISHED:
  218. case CONCLUDED:
  219. sender.sendMessage(Messages.commandStartErrorFinished);
  220. return false;
  221. default:
  222. return false;
  223. }
  224. }
  225. @Override public boolean pause(final CommandSender sender){
  226. clock.turnOff();
  227. switch(state){
  228. case COUNTDOWN:
  229. timeLeft = duration;
  230. state = GameState.WAITING;
  231. for(Player p:players){
  232. p.sendMessage(Messages.gamePause);
  233. }
  234. sender.sendMessage(String.format(Messages.commandPauseSuccess, name));
  235. return true;
  236. case RUNNING:
  237. sender.sendMessage(String.format(Messages.commandPauseSuccess, name));
  238. state = GameState.PAUSED;
  239. broadcast(Messages.gamePause);
  240. return true;
  241. default:
  242. sender.sendMessage(Messages.commandPauseErrorGameNotRunning);
  243. return false;
  244. }
  245. }
  246. private List<AbbaScore> tally(){
  247. List<AbbaScore> scores = new ArrayList<AbbaScore>(players.size());
  248. int[] totalItems = new int[itemValues.length];
  249. for(Player p:players){
  250. AbbaScore score = new AbbaScore(p, itemValues.length);
  251. for(Iterator<ItemStack> iter = p.getInventory().iterator(); iter.hasNext();){
  252. ItemStack stack = iter.next();
  253. for(int i = 0; i < itemValues.length; i++){
  254. if(itemValues[i].isSimilar(stack)){
  255. score.count[i] += stack.getAmount();
  256. break;
  257. }
  258. }
  259. scores.add(score);
  260. }
  261. for(int i = 0; i < itemValues.length; i++){
  262. score.total += itemValues[i].getAmount() * score.count[i];
  263. totalItems[i] += score.count[i];
  264. }
  265. }
  266. scores.sort((s1, s2) -> {
  267. return s2.total - s1.total;
  268. });
  269. return scores;
  270. }
  271. @Override public void setOpen(boolean open){this.open = open;}
  272. @Override public boolean isOpen(){return false;}
  273. @Override public boolean hasRoom(){return false;}
  274. @Override public int getPlayerCount(){return players.size();}
  275. @Override public GameState getState(){return state;}
  276. @Override public void setPlayerCap(int playerCap) {this.playerCap = playerCap;}
  277. @Override public int getPlayerCap(){return playerCap;}
  278. @Override public List<Player> getPlayers(){return players;}
  279. @Override public String getName(){return name;}
  280. @Override public Location getSpawn(){return spawn;}
  281. @Override public int getDuration(){return duration;}
  282. @Override public void setTimeLeft(int timeLeft){if(state == GameState.WAITING)this.duration = timeLeft; else this.timeLeft = timeLeft;}
  283. @Override public int getTimeLeft(){return timeLeft;}
  284. @Override public void broadcast(final String message){for(Player p:players) p.sendMessage(message);}
  285. @Override public void tpAll(final Location loc){for(Player p:players) p.teleport(loc);}
  286. private static class Clock{
  287. private JavaPlugin plugin;
  288. private int taskId;
  289. private boolean clockEnabled = false;
  290. public Clock(JavaPlugin plugin){
  291. this.plugin = plugin;
  292. }
  293. public void turnOn(long delay, long interval, Runnable code){
  294. if(clockEnabled)
  295. turnOff();
  296. taskId = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, code, delay, interval);
  297. clockEnabled = true;
  298. }
  299. public void turnOff(){
  300. if(clockEnabled){
  301. plugin.getServer().getScheduler().cancelTask(taskId);
  302. clockEnabled = false;
  303. }
  304. }
  305. }
  306. private static class AbbaScore{
  307. public final int[] count;
  308. public final Player player;
  309. public int total;
  310. public AbbaScore(Player player, int size){
  311. count = new int[size];
  312. this.player = player;
  313. }
  314. }
  315. }