Prechádzať zdrojové kódy

ScoreboardManager reworked, add dynamic team member list

RedstoneFuture 3 rokov pred
rodič
commit
6823a56769

+ 14 - 38
missilewars-plugin/src/main/java/de/butzlabben/missilewars/game/Game.java

@@ -46,20 +46,10 @@ import de.butzlabben.missilewars.wrapper.event.PlayerArenaJoinEvent;
 import de.butzlabben.missilewars.wrapper.game.Team;
 import de.butzlabben.missilewars.wrapper.player.MWPlayer;
 import de.butzlabben.missilewars.wrapper.stats.FightStats;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.function.Consumer;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.ToString;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.GameMode;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.World;
+import org.bukkit.*;
 import org.bukkit.enchantments.Enchantment;
 import org.bukkit.entity.Player;
 import org.bukkit.event.HandlerList;
@@ -68,6 +58,12 @@ import org.bukkit.inventory.meta.ItemMeta;
 import org.bukkit.scheduler.BukkitTask;
 import org.bukkit.scoreboard.Scoreboard;
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.function.Consumer;
+
 /**
  * @author Butzlabben
  * @since 01.01.2018
@@ -94,7 +90,6 @@ public class Game {
     private GameWorld gameWorld;
     private long timestart;
     @Getter private Arena arena;
-    private Scoreboard scoreboard;
     private ScoreboardManager scoreboardManager;
     private GameBoundListener listener;
     private ItemStack customBow;
@@ -136,36 +131,10 @@ public class Game {
 
         team1 = new Team(lobby.getTeam1Name(), lobby.getTeam1Color(), this);
         team2 = new Team(lobby.getTeam2Name(), lobby.getTeam2Color(), this);
-
-        scoreboardManager = new ScoreboardManager(team1, team2, arena.getDisplayName(), getTimer());
       
         team1.createTeamArmor();
         team2.createTeamArmor();
 
-        org.bukkit.scoreboard.Team t = scoreboard.getTeam("0" + team1.getFullname());
-        if (t != null)
-            t.unregister();
-        t = scoreboard.registerNewTeam("0" + team1.getFullname());
-        t.setPrefix(team1.getColorCode());
-        VersionUtil.setScoreboardTeamColor(t, ChatColor.getByChar(team1.getColorCode().charAt(1)));
-        team1.setSBTeam(t);
-
-        t = scoreboard.getTeam("1" + team2.getFullname());
-        if (t != null)
-            t.unregister();
-        t = scoreboard.registerNewTeam("1" + team2.getFullname());
-        t.setPrefix(team2.getColorCode());
-        VersionUtil.setScoreboardTeamColor(t, ChatColor.getByChar(team2.getColorCode().charAt(1)));
-        team2.setSBTeam(t);
-
-        t = scoreboard.getTeam("2Guest§7");
-        if (t != null)
-            t.unregister();
-        t = scoreboard.registerNewTeam("2Guest§7");
-        t.setPrefix("§7");
-
-        VersionUtil.setScoreboardTeamColor(t, ChatColor.GRAY);
-
         Logger.DEBUG.log("Registering, teleporting, etc. all players");
 
         for (Player all : Bukkit.getOnlinePlayers()) {
@@ -188,6 +157,7 @@ public class Game {
             return;
         }
 
+        // choose the game arena
         if (lobby.getMapChooseProcedure() == MapChooseProcedure.FIRST) {
             setArena(lobby.getArenas().get(0));
         } else if (lobby.getMapChooseProcedure() == MapChooseProcedure.MAPCYCLE) {
@@ -203,6 +173,8 @@ public class Game {
             lobby.getArenas().forEach(arena -> votes.put(arena.getName(), 0));
         }
 
+        scoreboardManager = new ScoreboardManager(this);
+        scoreboardManager.createScoreboard();
 
         Logger.DEBUG.log("Making game ready");
         ++fights;
@@ -215,6 +187,10 @@ public class Game {
         createGameItems();
     }
 
+    public Scoreboard getScoreboard() {
+        return scoreboardManager.board;
+    }
+
     public void startGame() {
         if (Config.isSetup()) {
             Logger.WARN.log("Did not start game. Setup mode is still enabled");

+ 1 - 1
missilewars-plugin/src/main/java/de/butzlabben/missilewars/game/timer/GameTimer.java

@@ -70,7 +70,7 @@ public class GameTimer extends Timer {
             getGame().stopGame();
         }
         if (seconds % 10 == 0)
-            getGame().getScoreboardManager().updateInGameScoreboard();
+            getGame().getScoreboardManager().updateScoreboard();
         --seconds;
     }
 }

+ 1 - 3
missilewars-plugin/src/main/java/de/butzlabben/missilewars/listener/EndListener.java

@@ -56,10 +56,8 @@ public class EndListener extends GameBoundListener {
         Bukkit.getScheduler().runTaskLater(MissileWars.getInstance(), () -> p.teleport(game.getArena().getSpectatorSpawn()), 2);
 
         Bukkit.getScheduler().runTaskLater(MissileWars.getInstance(), () -> p.setGameMode(GameMode.SPECTATOR), 35);
-        Scoreboard sb = game.getScoreboard();
-        p.setScoreboard(sb);
-        sb.getTeam("2Guest§7").addPlayer(p);
         p.setDisplayName("§7" + p.getName() + "§r");
+        // TODO scoreboard entfernen
         game.addPlayer(p);
     }
 

+ 5 - 5
missilewars-plugin/src/main/java/de/butzlabben/missilewars/listener/GameListener.java

@@ -58,7 +58,6 @@ import org.bukkit.event.player.PlayerMoveEvent;
 import org.bukkit.event.player.PlayerRespawnEvent;
 import org.bukkit.inventory.ItemStack;
 import org.bukkit.scheduler.BukkitTask;
-import org.bukkit.scoreboard.Scoreboard;
 import org.bukkit.util.Vector;
 
 /**
@@ -176,11 +175,10 @@ public class GameListener extends GameBoundListener {
         if (!game.getLobby().isJoinOngoingGame() || game.getPlayers().size() >= game.getLobby().getMaxSize()) {
             p.sendMessage(MessageConfig.getMessage("spectator"));
             Bukkit.getScheduler().runTaskLater(MissileWars.getInstance(), () -> p.teleport(game.getArena().getSpectatorSpawn()), 2);
-            Bukkit.getScheduler().runTaskLater(MissileWars.getInstance(), () -> p.setGameMode(GameMode.SPECTATOR), 35);
-            Scoreboard sb = game.getScoreboard();
-            p.setScoreboard(sb);
-            sb.getTeam("2Guest§7").addPlayer(p);
+            Bukkit.getScheduler().runTaskLater(MissileWars.getInstance(), () -> p.setGameMode(GameMode.SPECTATOR), 35);;
             p.setDisplayName("§7" + p.getName() + "§r");
+            p.setScoreboard(game.getScoreboard());
+            game.getScoreboardManager().updateScoreboard();
         } else {
             Team to;
             int size1 = game.getTeam1().getMembers().size();
@@ -194,6 +192,7 @@ public class GameListener extends GameBoundListener {
             to.updateIntervals(game.getArena().getInterval(to.getMembers().size()));
             game.startForPlayer(p);
             p.setScoreboard(game.getScoreboard());
+            game.getScoreboardManager().updateScoreboard();
         }
     }
 
@@ -315,6 +314,7 @@ public class GameListener extends GameBoundListener {
             getGame().broadcast(
                     MessageConfig.getMessage("player_left").replace("%player%", e.getPlayer().getDisplayName()));
             team.removeMember(getGame().getPlayer(e.getPlayer()));
+            game.getScoreboardManager().resetScoreboard();
             int teamSize = team.getMembers().size();
             if (teamSize == 0) {
                 Bukkit.getScheduler().runTask(MissileWars.getInstance(), () -> {

+ 1 - 0
missilewars-plugin/src/main/java/de/butzlabben/missilewars/listener/LobbyListener.java

@@ -95,6 +95,7 @@ public class LobbyListener extends GameBoundListener {
         p.setFoodLevel(20);
         p.setHealth(p.getMaxHealth());
         p.setScoreboard(game.getScoreboard());
+        game.getScoreboardManager().updateScoreboard();
 
         Bukkit.getScheduler().runTaskLater(MissileWars.getInstance(), () -> p.setGameMode(GameMode.ADVENTURE), 10);
         Bukkit.getScheduler().runTaskLater(MissileWars.getInstance(), () -> p.teleport(game.getLobby().getSpawnPoint()), 2);

+ 175 - 47
missilewars-plugin/src/main/java/de/butzlabben/missilewars/util/ScoreboardManager.java

@@ -19,7 +19,8 @@
 package de.butzlabben.missilewars.util;
 
 import de.butzlabben.missilewars.Config;
-import de.butzlabben.missilewars.game.timer.Timer;
+import de.butzlabben.missilewars.game.Game;
+import de.butzlabben.missilewars.wrapper.abstracts.Arena;
 import de.butzlabben.missilewars.wrapper.game.Team;
 import de.butzlabben.missilewars.wrapper.player.MWPlayer;
 import lombok.RequiredArgsConstructor;
@@ -28,35 +29,114 @@ import org.bukkit.scoreboard.DisplaySlot;
 import org.bukkit.scoreboard.Objective;
 import org.bukkit.scoreboard.Scoreboard;
 
+import java.util.HashMap;
+import java.util.List;
+
+// Scoreboard Management: https://www.spigotmc.org/wiki/making-scoreboard-with-teams-no-flicker
+
 @RequiredArgsConstructor
 public class ScoreboardManager {
 
-    private Scoreboard board = Bukkit.getScoreboardManager().getNewScoreboard();
+    private final Game game;
 
-    private final Team team1;
-    private final Team team2;
-    private final String arenaDisplayName;
-    private final Timer gameTimer;
+    private Team team1;
+    private Team team2;
+    private Arena arena;
 
     // get config options
-    String scoreBoardTitle = Config.getScoreboardTitle();
-    String memberListStyle = Config.getScoreboardMembersStyle();
-    int memberListMaxSize = Config.getScoreboardMembersMax();
+    private String scoreBoardTitle = Config.getScoreboardTitle();
+    private String memberListStyle = Config.getScoreboardMembersStyle();
+    private int memberListMaxSize = Config.getScoreboardMembersMax();
+    private List<String> scoreBoardEntries = Config.getScoreboardEntries();
+
+    private boolean isTeam1ListUsed = false;
+    private boolean isTeam2ListUsed = false;
+
+    private int maxScoreboardLines = 15;
+    public Scoreboard board;
+    private Objective obj;
+    private HashMap<Integer, org.bukkit.scoreboard.Team> teams = new HashMap<>();
+    String[] colorCodes = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
+    
+    /**
+     * This method register the scoreboard.
+     */
+    public void createScoreboard() {
+
+        team1 = game.getTeam1();
+        team2 = game.getTeam2();
+        arena = game.getArena();
+        
+        // register Scoreboard
+        if (board == null) {
+            board = Bukkit.getScoreboardManager().getNewScoreboard();
+        }
+        obj = board.registerNewObjective("Info", "dummy");
+        obj.setDisplaySlot(DisplaySlot.SIDEBAR);
+        obj.setDisplayName(scoreBoardTitle.replace("&", "§"));
+
+        // check if the team lists are used
+        for (String cleanLine : scoreBoardEntries) {
+            if (cleanLine.contains("%team1_members%")) {
+                isTeam1ListUsed = true;
+            } else if (cleanLine.contains("%team2_members%")) {
+                isTeam2ListUsed = true;
+            }
+        }
 
-    public void updateInGameScoreboard() {
-        removeScoreboard();
+        updateScoreboard();
+    }
 
-        Objective obj = board.registerNewObjective("Info", "dummy");
-        obj.setDisplaySlot(DisplaySlot.SIDEBAR);
-        obj.setDisplayName(scoreBoardTitle);
+    /**
+     * This method create a team for the scoreboard and add it to the teams ArrayList.
+     *
+     * @param line the Scoreboard line number
+     */
+    private void addScoreboardTeam(int line) {
+        org.bukkit.scoreboard.Team team;
+
+        if (teams.size() < line) {
+            team = board.registerNewTeam(arena.getName() + "-" + line);
+            team.addEntry("§" + colorCodes[line - 1]);
+            obj.getScore("§" + colorCodes[line - 1]).setScore(line);
+            teams.put(line, team);
+
+            // VersionUtil.setScoreboardTeamColor(t, ChatColor.getByChar(team2.getColorCode().charAt(1)));
+        }
+    }
+
+    public void updateScoreboard() {
+
+        // the number of lines required for the complete Scoreboard
+        int scoreboardLine = scoreBoardEntries.size() + getLineOffset();
+
+        // add new teams
+        for (int i = 1; i <= scoreboardLine; i++) {
+            addScoreboardTeam(i);
+        }
+
+        /*
+
+        Not possible! When a user leaves the game, the scoreboard must be reset.
 
-        for (String cleanLine : Config.getScoreboardEntries()) {
-            int i = 1;
-            String replacedLine;
+        // removes old teams when they are no longer needed
+        while (teams.size() > scoreboardLine) {
+            int oldTeamNumber = teams.size();
+            removeScoreboardTeam(oldTeamNumber);
+        }
+         */
+
+        String replacedLine;
+
+        for (String cleanLine : scoreBoardEntries) {
+            if (scoreboardLine <= 0) {
+                break;
+            }
 
             if (cleanLine.contains("%team1_members%") || cleanLine.contains("%team2_members%")) {
 
-                // team member list
+                // team member list placeholder management:
+
                 Team placeholderTeam;
 
                 // set the current placeholder team
@@ -66,8 +146,14 @@ public class ScoreboardManager {
                     placeholderTeam = team2;
                 }
 
+                // check if there is no one in the team at the moment
+                if (placeholderTeam.getMembers().isEmpty()) {
+                    continue;
+                }
+
                 int players = 0;
 
+                // list all team members
                 for (MWPlayer player : placeholderTeam.getMembers()) {
 
                     // limit check
@@ -80,27 +166,79 @@ public class ScoreboardManager {
 
                     replacedLine = memberListStyle.replace("%playername%", playerName)
                             .replace("%team_color%", teamColor);
-                    setScoreBoardLine(obj, replacedLine, i);
+                    teams.get(scoreboardLine).setPrefix(replacedLine);
 
                     players++;
-                    i++;
+                    scoreboardLine--;
                 }
 
             } else {
 
-                // normal placeholders
+                // normal placeholders management:
+
                 replacedLine = replaceScoreboardPlaceholders(cleanLine);
-                setScoreBoardLine(obj, replacedLine, i);
+                teams.get(scoreboardLine).setPrefix(replacedLine);
 
-                i++;
+                scoreboardLine--;
             }
         }
     }
 
+    /**
+     * This method calculates the offset lines based of the amount of players
+     * and the using of the member-list placeholders for booth teams.
+     *
+     * @return (int) the amount of offset lines
+     */
+    private int getLineOffset() {
+
+        int team1ListSize = 0;
+        int team2ListSize = 0;
+
+        if (isTeam1ListUsed) {
+            if (team1.getMembers().size() > memberListMaxSize) {
+                team1ListSize = memberListMaxSize;
+            } else {
+                team1ListSize = team1.getMembers().size();
+            }
+            team1ListSize--;
+        }
+
+        if (isTeam2ListUsed) {
+            if (team2.getMembers().size() > memberListMaxSize) {
+                team2ListSize = memberListMaxSize;
+            } else {
+                team2ListSize = team2.getMembers().size();
+            }
+            team2ListSize--;
+        }
+
+        return (team1ListSize + team2ListSize);
+    }
+
+    /**
+     * This method deletes the old Scoreboard object, if one exists.
+     */
     public void removeScoreboard() {
-        Objective old = board.getObjective(DisplaySlot.SIDEBAR);
-        if (old != null)
-            old.unregister();
+
+        if (obj != null) {
+            obj.unregister();
+            obj = null;
+        }
+
+        if (!teams.isEmpty()) {
+            teams.forEach((k, v) -> v.unregister());
+            teams.clear();
+        }
+
+    }
+
+    /**
+     * This method remove the current Scoreboard and create a new one.
+     */
+    public void resetScoreboard() {
+        removeScoreboard();
+        createScoreboard();
     }
 
     /**
@@ -110,36 +248,26 @@ public class ScoreboardManager {
      */
     private String replaceScoreboardPlaceholders(String text) {
 
-        String time = "" + Integer.toString(gameTimer.getSeconds() / 60);
+        String time = Integer.toString(game.getTimer().getSeconds() / 60);
+
 
+        text = text.replace("&", "§");
 
-        text.replace("%team1%", team1.getFullname());
-        text.replace("%team2%", team2.getFullname());
+        text = text.replace("%team1%", team1.getFullname());
+        text = text.replace("%team2%", team2.getFullname());
 
-        text.replace("%team1_color%", team1.getColor());
-        text.replace("%team2_color%", team2.getColor());
+        text = text.replace("%team1_color%", team1.getColor());
+        text = text.replace("%team2_color%", team2.getColor());
 
-        text.replace("%team1_amount%", Integer.toString(team1.getMembers().size()));
-        text.replace("%team2_amount%", Integer.toString(team2.getMembers().size()));
+        text = text.replace("%team1_amount%", Integer.toString(team1.getMembers().size()));
+        text = text.replace("%team2_amount%", Integer.toString(team2.getMembers().size()));
 
-        text.replace("%arena_name%", arenaDisplayName);
+        text = text.replace("%arena_name%", arena.getDisplayName());
 
-        text.replace("%time%", time);
+        text = text.replace("%time%", time);
 
         return text;
     }
 
-    /**
-     * This methode set the scoreboard line.
-     *
-     * @param scoreBoardObject the vanilla scoreboard object
-     * @param message the text line
-     * @param lineNr the target line number (= object "score")
-     */
-    private static void setScoreBoardLine(Objective scoreBoardObject, String message, int lineNr) {
-        // Get the "score object" (instead of a player with a text line)
-        // and set the scoreboard line number with the definition of his score.
-        scoreBoardObject.getScore(message).setScore(lineNr);
-    }
 
 }

+ 2 - 16
missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/game/Team.java

@@ -78,11 +78,8 @@ public class Team {
         Player p = player.getPlayer();
         player.setTeam(null);
         if (p != null) {
-            if (scoreboardTeam.hasPlayer(p))
-                scoreboardTeam.removePlayer(p);
-
-            game.getScoreboard().getTeam("2Guest§7").addPlayer(p);
             p.setDisplayName("§7" + p.getName() + "§r");
+            //TODO Scoreboard entfernen
         }
         return members.removeIf(mp -> mp.getUUID().equals(player.getUUID()));
     }
@@ -102,21 +99,10 @@ public class Team {
         members.add(player);
         player.setTeam(this);
         p.setDisplayName(getColorCode() + p.getName() + "§r");
-        Scoreboard sb = game.getScoreboard();
-        if (sb.getPlayerTeam(p) != null)
-            sb.getPlayerTeam(p).removePlayer(p);
-        scoreboardTeam.addPlayer(p);
+        p.setScoreboard(game.getScoreboard());
         p.getInventory().setArmorContents(getTeamArmor());
     }
 
-    public org.bukkit.scoreboard.Team getSBTeam() {
-        return scoreboardTeam;
-    }
-
-    public void setSBTeam(org.bukkit.scoreboard.Team team) {
-        scoreboardTeam = team;
-    }
-
     public String getFullname() {
         return getColorCode() + name;
     }