浏览代码

Merge branch 'master' into refactoring

RedstoneFuture 3 年之前
父节点
当前提交
916959900b
共有 19 个文件被更改,包括 616 次插入332 次删除
  1. 0 1
      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. 107 57
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/game/Game.java
  5. 6 11
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/listener/EndListener.java
  6. 56 55
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/listener/GameListener.java
  7. 23 14
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/listener/LobbyListener.java
  8. 5 17
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/listener/PlayerListener.java
  9. 202 26
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/util/ScoreboardManager.java
  10. 2 8
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/util/version/VersionUtil.java
  11. 8 14
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/Arena.java
  12. 2 2
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/FireballConfiguration.java
  13. 33 0
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/GameRespawnConfiguration.java
  14. 33 0
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/GameSpawnConfiguration.java
  15. 7 7
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/MissileConfiguration.java
  16. 3 3
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/MoneyConfiguration.java
  17. 3 3
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/abstracts/arena/ShieldConfiguration.java
  18. 56 56
      missilewars-plugin/src/main/java/de/butzlabben/missilewars/wrapper/game/Team.java
  19. 二进制
      missilewars-plugin/src/main/resources/MissileWars-Arena.zip

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

+ 107 - 57
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,9 +90,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());
@@ -134,34 +131,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");
 
@@ -185,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) {
@@ -200,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;
@@ -208,6 +183,12 @@ public class Game {
 
         FightStats.checkTables();
         Logger.DEBUG.log("Fights: " + fights);
+
+        createGameItems();
+    }
+
+    public Scoreboard getScoreboard() {
+        return scoreboardManager.board;
     }
 
     public void startGame() {
@@ -295,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())
@@ -390,25 +370,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));
 
     }
 

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

+ 56 - 55
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,68 +226,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 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");

+ 8 - 14
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;

+ 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 - 56
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
@@ -58,6 +58,7 @@ public class Team {
     private transient boolean won;
     private transient org.bukkit.scoreboard.Team scoreboardTeam;
     private transient int currentInterval = 0;
+    ItemStack[] teamArmor;
 
     public ArrayList<MWPlayer> getMembers() {
         return members;
@@ -68,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);
-        setTeamArmor(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() {
@@ -126,34 +119,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) {

二进制
missilewars-plugin/src/main/resources/MissileWars-Arena.zip