Browse Source

Merge pull request #22 from RedstoneFuture/Improvements/CommandManagerV2

Switch to another Command Framework
Daniel 3 years ago
parent
commit
8a9c704f5f

+ 2 - 0
1_12/pom.xml

@@ -25,11 +25,13 @@
         <groupId>de.butzlabben</groupId>
         <groupId>de.butzlabben</groupId>
         <version>1.0</version>
         <version>1.0</version>
     </parent>
     </parent>
+
     <modelVersion>4.0.0</modelVersion>
     <modelVersion>4.0.0</modelVersion>
 
 
     <artifactId>1_12</artifactId>
     <artifactId>1_12</artifactId>
 
 
     <dependencies>
     <dependencies>
+        <!-- WorldEdit API -->
         <dependency>
         <dependency>
             <groupId>com.sk89q</groupId>
             <groupId>com.sk89q</groupId>
             <artifactId>worldedit</artifactId>
             <artifactId>worldedit</artifactId>

+ 3 - 0
1_13/pom.xml

@@ -25,12 +25,14 @@
         <groupId>de.butzlabben</groupId>
         <groupId>de.butzlabben</groupId>
         <version>1.0</version>
         <version>1.0</version>
     </parent>
     </parent>
+
     <modelVersion>4.0.0</modelVersion>
     <modelVersion>4.0.0</modelVersion>
 
 
     <artifactId>1_13</artifactId>
     <artifactId>1_13</artifactId>
 
 
     <dependencies>
     <dependencies>
         <dependency>
         <dependency>
+            <!-- WorldEdit (Bukkit) API -->
             <groupId>com.sk89q.worldedit</groupId>
             <groupId>com.sk89q.worldedit</groupId>
             <artifactId>worldedit-bukkit</artifactId>
             <artifactId>worldedit-bukkit</artifactId>
             <version>7.0.0-SNAPSHOT</version>
             <version>7.0.0-SNAPSHOT</version>
@@ -45,6 +47,7 @@
         </dependency>
         </dependency>
 
 
         <dependency>
         <dependency>
+            <!-- WorldEdit (Core) API -->
             <groupId>com.sk89q.worldedit</groupId>
             <groupId>com.sk89q.worldedit</groupId>
             <artifactId>worldedit-core</artifactId>
             <artifactId>worldedit-core</artifactId>
             <version>7.0.0-SNAPSHOT</version>
             <version>7.0.0-SNAPSHOT</version>

+ 2 - 1
1_13_FAWE/pom.xml

@@ -31,11 +31,12 @@
     <artifactId>1_13_FAWE</artifactId>
     <artifactId>1_13_FAWE</artifactId>
 
 
     <dependencies>
     <dependencies>
+        <!-- FAWE API -->
         <dependency>
         <dependency>
             <groupId>com.sk98q.worldedit</groupId>
             <groupId>com.sk98q.worldedit</groupId>
             <artifactId>FastAsnycWorldEdit</artifactId>
             <artifactId>FastAsnycWorldEdit</artifactId>
-            <scope>system</scope>
             <version>1.0</version>
             <version>1.0</version>
+            <scope>system</scope>
             <systemPath>${pom.basedir}/lib/FastAsyncWorldEdit.jar</systemPath>
             <systemPath>${pom.basedir}/lib/FastAsyncWorldEdit.jar</systemPath>
         </dependency>
         </dependency>
     </dependencies>
     </dependencies>

+ 11 - 6
missilewars-plugin/pom.xml

@@ -32,6 +32,13 @@
 
 
     <artifactId>missilewars-plugin</artifactId>
     <artifactId>missilewars-plugin</artifactId>
 
 
+    <repositories>
+        <repository>
+            <id>aikar</id>
+            <url>https://repo.aikar.co/content/groups/aikar/</url>
+        </repository>
+    </repositories>
+
     <dependencies>
     <dependencies>
         <dependency>
         <dependency>
             <groupId>de.butzlabben</groupId>
             <groupId>de.butzlabben</groupId>
@@ -66,13 +73,11 @@
             <version>2.11.0</version>
             <version>2.11.0</version>
         </dependency>
         </dependency>
 
 
-
-        <!-- https://mvnrepository.com/artifact/com.pro-crafting.mc/commandframework -->
+        <!-- https://github.com/aikar/commands -->
         <dependency>
         <dependency>
-            <groupId>com.pro-crafting.mc</groupId>
-            <artifactId>commandframework</artifactId>
-            <version>0.2.1</version>
-            <scope>compile</scope>
+            <groupId>co.aikar</groupId>
+            <artifactId>acf-paper</artifactId>
+            <version>0.5.1-SNAPSHOT</version>
         </dependency>
         </dependency>
 
 
         <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
         <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->

