diff --git a/.travis.yml b/.travis.yml index fc8755495..a10f3a28b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ before_install: - pwd - cd PlanPluginBridge - ls - - mvn install:install-file -Dfile=/home/travis/build/Rsl1122/Plan-PlayerAnalytics/PlanPluginBridge/PlanPluginBridge-4.2.0.jar -DpomFile=/home/travis/build/Rsl1122/Plan-PlayerAnalytics/PlanPluginBridge/pom.xml + - mvn install:install-file -Dfile=/home/travis/build/Rsl1122/Plan-PlayerAnalytics/PlanPluginBridge/PlanPluginBridge-4.3.0.jar -DpomFile=/home/travis/build/Rsl1122/Plan-PlayerAnalytics/PlanPluginBridge/pom.xml - cd ../Plan - ls install: diff --git a/Plan/dependency-reduced-pom.xml b/Plan/dependency-reduced-pom.xml index 2a9978de3..9951979db 100644 --- a/Plan/dependency-reduced-pom.xml +++ b/Plan/dependency-reduced-pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.djrapitops Plan - 4.2.0-SNAPSHOT + 4.3.0-SNAPSHOT ${basedir}/src/main/java ${basedir}/src/test/java @@ -19,6 +19,7 @@ **/*.html **/*.js **/*.css + locale/*.txt licence.yml @@ -62,6 +63,15 @@ junit:* + + + org.apache + plan.org.apache + + org.apache.logging.* + + + @@ -164,7 +174,11 @@ org.slf4j - asm-all + asm + org.ow2.asm + + + asm-commons org.ow2.asm @@ -260,7 +274,7 @@ org.spongepowered spongeapi - 7.0.0 + LATEST provided @@ -303,10 +317,6 @@ flow-noise com.flowpowered - - asm - org.ow2.asm - slf4j-api org.slf4j @@ -315,6 +325,10 @@ jsr305 com.google.code.findbugs + + asm + org.ow2.asm + gson com.google.code.gson diff --git a/Plan/pom.xml b/Plan/pom.xml index 978f562bc..545fc06c2 100644 --- a/Plan/pom.xml +++ b/Plan/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.djrapitops Plan - 4.2.0-SNAPSHOT + 4.3.0-SNAPSHOT jar @@ -29,13 +29,13 @@ com.djrapitops AbstractPluginFramework - 3.1.1 + 3.2.0 com.djrapitops PlanPluginBridge - 4.2.0-SNAPSHOT + 4.3.0-SNAPSHOT @@ -70,15 +70,14 @@ org.spongepowered spongeapi - 7.0.0 + LATEST jar provided - org.apache.commons - commons-lang3 - 3.6 + commons-text + 1.3 @@ -149,6 +148,7 @@ **/*.html **/*.js **/*.css + locale/*.txt licence.yml @@ -192,6 +192,15 @@ junit:* + + + org.apache + plan.org.apache + + org.apache.logging.* + + + diff --git a/Plan/src/main/java/com/djrapitops/plan/PlanSponge.java b/Plan/src/main/java/com/djrapitops/plan/PlanSponge.java index 364a669cc..5f9fa4ee0 100644 --- a/Plan/src/main/java/com/djrapitops/plan/PlanSponge.java +++ b/Plan/src/main/java/com/djrapitops/plan/PlanSponge.java @@ -1,6 +1,7 @@ package com.djrapitops.plan; import com.djrapitops.plan.api.exceptions.EnableException; +import com.djrapitops.plan.command.PlanCommand; import com.djrapitops.plan.system.SpongeSystem; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; @@ -22,7 +23,7 @@ import org.spongepowered.api.plugin.Plugin; import java.io.File; import java.io.InputStream; -@Plugin(id = "plan", name = "Plan", version = "4.2.0") +@Plugin(id = "plan", name = "Plan", version = "4.3.0", description = "Player Analytics Plugin by Rsl1122", authors = {"Rsl1122"}) public class PlanSponge extends SpongePlugin implements PlanPlugin { @Inject @@ -67,6 +68,7 @@ public class PlanSponge extends SpongePlugin implements PlanPlugin { Log.error("This error should be reported at https://github.com/Rsl1122/Plan-PlayerAnalytics/issues"); onDisable(); } + registerCommand("plan", new PlanCommand(this)); } @Override @@ -90,7 +92,6 @@ public class PlanSponge extends SpongePlugin implements PlanPlugin { return PlanColorScheme.create(); } - @Override public void onReload() { @@ -102,29 +103,8 @@ public class PlanSponge extends SpongePlugin implements PlanPlugin { } @Override - public void log(String level, String msg) { - switch (level.toUpperCase()) { - case "INFO_COLOR": - case "INFO": - case "I": - logger.info(msg); - break; - case "W": - case "WARN": - case "WARNING": - logger.warn(msg); - break; - case "E": - case "ERR": - case "ERROR": - case "SEVERE": - logger.error(msg); - break; - default: - logger.info(msg); - break; - } - + public Logger getLogger() { + return logger; } @Override @@ -134,7 +114,7 @@ public class PlanSponge extends SpongePlugin implements PlanPlugin { @Override public String getVersion() { - return "4.2.0"; + return "4.2.1"; } public SpongeSystem getSystem() { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/PlanBungeeCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/PlanBungeeCommand.java index bfbf39472..8c9707a91 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/PlanBungeeCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/PlanBungeeCommand.java @@ -6,8 +6,9 @@ import com.djrapitops.plan.command.commands.manage.ManageConDebugCommand; import com.djrapitops.plan.system.settings.Permissions; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; -import com.djrapitops.plugin.command.TreeCommand; +import com.djrapitops.plugin.command.TreeCmdNode; import com.djrapitops.plugin.command.defaultcmds.StatusCommand; /** @@ -18,7 +19,7 @@ import com.djrapitops.plugin.command.defaultcmds.StatusCommand; * @author Rsl1122 * @since 1.0.0 */ -public class PlanBungeeCommand extends TreeCommand { +public class PlanBungeeCommand extends TreeCmdNode { /** * CommandExecutor class Constructor. @@ -28,31 +29,28 @@ public class PlanBungeeCommand extends TreeCommand { * @param plugin Current instance of Plan */ public PlanBungeeCommand(PlanBungee plugin) { - super(plugin, "planbungee", CommandType.CONSOLE, Permissions.MANAGE.getPermission(), "", "planbungee"); - super.setDefaultCommand("help"); + super("planbungee", Permissions.MANAGE.getPermission(), CommandType.CONSOLE, null); super.setColorScheme(plugin.getColorScheme()); - } + setInDepthHelp(Locale.get(Msg.CMD_HELP_PLAN).toArray()); - @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_PLAN).toArray(); - } - - @Override - public void addCommands() { - add( - new ReloadCommand(plugin), - new StatusCommand<>(plugin, Permissions.MANAGE.getPermission(), plugin.getColorScheme()), - new ListCommand(), - new BungeeSetupToggleCommand() - ); RegisterCommand registerCommand = new RegisterCommand(); - add( - registerCommand, - new WebUserCommand(plugin, registerCommand), - new NetworkCommand(), - new ListServersCommand(plugin), - new ManageConDebugCommand() + setNodeGroups( + new CommandNode[]{ + new NetworkCommand(), + new ListServersCommand(plugin), + new ListCommand(), + }, + new CommandNode[]{ + registerCommand, + new WebUserCommand(plugin, registerCommand, this), + }, + new CommandNode[]{ + new ManageConDebugCommand(), + new BungeeSetupToggleCommand(), + new ReloadCommand(plugin), + new StatusCommand<>(plugin, Permissions.MANAGE.getPermission(), plugin.getColorScheme()), +// (Settings.ALLOW_UPDATE.isTrue() ? new UpdateCommand() : null) + } ); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/PlanCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/PlanCommand.java index e76518554..ed0787e36 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/PlanCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/PlanCommand.java @@ -1,13 +1,14 @@ package com.djrapitops.plan.command; -import com.djrapitops.plan.Plan; +import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.command.commands.*; import com.djrapitops.plan.system.settings.Permissions; import com.djrapitops.plan.system.settings.Settings; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; -import com.djrapitops.plugin.command.TreeCommand; +import com.djrapitops.plugin.command.TreeCmdNode; import com.djrapitops.plugin.command.defaultcmds.StatusCommand; /** @@ -18,41 +19,37 @@ import com.djrapitops.plugin.command.defaultcmds.StatusCommand; * @author Rsl1122 * @since 1.0.0 */ -public class PlanCommand extends TreeCommand { +public class PlanCommand extends TreeCmdNode { - public PlanCommand(Plan plugin) { - super(plugin, "plan", CommandType.CONSOLE, "", "", "plan"); + public PlanCommand(PlanPlugin plugin) { + super("plan", "", CommandType.CONSOLE, null); super.setDefaultCommand("inspect"); super.setColorScheme(plugin.getColorScheme()); - } + setInDepthHelp(Locale.get(Msg.CMD_HELP_PLAN).toArray()); - @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_PLAN).toArray(); - } - - @Override - public void addCommands() { - add( - new InspectCommand(), - new QInspectCommand(plugin), - new AnalyzeCommand(), - new SearchCommand(), - new InfoCommand(plugin), - new ReloadCommand(plugin), - new ManageCommand(plugin), - new StatusCommand<>(plugin, Permissions.MANAGE.getPermission(), plugin.getColorScheme()), - new ListCommand() - ); RegisterCommand registerCommand = new RegisterCommand(); - add( - registerCommand, - new WebUserCommand(plugin, registerCommand), - new NetworkCommand(), - new ListServersCommand(plugin)); - - if (Settings.DEV_MODE.isTrue()) { - add(new DevCommand()); - } + setNodeGroups( + new CommandNode[]{ + new InspectCommand(), + new QInspectCommand(plugin), + new SearchCommand(), + new ListCommand(), + new AnalyzeCommand(), + new NetworkCommand(), + new ListServersCommand(plugin) + }, + new CommandNode[]{ + new WebUserCommand(plugin, registerCommand, this), + registerCommand + }, + new CommandNode[]{ + new InfoCommand(plugin), + new ReloadCommand(plugin), + new ManageCommand(plugin, this), + new StatusCommand<>(plugin, Permissions.MANAGE.getPermission(), plugin.getColorScheme()), + (Settings.DEV_MODE.isTrue() ? new DevCommand() : null), +// (Settings.ALLOW_UPDATE.isTrue() ? new UpdateCommand() : null) + } + ); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/AnalyzeCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/AnalyzeCommand.java index 3e7502ae9..6a0f82074 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/AnalyzeCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/AnalyzeCommand.java @@ -14,10 +14,10 @@ import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.system.webserver.WebServerSystem; import com.djrapitops.plan.utilities.analysis.Analysis; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandUtils; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import org.bukkit.ChatColor; import java.util.Map; @@ -30,23 +30,17 @@ import java.util.UUID; * @author Rsl1122 * @since 2.0.0 */ -public class AnalyzeCommand extends SubCommand { +public class AnalyzeCommand extends CommandNode { public AnalyzeCommand() { - super("analyze, analyse, analysis, a", - CommandType.CONSOLE, - Permissions.ANALYZE.getPermission(), - Locale.get(Msg.CMD_USG_ANALYZE).parse(), - "[ServerName or ID]"); + super("analyze|analyse|analysis|a", Permissions.ANALYZE.getPermission(), CommandType.CONSOLE); + setShortHelp(Locale.get(Msg.CMD_USG_ANALYZE).parse()); + setInDepthHelp(Locale.get(Msg.CMD_HELP_ANALYZE).toArray()); + setArguments("[server/id]"); } @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_ANALYZE).toArray(); - } - - @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { sender.sendMessage(Locale.get(Msg.CMD_INFO_FETCH_DATA).toString()); Processing.submitNonCritical(() -> { @@ -63,7 +57,6 @@ public class AnalyzeCommand extends SubCommand { Log.toLog(this.getClass(), e); } }); - return true; } private void sendLink(Server server, ISender sender) { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/BungeeSetupToggleCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/BungeeSetupToggleCommand.java index f4e3b7482..63a7b3c60 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/BungeeSetupToggleCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/BungeeSetupToggleCommand.java @@ -6,25 +6,26 @@ package com.djrapitops.plan.command.commands; import com.djrapitops.plan.system.info.connection.ConnectionSystem; import com.djrapitops.plan.system.settings.Permissions; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; /** * Command for Toggling whether or not BungeeCord accepts set up requests. - * + *

* This was added as a security measure against unwanted MySQL snooping. * * @author Rsl1122 */ -public class BungeeSetupToggleCommand extends SubCommand { +public class BungeeSetupToggleCommand extends CommandNode { public BungeeSetupToggleCommand() { - super("setup", CommandType.ALL, Permissions.MANAGE.getPermission(), "Toggle Setup mode for Bungee"); + super("setup", Permissions.MANAGE.getPermission(), CommandType.ALL); + setShortHelp("Toggle Setup mode for Bungee"); } @Override - public boolean onCommand(ISender sender, String s, String[] strings) { + public void onCommand(ISender sender, String s, String[] strings) { boolean setupAllowed = ConnectionSystem.isSetupAllowed(); ConnectionSystem connectionSystem = ConnectionSystem.getInstance(); @@ -35,6 +36,5 @@ public class BungeeSetupToggleCommand extends SubCommand { } String msg = !setupAllowed ? "§aSet-up is now Allowed" : "§cSet-up is now Forbidden"; sender.sendMessage(msg); - return true; } } \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/DevCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/DevCommand.java index 7021b997e..16b15247f 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/DevCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/DevCommand.java @@ -8,25 +8,27 @@ import com.djrapitops.plan.system.info.connection.ConnectionSystem; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.utilities.Condition; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; /** * Command used for testing functions that are too difficult to unit test. * * @author Rsl1122 */ -public class DevCommand extends SubCommand { +public class DevCommand extends CommandNode { public DevCommand() { - super("dev", CommandType.PLAYER_OR_ARGS, "plan.*", "Test Plugin functions not testable with unit tests.", ""); + super("dev", "plan.*", CommandType.PLAYER_OR_ARGS); + setShortHelp("Test Plugin functions not testable with unit tests."); + setArguments(""); } @Override - public boolean onCommand(ISender sender, String cmd, String[] args) { + public void onCommand(ISender sender, String cmd, String[] args) { if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) { - return true; + return; } String feature = args[0]; switch (feature) { @@ -45,6 +47,5 @@ public class DevCommand extends SubCommand { default: break; } - return true; } } \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/InfoCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/InfoCommand.java index 801ef88d4..2f3eccbfa 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/InfoCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/InfoCommand.java @@ -1,14 +1,14 @@ package com.djrapitops.plan.command.commands; -import com.djrapitops.plan.Plan; +import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.system.database.databases.Database; import com.djrapitops.plan.system.settings.Permissions; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.system.update.VersionCheckSystem; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.settings.ColorScheme; /** @@ -17,21 +17,18 @@ import com.djrapitops.plugin.settings.ColorScheme; * @author Rsl1122 * @since 2.0.0 */ -public class InfoCommand extends SubCommand { +public class InfoCommand extends CommandNode { - private final Plan plugin; - - public InfoCommand(Plan plugin) { - super("info", - CommandType.CONSOLE, - Permissions.INFO.getPermission(), - Locale.get(Msg.CMD_USG_INFO).toString()); + private final PlanPlugin plugin; + public InfoCommand(PlanPlugin plugin) { + super("info", Permissions.INFO.getPermission(), CommandType.CONSOLE); + setShortHelp(Locale.get(Msg.CMD_USG_INFO).toString()); this.plugin = plugin; } @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { ColorScheme cs = plugin.getColorScheme(); String mColor = cs.getMainColor(); String sColor = cs.getSecondaryColor(); @@ -41,13 +38,12 @@ public class InfoCommand extends SubCommand { String upToDate = VersionCheckSystem.isNewVersionAvailable() ? "Update Available" : "Up to date"; String[] messages = { Locale.get(Msg.CMD_HEADER_INFO).toString(), - ball + mColor + " Version: " + sColor + plugin.getDescription().getVersion(), + ball + mColor + " Version: " + sColor + plugin.getVersion(), ball + mColor + " Up to date: " + sColor + upToDate, ball + mColor + " Active Database: " + tColor + Database.getActive().getConfigName(), Locale.get(Msg.CMD_CONSTANT_FOOTER).toString() }; sender.sendMessage(messages); - return true; } } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/InspectCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/InspectCommand.java index 1e6951417..52e688588 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/InspectCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/InspectCommand.java @@ -13,10 +13,10 @@ import com.djrapitops.plan.utilities.Condition; import com.djrapitops.plan.utilities.MiscUtils; import com.djrapitops.plan.utilities.uuid.UUIDUtility; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandUtils; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.RunnableFactory; import com.djrapitops.plugin.utilities.Verify; @@ -30,27 +30,20 @@ import java.util.UUID; * @author Rsl1122 * @since 1.0.0 */ -public class InspectCommand extends SubCommand { +public class InspectCommand extends CommandNode { public InspectCommand() { - super("inspect", - CommandType.PLAYER_OR_ARGS, - Permissions.INSPECT.getPermission(), - Locale.get(Msg.CMD_USG_INSPECT).toString(), - ""); + super("inspect", Permissions.INSPECT.getPermission(), CommandType.PLAYER_OR_ARGS); + setArguments(""); + setShortHelp(Locale.get(Msg.CMD_USG_INSPECT).toString()); + setInDepthHelp(Locale.get(Msg.CMD_HELP_INSPECT).toArray()); } @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_INSPECT).toArray(); - } - - @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { String playerName = MiscUtils.getPlayerName(args, sender); runInspectTask(playerName, sender); - return true; } private void runInspectTask(String playerName, ISender sender) { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/ListCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/ListCommand.java index db06e1f0d..d8b12f741 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/ListCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/ListCommand.java @@ -4,10 +4,10 @@ import com.djrapitops.plan.system.info.connection.ConnectionSystem; import com.djrapitops.plan.system.settings.Permissions; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandUtils; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; /** * Command used to display url to the player list page. @@ -15,22 +15,17 @@ import com.djrapitops.plugin.command.SubCommand; * @author Rsl1122 * @since 3.5.2 */ -public class ListCommand extends SubCommand { +public class ListCommand extends CommandNode { public ListCommand() { - super("list, pl, playerlist, players", CommandType.CONSOLE, Permissions.INSPECT_OTHER.getPermission(), Locale.get(Msg.CMD_USG_LIST).toString(), ""); + super("players|pl|playerlist|list", Permissions.INSPECT_OTHER.getPermission(), CommandType.CONSOLE); + setShortHelp(Locale.get(Msg.CMD_USG_LIST).toString()); + setInDepthHelp(Locale.get(Msg.CMD_HELP_LIST).toArray()); } @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_LIST).toArray(); - } - - @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { - + public void onCommand(ISender sender, String commandLabel, String[] args) { sendListMsg(sender); - return true; } private void sendListMsg(ISender sender) { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/ListServersCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/ListServersCommand.java index 2837d8b3f..cd147a0eb 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/ListServersCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/ListServersCommand.java @@ -8,9 +8,9 @@ import com.djrapitops.plan.system.settings.Permissions; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.settings.ColorScheme; import java.util.List; @@ -20,21 +20,19 @@ import java.util.List; * * @author Rsl1122 */ -public class ListServersCommand extends SubCommand { +public class ListServersCommand extends CommandNode { private final PlanPlugin plugin; public ListServersCommand(PlanPlugin plugin) { - super("servers, serverlist, listservers, sl", - CommandType.CONSOLE, - Permissions.MANAGE.getPermission(), - "List servers in the network"); + super("servers|serverlist|listservers|sl|ls", Permissions.MANAGE.getPermission(), CommandType.CONSOLE); + setShortHelp("List servers in the network"); this.plugin = plugin; } @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { ColorScheme colorScheme = plugin.getColorScheme(); String mCol = colorScheme.getMainColor(); String sCol = colorScheme.getSecondaryColor(); @@ -50,7 +48,6 @@ public class ListServersCommand extends SubCommand { sender.sendMessage("§cDatabase Exception occurred."); Log.toLog(this.getClass(), e); } - return true; } } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/ManageCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/ManageCommand.java index 521a09220..1f5b674ad 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/ManageCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/ManageCommand.java @@ -1,12 +1,13 @@ package com.djrapitops.plan.command.commands; -import com.djrapitops.plan.Plan; +import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.command.commands.manage.*; import com.djrapitops.plan.system.settings.Permissions; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; -import com.djrapitops.plugin.command.TreeCommand; +import com.djrapitops.plugin.command.TreeCmdNode; /** * This SubCommand is used to manage the the plugin's database and components. @@ -14,31 +15,28 @@ import com.djrapitops.plugin.command.TreeCommand; * @author Rsl1122 * @since 2.3.0 */ -public class ManageCommand extends TreeCommand { +public class ManageCommand extends TreeCmdNode { - public ManageCommand(Plan plugin) { - super(plugin, "manage,m", CommandType.CONSOLE, Permissions.MANAGE.getPermission(), Locale.get(Msg.CMD_USG_MANAGE).toString(), "plan m"); + public ManageCommand(PlanPlugin plugin, CommandNode parent) { + super("manage|m", Permissions.MANAGE.getPermission(), CommandType.CONSOLE, parent); + setShortHelp(Locale.get(Msg.CMD_USG_MANAGE).toString()); + setInDepthHelp(Locale.get(Msg.CMD_HELP_MANAGE).toArray()); super.setColorScheme(plugin.getColorScheme()); - } - - @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_MANAGE).toArray(); - } - - @Override - public void addCommands() { - add( - new ManageMoveCommand(), - new ManageHotswapCommand(plugin), - new ManageBackupCommand(), - new ManageRestoreCommand(plugin), - new ManageImportCommand(), - new ManageRemoveCommand(), - new ManageClearCommand(plugin), - new ManageSetupCommand(), - new ManageDisableCommand(), - new ManageConDebugCommand() + setNodeGroups( + new CommandNode[]{ + new ManageMoveCommand(), + new ManageBackupCommand(), + new ManageRestoreCommand(plugin), + new ManageRemoveCommand(), + new ManageHotSwapCommand(plugin), + new ManageClearCommand(plugin), + }, + new CommandNode[]{ + new ManageSetupCommand(), + new ManageConDebugCommand(), + new ManageImportCommand(), + new ManageDisableCommand() + } ); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/NetworkCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/NetworkCommand.java index d9bd4fc87..3b4b89725 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/NetworkCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/NetworkCommand.java @@ -4,29 +4,26 @@ import com.djrapitops.plan.system.info.connection.ConnectionSystem; import com.djrapitops.plan.system.settings.Permissions; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandUtils; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; /** * Command used to display url to the network page. * * @author Rsl1122 */ -public class NetworkCommand extends SubCommand { +public class NetworkCommand extends CommandNode { public NetworkCommand() { - super("network, n, netw", - CommandType.CONSOLE, - Permissions.ANALYZE.getPermission(), - "Get the link to the network page"); + super("network|n|netw", Permissions.ANALYZE.getPermission(), CommandType.CONSOLE); + setShortHelp("View the network page"); } @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { sendNetworkMsg(sender); - return true; } private void sendNetworkMsg(ISender sender) { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/QInspectCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/QInspectCommand.java index f209a1455..781b03071 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/QInspectCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/QInspectCommand.java @@ -13,9 +13,9 @@ import com.djrapitops.plan.utilities.FormatUtils; import com.djrapitops.plan.utilities.MiscUtils; import com.djrapitops.plan.utilities.uuid.UUIDUtility; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.settings.ColorScheme; import com.djrapitops.plugin.settings.DefaultMessages; import com.djrapitops.plugin.task.AbsRunnable; @@ -30,7 +30,7 @@ import java.util.UUID; * @author Rsl1122 * @since 1.0.0 */ -public class QInspectCommand extends SubCommand { +public class QInspectCommand extends CommandNode { private final PlanPlugin plugin; @@ -40,27 +40,19 @@ public class QInspectCommand extends SubCommand { * @param plugin Current instance of Plan */ public QInspectCommand(PlanPlugin plugin) { - super("qinspect", - CommandType.PLAYER_OR_ARGS, - Permissions.QUICK_INSPECT.getPermission(), - Locale.get(Msg.CMD_USG_QINSPECT).toString(), - ""); - + super("qinspect", Permissions.QUICK_INSPECT.getPermission(), CommandType.PLAYER_OR_ARGS); + setArguments(""); + setShortHelp(Locale.get(Msg.CMD_USG_QINSPECT).toString()); + setInDepthHelp(Locale.get(Msg.CMD_HELP_QINSPECT).toArray()); this.plugin = plugin; } @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_QINSPECT).toArray(); - } - - @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { String playerName = MiscUtils.getPlayerName(args, sender, Permissions.QUICK_INSPECT_OTHER); runInspectTask(playerName, sender); - return true; } private void runInspectTask(String playerName, ISender sender) { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/RegisterCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/RegisterCommand.java index 12280ec51..f88981af6 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/RegisterCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/RegisterCommand.java @@ -9,13 +9,15 @@ import com.djrapitops.plan.utilities.Condition; import com.djrapitops.plan.utilities.PassEncryptUtil; import com.djrapitops.plugin.api.Check; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandUtils; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.RunnableFactory; +import java.util.Arrays; + /** * Command for registering web users. *

@@ -27,27 +29,22 @@ import com.djrapitops.plugin.task.RunnableFactory; * @author Rsl1122 * @since 3.5.2 */ -public class RegisterCommand extends SubCommand { +public class RegisterCommand extends CommandNode { public RegisterCommand() { - super("register", - CommandType.PLAYER_OR_ARGS, - "", // No Permission Requirement - Locale.get(Msg.CMD_USG_WEB_REGISTER).toString(), - " [name] [access lvl]"); + // No Permission Requirement + super("register", "", CommandType.PLAYER_OR_ARGS); + setShortHelp(Locale.get(Msg.CMD_USG_WEB_REGISTER).toString()); + setArguments("", "[name]", "[lvl]"); + setInDepthHelp(Locale.get(Msg.CMD_HELP_WEB_REGISTER).toArray()); if (Check.isBukkitAvailable()) { setupFilter(); } } @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_WEB_REGISTER).toArray(); - } - - @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { - String notEnoughArgsMsg = Locale.get(Msg.CMD_FAIL_REQ_ARGS).parse("(3) " + super.getArguments()); + public void onCommand(ISender sender, String commandLabel, String[] args) { + String notEnoughArgsMsg = Locale.get(Msg.CMD_FAIL_REQ_ARGS).parse("(3) " + Arrays.toString(getArguments())); String hashErrorMsg = "§cPassword hash error."; String permLvlErrorMsg = "§cIncorrect perm level, not a number: "; try { @@ -65,7 +62,6 @@ public class RegisterCommand extends SubCommand { } catch (Exception e) { Log.toLog(this.getClass().getSimpleName(), e); } - return true; } private void consoleRegister(String[] args, ISender sender, String notEnoughArgsMsg) throws PassEncryptUtil.CannotPerformOperationException { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/ReloadCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/ReloadCommand.java index 839a3cd4c..17bacbdd4 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/ReloadCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/ReloadCommand.java @@ -5,9 +5,9 @@ import com.djrapitops.plan.system.settings.Permissions; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; /** * This SubCommand is used to reload the plugin. @@ -15,21 +15,18 @@ import com.djrapitops.plugin.command.SubCommand; * @author Rsl1122 * @since 2.0.0 */ -public class ReloadCommand extends SubCommand { +public class ReloadCommand extends CommandNode { private final PlanPlugin plugin; public ReloadCommand(PlanPlugin plugin) { - super("reload", - CommandType.CONSOLE, - Permissions.MANAGE.getPermission(), - Locale.get(Msg.CMD_USG_RELOAD).toString()); - + super("reload", Permissions.MANAGE.getPermission(), CommandType.CONSOLE); + setShortHelp(Locale.get(Msg.CMD_USG_RELOAD).toString()); this.plugin = plugin; } @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { try { plugin.reloadPlugin(true); } catch (Exception e) { @@ -37,7 +34,5 @@ public class ReloadCommand extends SubCommand { sender.sendMessage("§cSomething went wrong during reload of the plugin, a restart is recommended."); } sender.sendMessage(Locale.get(Msg.CMD_INFO_RELOAD_COMPLETE).toString()); - return true; } - } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/SearchCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/SearchCommand.java index 72441ad8d..8a2211fd0 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/SearchCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/SearchCommand.java @@ -5,9 +5,9 @@ import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.utilities.Condition; import com.djrapitops.plan.utilities.MiscUtils; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.RunnableFactory; import com.djrapitops.plugin.utilities.FormatUtils; @@ -22,31 +22,23 @@ import java.util.List; * @author Rsl1122 * @since 2.0.0 */ -public class SearchCommand extends SubCommand { +public class SearchCommand extends CommandNode { public SearchCommand() { - super("search", - CommandType.PLAYER_OR_ARGS, - Permissions.SEARCH.getPermission(), - Locale.get(Msg.CMD_USG_SEARCH).toString(), - ""); - + super("search", Permissions.SEARCH.getPermission(), CommandType.PLAYER_OR_ARGS); + setShortHelp(Locale.get(Msg.CMD_USG_SEARCH).toString()); + setArguments(""); + setInDepthHelp(Locale.get(Msg.CMD_HELP_SEARCH).toArray()); } @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_SEARCH).toArray(); - } - - @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) { - return true; + return; } sender.sendMessage(Locale.get(Msg.CMD_INFO_SEARCHING).toString()); runSearchTask(args, sender); - return true; } private void runSearchTask(String[] args, ISender sender) { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/UpdateCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/UpdateCommand.java new file mode 100644 index 000000000..a12ffd7ea --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/UpdateCommand.java @@ -0,0 +1,237 @@ +package com.djrapitops.plan.command.commands; + +import com.djrapitops.plan.api.exceptions.connection.*; +import com.djrapitops.plan.api.exceptions.database.DBException; +import com.djrapitops.plan.command.commands.manage.ManageConDebugCommand; +import com.djrapitops.plan.system.database.databases.Database; +import com.djrapitops.plan.system.database.databases.operation.FetchOperations; +import com.djrapitops.plan.system.info.InfoSystem; +import com.djrapitops.plan.system.info.request.UpdateCancelRequest; +import com.djrapitops.plan.system.info.request.UpdateRequest; +import com.djrapitops.plan.system.info.server.Server; +import com.djrapitops.plan.system.settings.Permissions; +import com.djrapitops.plan.system.settings.locale.Locale; +import com.djrapitops.plan.system.settings.locale.Msg; +import com.djrapitops.plan.system.update.VersionCheckSystem; +import com.djrapitops.plan.system.update.VersionInfo; +import com.djrapitops.plan.system.webserver.WebServerSystem; +import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; +import com.djrapitops.plugin.command.CommandType; +import com.djrapitops.plugin.command.CommandUtils; +import com.djrapitops.plugin.command.ISender; +import com.djrapitops.plugin.task.AbsRunnable; +import com.djrapitops.plugin.task.RunnableFactory; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +/** + * Command that updates all servers in the network + * + * @author Rsl1122 + */ +public class UpdateCommand extends CommandNode { + + public UpdateCommand() { + super("update", Permissions.MANAGE.getPermission(), CommandType.ALL); + setArguments("[-u]/[cancel]"); + setShortHelp("Get change log link or update plugin."); + setInDepthHelp( + "/plan update", + " Used to update the plugin on the next shutdown\n", + " /plan update - get change log link", + " /plan update -u - Schedule update to happen on all network servers that are online next time they reboot.", + " /plan update cancel - Cancel scheduled update on servers that haven't rebooted yet." + ); + } + + @Override + public void onCommand(ISender sender, String commandLabel, String[] args) { + if (!VersionCheckSystem.isNewVersionAvailable()) { + sender.sendMessage("§aYou're running the latest version of Plan."); + return; + } + + VersionInfo available = VersionCheckSystem.getInstance().getNewVersionAvailable(); + String downloadUrl = available.getDownloadUrl(); + + if (!available.isTrusted()) { + sender.sendMessage("§cVersion download url did not start with " + + "https://github.com/Rsl1122/Plan-PlayerAnalytics/releases/ " + + "and might not be trusted. You can download this version manually here (Direct download):"); + sender.sendLink(downloadUrl, downloadUrl); + return; + } + + if (args.length == 0) { + String message = "Change Log v" + available.getVersion().toString() + ": "; + String url = available.getChangeLogUrl(); + if (CommandUtils.isConsole(sender)) { + sender.sendMessage(message + url); + } else { + sender.sendMessage(message); + sender.sendLink(" ", Locale.get(Msg.CMD_INFO_CLICK_ME).toString(), url); + } + return; + } + + String firstArgument = args[0]; + RunnableFactory.createNew("Update Command Task", new AbsRunnable() { + @Override + public void run() { + try { + if ("-u".equals(firstArgument)) { + handleUpdate(sender, args); + } else if ("cancel".equals(firstArgument)) { + handleCancel(sender); + } else { + throw new IllegalArgumentException("Unknown argument, use '-u' or 'cancel'"); + } + } finally { + cancel(); + } + } + }).runTaskAsynchronously(); + } + + private void handleCancel(ISender sender) { + try { + cancel(sender, Database.getActive().fetch().getServers()); + sender.sendMessage("§aCancel operation performed."); + } catch (DBException e) { + sender.sendMessage("§cDatabase error occurred, cancel could not be performed."); + Log.toLog(this.getClass().getName(), e); + } + } + + private void handleUpdate(ISender sender, String[] args) { + sender.sendMessage("§aYou can cancel the update on servers that haven't rebooted yet with /plan update cancel."); + sender.sendMessage("Checking that all servers are online.."); + if (!checkNetworkStatus(sender)) { + sender.sendMessage("§cNot all servers were online or accessible, you can still update available servers using /plan -update -force"); + // If -force, continue, otherwise return. + if (args.length < 2 || !"-force".equals(args[1])) { + return; + } + } + try { + List servers = Database.getActive().fetch().getServers(); + update(sender, servers, args); + } catch (DBException e) { + Log.toLog(this.getClass().getName(), e); + } + } + + private void update(ISender sender, List servers, String[] args) { + for (Server server : servers) { + if (update(sender, server)) { + sender.sendMessage("§a" + server.getName() + " scheduled for update."); + } else { + if (args.length > 1 && "-force".equals(args[1])) { + sender.sendMessage("§e" + server.getName() + " failed to update, -force specified, continuing update."); + continue; + } + sender.sendMessage("§cUpdate failed on a server, cancelling update on all servers.."); + cancel(sender, servers); + sender.sendMessage("§cUpdate cancelled."); + break; + } + } + } + + private void cancel(ISender sender, List servers) { + for (Server server : servers) { + cancel(sender, server); + } + + } + + private void cancel(ISender sender, Server server) { + try { + InfoSystem.getInstance().getConnectionSystem().sendInfoRequest(new UpdateCancelRequest(), server); + } catch (ForbiddenException | GatewayException | InternalErrorException e) { + sender.sendMessage("§cCancel failed on " + server.getName() + ": Odd Exception: " + e.getClass().getSimpleName()); + } catch (UnauthorizedServerException e) { + sender.sendMessage("§cCancel failed on " + server.getName() + ": Unauthorized. " + server.getName() + " might be using different database."); + } catch (ConnectionFailException e) { + sender.sendMessage("§cCancel failed on " + server.getName() + ": " + e.getCause().getClass().getSimpleName() + " " + e.getCause().getMessage()); + String address = server.getWebAddress(); + boolean local = address.contains("localhost") + || address.startsWith("https://:") // IP empty = Localhost + || address.startsWith("http://:") // IP empty = Localhost + || address.contains("127.0.0.1"); + if (!local) { + sender.sendMessage("§cNon-local address, check that port is open"); + } + } catch (NotFoundException e) { + /* Ignored, older version */ + } catch (WebException e) { + sender.sendMessage("§cCancel failed on " + server.getName() + ": Odd Exception:" + e.getClass().getSimpleName()); + } + } + + private boolean update(ISender sender, Server server) { + try { + InfoSystem.getInstance().getConnectionSystem().sendInfoRequest(new UpdateRequest(), server); + return true; + } catch (BadRequestException e) { + sender.sendMessage("§c" + server.getName() + " has Allow-Update set to false, aborting update."); + return false; + } catch (ForbiddenException | GatewayException | InternalErrorException | NoServersException e) { + sender.sendMessage("§c" + server.getName() + ": Odd Exception: " + e.getClass().getSimpleName()); + return false; + } catch (UnauthorizedServerException e) { + sender.sendMessage("§cFail reason: Unauthorized. " + server.getName() + " might be using different database."); + return false; + } catch (ConnectionFailException e) { + sender.sendMessage("§cFail reason: " + e.getCause().getClass().getSimpleName() + " " + e.getCause().getMessage()); + String address = server.getWebAddress(); + boolean local = address.contains("localhost") + || address.startsWith("https://:") // IP empty = Localhost + || address.startsWith("http://:") // IP empty = Localhost + || address.contains("127.0.0.1"); + if (!local) { + sender.sendMessage("§cNon-local address, check that port is open"); + } + return false; + } catch (NotFoundException e) { + sender.sendMessage("§e" + server.getName() + " is using older version and can not be scheduled for update. " + + "You can update it manually, update will proceed."); + return true; + } catch (WebException e) { + sender.sendMessage("§eOdd Exception: " + e.getClass().getSimpleName()); + return false; + } + } + + private boolean checkNetworkStatus(ISender sender) { + try { + FetchOperations fetch = Database.getActive().fetch(); + Optional bungeeInformation = fetch.getBungeeInformation(); + if (!bungeeInformation.isPresent()) { + sender.sendMessage("Bungee address not found in the database, assuming this is not a network."); + return true; + } + Map bukkitServers = fetch.getBukkitServers(); + String accessAddress = WebServerSystem.getInstance().getWebServer().getAccessAddress(); + boolean success = true; + for (Server server : bukkitServers.values()) { + if (!ManageConDebugCommand.testServer(sender, accessAddress, server)) { + success = false; + } + } + Server bungee = bungeeInformation.get(); + if (!ManageConDebugCommand.testServer(sender, accessAddress, bungee)) { + success = false; + } + return success; + } catch (DBException e) { + sender.sendMessage("§cDatabase error occurred, update has been cancelled."); + Log.toLog(this.getClass().getName(), e); + return false; + } + } +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/WebUserCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/WebUserCommand.java index 5119c40d1..7a18cfcdc 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/WebUserCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/WebUserCommand.java @@ -1,7 +1,5 @@ package com.djrapitops.plan.command.commands; -import com.djrapitops.plan.Plan; -import com.djrapitops.plan.PlanBungee; import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.command.commands.webuser.WebCheckCommand; import com.djrapitops.plan.command.commands.webuser.WebDeleteCommand; @@ -10,8 +8,9 @@ import com.djrapitops.plan.command.commands.webuser.WebListUsersCommand; import com.djrapitops.plan.system.settings.Permissions; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; -import com.djrapitops.plugin.command.TreeCommand; +import com.djrapitops.plugin.command.TreeCmdNode; /** * Web subcommand used to manage Web users. @@ -19,39 +18,21 @@ import com.djrapitops.plugin.command.TreeCommand; * @author Rsl1122 * @since 3.5.2 */ -public class WebUserCommand extends TreeCommand { +public class WebUserCommand extends TreeCmdNode { - public WebUserCommand(Plan plugin, RegisterCommand register) { - super(plugin, "webuser, web", - CommandType.CONSOLE, - Permissions.MANAGE_WEB.getPerm(), - Locale.get(Msg.CMD_USG_WEB).toString(), - "plan web"); + public WebUserCommand(PlanPlugin plugin, RegisterCommand register, CommandNode parent) { + super("webuser|web", Permissions.MANAGE_WEB.getPerm(), CommandType.CONSOLE, parent); + setShortHelp(Locale.get(Msg.CMD_USG_WEB).toString()); super.setColorScheme(plugin.getColorScheme()); - add(register); - } - - public WebUserCommand(PlanBungee plugin, RegisterCommand register) { - super(plugin, "webuser, web", - CommandType.CONSOLE, - Permissions.MANAGE_WEB.getPerm(), - Locale.get(Msg.CMD_USG_WEB).toString(), - "planbungee web"); - add(register); - } - - @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_WEB).toArray(); - } - - @Override - public void addCommands() { - add( - new WebLevelCommand(plugin), - new WebListUsersCommand(plugin), - new WebCheckCommand(), - new WebDeleteCommand() + setInDepthHelp(Locale.get(Msg.CMD_HELP_WEB).toArray()); + setNodeGroups( + new CommandNode[]{ + register, + new WebLevelCommand(plugin), + new WebListUsersCommand(plugin), + new WebCheckCommand(), + new WebDeleteCommand() + } ); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageBackupCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageBackupCommand.java index 7362b103d..ec69b3257 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageBackupCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageBackupCommand.java @@ -9,9 +9,9 @@ import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.utilities.Condition; import com.djrapitops.plan.utilities.ManageUtils; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.RunnableFactory; import com.djrapitops.plugin.utilities.Verify; @@ -22,28 +22,26 @@ import com.djrapitops.plugin.utilities.Verify; * @author Rsl1122 * @since 2.3.0 */ -public class ManageBackupCommand extends SubCommand { +public class ManageBackupCommand extends CommandNode { public ManageBackupCommand() { - super("backup", - CommandType.CONSOLE, - Permissions.MANAGE.getPermission(), - Locale.get(Msg.CMD_USG_MANAGE_BACKUP).toString(), - ""); + super("backup", Permissions.MANAGE.getPermission(), CommandType.CONSOLE); + setShortHelp(Locale.get(Msg.CMD_USG_MANAGE_BACKUP).toString()); + setArguments(""); } @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { try { if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ARGS).parse(this.getArguments()), sender)) { - return true; + return; } String dbName = args[0].toLowerCase(); boolean isCorrectDB = "sqlite".equals(dbName) || "mysql".equals(dbName); if (!Condition.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + dbName, sender)) { - return true; + return; } final Database database = DBSystem.getActiveDatabaseByName(dbName); @@ -51,7 +49,7 @@ public class ManageBackupCommand extends SubCommand { // If DB is null return if (!Condition.isTrue(Verify.notNull(database), Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString(), sender)) { Log.error(dbName + " was null!"); - return true; + return; } Log.debug("Backup", "Start"); runBackupTask(sender, args, database); @@ -60,7 +58,6 @@ public class ManageBackupCommand extends SubCommand { } finally { Log.logDebug("Backup"); } - return true; } private void runBackupTask(ISender sender, String[] args, final Database database) { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageClearCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageClearCommand.java index 4ada4101f..f47891e88 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageClearCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageClearCommand.java @@ -1,11 +1,9 @@ package com.djrapitops.plan.command.commands.manage; -import com.djrapitops.plan.Plan; +import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.api.exceptions.database.DBException; import com.djrapitops.plan.api.exceptions.database.DBInitException; import com.djrapitops.plan.api.exceptions.database.FatalDBException; -import com.djrapitops.plan.data.container.Session; -import com.djrapitops.plan.system.cache.SessionCache; import com.djrapitops.plan.system.database.DBSystem; import com.djrapitops.plan.system.database.databases.Database; import com.djrapitops.plan.system.settings.Permissions; @@ -14,9 +12,9 @@ import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.utilities.Condition; import com.djrapitops.plan.utilities.MiscUtils; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.RunnableFactory; import com.djrapitops.plugin.utilities.Verify; @@ -27,41 +25,34 @@ import com.djrapitops.plugin.utilities.Verify; * @author Rsl1122 * @since 2.3.0 */ -public class ManageClearCommand extends SubCommand { +public class ManageClearCommand extends CommandNode { - private final Plan plugin; - - public ManageClearCommand(Plan plugin) { - super("clear", - CommandType.PLAYER_OR_ARGS, - Permissions.MANAGE.getPermission(), - Locale.get(Msg.CMD_USG_MANAGE_CLEAR).toString(), - " [-a]"); + private final PlanPlugin plugin; + public ManageClearCommand(PlanPlugin plugin) { + super("clear", Permissions.MANAGE.getPermission(), CommandType.PLAYER_OR_ARGS); + setShortHelp(Locale.get(Msg.CMD_USG_MANAGE_CLEAR).toString()); + setArguments("", "[-a]"); + setInDepthHelp(Locale.get(Msg.CMD_HELP_MANAGE_CLEAR).toArray()); this.plugin = plugin; } @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_MANAGE_CLEAR).toArray(); - } - - @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) { - return true; + return; } String dbName = args[0].toLowerCase(); boolean isCorrectDB = "sqlite".equals(dbName) || "mysql".equals(dbName); if (!Condition.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + dbName, sender)) { - return true; + return; } if (!Condition.isTrue(Verify.contains("-a", args), Locale.get(Msg.MANAGE_FAIL_CONFIRM).parse(Locale.get(Msg.MANAGE_NOTIFY_REMOVE).parse(args[0])), sender)) { - return true; + return; } try { @@ -70,7 +61,6 @@ public class ManageClearCommand extends SubCommand { } catch (DBInitException e) { sender.sendMessage(Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString()); } - return true; } private void runClearTask(ISender sender, Database database) { @@ -83,11 +73,6 @@ public class ManageClearCommand extends SubCommand { database.remove().everything(); long now = MiscUtils.getTime(); - SessionCache.clear(); - plugin.getServer().getOnlinePlayers().forEach( - player -> SessionCache.getInstance().cacheSession(player.getUniqueId(), - new Session(now, player.getWorld().getName(), player.getGameMode().name())) - ); sender.sendMessage(Locale.get(Msg.MANAGE_INFO_CLEAR_SUCCESS).toString()); } catch (FatalDBException e) { sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString() diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageConDebugCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageConDebugCommand.java index fe403ad9d..7414538e8 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageConDebugCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageConDebugCommand.java @@ -10,13 +10,11 @@ import com.djrapitops.plan.system.info.server.Server; import com.djrapitops.plan.system.info.server.ServerInfo; import com.djrapitops.plan.system.processing.Processing; import com.djrapitops.plan.system.settings.Permissions; -import com.djrapitops.plan.system.settings.locale.Locale; -import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.system.webserver.WebServerSystem; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.settings.ColorScheme; import java.util.List; @@ -28,41 +26,31 @@ import java.util.UUID; * @author Rsl1122 * @since 2.3.0 */ -public class ManageConDebugCommand extends SubCommand { - - private final ColorScheme cs; +public class ManageConDebugCommand extends CommandNode { public ManageConDebugCommand() { - super("con", - CommandType.ALL, - Permissions.MANAGE.getPermission(), - "Debug Bukkit-Bungee Connections", - ""); - - cs = PlanPlugin.getInstance().getColorScheme(); + super("con", Permissions.MANAGE.getPermission(), CommandType.ALL); + setShortHelp("Debug Bukkit-Bungee Connections"); } @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_MANAGE_HOTSWAP).toArray(); - } - - @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { if (!WebServerSystem.isWebServerEnabled()) { sender.sendMessage("§cWebServer is not enabled on this server."); - return true; + return; } Processing.submitNonCritical(() -> testServers(sender)); - - return true; } private void testServers(ISender sender) { try { List servers = Database.getActive().fetch().getServers(); + if (servers.isEmpty()) { + sender.sendMessage("§cNo Servers found in the database."); + } + String accessAddress = WebServerSystem.getInstance().getWebServer().getAccessAddress(); UUID thisServer = ServerInfo.getServerUUID(); for (Server server : servers) { @@ -77,18 +65,19 @@ public class ManageConDebugCommand extends SubCommand { } } - private void testServer(ISender sender, String accessAddress, Server server) { + public static boolean testServer(ISender sender, String accessAddress, Server server) { String address = server.getWebAddress().toLowerCase(); boolean usingHttps = address.startsWith("https"); boolean local = address.contains("localhost") - || address.startsWith("https://:") - || address.startsWith("http://:") + || address.startsWith("https://:") // IP empty = Localhost + || address.startsWith("http://:") // IP empty = Localhost || address.contains("127.0.0.1"); try { InfoSystem.getInstance().getConnectionSystem().sendInfoRequest(new CheckConnectionRequest(accessAddress), server); sender.sendMessage(getMsgFor(address, usingHttps, local, true, true)); + return true; } catch (ForbiddenException | BadRequestException | InternalErrorException e) { sender.sendMessage(getMsgFor(address, usingHttps, local, false, false)); @@ -111,9 +100,11 @@ public class ManageConDebugCommand extends SubCommand { sender.sendMessage(getMsgFor(address, usingHttps, local, false, false)); sender.sendMessage("§eOdd Exception: " + e.getClass().getSimpleName()); } + return false; } - private String getMsgFor(String address, boolean usingHttps, boolean local, boolean successTo, boolean successFrom) { + private static String getMsgFor(String address, boolean usingHttps, boolean local, boolean successTo, boolean successFrom) { + ColorScheme cs = PlanPlugin.getInstance().getColorScheme(); String tCol = cs.getTertiaryColor(); String sCol = cs.getSecondaryColor(); return tCol + address + sCol + ": " diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageDisableCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageDisableCommand.java index cf00f566f..bbca26d0f 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageDisableCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageDisableCommand.java @@ -5,9 +5,9 @@ import com.djrapitops.plan.system.settings.Permissions; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.utilities.Condition; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; /** * This manage SubCommand is used to disable some features of the plugin temporarily. @@ -15,22 +15,20 @@ import com.djrapitops.plugin.command.SubCommand; * @author Rsl1122 * @since 4.0.4 */ -public class ManageDisableCommand extends SubCommand { +public class ManageDisableCommand extends CommandNode { /** * Class Constructor. */ public ManageDisableCommand() { - super("disable", - CommandType.PLAYER_OR_ARGS, - Permissions.MANAGE.getPermission(), - "Used to disable some features of the Plugin temporarily", - ""); + super("disable", Permissions.MANAGE.getPermission(), CommandType.PLAYER_OR_ARGS); + setShortHelp("Disable a feature temporarily"); + setArguments(""); } @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ARGS).parse(this.getArguments()), sender)) { - return true; + return; } switch (args[0].toLowerCase()) { case "kickcount": @@ -40,6 +38,5 @@ public class ManageDisableCommand extends SubCommand { default: sender.sendMessage("§eDefine a feature to disable! (currently supports only kickCount)"); } - return true; } } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageHotswapCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageHotSwapCommand.java similarity index 71% rename from Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageHotswapCommand.java rename to Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageHotSwapCommand.java index a77a9b8b9..32e26aaca 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageHotswapCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageHotSwapCommand.java @@ -1,6 +1,6 @@ package com.djrapitops.plan.command.commands.manage; -import com.djrapitops.plan.Plan; +import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.system.database.DBSystem; import com.djrapitops.plan.system.database.databases.Database; import com.djrapitops.plan.system.settings.Permissions; @@ -9,9 +9,9 @@ import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.utilities.Condition; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.utilities.Verify; /** @@ -21,40 +21,33 @@ import com.djrapitops.plugin.utilities.Verify; * @author Rsl1122 * @since 2.3.0 */ -public class ManageHotswapCommand extends SubCommand { +public class ManageHotSwapCommand extends CommandNode { - private final Plan plugin; - - public ManageHotswapCommand(Plan plugin) { - super("hotswap", - CommandType.PLAYER_OR_ARGS, - Permissions.MANAGE.getPermission(), - Locale.get(Msg.CMD_USG_MANAGE_HOTSWAP).toString(), - ""); + private final PlanPlugin plugin; + public ManageHotSwapCommand(PlanPlugin plugin) { + super("hotswap", Permissions.MANAGE.getPermission(), CommandType.PLAYER_OR_ARGS); + setShortHelp(Locale.get(Msg.CMD_USG_MANAGE_HOTSWAP).toString()); + setArguments(""); + setInDepthHelp(Locale.get(Msg.CMD_HELP_MANAGE_HOTSWAP).toArray()); this.plugin = plugin; } @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_MANAGE_HOTSWAP).toArray(); - } - - @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) { - return true; + return; } String dbName = args[0].toLowerCase(); boolean isCorrectDB = "sqlite".equals(dbName) || "mysql".equals(dbName); if (!Condition.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + dbName, sender)) { - return true; + return; } if (Condition.isTrue(dbName.equals(Database.getActive().getConfigName()), Locale.get(Msg.MANAGE_FAIL_SAME_DB).toString(), sender)) { - return true; + return; } try { @@ -63,22 +56,21 @@ public class ManageHotswapCommand extends SubCommand { // If DB is null return if (!Condition.isTrue(Verify.notNull(database), Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString(), sender)) { Log.error(dbName + " was null!"); - return true; + return; } if (!database.isOpen()) { - return true; + return; } } catch (Exception e) { Log.toLog(this.getClass(), e); sender.sendMessage(Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString()); - return true; + return; } Settings.DB_TYPE.set(dbName); Settings.save(); plugin.reloadPlugin(true); - return true; } } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageImportCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageImportCommand.java index 575abb1bf..3585fd2ea 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageImportCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageImportCommand.java @@ -6,37 +6,33 @@ import com.djrapitops.plan.system.settings.Permissions; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.utilities.Condition; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.RunnableFactory; +import java.util.Arrays; + /** * This manage SubCommand is used to import data from 3rd party plugins. * * @author Rsl1122 * @since 2.3.0 */ -public class ManageImportCommand extends SubCommand { +public class ManageImportCommand extends CommandNode { public ManageImportCommand() { - super("import", - CommandType.CONSOLE, - Permissions.MANAGE.getPermission(), - Locale.get(Msg.CMD_USG_MANAGE_IMPORT).toString(), - "/list [import args]"); + super("import", Permissions.MANAGE.getPermission(), CommandType.CONSOLE); + setShortHelp(Locale.get(Msg.CMD_USG_MANAGE_IMPORT).toString()); + setArguments("/list", "[import args]"); + setInDepthHelp(Locale.get(Msg.CMD_HELP_MANAGE_IMPORT).toArray()); } @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_MANAGE_IMPORT).toArray(); - } - - @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { - if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG) + " " + this.getArguments(), sender)) { - return true; + public void onCommand(ISender sender, String commandLabel, String[] args) { + if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG) + " " + Arrays.toString(this.getArguments()), sender)) { + return; } String importArg = args[0]; @@ -47,13 +43,13 @@ public class ManageImportCommand extends SubCommand { .map(Importer::getNames) .map(list -> list.get(0)) .forEach(name -> sender.sendMessage("- " + name)); - return true; + return; } Importer importer = ImporterManager.getImporter(importArg); if (importer == null) { sender.sendMessage("§eImporter '" + importArg + "' doesn't exist"); - return true; + return; } RunnableFactory.createNew("Import:" + importArg, new AbsRunnable() { @@ -66,6 +62,5 @@ public class ManageImportCommand extends SubCommand { } } }).runTaskAsynchronously(); - return true; } } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageMoveCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageMoveCommand.java index f6ff42b13..1e6965a98 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageMoveCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageMoveCommand.java @@ -8,9 +8,9 @@ import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.utilities.Condition; import com.djrapitops.plan.utilities.ManageUtils; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.RunnableFactory; import com.djrapitops.plugin.utilities.Verify; @@ -23,42 +23,40 @@ import com.djrapitops.plugin.utilities.Verify; * @author Rsl1122 * @since 2.3.0 */ -public class ManageMoveCommand extends SubCommand { +public class ManageMoveCommand extends CommandNode { public ManageMoveCommand() { - super("move", - CommandType.PLAYER_OR_ARGS, - Permissions.MANAGE.getPermission(), - Locale.get(Msg.CMD_USG_MANAGE_MOVE).toString(), - " [-a]"); + super("move", Permissions.MANAGE.getPermission(), CommandType.PLAYER_OR_ARGS); + setShortHelp(Locale.get(Msg.CMD_USG_MANAGE_MOVE).toString()); + setArguments("", "", "[-a]"); } @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { if (!Condition.isTrue(args.length >= 2, Locale.get(Msg.CMD_FAIL_REQ_ARGS).parse(this.getArguments()), sender)) { - return true; + return; } String fromDB = args[0].toLowerCase(); boolean isCorrectDB = "sqlite".equals(fromDB) || "mysql".equals(fromDB); if (!Condition.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + fromDB, sender)) { - return true; + return; } String toDB = args[1].toLowerCase(); isCorrectDB = "sqlite".equals(toDB) || "mysql".equals(toDB); if (!Condition.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + toDB, sender)) { - return true; + return; } if (!Condition.isTrue(!Verify.equalsIgnoreCase(fromDB, toDB), Locale.get(Msg.MANAGE_FAIL_SAME_DB).toString(), sender)) { - return true; + return; } if (!Condition.isTrue(Verify.contains("-a", args), Locale.get(Msg.MANAGE_FAIL_CONFIRM).parse(Locale.get(Msg.MANAGE_NOTIFY_REMOVE).parse(args[1])), sender)) { - return true; + return; } try { @@ -69,7 +67,6 @@ public class ManageMoveCommand extends SubCommand { } catch (Exception e) { sender.sendMessage(Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString()); } - return true; } private void runMoveTask(final Database fromDatabase, final Database toDatabase, ISender sender) { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRemoveCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRemoveCommand.java index 2dc0d9ef0..5131c1a8d 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRemoveCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRemoveCommand.java @@ -1,8 +1,6 @@ package com.djrapitops.plan.command.commands.manage; import com.djrapitops.plan.api.exceptions.database.DBException; -import com.djrapitops.plan.data.container.Session; -import com.djrapitops.plan.system.cache.SessionCache; import com.djrapitops.plan.system.database.databases.Database; import com.djrapitops.plan.system.settings.Permissions; import com.djrapitops.plan.system.settings.locale.Locale; @@ -11,49 +9,39 @@ import com.djrapitops.plan.utilities.Condition; import com.djrapitops.plan.utilities.MiscUtils; import com.djrapitops.plan.utilities.uuid.UUIDUtility; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.RunnableFactory; import com.djrapitops.plugin.utilities.Verify; -import org.bukkit.entity.Player; import java.util.UUID; -import static org.bukkit.Bukkit.getPlayer; - /** * This manage subcommand is used to remove a single player's data from the * database. * * @author Rsl1122 */ -public class ManageRemoveCommand extends SubCommand { +public class ManageRemoveCommand extends CommandNode { public ManageRemoveCommand() { - super("remove", - CommandType.PLAYER_OR_ARGS, - Permissions.MANAGE.getPermission(), - Locale.get(Msg.CMD_USG_MANAGE_REMOVE).toString(), - " [-a]"); + super("remove|delete", Permissions.MANAGE.getPermission(), CommandType.PLAYER_OR_ARGS); + setShortHelp(Locale.get(Msg.CMD_USG_MANAGE_REMOVE).toString()); + setArguments("", "[-a]"); + setInDepthHelp(Locale.get(Msg.CMD_HELP_MANAGE_REMOVE).toArray()); } @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_MANAGE_REMOVE).toArray(); - } - - @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) { - return true; + return; } String playerName = MiscUtils.getPlayerName(args, sender, Permissions.MANAGE); runRemoveTask(playerName, sender, args); - return true; } private void runRemoveTask(String playerName, ISender sender, String[] args) { @@ -83,11 +71,6 @@ public class ManageRemoveCommand extends SubCommand { database.remove().player(uuid); - Player player = getPlayer(uuid); - if (player != null) { - SessionCache.getActiveSessions().remove(uuid); - SessionCache.getInstance().cacheSession(uuid, new Session(MiscUtils.getTime(), player.getWorld().getName(), player.getGameMode().name())); - } sender.sendMessage(Locale.get(Msg.MANAGE_INFO_REMOVE_SUCCESS).parse(playerName, Database.getActive().getConfigName())); } catch (DBException e) { Log.toLog(this.getClass(), e); diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRestoreCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRestoreCommand.java index 06e2e1485..fa9007768 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRestoreCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageRestoreCommand.java @@ -1,6 +1,6 @@ package com.djrapitops.plan.command.commands.manage; -import com.djrapitops.plan.Plan; +import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.system.database.DBSystem; import com.djrapitops.plan.system.database.databases.Database; import com.djrapitops.plan.system.database.databases.sql.SQLiteDB; @@ -10,14 +10,15 @@ import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.utilities.Condition; import com.djrapitops.plan.utilities.ManageUtils; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.RunnableFactory; import com.djrapitops.plugin.utilities.Verify; import java.io.File; +import java.util.Arrays; /** * This manage SubCommand is used to restore a backup.db file in the @@ -25,35 +26,33 @@ import java.io.File; * * @author Rsl1122 */ -public class ManageRestoreCommand extends SubCommand { +public class ManageRestoreCommand extends CommandNode { - private final Plan plugin; + private final PlanPlugin plugin; - public ManageRestoreCommand(Plan plugin) { - super("restore", - CommandType.CONSOLE, - Permissions.MANAGE.getPermission(), - Locale.get(Msg.CMD_USG_MANAGE_RESTORE).toString(), - " [-a]"); + public ManageRestoreCommand(PlanPlugin plugin) { + super("restore", Permissions.MANAGE.getPermission(), CommandType.CONSOLE); + setShortHelp(Locale.get(Msg.CMD_USG_MANAGE_RESTORE).toString()); + setArguments("", "", "[-a]"); this.plugin = plugin; } @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { - if (!Condition.isTrue(args.length >= 2, Locale.get(Msg.CMD_FAIL_REQ_ARGS).parse(this.getArguments()), sender)) { - return true; + public void onCommand(ISender sender, String commandLabel, String[] args) { + if (!Condition.isTrue(args.length >= 2, Locale.get(Msg.CMD_FAIL_REQ_ARGS).parse(Arrays.toString(this.getArguments())), sender)) { + return; } String db = args[1].toLowerCase(); boolean isCorrectDB = "sqlite".equals(db) || "mysql".equals(db); if (!Condition.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + db, sender)) { - return true; + return; } if (!Condition.isTrue(Verify.contains("-a", args), Locale.get(Msg.MANAGE_FAIL_CONFIRM).parse(Locale.get(Msg.MANAGE_NOTIFY_REWRITE).parse(args[1])), sender)) { - return true; + return; } try { @@ -63,7 +62,6 @@ public class ManageRestoreCommand extends SubCommand { } catch (Exception e) { sender.sendMessage(Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString()); } - return true; } private void runRestoreTask(String[] args, ISender sender, final Database database) { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageSetupCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageSetupCommand.java index 137d7bb07..6f0cf2a7b 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageSetupCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageSetupCommand.java @@ -10,9 +10,9 @@ import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.system.webserver.WebServerSystem; import com.djrapitops.plan.utilities.Condition; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; /** * This manage SubCommand is used to request settings from Bungee so that connection can be established. @@ -20,42 +20,34 @@ import com.djrapitops.plugin.command.SubCommand; * @author Rsl1122 * @since 2.3.0 */ -public class ManageSetupCommand extends SubCommand { +public class ManageSetupCommand extends CommandNode { public ManageSetupCommand() { - super("setup", - CommandType.PLAYER_OR_ARGS, - Permissions.MANAGE.getPermission(), - "Set-Up Bungee WebServer connection", - ""); + super("setup", Permissions.MANAGE.getPermission(), CommandType.PLAYER_OR_ARGS); + setShortHelp("Set-Up Bungee connection"); + setArguments(""); + setInDepthHelp(Locale.get(Msg.CMD_HELP_MANAGE_HOTSWAP).toArray()); } @Override - public String[] addHelp() { - return Locale.get(Msg.CMD_HELP_MANAGE_HOTSWAP).toArray(); - } - - @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) { - return true; + return; } if (!WebServerSystem.isWebServerEnabled()) { sender.sendMessage("§cWebServer is not enabled on this server! Make sure it enables on boot!"); - return true; + return; } String address = args[0].toLowerCase(); if (!address.startsWith("http") || address.endsWith("://")) { sender.sendMessage("§cMake sure you're using the full address (Starts with http:// or https://) - Check Bungee enable log for the full address."); - return true; + return; } if (address.endsWith("/")) { address = address.substring(0, address.length() - 1); } requestSetup(sender, address); - - return true; } private void requestSetup(ISender sender, String address) { diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebCheckCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebCheckCommand.java index 4723e8a4f..ec963f0ae 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebCheckCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebCheckCommand.java @@ -7,9 +7,9 @@ import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.utilities.Condition; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.RunnableFactory; import org.bukkit.ChatColor; @@ -20,20 +20,18 @@ import org.bukkit.ChatColor; * @author Rsl1122 * @since 3.5.2 */ -public class WebCheckCommand extends SubCommand { +public class WebCheckCommand extends CommandNode { public WebCheckCommand() { - super("check", - CommandType.PLAYER_OR_ARGS, - Permissions.MANAGE_WEB.getPerm(), - Locale.get(Msg.CMD_USG_WEB_CHECK).toString(), - ""); + super("check", Permissions.MANAGE_WEB.getPerm(), CommandType.PLAYER_OR_ARGS); + setShortHelp(Locale.get(Msg.CMD_USG_WEB_CHECK).toString()); + setArguments(""); } @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).parse() + " ", sender)) { - return true; + return; } Database database = Database.getActive(); String user = args[0]; @@ -55,7 +53,6 @@ public class WebCheckCommand extends SubCommand { } } }).runTaskAsynchronously(); - return true; } } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebDeleteCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebDeleteCommand.java index cd383a4be..2c8acb35a 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebDeleteCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebDeleteCommand.java @@ -6,9 +6,9 @@ import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.utilities.Condition; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.RunnableFactory; import net.md_5.bungee.api.ChatColor; @@ -19,20 +19,18 @@ import net.md_5.bungee.api.ChatColor; * @author Rsl1122 * @since 3.5.2 */ -public class WebDeleteCommand extends SubCommand { +public class WebDeleteCommand extends CommandNode { public WebDeleteCommand() { - super("delete, remove", - CommandType.PLAYER_OR_ARGS, - Permissions.MANAGE_WEB.getPerm(), - Locale.get(Msg.CMD_USG_WEB_DELETE).toString(), - ""); + super("delete|remove", Permissions.MANAGE_WEB.getPerm(), CommandType.PLAYER_OR_ARGS); + setShortHelp(Locale.get(Msg.CMD_USG_WEB_DELETE).toString()); + setArguments(""); } @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).parse() + " ", sender)) { - return true; + return; } Database database = Database.getActive(); String user = args[0]; @@ -54,7 +52,6 @@ public class WebDeleteCommand extends SubCommand { } } }).runTaskAsynchronously(); - return true; } } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebLevelCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebLevelCommand.java index 033f436ac..1a054105f 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebLevelCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebLevelCommand.java @@ -4,9 +4,9 @@ import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.system.settings.Permissions; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.settings.ColorScheme; /** @@ -15,20 +15,18 @@ import com.djrapitops.plugin.settings.ColorScheme; * @author Rsl1122 * @since 3.5.2 */ -public class WebLevelCommand extends SubCommand { +public class WebLevelCommand extends CommandNode { private final PlanPlugin plugin; public WebLevelCommand(PlanPlugin plugin) { - super("level", - CommandType.CONSOLE, - Permissions.MANAGE_WEB.getPerm(), - Locale.get(Msg.CMD_USG_WEB_LEVEL).toString()); + super("level", Permissions.MANAGE_WEB.getPerm(), CommandType.CONSOLE); + setShortHelp(Locale.get(Msg.CMD_USG_WEB_LEVEL).toString()); this.plugin = plugin; } @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { ColorScheme cs = plugin.getColorScheme(); String sCol = cs.getSecondaryColor(); String cmdBall = Locale.get(Msg.CMD_CONSTANT_LIST_BALL).parse(); @@ -44,7 +42,6 @@ public class WebLevelCommand extends SubCommand { }; sender.sendMessage(messages); - return true; } } diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebListUsersCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebListUsersCommand.java index ba3ecd59a..55f775ae3 100644 --- a/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebListUsersCommand.java +++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/webuser/WebListUsersCommand.java @@ -8,9 +8,9 @@ import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; import com.djrapitops.plan.utilities.comparators.WebUserComparator; import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.command.CommandNode; import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.ISender; -import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.settings.ColorScheme; import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.RunnableFactory; @@ -23,17 +23,18 @@ import java.util.List; * @author Rsl1122 * @since 3.5.2 */ -public class WebListUsersCommand extends SubCommand { +public class WebListUsersCommand extends CommandNode { private final PlanPlugin plugin; public WebListUsersCommand(PlanPlugin plugin) { - super("list", CommandType.CONSOLE, Permissions.MANAGE_WEB.getPerm(), "List registered web users & permission levels."); + super("list", Permissions.MANAGE_WEB.getPerm(), CommandType.CONSOLE); + setShortHelp("List registered web users & permission levels."); this.plugin = plugin; } @Override - public boolean onCommand(ISender sender, String commandLabel, String[] args) { + public void onCommand(ISender sender, String commandLabel, String[] args) { RunnableFactory.createNew(new AbsRunnable("Webuser List Task") { @Override public void run() { @@ -55,7 +56,6 @@ public class WebListUsersCommand extends SubCommand { } } }).runTaskAsynchronously(); - return true; } } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/Actions.java b/Plan/src/main/java/com/djrapitops/plan/data/Actions.java index f7784fe22..d9f7a5a9e 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/Actions.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/Actions.java @@ -4,7 +4,7 @@ */ package com.djrapitops.plan.data; -import org.apache.commons.lang3.text.WordUtils; +import org.apache.commons.text.WordUtils; /** * IDs of various actions diff --git a/Plan/src/main/java/com/djrapitops/plan/data/PlayerProfile.java b/Plan/src/main/java/com/djrapitops/plan/data/PlayerProfile.java index 999404cf5..e31d2e820 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/PlayerProfile.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/PlayerProfile.java @@ -241,7 +241,7 @@ public class PlayerProfile { public GeoInfo getMostRecentGeoInfo() { if (geoInformation.isEmpty()) { - return new GeoInfo("-", "Not Known", MiscUtils.getTime()); + return new GeoInfo("-", "Not Known", MiscUtils.getTime(), ""); } geoInformation.sort(new GeoInfoComparator()); return geoInformation.get(0); diff --git a/Plan/src/main/java/com/djrapitops/plan/data/container/GeoInfo.java b/Plan/src/main/java/com/djrapitops/plan/data/container/GeoInfo.java index f34bf5f21..89f6429b7 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/container/GeoInfo.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/container/GeoInfo.java @@ -4,8 +4,13 @@ */ package com.djrapitops.plan.data.container; +import com.djrapitops.plan.utilities.FormatUtils; +import com.djrapitops.plan.utilities.SHA256Hash; import com.google.common.base.Objects; +import java.io.UnsupportedEncodingException; +import java.security.NoSuchAlgorithmException; + /** * Data class that contains information about IP and Geolocation. * @@ -15,12 +20,19 @@ public class GeoInfo { private final String ip; private final String geolocation; + private final String ipHash; private final long lastUsed; - public GeoInfo(String ip, String geolocation, long lastUsed) { + public GeoInfo(String ip, String geolocation, long lastUsed) + throws UnsupportedEncodingException, NoSuchAlgorithmException { + this(FormatUtils.formatIP(ip), geolocation, lastUsed, new SHA256Hash(ip).create()); + } + + public GeoInfo(String ip, String geolocation, long lastUsed, String ipHash) { this.ip = ip; this.geolocation = geolocation; this.lastUsed = lastUsed; + this.ipHash = ipHash; } public String getIp() { @@ -35,6 +47,10 @@ public class GeoInfo { return lastUsed; } + public String getIpHash() { + return ipHash; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/Plan/src/main/java/com/djrapitops/plan/system/BukkitSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/BukkitSystem.java index 63019c76c..dc22a04e3 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/BukkitSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/BukkitSystem.java @@ -9,13 +9,13 @@ import com.djrapitops.plan.ShutdownHook; import com.djrapitops.plan.api.ServerAPI; import com.djrapitops.plan.api.exceptions.EnableException; import com.djrapitops.plan.data.plugin.HookHandler; -import com.djrapitops.plan.system.database.BukkitDBSystem; +import com.djrapitops.plan.system.database.ServerDBSystem; import com.djrapitops.plan.system.file.FileSystem; -import com.djrapitops.plan.system.info.BukkitInfoSystem; +import com.djrapitops.plan.system.info.ServerInfoSystem; import com.djrapitops.plan.system.info.server.BukkitServerInfo; import com.djrapitops.plan.system.listeners.BukkitListenerSystem; import com.djrapitops.plan.system.settings.PlanErrorManager; -import com.djrapitops.plan.system.settings.config.BukkitConfigSystem; +import com.djrapitops.plan.system.settings.config.ServerConfigSystem; import com.djrapitops.plan.system.settings.network.NetworkSettings; import com.djrapitops.plan.system.tasks.BukkitTaskSystem; import com.djrapitops.plan.system.update.VersionCheckSystem; @@ -37,12 +37,12 @@ public class BukkitSystem extends PlanSystem implements ServerSystem { versionCheckSystem = new VersionCheckSystem(plugin.getVersion()); fileSystem = new FileSystem(plugin); - configSystem = new BukkitConfigSystem(); - databaseSystem = new BukkitDBSystem(); + configSystem = new ServerConfigSystem(); + databaseSystem = new ServerDBSystem(); listenerSystem = new BukkitListenerSystem(plugin); taskSystem = new BukkitTaskSystem(plugin); - infoSystem = new BukkitInfoSystem(); + infoSystem = new ServerInfoSystem(); serverInfo = new BukkitServerInfo(plugin); hookHandler = new HookHandler(); diff --git a/Plan/src/main/java/com/djrapitops/plan/system/PlanSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/PlanSystem.java index d2a42788e..516dd7b02 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/PlanSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/PlanSystem.java @@ -81,9 +81,9 @@ public abstract class PlanSystem implements SubSystem { checkSubSystemInitialization(); SubSystem[] systems = new SubSystem[]{ - versionCheckSystem, fileSystem, configSystem, + versionCheckSystem, databaseSystem, webServerSystem, processing, diff --git a/Plan/src/main/java/com/djrapitops/plan/system/SpongeSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/SpongeSystem.java index 90169df5c..7bfb57173 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/SpongeSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/SpongeSystem.java @@ -9,13 +9,13 @@ import com.djrapitops.plan.ShutdownHook; import com.djrapitops.plan.api.ServerAPI; import com.djrapitops.plan.api.exceptions.EnableException; import com.djrapitops.plan.data.plugin.HookHandler; -import com.djrapitops.plan.system.database.BukkitDBSystem; +import com.djrapitops.plan.system.database.ServerDBSystem; import com.djrapitops.plan.system.file.FileSystem; -import com.djrapitops.plan.system.info.BukkitInfoSystem; +import com.djrapitops.plan.system.info.ServerInfoSystem; import com.djrapitops.plan.system.info.server.SpongeServerInfo; import com.djrapitops.plan.system.listeners.SpongeListenerSystem; import com.djrapitops.plan.system.settings.PlanErrorManager; -import com.djrapitops.plan.system.settings.config.BukkitConfigSystem; +import com.djrapitops.plan.system.settings.config.SpongeConfigSystem; import com.djrapitops.plan.system.settings.network.NetworkSettings; import com.djrapitops.plan.system.tasks.SpongeTaskSystem; import com.djrapitops.plan.system.update.VersionCheckSystem; @@ -29,6 +29,8 @@ import com.djrapitops.plugin.api.utility.log.Log; */ public class SpongeSystem extends PlanSystem implements ServerSystem { + private boolean firstInstall = false; + public SpongeSystem(PlanSponge plugin) { testSystem = this; @@ -36,12 +38,12 @@ public class SpongeSystem extends PlanSystem implements ServerSystem { versionCheckSystem = new VersionCheckSystem(plugin.getVersion()); fileSystem = new FileSystem(plugin); - configSystem = new BukkitConfigSystem(); - databaseSystem = new BukkitDBSystem(); - listenerSystem = new SpongeListenerSystem(); - taskSystem = new SpongeTaskSystem(); + configSystem = new SpongeConfigSystem(); + databaseSystem = new ServerDBSystem(); + listenerSystem = new SpongeListenerSystem(plugin); + taskSystem = new SpongeTaskSystem(plugin); - infoSystem = new BukkitInfoSystem(); + infoSystem = new ServerInfoSystem(); serverInfo = new SpongeServerInfo(); hookHandler = new HookHandler(); diff --git a/Plan/src/main/java/com/djrapitops/plan/system/cache/GeolocationCache.java b/Plan/src/main/java/com/djrapitops/plan/system/cache/GeolocationCache.java index 353083fac..29b1dd6cb 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/cache/GeolocationCache.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/cache/GeolocationCache.java @@ -3,6 +3,7 @@ package com.djrapitops.plan.system.cache; import com.djrapitops.plan.api.exceptions.EnableException; import com.djrapitops.plan.system.SubSystem; import com.djrapitops.plan.system.file.FileSystem; +import com.djrapitops.plan.system.settings.Settings; import com.djrapitops.plugin.api.utility.log.Log; import com.djrapitops.plugin.utilities.Verify; import com.google.common.cache.Cache; @@ -45,12 +46,14 @@ public class GeolocationCache implements SubSystem { @Override public void enable() throws EnableException { geolocationDB = new File(FileSystem.getDataFolder(), "GeoIP.dat"); - try { - GeolocationCache.checkDB(); - } catch (UnknownHostException e) { - Log.error("Plan Requires internet access on first run to download GeoLite2 Geolocation database."); - } catch (IOException e) { - throw new EnableException("Something went wrong saving the downloaded GeoLite2 Geolocation database", e); + if (Settings.DATA_GEOLOCATIONS.isTrue()) { + try { + GeolocationCache.checkDB(); + } catch (UnknownHostException e) { + Log.error("Plan Requires internet access on first run to download GeoLite2 Geolocation database."); + } catch (IOException e) { + throw new EnableException("Something went wrong saving the downloaded GeoLite2 Geolocation database", e); + } } } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/DBSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/database/DBSystem.java index 54cbd3472..73393e5ec 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/DBSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/DBSystem.java @@ -50,7 +50,8 @@ public abstract class DBSystem implements SubSystem { Benchmark.stop("Enable", "Init Database"); } catch (DBInitException e) { Throwable cause = e.getCause(); - throw new EnableException(db.getName() + " init failure: " + cause.getMessage(), cause); + String message = cause == null ? e.getMessage() : cause.getMessage(); + throw new EnableException((db != null ? db.getName() : "Database") + " init failure: " + message, cause); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/BukkitDBSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/database/ServerDBSystem.java similarity index 76% rename from Plan/src/main/java/com/djrapitops/plan/system/database/BukkitDBSystem.java rename to Plan/src/main/java/com/djrapitops/plan/system/database/ServerDBSystem.java index 50837dc6e..c17ec6e63 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/BukkitDBSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/ServerDBSystem.java @@ -7,18 +7,20 @@ package com.djrapitops.plan.system.database; import com.djrapitops.plan.api.exceptions.database.DBInitException; import com.djrapitops.plan.system.database.databases.sql.MySQLDB; import com.djrapitops.plan.system.database.databases.sql.SQLiteDB; +import com.djrapitops.plan.system.database.databases.sql.SpongeMySQLDB; import com.djrapitops.plan.system.settings.Settings; +import com.djrapitops.plugin.api.Check; /** * Bukkit Database system that initializes SQLite and MySQL database objects. * * @author Rsl1122 */ -public class BukkitDBSystem extends DBSystem { +public class ServerDBSystem extends DBSystem { @Override protected void initDatabase() throws DBInitException { - databases.add(new MySQLDB()); + databases.add(Check.isSpongeAvailable() ? new SpongeMySQLDB() : new MySQLDB()); databases.add(new SQLiteDB()); String dbType = Settings.DB_TYPE.toString().toLowerCase().trim(); diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/MySQLDB.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/MySQLDB.java index 34cf4fed0..01f8321d2 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/MySQLDB.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/MySQLDB.java @@ -1,9 +1,11 @@ package com.djrapitops.plan.system.database.databases.sql; +import com.djrapitops.plan.api.exceptions.database.DBInitException; import com.djrapitops.plan.system.settings.Settings; import com.djrapitops.plugin.api.utility.log.Log; import org.apache.commons.dbcp2.BasicDataSource; +import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; @@ -12,7 +14,7 @@ import java.sql.SQLException; */ public class MySQLDB extends SQLDB { - private BasicDataSource dataSource; + protected DataSource dataSource; public MySQLDB() { } @@ -21,8 +23,9 @@ public class MySQLDB extends SQLDB { * Setups the {@link BasicDataSource} */ @Override - public void setupDataSource() { - dataSource = new BasicDataSource(); + public void setupDataSource() throws DBInitException { + BasicDataSource dataSource = new BasicDataSource(); + this.dataSource = dataSource; dataSource.setDriverClassName("com.mysql.jdbc.Driver"); String host = Settings.DB_HOST.toString(); @@ -62,7 +65,9 @@ public class MySQLDB extends SQLDB { @Override public void close() { try { - dataSource.close(); + if (dataSource != null && dataSource instanceof BasicDataSource) { + ((BasicDataSource) dataSource).close(); + } } catch (SQLException e) { Log.toLog(this.getClass(), e); } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/SQLDB.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/SQLDB.java index 9935158f9..dd28c3101 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/SQLDB.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/SQLDB.java @@ -1,11 +1,13 @@ package com.djrapitops.plan.system.database.databases.sql; +import com.djrapitops.plan.api.exceptions.database.DBException; import com.djrapitops.plan.api.exceptions.database.DBInitException; import com.djrapitops.plan.system.database.databases.Database; import com.djrapitops.plan.system.database.databases.operation.*; import com.djrapitops.plan.system.database.databases.sql.operation.*; import com.djrapitops.plan.system.database.databases.sql.tables.*; import com.djrapitops.plan.system.database.databases.sql.tables.move.Version8TransferTable; +import com.djrapitops.plan.system.settings.Settings; import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.api.utility.log.Log; import com.djrapitops.plugin.task.AbsRunnable; @@ -15,6 +17,10 @@ import org.apache.commons.dbcp2.BasicDataSource; import java.sql.Connection; import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; /** * Class containing main logic for different data related save and load functionality. @@ -133,7 +139,7 @@ public abstract class SQLDB extends Database { if (newDatabase) { Log.info("New Database created."); - versionTable.setVersion(16); + versionTable.setVersion(17); } int version = versionTable.getVersion(); @@ -177,6 +183,10 @@ public abstract class SQLDB extends Database { worldTimesTable.alterTableV16(); versionTable.setVersion(16); } + if (version < 17) { + geoInfoTable.alterTableV17(); + versionTable.setVersion(17); + } } catch (SQLException e) { throw new DBInitException("Failed to set-up Database", e); } @@ -246,6 +256,22 @@ public abstract class SQLDB extends Database { private void clean() throws SQLException { tpsTable.clean(); transferTable.clean(); + + long now = System.currentTimeMillis(); + long keepActiveAfter = now - TimeAmount.DAY.ms() * Settings.KEEP_INACTIVE_PLAYERS_DAYS.getNumber(); + + List inactivePlayers = sessionsTable.getLastSeenForAllPlayers().entrySet().stream() + .filter(entry -> entry.getValue() > keepActiveAfter) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + for (UUID uuid : inactivePlayers) { + try { + removeOps.player(uuid); + } catch (DBException e) { + Log.toLog(this.getClass().getName(), e); + } + } + Log.info("Removed data of " + inactivePlayers.size() + " players."); } public abstract Connection getConnection() throws SQLException; diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/SpongeMySQLDB.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/SpongeMySQLDB.java new file mode 100644 index 000000000..a066005ca --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/SpongeMySQLDB.java @@ -0,0 +1,47 @@ +package com.djrapitops.plan.system.database.databases.sql; + +import com.djrapitops.plan.api.exceptions.database.DBInitException; +import com.djrapitops.plan.system.settings.Settings; +import com.djrapitops.plugin.api.utility.log.Log; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.service.sql.SqlService; + +import java.sql.SQLException; +import java.util.Optional; + +/** + * MySQLDB implementation for Sponge since default driver is not available. + * + * @author Rsl1122 + */ +public class SpongeMySQLDB extends MySQLDB { + + @Override + public void setupDataSource() throws DBInitException { + Optional sqlServiceProvider = Sponge.getServiceManager().provide(SqlService.class); + if (!sqlServiceProvider.isPresent()) { + return; + } + + String host = Settings.DB_HOST.toString(); + String port = Integer.toString(Settings.DB_PORT.getNumber()); + String database = Settings.DB_DATABASE.toString(); + String launchOptions = Settings.DB_LAUNCH_OPTIONS.toString(); + if (launchOptions.isEmpty() || !launchOptions.startsWith("?") || launchOptions.endsWith("&")) { + Log.error("Launch Options were faulty, using default (?rewriteBatchedStatements=true&useSSL=false)"); + launchOptions = "?rewriteBatchedStatements=true&useSSL=false"; + } + + String url = host + ":" + port + "/" + database + launchOptions; + String username = Settings.DB_USER.toString(); + String password = Settings.DB_PASS.toString(); + try { + this.dataSource = sqlServiceProvider.get().getDataSource( + "jdbc:mysql://" + username + ":" + password + "@" + url + ); + } catch (SQLException e) { + throw new DBInitException(e); + } + } + +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/GeoInfoTable.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/GeoInfoTable.java index b401cda14..24a6ed238 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/GeoInfoTable.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/GeoInfoTable.java @@ -10,8 +10,14 @@ import com.djrapitops.plan.system.database.databases.sql.statements.Column; import com.djrapitops.plan.system.database.databases.sql.statements.Select; import com.djrapitops.plan.system.database.databases.sql.statements.Sql; import com.djrapitops.plan.system.database.databases.sql.statements.TableSqlParser; +import com.djrapitops.plan.system.settings.Settings; +import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.task.AbsRunnable; +import com.djrapitops.plugin.task.RunnableFactory; import com.djrapitops.plugin.utilities.Verify; +import java.io.UnsupportedEncodingException; +import java.security.NoSuchAlgorithmException; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -33,11 +39,12 @@ public class GeoInfoTable extends UserIDTable { insertStatement = "INSERT INTO " + tableName + " (" + Col.USER_ID + ", " + Col.IP + ", " + + Col.IP_HASH + ", " + Col.GEOLOCATION + ", " + Col.LAST_USED + ") VALUES (" + usersTable.statementSelectID + ", " - + "?, ?, ?)"; + + "?, ?, ?, ?)"; } private String insertStatement; @@ -48,6 +55,7 @@ public class GeoInfoTable extends UserIDTable { .column(Col.USER_ID, Sql.INT).notNull() .column(Col.IP, Sql.varchar(39)).notNull() .column(Col.GEOLOCATION, Sql.varchar(50)).notNull() + .column(Col.IP_HASH, Sql.varchar(200)) .column(Col.LAST_USED, Sql.LONG).notNull().defaultValue("0") .foreignKey(Col.USER_ID, usersTable.getTableName(), UsersTable.Col.ID) .toString() @@ -64,6 +72,49 @@ public class GeoInfoTable extends UserIDTable { addColumns(Col.LAST_USED + " bigint NOT NULL DEFAULT 0"); } + public void alterTableV17() { + addColumns(Col.IP_HASH.get() + " varchar(200) DEFAULT ''"); + + RunnableFactory.createNew("DB Version 16->17", new AbsRunnable() { + @Override + public void run() { + try { + Map> allGeoInfo = getAllGeoInfo(); + + String sql = "UPDATE " + tableName + " SET " + + Col.IP + "=?, " + + Col.IP_HASH + "=? " + + "WHERE " + Col.IP + "=?"; + executeBatch(new ExecStatement(sql) { + @Override + public void prepare(PreparedStatement statement) throws SQLException { + for (List geoInfos : allGeoInfo.values()) { + for (GeoInfo geoInfo : geoInfos) { + try { + GeoInfo updatedInfo = new GeoInfo( + geoInfo.getIp(), + geoInfo.getGeolocation(), + geoInfo.getLastUsed() + ); + statement.setString(1, updatedInfo.getIp()); + statement.setString(2, updatedInfo.getIpHash()); + statement.setString(3, geoInfo.getIp()); + } catch (UnsupportedEncodingException | NoSuchAlgorithmException e) { + if (Settings.DEV_MODE.isTrue()) { + Log.toLog(this.getClass(), e); + } + } + } + } + } + }); + } catch (SQLException e) { + e.printStackTrace(); + } + } + }); + } + public List getGeoInfo(UUID uuid) throws SQLException { String sql = "SELECT DISTINCT * FROM " + tableName + " WHERE " + Col.USER_ID + "=" + usersTable.statementSelectID; @@ -80,8 +131,9 @@ public class GeoInfoTable extends UserIDTable { while (set.next()) { String ip = set.getString(Col.IP.get()); String geolocation = set.getString(Col.GEOLOCATION.get()); + String ipHash = set.getString(Col.IP_HASH.get()); long lastUsed = set.getLong(Col.LAST_USED.get()); - geoInfo.add(new GeoInfo(ip, geolocation, lastUsed)); + geoInfo.add(new GeoInfo(ip, geolocation, lastUsed, ipHash)); } return geoInfo; } @@ -92,7 +144,7 @@ public class GeoInfoTable extends UserIDTable { String sql = "UPDATE " + tableName + " SET " + Col.LAST_USED + "=?" + " WHERE " + Col.USER_ID + "=" + usersTable.statementSelectID + - " AND " + Col.IP + "=?" + + " AND " + Col.IP_HASH + "=?" + " AND " + Col.GEOLOCATION + "=?"; execute(new ExecStatement(sql) { @@ -100,7 +152,7 @@ public class GeoInfoTable extends UserIDTable { public void prepare(PreparedStatement statement) throws SQLException { statement.setLong(1, info.getLastUsed()); statement.setString(2, uuid.toString()); - statement.setString(3, info.getIp()); + statement.setString(3, info.getIpHash()); statement.setString(4, info.getGeolocation()); } }); @@ -120,8 +172,9 @@ public class GeoInfoTable extends UserIDTable { public void prepare(PreparedStatement statement) throws SQLException { statement.setString(1, uuid.toString()); statement.setString(2, info.getIp()); - statement.setString(3, info.getGeolocation()); - statement.setLong(4, info.getLastUsed()); + statement.setString(3, info.getIpHash()); + statement.setString(4, info.getGeolocation()); + statement.setLong(5, info.getLastUsed()); } }); } @@ -154,6 +207,7 @@ public class GeoInfoTable extends UserIDTable { Col.IP + ", " + Col.GEOLOCATION + ", " + Col.LAST_USED + ", " + + Col.IP_HASH + ", " + usersUUIDColumn + " FROM " + tableName + " INNER JOIN " + usersTable + " on " + usersIDColumn + "=" + Col.USER_ID; @@ -169,8 +223,9 @@ public class GeoInfoTable extends UserIDTable { String ip = set.getString(Col.IP.get()); String geolocation = set.getString(Col.GEOLOCATION.get()); + String ipHash = set.getString(Col.IP_HASH.get()); long lastUsed = set.getLong(Col.LAST_USED.get()); - userGeoInfo.add(new GeoInfo(ip, geolocation, lastUsed)); + userGeoInfo.add(new GeoInfo(ip, geolocation, lastUsed, ipHash)); geoLocations.put(uuid, userGeoInfo); } @@ -203,9 +258,40 @@ public class GeoInfoTable extends UserIDTable { }); } + public void insertAllGeoInfo(Map> allIPsAndGeolocations) throws SQLException { + if (Verify.isEmpty(allIPsAndGeolocations)) { + return; + } + + executeBatch(new ExecStatement(insertStatement) { + @Override + public void prepare(PreparedStatement statement) throws SQLException { + // Every User + for (UUID uuid : allIPsAndGeolocations.keySet()) { + // Every GeoInfo + for (GeoInfo info : allIPsAndGeolocations.get(uuid)) { + String ip = info.getIp(); + String ipHash = info.getIpHash(); + String geoLocation = info.getGeolocation(); + long lastUsed = info.getLastUsed(); + + statement.setString(1, uuid.toString()); + statement.setString(2, ip); + statement.setString(3, ipHash); + statement.setString(4, geoLocation); + statement.setLong(5, lastUsed); + + statement.addBatch(); + } + } + } + }); + } + public enum Col implements Column { USER_ID(UserIDTable.Col.USER_ID.get()), IP("ip"), + IP_HASH("ip_hash"), GEOLOCATION("geolocation"), LAST_USED("last_used"); @@ -225,32 +311,4 @@ public class GeoInfoTable extends UserIDTable { return column; } } - - public void insertAllGeoInfo(Map> allIPsAndGeolocations) throws SQLException { - if (Verify.isEmpty(allIPsAndGeolocations)) { - return; - } - - executeBatch(new ExecStatement(insertStatement) { - @Override - public void prepare(PreparedStatement statement) throws SQLException { - // Every User - for (UUID uuid : allIPsAndGeolocations.keySet()) { - // Every GeoInfo - for (GeoInfo info : allIPsAndGeolocations.get(uuid)) { - String ip = info.getIp(); - String geoLocation = info.getGeolocation(); - long lastUsed = info.getLastUsed(); - - statement.setString(1, uuid.toString()); - statement.setString(2, ip); - statement.setString(3, geoLocation); - statement.setLong(4, lastUsed); - - statement.addBatch(); - } - } - } - }); - } } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/file/FileSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/file/FileSystem.java index 953c2277f..affecc907 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/file/FileSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/file/FileSystem.java @@ -8,7 +8,11 @@ import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.api.exceptions.EnableException; import com.djrapitops.plan.system.PlanSystem; import com.djrapitops.plan.system.SubSystem; +import com.djrapitops.plan.system.tasks.LogsFolderCleanTask; import com.djrapitops.plan.utilities.file.FileUtil; +import com.djrapitops.plugin.api.TimeAmount; +import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.task.RunnableFactory; import com.djrapitops.plugin.utilities.Verify; import java.io.File; @@ -63,10 +67,11 @@ public class FileSystem implements SubSystem { if (configFile.exists()) { configFile.createNewFile(); } + RunnableFactory.createNew(new LogsFolderCleanTask(Log.getLogsFolder())) + .runTaskLaterAsynchronously(TimeAmount.SECOND.ticks() * 30L); } catch (IOException e) { throw new EnableException("Failed to create config.yml", e); } - } @Override diff --git a/Plan/src/main/java/com/djrapitops/plan/system/info/BukkitInfoSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/info/ServerInfoSystem.java similarity index 87% rename from Plan/src/main/java/com/djrapitops/plan/system/info/BukkitInfoSystem.java rename to Plan/src/main/java/com/djrapitops/plan/system/info/ServerInfoSystem.java index 3bb0b4b85..8501140ff 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/info/BukkitInfoSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/info/ServerInfoSystem.java @@ -6,7 +6,7 @@ package com.djrapitops.plan.system.info; import com.djrapitops.plan.api.exceptions.connection.NoServersException; import com.djrapitops.plan.api.exceptions.connection.WebException; -import com.djrapitops.plan.system.info.connection.BukkitConnectionSystem; +import com.djrapitops.plan.system.info.connection.ServerConnectionSystem; import com.djrapitops.plan.system.info.request.CacheNetworkPageContentRequest; import com.djrapitops.plan.system.info.request.InfoRequest; import com.djrapitops.plan.system.info.request.SetupRequest; @@ -19,10 +19,10 @@ import com.djrapitops.plugin.api.utility.log.Log; * * @author Rsl1122 */ -public class BukkitInfoSystem extends InfoSystem { +public class ServerInfoSystem extends InfoSystem { - public BukkitInfoSystem() { - super(new BukkitConnectionSystem()); + public ServerInfoSystem() { + super(new ServerConnectionSystem()); } @Override diff --git a/Plan/src/main/java/com/djrapitops/plan/system/info/connection/ConnectionSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/info/connection/ConnectionSystem.java index 546c8a884..50d9c9716 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/info/connection/ConnectionSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/info/connection/ConnectionSystem.java @@ -125,6 +125,9 @@ public abstract class ConnectionSystem implements SubSystem { putRequest(requests, SaveDBSettingsRequest.createHandler()); putRequest(requests, SendDBSettingsRequest.createHandler()); putRequest(requests, CheckConnectionRequest.createHandler()); + +// putRequest(requests, UpdateRequest.createHandler()); +// putRequest(requests, UpdateCancelRequest.createHandler()); return requests; } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/info/connection/BukkitConnectionSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/info/connection/ServerConnectionSystem.java similarity index 98% rename from Plan/src/main/java/com/djrapitops/plan/system/info/connection/BukkitConnectionSystem.java rename to Plan/src/main/java/com/djrapitops/plan/system/info/connection/ServerConnectionSystem.java index 582572595..c0f5c71bd 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/info/connection/BukkitConnectionSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/info/connection/ServerConnectionSystem.java @@ -28,13 +28,13 @@ import java.util.UUID; * * @author Rsl1122 */ -public class BukkitConnectionSystem extends ConnectionSystem { +public class ServerConnectionSystem extends ConnectionSystem { private long latestServerMapRefresh; private Server mainServer; - public BukkitConnectionSystem() { + public ServerConnectionSystem() { latestServerMapRefresh = 0; } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/info/request/CacheInspectPageRequest.java b/Plan/src/main/java/com/djrapitops/plan/system/info/request/CacheInspectPageRequest.java index e1855733f..c1aaba26f 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/info/request/CacheInspectPageRequest.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/info/request/CacheInspectPageRequest.java @@ -17,7 +17,7 @@ import com.djrapitops.plan.system.webserver.response.pages.InspectPageResponse; import com.djrapitops.plan.utilities.Base64Util; import com.djrapitops.plan.utilities.file.export.HtmlExport; import com.djrapitops.plugin.utilities.Verify; -import org.apache.commons.lang3.text.StrSubstitutor; +import org.apache.commons.text.StringSubstitutor; import java.util.Collections; import java.util.Map; @@ -63,7 +63,7 @@ public class CacheInspectPageRequest extends InfoRequestWithVariables implements Map replace = Collections.singletonMap("networkName", ServerInfo.getServerName()); boolean export = Settings.ANALYSIS_EXPORT.isTrue(); - cache(export, uuid, StrSubstitutor.replace(Base64Util.decode(html), replace)); + cache(export, uuid, StringSubstitutor.replace(Base64Util.decode(html), replace)); return DefaultResponses.SUCCESS.get(); } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/info/request/SaveDBSettingsRequest.java b/Plan/src/main/java/com/djrapitops/plan/system/info/request/SaveDBSettingsRequest.java index 63a64136c..a5522ab18 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/info/request/SaveDBSettingsRequest.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/info/request/SaveDBSettingsRequest.java @@ -4,7 +4,7 @@ */ package com.djrapitops.plan.system.info.request; -import com.djrapitops.plan.Plan; +import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.api.exceptions.connection.BadRequestException; import com.djrapitops.plan.api.exceptions.connection.WebException; import com.djrapitops.plan.system.settings.Settings; @@ -64,7 +64,7 @@ public class SaveDBSettingsRequest extends InfoRequestWithVariables implements S Log.info("----------------------------------"); return DefaultResponses.SUCCESS.get(); } finally { - Plan.getInstance().reloadPlugin(true); + PlanPlugin.getInstance().reloadPlugin(true); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/info/request/UpdateCancelRequest.java b/Plan/src/main/java/com/djrapitops/plan/system/info/request/UpdateCancelRequest.java new file mode 100644 index 000000000..e7aeebc55 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/info/request/UpdateCancelRequest.java @@ -0,0 +1,37 @@ +/* + * Licence is provided in the jar as license.yml also here: + * https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml + */ +package com.djrapitops.plan.system.info.request; + +import com.djrapitops.plan.system.update.ShutdownUpdateHook; +import com.djrapitops.plan.system.webserver.response.DefaultResponses; +import com.djrapitops.plan.system.webserver.response.Response; + +import java.util.Map; + +/** + * InfoRequest used for Updating the plugin on a network. + * + * @author Rsl1122 + */ +public class UpdateCancelRequest implements InfoRequest { + + public UpdateCancelRequest() { + } + + public static UpdateCancelRequest createHandler() { + return new UpdateCancelRequest(); + } + + @Override + public void runLocally() { + ShutdownUpdateHook.deActivate(); + } + + @Override + public Response handleRequest(Map variables) { + ShutdownUpdateHook.deActivate(); + return DefaultResponses.SUCCESS.get(); + } +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/info/request/UpdateRequest.java b/Plan/src/main/java/com/djrapitops/plan/system/info/request/UpdateRequest.java new file mode 100644 index 000000000..c724d1abb --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/info/request/UpdateRequest.java @@ -0,0 +1,43 @@ +/* + * Licence is provided in the jar as license.yml also here: + * https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml + */ +package com.djrapitops.plan.system.info.request; + +import com.djrapitops.plan.system.settings.Settings; +import com.djrapitops.plan.system.update.ShutdownUpdateHook; +import com.djrapitops.plan.system.webserver.response.DefaultResponses; +import com.djrapitops.plan.system.webserver.response.Response; +import com.djrapitops.plan.system.webserver.response.api.BadRequestResponse; + +import java.util.Map; + +/** + * InfoRequest used for Updating the plugin on a network. + * + * @author Rsl1122 + */ +public class UpdateRequest implements InfoRequest { + + public UpdateRequest() { + } + + public static UpdateRequest createHandler() { + return new UpdateRequest(); + } + + @Override + public void runLocally() { + new ShutdownUpdateHook().register(); + } + + @Override + public Response handleRequest(Map variables) { + if (Settings.ALLOW_UPDATE.isTrue()) { + new ShutdownUpdateHook().register(); + return DefaultResponses.SUCCESS.get(); + } else { + return new BadRequestResponse("Update not allowed on this server"); + } + } +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/SpongeListenerSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/SpongeListenerSystem.java index 793df78a4..27ccc1def 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/listeners/SpongeListenerSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/SpongeListenerSystem.java @@ -1,14 +1,32 @@ package com.djrapitops.plan.system.listeners; +import com.djrapitops.plan.PlanSponge; +import com.djrapitops.plan.system.listeners.sponge.*; +import org.spongepowered.api.Sponge; + public class SpongeListenerSystem extends ListenerSystem { + private final PlanSponge plugin; + + public SpongeListenerSystem(PlanSponge plugin) { + this.plugin = plugin; + } + @Override protected void registerListeners() { - + plugin.registerListener( + new SpongeAFKListener(), + new SpongeChatListener(), + new SpongeCommandListener(), + new SpongeDeathListener(), + new SpongeGMChangeListener(), + new SpongePlayerListener(), + new SpongeWorldChangeListener() + ); } @Override protected void unregisterListeners() { - + Sponge.getEventManager().unregisterPluginListeners(plugin); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/ChatListener.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/ChatListener.java index 2f767ba06..2a87cd7eb 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/ChatListener.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/ChatListener.java @@ -31,19 +31,23 @@ public class ChatListener implements Listener { } try { - Player p = event.getPlayer(); - UUID uuid = p.getUniqueId(); - String name = p.getName(); - String displayName = p.getDisplayName(); - - SessionCache sessionCache = SessionCache.getInstance(); - if (sessionCache.isFirstSession(uuid)) { - sessionCache.firstSessionMessageSent(uuid); - } - - Processing.submit(new NameProcessor(uuid, name, displayName)); + actOnChatEvent(event); } catch (Exception e) { Log.toLog(this.getClass(), e); } } + + private void actOnChatEvent(AsyncPlayerChatEvent event) { + Player p = event.getPlayer(); + UUID uuid = p.getUniqueId(); + String name = p.getName(); + String displayName = p.getDisplayName(); + + SessionCache sessionCache = SessionCache.getInstance(); + if (sessionCache.isFirstSession(uuid)) { + sessionCache.firstSessionMessageSent(uuid); + } + + Processing.submit(new NameProcessor(uuid, name, displayName)); + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/CommandPreprocessListener.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/CommandPreprocessListener.java index 0d7aabde9..9af4a5f0d 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/CommandPreprocessListener.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/CommandPreprocessListener.java @@ -43,27 +43,31 @@ public class CommandPreprocessListener implements Listener { } try { - String commandName = event.getMessage().substring(1).split(" ")[0].toLowerCase(); - - boolean logUnknownCommands = Settings.LOG_UNKNOWN_COMMANDS.isTrue(); - boolean combineCommandAliases = Settings.COMBINE_COMMAND_ALIASES.isTrue(); - - if (!logUnknownCommands || combineCommandAliases) { - Command command = getBukkitCommand(commandName); - if (command == null) { - if (!logUnknownCommands) { - return; - } - } else if (combineCommandAliases) { - commandName = command.getName(); - } - } - Processing.submit(new CommandProcessor(commandName)); + actOnCommandEvent(event); } catch (Exception e) { Log.toLog(this.getClass(), e); } } + private void actOnCommandEvent(PlayerCommandPreprocessEvent event) { + String commandName = event.getMessage().substring(1).split(" ")[0].toLowerCase(); + + boolean logUnknownCommands = Settings.LOG_UNKNOWN_COMMANDS.isTrue(); + boolean combineCommandAliases = Settings.COMBINE_COMMAND_ALIASES.isTrue(); + + if (!logUnknownCommands || combineCommandAliases) { + Command command = getBukkitCommand(commandName); + if (command == null) { + if (!logUnknownCommands) { + return; + } + } else if (combineCommandAliases) { + commandName = command.getName(); + } + } + Processing.submit(new CommandProcessor(commandName)); + } + private Command getBukkitCommand(String commandName) { Command command = plugin.getServer().getPluginCommand(commandName); if (command == null) { diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/PlayerOnlineListener.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/PlayerOnlineListener.java index 31fd2ba4b..eda55f727 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/PlayerOnlineListener.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/PlayerOnlineListener.java @@ -72,61 +72,69 @@ public class PlayerOnlineListener implements Listener { @EventHandler(priority = EventPriority.MONITOR) public void onPlayerJoin(PlayerJoinEvent event) { try { - Player player = event.getPlayer(); - NotificationCenter.checkNotifications(player); - - UUID uuid = player.getUniqueId(); - long time = MiscUtils.getTime(); - - AFKListener.AFK_TRACKER.performedAction(uuid, time); - - String world = player.getWorld().getName(); - String gm = player.getGameMode().name(); - - String ip = player.getAddress().getAddress().getHostAddress(); - - String playerName = player.getName(); - String displayName = player.getDisplayName(); - - int playersOnline = TaskSystem.getInstance().getTpsCountTimer().getLatestPlayersOnline(); - - SessionCache.getInstance().cacheSession(uuid, new Session(time, world, gm)); - - Processing.submit( - new RegisterProcessor(uuid, player.getFirstPlayed(), time, playerName, playersOnline, - new IPUpdateProcessor(uuid, ip, time), - new NameProcessor(uuid, playerName, displayName), - new PlayerPageUpdateProcessor(uuid) - ) - ); - Processing.submit(new NetworkPageUpdateProcessor()); + actOnJoinEvent(event); } catch (Exception e) { Log.toLog(this.getClass(), e); } } + private void actOnJoinEvent(PlayerJoinEvent event) { + Player player = event.getPlayer(); + NotificationCenter.checkNotifications(player); + + UUID uuid = player.getUniqueId(); + long time = MiscUtils.getTime(); + + AFKListener.AFK_TRACKER.performedAction(uuid, time); + + String world = player.getWorld().getName(); + String gm = player.getGameMode().name(); + + String ip = player.getAddress().getAddress().getHostAddress(); + + String playerName = player.getName(); + String displayName = player.getDisplayName(); + + int playersOnline = TaskSystem.getInstance().getTpsCountTimer().getLatestPlayersOnline(); + + SessionCache.getInstance().cacheSession(uuid, new Session(time, world, gm)); + + Processing.submit( + new RegisterProcessor(uuid, player.getFirstPlayed(), time, playerName, playersOnline, + new IPUpdateProcessor(uuid, ip, time), + new NameProcessor(uuid, playerName, displayName), + new PlayerPageUpdateProcessor(uuid) + ) + ); + Processing.submit(new NetworkPageUpdateProcessor()); + } + @EventHandler(priority = EventPriority.MONITOR) public void onPlayerQuit(PlayerQuitEvent event) { try { - long time = MiscUtils.getTime(); - Player player = event.getPlayer(); - UUID uuid = player.getUniqueId(); - - AFKListener.AFK_TRACKER.loggedOut(uuid, time); - - Processing.submit(new BanAndOpProcessor(uuid, player.isBanned(), player.isOp())); - Processing.submit(new EndSessionProcessor(uuid, time)); - Processing.submit(new NetworkPageUpdateProcessor()); - - SessionCache sessionCache = SessionCache.getInstance(); - if (sessionCache.isFirstSession(uuid)) { - int messagesSent = sessionCache.getFirstSessionMsgCount(uuid); - Processing.submit(new FirstLeaveProcessor(uuid, time, messagesSent)); - } - - Processing.submit(new PlayerPageUpdateProcessor(uuid)); + actOnQuitEvent(event); } catch (Exception e) { Log.toLog(this.getClass(), e); } } + + private void actOnQuitEvent(PlayerQuitEvent event) { + long time = MiscUtils.getTime(); + Player player = event.getPlayer(); + UUID uuid = player.getUniqueId(); + + AFKListener.AFK_TRACKER.loggedOut(uuid, time); + + Processing.submit(new BanAndOpProcessor(uuid, player.isBanned(), player.isOp())); + Processing.submit(new EndSessionProcessor(uuid, time)); + Processing.submit(new NetworkPageUpdateProcessor()); + + SessionCache sessionCache = SessionCache.getInstance(); + if (sessionCache.isFirstSession(uuid)) { + int messagesSent = sessionCache.getFirstSessionMsgCount(uuid); + Processing.submit(new FirstLeaveProcessor(uuid, time, messagesSent)); + } + + Processing.submit(new PlayerPageUpdateProcessor(uuid)); + } } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeAFKListener.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeAFKListener.java new file mode 100644 index 000000000..62a2897fd --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeAFKListener.java @@ -0,0 +1,68 @@ +package com.djrapitops.plan.system.listeners.sponge; + +import com.djrapitops.plan.system.afk.AFKTracker; +import com.djrapitops.plan.utilities.MiscUtils; +import com.djrapitops.plugin.api.utility.log.Log; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.Order; +import org.spongepowered.api.event.command.SendCommandEvent; +import org.spongepowered.api.event.entity.MoveEntityEvent; +import org.spongepowered.api.event.entity.living.humanoid.player.PlayerChangeClientSettingsEvent; +import org.spongepowered.api.event.entity.living.humanoid.player.TargetPlayerEvent; +import org.spongepowered.api.event.filter.cause.First; +import org.spongepowered.api.event.message.MessageChannelEvent; + +import java.util.UUID; + +/** + * Listener that keeps track of actions that are not considered being AFK. + *

+ * Additional Listener calls in SpongePlayerListener to avoid having HIGHEST priority listeners. + * + * @author Rsl1122 + * @see SpongePlayerListener + */ +public class SpongeAFKListener { + + // Static so that /reload does not cause afk tracking to fail. + public static final AFKTracker AFK_TRACKER = new AFKTracker(); + + private void event(TargetPlayerEvent event) { + try { + UUID uuid = event.getTargetEntity().getUniqueId(); + long time = MiscUtils.getTime(); + + AFK_TRACKER.performedAction(uuid, time); + } catch (Exception e) { + Log.toLog(this.getClass(), e); + } + } + + @Listener(order = Order.POST) + public void onMove(MoveEntityEvent event, @First Player player) { + UUID uuid = player.getUniqueId(); + long time = MiscUtils.getTime(); + AFK_TRACKER.performedAction(uuid, time); + } + + @Listener(order = Order.POST) + public void onPlayerChat(MessageChannelEvent.Chat event, @First Player player) { + UUID uuid = player.getUniqueId(); + long time = MiscUtils.getTime(); + AFK_TRACKER.performedAction(uuid, time); + } + + @Listener(order = Order.POST) + public void onPlayerCommand(SendCommandEvent event, @First Player player) { + UUID uuid = player.getUniqueId(); + long time = MiscUtils.getTime(); + AFK_TRACKER.performedAction(uuid, time); + } + + @Listener(order = Order.POST) + public void onSettingsChange(PlayerChangeClientSettingsEvent event) { + event(event); + } + +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeChatListener.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeChatListener.java new file mode 100644 index 000000000..c3f7f56af --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeChatListener.java @@ -0,0 +1,48 @@ +package com.djrapitops.plan.system.listeners.sponge; + +import com.djrapitops.plan.system.cache.SessionCache; +import com.djrapitops.plan.system.processing.Processing; +import com.djrapitops.plan.system.processing.processors.player.NameProcessor; +import com.djrapitops.plugin.api.utility.log.Log; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.Order; +import org.spongepowered.api.event.filter.cause.First; +import org.spongepowered.api.event.message.MessageChannelEvent; + +import java.util.UUID; + +/** + * Listener that keeps track of player display name. + * + * @author Rsl1122 + */ +public class SpongeChatListener { + + @Listener(order = Order.POST) + public void onPlayerChat(MessageChannelEvent.Chat event, @First Player player) { + if (event.isCancelled()) { + return; + } + + try { + actOnChatEvent(player); + } catch (Exception e) { + Log.toLog(this.getClass(), e); + } + } + + private void actOnChatEvent(@First Player player) { + UUID uuid = player.getUniqueId(); + String name = player.getName(); + String displayName = player.getDisplayNameData().displayName().get().toPlain(); + + SessionCache sessionCache = SessionCache.getInstance(); + if (sessionCache.isFirstSession(uuid)) { + sessionCache.firstSessionMessageSent(uuid); + } + + Processing.submit(new NameProcessor(uuid, name, displayName)); + } + +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeCommandListener.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeCommandListener.java new file mode 100644 index 000000000..1eccd3774 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeCommandListener.java @@ -0,0 +1,57 @@ +package com.djrapitops.plan.system.listeners.sponge; + +import com.djrapitops.plan.system.processing.Processing; +import com.djrapitops.plan.system.processing.processors.CommandProcessor; +import com.djrapitops.plan.system.settings.Permissions; +import com.djrapitops.plan.system.settings.Settings; +import com.djrapitops.plugin.api.utility.log.Log; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.command.CommandMapping; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.Order; +import org.spongepowered.api.event.command.SendCommandEvent; +import org.spongepowered.api.event.filter.cause.First; + +import java.util.Optional; + +/** + * Listener that keeps track of used commands. + * + * @author Rsl1122 + */ +public class SpongeCommandListener { + + @Listener(order = Order.POST) + public void onPlayerCommand(SendCommandEvent event, @First Player player) { + boolean hasIgnorePermission = player.hasPermission(Permissions.IGNORE_COMMANDUSE.getPermission()); + if (event.isCancelled() || hasIgnorePermission) { + return; + } + try { + actOnCommandEvent(event); + } catch (Exception e) { + Log.toLog(this.getClass(), e); + } + } + + private void actOnCommandEvent(SendCommandEvent event) { + String commandName = event.getCommand(); + + boolean logUnknownCommands = Settings.LOG_UNKNOWN_COMMANDS.isTrue(); + boolean combineCommandAliases = Settings.COMBINE_COMMAND_ALIASES.isTrue(); + + if (!logUnknownCommands || combineCommandAliases) { + Optional existingCommand = Sponge.getCommandManager().get(commandName); + if (!existingCommand.isPresent()) { + if (!logUnknownCommands) { + return; + } + } else if (combineCommandAliases) { + commandName = existingCommand.get().getPrimaryAlias(); + } + } + Processing.submit(new CommandProcessor(commandName)); + } + +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeDeathListener.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeDeathListener.java new file mode 100644 index 000000000..43aa426ed --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeDeathListener.java @@ -0,0 +1,131 @@ +package com.djrapitops.plan.system.listeners.sponge; + +import com.djrapitops.plan.data.container.Session; +import com.djrapitops.plan.system.cache.SessionCache; +import com.djrapitops.plan.system.processing.Processing; +import com.djrapitops.plan.system.processing.processors.player.SpongeKillProcessor; +import com.djrapitops.plan.utilities.MiscUtils; +import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.utilities.Format; +import org.spongepowered.api.data.key.Keys; +import org.spongepowered.api.data.type.HandTypes; +import org.spongepowered.api.entity.Entity; +import org.spongepowered.api.entity.living.Living; +import org.spongepowered.api.entity.living.animal.Wolf; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.entity.projectile.arrow.Arrow; +import org.spongepowered.api.entity.projectile.source.ProjectileSource; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.cause.entity.damage.source.EntityDamageSource; +import org.spongepowered.api.event.entity.DestructEntityEvent; +import org.spongepowered.api.item.ItemType; +import org.spongepowered.api.item.ItemTypes; +import org.spongepowered.api.item.inventory.ItemStack; + +import java.util.Optional; +import java.util.UUID; + +/** + * Listener for Deaths and Kills on Sponge. + * + * @author Rsl1122 + */ +public class SpongeDeathListener { + + @Listener + public void onEntityDeath(DestructEntityEvent.Death event) { + long time = MiscUtils.getTime(); + Living dead = event.getTargetEntity(); + + if (dead instanceof Player) { + // Process Death + Processing.submitCritical(() -> SessionCache.getCachedSession(dead.getUniqueId()).ifPresent(Session::died)); + } + + try { + Optional optDamageSource = event.getCause().first(EntityDamageSource.class); + if (optDamageSource.isPresent()) { + EntityDamageSource damageSource = optDamageSource.get(); + Entity killerEntity = damageSource.getSource(); + handleKill(time, dead, killerEntity); + } + } catch (Exception e) { + Log.toLog(this.getClass(), e); + } + } + + private void handleKill(long time, Living dead, Entity killerEntity) { + SpongeKillProcessor processor = null; + if (killerEntity instanceof Player) { + processor = handlePlayerKill(time, dead, (Player) killerEntity); + } else if (killerEntity instanceof Wolf) { + processor = handleWolfKill(time, dead, (Wolf) killerEntity); + } else if (killerEntity instanceof Arrow) { + processor = handleArrowKill(time, dead, (Arrow) killerEntity); + } + if (processor != null) { + Processing.submit(processor); + } + } + + private SpongeKillProcessor handlePlayerKill(long time, Living dead, Player killer) { + + Optional inMainHand = killer.getItemInHand(HandTypes.MAIN_HAND); + ItemStack inHand = inMainHand.orElse(killer.getItemInHand(HandTypes.OFF_HAND).orElse(ItemStack.empty())); + ItemType type = inHand.isEmpty() ? ItemTypes.AIR : inHand.getType(); + + return new SpongeKillProcessor(killer.getUniqueId(), time, getUUID(dead), normalizeItemName(type)); + } + + private UUID getUUID(Living dead) { + if (dead instanceof Player) { + return dead.getUniqueId(); + } + return null; + } + + private SpongeKillProcessor handleWolfKill(long time, Living dead, Wolf wolf) { + Optional> owner = wolf.get(Keys.TAMED_OWNER); + + if (!owner.isPresent()) { + return null; + } + + return owner.get().map( + uuid -> new SpongeKillProcessor(uuid, time, getUUID(dead), "Wolf") + ).orElse(null); + } + + private SpongeKillProcessor handleArrowKill(long time, Living dead, Arrow arrow) { + ProjectileSource source = arrow.getShooter(); + if (!(source instanceof Player)) { + return null; + } + + Player player = (Player) source; + + return new SpongeKillProcessor(player.getUniqueId(), time, getUUID(dead), "Bow"); + } + + /** + * Normalizes an item name + * + * @param type The type of the item + * @return The normalized item name + */ + private String normalizeItemName(ItemType type) { + String[] parts = type.getName().split("_"); + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < parts.length; i++) { + String part = new Format(parts[i]).capitalize().toString(); + builder.append(part); + if (i < parts.length - 1) { + builder.append(" "); + } + } + + return builder.toString(); + } + +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeGMChangeListener.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeGMChangeListener.java new file mode 100644 index 000000000..c1bfa3850 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeGMChangeListener.java @@ -0,0 +1,50 @@ +package com.djrapitops.plan.system.listeners.sponge; + +import com.djrapitops.plan.data.container.Session; +import com.djrapitops.plan.system.cache.SessionCache; +import com.djrapitops.plan.system.settings.WorldAliasSettings; +import com.djrapitops.plan.utilities.MiscUtils; +import com.djrapitops.plugin.api.utility.log.Log; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.Order; +import org.spongepowered.api.event.entity.living.humanoid.ChangeGameModeEvent; + +import java.util.Optional; +import java.util.UUID; + +/** + * Listener for GameMode change on Sponge. + * + * @author Rsl1122 + */ +public class SpongeGMChangeListener { + + @Listener(order = Order.POST) + public void onGMChange(ChangeGameModeEvent.TargetPlayer event) { + if (event.isCancelled()) { + return; + } + + try { + actOnGMChangeEvent(event); + } catch (Exception e) { + Log.toLog(this.getClass(), e); + } + } + + private void actOnGMChangeEvent(ChangeGameModeEvent.TargetPlayer event) { + Player player = event.getTargetEntity(); + UUID uuid = player.getUniqueId(); + long time = MiscUtils.getTime(); + + String gameMode = event.getGameMode().getName().toUpperCase(); + String worldName = player.getWorld().getName(); + + WorldAliasSettings.addWorld(worldName); + + Optional cachedSession = SessionCache.getCachedSession(uuid); + cachedSession.ifPresent(session -> session.changeState(worldName, gameMode, time)); + } + +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongePlayerListener.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongePlayerListener.java new file mode 100644 index 000000000..38135e5be --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongePlayerListener.java @@ -0,0 +1,143 @@ +package com.djrapitops.plan.system.listeners.sponge; + +import com.djrapitops.plan.data.container.Session; +import com.djrapitops.plan.system.cache.SessionCache; +import com.djrapitops.plan.system.processing.Processing; +import com.djrapitops.plan.system.processing.processors.info.NetworkPageUpdateProcessor; +import com.djrapitops.plan.system.processing.processors.info.PlayerPageUpdateProcessor; +import com.djrapitops.plan.system.processing.processors.player.*; +import com.djrapitops.plan.system.tasks.TaskSystem; +import com.djrapitops.plan.utilities.MiscUtils; +import com.djrapitops.plugin.api.systems.NotificationCenter; +import com.djrapitops.plugin.api.utility.log.Log; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.data.key.Keys; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.entity.living.player.gamemode.GameMode; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.Order; +import org.spongepowered.api.event.entity.living.humanoid.player.KickPlayerEvent; +import org.spongepowered.api.event.network.ClientConnectionEvent; +import org.spongepowered.api.profile.GameProfile; +import org.spongepowered.api.service.ProviderRegistration; +import org.spongepowered.api.service.ban.BanService; + +import java.util.Optional; +import java.util.UUID; + +/** + * Listener for Player Join/Leave on Sponge. + * + * @author Rsl1122 + */ +public class SpongePlayerListener { + + @Listener(order = Order.POST) + public void onLogin(ClientConnectionEvent.Login event) { + try { + actOnLoginEvent(event); + } catch (Exception e) { + Log.toLog(this.getClass(), e); + } + } + + private void actOnLoginEvent(ClientConnectionEvent.Login event) { + GameProfile profile = event.getProfile(); + UUID uuid = profile.getUniqueId(); + boolean banned = isBanned(profile); + Processing.submit(new BanAndOpProcessor(uuid, banned, false)); + } + + @Listener(order = Order.POST) + public void onKick(KickPlayerEvent event) { + try { + UUID uuid = event.getTargetEntity().getUniqueId(); + Processing.submit(new KickProcessor(uuid)); + } catch (Exception e) { + Log.toLog(this.getClass(), e); + } + } + + private boolean isBanned(GameProfile profile) { + Optional> banService = Sponge.getServiceManager().getRegistration(BanService.class); + boolean banned = false; + if (banService.isPresent()) { + banned = banService.get().getProvider().isBanned(profile); + } + return banned; + } + + @Listener(order = Order.POST) + public void onJoin(ClientConnectionEvent.Join event) { + try { + actOnJoinEvent(event); + } catch (Exception e) { + Log.toLog(this.getClass(), e); + } + } + + private void actOnJoinEvent(ClientConnectionEvent.Join event) { + Player player = event.getTargetEntity(); + + NotificationCenter.checkNotifications(player); + + UUID uuid = player.getUniqueId(); + long time = MiscUtils.getTime(); + + SpongeAFKListener.AFK_TRACKER.performedAction(uuid, time); + + String world = player.getWorld().getName(); + Optional gameMode = player.getGameModeData().get(Keys.GAME_MODE); + String gm = "ADVENTURE"; + if (gameMode.isPresent()) { + gm = gameMode.get().getName().toUpperCase(); + } + + String ip = player.getConnection().getAddress().getAddress().getHostAddress(); + + String playerName = player.getName(); + String displayName = player.getDisplayNameData().displayName().get().toPlain(); + + int playersOnline = TaskSystem.getInstance().getTpsCountTimer().getLatestPlayersOnline(); + + SessionCache.getInstance().cacheSession(uuid, new Session(time, world, gm)); + + Processing.submit( + new RegisterProcessor(uuid, time, time, playerName, playersOnline, + new IPUpdateProcessor(uuid, ip, time), + new NameProcessor(uuid, playerName, displayName), + new PlayerPageUpdateProcessor(uuid) + ) + ); + Processing.submit(new NetworkPageUpdateProcessor()); + } + + @Listener(order = Order.POST) + public void onQuit(ClientConnectionEvent.Disconnect event) { + try { + actOnQuitEvent(event); + } catch (Exception e) { + Log.toLog(this.getClass(), e); + } + } + + private void actOnQuitEvent(ClientConnectionEvent.Disconnect event) { + long time = MiscUtils.getTime(); + Player player = event.getTargetEntity(); + UUID uuid = player.getUniqueId(); + + SpongeAFKListener.AFK_TRACKER.loggedOut(uuid, time); + + Processing.submit(new BanAndOpProcessor(uuid, isBanned(player.getProfile()), false)); + Processing.submit(new EndSessionProcessor(uuid, time)); + Processing.submit(new NetworkPageUpdateProcessor()); + + SessionCache sessionCache = SessionCache.getInstance(); + if (sessionCache.isFirstSession(uuid)) { + int messagesSent = sessionCache.getFirstSessionMsgCount(uuid); + Processing.submit(new FirstLeaveProcessor(uuid, time, messagesSent)); + } + + Processing.submit(new PlayerPageUpdateProcessor(uuid)); + } +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeWorldChangeListener.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeWorldChangeListener.java new file mode 100644 index 000000000..230983ea8 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/sponge/SpongeWorldChangeListener.java @@ -0,0 +1,58 @@ +package com.djrapitops.plan.system.listeners.sponge; + +import com.djrapitops.plan.data.container.Session; +import com.djrapitops.plan.system.cache.SessionCache; +import com.djrapitops.plan.system.settings.WorldAliasSettings; +import com.djrapitops.plan.utilities.MiscUtils; +import com.djrapitops.plugin.api.utility.log.Log; +import org.spongepowered.api.data.key.Keys; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.entity.living.player.gamemode.GameMode; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.Order; +import org.spongepowered.api.event.entity.MoveEntityEvent; +import org.spongepowered.api.event.filter.cause.First; + +import java.util.Optional; +import java.util.UUID; + +/** + * Listener for World change on Sponge. + * + * @author Rsl1122 + */ +public class SpongeWorldChangeListener { + + @Listener(order = Order.POST) + public void onWorldChange(MoveEntityEvent.Teleport event, @First Player player) { + if (event.isCancelled()) { + return; + } + + try { + actOnEvent(event, player); + } catch (Exception e) { + Log.toLog(this.getClass(), e); + } + } + + private void actOnEvent(MoveEntityEvent.Teleport event, Player player) { + long time = MiscUtils.getTime(); + + UUID uuid = player.getUniqueId(); + + String worldName = event.getToTransform().getExtent().getName(); + String gameMode = getGameMode(player); + + WorldAliasSettings.addWorld(worldName); + + Optional cachedSession = SessionCache.getCachedSession(uuid); + cachedSession.ifPresent(session -> session.changeState(worldName, gameMode, time)); + } + + private String getGameMode(Player player) { + Optional gameMode = player.getGameModeData().get(Keys.GAME_MODE); + return gameMode.map(gm -> gm.getName().toUpperCase()).orElse("ADVENTURE"); + } + +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/processing/importing/importers/Importer.java b/Plan/src/main/java/com/djrapitops/plan/system/processing/importing/importers/Importer.java index 51bb8d27a..fadfac3e4 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/processing/importing/importers/Importer.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/processing/importing/importers/Importer.java @@ -23,6 +23,8 @@ import com.djrapitops.plugin.api.utility.log.Log; import com.djrapitops.plugin.utilities.Verify; import com.google.common.collect.ImmutableMap; +import java.io.UnsupportedEncodingException; +import java.security.NoSuchAlgorithmException; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -228,7 +230,11 @@ public abstract class Importer { return userImportData.getIps().parallelStream() .map(ip -> { String geoLoc = GeolocationCache.getCountry(ip); - return new GeoInfo(ip, geoLoc, date); + try { + return new GeoInfo(ip, geoLoc, date); + } catch (UnsupportedEncodingException | NoSuchAlgorithmException e) { + throw new IllegalArgumentException(e); + } }).collect(Collectors.toList()); } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/info/PlayerPageUpdateProcessor.java b/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/info/PlayerPageUpdateProcessor.java index df386e77d..19fb85ed3 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/info/PlayerPageUpdateProcessor.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/info/PlayerPageUpdateProcessor.java @@ -2,6 +2,9 @@ package com.djrapitops.plan.system.processing.processors.info; import com.djrapitops.plan.system.info.InfoSystem; import com.djrapitops.plan.system.info.connection.WebExceptionLogger; +import com.djrapitops.plugin.api.TimeAmount; +import com.djrapitops.plugin.task.AbsRunnable; +import com.djrapitops.plugin.task.RunnableFactory; import java.util.UUID; @@ -15,8 +18,17 @@ public class PlayerPageUpdateProcessor implements Runnable { @Override public void run() { - WebExceptionLogger.logIfOccurs(this.getClass(), - () -> InfoSystem.getInstance().generateAndCachePlayerPage(uuid) - ); + RunnableFactory.createNew("Generate Inspect page: " + uuid, new AbsRunnable() { + @Override + public void run() { + try { + WebExceptionLogger.logIfOccurs(PlayerPageUpdateProcessor.class, + () -> InfoSystem.getInstance().generateAndCachePlayerPage(uuid) + ); + } finally { + cancel(); + } + } + }).runTaskLaterAsynchronously(TimeAmount.SECOND.ticks() * 20); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/IPUpdateProcessor.java b/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/IPUpdateProcessor.java index 759695e73..7bebbaea4 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/IPUpdateProcessor.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/IPUpdateProcessor.java @@ -9,8 +9,11 @@ import com.djrapitops.plan.data.container.GeoInfo; import com.djrapitops.plan.system.cache.GeolocationCache; import com.djrapitops.plan.system.database.databases.Database; import com.djrapitops.plan.system.processing.CriticalRunnable; +import com.djrapitops.plan.system.settings.Settings; import com.djrapitops.plugin.api.utility.log.Log; +import java.io.UnsupportedEncodingException; +import java.security.NoSuchAlgorithmException; import java.util.UUID; /** @@ -32,11 +35,13 @@ public class IPUpdateProcessor implements CriticalRunnable { @Override public void run() { - String country = GeolocationCache.getCountry(ip); - try { - Database.getActive().save().geoInfo(uuid, new GeoInfo(ip, country, time)); - } catch (DBException e) { - Log.toLog(this.getClass(), e); + if (Settings.DATA_GEOLOCATIONS.isTrue()) { + String country = GeolocationCache.getCountry(ip); + try { + Database.getActive().save().geoInfo(uuid, new GeoInfo(ip, country, time)); + } catch (DBException | UnsupportedEncodingException | NoSuchAlgorithmException e) { + Log.toLog(this.getClass(), e); + } } } } \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/SpongeKillProcessor.java b/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/SpongeKillProcessor.java new file mode 100644 index 000000000..c737e6aa6 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/SpongeKillProcessor.java @@ -0,0 +1,56 @@ +package com.djrapitops.plan.system.processing.processors.player; + +import com.djrapitops.plan.data.container.PlayerKill; +import com.djrapitops.plan.data.container.Session; +import com.djrapitops.plan.system.cache.SessionCache; +import com.djrapitops.plan.system.processing.CriticalRunnable; + +import java.util.Optional; +import java.util.UUID; + +/** + * Processor Class for KillEvent information when the killer is a + * player. + *

+ * Adds PlayerKill or a Mob kill to the active Session. + * + * @author Rsl1122 + * @since 4.3.0 + */ +public class SpongeKillProcessor implements CriticalRunnable { + + private final UUID uuid; + private final UUID deadUUID; + private final String weaponName; + private final long time; + + /** + * Constructor. + * + * @param uuid UUID of the killer. + * @param time Epoch ms the event occurred. + * @param deadUUID Dead entity (Mob or Player) + * @param weaponName Weapon used. + */ + public SpongeKillProcessor(UUID uuid, long time, UUID deadUUID, String weaponName) { + this.uuid = uuid; + this.time = time; + this.deadUUID = deadUUID; + this.weaponName = weaponName; + } + + @Override + public void run() { + Optional cachedSession = SessionCache.getCachedSession(uuid); + if (!cachedSession.isPresent()) { + return; + } + Session session = cachedSession.get(); + + if (deadUUID != null) { + session.playerKilled(new PlayerKill(deadUUID, weaponName, time)); + } else { + session.mobKilled(); + } + } +} diff --git a/Plan/src/main/java/com/djrapitops/plan/system/settings/PlanErrorManager.java b/Plan/src/main/java/com/djrapitops/plan/system/settings/PlanErrorManager.java index 8d16f3495..5b5dc0470 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/settings/PlanErrorManager.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/settings/PlanErrorManager.java @@ -20,7 +20,7 @@ import java.util.logging.Logger; * * @author Rsl1122 */ -public class PlanErrorManager extends ErrorManager { +public class PlanErrorManager implements ErrorManager { @Override public void toLog(String source, Throwable e, Class callingPlugin) { diff --git a/Plan/src/main/java/com/djrapitops/plan/system/settings/Settings.java b/Plan/src/main/java/com/djrapitops/plan/system/settings/Settings.java index bee0bf5bc..6ea6583bd 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/settings/Settings.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/settings/Settings.java @@ -36,6 +36,9 @@ public enum Settings { FORMAT_DATE_RECENT_DAYS("Customization.Formatting.Dates.RecentDays"), DISPLAY_PLAYER_IPS("Customization.Display.PlayerIPs"), DISPLAY_GAPS_IN_GRAPH_DATA("Customization.Display.GapsInGraphData"), + DATA_GEOLOCATIONS("Data.Geolocations"), + ALLOW_UPDATE("Plugin.Allow-Update-Command"), + NOTIFY_ABOUT_DEV_RELEASES("Plugin.Notify-About-DEV-Releases"), // Integer WEBSERVER_PORT("WebServer.Port"), @@ -47,6 +50,8 @@ public enum Settings { MAX_PLAYERS("Customization.Display.MaxPlayers"), MAX_PLAYERS_PLAYERS_PAGE("Customization.Display.MaxPlayersPlayersPage"), AFK_THRESHOLD_MINUTES("Data.AFKThresholdMinutes"), + KEEP_LOGS_DAYS("Plugin.KeepLogsForXDays"), + KEEP_INACTIVE_PLAYERS_DAYS("Data.KeepInactivePlayerDataForDays"), // String DEBUG("Plugin.Debug"), diff --git a/Plan/src/main/java/com/djrapitops/plan/system/settings/config/BukkitConfigSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/settings/config/ServerConfigSystem.java similarity index 91% rename from Plan/src/main/java/com/djrapitops/plan/system/settings/config/BukkitConfigSystem.java rename to Plan/src/main/java/com/djrapitops/plan/system/settings/config/ServerConfigSystem.java index c9d9f6849..7d3e56339 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/settings/config/BukkitConfigSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/settings/config/ServerConfigSystem.java @@ -15,7 +15,7 @@ import java.io.IOException; * * @author Rsl1122 */ -public class BukkitConfigSystem extends ConfigSystem { +public class ServerConfigSystem extends ConfigSystem { @Override protected void copyDefaults() throws IOException { diff --git a/Plan/src/main/java/com/djrapitops/plan/system/settings/config/SpongeConfigSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/settings/config/SpongeConfigSystem.java new file mode 100644 index 000000000..477a57ab7 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/settings/config/SpongeConfigSystem.java @@ -0,0 +1,37 @@ +package com.djrapitops.plan.system.settings.config; + +import com.djrapitops.plan.api.exceptions.EnableException; +import com.djrapitops.plan.system.file.FileSystem; +import com.djrapitops.plan.system.settings.Settings; +import com.djrapitops.plugin.api.utility.log.Log; + +import java.io.IOException; + +/** + * Sponge ConfigSystem that disables WebServer and Geolocations on first enable. + * + * @author Rsl1122 + */ +public class SpongeConfigSystem extends ServerConfigSystem { + + private boolean firstInstall; + + @Override + public void enable() throws EnableException { + firstInstall = !FileSystem.getConfigFile().exists(); + super.enable(); + } + + @Override + protected void copyDefaults() throws IOException { + super.copyDefaults(); + if (firstInstall) { + Log.info("§eWebServer and Geolocations disabled by default on Sponge servers. You can enable them in the config:"); + Log.info("§e " + Settings.WEBSERVER_DISABLED.getPath()); + Log.info("§e " + Settings.DATA_GEOLOCATIONS.getPath()); + Settings.WEBSERVER_DISABLED.set(true); + Settings.DATA_GEOLOCATIONS.set(false); + Settings.save(); + } + } +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/settings/locale/Locale.java b/Plan/src/main/java/com/djrapitops/plan/system/settings/locale/Locale.java index 1080ab38d..408b48710 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/settings/locale/Locale.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/settings/locale/Locale.java @@ -71,7 +71,7 @@ public class Locale { } else if (locale.equals("DEFAULT")) { Log.info("Using Locale: Default (EN)"); } else { - loadFromResource("locale_" + locale + ".txt"); + loadFromResource("locale/locale_" + locale + ".txt"); } } catch (IOException e) { Log.toLog(this.getClass(), e); @@ -203,35 +203,33 @@ public class Locale { add(Msg.CMD_USG_QANALYZE, "View the Server Analysis as Text"); add(Msg.CMD_USG_HELP, "Show command list."); add(Msg.CMD_USG_INFO, "Check the version of Plan"); - add(Msg.CMD_USG_INSPECT, "Inspect Player's Data"); - add(Msg.CMD_USG_QINSPECT, "Inspect Player's Data as Text"); + add(Msg.CMD_USG_INSPECT, "Inspect player's data"); + add(Msg.CMD_USG_QINSPECT, "Inspect player's data in game"); add(Msg.CMD_USG_LIST, "List to all cached players"); add(Msg.CMD_USG_MANAGE, "Database management command"); add(Msg.CMD_USG_MANAGE_BACKUP, "Backup a database to .db file"); add(Msg.CMD_USG_MANAGE_CLEAN, "Clear old data from the database"); add(Msg.CMD_USG_MANAGE_CLEAR, "Clear ALL data from the database"); add(Msg.CMD_USG_MANAGE_DUMP, "Create a Hastebin log for Dev for easier Issue reporting."); - add(Msg.CMD_USG_MANAGE_HOTSWAP, "Hotswap to another database & restart the plugin"); - add(Msg.CMD_USG_MANAGE_IMPORT, "Import Data from supported plugins to Active Database."); - add(Msg.CMD_USG_MANAGE_MOVE, "Copy data from one database to another & overwrite values"); + add(Msg.CMD_USG_MANAGE_HOTSWAP, "Hotswap database & restart the plugin"); + add(Msg.CMD_USG_MANAGE_IMPORT, "Import Data from plugins"); + add(Msg.CMD_USG_MANAGE_MOVE, "Move data between databases"); add(Msg.CMD_USG_MANAGE_REMOVE, "Remove players's data from the Active Database."); - add(Msg.CMD_USG_MANAGE_RESTORE, "Restore a database from a backup file"); + add(Msg.CMD_USG_MANAGE_RESTORE, "Restore a database"); add(Msg.CMD_USG_RELOAD, "Restart the Plugin (Reloads config)"); add(Msg.CMD_USG_SEARCH, "Search for player"); - add(Msg.CMD_USG_WEB, "Manage Webusers"); - add(Msg.CMD_USG_WEB_CHECK, "Check a webuser and their permission level."); - add(Msg.CMD_USG_WEB_DELETE, "Delete a webuser"); + add(Msg.CMD_USG_WEB, "Manage Web users"); + add(Msg.CMD_USG_WEB_CHECK, "Check a web user's permission level."); + add(Msg.CMD_USG_WEB_DELETE, "Delete a web user"); add(Msg.CMD_USG_WEB_LEVEL, "Info about permission levels."); - add(Msg.CMD_USG_WEB_REGISTER, "Register a user for the webserver"); + add(Msg.CMD_USG_WEB_REGISTER, "Register a web user"); add(Msg.CMD_HELP_ANALYZE, mCol + "Analysis Command" + "\\" + tCol + " Used to Refresh analysis cache & Access the result page" - + "\\" + sCol + " /plan status can be used to check status of analysis while it is running." - + "\\" + sCol + " Aliases: analyze, analyse, analysis, a"); + + "\\" + sCol + " /plan status can be used to check status of analysis while it is running."); add(Msg.CMD_HELP_QANALYZE, mCol + "Quick Analysis command" + "\\" + tCol + " Used to get in game info about analysis." - + "\\" + sCol + " Has less info than full Analysis web page." - + "\\" + sCol + " Aliases: qanalyze, ganalyse, qanalysis, qa"); + + "\\" + sCol + " Has less info than full Analysis web page."); add(Msg.CMD_HELP_PLAN, mCol + "/plan - Main Command" + "\\" + tCol + " Used to access all SubCommands & help" + "\\" + sCol + " /plan - List subcommands" @@ -242,21 +240,17 @@ public class Locale { + "\\" + sCol + " Alias: /plan "); add(Msg.CMD_HELP_QINSPECT, mCol + "Quick Inspect command" + "\\" + tCol + " Used to get some inspect info in game." - + "\\" + sCol + " Has less info than full Inspect web page." - + "\\" + sCol + " Alias: /plan qi"); + + "\\" + sCol + " Has less info than full Inspect web page."); add(Msg.CMD_HELP_LIST, mCol + "List command" + "\\" + tCol + " Used to get a link to players page." - + "\\" + sCol + " Players page contains links to all cached inspect pages." - + "\\" + sCol + " Alias: /plan pl"); + + "\\" + sCol + " Players page contains links to all cached inspect pages."); add(Msg.CMD_HELP_MANAGE, mCol + "Manage command\\" + tCol + " Used to Manage Database of the plugin." - + "\\" + sCol + " Alias: /plan m" + "\\" + sCol + " /plan m - List subcommands" + "\\" + sCol + " /plan m ? - in depth help"); add(Msg.CMD_HELP_MANAGE_CLEAR, mCol + "Manage Clear command" + "\\" + tCol + " Used to delete ALL data in the active database." - + "\\" + sCol + " Plugin should be reloaded after successful clear." - + "\\" + sCol + " Alias: /plan pl"); + + "\\" + sCol + " Plugin should be reloaded after successful clear."); add(Msg.CMD_HELP_MANAGE_DUMP, mCol + "Manage Dump command" + "\\" + tCol + " Used to dump important data for bug reporting to hastebin."); add(Msg.CMD_HELP_MANAGE_HOTSWAP, mCol + "Manage Hotswap command" @@ -275,8 +269,7 @@ public class Locale { + "\\" + sCol + " Users have a permission level:" + "\\" + tCol + " 0 - Access to all pages" + "\\" + tCol + " 1 - Access to /players & all inspect pages" - + "\\" + tCol + " 2 - Access to own inspect page" - + "\\" + sCol + " Alias: /plan web"); + + "\\" + tCol + " 2 - Access to own inspect page"); add(Msg.CMD_HELP_WEB_REGISTER, mCol + "Web Register command" + "\\" + tCol + " Used to register a new user for the webserver." + "\\" + sCol + " Registering a user for another player requires " + Permissions.MANAGE_WEB.getPerm() + " permission." diff --git a/Plan/src/main/java/com/djrapitops/plan/system/settings/locale/Message.java b/Plan/src/main/java/com/djrapitops/plan/system/settings/locale/Message.java index 563ebfe6e..957b19aca 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/settings/locale/Message.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/settings/locale/Message.java @@ -1,7 +1,7 @@ package com.djrapitops.plan.system.settings.locale; import com.djrapitops.plugin.utilities.Verify; -import org.apache.commons.lang3.text.StrSubstitutor; +import org.apache.commons.text.StringSubstitutor; import java.io.Serializable; import java.util.HashMap; @@ -30,7 +30,7 @@ public class Message { replaceMap.put(String.valueOf(i), p[i].toString()); } - StrSubstitutor sub = new StrSubstitutor(replaceMap); + StringSubstitutor sub = new StringSubstitutor(replaceMap); return sub.replace(content); } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/settings/network/NetworkSettings.java b/Plan/src/main/java/com/djrapitops/plan/system/settings/network/NetworkSettings.java index d42a7efa3..780613bf7 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/settings/network/NetworkSettings.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/settings/network/NetworkSettings.java @@ -21,6 +21,8 @@ import java.util.Map; import java.util.Optional; import java.util.UUID; +import static com.djrapitops.plan.system.settings.Settings.*; + /** * Class for managing Config setting transfer from Bungee to Bukkit servers. * @@ -36,7 +38,7 @@ public class NetworkSettings { return; } - if (Settings.BUNGEE_OVERRIDE_STANDALONE_MODE.isTrue() || Settings.BUNGEE_COPY_CONFIG.isFalse()) { + if (BUNGEE_OVERRIDE_STANDALONE_MODE.isTrue() || BUNGEE_COPY_CONFIG.isFalse()) { return; } @@ -134,26 +136,51 @@ public class NetworkSettings { private Map getConfigValues() throws DBException { Log.debug("NetworkSettings: Loading Config Values.."); Map configValues = new HashMap<>(); - addConfigValue(configValues, Settings.DB_TYPE, "mysql"); + addConfigValue(configValues, DB_TYPE, "mysql"); Settings[] sameStrings = new Settings[]{ - Settings.DB_HOST, Settings.DB_USER, Settings.DB_PASS, - Settings.DB_DATABASE, Settings.DB_LAUNCH_OPTIONS, - Settings.FORMAT_DECIMALS, Settings.FORMAT_SECONDS, - Settings.FORMAT_DAY, Settings.FORMAT_DAYS, Settings.FORMAT_HOURS, - Settings.FORMAT_MINUTES, Settings.FORMAT_MONTHS, Settings.FORMAT_MONTH, - Settings.FORMAT_YEAR, Settings.FORMAT_YEARS, Settings.FORMAT_ZERO_SECONDS, - Settings.USE_SERVER_TIME, Settings.DISPLAY_SESSIONS_AS_TABLE, Settings.APPEND_WORLD_PERC, - Settings.ORDER_WORLD_PIE_BY_PERC, Settings.MAX_SESSIONS, Settings.MAX_PLAYERS, - Settings.MAX_PLAYERS_PLAYERS_PAGE, Settings.PLAYERTABLE_FOOTER, Settings.FORMAT_DATE_RECENT_DAYS, - Settings.FORMAT_DATE_RECENT_DAYS_PATTERN, Settings.FORMAT_DATE_CLOCK, Settings.FORMAT_DATE_NO_SECONDS, - Settings.FORMAT_DATE_FULL, Settings.DISPLAY_PLAYER_IPS, Settings.ACTIVE_LOGIN_THRESHOLD, - Settings.ACTIVE_PLAY_THRESHOLD, Settings.DISPLAY_GAPS_IN_GRAPH_DATA, Settings.AFK_THRESHOLD_MINUTES + DB_HOST, + DB_USER, + DB_PASS, + DB_DATABASE, + DB_LAUNCH_OPTIONS, + FORMAT_DECIMALS, + FORMAT_SECONDS, + FORMAT_DAY, + FORMAT_DAYS, + FORMAT_HOURS, + FORMAT_MINUTES, + FORMAT_MONTHS, + FORMAT_MONTH, + FORMAT_YEAR, + FORMAT_YEARS, + FORMAT_ZERO_SECONDS, + USE_SERVER_TIME, + DISPLAY_SESSIONS_AS_TABLE, + APPEND_WORLD_PERC, + ORDER_WORLD_PIE_BY_PERC, + MAX_SESSIONS, + MAX_PLAYERS, + MAX_PLAYERS_PLAYERS_PAGE, + PLAYERTABLE_FOOTER, + FORMAT_DATE_RECENT_DAYS, + FORMAT_DATE_RECENT_DAYS_PATTERN, + FORMAT_DATE_CLOCK, + FORMAT_DATE_NO_SECONDS, + FORMAT_DATE_FULL, + DISPLAY_PLAYER_IPS, + ACTIVE_LOGIN_THRESHOLD, + ACTIVE_PLAY_THRESHOLD, + DISPLAY_GAPS_IN_GRAPH_DATA, + AFK_THRESHOLD_MINUTES, + DATA_GEOLOCATIONS, + KEEP_LOGS_DAYS, + KEEP_INACTIVE_PLAYERS_DAYS }; Log.debug("NetworkSettings: Adding Config Values.."); for (Settings setting : sameStrings) { addConfigValue(configValues, setting, setting.toString()); } - addConfigValue(configValues, Settings.DB_PORT, Settings.DB_PORT.getNumber()); + addConfigValue(configValues, DB_PORT, DB_PORT.getNumber()); addServerSpecificValues(configValues); return configValues; } @@ -175,18 +202,18 @@ public class NetworkSettings { ServerSpecificSettings settings = Settings.serverSpecific(); for (UUID serverUUID : Database.getActive().fetch().getServerUUIDs()) { - String theme = settings.getString(serverUUID, Settings.THEME_BASE); - Integer port = settings.getInt(serverUUID, Settings.WEBSERVER_PORT); - String name = settings.getString(serverUUID, Settings.SERVER_NAME); + String theme = settings.getString(serverUUID, THEME_BASE); + Integer port = settings.getInt(serverUUID, WEBSERVER_PORT); + String name = settings.getString(serverUUID, SERVER_NAME); if (!Verify.isEmpty(theme)) { - addConfigValue(configValues, serverUUID, Settings.THEME_BASE, theme); + addConfigValue(configValues, serverUUID, THEME_BASE, theme); } if (port != null && port != 0) { - addConfigValue(configValues, serverUUID, Settings.WEBSERVER_PORT, port); + addConfigValue(configValues, serverUUID, WEBSERVER_PORT, port); } if (!Verify.isEmpty(name)) { - addConfigValue(configValues, serverUUID, Settings.SERVER_NAME, name); + addConfigValue(configValues, serverUUID, SERVER_NAME, name); } } } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/BukkitTaskSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/BukkitTaskSystem.java index 087ad6744..b9f18a62e 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/tasks/BukkitTaskSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/BukkitTaskSystem.java @@ -5,17 +5,9 @@ package com.djrapitops.plan.system.tasks; import com.djrapitops.plan.Plan; -import com.djrapitops.plan.system.settings.Settings; -import com.djrapitops.plan.system.settings.locale.Locale; -import com.djrapitops.plan.system.settings.locale.Msg; -import com.djrapitops.plan.system.tasks.bukkit.*; -import com.djrapitops.plan.utilities.file.export.HtmlExport; -import com.djrapitops.plugin.api.Benchmark; +import com.djrapitops.plan.system.tasks.server.BukkitTPSCountTimer; +import com.djrapitops.plan.system.tasks.server.PaperTPSCountTimer; import com.djrapitops.plugin.api.Check; -import com.djrapitops.plugin.api.TimeAmount; -import com.djrapitops.plugin.api.utility.log.Log; -import com.djrapitops.plugin.task.ITask; -import com.djrapitops.plugin.task.RunnableFactory; import org.bukkit.Bukkit; /** @@ -23,62 +15,18 @@ import org.bukkit.Bukkit; * * @author Rsl1122 */ -public class BukkitTaskSystem extends TaskSystem { - - private ITask bootAnalysisTask; - - private final Plan plugin; +public class BukkitTaskSystem extends ServerTaskSystem { public BukkitTaskSystem(Plan plugin) { + super(plugin); tpsCountTimer = Check.isPaperAvailable() ? new PaperTPSCountTimer(plugin) : new BukkitTPSCountTimer(plugin); - - this.plugin = plugin; - } - - @Override - public void enable() { - registerTasks(); } @Override public void disable() { super.disable(); - Bukkit.getScheduler().cancelTasks(plugin); - } - - private void registerTasks() { - Benchmark.start("Task Registration"); - - // Analysis refresh settings - int analysisRefreshMinutes = Settings.ANALYSIS_AUTO_REFRESH.getNumber(); - boolean analysisRefreshTaskIsEnabled = analysisRefreshMinutes > 0; - long analysisPeriod = analysisRefreshMinutes * TimeAmount.MINUTE.ticks(); - - Log.info(Locale.get(Msg.ENABLE_BOOT_ANALYSIS_INFO).toString()); - - registerTask(tpsCountTimer).runTaskTimer(1000, TimeAmount.SECOND.ticks()); - registerTask(new NetworkPageRefreshTask()).runTaskTimerAsynchronously(20L, 5L * TimeAmount.MINUTE.ticks()); - bootAnalysisTask = registerTask(new BootAnalysisTask()).runTaskLaterAsynchronously(30L * TimeAmount.SECOND.ticks()); - - if (analysisRefreshTaskIsEnabled) { - registerTask(new PeriodicAnalysisTask()).runTaskTimerAsynchronously(analysisPeriod, analysisPeriod); - } - if (Settings.ANALYSIS_EXPORT.isTrue()) { - RunnableFactory.createNew(new HtmlExport(plugin)).runTaskAsynchronously(); - } - Benchmark.stop("Enable", "Task Registration"); - } - - public void cancelBootAnalysis() { - try { - if (bootAnalysisTask != null) { - bootAnalysisTask.cancel(); - bootAnalysisTask = null; - } - } catch (Exception ignored) { - /* Ignored */ - } + Bukkit.getScheduler().cancelTasks((Plan) plugin); } } \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/BungeeTaskSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/BungeeTaskSystem.java index bd71063fd..49719b024 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/tasks/BungeeTaskSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/BungeeTaskSystem.java @@ -6,9 +6,9 @@ package com.djrapitops.plan.system.tasks; import com.djrapitops.plan.PlanBungee; import com.djrapitops.plan.system.settings.Settings; -import com.djrapitops.plan.system.tasks.bukkit.NetworkPageRefreshTask; import com.djrapitops.plan.system.tasks.bungee.BungeeTPSCountTimer; import com.djrapitops.plan.system.tasks.bungee.EnableConnectionTask; +import com.djrapitops.plan.system.tasks.server.NetworkPageRefreshTask; import com.djrapitops.plan.utilities.file.export.HtmlExport; import com.djrapitops.plugin.api.TimeAmount; diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/LogsFolderCleanTask.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/LogsFolderCleanTask.java new file mode 100644 index 000000000..1bdd02b12 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/LogsFolderCleanTask.java @@ -0,0 +1,54 @@ +package com.djrapitops.plan.system.tasks; + +import com.djrapitops.plan.system.settings.Settings; +import com.djrapitops.plugin.api.TimeAmount; +import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.task.AbsRunnable; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Objects; + +/** + * Task in charge of removing old log files + * + * @author Rsl1122 + */ +public class LogsFolderCleanTask extends AbsRunnable { + + private final File folder; + + public LogsFolderCleanTask(File folder) { + super(LogsFolderCleanTask.class.getSimpleName()); + this.folder = folder; + } + + @Override + public void run() { + try { + if (!folder.exists() || folder.isFile()) { + return; + } + cleanFolder(); + } catch (NullPointerException ignore) { + /* Ignored - not supposed to occur. */ + } finally { + cancel(); + } + } + + private void cleanFolder() { + long now = System.currentTimeMillis(); + for (File file : Objects.requireNonNull(folder.listFiles())) { + long forDaysMs = Settings.KEEP_LOGS_DAYS.getNumber() * TimeAmount.DAY.ms(); + if (now - file.lastModified() > (forDaysMs > 0 ? forDaysMs : TimeAmount.DAY.ms())) { + try { + Files.delete(file.toPath()); + } catch (IOException e) { + Log.warn("Could not delete log file at: " + file.getAbsolutePath() + ", " + e.getMessage()); + } + } + } + } +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/ServerTaskSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/ServerTaskSystem.java new file mode 100644 index 000000000..643205841 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/ServerTaskSystem.java @@ -0,0 +1,69 @@ +package com.djrapitops.plan.system.tasks; + +import com.djrapitops.plan.PlanPlugin; +import com.djrapitops.plan.system.settings.Settings; +import com.djrapitops.plan.system.settings.locale.Locale; +import com.djrapitops.plan.system.settings.locale.Msg; +import com.djrapitops.plan.system.tasks.server.BootAnalysisTask; +import com.djrapitops.plan.system.tasks.server.NetworkPageRefreshTask; +import com.djrapitops.plan.system.tasks.server.PeriodicAnalysisTask; +import com.djrapitops.plan.utilities.file.export.HtmlExport; +import com.djrapitops.plugin.api.Benchmark; +import com.djrapitops.plugin.api.TimeAmount; +import com.djrapitops.plugin.api.utility.log.Log; +import com.djrapitops.plugin.task.ITask; +import com.djrapitops.plugin.task.RunnableFactory; + +/** + * Abstracted TaskSystem implementation for both Bukkit and Sponge. + * + * @author Rsl1122 + */ +public class ServerTaskSystem extends TaskSystem { + + protected final PlanPlugin plugin; + protected ITask bootAnalysisTask; + + public ServerTaskSystem(PlanPlugin plugin) { + this.plugin = plugin; + } + + @Override + public void enable() { + registerTasks(); + } + + private void registerTasks() { + Benchmark.start("Task Registration"); + + // Analysis refresh settings + int analysisRefreshMinutes = Settings.ANALYSIS_AUTO_REFRESH.getNumber(); + boolean analysisRefreshTaskIsEnabled = analysisRefreshMinutes > 0; + long analysisPeriod = analysisRefreshMinutes * TimeAmount.MINUTE.ticks(); + + Log.info(Locale.get(Msg.ENABLE_BOOT_ANALYSIS_INFO).toString()); + + registerTask(tpsCountTimer).runTaskTimer(1000, TimeAmount.SECOND.ticks()); + registerTask(new NetworkPageRefreshTask()).runTaskTimerAsynchronously(20L, 5L * TimeAmount.MINUTE.ticks()); + bootAnalysisTask = registerTask(new BootAnalysisTask()).runTaskLaterAsynchronously(30L * TimeAmount.SECOND.ticks()); + + if (analysisRefreshTaskIsEnabled) { + registerTask(new PeriodicAnalysisTask()).runTaskTimerAsynchronously(analysisPeriod, analysisPeriod); + } + if (Settings.ANALYSIS_EXPORT.isTrue()) { + RunnableFactory.createNew(new HtmlExport(plugin)).runTaskAsynchronously(); + } + Benchmark.stop("Enable", "Task Registration"); + } + + public void cancelBootAnalysis() { + try { + if (bootAnalysisTask != null) { + bootAnalysisTask.cancel(); + bootAnalysisTask = null; + } + } catch (Exception ignored) { + /* Ignored */ + } + } +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/SpongeTaskSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/SpongeTaskSystem.java index f6f9832f1..e9e8f4c6f 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/tasks/SpongeTaskSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/SpongeTaskSystem.java @@ -1,9 +1,22 @@ package com.djrapitops.plan.system.tasks; -public class SpongeTaskSystem extends TaskSystem { +import com.djrapitops.plan.PlanSponge; +import com.djrapitops.plan.system.tasks.server.SpongeTPSCountTimer; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.scheduler.Task; + +public class SpongeTaskSystem extends ServerTaskSystem { + + public SpongeTaskSystem(PlanSponge plugin) { + super(plugin); + tpsCountTimer = new SpongeTPSCountTimer(plugin); + } @Override - public void enable() { - + public void disable() { + super.disable(); + for (Task task : Sponge.getScheduler().getScheduledTasks(plugin)) { + task.cancel(); + } } } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/BootAnalysisTask.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/BootAnalysisTask.java similarity index 96% rename from Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/BootAnalysisTask.java rename to Plan/src/main/java/com/djrapitops/plan/system/tasks/server/BootAnalysisTask.java index 90cd49488..baa8c53ff 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/BootAnalysisTask.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/BootAnalysisTask.java @@ -1,4 +1,4 @@ -package com.djrapitops.plan.system.tasks.bukkit; +package com.djrapitops.plan.system.tasks.server; import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.system.info.InfoSystem; diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/BukkitTPSCountTimer.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/BukkitTPSCountTimer.java similarity index 98% rename from Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/BukkitTPSCountTimer.java rename to Plan/src/main/java/com/djrapitops/plan/system/tasks/server/BukkitTPSCountTimer.java index 027294e98..0bc8a0b74 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/BukkitTPSCountTimer.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/BukkitTPSCountTimer.java @@ -1,4 +1,4 @@ -package com.djrapitops.plan.system.tasks.bukkit; +package com.djrapitops.plan.system.tasks.server; import com.djrapitops.plan.Plan; import com.djrapitops.plan.data.container.TPS; diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/NetworkPageRefreshTask.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/NetworkPageRefreshTask.java similarity index 90% rename from Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/NetworkPageRefreshTask.java rename to Plan/src/main/java/com/djrapitops/plan/system/tasks/server/NetworkPageRefreshTask.java index 6589bf4c1..0b598e1dd 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/NetworkPageRefreshTask.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/NetworkPageRefreshTask.java @@ -1,4 +1,4 @@ -package com.djrapitops.plan.system.tasks.bukkit; +package com.djrapitops.plan.system.tasks.server; import com.djrapitops.plan.system.info.InfoSystem; import com.djrapitops.plan.system.info.connection.WebExceptionLogger; diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/PaperTPSCountTimer.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PaperTPSCountTimer.java similarity index 96% rename from Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/PaperTPSCountTimer.java rename to Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PaperTPSCountTimer.java index 845a22a9d..00b5fd9ce 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/PaperTPSCountTimer.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PaperTPSCountTimer.java @@ -1,4 +1,4 @@ -package com.djrapitops.plan.system.tasks.bukkit; +package com.djrapitops.plan.system.tasks.server; import com.djrapitops.plan.Plan; import com.djrapitops.plan.data.container.TPS; diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/PeriodicAnalysisTask.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PeriodicAnalysisTask.java similarity index 96% rename from Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/PeriodicAnalysisTask.java rename to Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PeriodicAnalysisTask.java index e3a11f3d1..32436b109 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/tasks/bukkit/PeriodicAnalysisTask.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PeriodicAnalysisTask.java @@ -1,4 +1,4 @@ -package com.djrapitops.plan.system.tasks.bukkit; +package com.djrapitops.plan.system.tasks.server; import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.system.info.InfoSystem; diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/SpongeTPSCountTimer.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/SpongeTPSCountTimer.java new file mode 100644 index 000000000..f19301d6a --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/SpongeTPSCountTimer.java @@ -0,0 +1,105 @@ +package com.djrapitops.plan.system.tasks.server; + +import com.djrapitops.plan.PlanSponge; +import com.djrapitops.plan.data.container.TPS; +import com.djrapitops.plan.data.container.builders.TPSBuilder; +import com.djrapitops.plan.system.info.server.ServerInfo; +import com.djrapitops.plan.system.tasks.TPSCountTimer; +import com.djrapitops.plan.utilities.analysis.MathUtils; +import com.djrapitops.plugin.api.utility.log.Log; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.world.Chunk; +import org.spongepowered.api.world.World; + +import java.lang.management.ManagementFactory; +import java.lang.management.OperatingSystemMXBean; +import java.util.Iterator; + +public class SpongeTPSCountTimer extends TPSCountTimer { + + private long lastCheckNano; + + public SpongeTPSCountTimer(PlanSponge plugin) { + super(plugin); + lastCheckNano = -1; + } + + @Override + public void addNewTPSEntry(long nanoTime, long now) { + long diff = nanoTime - lastCheckNano; + + lastCheckNano = nanoTime; + + if (diff > nanoTime) { // First run's diff = nanoTime + 1, no calc possible. + Log.debug("First run of TPSCountTimer Task."); + return; + } + + history.add(calculateTPS(diff, now)); + } + + /** + * Calculates the TPS + * + * @param diff The time difference between the last run and the new run + * @param now The time right now + * @return the TPS + */ + private TPS calculateTPS(long diff, long now) { + OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); + int availableProcessors = operatingSystemMXBean.getAvailableProcessors(); + double averageCPUUsage = MathUtils.round(operatingSystemMXBean.getSystemLoadAverage() / availableProcessors * 100.0); + + if (averageCPUUsage < 0) { // If unavailable, getSystemLoadAverage() returns -1 + averageCPUUsage = -1; + } + + Runtime runtime = Runtime.getRuntime(); + + long totalMemory = runtime.totalMemory(); + long usedMemory = (totalMemory - runtime.freeMemory()) / 1000000; + + double tps = Sponge.getGame().getServer().getTicksPerSecond(); + int playersOnline = ServerInfo.getServerProperties().getOnlinePlayers(); + latestPlayersOnline = playersOnline; + int loadedChunks = -1; + int entityCount = getEntityCount(); + + return TPSBuilder.get() + .date(now) + .tps(tps) + .playersOnline(playersOnline) + .usedCPU(averageCPUUsage) + .usedMemory(usedMemory) + .entities(entityCount) + .chunksLoaded(loadedChunks) + .toTPS(); + } + + /** + * Gets the amount of loaded chunks + * + * @return amount of loaded chunks + */ + private int getLoadedChunks() { + // DISABLED + + int loaded = 0; + for (World world : Sponge.getGame().getServer().getWorlds()) { + Iterator iterator = world.getLoadedChunks().iterator(); + while (iterator.hasNext()) { + loaded++; + } + } + return loaded; + } + + /** + * Gets the amount of entities on the server + * + * @return amount of entities + */ + protected int getEntityCount() { + return Sponge.getGame().getServer().getWorlds().stream().mapToInt(world -> world.getEntities().size()).sum(); + } +} diff --git a/Plan/src/main/java/com/djrapitops/plan/system/update/ShutdownUpdateHook.java b/Plan/src/main/java/com/djrapitops/plan/system/update/ShutdownUpdateHook.java new file mode 100644 index 000000000..889aa3cdf --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/update/ShutdownUpdateHook.java @@ -0,0 +1,139 @@ +package com.djrapitops.plan.system.update; + +import com.djrapitops.plan.PlanPlugin; +import com.djrapitops.plugin.api.Check; +import com.djrapitops.plugin.api.utility.Version; +import com.djrapitops.plugin.api.utility.log.Log; + +import java.io.*; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.HashSet; +import java.util.Set; + +/** + * Shutdown hook that updates the plugin on server shutdown. + *

+ * Does not perform update on force close. + * + * @author Rsl1122 + */ +public class ShutdownUpdateHook extends Thread { + + private static boolean activated = false; + private static File newJar; + + private static Set toDelete = new HashSet<>(); + + private static boolean isActivated() { + return activated; + } + + public static void activate() { + activated = true; + VersionInfo available = VersionCheckSystem.getInstance().getNewVersionAvailable(); + + if (!Version.isNewVersionAvailable(new Version(VersionCheckSystem.getCurrentVersion()), available.getVersion())) { + return; + } + try { + File pluginsFolder = getPluginsFolder(); + newJar = new File(pluginsFolder, "Plan-" + available.getVersion() + ".jar"); + + downloadNewJar(available, newJar); + registerOldJarForDeletion(pluginsFolder, newJar); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static File getPluginsFolder() throws FileNotFoundException { + File dataFolder = PlanPlugin.getInstance().getDataFolder(); + File pluginsFolder = Check.isSpongeAvailable() + ? new File(dataFolder.getParentFile().getParentFile().getPath(), "mods") + : new File(dataFolder.getParentFile().getPath()); + if (!pluginsFolder.isDirectory()) { + throw new FileNotFoundException("Could not get plugin folder for Plan."); + } + return pluginsFolder; + } + + public static void deActivate() { + activated = false; + Log.infoColor("§aUpdate has been cancelled."); + + if (newJar != null && newJar.exists()) { + if (!newJar.delete()) { + newJar.deleteOnExit(); + } + } + toDelete.clear(); + } + + public static void registerOldJarForDeletion(File pluginsFolder, File newFileLocation) throws FileNotFoundException { + File[] files = pluginsFolder.listFiles(); + if (files == null) { + throw new FileNotFoundException("Could not delete old jar."); + } + for (File file : files) { + String fileName = file.getName(); + boolean isPlanJar = (fileName.startsWith("Plan-") && fileName.endsWith(".jar")) + || fileName.equals("Plan.jar"); + boolean isNewJar = fileName.equals(newFileLocation.getName()); + if (isPlanJar && !isNewJar) { + toDelete.add(file); + } + } + } + + public static void downloadNewJar(VersionInfo available, File newFileLocation) throws IOException { + URL downloadFrom = new URL(available.getDownloadUrl()); + try ( + BufferedInputStream in = new BufferedInputStream(downloadFrom.openStream()); + FileOutputStream fout = new FileOutputStream(newFileLocation) + ) { + final byte data[] = new byte[1024]; + int count; + while ((count = in.read(data, 0, 1024)) != -1) { + fout.write(data, 0, count); + } + } + } + + public void register() { + if (isActivated()) { + return; + } + Log.infoColor("§aUpdate has been scheduled, Downloading new jar.. Restart server to take effect."); + activate(); + Runtime.getRuntime().addShutdownHook(this); + } + + @Override + public void run() { + if (!(Check.isBukkitAvailable() && Check.isSpongeAvailable() && Check.isBungeeAvailable())) { + unloadJar(); + } + + for (File f : toDelete) { + if (!f.delete()) { + f.deleteOnExit(); + } + } + } + + private void unloadJar() { + ClassLoader classLoader = PlanPlugin.class.getClassLoader(); + + if (classLoader instanceof URLClassLoader) { + try { + ((URLClassLoader) classLoader).close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + System.gc(); + } + +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/update/VersionCheckSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/update/VersionCheckSystem.java index 5051d2441..bf6465161 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/update/VersionCheckSystem.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/update/VersionCheckSystem.java @@ -6,6 +6,7 @@ package com.djrapitops.plan.system.update; import com.djrapitops.plan.system.PlanSystem; import com.djrapitops.plan.system.SubSystem; +import com.djrapitops.plan.system.settings.Settings; import com.djrapitops.plugin.api.Priority; import com.djrapitops.plugin.api.systems.NotificationCenter; import com.djrapitops.plugin.api.utility.Version; @@ -13,6 +14,8 @@ import com.djrapitops.plugin.api.utility.log.Log; import com.djrapitops.plugin.utilities.Verify; import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; /** * System for checking if new Version is available when the System initializes. @@ -22,7 +25,7 @@ import java.io.IOException; public class VersionCheckSystem implements SubSystem { private final String currentVersion; - private boolean newVersionAvailable = false; + private VersionInfo newVersionAvailable; public VersionCheckSystem(String currentVersion) { this.currentVersion = currentVersion; @@ -35,7 +38,7 @@ public class VersionCheckSystem implements SubSystem { } public static boolean isNewVersionAvailable() { - return getInstance().newVersionAvailable; + return getInstance().newVersionAvailable != null; } public static String getCurrentVersion() { @@ -44,14 +47,40 @@ public class VersionCheckSystem implements SubSystem { @Override public void enable() { - checkForNewVersion(); + if (Settings.ALLOW_UPDATE.isTrue()) { + try { + List versions = VersionInfoLoader.load(); + if (Settings.NOTIFY_ABOUT_DEV_RELEASES.isFalse()) { + versions = versions.stream().filter(VersionInfo::isRelease).collect(Collectors.toList()); + } + VersionInfo newestVersion = versions.get(0); + if (Version.isNewVersionAvailable(new Version(currentVersion), newestVersion.getVersion())) { + newVersionAvailable = newestVersion; + String notification = + "New Release (" + newestVersion.getVersion().toString() + ") is available " + +// "and can be updated to using update subcommand." + + newestVersion.getChangeLogUrl() + + (newestVersion.isRelease() ? "" : " This is a DEV release."); + Log.infoColor("§a----------------------------------------"); + Log.infoColor("§a" + notification); + Log.infoColor("§a----------------------------------------"); + NotificationCenter.addNotification(newestVersion.isRelease() ? Priority.HIGH : Priority.MEDIUM, notification); + } else { + Log.info("You're using the latest version."); + } + } catch (IOException e) { + Log.error("Version information could not be loaded from Github/versions.txt"); + } + } else { + checkForNewVersion(); + } } private void checkForNewVersion() { String githubVersionUrl = "https://raw.githubusercontent.com/Rsl1122/Plan-PlayerAnalytics/master/Plan/src/main/resources/plugin.yml"; String spigotUrl = "https://www.spigotmc.org/resources/plan-player-analytics.32536/"; try { - newVersionAvailable = Version.checkVersion(currentVersion, githubVersionUrl); + boolean newVersionAvailable = Version.checkVersion(currentVersion, githubVersionUrl); if (!newVersionAvailable) { try { newVersionAvailable = Version.checkVersion(currentVersion, spigotUrl); @@ -77,4 +106,8 @@ public class VersionCheckSystem implements SubSystem { public void disable() { /* Does not need to be closed */ } + + public VersionInfo getNewVersionAvailable() { + return newVersionAvailable; + } } \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/update/VersionInfo.java b/Plan/src/main/java/com/djrapitops/plan/system/update/VersionInfo.java new file mode 100644 index 000000000..c294a5803 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/update/VersionInfo.java @@ -0,0 +1,63 @@ +package com.djrapitops.plan.system.update; + +import com.djrapitops.plugin.api.utility.Version; +import com.google.common.base.Objects; + +/** + * Data class for reading version.txt in https://github.com/Rsl1122/Plan-PlayerAnalytics. + * + * @author Rsl1122 + */ +public class VersionInfo implements Comparable { + + private final boolean release; + private final Version version; + private final String downloadUrl; + private final String changeLogUrl; + + public VersionInfo(boolean release, Version version, String downloadUrl, String changeLogUrl) { + this.release = release; + this.version = version; + this.downloadUrl = downloadUrl; + this.changeLogUrl = changeLogUrl; + } + + public boolean isRelease() { + return release; + } + + public Version getVersion() { + return version; + } + + public String getDownloadUrl() { + return downloadUrl; + } + + public String getChangeLogUrl() { + return changeLogUrl; + } + + public boolean isTrusted() { + return downloadUrl.startsWith("https://github.com/Rsl1122/Plan-PlayerAnalytics/releases/download/"); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + VersionInfo that = (VersionInfo) o; + return release == that.release && + Objects.equal(version, that.version); + } + + @Override + public int hashCode() { + return Objects.hashCode(release, version); + } + + @Override + public int compareTo(VersionInfo o) { + return -this.version.compareTo(o.version); + } +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/update/VersionInfoLoader.java b/Plan/src/main/java/com/djrapitops/plan/system/update/VersionInfoLoader.java new file mode 100644 index 000000000..4ff8281bf --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/update/VersionInfoLoader.java @@ -0,0 +1,57 @@ +package com.djrapitops.plan.system.update; + +import com.djrapitops.plugin.api.utility.Version; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Scanner; + +/** + * Utility for loading version information from github. + * + * @author Rsl1122 + */ +public class VersionInfoLoader { + + private static final String VERSION_TXT_URL = + "https://raw.githubusercontent.com/Rsl1122/Plan-PlayerAnalytics/master/versions.txt"; + + /** + * Loads version information from github. + * + * @return List of VersionInfo, newest version first. + * @throws IOException If site can not be accessed. + * @throws java.net.MalformedURLException If VERSION_TXT_URL is not valid. + */ + public static List load() throws IOException { + URL url = new URL(VERSION_TXT_URL); + + List versionInfo = new ArrayList<>(); + + try (Scanner websiteScanner = new Scanner(url.openStream())) { + while (websiteScanner.hasNextLine()) { + String line = websiteScanner.nextLine(); + if (!line.startsWith("REL") && !line.startsWith("DEV")) { + continue; + } + String[] parts = line.split("\\|"); + if (parts.length < 4) { + continue; + } + boolean release = parts[0].equals("REL"); + Version version = new Version(parts[1]); + String downloadUrl = parts[2]; + String changeLogUrl = parts[3]; + + versionInfo.add(new VersionInfo(release, version, downloadUrl, changeLogUrl)); + } + } + + Collections.sort(versionInfo); + return versionInfo; + } + +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/RequestHandler.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/RequestHandler.java index f699040b7..2d1f9bf03 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/RequestHandler.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/RequestHandler.java @@ -45,7 +45,7 @@ public class RequestHandler implements HttpHandler { Response response = responseHandler.getResponse(request); responseCode = response.getCode(); if (response instanceof PromptAuthorizationResponse) { - responseHeaders.set("WWW-Authenticate", "Basic realm=\"/\";"); + responseHeaders.set("WWW-Authenticate", "Basic realm=\"/\""); } response.setResponseHeaders(responseHeaders); diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/JavaScriptResponse.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/JavaScriptResponse.java index 884df375a..bcfba7697 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/JavaScriptResponse.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/JavaScriptResponse.java @@ -2,7 +2,7 @@ package com.djrapitops.plan.system.webserver.response; import com.djrapitops.plan.system.settings.theme.Theme; import com.djrapitops.plan.system.settings.theme.ThemeVal; -import org.apache.commons.lang3.text.StrSubstitutor; +import org.apache.commons.text.StringSubstitutor; import java.util.HashMap; import java.util.Map; @@ -18,6 +18,6 @@ public class JavaScriptResponse extends FileResponse { super.setType(ResponseType.JAVASCRIPT); Map replace = new HashMap<>(); replace.put("defaultTheme", Theme.getValue(ThemeVal.THEME_DEFAULT)); - setContent(StrSubstitutor.replace(Theme.replaceColors(getContent()), replace)); + setContent(StringSubstitutor.replace(Theme.replaceColors(getContent()), replace)); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/errors/ErrorResponse.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/errors/ErrorResponse.java index 26a50d66f..db2e8cad7 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/errors/ErrorResponse.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/errors/ErrorResponse.java @@ -9,7 +9,7 @@ import com.djrapitops.plan.system.webserver.response.Response; import com.djrapitops.plan.utilities.MiscUtils; import com.djrapitops.plan.utilities.file.FileUtil; import com.djrapitops.plugin.api.utility.log.Log; -import org.apache.commons.lang3.text.StrSubstitutor; +import org.apache.commons.text.StringSubstitutor; import java.io.IOException; import java.util.HashMap; @@ -41,7 +41,7 @@ public class ErrorResponse extends Response { placeHolders.put("paragraph", paragraph); placeHolders.put("version", MiscUtils.getPlanVersion()); - setContent(StrSubstitutor.replace(getContent(), placeHolders)); + setContent(StringSubstitutor.replace(getContent(), placeHolders)); } public void setTitle(String title) { diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/InspectPageResponse.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/InspectPageResponse.java index a072ee71c..3735fe690 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/InspectPageResponse.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/InspectPageResponse.java @@ -6,7 +6,7 @@ import com.djrapitops.plan.system.webserver.response.cache.PageId; import com.djrapitops.plan.system.webserver.response.cache.ResponseCache; import com.djrapitops.plan.system.webserver.response.errors.ErrorResponse; import com.djrapitops.plan.system.webserver.response.pages.parts.InspectPagePluginsContent; -import org.apache.commons.lang3.text.StrSubstitutor; +import org.apache.commons.text.StringSubstitutor; import java.util.HashMap; import java.util.Map; @@ -35,7 +35,7 @@ public class InspectPageResponse extends Response { replaceMap.put("navPluginsTabs", inspectPagePluginsTab[0]); replaceMap.put("pluginsTabs", inspectPagePluginsTab[1]); - return StrSubstitutor.replace(super.getContent(), replaceMap); + return StringSubstitutor.replace(super.getContent(), replaceMap); } private String[] getCalculating() { diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/PlayersPageResponse.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/PlayersPageResponse.java index ace6d0bfc..5afde7d68 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/PlayersPageResponse.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/PlayersPageResponse.java @@ -20,7 +20,7 @@ import com.djrapitops.plan.utilities.file.FileUtil; import com.djrapitops.plan.utilities.html.Html; import com.djrapitops.plugin.api.Check; import com.djrapitops.plugin.api.utility.log.Log; -import org.apache.commons.lang3.text.StrSubstitutor; +import org.apache.commons.text.StringSubstitutor; import java.io.IOException; import java.util.*; @@ -47,7 +47,7 @@ public class PlayersPageResponse extends Response { } replace.put("playersTable", buildPlayersTable(db)); replace.put("version", plugin.getVersion()); - super.setContent(Theme.replaceColors(StrSubstitutor.replace(FileUtil.getStringFromResource("web/players.html"), replace))); + super.setContent(Theme.replaceColors(StringSubstitutor.replace(FileUtil.getStringFromResource("web/players.html"), replace))); } catch (DBException | IOException e) { Log.toLog(this.getClass(), e); setContent(new InternalErrorResponse("/players", e).getContent()); diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/FormatUtils.java b/Plan/src/main/java/com/djrapitops/plan/utilities/FormatUtils.java index df7aefc2d..70e77a9be 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/FormatUtils.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/FormatUtils.java @@ -276,10 +276,13 @@ public class FormatUtils { } public static String formatIP(String ip) { + if ("localhost".equals(ip)) { + return ip; + } StringBuilder b = new StringBuilder(); int i = 0; for (String part : ip.split("\\.")) { - if (i >= 3) { + if (i >= 2) { break; } @@ -288,7 +291,7 @@ public class FormatUtils { i++; } - return b.append("xx").toString(); + return b.append("xx.xx").toString(); } /** diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/MiscUtils.java b/Plan/src/main/java/com/djrapitops/plan/utilities/MiscUtils.java index 722d24b52..18a740eeb 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/MiscUtils.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/MiscUtils.java @@ -1,14 +1,12 @@ package com.djrapitops.plan.utilities; -import com.djrapitops.plan.Plan; -import com.djrapitops.plan.PlanBungee; +import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.api.exceptions.database.DBException; import com.djrapitops.plan.system.database.databases.Database; import com.djrapitops.plan.system.settings.Permissions; import com.djrapitops.plan.system.settings.Settings; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; -import com.djrapitops.plugin.api.Check; import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.api.utility.log.Log; import com.djrapitops.plugin.command.CommandUtils; @@ -142,10 +140,6 @@ public class MiscUtils { } public static String getPlanVersion() { - if (Check.isBukkitAvailable()) { - return Plan.getInstance().getDescription().getVersion(); - } else { - return PlanBungee.getInstance().getDescription().getVersion(); - } + return PlanPlugin.getInstance().getVersion(); } } diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/SHA256Hash.java b/Plan/src/main/java/com/djrapitops/plan/utilities/SHA256Hash.java new file mode 100644 index 000000000..0335912f6 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/SHA256Hash.java @@ -0,0 +1,21 @@ +package com.djrapitops.plan.utilities; + +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; + +public class SHA256Hash { + + private final String original; + + public SHA256Hash(String original) { + this.original = original; + } + + public String create() throws NoSuchAlgorithmException, UnsupportedEncodingException { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + digest.update(original.getBytes("UTF-8")); + return Base64.getEncoder().encodeToString(digest.digest()); + } +} diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java index 873ca9395..5cd90d252 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java @@ -16,7 +16,7 @@ import com.djrapitops.plan.system.processing.Processing; import com.djrapitops.plan.system.settings.Settings; import com.djrapitops.plan.system.settings.locale.Locale; import com.djrapitops.plan.system.settings.locale.Msg; -import com.djrapitops.plan.system.tasks.BukkitTaskSystem; +import com.djrapitops.plan.system.tasks.ServerTaskSystem; import com.djrapitops.plan.system.tasks.TaskSystem; import com.djrapitops.plan.utilities.MiscUtils; import com.djrapitops.plugin.StaticHolder; @@ -79,7 +79,7 @@ public class Analysis implements Callable { } private AnalysisData runAnalysis() throws Exception { - ((BukkitTaskSystem) TaskSystem.getInstance()).cancelBootAnalysis(); + ((ServerTaskSystem) TaskSystem.getInstance()).cancelBootAnalysis(); Benchmark.start("Analysis: Total"); log(Locale.get(Msg.ANALYSIS_START).toString()); diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/html/Html.java b/Plan/src/main/java/com/djrapitops/plan/utilities/html/Html.java index 885a80d85..8873663fa 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/html/Html.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/html/Html.java @@ -1,6 +1,6 @@ package com.djrapitops.plan.utilities.html; -import org.apache.commons.lang3.text.StrSubstitutor; +import org.apache.commons.text.StringSubstitutor; import java.io.Serializable; import java.util.HashMap; @@ -131,7 +131,7 @@ public enum Html { replaceMap.put(String.valueOf(i), p[i]); } - StrSubstitutor sub = new StrSubstitutor(replaceMap); + StringSubstitutor sub = new StringSubstitutor(replaceMap); sub.setEnableSubstitutionInVariables(false); return sub.replace(html); } diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/html/HtmlUtils.java b/Plan/src/main/java/com/djrapitops/plan/utilities/html/HtmlUtils.java index 9112bef4a..53358ed0d 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/html/HtmlUtils.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/html/HtmlUtils.java @@ -2,7 +2,7 @@ package com.djrapitops.plan.utilities.html; import com.djrapitops.plan.system.info.server.ServerInfo; import com.djrapitops.plan.system.settings.Settings; -import org.apache.commons.lang3.text.StrSubstitutor; +import org.apache.commons.text.StringSubstitutor; import java.io.Serializable; import java.util.Map; @@ -27,7 +27,7 @@ public class HtmlUtils { * @return Html with placeholders replaced */ public static String replacePlaceholders(String html, Map replaceMap) { - StrSubstitutor sub = new StrSubstitutor(replaceMap); + StringSubstitutor sub = new StringSubstitutor(replaceMap); sub.setEnableSubstitutionInVariables(true); return sub.replace(html); } diff --git a/Plan/src/main/resources/bungee.yml b/Plan/src/main/resources/bungee.yml index ff3950d61..4c7a06885 100644 --- a/Plan/src/main/resources/bungee.yml +++ b/Plan/src/main/resources/bungee.yml @@ -1,4 +1,4 @@ name: Plan author: Rsl1122 main: com.djrapitops.plan.PlanBungee -version: 4.2.0 \ No newline at end of file +version: 4.3.0 \ No newline at end of file diff --git a/Plan/src/main/resources/bungeeconfig.yml b/Plan/src/main/resources/bungeeconfig.yml index 439e5f76b..0e4be559d 100644 --- a/Plan/src/main/resources/bungeeconfig.yml +++ b/Plan/src/main/resources/bungeeconfig.yml @@ -12,6 +12,9 @@ Network: Plugin: Debug: 'false' Locale: default + Allow-Update-Command: true + Notify-About-DEV-Releases: false + KeepLogsForXDays: 7 # ----------------------------------------------------- # More information about SSL Certificate Settings: @@ -63,6 +66,8 @@ Data: Commands: LogUnknownCommands: false CombineCommandAliases: true + Geolocations: true + KeepInactivePlayerDataForDays: 180 # ----------------------------------------------------- Customization: UseServerTime: true diff --git a/Plan/src/main/resources/config.yml b/Plan/src/main/resources/config.yml index 65cbe2836..be15fa519 100644 --- a/Plan/src/main/resources/config.yml +++ b/Plan/src/main/resources/config.yml @@ -17,6 +17,9 @@ Plugin: Bungee-Override: StandaloneMode: false CopyBungeeConfig: true + Allow-Update-Command: true + Notify-About-DEV-Releases: false + KeepLogsForXDays: 7 # ----------------------------------------------------- # More information about SSL Certificate Settings: @@ -77,6 +80,8 @@ Data: Commands: LogUnknownCommands: false CombineCommandAliases: true + Geolocations: true + KeepInactivePlayerDataForDays: 180 # ----------------------------------------------------- Customization: UseServerTime: true diff --git a/Plan/src/main/resources/plugin.yml b/Plan/src/main/resources/plugin.yml index ae52c2950..dc914b096 100644 --- a/Plan/src/main/resources/plugin.yml +++ b/Plan/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: Plan author: Rsl1122 main: com.djrapitops.plan.Plan -version: 4.2.0 +version: 4.3.0 softdepend: - EssentialsX - Towny diff --git a/Plan/src/test/java/com/djrapitops/plan/system/BungeeBukkitConnectionTest.java b/Plan/src/test/java/com/djrapitops/plan/system/BungeeBukkitConnectionTest.java index a7ed9e625..72de62411 100644 --- a/Plan/src/test/java/com/djrapitops/plan/system/BungeeBukkitConnectionTest.java +++ b/Plan/src/test/java/com/djrapitops/plan/system/BungeeBukkitConnectionTest.java @@ -8,7 +8,7 @@ import com.djrapitops.plan.Plan; import com.djrapitops.plan.PlanBungee; import com.djrapitops.plan.api.exceptions.EnableException; import com.djrapitops.plan.api.exceptions.connection.WebException; -import com.djrapitops.plan.system.database.BukkitDBSystem; +import com.djrapitops.plan.system.database.ServerDBSystem; import com.djrapitops.plan.system.info.request.GenerateInspectPageRequest; import com.djrapitops.plan.system.info.server.ServerInfo; import com.djrapitops.plan.system.settings.Settings; @@ -97,7 +97,7 @@ public class BungeeBukkitConnectionTest { Settings.WEBSERVER_PORT.setTemporaryValue(9250); Settings.BUNGEE_IP.setTemporaryValue("localhost"); Settings.DB_TYPE.setTemporaryValue("sqlite"); - bungeeSystem.setDatabaseSystem(new BukkitDBSystem()); + bungeeSystem.setDatabaseSystem(new ServerDBSystem()); bungeeSystem.enable(); diff --git a/Plan/src/test/java/com/djrapitops/plan/system/BungeeSystemTest.java b/Plan/src/test/java/com/djrapitops/plan/system/BungeeSystemTest.java index fad9d8338..8a2e169c0 100644 --- a/Plan/src/test/java/com/djrapitops/plan/system/BungeeSystemTest.java +++ b/Plan/src/test/java/com/djrapitops/plan/system/BungeeSystemTest.java @@ -6,7 +6,7 @@ package com.djrapitops.plan.system; import com.djrapitops.plan.PlanBungee; import com.djrapitops.plan.api.exceptions.EnableException; -import com.djrapitops.plan.system.database.BukkitDBSystem; +import com.djrapitops.plan.system.database.ServerDBSystem; import com.djrapitops.plan.system.settings.Settings; import org.junit.*; import org.junit.rules.ExpectedException; @@ -63,7 +63,7 @@ public class BungeeSystemTest { Settings.WEBSERVER_PORT.setTemporaryValue(9005); Settings.BUNGEE_IP.setTemporaryValue("8.8.8.8"); Settings.DB_TYPE.setTemporaryValue("sqlite"); - bungeeSystem.setDatabaseSystem(new BukkitDBSystem()); + bungeeSystem.setDatabaseSystem(new ServerDBSystem()); bungeeSystem.enable(); } @@ -77,7 +77,7 @@ public class BungeeSystemTest { Settings.WEBSERVER_PORT.setTemporaryValue(9005); Settings.DB_TYPE.setTemporaryValue("sqlite"); - bungeeSystem.setDatabaseSystem(new BukkitDBSystem()); + bungeeSystem.setDatabaseSystem(new ServerDBSystem()); bungeeSystem.enable(); } diff --git a/Plan/src/test/java/com/djrapitops/plan/system/database/databases/SQLiteTest.java b/Plan/src/test/java/com/djrapitops/plan/system/database/databases/SQLiteTest.java index 939a38bb6..6364ce644 100644 --- a/Plan/src/test/java/com/djrapitops/plan/system/database/databases/SQLiteTest.java +++ b/Plan/src/test/java/com/djrapitops/plan/system/database/databases/SQLiteTest.java @@ -22,6 +22,7 @@ import com.djrapitops.plan.system.processing.processors.player.RegisterProcessor import com.djrapitops.plan.utilities.Base64Util; import com.djrapitops.plan.utilities.ManageUtils; import com.djrapitops.plan.utilities.MiscUtils; +import com.djrapitops.plan.utilities.SHA256Hash; import com.djrapitops.plan.utilities.analysis.MathUtils; import com.djrapitops.plugin.StaticHolder; import com.djrapitops.plugin.api.utility.log.Log; @@ -36,8 +37,10 @@ import utilities.TestConstants; import utilities.TestErrorManager; import utilities.mocks.SystemMockUtil; +import java.io.UnsupportedEncodingException; import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; +import java.security.NoSuchAlgorithmException; import java.sql.SQLException; import java.util.*; @@ -258,7 +261,7 @@ public class SQLiteTest { String expectedGeoLoc = "TestLocation"; long time = MiscUtils.getTime(); - GeoInfo expected = new GeoInfo(expectedIP, expectedGeoLoc, time); + GeoInfo expected = new GeoInfo(expectedIP, expectedGeoLoc, time, "3"); geoInfoTable.saveGeoInfo(playerUUID, expected); geoInfoTable.saveGeoInfo(playerUUID, expected); commitTest(); @@ -563,7 +566,7 @@ public class SQLiteTest { sessionsTable.saveSession(playerUUID, session); nicknamesTable.saveUserName(playerUUID, "TestNick"); - geoInfoTable.saveGeoInfo(playerUUID, new GeoInfo("1.2.3.4", "TestLoc", 223456789L)); + geoInfoTable.saveGeoInfo(playerUUID, new GeoInfo("1.2.3.4", "TestLoc", 223456789L, "3")); actionsTable.insertAction(playerUUID, new Action(1324L, Actions.FIRST_SESSION, "Add")); assertTrue(usersTable.isRegistered(playerUUID)); @@ -579,7 +582,7 @@ public class SQLiteTest { } @Test - public void testRemovalEverything() throws SQLException, DBException { + public void testRemovalEverything() throws SQLException, DBException, UnsupportedEncodingException, NoSuchAlgorithmException { UserInfoTable userInfoTable = db.getUserInfoTable(); UsersTable usersTable = db.getUsersTable(); SessionsTable sessionsTable = db.getSessionsTable(); @@ -608,7 +611,7 @@ public class SQLiteTest { assertTrue(securityTable.getUsers().isEmpty()); } - private void saveAllData(SQLDB database) throws SQLException { + private void saveAllData(SQLDB database) throws SQLException, UnsupportedEncodingException, NoSuchAlgorithmException { System.out.println("Saving all possible data to the Database.."); UserInfoTable userInfoTable = database.getUserInfoTable(); UsersTable usersTable = database.getUsersTable(); @@ -632,7 +635,8 @@ public class SQLiteTest { sessionsTable.saveSession(playerUUID, session); nicknamesTable.saveUserName(playerUUID, "TestNick"); - geoInfoTable.saveGeoInfo(playerUUID, new GeoInfo("1.2.3.4", "TestLoc", 223456789L)); + geoInfoTable.saveGeoInfo(playerUUID, new GeoInfo("1.2.3.4", "TestLoc", 223456789L, + new SHA256Hash("1.2.3.4").create())); actionsTable.insertAction(playerUUID, new Action(1324L, Actions.FIRST_SESSION, "Add")); assertTrue(usersTable.isRegistered(playerUUID)); @@ -756,7 +760,7 @@ public class SQLiteTest { } @Test - public void testBackupAndRestore() throws SQLException, DBInitException { + public void testBackupAndRestore() throws SQLException, DBInitException, UnsupportedEncodingException, NoSuchAlgorithmException { System.out.println("- Creating Backup Database -"); SQLiteDB backup = new SQLiteDB("debug-backup" + MiscUtils.getTime()); backup.init(); @@ -894,7 +898,7 @@ public class SQLiteTest { } @Test - public void testWorldTableGetWorldNamesNoException() throws SQLException { + public void testWorldTableGetWorldNamesNoException() throws SQLException, UnsupportedEncodingException, NoSuchAlgorithmException { saveAllData(db); Set worldNames = db.getWorldTable().getWorldNames(TestConstants.SERVER_UUID); assertEquals(new HashSet<>(worlds), worldNames); @@ -924,11 +928,11 @@ public class SQLiteTest { usersTable.registerUser(secondUuid, 0, ""); usersTable.registerUser(thirdUuid, 0, ""); - geoInfoTable.saveGeoInfo(firstUuid, new GeoInfo("-", "Test1", 0)); - GeoInfo secondInfo = new GeoInfo("-", "Test2", 5); + geoInfoTable.saveGeoInfo(firstUuid, new GeoInfo("-", "Test1", 0, "3")); + GeoInfo secondInfo = new GeoInfo("-", "Test2", 5, "3"); geoInfoTable.saveGeoInfo(firstUuid, secondInfo); - geoInfoTable.saveGeoInfo(secondUuid, new GeoInfo("-", "Test3", 0)); - geoInfoTable.saveGeoInfo(thirdUuid, new GeoInfo("-", "Test4", 0)); + geoInfoTable.saveGeoInfo(secondUuid, new GeoInfo("-", "Test3", 0, "3")); + geoInfoTable.saveGeoInfo(thirdUuid, new GeoInfo("-", "Test4", 0, "3")); List geolocations = geoInfoTable.getNetworkGeolocations(); System.out.println(geolocations); diff --git a/Plan/src/test/java/com/djrapitops/plan/system/update/ShutdownUpdateHookTest.java b/Plan/src/test/java/com/djrapitops/plan/system/update/ShutdownUpdateHookTest.java new file mode 100644 index 000000000..825ae3a47 --- /dev/null +++ b/Plan/src/test/java/com/djrapitops/plan/system/update/ShutdownUpdateHookTest.java @@ -0,0 +1,57 @@ +package com.djrapitops.plan.system.update; + +import com.djrapitops.plugin.api.utility.Version; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Test for ShutdownUpdateHook functionality. + * + * @author Rsl1122 + * @see ShutdownUpdateHook + */ +public class ShutdownUpdateHookTest { + + @ClassRule + public static TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Test + public void downloadNewJar() throws IOException { + File newJar = new File(temporaryFolder.getRoot(), "Plan-4.2.0.jar"); + ShutdownUpdateHook.downloadNewJar(new VersionInfo( + true, + new Version("4.2.0"), + "https://github.com/Rsl1122/Plan-PlayerAnalytics/releases/download/4.2.0/Plan-4.2.0.jar", + "" + ), newJar + ); + + assertTrue(newJar.exists()); + } + + @Test + public void deleteOldJarAndKeepNewJar() throws IOException { + File newJar = new File(temporaryFolder.getRoot(), "Plan-4.2.0.jar"); + File oldJar = new File(temporaryFolder.getRoot(), "Plan.jar"); + + assertTrue(newJar.createNewFile()); + assertTrue(oldJar.createNewFile()); + + System.out.println(Arrays.toString(temporaryFolder.getRoot().listFiles())); + ShutdownUpdateHook.registerOldJarForDeletion(temporaryFolder.getRoot(), new File(temporaryFolder.getRoot(), "Plan-4.2.0.jar")); + + new ShutdownUpdateHook().run(); + + System.out.println(Arrays.toString(temporaryFolder.getRoot().listFiles())); + assertTrue(newJar.exists()); + assertFalse(oldJar.exists()); + } +} \ No newline at end of file diff --git a/Plan/src/test/java/com/djrapitops/plan/system/update/VersionInfoLoaderTest.java b/Plan/src/test/java/com/djrapitops/plan/system/update/VersionInfoLoaderTest.java new file mode 100644 index 000000000..60734e2a0 --- /dev/null +++ b/Plan/src/test/java/com/djrapitops/plan/system/update/VersionInfoLoaderTest.java @@ -0,0 +1,24 @@ +package com.djrapitops.plan.system.update; + +import com.djrapitops.plugin.api.utility.Version; +import org.junit.Test; + +import java.io.IOException; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class VersionInfoLoaderTest { + + @Test + public void versionLoaderTest() throws IOException { + List versions = VersionInfoLoader.load(); + + VersionInfo oldest = versions.get(versions.size() - 1); + assertEquals(new Version("4.1.7"), oldest.getVersion()); + assertTrue(oldest.isRelease()); + assertTrue(oldest.isTrusted()); + } + +} \ No newline at end of file diff --git a/Plan/src/test/java/com/djrapitops/plan/utilities/FormatUtilsTest.java b/Plan/src/test/java/com/djrapitops/plan/utilities/FormatUtilsTest.java index ac4e2e1fb..87c853d10 100644 --- a/Plan/src/test/java/com/djrapitops/plan/utilities/FormatUtilsTest.java +++ b/Plan/src/test/java/com/djrapitops/plan/utilities/FormatUtilsTest.java @@ -161,7 +161,7 @@ public class FormatUtilsTest { String ip = "1.2.3.4"; String ip2 = "1.2.3.26"; String ip3 = "1.2.3.235"; - String expected = "1.2.3.xx"; + String expected = "1.2.xx.xx"; assertEquals(expected, FormatUtils.formatIP(ip)); assertEquals(expected, FormatUtils.formatIP(ip2)); diff --git a/Plan/src/test/java/com/djrapitops/plan/utilities/SHA256HashTest.java b/Plan/src/test/java/com/djrapitops/plan/utilities/SHA256HashTest.java new file mode 100644 index 000000000..4af7d88e8 --- /dev/null +++ b/Plan/src/test/java/com/djrapitops/plan/utilities/SHA256HashTest.java @@ -0,0 +1,19 @@ +package com.djrapitops.plan.utilities; + +import org.junit.Test; + +import java.io.UnsupportedEncodingException; +import java.security.NoSuchAlgorithmException; + +import static org.junit.Assert.assertEquals; + +public class SHA256HashTest { + + @Test + public void sameStringReturnsSameHash() throws UnsupportedEncodingException, NoSuchAlgorithmException { + String expected = new SHA256Hash("1.3.4.5").create(); + String result = new SHA256Hash("1.3.4.5").create(); + assertEquals(expected, result); + } + +} \ No newline at end of file diff --git a/Plan/src/test/java/utilities/TestErrorManager.java b/Plan/src/test/java/utilities/TestErrorManager.java index 292a40224..425029cd7 100644 --- a/Plan/src/test/java/utilities/TestErrorManager.java +++ b/Plan/src/test/java/utilities/TestErrorManager.java @@ -11,7 +11,7 @@ import com.djrapitops.plugin.api.utility.log.errormanager.ErrorManager; * * @author Rsl1122 */ -public class TestErrorManager extends ErrorManager { +public class TestErrorManager implements ErrorManager { @Override public void toLog(String s, Throwable throwable, Class aClass) { diff --git a/PlanPluginBridge/PlanPluginBridge-4.2.0.jar b/PlanPluginBridge/PlanPluginBridge-4.3.0.jar similarity index 77% rename from PlanPluginBridge/PlanPluginBridge-4.2.0.jar rename to PlanPluginBridge/PlanPluginBridge-4.3.0.jar index 785b36dc9..214f1f3a9 100644 Binary files a/PlanPluginBridge/PlanPluginBridge-4.2.0.jar and b/PlanPluginBridge/PlanPluginBridge-4.3.0.jar differ diff --git a/PlanPluginBridge/pom.xml b/PlanPluginBridge/pom.xml index db9c9f651..fde602e3a 100644 --- a/PlanPluginBridge/pom.xml +++ b/PlanPluginBridge/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.djrapitops PlanPluginBridge - 4.2.0-SNAPSHOT + 4.3.0-SNAPSHOT jar ${project.groupId}:${project.artifactId} @@ -65,13 +65,17 @@ viaversion-repo https://repo.viaversion.com + + placeholderapi + http://repo.extendedclip.com/content/repositories/placeholderapi/ + com.djrapitops Plan - 4.2.0-SNAPSHOT + 4.3.0-SNAPSHOT provided @@ -210,6 +214,12 @@ 3.3.5 provided + + me.clip + placeholderapi + LATEST + provided + ${project.artifactId} diff --git a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/Bridge.java b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/Bridge.java index 13a44d935..076bdbdb3 100644 --- a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/Bridge.java +++ b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/Bridge.java @@ -17,6 +17,7 @@ import com.djrapitops.pluginbridge.plan.jobs.JobsHook; import com.djrapitops.pluginbridge.plan.kingdoms.KingdomsHook; import com.djrapitops.pluginbridge.plan.litebans.LiteBansHook; import com.djrapitops.pluginbridge.plan.mcmmo.McmmoHook; +import com.djrapitops.pluginbridge.plan.placeholderapi.PlaceholderAPIHook; import com.djrapitops.pluginbridge.plan.protocolsupport.ProtocolSupportHook; import com.djrapitops.pluginbridge.plan.redprotect.RedProtectHook; import com.djrapitops.pluginbridge.plan.superbvote.SuperbVoteHook; @@ -87,7 +88,8 @@ public class Bridge { new RedProtectHook(h), new TownyHook(h), new VaultHook(h), - new ViaVersionHook(h) + new ViaVersionHook(h)//, +// new PlaceholderAPIHook(h) }; } } diff --git a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/griefprevention/GriefPreventionData.java b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/griefprevention/GriefPreventionData.java index 971672bdf..002453587 100644 --- a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/griefprevention/GriefPreventionData.java +++ b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/griefprevention/GriefPreventionData.java @@ -13,7 +13,6 @@ import com.djrapitops.plan.utilities.analysis.MathUtils; import com.djrapitops.plugin.utilities.FormatUtils; import me.ryanhamshire.GriefPrevention.Claim; import me.ryanhamshire.GriefPrevention.DataStore; -import me.ryanhamshire.GriefPrevention.PlayerData; import java.util.*; import java.util.stream.Collectors; @@ -43,15 +42,12 @@ public class GriefPreventionData extends PluginData { claim -> FormatUtils.formatLocation(claim.getGreaterBoundaryCorner()), Claim::getArea) ); - PlayerData data = dataStore.getPlayerData(uuid); - int blocks = data.getAccruedClaimBlocks() + data.getBonusClaimBlocks() + dataStore.getGroupBonusBlocks(uuid); String softMuted = dataStore.isSoftMuted(uuid) ? "Yes" : "No"; long totalArea = MathUtils.sumLong(claims.values().stream().map(i -> (long) i)); inspectContainer.addValue(getWithIcon("SoftMuted", "bell-slash-o", "deep-orange"), softMuted); inspectContainer.addValue(getWithIcon("Claims", "map-marker", "blue-grey"), claims.size()); inspectContainer.addValue(getWithIcon("Claimed Area", "map-o", "light-green"), totalArea); - inspectContainer.addValue(getWithIcon("Claim Blocks Available", "map-o", "light-green"), blocks); TableContainer claimsTable = new TableContainer(getWithIcon("Claim", "map-marker"), getWithIcon("Area", "map-o")); claimsTable.setColor("blue-grey"); diff --git a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/griefprevention/plus/GriefPreventionPlusData.java b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/griefprevention/plus/GriefPreventionPlusData.java index 37a14527e..3045d7ce9 100644 --- a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/griefprevention/plus/GriefPreventionPlusData.java +++ b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/griefprevention/plus/GriefPreventionPlusData.java @@ -13,7 +13,6 @@ import com.djrapitops.plan.utilities.analysis.MathUtils; import com.djrapitops.plugin.utilities.FormatUtils; import net.kaikk.mc.gpp.Claim; import net.kaikk.mc.gpp.DataStore; -import net.kaikk.mc.gpp.PlayerData; import java.util.*; import java.util.stream.Collectors; @@ -43,13 +42,10 @@ public class GriefPreventionPlusData extends PluginData { claim -> FormatUtils.formatLocation(claim.getGreaterBoundaryCorner()), Claim::getArea) ); - PlayerData data = dataStore.getPlayerData(uuid); - int blocks = data.getAccruedClaimBlocks() + data.getBonusClaimBlocks(); long totalArea = MathUtils.sumLong(claims.values().stream().map(i -> (long) i)); inspectContainer.addValue(getWithIcon("Claims", "map-marker", "blue-grey"), claims.size()); inspectContainer.addValue(getWithIcon("Claimed Area", "map-o", "light-green"), totalArea); - inspectContainer.addValue(getWithIcon("Claim Blocks Available", "map-o", "light-green"), blocks); TableContainer claimsTable = new TableContainer(getWithIcon("Claim", "map-marker"), getWithIcon("Area", "map-o")); claimsTable.setColor("blue-grey"); diff --git a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/placeholderapi/PlaceholderAPIHook.java b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/placeholderapi/PlaceholderAPIHook.java new file mode 100644 index 000000000..e4572a8a6 --- /dev/null +++ b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/placeholderapi/PlaceholderAPIHook.java @@ -0,0 +1,31 @@ +package com.djrapitops.pluginbridge.plan.placeholderapi; + +import com.djrapitops.plan.data.plugin.HookHandler; +import com.djrapitops.pluginbridge.plan.Hook; +import me.clip.placeholderapi.PlaceholderAPI; + +/** + * A Class responsible for hooking to PlaceholderAPI. + * + * @author Rsl1122 + */ +public class PlaceholderAPIHook extends Hook { + + /** + * Hooks the plugin and registers it's PluginData objects. + *

+ * API#addPluginDataSource uses the same method from HookHandler. + * + * @param hookH HookHandler instance for registering the data sources. + */ + public PlaceholderAPIHook(HookHandler hookH) { + super("me.clip.placeholderapi.PlaceholderAPI", hookH); + } + + public void hook() throws NoClassDefFoundError { + if (enabled) { + PlaceholderAPI.unregisterPlaceholderHook("plan"); + PlaceholderAPI.registerPlaceholderHook("plan", new PlanPlaceholders()); + } + } +} diff --git a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/placeholderapi/PlanPlaceholders.java b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/placeholderapi/PlanPlaceholders.java new file mode 100644 index 000000000..3f0f576fd --- /dev/null +++ b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/placeholderapi/PlanPlaceholders.java @@ -0,0 +1,190 @@ +package com.djrapitops.pluginbridge.plan.placeholderapi; + +import com.djrapitops.plan.PlanPlugin; +import com.djrapitops.plan.data.PlayerProfile; +import com.djrapitops.plan.data.ServerProfile; +import com.djrapitops.plan.data.calculation.ActivityIndex; +import com.djrapitops.plan.data.container.TPS; +import com.djrapitops.plan.system.PlanSystem; +import com.djrapitops.plan.system.database.databases.Database; +import com.djrapitops.plan.utilities.FormatUtils; +import com.djrapitops.plan.utilities.MiscUtils; +import com.djrapitops.plan.utilities.analysis.Analysis; +import com.djrapitops.plan.utilities.analysis.MathUtils; +import com.djrapitops.plugin.api.TimeAmount; +import com.djrapitops.plugin.api.utility.log.Log; +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import org.bukkit.entity.Player; + +import java.io.Serializable; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.stream.Collectors; + +/** + * Placeholders of Plan. + * + * @author Rsl1122 + */ +public class PlanPlaceholders extends PlaceholderExpansion { + + private final PlanPlugin plugin; + + public PlanPlaceholders() { + plugin = PlanPlugin.getInstance(); + } + + @Override + public String getIdentifier() { + return "plan"; + } + + @Override + public String getPlugin() { + return "Plan"; + } + + @Override + public String getAuthor() { + return "Rsl1122"; + } + + @Override + public String getVersion() { + return plugin.getVersion(); + } + + @Override + public String onPlaceholderRequest(Player player, String identifier) { + Serializable planValue = getPlanValue(identifier); + if (planValue != null) { + return planValue.toString(); + } + Serializable serverValue = getServerValue(identifier); + if (serverValue != null) { + return serverValue.toString(); + } + + if (player != null) { + Serializable playerValue = getPlayerValue(player, identifier); + if (playerValue != null) { + return playerValue.toString(); + } + } + + return null; + } + + private Serializable getPlanValue(String identifier) { + switch (identifier.toLowerCase()) { + case "address": + return PlanSystem.getInstance().getWebServerSystem().getWebServer().getAccessAddress(); + case "analysis_refresh": + Optional refreshDate = Analysis.getRefreshDate(); + if (refreshDate.isPresent()) { + return FormatUtils.formatTimeStampClock(refreshDate.get()); + } + return "Not yet run"; + default: + return null; + } + } + + private Serializable getServerValue(String identifier) { + Callable serverProfile = Analysis::getServerProfile; + + long now = MiscUtils.getTime(); + long dayAgo = now - TimeAmount.DAY.ms(); + long weekAgo = now - TimeAmount.WEEK.ms(); + long monthAgo = now - TimeAmount.MONTH.ms(); + + try { + switch (identifier.toLowerCase()) { + case "players_total": + return serverProfile.call().getPlayerCount(); + case "players_new_day": + return serverProfile.call().getPlayersWhoRegistered(0, dayAgo).count(); + case "players_new_week": + return serverProfile.call().getPlayersWhoRegistered(0, weekAgo).count(); + case "players_new_month": + return serverProfile.call().getPlayersWhoRegistered(0, monthAgo).count(); + case "players_unique_day": + return serverProfile.call().getPlayersWhoPlayedBetween(0, dayAgo).count(); + case "players_unique_week": + return serverProfile.call().getPlayersWhoPlayedBetween(0, weekAgo).count(); + case "players_unique_month": + return serverProfile.call().getPlayersWhoPlayedBetween(0, monthAgo).count(); + case "playtime_total": + return FormatUtils.formatTimeAmount(serverProfile.call().getTotalPlaytime()); + case "session_avg": + return FormatUtils.formatTimeAmount( + PlayerProfile.getSessionAverage(serverProfile.call().getAllSessions().stream()) + ); + case "session_count": + return serverProfile.call().getAllSessions().size(); + case "kills_players": + return PlayerProfile.getPlayerKills(serverProfile.call().getAllSessions().stream()).count(); + case "kills_mobs": + return PlayerProfile.getMobKillCount(serverProfile.call().getAllSessions().stream()); + case "deaths_total": + return PlayerProfile.getDeathCount(serverProfile.call().getAllSessions().stream()); + case "tps_day": + return FormatUtils.cutDecimals( + MathUtils.averageDouble(serverProfile.call().getTPSData(0, dayAgo).map(TPS::getTicksPerSecond)) + ); + case "tps_drops_week": + return ServerProfile.getLowSpikeCount(serverProfile.call().getTPSData(0, weekAgo).collect(Collectors.toList())); + default: + break; + } + } catch (Exception e) { + Log.toLog(this.getClass().getName(), e); + } + return null; + } + + private Serializable getPlayerValue(Player player, String identifier) { + UUID uuid = player.getUniqueId(); + Callable profile = () -> Database.getActive().fetch().getPlayerProfile(uuid); + + long now = MiscUtils.getTime(); + long dayAgo = now - TimeAmount.DAY.ms(); + long weekAgo = now - TimeAmount.WEEK.ms(); + long monthAgo = now - TimeAmount.MONTH.ms(); + + try { + switch (identifier.toLowerCase()) { + case "playtime": + return FormatUtils.formatTimeAmount(profile.call().getPlaytime(0, now)); + case "playtime_day": + return FormatUtils.formatTimeAmount(profile.call().getPlaytime(dayAgo, now)); + case "playtime_week": + return FormatUtils.formatTimeAmount(profile.call().getPlaytime(weekAgo, now)); + case "playtime_month": + return FormatUtils.formatTimeAmount(profile.call().getPlaytime(monthAgo, now)); + case "geolocation": + return profile.call().getMostRecentGeoInfo().getGeolocation(); + case "activity_index": + ActivityIndex activityIndex = profile.call().getActivityIndex(now); + return activityIndex.getValue() + " (" + activityIndex.getGroup() + ")"; + case "registered": + return FormatUtils.formatTimeAmount(profile.call().getRegistered()); + case "last_seen": + return FormatUtils.formatTimeAmount(profile.call().getLastSeen()); + case "player_kills": + return profile.call().getPlayerKills().count(); + case "mob_kills": + return profile.call().getMobKillCount(); + case "deaths": + return profile.call().getDeathCount(); + default: + break; + } + } catch (Exception e) { + Log.toLog(this.getClass().getName(), e); + } + return null; + } + +} \ No newline at end of file