فهرست منبع

Merge branch 'master' into improvement/game-end-message

RedstoneFuture 3 سال پیش
والد
کامیت
a62c66f2aa
26فایلهای تغییر یافته به همراه844 افزوده شده و 503 حذف شده
  1. 1 2
      missilewars-plugin/pom.xml
  2. 66 56
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/Config.java
  3. 4 2
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/cmd/UserCommands.java
  4. 100 46
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/game/Game.java
  5. 13 5
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/game/timer/EndTimer.java
  6. 32 36
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/game/timer/GameTimer.java
  7. 32 39
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/game/timer/LobbyTimer.java
  8. 6 11
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/listener/EndListener.java
  9. 52 44
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/listener/GameListener.java
  10. 23 14
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/listener/LobbyListener.java
  11. 4 11
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/listener/PlayerListener.java
  12. 151 0
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/util/GameRandomizer.java
  13. 0 114
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/util/Randomizer.java
  14. 202 26
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/util/ScoreboardManager.java
  15. 2 8
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/util/version/VersionUtil.java
  16. 9 15
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/Arena.java
  17. 2 2
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/FireballConfiguration.java
  18. 33 0
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/GameRespawnConfiguration.java
  19. 33 0
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/GameSpawnConfiguration.java
  20. 7 7
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/MissileConfiguration.java
  21. 3 3
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/MoneyConfiguration.java
  22. 3 3
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/ShieldConfiguration.java
  23. 56 55
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/game/Team.java
  24. 6 0
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/missile/Missile.java
  25. 4 4
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/player/MWPlayer.java
  26. BIN
      missilewars-plugin/src/main/resources/MissileWars-Arena.zip

+ 1 - 2
missilewars-plugin/pom.xml

@@ -26,7 +26,7 @@
         <version>1.0</version>
     </parent>
 
-    <version>4.1.2</version>
+    <version>4.2.0</version>
 
     <modelVersion>4.0.0</modelVersion>
 
@@ -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()));

+ 100 - 46
missilewars-plugin/src/main/java/de/butzlabben/missilewars/game/Game.java