+ 28 - 13
missilewars-plugin/src/main/java/de/butzlabben/missilewars/MissileWars.java

@@ -18,7 +18,7 @@
 
 
 package de.butzlabben.missilewars;
 package de.butzlabben.missilewars;
 
 
-import com.pro_crafting.mc.commandframework.CommandFramework;
+import co.aikar.commands.PaperCommandManager;
 import de.butzlabben.missilewars.cmd.MWCommands;
 import de.butzlabben.missilewars.cmd.MWCommands;
 import de.butzlabben.missilewars.cmd.StatsCommands;
 import de.butzlabben.missilewars.cmd.StatsCommands;
 import de.butzlabben.missilewars.cmd.UserCommands;
 import de.butzlabben.missilewars.cmd.UserCommands;
@@ -54,7 +54,6 @@ public class MissileWars extends JavaPlugin {
 
 
     private static MissileWars instance;
     private static MissileWars instance;
     public final String version = getDescription().getVersion();
     public final String version = getDescription().getVersion();
-    private CommandFramework framework;
     private SignRepository signRepository;
     private SignRepository signRepository;
 
 
     private boolean foundFAWE;
     private boolean foundFAWE;
@@ -93,17 +92,8 @@ public class MissileWars extends JavaPlugin {
         SignRepository repository = SignRepository.load();
         SignRepository repository = SignRepository.load();
         this.signRepository = repository;
         this.signRepository = repository;
 
 
-        Bukkit.getPluginManager().registerEvents(new PlayerListener(), this);
-        Bukkit.getPluginManager().registerEvents(new ClickListener(), this);
-        Bukkit.getPluginManager().registerEvents(new ManageListener(), this);
-
-        Logger.BOOT.log("Registering commands");
-        framework = new CommandFramework(this);
-        framework.registerCommands(new MWCommands());
-        framework.registerCommands(new StatsCommands());
-        framework.registerCommands(new UserCommands());
-        // TODO make more admin commands usable with console by adding more optional arguments like game name etc.
-        framework.setInGameOnlyMessage(MessageConfig.getPrefix() + "§cYou are not a player");
+        registerEvents();
+        registerCommands();
 
 
         Arenas.load();
         Arenas.load();
         SetupUtil.checkShields();
         SetupUtil.checkShields();
@@ -142,6 +132,31 @@ public class MissileWars extends JavaPlugin {
         ConnectionHolder.close();
         ConnectionHolder.close();
     }
     }
 
 
+    /**
+     * This method registers all events of the missilewars event listener.
+     */
+    private void registerEvents() {
+        Bukkit.getPluginManager().registerEvents(new PlayerListener(), this);
+        Bukkit.getPluginManager().registerEvents(new ClickListener(), this);
+        Bukkit.getPluginManager().registerEvents(new ManageListener(), this);
+    }
+
+    /**
+     * This method loads the command manager and registers the missilewars commands.
+     */
+    private void registerCommands() {
+        Logger.BOOT.log("Registering commands");
+
+        // Using the Paper Command Manager does not mean the plugin requires Paper.
+        // It simply lets it take advantage of Paper specific features if available,
+        // such as Asynchronous Tab Completions.
+        PaperCommandManager manager = new PaperCommandManager(this);
+
+        manager.registerCommand(new MWCommands());
+        manager.registerCommand(new StatsCommands());
+        manager.registerCommand(new UserCommands());
+    }
+
     /**
     /**
      * This method checks if FAWE (FastAsyncWorldEdit) is installed.
      * This method checks if FAWE (FastAsyncWorldEdit) is installed.
      *
      *

+ 87 - 65
missilewars-plugin/src/main/java/de/butzlabben/missilewars/cmd/MWCommands.java

@@ -18,8 +18,8 @@
 
 
 package de.butzlabben.missilewars.cmd;
 package de.butzlabben.missilewars.cmd;
 
 
-import com.pro_crafting.mc.commandframework.Command;
-import com.pro_crafting.mc.commandframework.CommandArgs;
+import co.aikar.commands.BaseCommand;
+import co.aikar.commands.annotation.*;
 import de.butzlabben.missilewars.Config;
 import de.butzlabben.missilewars.Config;
 import de.butzlabben.missilewars.Logger;
 import de.butzlabben.missilewars.Logger;
 import de.butzlabben.missilewars.MessageConfig;
 import de.butzlabben.missilewars.MessageConfig;
@@ -42,12 +42,47 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.Optional;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
-public class MWCommands {
+@CommandAlias("mw|missilewars")
+public class MWCommands extends BaseCommand {
 
 
-    @Command(name = "mw.paste", usage = "/mw paste <missile>", permission = "mw.paste", description = "Pastes a missile", inGameOnly = true)
-    public void pasteCommand(CommandArgs args) {
+    @Default
+    @Description("Shows information about the MissileWars Plugin.")
+    public void mwCommand(CommandSender sender) {
+
+        sender.sendMessage(MessageConfig.getPrefix() + "MissileWars v" + MissileWars.getInstance().version + " by Butzlabben");
+
+        if (sender.hasPermission("mw.quit"))
+            sender.sendMessage(MessageConfig.getPrefix() + "/mw quit -  Quit a game");
+        if (sender.hasPermission("mw.start"))
+            sender.sendMessage(MessageConfig.getPrefix() + "/mw start - Starts the game");
+        if (sender.hasPermission("mw.stop"))
+            sender.sendMessage(MessageConfig.getPrefix() + "/mw stop - Stops the game");
+        if (sender.hasPermission("mw.restart"))
+            sender.sendMessage(MessageConfig.getPrefix() + "/mw start - Restarts the game");
+        if (sender.hasPermission("mw.appendrestart"))
+            sender.sendMessage(MessageConfig.getPrefix()
+                    + "/mw appendrestart - Appends a restart after the next game ends");
+        if (sender.hasPermission("mw.paste"))
+            sender.sendMessage(MessageConfig.getPrefix() + "/mw paste - Pastes a missile");
+        if (sender.hasPermission("mw.reload"))
+            sender.sendMessage(MessageConfig.getPrefix() + "/mw reload - Reloads configurations");
+        if (sender.hasPermission("mw.stats"))
+            sender.sendMessage(MessageConfig.getPrefix() + "/mw stats - Shows stats");
+        if (sender.hasPermission("mw.stats.recommendations"))
+            sender.sendMessage(MessageConfig.getPrefix() + "/mw stats recommendations - Shows recommendations");
+        if (sender.hasPermission("mw.stats.players"))
+            sender.sendMessage(MessageConfig.getPrefix() + "/mw stats players - Shows player list");
+        if (sender.hasPermission("mw.stats.list"))
+            sender.sendMessage(MessageConfig.getPrefix() + "/mw stats list - Lists history of games");
+    }
+
+    @Subcommand("paste")
+    @Description("Pastes a missile.")
+    @Syntax("/mw paste <missile>")
+    @CommandCompletion("@nothing")
+    @CommandPermission("mw.paste")
+    public void pasteCommand(CommandSender sender, String[] args) {
 
 
-        CommandSender sender = args.getSender();
         if (!senderIsPlayer(sender)) return;
         if (!senderIsPlayer(sender)) return;
         Player player = (Player) sender;
         Player player = (Player) sender;
 
 
@@ -57,8 +92,8 @@ public class MWCommands {
             return;
             return;
         }
         }
         StringBuilder sb = new StringBuilder();
         StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < args.length(); i++) {
-            sb.append(args.getArgs(i).replaceAll("&.", ""));
+        for (int i = 0; i < args.length; i++) {
+            sb.append(args[i].replaceAll("&.", ""));
             sb.append(" ");
             sb.append(" ");
         }
         }
         Missile m = game.getArena().getMissileConfiguration().getMissileFromName(sb.toString().trim());
         Missile m = game.getArena().getMissileConfiguration().getMissileFromName(sb.toString().trim());
@@ -70,10 +105,13 @@ public class MWCommands {
         m.paste(player, mf, game);
         m.paste(player, mf, game);
     }
     }
 
 
-    @Command(name = "mw.start", usage = "/mw start", permission = "mw.start", description = "Starts the game", inGameOnly = true)
-    public void startCommand(CommandArgs args) {
+    @Subcommand("start")
+    @Description("Starts the game.")
+    @Syntax("/mw start")
+    @CommandCompletion("@nothing")
+    @CommandPermission("mw.start")
+    public void startCommand(CommandSender sender, String[] args) {
 
 
-        CommandSender sender = args.getSender();
         if (!senderIsPlayer(sender)) return;
         if (!senderIsPlayer(sender)) return;
         Player player = (Player) sender;
         Player player = (Player) sender;
 
 
@@ -110,10 +148,13 @@ public class MWCommands {
         }
         }
     }
     }
 
 
-    @Command(name = "mw.stop", usage = "/mw stop", permission = "mw.stop", description = "Stops the game", inGameOnly = true)
-    public void stopCommand(CommandArgs args) {
+    @Subcommand("stop")
+    @Description("Stops the game.")
+    @Syntax("/mw stop")
+    @CommandCompletion("@nothing")
+    @CommandPermission("mw.stop")
+    public void stopCommand(CommandSender sender, String[] args) {
 
 
-        CommandSender sender = args.getSender();
         if (!senderIsPlayer(sender)) return;
         if (!senderIsPlayer(sender)) return;
         Player player = (Player) sender;
         Player player = (Player) sender;
 
 
@@ -126,11 +167,13 @@ public class MWCommands {
         Bukkit.getScheduler().runTask(MissileWars.getInstance(), game::stopGame);
         Bukkit.getScheduler().runTask(MissileWars.getInstance(), game::stopGame);
     }
     }
 
 
+    @Subcommand("restart")
+    @Description("Restarts the game.")
+    @Syntax("/mw restart")
+    @CommandCompletion("@nothing")
+    @CommandPermission("mw.restart")
+    public void restartCommand(CommandSender sender, String[] args) {
 
 
-    @Command(name = "mw.restart", usage = "/mw restart", permission = "mw.restart", description = "Restarts the game", inGameOnly = true)
-    public void restartCommand(CommandArgs args) {
-
-        CommandSender sender = args.getSender();
         if (!senderIsPlayer(sender)) return;
         if (!senderIsPlayer(sender)) return;
         Player player = (Player) sender;
         Player player = (Player) sender;
 
 
@@ -148,48 +191,23 @@ public class MWCommands {
         });
         });
     }
     }
 
 
-    @Command(name = "mw.appendrestart", usage = "/mw appendrestart", permission = "mw.appendrestart", description = "Appends a restart after the next game ends")
-    public void appendRestartCommand(CommandArgs args) {
-        GameManager.getInstance().getGames().values().forEach(Game::appendRestart);
-        args.getSender().sendMessage(MessageConfig.getMessage("restart_after_game"));
-    }
-
-    @Command(name = "mw", aliases = "missilewars", usage = "/mw", description = "Shows information about the MissileWars Plugin")
-    public void mwCommand(CommandArgs args) {
-
-        CommandSender sender = args.getSender();
-
-        sender.sendMessage(MessageConfig.getPrefix() + "MissileWars v" + MissileWars.getInstance().version + " by Butzlabben");
+    @Subcommand("appendrestart")
+    @Description("Appends a restart after the next game ends.")
+    @Syntax("/mw appendrestart")
+    @CommandCompletion("@nothing")
+    @CommandPermission("mw.appendrestart")
+    public void appendRestartCommand(CommandSender sender, String[] args) {
 
 
-        if (sender.hasPermission("mw.quit"))
-            sender.sendMessage(MessageConfig.getPrefix() + "/mw quit -  Quit a game");
-        if (sender.hasPermission("mw.start"))
-            sender.sendMessage(MessageConfig.getPrefix() + "/mw start - Starts the game");
-        if (sender.hasPermission("mw.stop"))
-            sender.sendMessage(MessageConfig.getPrefix() + "/mw stop - Stops the game");
-        if (sender.hasPermission("mw.restart"))
-            sender.sendMessage(MessageConfig.getPrefix() + "/mw start - Restarts the game");
-        if (sender.hasPermission("mw.appendrestart"))
-            sender.sendMessage(MessageConfig.getPrefix()
-                    + "/mw appendrestart - Appends a restart after the next game ends");
-        if (sender.hasPermission("mw.paste"))
-            sender.sendMessage(MessageConfig.getPrefix() + "/mw paste - Pastes a missile");
-        if (sender.hasPermission("mw.reload"))
-            sender.sendMessage(MessageConfig.getPrefix() + "/mw reload - Reloads configurations");
-        if (sender.hasPermission("mw.stats"))
-            sender.sendMessage(MessageConfig.getPrefix() + "/mw stats - Shows stats");
-        if (sender.hasPermission("mw.stats.recommendations"))
-            sender.sendMessage(MessageConfig.getPrefix() + "/mw stats recommendations - Shows recommendations");
-        if (sender.hasPermission("mw.stats.players"))
-            sender.sendMessage(MessageConfig.getPrefix() + "/mw stats players - Shows player list");
-        if (sender.hasPermission("mw.stats.list"))
-            sender.sendMessage(MessageConfig.getPrefix() + "/mw stats list - Lists history of games");
+        GameManager.getInstance().getGames().values().forEach(Game::appendRestart);
+        sender.sendMessage(MessageConfig.getMessage("restart_after_game"));
     }
     }
 
 
-    @Command(name = "mw.reload", permission = "mw.reload", usage = "/mw reload")
-    public void onReload(CommandArgs args) {
-
-        CommandSender sender = args.getSender();
+    @Subcommand("reload")
+    @Description("Reload the plugin.")
+    @Syntax("/mw reload")
+    @CommandCompletion("@nothing")
+    @CommandPermission("mw.reload")
+    public void onReload(CommandSender sender, String[] args) {
 
 
         Config.load();
         Config.load();
         MessageConfig.load();
         MessageConfig.load();
@@ -197,10 +215,12 @@ public class MWCommands {
         sender.sendMessage(MessageConfig.getPrefix() + "Reloaded configs");
         sender.sendMessage(MessageConfig.getPrefix() + "Reloaded configs");
     }
     }
 
 
-    @Command(name = "mw.debug", permission = "mw.debug", usage = "/mw debug")
-    public void onDebug(CommandArgs args) {
-
-        CommandSender sender = args.getSender();
+    @Subcommand("debug")
+    @Description("Show debug info.")
+    @Syntax("/mw debug")
+    @CommandCompletion("@nothing")
+    @CommandPermission("mw.debug")
+    public void onDebug(CommandSender sender, String[] args) {
 
 
         int i = 0;
         int i = 0;
         Logger.NORMAL.log("Starting to print debug information for MissileWars v" + MissileWars.getInstance().version);
         Logger.NORMAL.log("Starting to print debug information for MissileWars v" + MissileWars.getInstance().version);
@@ -211,10 +231,12 @@ public class MWCommands {
         sender.sendMessage(MessageConfig.getPrefix() + "Printed debug message into the log file");
         sender.sendMessage(MessageConfig.getPrefix() + "Printed debug message into the log file");
     }
     }
 
 
-    @Command(name = "mw.restartall", permission = "mw.reload", usage = "/mw restartall")
-    public void onRestartAll(CommandArgs args) {
-
-        CommandSender sender = args.getSender();
+    @Subcommand("restartall")
+    @Description("Restart all games.")
+    @Syntax("/mw restartall")
+    @CommandCompletion("@nothing")
+    @CommandPermission("mw.reload")
+    public void onRestartAll(CommandSender sender, String[] args) {
 
 
         sender.sendMessage(MessageConfig.getPrefix() + "§cWarning - Restarting all games. This may take a while");
         sender.sendMessage(MessageConfig.getPrefix() + "§cWarning - Restarting all games. This may take a while");
         List<Lobby> arenaPropertiesList = GameManager.getInstance().getGames().values()
         List<Lobby> arenaPropertiesList = GameManager.getInstance().getGames().values()

+ 65 - 55
missilewars-plugin/src/main/java/de/butzlabben/missilewars/cmd/StatsCommands.java

@@ -18,8 +18,8 @@
 
 
 package de.butzlabben.missilewars.cmd;
 package de.butzlabben.missilewars.cmd;
 
 
-import com.pro_crafting.mc.commandframework.Command;
-import com.pro_crafting.mc.commandframework.CommandArgs;
+import co.aikar.commands.BaseCommand;
+import co.aikar.commands.annotation.*;
 import de.butzlabben.missilewars.Config;
 import de.butzlabben.missilewars.Config;
 import de.butzlabben.missilewars.MessageConfig;
 import de.butzlabben.missilewars.MessageConfig;
 import de.butzlabben.missilewars.inventory.CustomInv;
 import de.butzlabben.missilewars.inventory.CustomInv;
@@ -42,7 +42,9 @@ import java.time.Duration;
 import java.util.*;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
-public class StatsCommands {
+@CommandAlias("mw|missilewars")
+@Subcommand("stats")
+public class StatsCommands extends BaseCommand {
 
 
     private final static int MAX_FIGHT_DRAW_PERCENTAGE = 15;
     private final static int MAX_FIGHT_DRAW_PERCENTAGE = 15;
     private final static int MIN_FIGHT_DURATION = 5;
     private final static int MIN_FIGHT_DURATION = 5;
@@ -50,48 +52,12 @@ public class StatsCommands {
     private final SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy");
     private final SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy");
     private final SimpleDateFormat preciseFormat = new SimpleDateFormat("hh:mm dd.MM.yyyy");
     private final SimpleDateFormat preciseFormat = new SimpleDateFormat("hh:mm dd.MM.yyyy");
 
 
-    @Command(name = "mw.stats.recommendations", permission = "mw.stats.recommendations", inGameOnly = true, usage = "/mw stats recommendations [from] [arena]")
-    public void onRecommendations(CommandArgs args) {
+    @Default
+    @Description("Shows stats.")
+    @Syntax("/mw stats [from] [arena]")
+    @CommandPermission("mw.stats")
+    public void onStats(CommandSender sender, String[] args) {
 
 
-        CommandSender sender = args.getSender();
-        if (!senderIsPlayer(sender)) return;
-        Player player = (Player) sender;
-
-        StatsFetcher fetcher = getFetcher(player, args);
-        if (fetcher == null) return;
-        SavedStats avgStatsWithDraws = fetcher.getAverageSavedStats(false);
-        SavedStats avgStatsWithoutDraws = fetcher.getAverageSavedStats(true);
-        List<String> recommendations = new ArrayList<>();
-        int gameCount = fetcher.getGameCount();
-
-        double avgWins = avgStatsWithoutDraws.getTeamWon();
-        if (Math.abs(avgWins - 1) > MAX_AVIATION_WIN) {
-            recommendations.add("It could be, that your map is biased to one team, as wins are not equally distributed");
-        }
-
-        int draws = fetcher.getDrawFights();
-        if ((((double) draws / (double) gameCount) * 100) > MAX_FIGHT_DRAW_PERCENTAGE) {
-            recommendations.add("Increase the game_length option. More than 15% of your games are draws");
-        }
-
-        Duration duration = Duration.ofMillis(avgStatsWithoutDraws.getTimeElapsed());
-        if (((double) duration.getSeconds() / 60.0) <= MIN_FIGHT_DURATION) {
-            recommendations.add("Remove some overpowered features. The average game length at won games is under 5 minutes");
-        }
-        // TODO implement more features
-
-        if (recommendations.size() == 0) {
-            player.sendMessage(MessageConfig.getPrefix() + "§aThere are currently no recommendations, everything seems fine :)");
-        } else {
-            player.sendMessage(MessageConfig.getPrefix() + "§7=====[ §eMissileWars recommendations §7]=====");
-            recommendations.forEach(str -> player.sendMessage(MessageConfig.getPrefix() + str));
-        }
-    }
-
-    @Command(name = "mw.stats", permission = "mw.stats", inGameOnly = true, usage = "/mw stats [from] [arena]")
-    public void onStats(CommandArgs args) {
-
-        CommandSender sender = args.getSender();
         if (!senderIsPlayer(sender)) return;
         if (!senderIsPlayer(sender)) return;
         Player player = (Player) sender;
         Player player = (Player) sender;
 
 
@@ -139,10 +105,52 @@ public class StatsCommands {
         player.openInventory(inv.getInventory(player));
         player.openInventory(inv.getInventory(player));
     }
     }
 
 
-    @Command(name = "mw.stats.players", permission = "mw.stats.players", inGameOnly = true, usage = "/mw stats players [from] [arena]")
-    public void onPlayers(CommandArgs args) {
+    @Subcommand("recommendations")
+    @Description("Shows recommendations.")
+    @Syntax("/mw stats recommendations [from] [arena]")
+    @CommandPermission("mw.stats.recommendations")
+    public void onRecommendations(CommandSender sender, String[] args) {
+
+        if (!senderIsPlayer(sender)) return;
+        Player player = (Player) sender;
+
+        StatsFetcher fetcher = getFetcher(player, args);
+        if (fetcher == null) return;
+        SavedStats avgStatsWithDraws = fetcher.getAverageSavedStats(false);
+        SavedStats avgStatsWithoutDraws = fetcher.getAverageSavedStats(true);
+        List<String> recommendations = new ArrayList<>();
+        int gameCount = fetcher.getGameCount();
+
+        double avgWins = avgStatsWithoutDraws.getTeamWon();
+        if (Math.abs(avgWins - 1) > MAX_AVIATION_WIN) {
+            recommendations.add("It could be, that your map is biased to one team, as wins are not equally distributed");
+        }
+
+        int draws = fetcher.getDrawFights();
+        if ((((double) draws / (double) gameCount) * 100) > MAX_FIGHT_DRAW_PERCENTAGE) {
+            recommendations.add("Increase the game_length option. More than 15% of your games are draws");
+        }
+
+        Duration duration = Duration.ofMillis(avgStatsWithoutDraws.getTimeElapsed());
+        if (((double) duration.getSeconds() / 60.0) <= MIN_FIGHT_DURATION) {
+            recommendations.add("Remove some overpowered features. The average game length at won games is under 5 minutes");
+        }
+        // TODO implement more features
+
+        if (recommendations.size() == 0) {
+            player.sendMessage(MessageConfig.getPrefix() + "§aThere are currently no recommendations, everything seems fine :)");
+        } else {
+            player.sendMessage(MessageConfig.getPrefix() + "§7=====[ §eMissileWars recommendations §7]=====");
+            recommendations.forEach(str -> player.sendMessage(MessageConfig.getPrefix() + str));
+        }
+    }
+
+    @Subcommand("players")
+    @Description("Shows player list.")
+    @Syntax("/mw stats players [from] [arena]")
+    @CommandPermission("mw.stats.players")
+    public void onPlayers(CommandSender sender, String[] args) {
 
 
-        CommandSender sender = args.getSender();
         if (!senderIsPlayer(sender)) return;
         if (!senderIsPlayer(sender)) return;
         Player player = (Player) sender;
         Player player = (Player) sender;
 
 
@@ -155,10 +163,12 @@ public class StatsCommands {
         playerGuiFactory.openWhenReady(player);
         playerGuiFactory.openWhenReady(player);
     }
     }
 
 
-    @Command(name = "mw.stats.list", permission = "mw.stats.list", inGameOnly = true, usage = "/mw stats list [from] [arena]")
-    public void onList(CommandArgs args) {
+    @Subcommand("list")
+    @Description("Lists history of games.")
+    @Syntax("/mw stats list [from] [arena]")
+    @CommandPermission("mw.stats.list")
+    public void onList(CommandSender sender, String[] args) {
 
 
-        CommandSender sender = args.getSender();
         if (!senderIsPlayer(sender)) return;
         if (!senderIsPlayer(sender)) return;
         Player player = (Player) sender;
         Player player = (Player) sender;
 
 
@@ -176,22 +186,22 @@ public class StatsCommands {
         creator.show(player);
         creator.show(player);
     }
     }
 
 
-    private StatsFetcher getFetcher(Player player, CommandArgs args) {
+    private StatsFetcher getFetcher(Player player, String[] args) {
         if (!Config.isFightStatsEnabled()) {
         if (!Config.isFightStatsEnabled()) {
             player.sendMessage(MessageConfig.getPrefix() + "§cFightStats are not enabled!");
             player.sendMessage(MessageConfig.getPrefix() + "§cFightStats are not enabled!");
             return null;
             return null;
         }
         }
         Date from = new Date(0);
         Date from = new Date(0);
         String arena = "";
         String arena = "";
-        if (args.length() > 0) {
+        if (args.length > 0) {
             try {
             try {
-                from = format.parse(args.getArgs(0));
+                from = format.parse(args[0]);
             } catch (ParseException e) {
             } catch (ParseException e) {
                 player.sendMessage(MessageConfig.getPrefix() + "§cPlease use the date format dd.MM.yyyy");
                 player.sendMessage(MessageConfig.getPrefix() + "§cPlease use the date format dd.MM.yyyy");
                 return null;
                 return null;
             }
             }
-            if (args.length() > 1) {
-                arena = args.getArgs(1);
+            if (args.length > 1) {
+                arena = args[1];
             }
             }
         }
         }
 
 

+ 26 - 18
missilewars-plugin/src/main/java/de/butzlabben/missilewars/cmd/UserCommands.java

@@ -18,8 +18,8 @@
 
 
 package de.butzlabben.missilewars.cmd;
 package de.butzlabben.missilewars.cmd;
 
 
-import com.pro_crafting.mc.commandframework.Command;
-import com.pro_crafting.mc.commandframework.CommandArgs;
+import co.aikar.commands.BaseCommand;
+import co.aikar.commands.annotation.*;
 import de.butzlabben.missilewars.Config;
 import de.butzlabben.missilewars.Config;
 import de.butzlabben.missilewars.MessageConfig;
 import de.butzlabben.missilewars.MessageConfig;
 import de.butzlabben.missilewars.game.Arenas;
 import de.butzlabben.missilewars.game.Arenas;
@@ -36,12 +36,16 @@ import org.bukkit.entity.Player;
 
 
 import java.util.Optional;
 import java.util.Optional;
 
 
-public class UserCommands {
+@CommandAlias("mw|missilewars")
+public class UserCommands extends BaseCommand {
 
 
-    @Command(name = "mw.change", usage = "/mw change <1|2>", permission = "mw.change", description = "Changes your team", inGameOnly = true)
-    public void changeCommand(CommandArgs args) {
+    @Subcommand("change")
+    @Description("Changes your team.")
+    @Syntax("/mw change <1|2>")
+    @CommandCompletion("@range:1-2")
+    @CommandPermission("mw.change")
+    public void changeCommand(CommandSender sender, String[] args) {
 
 
-        CommandSender sender = args.getSender();
         if (!senderIsPlayer(sender)) return;
         if (!senderIsPlayer(sender)) return;
         Player player = (Player) sender;
         Player player = (Player) sender;
 
 
@@ -56,18 +60,18 @@ public class UserCommands {
             return;
             return;
         }
         }
 
 
-        if (args.length() != 1) {
+        if (args.length != 1) {
             player.sendMessage(MessageConfig.getPrefix() + "§c/mw vote <arena>");
             player.sendMessage(MessageConfig.getPrefix() + "§c/mw vote <arena>");
             return;
             return;
         }
         }
 
 
-        if (args.length() != 1) {
+        if (args.length != 1) {
             player.sendMessage(MessageConfig.getPrefix() + "§c/mw change <1|2>");
             player.sendMessage(MessageConfig.getPrefix() + "§c/mw change <1|2>");
             return;
             return;
         }
         }
         try {
         try {
             MWPlayer mwPlayer = game.getPlayer(player);
             MWPlayer mwPlayer = game.getPlayer(player);
-            int teamNumber = Integer.parseInt(args.getArgs(0));
+            int teamNumber = Integer.parseInt(args[0]);
             Team to = teamNumber == 1 ? game.getTeam1() : game.getTeam2();
             Team to = teamNumber == 1 ? game.getTeam1() : game.getTeam2();
             int otherCount = to.getEnemyTeam().getMembers().size() - 1;
             int otherCount = to.getEnemyTeam().getMembers().size() - 1;
             int toCount = to.getMembers().size() + 1;
             int toCount = to.getMembers().size() + 1;
@@ -86,12 +90,13 @@ public class UserCommands {
         }
         }
     }
     }
 
 
-
-    @Command(name = "mw.vote", usage = "/mw vote <arena>", description = "Stops the game", inGameOnly = true)
-    public void voteCommand(CommandArgs args) {
+    @Subcommand("vote")
+    @Description("Stops the game.")
+    @Syntax("/mw vote <arena>")
+    @CommandPermission("mw.vote")
+    public void voteCommand(CommandSender sender, String[] args) {
 
 
         // TODO more messageconfig
         // TODO more messageconfig
-        CommandSender sender = args.getSender();
         if (!senderIsPlayer(sender)) return;
         if (!senderIsPlayer(sender)) return;
         Player player = (Player) sender;
         Player player = (Player) sender;
 
 
@@ -116,12 +121,12 @@ public class UserCommands {
             return;
             return;
         }
         }
 
 
-        if (args.length() != 1) {
+        if (args.length != 1) {
             player.sendMessage(MessageConfig.getPrefix() + "§c/mw vote <arena>");
             player.sendMessage(MessageConfig.getPrefix() + "§c/mw vote <arena>");
             return;
             return;
         }
         }
 
 
-        String arenaName = args.getArgs(0);
+        String arenaName = args[0];
         Optional<Arena> arena = Arenas.getFromName(arenaName);
         Optional<Arena> arena = Arenas.getFromName(arenaName);
         if (!game.getVotes().containsKey(arenaName) || !arena.isPresent()) {
         if (!game.getVotes().containsKey(arenaName) || !arena.isPresent()) {
             player.sendMessage(MessageConfig.getPrefix() + "§cNo map with this title was found");
             player.sendMessage(MessageConfig.getPrefix() + "§cNo map with this title was found");
@@ -132,11 +137,14 @@ public class UserCommands {
         player.sendMessage(MessageConfig.getMessage("vote.success").replace("%map%", arena.get().getDisplayName()));
         player.sendMessage(MessageConfig.getMessage("vote.success").replace("%map%", arena.get().getDisplayName()));
     }
     }
 
 
-    @Command(name = "mw.quit", inGameOnly = true, usage = "/mw quit", permission = "mw.quit", description = "Quit a game")
-    public void onQuit(CommandArgs args) {
+    @Subcommand("quit|leave")
+    @Description("Quit a game.")
+    @Syntax("/mw quit")
+    @CommandCompletion("@nothing")
+    @CommandPermission("mw.quit")
+    public void onQuit(CommandSender sender, String[] args) {
 
 
         // TODO message config
         // TODO message config
-        CommandSender sender = args.getSender();
         if (!senderIsPlayer(sender)) return;
         if (!senderIsPlayer(sender)) return;
         Player player = (Player) sender;
         Player player = (Player) sender;