Procházet zdrojové kódy

Merge pull request #9 from RedstoneFuture/improvement/better-game-scoreboard

Improvement/better game scoreboard
Daniel před 3 roky
rodič
revize
3f4dabad9a

+ 0 - 1
missilewars-plugin/pom.xml

@@ -64,7 +64,6 @@
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
             <version>2.11.0</version>
-            <scope>compile</scope>
         </dependency>
 
 

+ 66 - 56
missilewars-plugin/src/main/java/de/butzlabben/missilewars/Config.java

@@ -28,7 +28,8 @@ import org.bukkit.configuration.file.YamlConfiguration;
 
 import java.io.*;
 import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.List;
 
 import static org.bukkit.Material.JUKEBOX;
 import static org.bukkit.Material.valueOf;
@@ -127,16 +128,21 @@ public class Config {
         cfg.addDefault("mysql.fights_table", "mw_fights");
         cfg.addDefault("mysql.fightmember_table", "mw_fightmember");
 
-        cfg.addDefault("sidebar.title", "§eInfo ●§6•");
+        cfg.addDefault("sidebar.title", "&eInfo ●&6•");
+        cfg.addDefault("sidebar.member_list_style", "%team_color%%playername%");
+        cfg.addDefault("sidebar.member_list_max", "4");
+
         if (configNew) {
-            cfg.addDefault("sidebar.entries.6", "§7Time left:");
-            cfg.addDefault("sidebar.entries.5", "§e» %time%m");
+            List<String> sidebarList = new ArrayList<>();
 
-            cfg.addDefault("sidebar.entries.4", "  ");
-            cfg.addDefault("sidebar.entries.3", "%team1% §7» %team1_color%%team1_amount%");
+            sidebarList.add("§7Time left:");
+            sidebarList.add("§e» %time%m");
+            sidebarList.add("");
+            sidebarList.add("%team1% §7» %team1_color%%team1_amount%");
+            sidebarList.add("");
+            sidebarList.add("%team2% §7» %team2_color%%team2_amount%");
 
-            cfg.addDefault("sidebar.entries.2", "   ");
-            cfg.addDefault("sidebar.entries.1", "%team2% §7» %team2_color%%team2_amount%");
+            cfg.set("sidebar.entries", sidebarList);
         }
     }
 
@@ -149,13 +155,8 @@ public class Config {
         }
     }
 