@@ -86,9 +86,10 @@ 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;
+    private ItemStack customPickaxe;
 
     public Game(Lobby lobby) {
         Logger.BOOT.log("Loading game " + lobby.getDisplayName());
@@ -126,34 +127,9 @@ public class Game {
 
         team1 = new Team(lobby.getTeam1Name(), lobby.getTeam1Color(), this);
         team2 = new Team(lobby.getTeam2Name(), lobby.getTeam2Color(), this);
-
-        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);
+      
+        team1.createTeamArmor();
+        team2.createTeamArmor();
 
         Logger.DEBUG.log("Registering, teleporting, etc. all players");
 
@@ -177,6 +153,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) {
@@ -192,6 +169,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;
@@ -200,6 +179,12 @@ public class Game {
 
         FightStats.checkTables();
         Logger.DEBUG.log("Fights: " + fights);
+
+        createGameItems();
+    }
+
+    public Scoreboard getScoreboard() {
+        return scoreboardManager.board;
     }
 
     public void startGame() {
@@ -279,7 +264,6 @@ public class Game {
 
         timer = new EndTimer(this);
         bt = Bukkit.getScheduler().runTaskTimer(MissileWars.getInstance(), timer, 5, 20);
-        scoreboardManager.removeScoreboard();
 
         // Change MOTD
         if (!Config.isMultipleLobbies()) {
@@ -369,25 +353,95 @@ public class Game {
         }
 
         player.teleport(mwPlayer.getTeam().getSpawn());
-        ItemStack air = new ItemStack(Material.AIR);
-        ItemStack bow = new ItemStack(Material.BOW);
-        bow.addEnchantment(Enchantment.ARROW_FIRE, 1);
-        bow.addEnchantment(Enchantment.ARROW_DAMAGE, 1);
-        bow.addEnchantment(Enchantment.ARROW_KNOCKBACK, 1);
-        ItemMeta im = bow.getItemMeta();
-        im.addEnchant(Enchantment.DAMAGE_ALL, 6, true);
-        bow.setItemMeta(im);
-        VersionUtil.setUnbreakable(bow);
-
-        player.getInventory().setItem(0, air);
-        player.getInventory().setItem(8, air);
-        player.getInventory().addItem(bow);
-        mwPlayer.getTeam().setTeamArmor(player);
+
+        sendGameItems(player, false);
+        setPlayerAttributes(player);
+
+        playerTasks.put(player.getUniqueId(),
+                Bukkit.getScheduler().runTaskTimer(MissileWars.getInstance(), mwPlayer, 0, 20));
+
+    }
+
+    /**
+     * This method is used to create the game items for the player kit.
+     */
+    private void createGameItems() {
+
+        // Will it be used ?
+        if (this.getArena().getSpawn().isSendBow() || this.getArena().getRespawn().isSendBow()) {
+
+            ItemStack bow = new ItemStack(Material.BOW);
+            bow.addEnchantment(Enchantment.ARROW_FIRE, 1);
+            bow.addEnchantment(Enchantment.ARROW_DAMAGE, 1);
+            bow.addEnchantment(Enchantment.ARROW_KNOCKBACK, 1);
+            ItemMeta im = bow.getItemMeta();
+            im.addEnchant(Enchantment.DAMAGE_ALL, 6, true);
+            bow.setItemMeta(im);
+            VersionUtil.setUnbreakable(bow);
+            this.customBow = bow;
+        }
+
+        // Will it be used ?
+        if (this.getArena().getSpawn().isSendPickaxe() || this.getArena().getRespawn().isSendPickaxe()) {
+
+            ItemStack pickaxe = new ItemStack(Material.IRON_PICKAXE);
+            VersionUtil.setUnbreakable(pickaxe);
+            this.customPickaxe = pickaxe;
+        }
+
+    }
+
+    /**
+     * This method gives the player the starter item set, based on the config.yml
+     * configuration for spawn and respawn.
+     *
+     * @param player the target player
+     * @param isRespawn true, if the player should receive it after a respawn
+     */
+    public void sendGameItems(Player player, boolean isRespawn) {
+
+        // clear inventory
+        player.getInventory().clear();
+
+        // send armor
+        ItemStack[] armor = getPlayer(player).getTeam().getTeamArmor();
+        player.getInventory().setArmorContents(armor);
+
+        // send kit items
+        if (isRespawn) {
+
+            if (this.getArena().getRespawn().isSendBow()) {
+                player.getInventory().addItem(this.customBow);
+            }
+
+            if (this.getArena().getRespawn().isSendPickaxe()) {
+                player.getInventory().addItem(this.customPickaxe);
+            }
+
+        } else {
+
+            if (this.getArena().getSpawn().isSendBow()) {
+                player.getInventory().addItem(this.customBow);
+            }
+
+            if (this.getArena().getSpawn().isSendPickaxe()) {
+                player.getInventory().addItem(this.customPickaxe);
+            }
+
+        }
+
+    }
+
+    /**
+     * This method sets the player attributes (game mode, level, enchantments, ...).
+     *
+     * @param player the target player
+     */
+    public void setPlayerAttributes(Player player) {
+
         player.setGameMode(GameMode.SURVIVAL);
         player.setLevel(0);
         player.setFireTicks(0);
-        playerTasks.put(player.getUniqueId(),
-                Bukkit.getScheduler().runTaskTimer(MissileWars.getInstance(), mwPlayer, 0, 20));
 
     }
 

+ 13 - 5
missilewars-plugin/src/main/java/de/butzlabben/missilewars/game/timer/EndTimer.java

@@ -34,11 +34,19 @@ public class EndTimer extends Timer {
 
     @Override
     public void tick() {
-        if (seconds == 20)
-            broadcast(MessageConfig.getMessage("game_starts_new_in").replace("%seconds%", "" + seconds));
-        else if (seconds == 0)
-            getGame().reset();
-        --seconds;
+
+        switch(seconds) {
+            case 20:
+                broadcast(MessageConfig.getMessage("game_starts_new_in").replace("%seconds%", Integer.toString(seconds)));
+                break;
+            case 0:
+                getGame().reset();
+                break;
+            default:
+                break;
+        }
+
+        seconds--;
     }
 
 }

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

@@ -34,43 +34,39 @@ public class GameTimer extends Timer {
 
     @Override
     public void tick() {
-        if (seconds == 7200) {
-            broadcast(MessageConfig.getMessage("game_ends_in_minutes").replace("%minutes%", "120"));
-        } else if (seconds == 5400) {
-            broadcast(MessageConfig.getMessage("game_ends_in_minutes").replace("%minutes%", "90"));
-        } else if (seconds == 3600) {
-            broadcast(MessageConfig.getMessage("game_ends_in_minutes").replace("%minutes%", "60"));
-        } else if (seconds == 1800) {
-            broadcast(MessageConfig.getMessage("game_ends_in_minutes").replace("%minutes%", "30"));
-        } else if (seconds == 1200) {
-            broadcast(MessageConfig.getMessage("game_ends_in_minutes").replace("%minutes%", "20"));
-        } else if (seconds == 600) {
-            broadcast(MessageConfig.getMessage("game_ends_in_minutes").replace("%minutes%", "10"));
-        } else if (seconds == 300) {
-            broadcast(MessageConfig.getMessage("game_ends_in_minutes").replace("%minutes%", "5"));
-        } else if (seconds == 180) {
-            broadcast(MessageConfig.getMessage("game_ends_in_minutes").replace("%minutes%", "3"));
-        } else if (seconds == 60) {
-            broadcast(MessageConfig.getMessage("game_ends_in_seconds").replace("%seconds%", "60"));
-        } else if (seconds == 30) {
-            broadcast(MessageConfig.getMessage("game_ends_in_seconds").replace("%seconds%", "30"));
-        } else if (seconds == 10) {
-            broadcast(MessageConfig.getMessage("game_ends_in_seconds").replace("%seconds%", "10"));
-        } else if (seconds == 5) {
-            broadcast(MessageConfig.getMessage("game_ends_in_seconds").replace("%seconds%", "5"));
-        } else if (seconds == 4) {
-            broadcast(MessageConfig.getMessage("game_ends_in_seconds").replace("%seconds%", "4"));
-        } else if (seconds == 3) {
-            broadcast(MessageConfig.getMessage("game_ends_in_seconds").replace("%seconds%", "3"));
-        } else if (seconds == 2) {
-            broadcast(MessageConfig.getMessage("game_ends_in_seconds").replace("%seconds%", "2"));
-        } else if (seconds == 1) {
-            broadcast(MessageConfig.getMessage("game_ends_in_seconds").replace("%seconds%", "1"));
-        } else if (seconds == 0) {
-            getGame().stopGame();
+
+        switch(seconds) {
+            case 7200:
+            case 5400:
+            case 3600:
+            case 1800:
+            case 1200:
+            case 600:
+            case 300:
+            case 180:
+                broadcast(MessageConfig.getMessage("game_ends_in_minutes").replace("%minutes%", Integer.toString(seconds/60)));
+                break;
+            case 60:
+            case 30:
+            case 10:
+            case 5:
+            case 4:
+            case 3:
+            case 2:
+            case 1:
+                broadcast(MessageConfig.getMessage("game_ends_in_seconds").replace("%seconds%", Integer.toString(seconds)));
+                break;
+            case 0:
+                getGame().stopGame();
+                break;
+            default:
+                break;
         }
-        if (seconds % 10 == 0)
+
+        if (seconds % 10 == 0) {
             getGame().getScoreboardManager().updateInGameScoreboard();
-        --seconds;
+        }
+
+        seconds--;
     }
 }

+ 32 - 39
missilewars-plugin/src/main/java/de/butzlabben/missilewars/game/timer/LobbyTimer.java

@@ -25,6 +25,7 @@ import de.butzlabben.missilewars.util.version.VersionUtil;
 import de.butzlabben.missilewars.wrapper.abstracts.Arena;
 import de.butzlabben.missilewars.wrapper.abstracts.MapChooseProcedure;
 import de.butzlabben.missilewars.wrapper.player.MWPlayer;
+
 import java.util.Map;
 import java.util.Optional;
 
@@ -71,48 +72,40 @@ public class LobbyTimer extends Timer implements Runnable {
             remaining = 90;
             broadcast(MessageConfig.getMessage("not_enough_players"));
         }
-        if (seconds == 120) {
-            broadcast(MessageConfig.getMessage("game_starts_in").replace("%seconds%", "120"));
-            playPling();
-        } else if (seconds == 60) {
-            broadcast(MessageConfig.getMessage("game_starts_in").replace("%seconds%", "60"));
-            playPling();
-        } else if (seconds == 30) {
-            broadcast(MessageConfig.getMessage("game_starts_in").replace("%seconds%", "30"));
-            playPling();
-        } else if (seconds == 10) {
-            checkVote();
-            broadcast(MessageConfig.getMessage("game_starts_in").replace("%seconds%", "10"));
-            playPling();
-        } else if (seconds == 5) {
-            broadcast(MessageConfig.getMessage("game_starts_in").replace("%seconds%", "5"));
-            playPling();
-        } else if (seconds == 4) {
-            broadcast(MessageConfig.getMessage("game_starts_in").replace("%seconds%", "4"));
-            playPling();
-        } else if (seconds == 3) {
-            broadcast(MessageConfig.getMessage("game_starts_in").replace("%seconds%", "3"));
-            playPling();
-        } else if (seconds == 2) {
-            broadcast(MessageConfig.getMessage("game_starts_in").replace("%seconds%", "2"));
-            playPling();
-        } else if (seconds == 1) {
-            broadcast(MessageConfig.getMessage("game_starts_in").replace("%seconds%", "1"));
-            playPling();
 
-        } else if (seconds == 0) {
-            int diff = size1 - size2;
-            if (diff >= 2 || diff <= -2) {
-                broadcast(MessageConfig.getMessage("teams_unequal"));
-                seconds = startTime;
+        switch(seconds) {
+            case 120:
+            case 60:
+            case 30:
+            case 5:
+            case 4:
+            case 3:
+            case 2:
+            case 1:
+                broadcast(MessageConfig.getMessage("game_starts_in").replace("%seconds%", Integer.toString(seconds)));
+                playPling();
+                break;
+            case 10:
+                checkVote();
+                broadcast(MessageConfig.getMessage("game_starts_in").replace("%seconds%", Integer.toString(seconds)));
+                playPling();
+                break;
+            case 0:
+                int diff = size1 - size2;
+                if (diff >= 2 || diff <= -2) {
+                    broadcast(MessageConfig.getMessage("teams_unequal"));
+                    seconds = startTime;
+                    return;
+                }
+                broadcast(MessageConfig.getMessage("game_starts"));
+                playPling();
+                getGame().startGame();
                 return;
-            }
-            broadcast(MessageConfig.getMessage("game_starts"));
-            playPling();
-            getGame().startGame();
-            return;
+            default:
+                break;
         }
-        --seconds;
+
+        seconds--;
     }
 
     private void playPling() {

+ 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())

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

@@ -50,7 +50,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;
 
 import java.util.Objects;
@@ -68,8 +67,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());
@@ -89,8 +88,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())
@@ -117,12 +116,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();
@@ -161,8 +158,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);
@@ -172,11 +168,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();
@@ -185,18 +179,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();
@@ -209,10 +205,9 @@ public class GameListener extends GameBoundListener {
 
     @EventHandler
     public void onDamage(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();
@@ -234,68 +229,81 @@ 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;
 
-        Team t = Objects.requireNonNull(getGame().getPlayer(e.getPlayer())).getTeam();
+        Game game = getGame();
+        Player player = e.getPlayer();
+
+        Team t = Objects.requireNonNull(getGame().getPlayer(player)).getTeam();
         if (t != null) {
             e.setRespawnLocation(t.getSpawn());
             FallProtectionConfiguration fallProtection = getGame().getArena().getFallProtection();
             if (fallProtection.isEnabled())
-                new RespawnGoldBlock(e.getPlayer(), fallProtection.getDuration(), fallProtection.isMessageOnlyOnStart(), getGame());
+                new RespawnGoldBlock(player, fallProtection.getDuration(), fallProtection.isMessageOnlyOnStart(), getGame());
         } else {
             e.setRespawnLocation(getGame().getArena().getSpectatorSpawn());
         }
+
+        game.sendGameItems(player, true);
+        game.setPlayerAttributes(player);
     }
 
     @EventHandler
     public void onDeath(PlayerDeathEvent e) {
-        if (!isInGameWorld(e.getEntity().getLocation()))
-            return;
-        Game game = getGame();
 
+        // check if the player is in a game world
+        if (!isInGameWorld(e.getEntity().getLocation())) return;
+
+        Game game = getGame();
         Player p = e.getEntity();
-        e.setDeathMessage(MessageConfig.getNativeMessage("died").replace("%player%", p.getDisplayName()));
+
+        e.setDeathMessage(null);
+        // delete vanilla death message
+        String deathBroadcastMessage = null;
+
         MWPlayer player = getGame().getPlayer(p);
         assert player != null;
 
         if (game.getArena().isAutoRespawn()) Bukkit.getScheduler().runTaskLater(MissileWars.getInstance(), () -> p.spigot().respawn(), 20L);
 
+        // spectator respawn for people there are not in a team
         if (player.getTeam() == null) {
             p.setHealth(p.getMaxHealth());
             p.teleport(getGame().getArena().getSpectatorSpawn());
-            e.setDeathMessage(null);
             return;
         }
 
-        p.setGameMode(GameMode.SURVIVAL);
-        if (p.getLastDamageCause() != null)
-            if (p.getLastDamageCause().getCause() == EntityDamageEvent.DamageCause.BLOCK_EXPLOSION
-                    || p.getLastDamageCause().getCause() == EntityDamageEvent.DamageCause.ENTITY_EXPLOSION) {
-                e.setDeathMessage(
-                        MessageConfig.getNativeMessage("died_explosion").replace("%player%", p.getDisplayName()));
+        // check the death cause for choice the death message
+        if (p.getLastDamageCause() != null) {
+
+            EntityDamageEvent.DamageCause damageCause = p.getLastDamageCause().getCause();
+
+            if (damageCause == EntityDamageEvent.DamageCause.BLOCK_EXPLOSION || damageCause == EntityDamageEvent.DamageCause.ENTITY_EXPLOSION) {
+                deathBroadcastMessage = MessageConfig.getNativeMessage("died_explosion").replace("%player%", p.getDisplayName());
+            } else {
+                deathBroadcastMessage = MessageConfig.getNativeMessage("died").replace("%player%", p.getDisplayName());
             }
+        }
 
-        String msg = e.getDeathMessage();
-        e.setDeathMessage(null);
-        getGame().broadcast(msg);
+        getGame().broadcast(deathBroadcastMessage);
     }
 
     @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 onInteract(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 onDamage(EntityDamageEvent e) {
-        if (isInLobbyArea(e.getEntity().getLocation())) e.setCancelled(true);
+        if (isInLobbyArea(e.getEntity().getLocation())) {
+            e.setCancelled(true);
+        }
     }
 
     @EventHandler
     public void onRespawn(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 onInventoryClick(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())

+ 4 - 11
missilewars-plugin/src/main/java/de/butzlabben/missilewars/listener/PlayerListener.java

@@ -45,8 +45,6 @@ import org.bukkit.event.inventory.InventoryClickEvent;
 import org.bukkit.event.inventory.InventoryType;
 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;
 
 /**
@@ -140,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());
 
@@ -154,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);
 

+ 151 - 0
missilewars-plugin/src/main/java/de/butzlabben/missilewars/util/GameRandomizer.java

@@ -0,0 +1,151 @@
+/*
+ * This file is part of MissileWars (https://github.com/Butzlabben/missilewars).
+ * Copyright (c) 2018-2021 Daniel Nägele.
+ *
+ * MissileWars is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MissileWars is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MissileWars.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package de.butzlabben.missilewars.util;
+
+import de.butzlabben.missilewars.Logger;
+import de.butzlabben.missilewars.game.Game;
+import de.butzlabben.missilewars.util.version.VersionUtil;
+import de.butzlabben.missilewars.wrapper.abstracts.arena.MissileConfiguration;
+import de.butzlabben.missilewars.wrapper.missile.Missile;
+import de.butzlabben.missilewars.wrapper.player.Interval;
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+
+import java.util.HashMap;
+import java.util.Random;
+
+/**
+ * @author Butzlabben
+ * @since 19.01.2018
+ */
+public class GameRandomizer {
+
+    private final MissileConfiguration missileConfiguration;
+    private final Game game;
+    private final HashMap<Interval, String> defensive = new HashMap<>();
+    private final HashMap<Interval, String> missiles = new HashMap<>();
+
+    private int totalOccurrenceMissiles = 0;
+    private int totalOccurrenceDefensive = 0;
+    private int randomizeCounter = 1;
+
+    private ItemStack shield;
+    private ItemStack arrow;
+    private ItemStack fireball;
+
+
+    public GameRandomizer(Game game) {
+        this.game = game;
+        missileConfiguration = game.getArena().getMissileConfiguration();
+
+        createDefenseItems();
+
+        // get missiles
+        for (Missile missile : missileConfiguration.getMissiles()) {
+
+            Interval interval = new Interval(totalOccurrenceMissiles, totalOccurrenceMissiles + missile.occurrence() - 1);
+            missiles.put(interval, missile.getName());
+            totalOccurrenceMissiles += missile.occurrence();
+        }
+
+        // get shield
+        int shieldOccurrence = game.getArena().getShieldConfiguration().getOccurrence();
+        Interval shield = new Interval(totalOccurrenceDefensive, totalOccurrenceDefensive + shieldOccurrence - 1);
+        totalOccurrenceDefensive += shieldOccurrence;
+        defensive.put(shield, "s");
+
+        // get arrow
+        int arrowOccurrence = game.getArena().getArrowOccurrence();
+        Interval arrow = new Interval(totalOccurrenceDefensive, totalOccurrenceDefensive + arrowOccurrence - 1);
+        totalOccurrenceDefensive += arrowOccurrence;
+        defensive.put(arrow, "a");
+
+        // get fireball
+        Interval fireball = new Interval(totalOccurrenceDefensive, totalOccurrenceDefensive + arrowOccurrence - 1);
+        totalOccurrenceDefensive += arrowOccurrence;
+        defensive.put(fireball, "f");
+    }
+
+    public ItemStack getRandomItem() {
+        Random randomizer = new Random();
+        int random;
+
+        ItemStack itemStack = null;
+
+        // switch between type of "items":
+        // after 2 occurrence items, you get one defensive item
+        if (randomizeCounter == 2) {
+            randomizeCounter = 0;
+            random = randomizer.nextInt(totalOccurrenceDefensive);
+            
+            for (Interval interval : defensive.keySet()) {
+                if (interval.isIn(random)) {
+
+                    switch (defensive.get(interval)) {
+                        case "s": return shield;
+                        case "a": return arrow;
+                        case "f": return fireball;
+                        default: return null;
+                    }
+
+                }
+            }
+        } else {
+            random = randomizer.nextInt(totalOccurrenceMissiles);
+            
+            for (Interval interval : missiles.keySet()) {
+                if (interval.isIn(random)) {
+                    String randomItem = missiles.get(interval);
+                    Missile missile = missileConfiguration.getMissileFromName(randomItem);
+
+                    if (missile != null) {
+                        itemStack = missile.getItem();
+                    } else
+                        Logger.DEBUG.log("There wasn't a missile found, when giving out items");
+                    randomizeCounter++;
+                }
+            }
+        }
+        return itemStack;
+    }
+
+    /**
+     * This method creates the item stacks for the defense random-items.
+     */
+    private void createDefenseItems() {
+
+        // create MW shield
+        shield = new ItemStack(VersionUtil.getSnowball());
+        ItemMeta shieldMeta = shield.getItemMeta();
+        shieldMeta.setDisplayName(game.getArena().getShieldConfiguration().getName());
+        shield.setItemMeta(shieldMeta);
+
+        // create MW arrow
+        arrow = new ItemStack(Material.ARROW, 3);
+
+        // create MW fireball
+        fireball = new ItemStack(VersionUtil.getFireball());
+        ItemMeta fireballMeta = fireball.getItemMeta();
+        fireballMeta.setDisplayName(game.getArena().getFireballConfiguration().getName());
+        fireball.setItemMeta(fireballMeta);
+
+    }
+
+}

+ 0 - 114
missilewars-plugin/src/main/java/de/butzlabben/missilewars/util/Randomizer.java

@@ -1,114 +0,0 @@
-/*
- * This file is part of MissileWars (https://github.com/Butzlabben/missilewars).
- * Copyright (c) 2018-2021 Daniel Nägele.
- *
- * MissileWars is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * MissileWars is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with MissileWars.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-package de.butzlabben.missilewars.util;
-
-import de.butzlabben.missilewars.Logger;
-import de.butzlabben.missilewars.game.Game;
-import de.butzlabben.missilewars.util.version.VersionUtil;
-import de.butzlabben.missilewars.wrapper.abstracts.arena.MissileConfiguration;
-import de.butzlabben.missilewars.wrapper.missile.Missile;
-import de.butzlabben.missilewars.wrapper.player.Interval;
-import java.util.HashMap;
-import java.util.Random;
-import org.bukkit.Material;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.ItemMeta;
-
-/**
- * @author Butzlabben
- * @since 19.01.2018
- */
-public class Randomizer {
-
-    private final MissileConfiguration missileConfiguration;
-    private final Game game;
-    private final HashMap<Interval, String> defensive = new HashMap<>();
-    private final HashMap<Interval, String> missiles = new HashMap<>();
-
-    private int allMissiles = 0;
-    private int allDefensives = 0;
-    private int count = 1;
-
-    public Randomizer(Game game) {
-        this.game = game;
-        missileConfiguration = game.getArena().getMissileConfiguration();
-        for (Missile missile : missileConfiguration.getMissiles()) {
-            Interval i = new Interval(allMissiles, allMissiles + missile.occurrence() - 1);
-            missiles.put(i, missile.getName());
-            allMissiles += missile.occurrence();
-        }
-
-        int shieldOccurrence = game.getArena().getShieldConfiguration().getOccurrence();
-        Interval shield = new Interval(allDefensives, allDefensives + shieldOccurrence - 1);
-        allDefensives += shieldOccurrence;
-        defensive.put(shield, "s");
-
-        int arrowOccurrence = game.getArena().getArrowOccurrence();
-        Interval arrow = new Interval(allDefensives, allDefensives + arrowOccurrence - 1);
-        allDefensives += arrowOccurrence;
-        defensive.put(arrow, "a");
-
-        Interval fireball = new Interval(allDefensives, allDefensives + arrowOccurrence - 1);
-        allDefensives += arrowOccurrence;
-        defensive.put(fireball, "f");
-    }
-
-    public ItemStack createItem() {
-        ItemStack is = null;
-        ItemMeta im;
-        Random r = new Random();
-        if (count == 2) {
-            count = 0;
-            int random = r.nextInt(allDefensives);
-            for (Interval i : defensive.keySet()) {
-                if (i.isIn(random)) {
-                    String to = defensive.get(i);
-                    if (to.equals("s")) {
-                        is = new ItemStack(VersionUtil.getSnowball());
-                        im = is.getItemMeta();
-                        im.setDisplayName(game.getArena().getShieldConfiguration().getName());
-                    } else if (to.equals("a")) {
-                        is = new ItemStack(Material.ARROW, 3);
-                        im = is.getItemMeta();
-                    } else {
-                        is = new ItemStack(VersionUtil.getFireball());
-                        im = is.getItemMeta();
-                        im.setDisplayName(game.getArena().getFireballConfiguration().getName());
-                    }
-                    is.setItemMeta(im);
-                    return is;
-                }
-            }
-        } else {
-            int random = r.nextInt(allMissiles);
-            for (Interval i : missiles.keySet()) {
-                if (i.isIn(random)) {
-                    String to = missiles.get(i);
-                    Missile m = missileConfiguration.getMissileFromName(to);
-                    if (m != null) {
-                        is = m.getItem();
-                    } else
-                        Logger.DEBUG.log("There wasn't a missile found, when giving out items");
-                    ++count;
-                }
-            }
-        }
-        return is;
-    }
-}

+ 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");

+ 9 - 15
missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/Arena.java

@@ -20,36 +20,30 @@ package de.butzlabben.missilewars.wrapper.abstracts;
 
 import com.google.gson.annotations.SerializedName;
 import de.butzlabben.missilewars.Logger;
-import de.butzlabben.missilewars.wrapper.abstracts.arena.FallProtectionConfiguration;
-import de.butzlabben.missilewars.wrapper.abstracts.arena.FireballConfiguration;
-import de.butzlabben.missilewars.wrapper.abstracts.arena.MissileConfiguration;
-import de.butzlabben.missilewars.wrapper.abstracts.arena.MoneyConfiguration;
-import de.butzlabben.missilewars.wrapper.abstracts.arena.ShieldConfiguration;
+import de.butzlabben.missilewars.wrapper.abstracts.arena.*;
 import de.butzlabben.missilewars.wrapper.geometry.FlatArea;
 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";
     @SerializedName("auto_respawn") private boolean autoRespawn = true;
+    @SerializedName("game_spawn") private GameSpawnConfiguration spawn = new GameSpawnConfiguration();
+    @SerializedName("game_respawn") private GameRespawnConfiguration respawn = new GameRespawnConfiguration();
     @SerializedName("do_tile_drops") private boolean doTileDrops = false;
     @SerializedName("max_height") private int maxHeight = 170;
     @SerializedName("death_height") private int deathHeight = 65;
@@ -61,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);

+ 2 - 2
missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/FireballConfiguration.java

@@ -28,7 +28,7 @@ import lombok.ToString;
 @RequiredArgsConstructor
 public class FireballConfiguration {
 
-    private final String name = "&cFireball";
-    private final int occurrence = 2;
+    private String name = "Fireball";
+    private int occurrence = 2;
     @SerializedName("destroy_portal") private boolean destroysPortal = false;
 }

+ 33 - 0
missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/GameRespawnConfiguration.java

@@ -0,0 +1,33 @@
+/*
+ * This file is part of MissileWars (https://github.com/Butzlabben/missilewars).
+ * Copyright (c) 2018-2021 Daniel Nägele.
+ *
+ * MissileWars is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MissileWars is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MissileWars.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package de.butzlabben.missilewars.wrapper.abstracts.arena;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+
+@Getter
+@ToString
+@RequiredArgsConstructor
+public class GameRespawnConfiguration {
+
+    @SerializedName("send_bow") private boolean sendBow = true;
+    @SerializedName("send_pickaxe") private boolean sendPickaxe = false;
+}

+ 33 - 0
missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/GameSpawnConfiguration.java

@@ -0,0 +1,33 @@
+/*
+ * This file is part of MissileWars (https://github.com/Butzlabben/missilewars).
+ * Copyright (c) 2018-2021 Daniel Nägele.
+ *
+ * MissileWars is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MissileWars is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MissileWars.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package de.butzlabben.missilewars.wrapper.abstracts.arena;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+
+@Getter
+@ToString
+@RequiredArgsConstructor
+public class GameSpawnConfiguration {
+
+    @SerializedName("send_bow") private boolean sendBow = true;
+    @SerializedName("send_pickaxe") private boolean sendPickaxe = false;
+}

+ 7 - 7
missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/MissileConfiguration.java

@@ -40,13 +40,13 @@ public class MissileConfiguration {
 
     // TODO pretty names
 
-    private final boolean onlyBlockPlaceable = false;
-    private final boolean onlyBetweenSpawnPlaceable = false;
-    private final boolean northFacing = true;
-    private final boolean eastFacing = true;
-    private final boolean southFacing = true;
-    private final boolean westFacing = true;
-    private final List<Missile> missiles = new ArrayList<Missile>() {{
+    private boolean onlyBlockPlaceable = false;
+    private boolean onlyBetweenSpawnPlaceable = false;
+    private boolean northFacing = true;
+    private boolean eastFacing = true;
+    private boolean southFacing = true;
+    private boolean westFacing = true;
+    private List<Missile> missiles = new ArrayList<Missile>() {{
         add(new Missile("Tomahawk.schematic", "&aTomahawk", EntityType.CREEPER, 2, 2, 3));
         add(new Missile("Cruiser.schematic", "&eCruiser", EntityType.BLAZE, 2, 2, 2));
         add(new Missile("Sword.schematic", "&7Sword", EntityType.SKELETON, 2, 2, 2));

+ 3 - 3
missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/MoneyConfiguration.java

@@ -27,7 +27,7 @@ import lombok.ToString;
 @RequiredArgsConstructor
 public class MoneyConfiguration {
 
-    private final int win = 80;
-    private final int loss = 50;
-    private final int draw = 30;
+    private int win = 80;
+    private int loss = 50;
+    private int draw = 30;
 }

+ 3 - 3
missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/ShieldConfiguration.java

@@ -28,8 +28,8 @@ import lombok.ToString;
 @RequiredArgsConstructor
 public class ShieldConfiguration {
 
-    private final String name = "Shield";
-    private final String schematic = "shield.schematic";
-    private final int occurrence = 1;
+    private String name = "Shield";
+    private String schematic = "shield.schematic";
+    private int occurrence = 1;
     @SerializedName("serialized_name") private int flyTime = 20;
 }

+ 56 - 55
missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/game/Team.java

@@ -36,7 +36,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;
 
 import java.util.ArrayList;
 
@@ -58,6 +59,7 @@ public class Team {
     private transient GameResult gameResult;
     private transient org.bukkit.scoreboard.Team scoreboardTeam;
     private transient int currentInterval = 0;
+    ItemStack[] teamArmor;
 
     public ArrayList<MWPlayer> getMembers() {
         return members;
@@ -68,52 +70,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);
-        setTeamArmor(p);
-    }
-
-    public org.bukkit.scoreboard.Team getSBTeam() {
-        return scoreboardTeam;
-    }
+        p.getInventory().setArmorContents(getTeamArmor());
 
-    public void setSBTeam(org.bukkit.scoreboard.Team team) {
-        scoreboardTeam = team;
+        game.getScoreboardManager().updateScoreboard();
+        p.setScoreboard(game.getScoreboard());
     }
 
     public String getFullname() {
@@ -126,34 +120,41 @@ public class Team {
         return color;
     }
 
-    public void setTeamArmor(Player p) {
-        Color c = ColorConverter.getColorFromCode(getColorCode());
-        ItemStack is = new ItemStack(Material.LEATHER_BOOTS);
-        LeatherArmorMeta lam = (LeatherArmorMeta) is.getItemMeta();
-        lam.setColor(c);
-        is.setItemMeta(lam);
-        VersionUtil.setUnbreakable(is);
-
-        ItemStack is1 = new ItemStack(Material.LEATHER_LEGGINGS);
-        LeatherArmorMeta lam1 = (LeatherArmorMeta) is1.getItemMeta();
-        lam1.setColor(c);
-        is1.setItemMeta(lam1);
-        VersionUtil.setUnbreakable(is1);
-
-        ItemStack is2 = new ItemStack(Material.LEATHER_CHESTPLATE);
-        LeatherArmorMeta lam2 = (LeatherArmorMeta) is2.getItemMeta();
-        lam2.setColor(c);
-        is2.setItemMeta(lam2);
-        VersionUtil.setUnbreakable(is2);
-
-        ItemStack is3 = new ItemStack(Material.LEATHER_HELMET);
-        LeatherArmorMeta lam3 = (LeatherArmorMeta) is3.getItemMeta();
-        lam3.setColor(c);
-        is3.setItemMeta(lam3);
-        VersionUtil.setUnbreakable(is3);
-
-        ItemStack[] armor = new ItemStack[] {is, is1, is2, is3};
-        p.getInventory().setArmorContents(armor);
+    /**
+     * This method creates the team armor based on the team color.
+     */
+    public void createTeamArmor() {
+        Color color = ColorConverter.getColorFromCode(getColorCode());
+
+        ItemStack boots = new ItemStack(Material.LEATHER_BOOTS);
+        LeatherArmorMeta bootsMeta = (LeatherArmorMeta) boots.getItemMeta();
+        bootsMeta.setColor(color);
+        boots.setItemMeta(bootsMeta);
+        VersionUtil.setUnbreakable(boots);
+
+        ItemStack leggings = new ItemStack(Material.LEATHER_LEGGINGS);
+        LeatherArmorMeta leggingsMeta = (LeatherArmorMeta) leggings.getItemMeta();
+        leggingsMeta.setColor(color);
+        leggings.setItemMeta(leggingsMeta);
+        VersionUtil.setUnbreakable(leggings);
+
+        ItemStack chestplate = new ItemStack(Material.LEATHER_CHESTPLATE);
+        LeatherArmorMeta chestplateMeta = (LeatherArmorMeta) chestplate.getItemMeta();
+        chestplateMeta.setColor(color);
+        chestplate.setItemMeta(chestplateMeta);
+        VersionUtil.setUnbreakable(chestplate);
+
+        ItemStack helmet = new ItemStack(Material.LEATHER_HELMET);
+        LeatherArmorMeta helmetMeta = (LeatherArmorMeta) helmet.getItemMeta();
+        helmetMeta.setColor(color);
+        helmet.setItemMeta(helmetMeta);
+        VersionUtil.setUnbreakable(helmet);
+
+        teamArmor = new ItemStack[] {boots, leggings, chestplate, helmet};
+    }
+
+    public ItemStack[] getTeamArmor() {
+        return this.teamArmor;
     }
 
     public boolean isMember(MWPlayer player) {

+ 6 - 0
missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/missile/Missile.java

@@ -98,6 +98,12 @@ public class Missile {
         return egg;
     }
 
+    /**
+     * This method provides the missile spawn item based on the
+     * mob spawn item specification in the arena configuration.
+     *
+     * @return ItemStack = the spawn egg with the missile name
+     */
     public ItemStack getItem() {
         ItemStack is = new ItemStack(VersionUtil.getMonsterEgg(egg));
         if (VersionUtil.getVersion() > 10) {

+ 4 - 4
missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/player/MWPlayer.java

@@ -19,7 +19,7 @@
 package de.butzlabben.missilewars.wrapper.player;
 
 import de.butzlabben.missilewars.game.Game;
-import de.butzlabben.missilewars.util.Randomizer;
+import de.butzlabben.missilewars.util.GameRandomizer;
 import de.butzlabben.missilewars.wrapper.game.Team;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicLong;
@@ -42,7 +42,7 @@ public class MWPlayer implements Runnable {
     private final Game game;
     int i = -1;
     private Team t;
-    private Randomizer r;
+    private GameRandomizer r;
     private int period;
 
     public MWPlayer(Player player, Game game) {
@@ -82,8 +82,8 @@ public class MWPlayer implements Runnable {
         i++;
         if (i >= period) {
             if (r == null)
-                r = new Randomizer(game);
-            p.getInventory().addItem(r.createItem());
+                r = new GameRandomizer(game);
+            p.getInventory().addItem(r.getRandomItem());
             i = 0;
         }
         p.setLevel(period - i);

BIN
missilewars-plugin/src/main/resources/MissileWars-Arena.zip