-    public static HashMap<String, Integer> getScoreboardEntries() {
-        HashMap<String, Integer> ret = new HashMap<>();
-        ConfigurationSection section = cfg.getConfigurationSection("sidebar.entries");
-        for (String s : section.getKeys(false)) {
-            ret.put(section.getString(s), Integer.valueOf(s));
-        }
-        return ret;
+    public static List<String> getScoreboardEntries() {
+        return cfg.getStringList("sidebar.entries");
     }
 
     /**
@@ -195,20 +196,40 @@ public class Config {
         return cfg;
     }
 
-    public static String motdEnded() {
-        return cfg.getString("motd.ended");
+    static boolean debug() {
+        return cfg.getBoolean("debug");
     }
 
-    public static String motdGame() {
-        return cfg.getString("motd.ingame");
+    public static boolean isSetup() {
+        return cfg.getBoolean("setup_mode");
     }
 
-    public static String motdLobby() {
-        return cfg.getString("motd.lobby");
+    public static boolean isContactAuth() {
+        return cfg.getBoolean("contact_auth_server");
     }
 
-    public static boolean motdEnabled() {
-        return cfg.getBoolean("motd.enable");
+    public static boolean isPrefetchPlayers() {
+        return cfg.getBoolean("prefetch_players");
+    }
+
+    public static int getFightRestart() {
+        return cfg.getInt("restart_after_fights");
+    }
+
+    public static String getArenaFolder() {
+        return cfg.getString("arena_folder") + "/";
+    }
+
+    public static boolean isMultipleLobbies() {
+        return cfg.getBoolean("lobbies.multiple_lobbies");
+    }
+
+    public static String getLobbiesFolder() {
+        return cfg.getString("lobbies.folder") + "/";
+    }
+
+    public static String getDefaultLobby() {
+        return cfg.getString("lobbies.default_lobby");
     }
 
     public static int getReplaceTicks() {
@@ -219,20 +240,28 @@ public class Config {
         return cfg.getInt("replace.radius");
     }
 
-    static boolean debug() {
-        return cfg.getBoolean("debug");
+    public static String motdEnded() {
+        return cfg.getString("motd.ended");
     }
 
-    public static boolean isSetup() {
-        return cfg.getBoolean("setup_mode");
+    public static String motdGame() {
+        return cfg.getString("motd.ingame");
     }
 
-    public static int getFightRestart() {
-        return cfg.getInt("restart_after_fights");
+    public static String motdLobby() {
+        return cfg.getString("motd.lobby");
     }
 
-    public static String getScoreboardTitle() {
-        return cfg.getString("sidebar.title");
+    public static boolean motdEnabled() {
+        return cfg.getBoolean("motd.enable");
+    }
+
+    public static boolean isFightStatsEnabled() {
+        return cfg.getBoolean("fightstats.enable");
+    }
+
+    public static boolean isShowRealSkins() {
+        return cfg.getBoolean("fightstats.show_real_skins");
     }
 
     public static String getHost() {
@@ -263,35 +292,16 @@ public class Config {
         return cfg.getString("mysql.fightmember_table");
     }
 
-    public static String getArenaFolder() {
-        return cfg.getString("arena_folder") + "/";
-    }
-
-    public static boolean isContactAuth() {
-        return cfg.getBoolean("contact_auth_server");
-    }
-
-    public static boolean isPrefetchPlayers() {
-        return cfg.getBoolean("prefetch_players");
-    }
-
-    public static boolean isShowRealSkins() {
-        return cfg.getBoolean("fightstats.show_real_skins");
-    }
-
-    public static boolean isMultipleLobbies() {
-        return cfg.getBoolean("lobbies.multiple_lobbies");
+    public static String getScoreboardTitle() {
+        return cfg.getString("sidebar.title");
     }
 
-    public static String getLobbiesFolder() {
-        return cfg.getString("lobbies.folder") + "/";
+    public static String getScoreboardMembersStyle() {
+        return cfg.getString("sidebar.member_list_style");
     }
 
-    public static String getDefaultLobby() {
-        return cfg.getString("lobbies.default_lobby");
+    public static int getScoreboardMembersMax() {
+        return cfg.getInt("sidebar.member_list_max");
     }
 
-    public static boolean isFightStatsEnabled() {
-        return cfg.getBoolean("fightstats.enable");
-    }
 }

+ 4 - 2
missilewars-plugin/src/main/java/de/butzlabben/missilewars/cmd/UserCommands.java

@@ -30,11 +30,12 @@ import de.butzlabben.missilewars.wrapper.abstracts.Arena;
 import de.butzlabben.missilewars.wrapper.abstracts.MapChooseProcedure;
 import de.butzlabben.missilewars.wrapper.game.Team;
 import de.butzlabben.missilewars.wrapper.player.MWPlayer;
-import java.util.Optional;
 import org.bukkit.Location;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 
+import java.util.Optional;
+
 public class UserCommands {
 
     @Command(name = "mw.change", usage = "/mw change <1|2>", permission = "mw.change", description = "Changes your team", inGameOnly = true)
@@ -77,7 +78,8 @@ public class UserCommands {
                 player.sendMessage(MessageConfig.getMessage("cannot_change_difference"));
                 return;
             }
-            mwPlayer.getTeam().removeMember(mwPlayer);
+
+            // Remove the player from the old team and add him to the new team
             to.addMember(mwPlayer);
 
             player.sendMessage(MessageConfig.getMessage("team_changed").replace("%team%", to.getFullname()));

+ 15 - 42
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,38 +131,10 @@ public class Game {
 
         team1 = new Team(lobby.getTeam1Name(), lobby.getTeam1Color(), this);
         team2 = new Team(lobby.getTeam2Name(), lobby.getTeam2Color(), this);
-
+      
         team1.createTeamArmor();
         team2.createTeamArmor();
 
-        scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
-
-        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);
-
-        scoreboardManager = new ScoreboardManager(this, scoreboard);
-
         Logger.DEBUG.log("Registering, teleporting, etc. all players");
 
         for (Player all : Bukkit.getOnlinePlayers()) {
@@ -190,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) {
@@ -205,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;
@@ -217,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");
@@ -302,7 +276,6 @@ public class Game {
 
         timer = new EndTimer(this);
         bt = Bukkit.getScheduler().runTaskTimer(MissileWars.getInstance(), timer, 5, 20);
-        scoreboardManager.removeScoreboard();
 
         // Change MOTD
         if (!Config.isMultipleLobbies())

+ 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;
     }
 }

+ 6 - 11
missilewars-plugin/src/main/java/de/butzlabben/missilewars/listener/EndListener.java

@@ -31,7 +31,6 @@ import org.bukkit.event.EventPriority;
 import org.bukkit.event.entity.PlayerDeathEvent;
 import org.bukkit.event.inventory.InventoryClickEvent;
 import org.bukkit.event.player.PlayerRespawnEvent;
-import org.bukkit.scoreboard.Scoreboard;
 
 /**
  * @author Butzlabben
@@ -47,8 +46,8 @@ public class EndListener extends GameBoundListener {
     @EventHandler
     public void onJoin(PlayerArenaJoinEvent e) {
         Game game = e.getGame();
-        if (game != getGame())
-            return;
+        if (game != getGame()) return;
+
         Player p = e.getPlayer();
         PlayerDataProvider.getInstance().storeInventory(p);
         p.sendMessage(MessageConfig.getMessage("spectator"));
@@ -56,9 +55,6 @@ 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");
         game.addPlayer(p);
     }
@@ -70,11 +66,10 @@ public class EndListener extends GameBoundListener {
         }
     }
 
+    @SuppressWarnings("deprecation")
     @EventHandler
-
     public void onDeath(PlayerDeathEvent e) {
-        if (!isInLobbyArea(e.getEntity().getLocation()))
-            return;
+        if (!isInLobbyArea(e.getEntity().getLocation())) return;
 
         Player p = e.getEntity();
         p.setHealth(p.getMaxHealth());
@@ -84,8 +79,8 @@ public class EndListener extends GameBoundListener {
 
     @EventHandler
     public void onClick(InventoryClickEvent e) {
-        if (!(e.getWhoClicked() instanceof Player))
-            return;
+        if (!(e.getWhoClicked() instanceof Player)) return;
+
         Player p = (Player) e.getWhoClicked();
         if (isInGameWorld(p.getLocation()))
             if (p.getGameMode() != GameMode.CREATIVE && !p.isOp())

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

@@ -33,24 +33,15 @@ import de.butzlabben.missilewars.wrapper.geometry.Plane;
 import de.butzlabben.missilewars.wrapper.missile.Missile;
 import de.butzlabben.missilewars.wrapper.missile.MissileFacing;
 import de.butzlabben.missilewars.wrapper.player.MWPlayer;
-import java.util.Objects;
 import org.bukkit.Bukkit;
 import org.bukkit.GameMode;
 import org.bukkit.Location;
-import org.bukkit.entity.EntityType;
-import org.bukkit.entity.Fireball;
-import org.bukkit.entity.Player;
-import org.bukkit.entity.Projectile;
-import org.bukkit.entity.Snowball;
+import org.bukkit.entity.*;
 import org.bukkit.event.EventHandler;
 import org.bukkit.event.EventPriority;
 import org.bukkit.event.block.Action;
 import org.bukkit.event.block.BlockPhysicsEvent;
-import org.bukkit.event.entity.EntityDamageByEntityEvent;
-import org.bukkit.event.entity.EntityDamageEvent;
-import org.bukkit.event.entity.EntityExplodeEvent;
-import org.bukkit.event.entity.PlayerDeathEvent;
-import org.bukkit.event.entity.ProjectileLaunchEvent;
+import org.bukkit.event.entity.*;
 import org.bukkit.event.inventory.InventoryClickEvent;
 import org.bukkit.event.inventory.InventoryType;
 import org.bukkit.event.player.PlayerInteractEvent;
@@ -58,9 +49,10 @@ 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;
 
+import java.util.Objects;
+
 /**
  * @author Butzlabben
  * @since 12.01.2018
@@ -74,8 +66,8 @@ public class GameListener extends GameBoundListener {
 
     @EventHandler
     public void onMove(PlayerMoveEvent e) {
-        if (!isInGameWorld(e.getTo()))
-            return;
+        if (!isInGameWorld(e.getTo())) return;
+
         Player p = e.getPlayer();
         if ((e.getTo().getBlockY() >= getGame().getArena().getMaxHeight()) && (p.getGameMode() == GameMode.SURVIVAL)) {
             p.teleport(e.getFrom());
@@ -95,8 +87,8 @@ public class GameListener extends GameBoundListener {
 
     @EventHandler
     public void onExplode(EntityExplodeEvent e) {
-        if (!isInGameWorld(e.getLocation()))
-            return;
+        if (!isInGameWorld(e.getLocation())) return;
+
         Game game = getGame();
         if (e.getEntity().getType() == EntityType.FIREBALL && !game.getArena().getFireballConfiguration().isDestroysPortal())
             e.blockList().removeIf(b -> b.getType() == VersionUtil.getPortal());
@@ -121,12 +113,10 @@ public class GameListener extends GameBoundListener {
 
     @EventHandler
     public void onInteract(PlayerInteractEvent e) {
-        if (!isInGameWorld(e.getPlayer().getLocation()))
-            return;
-        if (e.getItem() == null)
-            return;
-        if (e.getAction() != Action.RIGHT_CLICK_AIR && e.getAction() != Action.RIGHT_CLICK_BLOCK)
-            return;
+        if (!isInGameWorld(e.getPlayer().getLocation())) return;
+        if (e.getItem() == null) return;
+        if (e.getAction() != Action.RIGHT_CLICK_AIR && e.getAction() != Action.RIGHT_CLICK_BLOCK) return;
+
         Player player = e.getPlayer();
         ItemStack itemStack = e.getItem();
         Game game = getGame();
@@ -165,8 +155,7 @@ public class GameListener extends GameBoundListener {
     @EventHandler
     public void onJoin(PlayerArenaJoinEvent e) {
         Game game = e.getGame();
-        if (game != getGame())
-            return;
+        if (game != getGame()) return;
 
         Player p = e.getPlayer();
         MWPlayer mwPlayer = game.addPlayer(p);
@@ -176,11 +165,9 @@ 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());
         } else {
             Team to;
             int size1 = game.getTeam1().getMembers().size();
@@ -189,18 +176,20 @@ public class GameListener extends GameBoundListener {
                 to = getGame().getTeam2();
             else
                 to = getGame().getTeam1();
+
+            // Adds the player to the new team.
             to.addMember(mwPlayer);
+
             p.sendMessage(MessageConfig.getMessage("team_assigned").replace("%team%", to.getFullname()));
             to.updateIntervals(game.getArena().getInterval(to.getMembers().size()));
             game.startForPlayer(p);
-            p.setScoreboard(game.getScoreboard());
         }
     }
 
     @EventHandler
     public void onThrow(ProjectileLaunchEvent e) {
-        if (!isInGameWorld(e.getEntity().getLocation()))
-            return;
+        if (!isInGameWorld(e.getEntity().getLocation())) return;
+
         Game game = getGame();
         if (e.getEntity() instanceof Snowball) {
             Snowball ball = (Snowball) e.getEntity();
@@ -213,10 +202,9 @@ public class GameListener extends GameBoundListener {
 
     @EventHandler
     public void onDmg(EntityDamageByEntityEvent e) {
-        if (!isInGameWorld(e.getEntity().getLocation()))
-            return;
-        if (!(e.getEntity() instanceof Player))
-            return;
+        if (!isInGameWorld(e.getEntity().getLocation())) return;
+        if (!(e.getEntity() instanceof Player)) return;
+
         Player p = (Player) e.getEntity();
         if (e.getDamager() instanceof Projectile) {
             Projectile pj = (Projectile) e.getDamager();
@@ -238,8 +226,7 @@ public class GameListener extends GameBoundListener {
 
     @EventHandler(priority = EventPriority.HIGH)
     public void onRespawn(PlayerRespawnEvent e) {
-        if (!isInGameWorld(e.getPlayer().getLocation()))
-            return;
+        if (!isInGameWorld(e.getPlayer().getLocation())) return;
 
         Game game = getGame();
         Player player = e.getPlayer();
@@ -262,9 +249,7 @@ public class GameListener extends GameBoundListener {
     public void onDeath(PlayerDeathEvent e) {
 
         // check if the player is in a game world
-        if (!isInGameWorld(e.getEntity().getLocation())) {
-            return;
-        }
+        if (!isInGameWorld(e.getEntity().getLocation())) return;
 
         Game game = getGame();
         Player p = e.getEntity();
@@ -303,18 +288,19 @@ public class GameListener extends GameBoundListener {
     @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
     public void onLeave(PlayerArenaLeaveEvent e) {
         Game game = e.getGame();
-        if (game != getGame())
-            return;
+        if (game != getGame()) return;
 
         MWPlayer player = getGame().getPlayer(e.getPlayer());
         if (player == null) return;
         BukkitTask task = game.getPlayerTasks().get(player.getUUID());
         if (task != null) task.cancel();
+
         Team team = player.getTeam();
         if (team != null) {
             getGame().broadcast(
                     MessageConfig.getMessage("player_left").replace("%player%", e.getPlayer().getDisplayName()));
             team.removeMember(getGame().getPlayer(e.getPlayer()));
+
             int teamSize = team.getMembers().size();
             if (teamSize == 0) {
                 Bukkit.getScheduler().runTask(MissileWars.getInstance(), () -> {

+ 23 - 14
missilewars-plugin/src/main/java/de/butzlabben/missilewars/listener/LobbyListener.java

@@ -52,26 +52,31 @@ public class LobbyListener extends GameBoundListener {
 
     @EventHandler
     public void onClick(PlayerInteractEvent e) {
-        if (!isInLobbyArea(e.getPlayer().getLocation()))
-            return;
+        if (!isInLobbyArea(e.getPlayer().getLocation())) return;
+
         Player p = e.getPlayer();
-        if (p.getGameMode() == GameMode.CREATIVE)
-            return;
+        if (p.getGameMode() == GameMode.CREATIVE) return;
         e.setCancelled(true);
         if (e.getItem() == null) return;
 
         if (VersionUtil.isStainedGlassPane(e.getItem().getType())) {
+
             if (!p.hasPermission("mw.change")) return;
+
             if (getGame().getTimer().getSeconds() < 10) {
                 p.sendMessage(MessageConfig.getMessage("change_team_not_now"));
                 return;
             }
+
             String displayName = e.getItem().getItemMeta().getDisplayName();
             if (displayName.equals(getGame().getTeam1().getFullname())) {
                 p.performCommand("mw change 1");
+                getGame().getScoreboardManager().updateScoreboard();
             } else {
                 p.performCommand("mw change 2");
+                getGame().getScoreboardManager().updateScoreboard();
             }
+
         } else if (e.getItem().getType() == Material.NETHER_STAR) {
             VoteInventory inventory = new VoteInventory(getGame().getLobby().getArenas());
             p.openInventory(inventory.getInventory(p));
@@ -82,9 +87,7 @@ public class LobbyListener extends GameBoundListener {
     @EventHandler
     public void onJoin(PlayerArenaJoinEvent e) {
         Game game = e.getGame();
-        if (game != getGame())
-            return;
-
+        if (game != getGame()) return;
 
         Player p = e.getPlayer();
         MWPlayer mw = game.addPlayer(p);
@@ -94,7 +97,6 @@ public class LobbyListener extends GameBoundListener {
         p.getInventory().clear();
         p.setFoodLevel(20);
         p.setHealth(p.getMaxHealth());
-        p.setScoreboard(game.getScoreboard());
 
         Bukkit.getScheduler().runTaskLater(MissileWars.getInstance(), () -> p.setGameMode(GameMode.ADVENTURE), 10);
         Bukkit.getScheduler().runTaskLater(MissileWars.getInstance(), () -> p.teleport(game.getLobby().getSpawnPoint()), 2);
@@ -104,10 +106,11 @@ public class LobbyListener extends GameBoundListener {
         int size1 = getGame().getTeam1().getMembers().size();
         int size2 = getGame().getTeam2().getMembers().size();
 
-        if (size2 < size1)
+        if (size2 < size1) {
             to = getGame().getTeam2();
-        else
+        } else {
             to = getGame().getTeam1();
+        }
 
         // Premium version
         if (p.hasPermission("mw.change")) {
@@ -119,7 +122,9 @@ public class LobbyListener extends GameBoundListener {
             p.getInventory().setItem(4, new OrcItem(Material.NETHER_STAR, "§3Vote Map").getItemStack());
         }
 
+        // Adds the player to the new team.
         to.addMember(mw);
+
         p.sendMessage(MessageConfig.getMessage("team_assigned").replace("%team%", to.getFullname()));
 
         String name = p.getName();
@@ -133,18 +138,22 @@ public class LobbyListener extends GameBoundListener {
 
     @EventHandler
     public void on(EntityDamageEvent e) {
-        if (isInLobbyArea(e.getEntity().getLocation())) e.setCancelled(true);
+        if (isInLobbyArea(e.getEntity().getLocation())) {
+            e.setCancelled(true);
+        }
     }
 
     @EventHandler
     public void on(PlayerRespawnEvent e) {
-        if (isInLobbyArea(e.getPlayer().getLocation())) e.setRespawnLocation(getGame().getLobby().getSpawnPoint());
+        if (isInLobbyArea(e.getPlayer().getLocation())) {
+            e.setRespawnLocation(getGame().getLobby().getSpawnPoint());
+        }
     }
 
     @EventHandler
     public void onClick(InventoryClickEvent e) {
-        if (!(e.getWhoClicked() instanceof Player))
-            return;
+        if (!(e.getWhoClicked() instanceof Player)) return;
+
         Player p = (Player) e.getWhoClicked();
         if (isInLobbyArea(p.getLocation()))
             if (p.getGameMode() != GameMode.CREATIVE && !p.isOp())

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

@@ -43,15 +43,8 @@ import org.bukkit.event.block.BlockPlaceEvent;
 import org.bukkit.event.entity.FoodLevelChangeEvent;
 import org.bukkit.event.inventory.InventoryClickEvent;
 import org.bukkit.event.inventory.InventoryType;
-import org.bukkit.event.player.PlayerDropItemEvent;
-import org.bukkit.event.player.PlayerJoinEvent;
-import org.bukkit.event.player.PlayerMoveEvent;
-import org.bukkit.event.player.PlayerPickupItemEvent;
-import org.bukkit.event.player.PlayerQuitEvent;
-import org.bukkit.event.player.PlayerTeleportEvent;
+import org.bukkit.event.player.*;
 import org.bukkit.event.server.ServerListPingEvent;
-import org.bukkit.scoreboard.Scoreboard;
-import org.bukkit.scoreboard.Team;
 import org.bukkit.util.Vector;
 
 /**
@@ -145,11 +138,12 @@ public class PlayerListener implements Listener {
         Game game = event.getGame();
 
         MWPlayer mwPlayer = game.getPlayer(event.getPlayer());
-        if (mwPlayer == null)
-            return;
+        if (mwPlayer == null) return;
 
-        if (mwPlayer.getTeam() != null)
+        // Already in a team?
+        if (mwPlayer.getTeam() != null) {
             mwPlayer.getTeam().removeMember(mwPlayer);
+        }
 
         game.getPlayers().remove(event.getPlayer().getUniqueId());
 
@@ -159,13 +153,7 @@ public class PlayerListener implements Listener {
             return;
         }
 
-        Scoreboard sb = game.getScoreboard();
-        Team scoreboardTeam = sb.getPlayerTeam(player);
-        if (scoreboardTeam != null)
-            scoreboardTeam.removePlayer(player);
-
         player.getInventory().clear();
-        player.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard());
 
         MissileWars.getInstance().getSignRepository().getSigns(game).forEach(MWSign::update);
 

+ 202 - 26
missilewars-plugin/src/main/java/de/butzlabben/missilewars/util/ScoreboardManager.java

@@ -20,57 +20,233 @@ package de.butzlabben.missilewars.util;
 
 import de.butzlabben.missilewars.Config;
 import de.butzlabben.missilewars.game.Game;
-import java.util.HashMap;
+import de.butzlabben.missilewars.wrapper.abstracts.Arena;
+import de.butzlabben.missilewars.wrapper.game.Team;
+import de.butzlabben.missilewars.wrapper.player.MWPlayer;
 import lombok.RequiredArgsConstructor;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
 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 final Game game;
-    private final Scoreboard board;
 
-    public void updateInGameScoreboard() {
-        removeScoreboard();
+    private Team team1;
+    private Team team2;
+    private Arena arena;
+
+    // get config options
+    private static final String SCOREBOARD_TITLE = Config.getScoreboardTitle();
+    private static final String MEMBER_LIST_STYLE = Config.getScoreboardMembersStyle();
+    private static final int MEMBER_LIST_MAX_SIZE = Config.getScoreboardMembersMax();
+    private static final List<String> SCOREBOARD_ENTRIES = Config.getScoreboardEntries();
+
+    private boolean isTeam1ListUsed = false;
+    private boolean isTeam2ListUsed = false;
+
+    public Scoreboard board;
+    private Objective obj;
+    private HashMap<Integer, org.bukkit.scoreboard.Team> teams = new HashMap<>();
+    private static final String[] COLOR_CODES = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
+    
+    /**
+     * This method registers the scoreboard.
+     */
+    public void createScoreboard() {
 
-        Objective obj = board.registerNewObjective("Info", "dummy");
+        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(Config.getScoreboardTitle());
+        obj.setDisplayName(ChatColor.translateAlternateColorCodes('&', SCOREBOARD_TITLE));
+
+        // check if the team lists are used
+        for (String cleanLine : SCOREBOARD_ENTRIES) {
+            if (cleanLine.contains("%team1_members%")) {
+                isTeam1ListUsed = true;
+            } else if (cleanLine.contains("%team2_members%")) {
+                isTeam2ListUsed = true;
+            }
+        }
 
-        HashMap<String, Integer> entries = Config.getScoreboardEntries();
+        updateScoreboard();
+    }
 
-        for (String entry : entries.keySet()) {
-            String s = rep(entry);
-            obj.getScore(s).setScore(entries.get(entry));
+    /**
+     * This method creates a team for the scoreboard and adds 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("§" + COLOR_CODES[line - 1]);
+            obj.getScore("§" + COLOR_CODES[line - 1]).setScore(line);
+            teams.put(line, team);
         }
     }
 
-    public void removeScoreboard() {
-        Objective old = board.getObjective(DisplaySlot.SIDEBAR);
-        if (old != null)
-            old.unregister();
+    public void updateScoreboard() {
+
+        // the number of lines required for the complete Scoreboard
+        int scoreboardLine = SCOREBOARD_ENTRIES.size() + getLineOffset();
+
+        // add new teams
+        for (int i = 1; i <= scoreboardLine; i++) {
+            addScoreboardTeam(i);
+        }
+
+        String replacedLine;
+
+        for (String cleanLine : SCOREBOARD_ENTRIES) {
+            if (scoreboardLine <= 0) {
+                break;
+            }
+
+            if (cleanLine.contains("%team1_members%") || cleanLine.contains("%team2_members%")) {
+
+                // team member list placeholder management:
+
+                Team placeholderTeam;
+
+                // set the current placeholder team
+                if (cleanLine.contains("%team1_members%")) {
+                    placeholderTeam = team1;
+                } else {
+                    placeholderTeam = team2;
+                }
+
+                // check if there is no one in the team at the moment
+                if (placeholderTeam.getMembers().isEmpty()) {
+                    continue;
+                }
+
+                int playerCounter = 0;
+
+                // list all team members
+                for (MWPlayer player : placeholderTeam.getMembers()) {
+
+                    // limit check
+                    if (playerCounter >= MEMBER_LIST_MAX_SIZE) {
+                        break;
+                    }
+
+                    String playerName = player.getPlayer().getName();
+                    String teamColor = placeholderTeam.getColor();
+
+                    replacedLine = MEMBER_LIST_STYLE.replace("%playername%", playerName)
+                            .replace("%team_color%", teamColor);
+                    teams.get(scoreboardLine).setPrefix(replacedLine);
+
+                    playerCounter++;
+                    scoreboardLine--;
+                }
+
+            } else {
+
+                // normal placeholders management:
+
+                replacedLine = replaceScoreboardPlaceholders(cleanLine);
+                teams.get(scoreboardLine).setPrefix(replacedLine);
+
+                scoreboardLine--;
+            }
+        }
     }
 
-    private String rep(String entry) {
-        return replaceTeam1(replaceTeam2(replaceTime(entry)));
+    /**
+     * This method calculates the offset lines based of the amount of players
+     * and the using of the member-list placeholders for both teams.
+     *
+     * @return (int) the amount of offset lines
+     */
+    private int getLineOffset() {
+
+        int team1ListSize = 0;
+        int team2ListSize = 0;
+
+        if (isTeam1ListUsed) {
+            team1ListSize = Math.min(team1.getMembers().size(), MEMBER_LIST_MAX_SIZE);
+            team1ListSize--;
+        }
+
+        if (isTeam2ListUsed) {
+            team2ListSize = Math.min(team2.getMembers().size(), MEMBER_LIST_MAX_SIZE);
+            team2ListSize--;
+        }
+
+        return team1ListSize + team2ListSize;
     }
 
+    /**
+     * This method deletes the old Scoreboard object, if one exists.
+     */
+    public void removeScoreboard() {
+
+        if (obj != null) {
+            obj.unregister();
+            obj = null;
+        }
+
+        if (!teams.isEmpty()) {
+            teams.forEach((k, v) -> v.unregister());
+            teams.clear();
+        }
 
-    private String replaceTeam2(String str) {
-        return str.replace("%team2%", game.getTeam2().getFullname())
-                .replace("%team2_amount%", "" + game.getTeam2().getMembers().size())
-                .replace("%team2_color%", game.getTeam2().getColorCode());
     }
 
-    private String replaceTeam1(String str) {
-        return str.replace("%team1%", game.getTeam1().getFullname())
-                .replace("%team1_amount%", "" + game.getTeam1().getMembers().size())
-                .replace("%team1_color%", game.getTeam1().getColorCode());
+    /**
+     * This method deletes the current scoreboard and creates a new one.
+     */
+    public void resetScoreboard() {
+        removeScoreboard();
+        createScoreboard();
     }
 
-    private String replaceTime(String str) {
-        return str.replace("%time%", "" + game.getTimer().getSeconds() / 60);
+    /**
+     * This method replaces the placeholders with the current value.
+     * @param text (String) the original config String
+     * @return the replaced text as String
+     */
+    private String replaceScoreboardPlaceholders(String text) {
+
+        String time = Integer.toString(game.getTimer().getSeconds() / 60);
+
+
+        text = ChatColor.translateAlternateColorCodes('&', text);
+
+        text = text.replace("%team1%", team1.getFullname());
+        text = text.replace("%team2%", team2.getFullname());
+
+        text = text.replace("%team1_color%", team1.getColor());
+        text = text.replace("%team2_color%", team2.getColor());
+
+        text = text.replace("%team1_amount%", Integer.toString(team1.getMembers().size()));
+        text = text.replace("%team2_amount%", Integer.toString(team2.getMembers().size()));
+
+        text = text.replace("%arena_name%", arena.getDisplayName());
+
+        text = text.replace("%time%", time);
+
+        return text;
     }
+
+
 }

+ 2 - 8
missilewars-plugin/src/main/java/de/butzlabben/missilewars/util/version/VersionUtil.java

@@ -21,9 +21,7 @@ package de.butzlabben.missilewars.util.version;
 import de.butzlabben.missilewars.Logger;
 import de.butzlabben.missilewars.MessageConfig;
 import de.butzlabben.missilewars.wrapper.game.Team;
-import java.lang.reflect.Method;
 import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
 import org.bukkit.Location;
 import org.bukkit.Material;
 import org.bukkit.Sound;
@@ -32,6 +30,8 @@ import org.bukkit.entity.Player;
 import org.bukkit.inventory.ItemStack;
 import org.bukkit.inventory.meta.ItemMeta;
 
+import java.lang.reflect.Method;
+
 /**
  * @author Butzlabben
  * @since 14.08.2018
@@ -106,12 +106,6 @@ public class VersionUtil {
         }
     }
 
-    public static void setScoreboardTeamColor(org.bukkit.scoreboard.Team team, ChatColor color) {
-        if (VersionUtil.getVersion() >= 12) {
-            team.setColor(color);
-        }
-    }
-
     public static Material getFireball() {
         if (getVersion() < 13)
             return Material.valueOf("FIREBALL");

+ 6 - 10
missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/Arena.java

@@ -26,22 +26,18 @@ import de.butzlabben.missilewars.wrapper.geometry.Plane;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.RequiredArgsConstructor;
-import lombok.ToString;
+
+import lombok.*;
 import org.bukkit.Location;
 import org.bukkit.util.Vector;
 
-@Data
-@ToString
-@AllArgsConstructor
 @RequiredArgsConstructor
+@AllArgsConstructor
+@Data
 @Builder(toBuilder = true)
 public class Arena {
 
-    private String name = "arena";
+    private String name = "arena0";
     @SerializedName("display_name") private String displayName = "&eDefault map";
     @SerializedName("display_material") private String displayMaterial = "STONE";
     @SerializedName("template_world") private String templateWorld = "default_map";
@@ -59,7 +55,7 @@ public class Arena {
     @SerializedName("save_statistics") private boolean saveStatistics = true;
     @SerializedName("fall_protection") private FallProtectionConfiguration fallProtection = new FallProtectionConfiguration();
     @SerializedName("money") private MoneyConfiguration money = new MoneyConfiguration();
-    @SerializedName("intervals") private Map<Integer, Integer> intervals = new HashMap<Integer, Integer>() {{
+    @SerializedName("intervals") private Map<Integer, Integer> intervals = new HashMap<>() {{
         put(1, 15);
         put(2, 20);
         put(4, 25);

+ 19 - 27
missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/game/Team.java

@@ -26,7 +26,6 @@ import de.butzlabben.missilewars.util.version.ColorConverter;
 import de.butzlabben.missilewars.util.version.VersionUtil;
 import de.butzlabben.missilewars.wrapper.event.GameEndEvent;
 import de.butzlabben.missilewars.wrapper.player.MWPlayer;
-import java.util.ArrayList;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.Setter;
@@ -38,7 +37,8 @@ import org.bukkit.Material;
 import org.bukkit.entity.Player;
 import org.bukkit.inventory.ItemStack;
 import org.bukkit.inventory.meta.LeatherArmorMeta;
-import org.bukkit.scoreboard.Scoreboard;
+
+import java.util.ArrayList;
 
 /**
  * @author Butzlabben
@@ -69,52 +69,44 @@ public class Team {
             return game.getTeam2();
         return game.getTeam1();
     }
-
-    @SuppressWarnings("deprecation")
-    public boolean removeMember(MWPlayer player) {
-        if (!isMember(player))
-            return false;
+    
+    public void removeMember(MWPlayer player) {
+        if (!isMember(player)) return;
 
         Player p = player.getPlayer();
         player.setTeam(null);
-        if (p != null) {
-            if (scoreboardTeam.hasPlayer(p))
-                scoreboardTeam.removePlayer(p);
 
-            game.getScoreboard().getTeam("2Guest§7").addPlayer(p);
+        if (p != null) {
             p.setDisplayName("§7" + p.getName() + "§r");
         }
-        return members.removeIf(mp -> mp.getUUID().equals(player.getUUID()));
-    }
 
-    @SuppressWarnings("deprecation")
+        members.removeIf(mp -> mp.getUUID().equals(player.getUUID()));
+
+        game.getScoreboardManager().resetScoreboard();
+        p.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard());
+    }
+    
     public void addMember(MWPlayer player) {
-        if (isMember(player))
-            return;
+        if (isMember(player)) return;
+
+        // Already in a team?
         if (player.getTeam() != null) {
             player.getTeam().removeMember(player);
         }
+
         Player p = player.getPlayer();
         if (p == null) {
             Logger.WARN.log("Could not add player " + player.getUUID().toString() + " to a team because he went offline");
             return;
         }
+
         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.getInventory().setArmorContents(getTeamArmor());
-    }
-
-    public org.bukkit.scoreboard.Team getSBTeam() {
-        return scoreboardTeam;
-    }
 
-    public void setSBTeam(org.bukkit.scoreboard.Team team) {
-        scoreboardTeam = team;
+        game.getScoreboardManager().updateScoreboard();
+        p.setScoreboard(game.getScoreboard());
     }
 
     public String getFullname() {