org.bstats
diff --git a/Plan/src/main/java/com/djrapitops/plan/PlanSponge.java b/Plan/src/main/java/com/djrapitops/plan/PlanSponge.java
index bcf2623d9..e1110462c 100644
--- a/Plan/src/main/java/com/djrapitops/plan/PlanSponge.java
+++ b/Plan/src/main/java/com/djrapitops/plan/PlanSponge.java
@@ -29,6 +29,7 @@ import org.spongepowered.api.config.ConfigDir;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.game.state.GameStartedServerEvent;
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
+import org.spongepowered.api.plugin.Dependency;
import org.spongepowered.api.plugin.Plugin;
import javax.inject.Named;
@@ -80,7 +81,17 @@ class SpongePlanModule {
}
}
-@Plugin(id = "plan", name = "Plan", version = "4.4.3", description = "Player Analytics Plugin by Rsl1122", authors = {"Rsl1122"})
+@Plugin(
+ id = "plan",
+ name = "Plan",
+ version = "4.4.7",
+ description = "Player Analytics Plugin by Rsl1122",
+ authors = {"Rsl1122"},
+ dependencies = {
+ @Dependency(id = "nucleus", optional = true),
+ @Dependency(id = "luckperms", optional = true)
+ }
+)
public class PlanSponge extends SpongePlugin implements PlanPlugin {
@Inject
diff --git a/Plan/src/main/java/com/djrapitops/plan/PlanVelocity.java b/Plan/src/main/java/com/djrapitops/plan/PlanVelocity.java
new file mode 100644
index 000000000..7a9804902
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/PlanVelocity.java
@@ -0,0 +1,136 @@
+/*
+ * License is provided in the jar as LICENSE also here:
+ * https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
+ */
+package com.djrapitops.plan;
+
+import com.djrapitops.plan.api.exceptions.EnableException;
+import com.djrapitops.plan.command.PlanVelocityCommand;
+import com.djrapitops.plan.system.VelocitySystem;
+import com.djrapitops.plan.system.locale.Locale;
+import com.djrapitops.plan.system.locale.lang.PluginLang;
+import com.djrapitops.plan.system.settings.theme.PlanColorScheme;
+import com.djrapitops.plugin.StaticHolder;
+import com.djrapitops.plugin.VelocityPlugin;
+import com.djrapitops.plugin.api.Benchmark;
+import com.djrapitops.plugin.api.utility.log.DebugLog;
+import com.djrapitops.plugin.api.utility.log.Log;
+import com.djrapitops.plugin.settings.ColorScheme;
+import com.google.inject.Inject;
+import com.velocitypowered.api.plugin.Plugin;
+import com.velocitypowered.api.plugin.annotation.DataDirectory;
+import com.velocitypowered.api.proxy.ProxyServer;
+import org.slf4j.Logger;
+
+import java.io.File;
+import java.io.InputStream;
+import java.nio.file.Path;
+
+/**
+ * Velocity Main class.
+ *
+ * Based on the PlanBungee class
+ *
+ * @author MicleBrick
+ */
+@Plugin(id = "plan", name = "Plan", version = "4.4.6", description = "Player Analytics Plugin by Rsl1122", authors = {"Rsl1122"})
+public class PlanVelocity extends VelocityPlugin implements PlanPlugin {
+
+ private VelocitySystem system;
+ private Locale locale;
+
+ public static PlanVelocity getInstance() {
+ return (PlanVelocity) StaticHolder.getInstance(PlanVelocity.class);
+ }
+
+ @Inject
+ @DataDirectory
+ private Path dataFolderPath;
+
+ @Override
+ public File getDataFolder() {
+ return dataFolderPath.toFile();
+ }
+
+ @Override
+ public void onEnable() {
+ super.onEnable();
+ try {
+ system = new VelocitySystem(this);
+ locale = system.getLocaleSystem().getLocale();
+ system.enable();
+
+ Log.info(locale.getString(PluginLang.ENABLED));
+ } catch (AbstractMethodError e) {
+ Log.error("Plugin ran into AbstractMethodError - Server restart is required. Likely cause is updating the jar without a restart.");
+ } catch (EnableException e) {
+ Log.error("----------------------------------------");
+ Log.error("Error: " + e.getMessage());
+ Log.error("----------------------------------------");
+ Log.error("Plugin Failed to Initialize Correctly. If this issue is caused by config settings you can use /planvelocity reload");
+ onDisable();
+ } catch (Exception e) {
+ getLogger().error(this.getClass().getSimpleName() + "-v" + getVersion(), e);
+ Log.error("Plugin Failed to Initialize Correctly. If this issue is caused by config settings you can use /planvelocity reload");
+ Log.error("This error should be reported at https://github.com/Rsl1122/Plan-PlayerAnalytics/issues");
+ onDisable();
+ }
+ registerCommand("planvelocity", new PlanVelocityCommand(this));
+ }
+
+ @Override
+ public void onDisable() {
+ system.disable();
+
+ Log.info(locale.getString(PluginLang.DISABLED));
+ Benchmark.pluginDisabled(PlanVelocity.class);
+ DebugLog.pluginDisabled(PlanVelocity.class);
+ }
+
+ @Override
+ public String getVersion() {
+ return getClass().getAnnotation(Plugin.class).version();
+ }
+
+
+ @Override
+ public void onReload() {
+ // Nothing to be done, systems are disabled
+ }
+
+ @Override
+ public InputStream getResource(String resource) {
+ return getClass().getResourceAsStream(resource);
+ }
+
+ @Override
+ public ColorScheme getColorScheme() {
+ return PlanColorScheme.create();
+ }
+
+ @Override
+ public VelocitySystem getSystem() {
+ return system;
+ }
+
+ @Override
+ public boolean isReloading() {
+ return reloading;
+ }
+
+ @Inject
+ private ProxyServer proxy;
+
+ @Override
+ public ProxyServer getProxy() {
+ return proxy;
+ }
+
+ @Inject
+ private Logger logger;
+
+ @Override
+ protected Logger getLogger() {
+ return logger;
+ }
+}
diff --git a/Plan/src/main/java/com/djrapitops/plan/api/BungeeAPI.java b/Plan/src/main/java/com/djrapitops/plan/api/ProxyAPI.java
similarity index 100%
rename from Plan/src/main/java/com/djrapitops/plan/api/BungeeAPI.java
rename to Plan/src/main/java/com/djrapitops/plan/api/ProxyAPI.java
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 301eb2001..a1c2dc7b9 100644
--- a/Plan/src/main/java/com/djrapitops/plan/command/PlanBungeeCommand.java
+++ b/Plan/src/main/java/com/djrapitops/plan/command/PlanBungeeCommand.java
@@ -3,6 +3,7 @@ package com.djrapitops.plan.command;
import com.djrapitops.plan.command.commands.*;
import com.djrapitops.plan.command.commands.manage.ManageConDebugCommand;
import com.djrapitops.plan.command.commands.manage.ManageRawDataCommand;
+import com.djrapitops.plan.command.commands.manage.ManageUninstalledCommand;
import com.djrapitops.plan.system.locale.Locale;
import com.djrapitops.plan.system.locale.lang.DeepHelpLang;
import com.djrapitops.plan.system.settings.Permissions;
@@ -36,6 +37,7 @@ public class PlanBungeeCommand extends TreeCmdNode {
private final BungeeSetupToggleCommand setupToggleCommand;
private final ReloadCommand reloadCommand;
private final DisableCommand disableCommand;
+ private final ManageUninstalledCommand uninstalledCommand;
private boolean commandsRegistered;
@@ -54,10 +56,12 @@ public class PlanBungeeCommand extends TreeCmdNode {
ManageConDebugCommand conDebugCommand,
ManageRawDataCommand rawDataCommand,
BungeeSetupToggleCommand setupToggleCommand,
+ ManageUninstalledCommand uninstalledCommand,
ReloadCommand reloadCommand,
DisableCommand disableCommand
) {
super("planbungee", Permissions.MANAGE.getPermission(), CommandType.CONSOLE, null);
+ this.uninstalledCommand = uninstalledCommand;
commandsRegistered = false;
@@ -94,6 +98,7 @@ public class PlanBungeeCommand extends TreeCmdNode {
conDebugCommand,
rawDataCommand,
setupToggleCommand,
+ uninstalledCommand,
reloadCommand,
disableCommand
};
diff --git a/Plan/src/main/java/com/djrapitops/plan/command/PlanVelocityCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/PlanVelocityCommand.java
new file mode 100644
index 000000000..a1c2dc7b9
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/command/PlanVelocityCommand.java
@@ -0,0 +1,108 @@
+package com.djrapitops.plan.command;
+
+import com.djrapitops.plan.command.commands.*;
+import com.djrapitops.plan.command.commands.manage.ManageConDebugCommand;
+import com.djrapitops.plan.command.commands.manage.ManageRawDataCommand;
+import com.djrapitops.plan.command.commands.manage.ManageUninstalledCommand;
+import com.djrapitops.plan.system.locale.Locale;
+import com.djrapitops.plan.system.locale.lang.DeepHelpLang;
+import com.djrapitops.plan.system.settings.Permissions;
+import com.djrapitops.plugin.command.ColorScheme;
+import com.djrapitops.plugin.command.CommandNode;
+import com.djrapitops.plugin.command.CommandType;
+import com.djrapitops.plugin.command.TreeCmdNode;
+import dagger.Lazy;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * TreeCommand for the /plan command, and all subcommands.
+ *
+ * Uses the Abstract Plugin Framework for easier command management.
+ *
+ * @author Rsl1122
+ * @since 1.0.0
+ */
+@Singleton
+public class PlanBungeeCommand extends TreeCmdNode {
+
+ private final NetworkCommand networkCommand;
+ private final ListServersCommand listServersCommand;
+ private final ListPlayersCommand listPlayersCommand;
+ private final RegisterCommand registerCommand;
+ private final Lazy webUserCommand;
+ private final ManageConDebugCommand conDebugCommand;
+ private final ManageRawDataCommand rawDataCommand;
+ private final BungeeSetupToggleCommand setupToggleCommand;
+ private final ReloadCommand reloadCommand;
+ private final DisableCommand disableCommand;
+ private final ManageUninstalledCommand uninstalledCommand;
+
+ private boolean commandsRegistered;
+
+ @Inject
+ public PlanBungeeCommand(
+ ColorScheme colorScheme,
+ Locale locale,
+ // Group 1
+ NetworkCommand networkCommand,
+ ListServersCommand listServersCommand,
+ ListPlayersCommand listPlayersCommand,
+ // Group 2
+ RegisterCommand registerCommand,
+ Lazy webUserCommand,
+ // Group 3
+ ManageConDebugCommand conDebugCommand,
+ ManageRawDataCommand rawDataCommand,
+ BungeeSetupToggleCommand setupToggleCommand,
+ ManageUninstalledCommand uninstalledCommand,
+ ReloadCommand reloadCommand,
+ DisableCommand disableCommand
+ ) {
+ super("planbungee", Permissions.MANAGE.getPermission(), CommandType.CONSOLE, null);
+ this.uninstalledCommand = uninstalledCommand;
+
+ commandsRegistered = false;
+
+ this.networkCommand = networkCommand;
+ this.listServersCommand = listServersCommand;
+ this.listPlayersCommand = listPlayersCommand;
+ this.registerCommand = registerCommand;
+ this.webUserCommand = webUserCommand;
+ this.conDebugCommand = conDebugCommand;
+ this.rawDataCommand = rawDataCommand;
+ this.setupToggleCommand = setupToggleCommand;
+ this.reloadCommand = reloadCommand;
+ this.disableCommand = disableCommand;
+
+ setColorScheme(colorScheme);
+ setInDepthHelp(locale.getArray(DeepHelpLang.PLAN));
+ }
+
+ public void registerCommands() {
+ if (commandsRegistered) {
+ return;
+ }
+
+ CommandNode[] analyticsGroup = {
+ networkCommand,
+ listServersCommand,
+ listPlayersCommand
+ };
+ CommandNode[] webGroup = {
+ registerCommand,
+ webUserCommand.get()
+ };
+ CommandNode[] manageGroup = {
+ conDebugCommand,
+ rawDataCommand,
+ setupToggleCommand,
+ uninstalledCommand,
+ reloadCommand,
+ disableCommand
+ };
+ setNodeGroups(analyticsGroup, webGroup, manageGroup);
+ commandsRegistered = true;
+ }
+}
diff --git a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageUninstalledCommand.java b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageUninstalledCommand.java
index 09f2a9ee2..8922bf89c 100644
--- a/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageUninstalledCommand.java
+++ b/Plan/src/main/java/com/djrapitops/plan/command/commands/manage/ManageUninstalledCommand.java
@@ -2,7 +2,6 @@ package com.djrapitops.plan.command.commands.manage;
import com.djrapitops.plan.api.exceptions.database.DBOpException;
import com.djrapitops.plan.system.database.databases.Database;
-import com.djrapitops.plan.system.info.connection.ConnectionSystem;
import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.locale.Locale;
@@ -90,7 +89,7 @@ public class ManageUninstalledCommand extends CommandNode {
}
private Optional getServer(String[] args) {
- if (args.length >= 1 && connectionSystem.isServerAvailable()) {
+ if (args.length >= 1) {
Map bukkitServers = database.fetch().getBukkitServers();
String serverIdentifier = getGivenIdentifier(args);
for (Map.Entry entry : bukkitServers.entrySet()) {
diff --git a/Plan/src/main/java/com/djrapitops/plan/data/container/Session.java b/Plan/src/main/java/com/djrapitops/plan/data/container/Session.java
index ed0366c30..1c7f8ef95 100644
--- a/Plan/src/main/java/com/djrapitops/plan/data/container/Session.java
+++ b/Plan/src/main/java/com/djrapitops/plan/data/container/Session.java
@@ -152,11 +152,11 @@ public class Session extends DataContainer implements DateHolder {
}
public void setWorldTimes(WorldTimes worldTimes) {
- putRawData(SessionKeys.WORLD_TIMES, worldTimes);
+ this.worldTimes = worldTimes;
}
public void setPlayerKills(List playerKills) {
- putRawData(SessionKeys.PLAYER_KILLS, playerKills);
+ this.playerKills = playerKills;
}
public boolean isFetchedFromDB() {
@@ -180,14 +180,8 @@ public class Session extends DataContainer implements DateHolder {
getValue(SessionKeys.END).orElse(-1L).equals(session.getValue(SessionKeys.END).orElse(-1L)) &&
mobKills == session.mobKills &&
deaths == session.deaths &&
- Objects.equals(
- getValue(SessionKeys.WORLD_TIMES).orElse(null),
- session.getValue(SessionKeys.WORLD_TIMES).orElse(null)
- ) &&
- Objects.equals(
- getValue(SessionKeys.PLAYER_KILLS).orElse(new ArrayList<>()),
- session.getValue(SessionKeys.PLAYER_KILLS).orElse(new ArrayList<>())
- );
+ Objects.equals(playerKills, session.playerKills) &&
+ Objects.equals(worldTimes, session.worldTimes);
}
@Override
@@ -203,7 +197,7 @@ public class Session extends DataContainer implements DateHolder {
return worldTimes;
}
- private List getPlayerKills() {
+ public List getPlayerKills() {
return playerKills;
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/data/element/InspectContainer.java b/Plan/src/main/java/com/djrapitops/plan/data/element/InspectContainer.java
index 9b2f6fa60..f3a5b7b14 100644
--- a/Plan/src/main/java/com/djrapitops/plan/data/element/InspectContainer.java
+++ b/Plan/src/main/java/com/djrapitops/plan/data/element/InspectContainer.java
@@ -5,6 +5,8 @@
package com.djrapitops.plan.data.element;
import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@@ -25,18 +27,18 @@ import java.util.TreeMap;
*/
public class InspectContainer {
- protected TreeMap values;
+ protected List values;
protected TreeMap html;
protected TreeMap tables;
public InspectContainer() {
- values = new TreeMap<>();
+ values = new ArrayList<>();
html = new TreeMap<>();
tables = new TreeMap<>();
}
public final void addValue(String label, Serializable value) {
- values.put(label, value.toString());
+ values.add(label + ": " + value.toString());
}
public final void addHtml(String key, String html) {
@@ -52,8 +54,8 @@ public class InspectContainer {
if (!values.isEmpty()) {
parsed.append("");
- for (Map.Entry
entry : values.entrySet()) {
- parsed.append("").append(entry.getKey()).append(": ").append(entry.getValue()).append("
");
+ for (String value : values) {
+ parsed.append("").append(value).append("
");
}
parsed.append(" ");
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java b/Plan/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java
index d119bc9da..d12d4f945 100644
--- a/Plan/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java
+++ b/Plan/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java
@@ -90,9 +90,9 @@ public class AnalysisContainer extends DataContainer {
}
private void addAnalysisSuppliers() {
- putSupplier(AnalysisKeys.SESSIONS_MUTATOR, () -> SessionsMutator.forContainer(serverContainer));
- putSupplier(AnalysisKeys.TPS_MUTATOR, () -> TPSMutator.forContainer(serverContainer));
- putSupplier(AnalysisKeys.PLAYERS_MUTATOR, () -> PlayersMutator.forContainer(serverContainer));
+ putCachingSupplier(AnalysisKeys.SESSIONS_MUTATOR, () -> SessionsMutator.forContainer(serverContainer));
+ putCachingSupplier(AnalysisKeys.TPS_MUTATOR, () -> TPSMutator.forContainer(serverContainer));
+ putCachingSupplier(AnalysisKeys.PLAYERS_MUTATOR, () -> PlayersMutator.forContainer(serverContainer));
addConstants();
addPlayerSuppliers();
@@ -123,7 +123,7 @@ public class AnalysisContainer extends DataContainer {
}
private void addServerProperties() {
- putSupplier(AnalysisKeys.SERVER_NAME, () ->
+ putCachingSupplier(AnalysisKeys.SERVER_NAME, () ->
getUnsafe(serverNames).getOrDefault(serverContainer.getUnsafe(ServerKeys.SERVER_UUID), "Plan")
);
@@ -147,7 +147,7 @@ public class AnalysisContainer extends DataContainer {
}
private void addPlayerSuppliers() {
- putSupplier(AnalysisKeys.PLAYER_NAMES, () -> serverContainer.getValue(ServerKeys.PLAYERS).orElse(new ArrayList<>())
+ putCachingSupplier(AnalysisKeys.PLAYER_NAMES, () -> serverContainer.getValue(ServerKeys.PLAYERS).orElse(new ArrayList<>())
.stream().collect(Collectors.toMap(
p -> p.getUnsafe(PlayerKeys.UUID), p -> p.getValue(PlayerKeys.NAME).orElse("?"))
)
@@ -190,22 +190,22 @@ public class AnalysisContainer extends DataContainer {
Key uniqueDay = new Key<>(PlayersMutator.class, "UNIQUE_DAY");
Key uniqueWeek = new Key<>(PlayersMutator.class, "UNIQUE_WEEK");
Key uniqueMonth = new Key<>(PlayersMutator.class, "UNIQUE_MONTH");
- putSupplier(newDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
+ putCachingSupplier(newDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterRegisteredBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_DAY_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
- putSupplier(newWeek, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
+ putCachingSupplier(newWeek, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterRegisteredBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
- putSupplier(newMonth, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
+ putCachingSupplier(newMonth, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterRegisteredBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
- putSupplier(uniqueDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
+ putCachingSupplier(uniqueDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterPlayedBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_DAY_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
- putSupplier(uniqueWeek, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
+ putCachingSupplier(uniqueWeek, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterPlayedBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
- putSupplier(uniqueMonth, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
+ putCachingSupplier(uniqueMonth, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
.filterPlayedBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
@@ -231,7 +231,7 @@ public class AnalysisContainer extends DataContainer {
Key retentionDay = new Key<>(Integer.class, "RETENTION_DAY");
// compareAndFindThoseLikelyToBeRetained can throw exception.
- putSupplier(retentionDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).compareAndFindThoseLikelyToBeRetained(
+ putCachingSupplier(retentionDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).compareAndFindThoseLikelyToBeRetained(
getUnsafe(newDay).all(), getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO),
getUnsafe(AnalysisKeys.PLAYERS_ONLINE_RESOLVER),
config.getNumber(Settings.ACTIVE_PLAY_THRESHOLD),
@@ -245,13 +245,13 @@ public class AnalysisContainer extends DataContainer {
return 0;
}
});
- putSupplier(AnalysisKeys.PLAYERS_RETAINED_WEEK, () ->
+ putCachingSupplier(AnalysisKeys.PLAYERS_RETAINED_WEEK, () ->
getUnsafe(newWeek).filterRetained(
getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO),
getUnsafe(AnalysisKeys.ANALYSIS_TIME)
).count()
);
- putSupplier(AnalysisKeys.PLAYERS_RETAINED_MONTH, () ->
+ putCachingSupplier(AnalysisKeys.PLAYERS_RETAINED_MONTH, () ->
getUnsafe(newMonth).filterRetained(
getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO),
getUnsafe(AnalysisKeys.ANALYSIS_TIME)
@@ -283,8 +283,8 @@ public class AnalysisContainer extends DataContainer {
private void addSessionSuppliers() {
Key sessionAccordion = new Key<>(SessionAccordion.class, "SESSION_ACCORDION");
- putSupplier(serverNames, () -> database.fetch().getServerNames());
- putSupplier(sessionAccordion, () -> accordions.serverSessionAccordion(
+ putCachingSupplier(serverNames, () -> database.fetch().getServerNames());
+ putCachingSupplier(sessionAccordion, () -> accordions.serverSessionAccordion(
getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).all(),
getSupplier(serverNames),
() -> getUnsafe(AnalysisKeys.PLAYER_NAMES)
@@ -325,13 +325,13 @@ public class AnalysisContainer extends DataContainer {
Key sessionsDay = new Key<>(SessionsMutator.class, "SESSIONS_DAY");
Key sessionsWeek = new Key<>(SessionsMutator.class, "SESSIONS_WEEK");
Key sessionsMonth = new Key<>(SessionsMutator.class, "SESSIONS_MONTH");
- putSupplier(sessionsDay, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
+ putCachingSupplier(sessionsDay, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
.filterSessionsBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_DAY_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
- putSupplier(sessionsWeek, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
+ putCachingSupplier(sessionsWeek, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
.filterSessionsBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
- putSupplier(sessionsMonth, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
+ putCachingSupplier(sessionsMonth, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
.filterSessionsBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
@@ -344,7 +344,7 @@ public class AnalysisContainer extends DataContainer {
private void addGraphSuppliers() {
Key worldPie = new Key<>(WorldPie.class, "WORLD_PIE");
- putSupplier(worldPie, () -> graphs.pie().worldPie(
+ putCachingSupplier(worldPie, () -> graphs.pie().worldPie(
serverContainer.getValue(ServerKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>()))
));
putSupplier(AnalysisKeys.WORLD_PIE_SERIES, () -> getUnsafe(worldPie).toHighChartsSeries());
@@ -361,12 +361,12 @@ public class AnalysisContainer extends DataContainer {
graphs.special().worldMap(getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)).toHighChartsSeries()
);
Key geolocationBarChart = new Key<>(BarGraph.class, "GEOLOCATION_BAR_GRAPH");
- putSupplier(geolocationBarChart, () -> graphs.bar().geolocationBarGraph(getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)));
+ putCachingSupplier(geolocationBarChart, () -> graphs.bar().geolocationBarGraph(getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)));
putSupplier(AnalysisKeys.COUNTRY_CATEGORIES, () -> getUnsafe(geolocationBarChart).toHighChartsCategories());
putSupplier(AnalysisKeys.COUNTRY_SERIES, () -> getUnsafe(geolocationBarChart).toHighChartsSeries());
Key pingGraph = new Key<>(PingGraph.class, "PING_GRAPH");
- putSupplier(pingGraph, () ->
+ putCachingSupplier(pingGraph, () ->
graphs.line().pingGraph(PingMutator.forContainer(serverContainer).mutateToByMinutePings().all())
);
putSupplier(AnalysisKeys.AVG_PING_SERIES, () -> getUnsafe(pingGraph).toAvgSeries());
@@ -379,9 +379,9 @@ public class AnalysisContainer extends DataContainer {
getUnsafe(AnalysisKeys.NEW_PLAYERS_PER_DAY)
).toCalendarSeries());
- putSupplier(AnalysisKeys.ACTIVITY_DATA, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).toActivityDataMap(getUnsafe(AnalysisKeys.ANALYSIS_TIME), config.getNumber(Settings.ACTIVE_PLAY_THRESHOLD), config.getNumber(Settings.ACTIVE_LOGIN_THRESHOLD)));
+ putCachingSupplier(AnalysisKeys.ACTIVITY_DATA, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).toActivityDataMap(getUnsafe(AnalysisKeys.ANALYSIS_TIME), config.getNumber(Settings.ACTIVE_PLAY_THRESHOLD), config.getNumber(Settings.ACTIVE_LOGIN_THRESHOLD)));
Key activityStackGraph = new Key<>(StackGraph.class, "ACTIVITY_STACK_GRAPH");
- putSupplier(activityStackGraph, () -> graphs.stack().activityStackGraph(getUnsafe(AnalysisKeys.ACTIVITY_DATA)));
+ putCachingSupplier(activityStackGraph, () -> graphs.stack().activityStackGraph(getUnsafe(AnalysisKeys.ACTIVITY_DATA)));
putSupplier(AnalysisKeys.ACTIVITY_STACK_CATEGORIES, () -> getUnsafe(activityStackGraph).toHighChartsLabels());
putSupplier(AnalysisKeys.ACTIVITY_STACK_SERIES, () -> getUnsafe(activityStackGraph).toHighChartsSeries());
putSupplier(AnalysisKeys.ACTIVITY_PIE_SERIES, () -> graphs.pie().activityPie(
@@ -402,17 +402,17 @@ public class AnalysisContainer extends DataContainer {
Key tpsWeek = new Key<>(TPSMutator.class, "TPS_WEEK");
Key tpsDay = new Key<>(TPSMutator.class, "TPS_DAY");
- putSupplier(tpsMonth, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
+ putCachingSupplier(tpsMonth, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
.filterDataBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
- putSupplier(tpsWeek, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
+ putCachingSupplier(tpsWeek, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
.filterDataBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
- putSupplier(tpsDay, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
+ putCachingSupplier(tpsDay, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
.filterDataBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_DAY_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
);
- putSupplier(AnalysisKeys.PLAYERS_ONLINE_RESOLVER, () -> new PlayersOnlineResolver(getUnsafe(AnalysisKeys.TPS_MUTATOR)));
+ putCachingSupplier(AnalysisKeys.PLAYERS_ONLINE_RESOLVER, () -> new PlayersOnlineResolver(getUnsafe(AnalysisKeys.TPS_MUTATOR)));
int threshold = config.getNumber(Settings.THEME_GRAPH_TPS_THRESHOLD_MED);
@@ -444,7 +444,7 @@ public class AnalysisContainer extends DataContainer {
private void addServerHealth() {
Key healthInformation = new Key<>(HealthInformation.class, "HEALTH_INFORMATION");
- putSupplier(healthInformation, () -> new HealthInformation(
+ putCachingSupplier(healthInformation, () -> new HealthInformation(
this,
config.getNumber(Settings.THEME_GRAPH_TPS_THRESHOLD_MED),
config.getNumber(Settings.ACTIVE_PLAY_THRESHOLD),
@@ -458,7 +458,7 @@ public class AnalysisContainer extends DataContainer {
private void addPluginSuppliers() {
// TODO Refactor into a system that supports running the analysis on Bungee
Key navAndTabs = new Key<>(new Type() {}, "NAV_AND_TABS");
- putSupplier(navAndTabs, () -> pluginsTabContentCreator.createContent(this));
+ putCachingSupplier(navAndTabs, () -> pluginsTabContentCreator.createContent(this));
putSupplier(AnalysisKeys.PLUGINS_TAB_NAV, () -> getUnsafe(navAndTabs)[0]);
putSupplier(AnalysisKeys.PLUGINS_TAB, () -> getUnsafe(navAndTabs)[1]);
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/containers/DataContainer.java b/Plan/src/main/java/com/djrapitops/plan/data/store/containers/DataContainer.java
index 16f7aeda7..e6c26f85c 100644
--- a/Plan/src/main/java/com/djrapitops/plan/data/store/containers/DataContainer.java
+++ b/Plan/src/main/java/com/djrapitops/plan/data/store/containers/DataContainer.java
@@ -44,6 +44,13 @@ public class DataContainer {
}
public void putSupplier(Key key, Supplier supplier) {
+ if (supplier == null) {
+ return;
+ }
+ map.put(key, supplier);
+ }
+
+ public void putCachingSupplier(Key key, Supplier supplier) {
if (supplier == null) {
return;
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/containers/NetworkContainer.java b/Plan/src/main/java/com/djrapitops/plan/data/store/containers/NetworkContainer.java
index 7618b2709..b3a0ea600 100644
--- a/Plan/src/main/java/com/djrapitops/plan/data/store/containers/NetworkContainer.java
+++ b/Plan/src/main/java/com/djrapitops/plan/data/store/containers/NetworkContainer.java
@@ -69,7 +69,7 @@ public class NetworkContainer extends DataContainer {
this.formatters = formatters;
this.graphs = graphs;
- putSupplier(NetworkKeys.PLAYERS_MUTATOR, () -> PlayersMutator.forContainer(bungeeContainer));
+ putCachingSupplier(NetworkKeys.PLAYERS_MUTATOR, () -> PlayersMutator.forContainer(bungeeContainer));
addConstants();
addServerBoxes();
@@ -99,14 +99,14 @@ public class NetworkContainer extends DataContainer {
private void addNetworkHealth() {
Key healthInformation = new Key<>(NetworkHealthInformation.class, "HEALTH_INFORMATION");
- putSupplier(healthInformation, () -> new NetworkHealthInformation(
+ putCachingSupplier(healthInformation, () -> new NetworkHealthInformation(
this,
config.getNumber(Settings.ACTIVE_PLAY_THRESHOLD),
config.getNumber(Settings.ACTIVE_LOGIN_THRESHOLD),
formatters.timeAmount(), formatters.decimals(), formatters.percentage()
));
- putSupplier(NetworkKeys.HEALTH_INDEX, () -> getUnsafe(healthInformation).getServerHealth());
- putSupplier(NetworkKeys.HEALTH_NOTES, () -> getUnsafe(healthInformation).toHtml());
+ putCachingSupplier(NetworkKeys.HEALTH_INDEX, () -> getUnsafe(healthInformation).getServerHealth());
+ putCachingSupplier(NetworkKeys.HEALTH_NOTES, () -> getUnsafe(healthInformation).toHtml());
}
private void addConstants() {
@@ -120,7 +120,7 @@ public class NetworkContainer extends DataContainer {
putRawData(NetworkKeys.VERSION, version);
putSupplier(NetworkKeys.TIME_ZONE, config::getTimeZoneOffsetHours);
- putSupplier(NetworkKeys.NETWORK_NAME, () ->
+ putCachingSupplier(NetworkKeys.NETWORK_NAME, () ->
Check.isBungeeAvailable() ?
config.getString(Settings.BUNGEE_NETWORK_NAME) :
bungeeContainer.getValue(ServerKeys.NAME).orElse("Plan")
@@ -176,22 +176,22 @@ public class NetworkContainer extends DataContainer {
Key uniqueDay = new Key<>(PlayersMutator.class, "UNIQUE_DAY");
Key uniqueWeek = new Key<>(PlayersMutator.class, "UNIQUE_WEEK");
Key uniqueMonth = new Key<>(PlayersMutator.class, "UNIQUE_MONTH");
- putSupplier(newDay, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
+ putCachingSupplier(newDay, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
.filterRegisteredBetween(getUnsafe(NetworkKeys.REFRESH_TIME_DAY_AGO), getUnsafe(NetworkKeys.REFRESH_TIME))
);
- putSupplier(newWeek, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
+ putCachingSupplier(newWeek, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
.filterRegisteredBetween(getUnsafe(NetworkKeys.REFRESH_TIME_WEEK_AGO), getUnsafe(NetworkKeys.REFRESH_TIME))
);
- putSupplier(newMonth, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
+ putCachingSupplier(newMonth, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
.filterRegisteredBetween(getUnsafe(NetworkKeys.REFRESH_TIME_MONTH_AGO), getUnsafe(NetworkKeys.REFRESH_TIME))
);
- putSupplier(uniqueDay, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
+ putCachingSupplier(uniqueDay, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
.filterPlayedBetween(getUnsafe(NetworkKeys.REFRESH_TIME_DAY_AGO), getUnsafe(NetworkKeys.REFRESH_TIME))
);
- putSupplier(uniqueWeek, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
+ putCachingSupplier(uniqueWeek, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
.filterPlayedBetween(getUnsafe(NetworkKeys.REFRESH_TIME_WEEK_AGO), getUnsafe(NetworkKeys.REFRESH_TIME))
);
- putSupplier(uniqueMonth, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
+ putCachingSupplier(uniqueMonth, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
.filterPlayedBetween(getUnsafe(NetworkKeys.REFRESH_TIME_MONTH_AGO), getUnsafe(NetworkKeys.REFRESH_TIME))
);
@@ -203,6 +203,10 @@ public class NetworkContainer extends DataContainer {
putSupplier(NetworkKeys.PLAYERS_MONTH, () -> getUnsafe(uniqueMonth).count());
}
+ public ServerContainer getBungeeContainer() {
+ return bungeeContainer;
+ }
+
@Singleton
public static class Factory {
diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/SessionsMutator.java b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/SessionsMutator.java
index 10be83942..203d1c91a 100644
--- a/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/SessionsMutator.java
+++ b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/SessionsMutator.java
@@ -7,6 +7,7 @@ import com.djrapitops.plan.data.store.containers.DataContainer;
import com.djrapitops.plan.data.store.keys.CommonKeys;
import com.djrapitops.plan.data.store.keys.SessionKeys;
import com.djrapitops.plan.data.time.WorldTimes;
+import com.djrapitops.plan.utilities.analysis.Median;
import java.util.*;
import java.util.function.Predicate;
@@ -142,13 +143,8 @@ public class SessionsMutator {
}
public long toMedianSessionLength() {
- List sessionLengths = sessions.stream().map(Session::getLength)
- .sorted()
- .collect(Collectors.toList());
- if (sessionLengths.isEmpty()) {
- return 0;
- }
- return sessionLengths.get(sessionLengths.size() / 2);
+ List sessionLengths = sessions.stream().map(Session::getLength).collect(Collectors.toList());
+ return (long) Median.forLong(sessionLengths).calculate();
}
public int toAverageUniqueJoinsPerDay() {
@@ -200,5 +196,4 @@ public class SessionsMutator {
return toPlayerDeathList().size();
}
-
}
\ No newline at end of file
diff --git a/Plan/src/main/java/com/djrapitops/plan/modules/proxy/ProxySuperClassBindingModule.java b/Plan/src/main/java/com/djrapitops/plan/modules/proxy/ProxySuperClassBindingModule.java
new file mode 100644
index 000000000..057dd749f
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/modules/proxy/ProxySuperClassBindingModule.java
@@ -0,0 +1,9 @@
+package com.djrapitops.plan.modules.bungee.proxy;
+
+/**
+ * //TODO Class Javadoc Comment
+ *
+ * @author Rsl1122
+ */
+public class ProxySuperClassBindingModule {
+}
\ No newline at end of file
diff --git a/Plan/src/main/java/com/djrapitops/plan/modules/bungee/BungeeInfoModule.java b/Plan/src/main/java/com/djrapitops/plan/modules/proxy/bungee/BungeeServerPropertiesModule.java
similarity index 100%
rename from Plan/src/main/java/com/djrapitops/plan/modules/bungee/BungeeInfoModule.java
rename to Plan/src/main/java/com/djrapitops/plan/modules/proxy/bungee/BungeeServerPropertiesModule.java
diff --git a/Plan/src/main/java/com/djrapitops/plan/modules/bungee/BungeeSuperClassBindingModule.java b/Plan/src/main/java/com/djrapitops/plan/modules/proxy/bungee/BungeeSuperClassBindingModule.java
similarity index 100%
rename from Plan/src/main/java/com/djrapitops/plan/modules/bungee/BungeeSuperClassBindingModule.java
rename to Plan/src/main/java/com/djrapitops/plan/modules/proxy/bungee/BungeeSuperClassBindingModule.java
diff --git a/Plan/src/main/java/com/djrapitops/plan/modules/proxy/velocity/VelocityServerPropertiesModule.java b/Plan/src/main/java/com/djrapitops/plan/modules/proxy/velocity/VelocityServerPropertiesModule.java
new file mode 100644
index 000000000..342d99862
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/modules/proxy/velocity/VelocityServerPropertiesModule.java
@@ -0,0 +1,9 @@
+package com.djrapitops.plan.modules.proxy.velocity;
+
+/**
+ * //TODO Class Javadoc Comment
+ *
+ * @author Rsl1122
+ */
+public class VelocityServerProperties {
+}
\ No newline at end of file
diff --git a/Plan/src/main/java/com/djrapitops/plan/modules/proxy/velocity/VelocitySuperClassBindingModule.java b/Plan/src/main/java/com/djrapitops/plan/modules/proxy/velocity/VelocitySuperClassBindingModule.java
new file mode 100644
index 000000000..b952e4829
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/modules/proxy/velocity/VelocitySuperClassBindingModule.java
@@ -0,0 +1,47 @@
+package com.djrapitops.plan.modules.proxy.bungee;
+
+import com.djrapitops.plan.system.info.server.BungeeServerInfo;
+import com.djrapitops.plan.system.info.server.ServerInfo;
+import com.djrapitops.plan.system.listeners.BungeeListenerSystem;
+import com.djrapitops.plan.system.listeners.ListenerSystem;
+import com.djrapitops.plan.system.settings.config.BungeeConfigSystem;
+import com.djrapitops.plan.system.settings.config.ConfigSystem;
+import com.djrapitops.plan.system.tasks.BungeeTaskSystem;
+import com.djrapitops.plan.system.tasks.TaskSystem;
+import dagger.Module;
+import dagger.Provides;
+
+import javax.inject.Singleton;
+
+/**
+ * Module for binding Bungee specific classes to the interface implementations.
+ *
+ * @author Rsl1122
+ */
+@Module
+public class BungeeSuperClassBindingModule {
+
+ @Provides
+ @Singleton
+ ServerInfo provideBungeeServerInfo(BungeeServerInfo bungeeServerInfo) {
+ return bungeeServerInfo;
+ }
+
+ @Provides
+ @Singleton
+ ConfigSystem provideBungeeConfigSystem(BungeeConfigSystem bungeeConfigSystem) {
+ return bungeeConfigSystem;
+ }
+
+ @Provides
+ @Singleton
+ TaskSystem provideBungeeTaskSystem(BungeeTaskSystem bungeeTaskSystem) {
+ return bungeeTaskSystem;
+ }
+
+ @Provides
+ @Singleton
+ ListenerSystem provideBungeeListenerSystem(BungeeListenerSystem bungeeListenerSystem) {
+ return bungeeListenerSystem;
+ }
+}
\ No newline at end of file
diff --git a/Plan/src/main/java/com/djrapitops/plan/modules/server/bukkit/BukkitInfoModule.java b/Plan/src/main/java/com/djrapitops/plan/modules/server/bukkit/BukkitServerPropertiesModule.java
similarity index 100%
rename from Plan/src/main/java/com/djrapitops/plan/modules/server/bukkit/BukkitInfoModule.java
rename to Plan/src/main/java/com/djrapitops/plan/modules/server/bukkit/BukkitServerPropertiesModule.java
diff --git a/Plan/src/main/java/com/djrapitops/plan/modules/server/sponge/SpongeInfoModule.java b/Plan/src/main/java/com/djrapitops/plan/modules/server/sponge/SpongeServerPropertiesModule.java
similarity index 100%
rename from Plan/src/main/java/com/djrapitops/plan/modules/server/sponge/SpongeInfoModule.java
rename to Plan/src/main/java/com/djrapitops/plan/modules/server/sponge/SpongeServerPropertiesModule.java
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/BungeeSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/BungeeSystem.java
new file mode 100644
index 000000000..e69de29bb
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/afk/AFKTracker.java b/Plan/src/main/java/com/djrapitops/plan/system/afk/AFKTracker.java
index 371788b14..985cdb530 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/afk/AFKTracker.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/afk/AFKTracker.java
@@ -66,4 +66,14 @@ public class AFKTracker {
lastMovement.remove(uuid);
usedAFKCommand.remove(uuid);
}
+
+ public boolean isAfk(UUID uuid) {
+ long time = System.currentTimeMillis();
+
+ Long lastMoved = lastMovement.get(uuid);
+ if (lastMoved == null || lastMoved == -1) {
+ return false;
+ }
+ return time - lastMoved > afkThresholdMs;
+ }
}
\ No newline at end of file
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/cache/BungeeCacheSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/cache/BungeeCacheSystem.java
deleted file mode 100644
index 49d1503a6..000000000
--- a/Plan/src/main/java/com/djrapitops/plan/system/cache/BungeeCacheSystem.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.djrapitops.plan.system.cache;
-
-import javax.inject.Inject;
-
-/**
- * CacheSystem for Bungee.
- *
- * Used for overriding {@link DataCache} with {@link BungeeDataCache}
- *
- * @author Rsl1122
- */
-public class BungeeCacheSystem extends CacheSystem {
-
- @Inject
- public BungeeCacheSystem(BungeeDataCache dataCache, GeolocationCache geolocationCache) {
- super(dataCache, geolocationCache);
- }
-
-}
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 d4f7481bd..dc7191506 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
@@ -19,6 +19,7 @@ import javax.inject.Singleton;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
@@ -158,8 +159,12 @@ public class GeolocationCache implements SubSystem {
return;
}
URL downloadSite = new URL("http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz");
- try (ReadableByteChannel rbc = Channels.newChannel(new GZIPInputStream(downloadSite.openStream()));
- FileOutputStream fos = new FileOutputStream(geolocationDB.getAbsoluteFile())) {
+ try (
+ InputStream in = downloadSite.openStream();
+ GZIPInputStream gzipIn = new GZIPInputStream(in);
+ ReadableByteChannel rbc = Channels.newChannel(gzipIn);
+ FileOutputStream fos = new FileOutputStream(geolocationDB.getAbsoluteFile())
+ ) {
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
}
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/cache/BungeeDataCache.java b/Plan/src/main/java/com/djrapitops/plan/system/cache/ProxyDataCache.java
similarity index 69%
rename from Plan/src/main/java/com/djrapitops/plan/system/cache/BungeeDataCache.java
rename to Plan/src/main/java/com/djrapitops/plan/system/cache/ProxyDataCache.java
index d4ffe1e1b..4c1a844a8 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/cache/BungeeDataCache.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/cache/ProxyDataCache.java
@@ -8,23 +8,23 @@ import javax.inject.Singleton;
import java.util.UUID;
/**
- * Bungee specific DataCache.
+ * Proxy server specific DataCache.
*
* Used for overriding {@link SessionCache#endSession(UUID, long)}.
*
* @author Rsl1122
*/
@Singleton
-public class BungeeDataCache extends DataCache {
+public class ProxyDataCache extends DataCache {
@Inject
- public BungeeDataCache(Database database, ErrorHandler errorHandler) {
+ public ProxyDataCache(Database database, ErrorHandler errorHandler) {
super(database, errorHandler);
}
@Override
public void endSession(UUID uuid, long time) {
removeSessionFromCache(uuid);
- /* Bungee should not save sessions so session is not removed.. */
+ /* Proxy should not save sessions so session is not removed.. */
}
}
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 bc0ab6118..f8f5013f3 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
@@ -83,7 +83,7 @@ public abstract class DBSystem implements SubSystem {
public void enable() throws EnableException {
try {
db.init();
- db.scheduleClean(1L);
+ db.scheduleClean(20L);
logger.info(locale.getString(PluginLang.ENABLED_DATABASE, db.getName()));
} catch (DBInitException e) {
Throwable cause = e.getCause();
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/BungeeDBSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/database/ProxyDBSystem.java
similarity index 89%
rename from Plan/src/main/java/com/djrapitops/plan/system/database/BungeeDBSystem.java
rename to Plan/src/main/java/com/djrapitops/plan/system/database/ProxyDBSystem.java
index e53c807e6..f85a11a3c 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/database/BungeeDBSystem.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/ProxyDBSystem.java
@@ -19,10 +19,10 @@ import javax.inject.Singleton;
* @author Rsl1122
*/
@Singleton
-public class BungeeDBSystem extends DBSystem {
+public class ProxyDBSystem extends DBSystem {
@Inject
- public BungeeDBSystem(Locale locale, MySQLDB mySQLDB,
+ public ProxyDBSystem(Locale locale, MySQLDB mySQLDB,
PluginLogger logger, Timings timings, ErrorHandler errorHandler) {
super(locale, logger, timings, errorHandler);
databases.add(mySQLDB);
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/PatchTask.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/PatchTask.java
new file mode 100644
index 000000000..3a5f79711
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/PatchTask.java
@@ -0,0 +1,56 @@
+package com.djrapitops.plan.system.database.databases.sql;
+
+import com.djrapitops.plan.PlanPlugin;
+import com.djrapitops.plan.system.database.databases.sql.patches.Patch;
+import com.djrapitops.plan.system.locale.Locale;
+import com.djrapitops.plan.system.locale.lang.PluginLang;
+import com.djrapitops.plugin.api.utility.log.Log;
+import com.djrapitops.plugin.task.AbsRunnable;
+
+import java.util.function.Supplier;
+
+/**
+ * Task that is in charge on patching the database when the database enables.
+ *
+ * @author Rsl1122
+ */
+public class PatchTask extends AbsRunnable {
+
+ private final Patch[] patches;
+ private final Supplier locale;
+
+ public PatchTask(Patch[] patches, Supplier locale) {
+ this.patches = patches;
+ this.locale = locale;
+ }
+
+ @Override
+ public void run() {
+ try {
+ boolean didApply = applyPatches();
+ Log.info(locale.get().getString(
+ didApply ? PluginLang.DB_APPLIED_PATCHES : PluginLang.DB_APPLIED_PATCHES_ALREADY
+ ));
+ } catch (Exception e) {
+ Log.error("----------------------------------------------------");
+ Log.error(locale.get().getString(PluginLang.ENABLE_FAIL_DB_PATCH));
+ Log.error("----------------------------------------------------");
+ Log.toLog(this.getClass(), e);
+ PlanPlugin.getInstance().onDisable();
+ }
+ }
+
+ private boolean applyPatches() {
+ boolean didApply = false;
+ for (Patch patch : patches) {
+ if (!patch.hasBeenApplied()) {
+ String patchName = patch.getClass().getSimpleName();
+ Log.info(locale.get().getString(PluginLang.DB_APPLY_PATCH, patchName));
+ patch.apply();
+ didApply = true;
+ }
+ }
+ return didApply;
+ }
+
+}
\ No newline at end of file
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 2ac8bf84c..691fcb51f 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
@@ -183,30 +183,12 @@ public abstract class SQLDB extends Database {
new VersionTableRemovalPatch(this)
};
- runnableFactory.create("Database Patch", new AbsRunnable() {
- @Override
- public void run() {
- try {
- boolean applied = false;
- for (Patch patch : patches) {
- if (!patch.hasBeenApplied()) {
- String patchName = patch.getClass().getSimpleName();
- logger.info(locale.getString(PluginLang.DB_APPLY_PATCH, patchName));
- patch.apply();
- applied = true;
- }
- }
- logger.info(locale.getString(
- applied ? PluginLang.DB_APPLIED_PATCHES : PluginLang.DB_APPLIED_PATCHES_ALREADY
- ));
- } catch (Exception e) {
- logger.error("----------------------------------------------------");
- logger.error(locale.getString(PluginLang.ENABLE_FAIL_DB_PATCH));
- logger.error("----------------------------------------------------");
- errorHandler.log(L.CRITICAL, this.getClass(), e);
- }
- }
- }).runTaskLaterAsynchronously(TimeAmount.toTicks(5L, TimeUnit.SECONDS));
+ try {
+ runnableFactory.createNew("Database Patch", new PatchTask(patches, locale))
+ .runTaskLaterAsynchronously(TimeAmount.SECOND.ticks() * 5L);
+ } catch (Exception ignore) {
+ // Task failed to register because plugin is being disabled
+ }
} catch (DBOpException e) {
throw new DBInitException("Failed to set-up Database", e);
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/operation/SQLFetchOps.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/operation/SQLFetchOps.java
index 6d0602e85..a95f6532c 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/operation/SQLFetchOps.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/operation/SQLFetchOps.java
@@ -9,9 +9,11 @@ import com.djrapitops.plan.data.store.mutators.PlayersMutator;
import com.djrapitops.plan.data.store.mutators.SessionsMutator;
import com.djrapitops.plan.data.store.objects.DateObj;
import com.djrapitops.plan.data.time.WorldTimes;
+import com.djrapitops.plan.system.cache.SessionCache;
import com.djrapitops.plan.system.database.databases.operation.FetchOperations;
import com.djrapitops.plan.system.database.databases.sql.SQLDB;
import com.djrapitops.plan.system.info.server.Server;
+import com.djrapitops.plan.system.info.server.ServerInfo;
import java.util.*;
import java.util.concurrent.TimeUnit;
@@ -25,7 +27,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
@Override
public NetworkContainer getNetworkContainer() {
NetworkContainer networkContainer = db.getNetworkContainerFactory().forBungeeContainer(getBungeeServerContainer());
- networkContainer.putSupplier(NetworkKeys.BUKKIT_SERVERS, () -> getBukkitServers().values());
+ networkContainer.putCachingSupplier(NetworkKeys.BUKKIT_SERVERS, () -> getBukkitServers().values());
return networkContainer;
}
@@ -36,8 +38,8 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
}
ServerContainer container = getServerContainer(bungeeInfo.get().getUuid());
- container.putSupplier(ServerKeys.PLAYERS, this::getAllPlayerContainers);
- container.putSupplier(ServerKeys.TPS, tpsTable::getNetworkOnlineData);
+ container.putCachingSupplier(ServerKeys.PLAYERS, this::getAllPlayerContainers);
+ container.putCachingSupplier(ServerKeys.TPS, tpsTable::getNetworkOnlineData);
container.putSupplier(ServerKeys.WORLD_TIMES, null); // Additional Session information not supported
container.putSupplier(ServerKeys.PLAYER_KILLS, null);
container.putSupplier(ServerKeys.PLAYER_KILL_COUNT, null);
@@ -56,12 +58,12 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
container.putRawData(ServerKeys.SERVER_UUID, serverUUID);
container.putRawData(ServerKeys.NAME, serverInfo.get().getName());
- container.putSupplier(ServerKeys.PLAYERS, () -> getPlayerContainers(serverUUID));
+ container.putCachingSupplier(ServerKeys.PLAYERS, () -> getPlayerContainers(serverUUID));
container.putSupplier(ServerKeys.PLAYER_COUNT, () -> container.getUnsafe(ServerKeys.PLAYERS).size());
- container.putSupplier(ServerKeys.TPS, () -> tpsTable.getTPSData(serverUUID));
- container.putSupplier(ServerKeys.PING, () -> PlayersMutator.forContainer(container).pings());
- container.putSupplier(ServerKeys.ALL_TIME_PEAK_PLAYERS, () -> {
+ container.putCachingSupplier(ServerKeys.TPS, () -> tpsTable.getTPSData(serverUUID));
+ container.putCachingSupplier(ServerKeys.PING, () -> PlayersMutator.forContainer(container).pings());
+ container.putCachingSupplier(ServerKeys.ALL_TIME_PEAK_PLAYERS, () -> {
Optional allTimePeak = tpsTable.getAllTimePeak(serverUUID);
if (allTimePeak.isPresent()) {
TPS peak = allTimePeak.get();
@@ -69,7 +71,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
}
return null;
});
- container.putSupplier(ServerKeys.RECENT_PEAK_PLAYERS, () -> {
+ container.putCachingSupplier(ServerKeys.RECENT_PEAK_PLAYERS, () -> {
long twoDaysAgo = System.currentTimeMillis() - (TimeUnit.DAYS.toMillis(2L));
Optional lastPeak = tpsTable.getPeakPlayerCount(serverUUID, twoDaysAgo);
if (lastPeak.isPresent()) {
@@ -79,16 +81,22 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
return null;
});
- container.putSupplier(ServerKeys.COMMAND_USAGE, () -> commandUseTable.getCommandUse(serverUUID));
- container.putSupplier(ServerKeys.WORLD_TIMES, () -> worldTimesTable.getWorldTimesOfServer(serverUUID));
+ container.putCachingSupplier(ServerKeys.COMMAND_USAGE, () -> commandUseTable.getCommandUse(serverUUID));
+ container.putCachingSupplier(ServerKeys.WORLD_TIMES, () -> worldTimesTable.getWorldTimesOfServer(serverUUID));
// Calculating getters
- container.putSupplier(ServerKeys.OPERATORS, () -> PlayersMutator.forContainer(container).operators());
- container.putSupplier(ServerKeys.SESSIONS, () -> PlayersMutator.forContainer(container).getSessions());
- container.putSupplier(ServerKeys.PLAYER_KILLS, () -> SessionsMutator.forContainer(container).toPlayerKillList());
- container.putSupplier(ServerKeys.PLAYER_KILL_COUNT, () -> container.getUnsafe(ServerKeys.PLAYER_KILLS).size());
- container.putSupplier(ServerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount());
- container.putSupplier(ServerKeys.DEATH_COUNT, () -> SessionsMutator.forContainer(container).toDeathCount());
+ container.putCachingSupplier(ServerKeys.OPERATORS, () -> PlayersMutator.forContainer(container).operators());
+ container.putCachingSupplier(ServerKeys.SESSIONS, () -> {
+ List sessions = PlayersMutator.forContainer(container).getSessions();
+ if (serverUUID.equals(serverInfo.get().getUuid())) {
+ sessions.addAll(SessionCache.getActiveSessions().values());
+ }
+ return sessions;
+ });
+ container.putCachingSupplier(ServerKeys.PLAYER_KILLS, () -> SessionsMutator.forContainer(container).toPlayerKillList());
+ container.putCachingSupplier(ServerKeys.PLAYER_KILL_COUNT, () -> container.getUnsafe(ServerKeys.PLAYER_KILLS).size());
+ container.putCachingSupplier(ServerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount());
+ container.putCachingSupplier(ServerKeys.DEATH_COUNT, () -> SessionsMutator.forContainer(container).toDeathCount());
return container;
}
@@ -121,13 +129,13 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
container.putRawData(PlayerKeys.KICK_COUNT, timesKicked.get(uuid));
container.putRawData(PlayerKeys.GEO_INFO, geoInfo.get(uuid));
container.putRawData(PlayerKeys.PING, allPings.get(uuid));
- container.putSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
+ container.putCachingSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
container.putRawData(PlayerKeys.PER_SERVER, perServerInfo.get(uuid));
container.putRawData(PlayerKeys.BANNED, userInfo.isBanned());
container.putRawData(PlayerKeys.OPERATOR, userInfo.isOperator());
- container.putSupplier(PlayerKeys.SESSIONS, () -> {
+ container.putCachingSupplier(PlayerKeys.SESSIONS, () -> {
List playerSessions = sessions.getOrDefault(uuid, new ArrayList<>());
container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(playerSessions::add);
return playerSessions;
@@ -135,7 +143,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
);
// Calculating getters
- container.putSupplier(PlayerKeys.WORLD_TIMES, () -> {
+ container.putCachingSupplier(PlayerKeys.WORLD_TIMES, () -> {
WorldTimes worldTimes = new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).flatMapWorldTimes();
container.getValue(PlayerKeys.ACTIVE_SESSION)
.ifPresent(session -> worldTimes.add(
@@ -179,10 +187,10 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
container.putRawData(PlayerKeys.KICK_COUNT, timesKicked.get(uuid));
container.putRawData(PlayerKeys.GEO_INFO, geoInfo.get(uuid));
container.putRawData(PlayerKeys.PING, allPings.get(uuid));
- container.putSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
+ container.putCachingSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
container.putRawData(PlayerKeys.PER_SERVER, perServerInfo.get(uuid));
- container.putSupplier(PlayerKeys.SESSIONS, () -> {
+ container.putCachingSupplier(PlayerKeys.SESSIONS, () -> {
List playerSessions = PerServerMutator.forContainer(container).flatMapSessions();
container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(playerSessions::add);
return playerSessions;
@@ -277,21 +285,21 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
container.putRawData(PlayerKeys.UUID, uuid);
container.putAll(usersTable.getUserInformation(uuid));
- container.putSupplier(PlayerKeys.GEO_INFO, () -> geoInfoTable.getGeoInfo(uuid));
- container.putSupplier(PlayerKeys.PING, () -> pingTable.getPing(uuid));
- container.putSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
- container.putSupplier(PlayerKeys.PER_SERVER, () -> getPerServerData(uuid));
+ container.putCachingSupplier(PlayerKeys.GEO_INFO, () -> geoInfoTable.getGeoInfo(uuid));
+ container.putCachingSupplier(PlayerKeys.PING, () -> pingTable.getPing(uuid));
+ container.putCachingSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
+ container.putCachingSupplier(PlayerKeys.PER_SERVER, () -> getPerServerData(uuid));
container.putSupplier(PlayerKeys.BANNED, () -> new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).isBanned());
container.putSupplier(PlayerKeys.OPERATOR, () -> new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).isOperator());
- container.putSupplier(PlayerKeys.SESSIONS, () -> {
+ container.putCachingSupplier(PlayerKeys.SESSIONS, () -> {
List sessions = new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).flatMapSessions();
container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(sessions::add);
return sessions;
}
);
- container.putSupplier(PlayerKeys.WORLD_TIMES, () ->
+ container.putCachingSupplier(PlayerKeys.WORLD_TIMES, () ->
{
WorldTimes worldTimes = new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).flatMapWorldTimes();
container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(session -> worldTimes.add(
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/GeoInfoLastUsedPatch.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/GeoInfoLastUsedPatch.java
index 80b0d2ef5..d4ab90098 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/GeoInfoLastUsedPatch.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/GeoInfoLastUsedPatch.java
@@ -16,7 +16,7 @@ public class GeoInfoLastUsedPatch extends Patch {
@Override
public void apply() {
- addColumns(GeoInfoTable.TABLE_NAME,
+ addColumn(GeoInfoTable.TABLE_NAME,
GeoInfoTable.Col.LAST_USED + " bigint NOT NULL DEFAULT 0"
);
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/IPHashPatch.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/IPHashPatch.java
index a83134639..8f4b675ea 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/IPHashPatch.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/IPHashPatch.java
@@ -16,6 +16,6 @@ public class IPHashPatch extends Patch {
@Override
public void apply() {
- addColumns(GeoInfoTable.Col.IP_HASH.get() + " varchar(200) DEFAULT ''");
+ addColumn(GeoInfoTable.TABLE_NAME, GeoInfoTable.Col.IP_HASH.get() + " varchar(200) DEFAULT ''");
}
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/KillsServerIDPatch.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/KillsServerIDPatch.java
index e6832a7fd..8428524da 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/KillsServerIDPatch.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/KillsServerIDPatch.java
@@ -40,7 +40,7 @@ public class KillsServerIDPatch extends Patch {
@Override
public void apply() {
- addColumns(KillsTable.Col.SERVER_ID + " integer NOT NULL DEFAULT 0");
+ addColumn(KillsTable.TABLE_NAME, KillsTable.Col.SERVER_ID + " integer NOT NULL DEFAULT 0");
Map sessionIDServerIDRelation = db.getSessionsTable().getIDServerIDRelation();
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/NicknameLastSeenPatch.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/NicknameLastSeenPatch.java
index a45bc697b..a9155de2f 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/NicknameLastSeenPatch.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/NicknameLastSeenPatch.java
@@ -25,7 +25,7 @@ public class NicknameLastSeenPatch extends Patch {
@Override
public void apply() {
- addColumns(NicknamesTable.TABLE_NAME,
+ addColumn(NicknamesTable.TABLE_NAME,
NicknamesTable.Col.LAST_USED + " bigint NOT NULL DEFAULT '0'"
);
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/Patch.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/Patch.java
index 4205a114f..716f2055d 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/Patch.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/Patch.java
@@ -4,6 +4,7 @@ import com.djrapitops.plan.system.database.databases.sql.SQLDB;
import com.djrapitops.plan.system.database.databases.sql.processing.QueryAllStatement;
import com.djrapitops.plan.system.database.databases.sql.processing.QueryStatement;
import com.djrapitops.plan.system.database.databases.sql.statements.TableSqlParser;
+import com.djrapitops.plan.system.settings.Settings;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -30,13 +31,16 @@ public abstract class Patch {
public boolean hasTable(String tableName) {
String sql = usingMySQL ?
- "SELECT * FROM information_schema.TABLES WHERE table_name=? LIMIT 1" :
+ "SELECT * FROM information_schema.TABLES WHERE table_name=? AND TABLE_SCHEMA=? LIMIT 1" :
"SELECT tbl_name FROM sqlite_master WHERE tbl_name=?";
return query(new QueryStatement(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, tableName);
+ if (usingMySQL) {
+ statement.setString(2, Settings.DB_DATABASE.toString());
+ }
}
@Override
@@ -49,11 +53,12 @@ public abstract class Patch {
protected boolean hasColumn(String tableName, String columnName) {
return usingMySQL ?
query(new QueryStatement("SELECT * FROM information_schema.COLUMNS" +
- " WHERE TABLE_NAME=? AND COLUMN_NAME=?") {
+ " WHERE TABLE_NAME=? AND COLUMN_NAME=? AND TABLE_SCHEMA=?") {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, tableName);
statement.setString(2, columnName);
+ statement.setString(3, Settings.DB_DATABASE.toString());
}
@Override
@@ -74,11 +79,8 @@ public abstract class Patch {
});
}
- protected void addColumns(String tableName, String... columnInfo) {
- for (int i = 0; i < columnInfo.length; i++) {
- columnInfo[i] = "ALTER TABLE " + tableName + " ADD " + (usingMySQL ? "" : "COLUMN ") + columnInfo[i];
- }
- db.executeUnsafe(columnInfo);
+ protected void addColumn(String tableName, String columnInfo) {
+ db.executeUnsafe("ALTER TABLE " + tableName + " ADD " + (usingMySQL ? "" : "COLUMN ") + columnInfo);
}
protected void dropTable(String name) {
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/SessionAFKTimePatch.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/SessionAFKTimePatch.java
index 672780d3c..5e8a28032 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/SessionAFKTimePatch.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/SessionAFKTimePatch.java
@@ -16,7 +16,7 @@ public class SessionAFKTimePatch extends Patch {
@Override
public void apply() {
- addColumns(SessionsTable.TABLE_NAME,
+ addColumn(SessionsTable.TABLE_NAME,
SessionsTable.Col.AFK_TIME + " bigint NOT NULL DEFAULT 0"
);
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/TransferPartitionPatch.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/TransferPartitionPatch.java
index 147d8e47a..eea4affe9 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/TransferPartitionPatch.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/TransferPartitionPatch.java
@@ -16,6 +16,6 @@ public class TransferPartitionPatch extends Patch {
@Override
public void apply() {
- addColumns(TransferTable.TABLE_NAME, TransferTable.Col.PART + " bigint NOT NULL DEFAULT 0");
+ addColumn(TransferTable.TABLE_NAME, TransferTable.Col.PART + " bigint NOT NULL DEFAULT 0");
}
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/VersionTableRemovalPatch.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/VersionTableRemovalPatch.java
index c205cbded..b4252bfa0 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/VersionTableRemovalPatch.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/patches/VersionTableRemovalPatch.java
@@ -10,7 +10,7 @@ public class VersionTableRemovalPatch extends Patch {
@Override
public boolean hasBeenApplied() {
- return hasTable("plan_version");
+ return !hasTable("plan_version");
}
@Override
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/KillsTable.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/KillsTable.java
index 2c2fb86f0..1380ceab0 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/KillsTable.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/KillsTable.java
@@ -118,7 +118,7 @@ public class KillsTable extends UserIDTable {
String victimName = set.getString("victim_name");
long date = set.getLong(Col.DATE.get());
String weapon = set.getString(Col.WEAPON.get());
- session.getUnsafe(SessionKeys.PLAYER_KILLS).add(new PlayerKill(victim, weapon, date, victimName));
+ session.getPlayerKills().add(new PlayerKill(victim, weapon, date, victimName));
}
return null;
}
@@ -295,7 +295,7 @@ public class KillsTable extends UserIDTable {
for (Session session : sessions) {
int sessionID = session.getUnsafe(SessionKeys.DB_ID);
// Every kill
- for (PlayerKill kill : session.getUnsafe(SessionKeys.PLAYER_KILLS)) {
+ for (PlayerKill kill : session.getPlayerKills()) {
UUID victim = kill.getVictim();
long date = kill.getDate();
String weapon = kill.getWeapon();
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/ServerTable.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/ServerTable.java
index 6df2a8a83..d9a3aaf18 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/ServerTable.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/ServerTable.java
@@ -367,7 +367,7 @@ public class ServerTable extends Table {
}
public void setAsUninstalled(UUID serverUUID) {
- String sql = "UPDATE " + tableName + " SET (" + Col.INSTALLED + "=?) WHERE " + Col.SERVER_UUID + "=?";
+ String sql = "UPDATE " + tableName + " SET " + Col.INSTALLED + "=? WHERE " + Col.SERVER_UUID + "=?";
execute(new ExecStatement(sql) {
@Override
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/SessionsTable.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/SessionsTable.java
index 3f57aecc0..1a12e8ecd 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/SessionsTable.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/SessionsTable.java
@@ -112,7 +112,7 @@ public class SessionsTable extends UserIDTable {
}
db.getWorldTimesTable().saveWorldTimes(uuid, sessionID, session.getUnsafe(SessionKeys.WORLD_TIMES));
- db.getKillsTable().savePlayerKills(uuid, sessionID, session.getUnsafe(SessionKeys.PLAYER_KILLS));
+ db.getKillsTable().savePlayerKills(uuid, sessionID, session.getPlayerKills());
}
/**
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/TPSTable.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/TPSTable.java
index bc583183f..f2868648d 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/TPSTable.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/tables/TPSTable.java
@@ -147,9 +147,12 @@ public class TPSTable extends Table {
}
public Optional getPeakPlayerCount(UUID serverUUID, long afterDate) {
+ String subStatement = "SELECT MAX(" + Col.PLAYERS_ONLINE + ") FROM " + tableName +
+ " WHERE " + Col.SERVER_ID + "=" + serverTable.statementSelectServerID +
+ " AND " + Col.DATE + ">= ?";
String sql = Select.all(tableName)
.where(Col.SERVER_ID + "=" + serverTable.statementSelectServerID)
- .and(Col.PLAYERS_ONLINE + "= (SELECT MAX(" + Col.PLAYERS_ONLINE + ") FROM " + tableName + ")")
+ .and(Col.PLAYERS_ONLINE + "= (" + subStatement + ")")
.and(Col.DATE + ">= ?")
.toString();
@@ -157,13 +160,14 @@ public class TPSTable extends Table {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, serverUUID.toString());
- statement.setLong(2, afterDate);
+ statement.setString(2, serverUUID.toString());
+ statement.setLong(3, afterDate);
+ statement.setLong(4, afterDate);
}
@Override
public Optional processResults(ResultSet set) throws SQLException {
if (set.next()) {
-
TPS tps = TPSBuilder.get()
.date(set.getLong(Col.DATE.get()))
.tps(set.getDouble(Col.TPS.get()))
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/importing/data/UserImportData.java b/Plan/src/main/java/com/djrapitops/plan/system/importing/data/UserImportData.java
index 134f7f3e3..23e4d0b06 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/importing/data/UserImportData.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/importing/data/UserImportData.java
@@ -276,4 +276,28 @@ public class UserImportData {
return new UserImportData(name, uuid, nicknames, registered, op, banned, timesKicked, ips, worldTimes, kills, mobKills, deaths);
}
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof UserImportData)) return false;
+ UserImportData that = (UserImportData) o;
+ return registered == that.registered &&
+ op == that.op &&
+ banned == that.banned &&
+ timesKicked == that.timesKicked &&
+ mobKills == that.mobKills &&
+ deaths == that.deaths &&
+ Objects.equals(name, that.name) &&
+ Objects.equals(uuid, that.uuid) &&
+ Objects.equals(nicknames, that.nicknames) &&
+ Objects.equals(ips, that.ips) &&
+ Objects.equals(worldTimes, that.worldTimes) &&
+ Objects.equals(kills, that.kills);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, uuid, nicknames, registered, op, banned, timesKicked, ips, worldTimes, kills, mobKills, deaths);
+ }
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/info/BungeeInfoSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/info/ProxyInfoSystem.java
similarity index 81%
rename from Plan/src/main/java/com/djrapitops/plan/system/info/BungeeInfoSystem.java
rename to Plan/src/main/java/com/djrapitops/plan/system/info/ProxyInfoSystem.java
index a55b39146..2b973af21 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/info/BungeeInfoSystem.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/info/ProxyInfoSystem.java
@@ -7,10 +7,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.ConnectionSystem;
-import com.djrapitops.plan.system.info.request.CacheRequest;
-import com.djrapitops.plan.system.info.request.GenerateInspectPageRequest;
-import com.djrapitops.plan.system.info.request.InfoRequest;
-import com.djrapitops.plan.system.info.request.InfoRequestFactory;
+import com.djrapitops.plan.system.info.request.*;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.webserver.WebServer;
import com.djrapitops.plugin.logging.console.PluginLogger;
@@ -25,10 +22,10 @@ import javax.inject.Singleton;
* @author Rsl1122
*/
@Singleton
-public class BungeeInfoSystem extends InfoSystem {
+public class ProxyInfoSystem extends InfoSystem {
@Inject
- public BungeeInfoSystem(
+ public ProxyInfoSystem(
InfoRequestFactory infoRequestFactory,
ConnectionSystem connectionSystem,
ServerInfo serverInfo,
@@ -41,7 +38,9 @@ public class BungeeInfoSystem extends InfoSystem {
@Override
public void runLocally(InfoRequest infoRequest) throws WebException {
if (infoRequest instanceof CacheRequest
- || infoRequest instanceof GenerateInspectPageRequest) {
+ || infoRequest instanceof GenerateInspectPageRequest
+ || infoRequest instanceof GenerateInspectPluginsTabRequest
+ ) {
infoRequest.runLocally();
} else {
// runLocally is called when ConnectionSystem has no servers.
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/info/connection/ConnectionOut.java b/Plan/src/main/java/com/djrapitops/plan/system/info/connection/ConnectionOut.java
index 1d8c0f054..e781667e6 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/info/connection/ConnectionOut.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/info/connection/ConnectionOut.java
@@ -144,6 +144,7 @@ public class ConnectionOut {
post.setHeader("Content-Type", "application/x-www-form-urlencoded");
post.setHeader("charset", "UTF-8");
+ post.setHeader("Connection", "close");
byte[] toSend = parameters.getBytes();
post.setEntity(new ByteArrayEntity(toSend));
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/info/connection/BungeeConnectionSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/info/connection/ProxyConnectionSystem.java
similarity index 86%
rename from Plan/src/main/java/com/djrapitops/plan/system/info/connection/BungeeConnectionSystem.java
rename to Plan/src/main/java/com/djrapitops/plan/system/info/connection/ProxyConnectionSystem.java
index f35419bf5..11c7d6daa 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/info/connection/BungeeConnectionSystem.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/info/connection/ProxyConnectionSystem.java
@@ -22,12 +22,12 @@ import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
- * ConnectionSystem for Bungee.
+ * ConnectionSystem for proxy servers.
*
* @author Rsl1122
*/
@Singleton
-public class BungeeConnectionSystem extends ConnectionSystem {
+public class ProxyConnectionSystem extends ConnectionSystem {
private final Database database;
private final Lazy webServer;
@@ -37,7 +37,7 @@ public class BungeeConnectionSystem extends ConnectionSystem {
private long latestServerMapRefresh;
@Inject
- public BungeeConnectionSystem(
+ public ProxyConnectionSystem(
Database database,
Lazy webServer,
ConnectionLog connectionLog,
@@ -52,7 +52,6 @@ public class BungeeConnectionSystem extends ConnectionSystem {
this.webServer = webServer;
this.errorHandler = errorHandler;
this.webExceptionLogger = webExceptionLogger;
-
latestServerMapRefresh = 0;
}
@@ -71,7 +70,9 @@ public class BungeeConnectionSystem extends ConnectionSystem {
protected Server selectServerForRequest(InfoRequest infoRequest) throws NoServersException {
refreshServerMap();
Server server = null;
- if (infoRequest instanceof CacheRequest || infoRequest instanceof GenerateInspectPageRequest) {
+ if (infoRequest instanceof CacheRequest
+ || infoRequest instanceof GenerateInspectPageRequest
+ || infoRequest instanceof GenerateInspectPluginsTabRequest) {
// Run locally
return serverInfo.getServer();
} else if (infoRequest instanceof GenerateAnalysisPageRequest) {
@@ -93,6 +94,10 @@ public class BungeeConnectionSystem extends ConnectionSystem {
for (Server server : bukkitServers.values()) {
webExceptionLogger.logIfOccurs(this.getClass(), () -> sendInfoRequest(infoRequest, server));
}
+ // Quick hack
+ if (infoRequest instanceof GenerateInspectPluginsTabRequest) {
+ webExceptionLogger.logIfOccurs(this.getClass(), () -> InfoSystem.getInstance().sendRequest(infoRequest));
+ }
}
@Override
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/info/server/VelocityServerInfo.java b/Plan/src/main/java/com/djrapitops/plan/system/info/server/VelocityServerInfo.java
new file mode 100644
index 000000000..d3bb32488
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/system/info/server/VelocityServerInfo.java
@@ -0,0 +1,88 @@
+/*
+ * License is provided in the jar as LICENSE also here:
+ * https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
+ */
+package com.djrapitops.plan.system.info.server;
+
+import com.djrapitops.plan.PlanVelocity;
+import com.djrapitops.plan.api.exceptions.EnableException;
+import com.djrapitops.plan.api.exceptions.database.DBOpException;
+import com.djrapitops.plan.system.database.databases.Database;
+import com.djrapitops.plan.system.info.server.properties.VelocityServerProperties;
+import com.djrapitops.plan.system.info.server.properties.ServerProperties;
+import com.djrapitops.plan.system.webserver.WebServerSystem;
+import com.djrapitops.plugin.api.utility.log.Log;
+
+import java.util.Optional;
+import java.util.UUID;
+
+/**
+ * Manages Server information on the Velocity instance.
+ *
+ * Based on BungeeServerInfo
+ *
+ * @author MicleBrick
+ */
+public class VelocityServerInfo extends ServerInfo {
+
+ public VelocityServerInfo(PlanVelocity plugin) {
+ super(new VelocityServerProperties(plugin.getProxy()));
+ }
+
+ @Override
+ public Server loadServerInfo() throws EnableException {
+ checkIfDefaultIP();
+
+ try {
+ Database db = Database.getActive();
+ // doesn't seem like this would need to be different for velocity, perhaps rename to getProxyInformation()?
+ Optional velocityInfo = db.fetch().getBungeeInformation();
+ if (velocityInfo.isPresent()) {
+ server = velocityInfo.get();
+ updateServerInfo(db);
+ } else {
+ server = registerVelocityInfo(db);
+ }
+ } catch (DBOpException e) {
+ throw new EnableException("Failed to read Server information from Database.");
+ }
+ return server;
+ }
+
+ private void updateServerInfo(Database db) {
+ String accessAddress = WebServerSystem.getInstance().getWebServer().getAccessAddress();
+ if (!accessAddress.equals(server.getWebAddress())) {
+ server.setWebAddress(accessAddress);
+ db.save().serverInfoForThisServer(server);
+ }
+ }
+
+ private void checkIfDefaultIP() throws EnableException {
+ String ip = ServerInfo.getServerProperties().getIp();
+ if ("0.0.0.0".equals(ip)) {
+ Log.error("IP setting still 0.0.0.0 - Configure AlternativeIP/IP that connects to the Proxy server.");
+ Log.info("Player Analytics partially enabled (Use /planvelocity to reload config)");
+ throw new EnableException("IP setting still 0.0.0.0 - Configure AlternativeIP/IP that connects to the Proxy server.");
+ }
+ }
+
+ private Server registerVelocityInfo(Database db) throws EnableException {
+ ServerProperties properties = ServerInfo.getServerProperties();
+ UUID serverUUID = generateNewUUID(properties);
+ String accessAddress = WebServerSystem.getInstance().getWebServer().getAccessAddress();
+
+ Server velocityCord = new Server(-1, serverUUID, "VelocityCord", accessAddress, properties.getMaxPlayers());
+ db.save().serverInfoForThisServer(velocityCord);
+
+ Optional velocityInfo = db.fetch().getBungeeInformation();
+ if (velocityInfo.isPresent()) {
+ return velocityInfo.get();
+ }
+ throw new EnableException("VelocityCord registration failed (DB)");
+ }
+
+ private UUID generateNewUUID(ServerProperties properties) {
+ String seed = properties.getName() + properties.getIp() + properties.getPort() + properties.getVersion() + properties.getImplVersion();
+ return UUID.nameUUIDFromBytes(seed.getBytes());
+ }
+}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/info/server/properties/VelocityServerProperties.java b/Plan/src/main/java/com/djrapitops/plan/system/info/server/properties/VelocityServerProperties.java
new file mode 100644
index 000000000..01a76c09d
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/system/info/server/properties/VelocityServerProperties.java
@@ -0,0 +1,28 @@
+package com.djrapitops.plan.system.info.server.properties;
+
+import com.djrapitops.plan.system.settings.Settings;
+import com.velocitypowered.api.proxy.ProxyServer;
+
+/**
+ * ServerProperties for Velocity.
+ *
+ * Supports RedisBungee for Players online getting.
+ *
+ * @author Rsl1122
+ */
+public class VelocityServerProperties extends ServerProperties {
+
+ public VelocityServerProperties(ProxyServer server) {
+ super(
+ server.getAllServers().toString(),
+ "Velocity",
+ server.getBoundAddress().getPort(),
+ // not sure how to get these
+ server.getClass().getPackage().getImplementationVersion(),
+ server.getClass().getPackage().getImplementationVersion(),
+ Settings.BUNGEE_IP::toString,
+ -1, // not sure how to get this
+ RedisCheck.isClassAvailable() ? new RedisPlayersOnlineSupplier() : server::getPlayerCount
+ );
+ }
+}
\ No newline at end of file
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/VelocityListenerSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/VelocityListenerSystem.java
new file mode 100644
index 000000000..7d61fd098
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/VelocityListenerSystem.java
@@ -0,0 +1,23 @@
+package com.djrapitops.plan.system.listeners;
+
+import com.djrapitops.plan.PlanVelocity;
+import com.djrapitops.plan.system.listeners.velocity.PlayerOnlineListener;
+
+public class VelocityListenerSystem extends ListenerSystem {
+
+ private final PlanVelocity plugin;
+
+ public VelocityListenerSystem(PlanVelocity plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ protected void registerListeners() {
+ plugin.registerListener(new PlayerOnlineListener());
+ }
+
+ @Override
+ protected void unregisterListeners() {
+ plugin.getProxy().getEventManager().unregisterListeners(plugin);
+ }
+}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/AFKListener.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/AFKListener.java
index 482ec9b94..dd8989307 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/AFKListener.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/bukkit/AFKListener.java
@@ -15,6 +15,8 @@ import org.bukkit.event.player.PlayerEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import javax.inject.Inject;
+import java.util.HashMap;
+import java.util.Map;
import java.util.UUID;
/**
@@ -30,11 +32,13 @@ public class AFKListener implements Listener {
// Static so that /reload does not cause afk tracking to fail.
static AFKTracker AFK_TRACKER;
+ private final Map ignorePermissionInfo;
private final ErrorHandler errorHandler;
@Inject
public AFKListener(PlanConfig config, ErrorHandler errorHandler) {
this.errorHandler = errorHandler;
+ this.ignorePermissionInfo = new HashMap<>();
AFKListener.assignAFKTracker(config);
}
@@ -51,8 +55,15 @@ public class AFKListener implements Listener {
UUID uuid = player.getUniqueId();
long time = System.currentTimeMillis();
- if (player.hasPermission(Permissions.IGNORE_AFK.getPermission())) {
+ Boolean ignored = ignorePermissionInfo.get(uuid);
+ if (ignored == null) {
+ ignored = player.hasPermission(Permissions.IGNORE_AFK.getPermission());
+ }
+ if (ignored) {
AFK_TRACKER.hasIgnorePermission(uuid);
+ ignorePermissionInfo.put(uuid, true);
+ } else {
+ ignorePermissionInfo.put(uuid, false);
}
AFK_TRACKER.performedAction(uuid, time);
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 2cd627cf6..dd924bf5d 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
@@ -92,6 +92,10 @@ public class PlayerOnlineListener implements Listener {
return;
}
UUID uuid = event.getPlayer().getUniqueId();
+ if (AFKListener.AFK_TRACKER.isAfk(uuid)) {
+ return;
+ }
+
processing.submit(processors.player().kickProcessor(uuid));
} catch (Exception e) {
errorHandler.log(L.ERROR, this.getClass(), e);
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/bungee/PlayerOnlineListener.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/bungee/PlayerOnlineListener.java
index 17e8b0bb1..4d4d467d5 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/listeners/bungee/PlayerOnlineListener.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/bungee/PlayerOnlineListener.java
@@ -16,8 +16,8 @@ import com.djrapitops.plan.system.webserver.cache.ResponseCache;
import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.error.ErrorHandler;
import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
-import net.md_5.bungee.api.event.ServerDisconnectEvent;
import net.md_5.bungee.api.event.ServerSwitchEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
@@ -81,7 +81,7 @@ public class PlayerOnlineListener implements Listener {
}
@EventHandler
- public void onLogout(ServerDisconnectEvent event) {
+ public void onLogout(PlayerDisconnectEvent event) {
try {
ProxiedPlayer player = event.getPlayer();
UUID uuid = player.getUniqueId();
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
index 2f482a88f..a4584e2f5 100644
--- 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
@@ -3,6 +3,7 @@ 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.info.server.ServerInfo;
+import com.djrapitops.plan.system.listeners.bukkit.AFKListener;
import com.djrapitops.plan.system.processing.Processing;
import com.djrapitops.plan.system.processing.processors.Processors;
import com.djrapitops.plan.system.settings.Settings;
@@ -81,6 +82,10 @@ public class SpongePlayerListener {
public void onKick(KickPlayerEvent event) {
try {
UUID uuid = event.getTargetEntity().getUniqueId();
+ // TODO
+ if (AFKListener.AFK_TRACKER.isAfk(uuid)) {
+ return;
+ }
processing.submit(processors.player().kickProcessor(uuid));
} catch (Exception e) {
errorHandler.log(L.ERROR, this.getClass(), e);
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/listeners/velocity/PlayerOnlineListener.java b/Plan/src/main/java/com/djrapitops/plan/system/listeners/velocity/PlayerOnlineListener.java
new file mode 100644
index 000000000..e190c8d81
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/system/listeners/velocity/PlayerOnlineListener.java
@@ -0,0 +1,85 @@
+/*
+ * License is provided in the jar as LICENSE also here:
+ * https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
+ */
+package com.djrapitops.plan.system.listeners.velocity;
+
+import com.djrapitops.plan.data.container.Session;
+import com.djrapitops.plan.system.cache.SessionCache;
+import com.djrapitops.plan.system.info.server.ServerInfo;
+import com.djrapitops.plan.system.processing.Processing;
+import com.djrapitops.plan.system.processing.processors.info.PlayerPageUpdateProcessor;
+import com.djrapitops.plan.system.processing.processors.player.BungeePlayerRegisterProcessor;
+import com.djrapitops.plan.system.processing.processors.player.IPUpdateProcessor;
+import com.djrapitops.plan.system.webserver.cache.PageId;
+import com.djrapitops.plan.system.webserver.cache.ResponseCache;
+import com.djrapitops.plugin.api.utility.log.Log;
+import com.velocitypowered.api.event.Subscribe;
+import com.velocitypowered.api.event.connection.DisconnectEvent;
+import com.velocitypowered.api.event.connection.PostLoginEvent;
+import com.velocitypowered.api.event.player.ServerConnectedEvent;
+import com.velocitypowered.api.proxy.Player;
+
+import java.net.InetAddress;
+import java.util.UUID;
+
+/**
+ * Player Join listener for Velocity.
+ *
+ * Based on the bungee version.
+ *
+ * @author MicleBrick
+ */
+public class PlayerOnlineListener {
+
+ @Subscribe
+ public void onPostLogin(PostLoginEvent event) {
+ try {
+ Player player = event.getPlayer();
+ UUID uuid = player.getUniqueId();
+ String name = player.getUsername();
+ InetAddress address = player.getRemoteAddress().getAddress();
+ long now = System.currentTimeMillis();
+
+ SessionCache.getInstance().cacheSession(uuid, new Session(uuid, now, "", ""));
+
+ // maybe rename to ProxyPlayerRegisterProcessor?
+ Processing.submit(new BungeePlayerRegisterProcessor(uuid, name, now,
+ new IPUpdateProcessor(uuid, address, now))
+ );
+ Processing.submit(new PlayerPageUpdateProcessor(uuid));
+ ResponseCache.clearResponse(PageId.SERVER.of(ServerInfo.getServerUUID()));
+ } catch (Exception e) {
+ Log.toLog(this.getClass(), e);
+ }
+ }
+
+ @Subscribe
+ public void onLogout(DisconnectEvent event) {
+ try {
+ Player player = event.getPlayer();
+ UUID uuid = player.getUniqueId();
+
+ SessionCache.getInstance().endSession(uuid, System.currentTimeMillis());
+ Processing.submit(new PlayerPageUpdateProcessor(uuid));
+ ResponseCache.clearResponse(PageId.SERVER.of(ServerInfo.getServerUUID()));
+ } catch (Exception e) {
+ Log.toLog(this.getClass(), e);
+ }
+ }
+
+ @Subscribe
+ public void onServerSwitch(ServerConnectedEvent event) {
+ try {
+ Player player = event.getPlayer();
+ UUID uuid = player.getUniqueId();
+
+ long now = System.currentTimeMillis();
+ // Replaces the current session in the cache.
+ SessionCache.getInstance().cacheSession(uuid, new Session(uuid, now, "", ""));
+ Processing.submit(new PlayerPageUpdateProcessor(uuid));
+ } catch (Exception e) {
+ Log.toLog(this.getClass(), e);
+ }
+ }
+}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/locale/Locale.java b/Plan/src/main/java/com/djrapitops/plan/system/locale/Locale.java
index 5d7b08720..e0c950d24 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/locale/Locale.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/locale/Locale.java
@@ -1,14 +1,16 @@
package com.djrapitops.plan.system.locale;
import com.djrapitops.plan.PlanPlugin;
-import com.djrapitops.plan.system.locale.lang.Lang;
+import com.djrapitops.plan.system.locale.lang.*;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
import java.util.stream.Collectors;
/**
@@ -67,10 +69,22 @@ public class Locale extends HashMap {
String replaced = from;
- // Longest first so that entries that contain each other don't partially replace.
- List> entries = entrySet().stream().sorted(
- (one, two) -> Integer.compare(two.getKey().getIdentifier().length(), one.getKey().getIdentifier().length())
- ).collect(Collectors.toList());
+ Lang[][] langs = new Lang[][]{
+ NetworkPageLang.values(),
+ PlayerPageLang.values(),
+ ServerPageLang.values(),
+ CommonHtmlLang.values()
+ };
+
+ List> entries = Arrays.stream(langs)
+ .flatMap(Arrays::stream)
+ .collect(Collectors.toMap(Function.identity(), this::get))
+ .entrySet().stream()
+ // Longest first so that entries that contain each other don't partially replace.
+ .sorted((one, two) -> Integer.compare(
+ two.getKey().getIdentifier().length(),
+ one.getKey().getIdentifier().length()
+ )).collect(Collectors.toList());
for (Entry entry : entries) {
String defaultValue = entry.getKey().getDefault();
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/processing/Processing.java b/Plan/src/main/java/com/djrapitops/plan/system/processing/Processing.java
index 1f59cdded..e7d847b3d 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/processing/Processing.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/processing/Processing.java
@@ -8,6 +8,7 @@ import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.console.PluginLogger;
import com.djrapitops.plugin.logging.error.ErrorHandler;
import dagger.Lazy;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -33,8 +34,8 @@ public class Processing implements SubSystem {
this.locale = locale;
this.logger = logger;
this.errorHandler = errorHandler;
- nonCriticalExecutor = Executors.newFixedThreadPool(6);
- criticalExecutor = Executors.newFixedThreadPool(2);
+ nonCriticalExecutor = Executors.newFixedThreadPool(6, new ThreadFactoryBuilder().setNameFormat("Plan Non critical-pool-%d").build());
+ criticalExecutor = Executors.newFixedThreadPool(2, new ThreadFactoryBuilder().setNameFormat("Plan Critical-pool-%d").build());
}
public void submit(Runnable runnable) {
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 758e90f2c..653013156 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
@@ -1,51 +1,23 @@
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.Check;
-import com.djrapitops.plugin.api.TimeAmount;
-import com.djrapitops.plugin.task.AbsRunnable;
-import com.djrapitops.plugin.task.RunnableFactory;
+import com.djrapitops.plan.system.webserver.cache.PageId;
+import com.djrapitops.plan.system.webserver.cache.ResponseCache;
import java.util.UUID;
-import java.util.concurrent.TimeUnit;
public class PlayerPageUpdateProcessor implements Runnable {
private final UUID uuid;
- private final InfoSystem infoSystem;
- private final WebExceptionLogger webExceptionLogger;
- private final RunnableFactory runnableFactory;
-
+ // TODO Factory method fix
PlayerPageUpdateProcessor(
- UUID uuid,
- InfoSystem infoSystem,
- WebExceptionLogger webExceptionLogger,
- RunnableFactory runnableFactory
+ UUID uuid
) {
this.uuid = uuid;
- this.infoSystem = infoSystem;
- this.webExceptionLogger = webExceptionLogger;
- this.runnableFactory = runnableFactory;
}
@Override
public void run() {
- if (!infoSystem.getConnectionSystem().isServerAvailable() || Check.isBungeeAvailable()) {
- runnableFactory.create("Generate Inspect page: " + uuid, new AbsRunnable() {
- @Override
- public void run() {
- try {
-
- webExceptionLogger.logIfOccurs(PlayerPageUpdateProcessor.class,
- () -> infoSystem.generateAndCachePlayerPage(uuid)
- );
- } finally {
- cancel();
- }
- }
- }).runTaskLaterAsynchronously(TimeAmount.toTicks(20L, TimeUnit.SECONDS));
- }
+ ResponseCache.clearResponse(PageId.PLAYER.of(uuid));
}
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/PingInsertProcessor.java b/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/PingInsertProcessor.java
index 2c552a73e..077f1afbb 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/PingInsertProcessor.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/PingInsertProcessor.java
@@ -8,10 +8,12 @@ import com.djrapitops.plan.data.container.Ping;
import com.djrapitops.plan.data.store.objects.DateObj;
import com.djrapitops.plan.system.database.databases.Database;
import com.djrapitops.plan.system.processing.CriticalRunnable;
+import com.djrapitops.plan.utilities.analysis.Median;
import java.util.List;
import java.util.OptionalInt;
import java.util.UUID;
+import java.util.stream.Collectors;
/**
* Processes 60s values of a Ping list.
@@ -51,20 +53,25 @@ public class PingInsertProcessor implements CriticalRunnable {
return;
}
- int minValue = history.stream()
- .mapToInt(DateObj::getValue)
- .filter(i -> i > 0 && i < 4000)
- .min().orElse(-1);
+ int minValue = getMinValue(history);
- double avgValue = history.stream()
- .mapToInt(DateObj::getValue)
- .filter(i -> i > 0 && i < 4000)
- .average().orElse(-1);
+ int meanValue = getMeanValue(history);
int maxValue = max.getAsInt();
- Ping ping = new Ping(lastDate, serverUUID, minValue, maxValue, avgValue);
+ Ping ping = new Ping(lastDate, serverUUID, minValue, maxValue, meanValue);
database.save().ping(uuid, ping);
}
+
+ int getMinValue(List> history) {
+ return history.stream()
+ .mapToInt(DateObj::getValue)
+ .filter(i -> i > 0 && i < 4000)
+ .min().orElse(-1);
+ }
+
+ int getMeanValue(List> history) {
+ return (int) Median.forInt(history.stream().map(DateObj::getValue).collect(Collectors.toList())).calculate();
+ }
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/BungeeRegisterProcessor.java b/Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/ProxyRegisterProcessor.java
similarity index 100%
rename from Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/BungeeRegisterProcessor.java
rename to Plan/src/main/java/com/djrapitops/plan/system/processing/processors/player/ProxyRegisterProcessor.java
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/settings/Permissions.java b/Plan/src/main/java/com/djrapitops/plan/system/settings/Permissions.java
index 0a5377ccd..c61c54d5b 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/settings/Permissions.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/settings/Permissions.java
@@ -10,8 +10,8 @@ public enum Permissions {
HELP("plan.?"),
- INSPECT("plan.inspect"),
- QUICK_INSPECT("plan.qinspect"),
+ INSPECT("plan.inspect.base"),
+ QUICK_INSPECT("plan.qinspect.base"),
INSPECT_OTHER("plan.inspect.other"),
QUICK_INSPECT_OTHER("plan.qinspect.other"),
@@ -36,7 +36,7 @@ public enum Permissions {
/**
* Returns the permission node in plugin.yml.
*
- * @return permission node eg. plan.inspect
+ * @return permission node eg. plan.inspect.base
*/
public String getPermission() {
return permission;
@@ -45,7 +45,7 @@ public enum Permissions {
/**
* Same as {@link #getPermission()}.
*
- * @return permission node eg. plan.inspect
+ * @return permission node eg. plan.inspect.base
*/
public String getPerm() {
return getPermission();
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 7052bcb45..1774e8f61 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
@@ -44,6 +44,8 @@ public enum Settings implements Setting {
AFK_THRESHOLD_MINUTES("Data.AFKThresholdMinutes"),
KEEP_LOGS_DAYS("Plugin.KeepLogsForXDays"),
KEEP_INACTIVE_PLAYERS_DAYS("Data.KeepInactivePlayerDataForDays"),
+ PING_SERVER_ENABLE_DELAY("Data.Ping.ServerEnableDelaySeconds"),
+ PING_PLAYER_LOGIN_DELAY("Data.Ping.PlayerLoginDelaySeconds"),
// String
DEBUG("Plugin.Debug"),
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/settings/config/BungeeConfigSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/settings/config/ProxyConfigSystem.java
similarity index 100%
rename from Plan/src/main/java/com/djrapitops/plan/system/settings/config/BungeeConfigSystem.java
rename to Plan/src/main/java/com/djrapitops/plan/system/settings/config/ProxyConfigSystem.java
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 6bc1da0de..a51d21748 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
@@ -201,7 +201,9 @@ public class NetworkSettings {
AFK_THRESHOLD_MINUTES,
DATA_GEOLOCATIONS,
KEEP_LOGS_DAYS,
- KEEP_INACTIVE_PLAYERS_DAYS
+ KEEP_INACTIVE_PLAYERS_DAYS,
+ PING_SERVER_ENABLE_DELAY,
+ PING_PLAYER_LOGIN_DELAY
};
logger.debug("NetworkSettings: Adding Config Values..");
PlanConfig planConfig = config.get();
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 c28935a8e..cd0918c36 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,13 +5,16 @@
package com.djrapitops.plan.system.tasks;
import com.djrapitops.plan.Plan;
+import com.djrapitops.plan.system.settings.Settings;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.tasks.server.*;
import com.djrapitops.plugin.api.Check;
+import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.task.RunnableFactory;
import org.bukkit.Bukkit;
import javax.inject.Inject;
+import java.util.concurrent.TimeUnit;
/**
* TaskSystem responsible for registering tasks for Bukkit.
@@ -53,8 +56,10 @@ public class BukkitTaskSystem extends ServerTaskSystem {
super.enable();
try {
plugin.registerListener(pingCountTimer);
+ // TODO config
+ long startDelay = TimeAmount.toTicks(Settings.PING_SERVER_ENABLE_DELAY.getNumber(), TimeUnit.SECONDS);
registerTask("PingCountTimer", pingCountTimer)
- .runTaskTimer(20L, PingCountTimer.PING_INTERVAL);
+ .runTaskTimer(startDelay, 40L);
} catch (ExceptionInInitializerError | NoClassDefFoundError ignore) {
// Running CraftBukkit
}
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 49c04d545..dc7f21ff4 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
@@ -4,9 +4,11 @@
*/
package com.djrapitops.plan.system.tasks;
+import com.djrapitops.plan.system.settings.Settings;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.tasks.bungee.BungeeTPSCountTimer;
import com.djrapitops.plan.system.tasks.server.NetworkPageRefreshTask;
+import com.djrapitops.plan.system.tasks.server.PingCountTimerBungee;
import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.task.RunnableFactory;
@@ -55,5 +57,12 @@ public class BungeeTaskSystem extends TaskSystem {
config.getNetworkSettings().placeSettingsToDB();
}
}).runTaskAsynchronously();
+
+ // TODO Move this elsewhere
+ PingCountTimerBungee pingCountTimer = new PingCountTimerBungee();
+ plugin.registerListener(pingCountTimer);
+ long startDelay = TimeAmount.SECOND.ticks() * (long) Settings.PING_SERVER_ENABLE_DELAY.getNumber();
+ RunnableFactory.createNew("PingCountTimer", pingCountTimer)
+ .runTaskTimer(startDelay, PingCountTimerBungee.PING_INTERVAL);
}
}
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
index 1566b894d..8a88ed171 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/tasks/LogsFolderCleanTask.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/LogsFolderCleanTask.java
@@ -48,7 +48,11 @@ public class LogsFolderCleanTask extends AbsRunnable {
} catch (NullPointerException ignore) {
/* Ignored - not supposed to occur. */
} finally {
- cancel();
+ try {
+ cancel();
+ } catch (Exception ignore) {
+ /* Ignored, TaskCenter concurrent modification exception, will be fixed later in apf-3.3.0. */
+ }
}
}
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 a00c35a43..044527855 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
@@ -5,8 +5,12 @@ import com.djrapitops.plan.system.settings.config.PlanConfig;
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.system.settings.Settings;
+import com.djrapitops.plan.system.tasks.server.PingCountTimerSponge;
import com.djrapitops.plan.system.tasks.server.SpongeTPSCountTimer;
import com.djrapitops.plugin.task.RunnableFactory;
+import com.djrapitops.plugin.api.TimeAmount;
+import com.djrapitops.plugin.task.RunnableFactory;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.scheduler.Task;
@@ -38,6 +42,18 @@ public class SpongeTaskSystem extends ServerTaskSystem {
this.plugin = plugin;
}
+ @Override
+ public void enable() {
+ super.enable();
+
+ // TODO Move elsewhere
+ PingCountTimerSponge pingCountTimer = new PingCountTimerSponge();
+ plugin.registerListener(pingCountTimer);
+ long startDelay = TimeAmount.SECOND.ticks() * (long) Settings.PING_SERVER_ENABLE_DELAY.getNumber();
+ RunnableFactory.createNew("PingCountTimer", pingCountTimer)
+ .runTaskTimer(startDelay, PingCountTimerSponge.PING_INTERVAL);
+ }
+
@Override
public void disable() {
super.disable();
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/TPSCountTimer.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/TPSCountTimer.java
index 642061513..7e18bca46 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/tasks/TPSCountTimer.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/TPSCountTimer.java
@@ -8,6 +8,8 @@ import com.djrapitops.plugin.logging.console.PluginLogger;
import com.djrapitops.plugin.logging.error.ErrorHandler;
import com.djrapitops.plugin.task.AbsRunnable;
+import java.lang.management.ManagementFactory;
+import java.lang.management.OperatingSystemMXBean;
import java.util.ArrayList;
import java.util.List;
@@ -64,4 +66,27 @@ public abstract class TPSCountTimer extends AbsRunnable {
public int getLatestPlayersOnline() {
return latestPlayersOnline;
}
+
+ protected long getUsedMemory() {
+ Runtime runtime = Runtime.getRuntime();
+ long totalMemory = runtime.totalMemory();
+ return (totalMemory - runtime.freeMemory()) / 1000000;
+ }
+
+ protected double getCPUUsage() {
+ double averageCPUUsage;
+
+ OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
+ if (osBean instanceof com.sun.management.OperatingSystemMXBean) {
+ com.sun.management.OperatingSystemMXBean nativeOsBean = (com.sun.management.OperatingSystemMXBean) osBean;
+ averageCPUUsage = nativeOsBean.getSystemCpuLoad();
+ } else {
+ int availableProcessors = osBean.getAvailableProcessors();
+ averageCPUUsage = osBean.getSystemLoadAverage() / availableProcessors;
+ }
+ if (averageCPUUsage < 0) { // If unavailable, getSystemLoadAverage() returns -1
+ averageCPUUsage = -1;
+ }
+ return averageCPUUsage * 100.0;
+ }
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/VelocityTaskSystem.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/VelocityTaskSystem.java
new file mode 100644
index 000000000..6a1e0da4b
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/VelocityTaskSystem.java
@@ -0,0 +1,49 @@
+/*
+ * License is provided in the jar as LICENSE also here:
+ * https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
+ */
+package com.djrapitops.plan.system.tasks;
+
+import com.djrapitops.plan.PlanVelocity;
+import com.djrapitops.plan.system.settings.Settings;
+import com.djrapitops.plan.system.tasks.proxy.EnableConnectionTask;
+import com.djrapitops.plan.system.tasks.velocity.VelocityTPSCountTimer;
+import com.djrapitops.plan.system.tasks.server.NetworkPageRefreshTask;
+import com.djrapitops.plan.system.tasks.server.PingCountTimerVelocity;
+import com.djrapitops.plan.utilities.file.export.HtmlExport;
+import com.djrapitops.plugin.api.TimeAmount;
+import com.djrapitops.plugin.task.RunnableFactory;
+
+/**
+ * TaskSystem responsible for registering tasks for Velocity.
+ *
+ * @author Rsl1122
+ */
+public class VelocityTaskSystem extends TaskSystem {
+
+ private final PlanVelocity plugin;
+
+ public VelocityTaskSystem(PlanVelocity plugin) {
+ super(new VelocityTPSCountTimer(plugin));
+ this.plugin = plugin;
+ }
+
+ @Override
+ public void enable() {
+ registerTasks();
+ }
+
+ private void registerTasks() {
+ registerTask(new EnableConnectionTask()).runTaskAsynchronously();
+ registerTask(tpsCountTimer).runTaskTimerAsynchronously(1000, TimeAmount.SECOND.ticks());
+ registerTask(new NetworkPageRefreshTask()).runTaskTimerAsynchronously(1500, TimeAmount.MINUTE.ticks());
+ if (Settings.ANALYSIS_EXPORT.isTrue()) {
+ registerTask(new HtmlExport(plugin)).runTaskAsynchronously();
+ }
+ PingCountTimerVelocity pingCountTimer = new PingCountTimerVelocity();
+ plugin.registerListener(pingCountTimer);
+ long startDelay = TimeAmount.SECOND.ticks() * (long) Settings.PING_SERVER_ENABLE_DELAY.getNumber();
+ RunnableFactory.createNew("PingCountTimer", pingCountTimer)
+ .runTaskTimer(startDelay, PingCountTimerVelocity.PING_INTERVAL);
+ }
+}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/bungee/BungeeTPSCountTimer.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/bungee/BungeeTPSCountTimer.java
index 1e8cea17e..03cd02016 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/tasks/bungee/BungeeTPSCountTimer.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/bungee/BungeeTPSCountTimer.java
@@ -36,6 +36,10 @@ public class BungeeTPSCountTimer extends TPSCountTimer {
.date(now)
.skipTPS()
.playersOnline(onlineCount)
+ .usedCPU(getCPUUsage())
+ .usedMemory(getUsedMemory())
+ .entities(-1)
+ .chunksLoaded(-1)
.toTPS();
history.add(tps);
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/proxy/EnableConnectionTask.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/proxy/EnableConnectionTask.java
new file mode 100644
index 000000000..e69de29bb
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/BukkitTPSCountTimer.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/BukkitTPSCountTimer.java
index 741465adf..746bfad76 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/BukkitTPSCountTimer.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/BukkitTPSCountTimer.java
@@ -62,10 +62,7 @@ public class BukkitTPSCountTimer extends TPSCountTimer {
private TPS calculateTPS(long diff, long now) {
double averageCPUUsage = getCPUUsage();
- Runtime runtime = Runtime.getRuntime();
-
- long totalMemory = runtime.totalMemory();
- long usedMemory = (totalMemory - runtime.freeMemory()) / 1000000;
+ long usedMemory = getUsedMemory();
int playersOnline = serverProperties.getOnlinePlayers();
latestPlayersOnline = playersOnline;
@@ -77,22 +74,6 @@ public class BukkitTPSCountTimer extends TPSCountTimer {
return getTPS(diff, now, averageCPUUsage, usedMemory, entityCount, loadedChunks, playersOnline);
}
- private double getCPUUsage() {
- double averageCPUUsage;
-
- OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
- if (osBean instanceof com.sun.management.OperatingSystemMXBean) {
- com.sun.management.OperatingSystemMXBean nativeOsBean = (com.sun.management.OperatingSystemMXBean) osBean;
- averageCPUUsage = nativeOsBean.getSystemCpuLoad();
- } else {
- int availableProcessors = osBean.getAvailableProcessors();
- averageCPUUsage = osBean.getSystemLoadAverage() / availableProcessors;
- }
- if (averageCPUUsage < 0) { // If unavailable, getSystemLoadAverage() returns -1
- averageCPUUsage = -1;
- }
- return averageCPUUsage * 100.0;
- }
/**
* Gets the TPS for Spigot / Bukkit
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimer.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimerBukkit.java
similarity index 89%
rename from Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimer.java
rename to Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimerBukkit.java
index cade2a566..362a1e959 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimer.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimerBukkit.java
@@ -26,6 +26,7 @@ package com.djrapitops.plan.system.tasks.server;
import com.djrapitops.plan.data.store.objects.DateObj;
import com.djrapitops.plan.system.processing.Processing;
import com.djrapitops.plan.system.processing.processors.Processors;
+import com.djrapitops.plan.system.settings.Settings;
import com.djrapitops.plan.utilities.java.Reflection;
import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.task.AbsRunnable;
@@ -57,23 +58,23 @@ import java.util.logging.Logger;
* @author games647
*/
@Singleton
-public class PingCountTimer extends AbsRunnable implements Listener {
+public class PingCountTimerBukkit extends AbsRunnable implements Listener {
//the server is pinging the client every 40 Ticks (2 sec) - so check it then
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/PlayerConnection.java#L178
public static final int PING_INTERVAL = 2 * 20;
- private static final boolean pingMethodAvailable;
+ private static final boolean PING_METHOD_AVAILABLE;
- private static final MethodHandle pingField;
- private static final MethodHandle getHandleMethod;
+ private static final MethodHandle PING_FIELD;
+ private static final MethodHandle GET_HANDLE_METHOD;
static {
- pingMethodAvailable = isPingMethodAvailable();
+ PING_METHOD_AVAILABLE = isPingMethodAvailable();
MethodHandle localHandle = null;
MethodHandle localPing = null;
- if (!pingMethodAvailable) {
+ if (!PING_METHOD_AVAILABLE) {
Class> craftPlayerClass = Reflection.getCraftBukkitClass("entity.CraftPlayer");
Class> entityPlayer = Reflection.getMinecraftClass("EntityPlayer");
@@ -92,8 +93,8 @@ public class PingCountTimer extends AbsRunnable implements Listener {
}
}
- getHandleMethod = localHandle;
- pingField = localPing;
+ GET_HANDLE_METHOD = localHandle;
+ PING_FIELD = localPing;
}
private final Map>> playerHistory;
@@ -103,7 +104,7 @@ public class PingCountTimer extends AbsRunnable implements Listener {
private final RunnableFactory runnableFactory;
@Inject
- public PingCountTimer(
+ public PingCountTimerBukkit(
Processors processors,
Processing processing,
RunnableFactory runnableFactory
@@ -157,7 +158,7 @@ public class PingCountTimer extends AbsRunnable implements Listener {
}
private int getPing(Player player) {
- if (pingMethodAvailable) {
+ if (PING_METHOD_AVAILABLE) {
return player.spigot().getPing();
}
@@ -166,8 +167,8 @@ public class PingCountTimer extends AbsRunnable implements Listener {
private int getReflectionPing(Player player) {
try {
- Object entityPlayer = getHandleMethod.invoke(player);
- return (int) pingField.invoke(entityPlayer);
+ Object entityPlayer = GET_HANDLE_METHOD.invoke(player);
+ return (int) PING_FIELD.invoke(entityPlayer);
} catch (Exception ex) {
return -1;
} catch (Throwable throwable) {
@@ -184,8 +185,8 @@ public class PingCountTimer extends AbsRunnable implements Listener {
if (player.isOnline()) {
addPlayer(player);
}
- }
- }).runTaskLater(TimeAmount.toTicks(15L, TimeUnit.SECONDS));
+ }// TODO Config
+ }).runTaskLater(TimeAmount.toTicks(Settings.PING_PLAYER_LOGIN_DELAY.getNumber(), TimeUnit.SECONDS));
}
@EventHandler
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimerBungee.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimerBungee.java
new file mode 100644
index 000000000..cb24e2aa5
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimerBungee.java
@@ -0,0 +1,111 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016-2018
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.djrapitops.plan.system.tasks.server;
+
+import com.djrapitops.plan.data.store.objects.DateObj;
+import com.djrapitops.plan.system.processing.Processing;
+import com.djrapitops.plan.system.processing.processors.player.PingInsertProcessor;
+import com.djrapitops.plan.system.settings.Settings;
+import com.djrapitops.plugin.api.TimeAmount;
+import com.djrapitops.plugin.task.AbsRunnable;
+import com.djrapitops.plugin.task.RunnableFactory;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.event.ServerConnectedEvent;
+import net.md_5.bungee.api.event.ServerDisconnectEvent;
+import net.md_5.bungee.api.plugin.Listener;
+import net.md_5.bungee.event.EventHandler;
+import java.util.*;
+
+/**
+ * Task that handles player ping calculation on Bungee based servers.
+ *
+ * @author BrainStone
+ */
+public class PingCountTimerBungee extends AbsRunnable implements Listener {
+
+ //the server is pinging the client every 40 Ticks (2 sec) - so check it then
+ //https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/PlayerConnection.java#L178
+ public static final int PING_INTERVAL = 2 * 20;
+
+ private final Map>> playerHistory = new HashMap<>();
+
+ @Override
+ public void run() {
+ List loggedOut = new ArrayList<>();
+ long time = System.currentTimeMillis();
+ playerHistory.forEach((uuid, history) -> {
+ ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid);
+ if (player != null) {
+ int ping = getPing(player);
+ if (ping < -1 || ping > TimeAmount.SECOND.ms() * 8L) {
+ // Don't accept bad values
+ return;
+ }
+ history.add(new DateObj<>(time, ping));
+ if (history.size() >= 30) {
+ Processing.submit(new PingInsertProcessor(uuid, new ArrayList<>(history)));
+ history.clear();
+ }
+ } else {
+ loggedOut.add(uuid);
+ }
+ });
+ loggedOut.forEach(playerHistory::remove);
+ }
+
+ public void addPlayer(ProxiedPlayer player) {
+ playerHistory.put(player.getUniqueId(), new ArrayList<>());
+ }
+
+ public void removePlayer(ProxiedPlayer player) {
+ playerHistory.remove(player.getUniqueId());
+ }
+
+ private int getPing(ProxiedPlayer player) {
+ return player.getPing();
+ }
+
+ @EventHandler
+ public void onPlayerJoin(ServerConnectedEvent joinEvent) {
+ ProxiedPlayer player = joinEvent.getPlayer();
+ RunnableFactory.createNew("Add Player to Ping list", new AbsRunnable() {
+ @Override
+ public void run() {
+ if (player.isConnected()) {
+ addPlayer(player);
+ }
+ }
+ }).runTaskLater(TimeAmount.SECOND.ticks() * (long) Settings.PING_PLAYER_LOGIN_DELAY.getNumber());
+ }
+
+ @EventHandler
+ public void onPlayerQuit(ServerDisconnectEvent quitEvent) {
+ removePlayer(quitEvent.getPlayer());
+ }
+
+ public void clear() {
+ playerHistory.clear();
+ }
+}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimerSponge.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimerSponge.java
new file mode 100644
index 000000000..cfed96452
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimerSponge.java
@@ -0,0 +1,110 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016-2018
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.djrapitops.plan.system.tasks.server;
+
+import com.djrapitops.plan.data.store.objects.DateObj;
+import com.djrapitops.plan.system.processing.Processing;
+import com.djrapitops.plan.system.processing.processors.player.PingInsertProcessor;
+import com.djrapitops.plan.system.settings.Settings;
+import com.djrapitops.plugin.api.TimeAmount;
+import com.djrapitops.plugin.task.AbsRunnable;
+import com.djrapitops.plugin.task.RunnableFactory;
+import org.spongepowered.api.Sponge;
+import org.spongepowered.api.entity.living.player.Player;
+import org.spongepowered.api.event.Listener;
+import org.spongepowered.api.event.network.ClientConnectionEvent;
+
+import java.util.*;
+
+/**
+ * Task that handles player ping calculation on Sponge based servers.
+ *
+ * @author BrainStone
+ */
+public class PingCountTimerSponge extends AbsRunnable {
+
+ //the server is pinging the client every 40 Ticks (2 sec) - so check it then
+ //https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/PlayerConnection.java#L178
+ public static final int PING_INTERVAL = 2 * 20;
+
+ private final Map>> playerHistory = new HashMap<>();
+
+ @Override
+ public void run() {
+ List loggedOut = new ArrayList<>();
+ long time = System.currentTimeMillis();
+ playerHistory.forEach((uuid, history) -> {
+ Optional player = Sponge.getServer().getPlayer(uuid);
+ if (player.isPresent()) {
+ int ping = getPing(player.get());
+ if (ping < -1 || ping > TimeAmount.SECOND.ms() * 8L) {
+ // Don't accept bad values
+ return;
+ }
+ history.add(new DateObj<>(time, ping));
+ if (history.size() >= 30) {
+ Processing.submit(new PingInsertProcessor(uuid, new ArrayList<>(history)));
+ history.clear();
+ }
+ } else {
+ loggedOut.add(uuid);
+ }
+ });
+ loggedOut.forEach(playerHistory::remove);
+ }
+
+ public void addPlayer(Player player) {
+ playerHistory.put(player.getUniqueId(), new ArrayList<>());
+ }
+
+ public void removePlayer(Player player) {
+ playerHistory.remove(player.getUniqueId());
+ }
+
+ private int getPing(Player player) {
+ return player.getConnection().getLatency();
+ }
+
+ @Listener
+ public void onPlayerJoin(ClientConnectionEvent.Join joinEvent) {
+ Player player = joinEvent.getTargetEntity();
+ RunnableFactory.createNew("Add Player to Ping list", new AbsRunnable() {
+ @Override
+ public void run() {
+ if (player.isOnline()) {
+ addPlayer(player);
+ }
+ }
+ }).runTaskLater(TimeAmount.SECOND.ticks() * (long) Settings.PING_PLAYER_LOGIN_DELAY.getNumber());
+ }
+
+ @Listener
+ public void onPlayerQuit(ClientConnectionEvent.Disconnect quitEvent) {
+ removePlayer(quitEvent.getTargetEntity());
+ }
+
+ public void clear() {
+ playerHistory.clear();
+ }
+}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimerVelocity.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimerVelocity.java
new file mode 100644
index 000000000..493940387
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/server/PingCountTimerVelocity.java
@@ -0,0 +1,113 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016-2018
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.djrapitops.plan.system.tasks.server;
+
+import com.djrapitops.plan.PlanVelocity;
+import com.djrapitops.plan.data.store.objects.DateObj;
+import com.djrapitops.plan.system.processing.Processing;
+import com.djrapitops.plan.system.processing.processors.player.PingInsertProcessor;
+import com.djrapitops.plan.system.settings.Settings;
+import com.djrapitops.plugin.api.TimeAmount;
+import com.djrapitops.plugin.task.AbsRunnable;
+import com.djrapitops.plugin.task.RunnableFactory;
+import com.velocitypowered.api.event.Subscribe;
+import com.velocitypowered.api.event.connection.DisconnectEvent;
+import com.velocitypowered.api.event.player.ServerConnectedEvent;
+import com.velocitypowered.api.proxy.Player;
+
+import java.util.*;
+
+/**
+ * Task that handles player ping calculation on Velocity based servers.
+ *
+ * Based on PingCountTimerBungee
+ *
+ * @author MicleBrick
+ */
+public class PingCountTimerVelocity extends AbsRunnable {
+
+ //the server is pinging the client every 40 Ticks (2 sec) - so check it then
+ //https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/PlayerConnection.java#L178
+ public static final int PING_INTERVAL = 2 * 20;
+
+ private final Map>> playerHistory = new HashMap<>();
+
+ @Override
+ public void run() {
+ List loggedOut = new ArrayList<>();
+ long time = System.currentTimeMillis();
+ playerHistory.forEach((uuid, history) -> {
+ Player player = PlanVelocity.getInstance().getProxy().getPlayer(uuid).orElse(null);
+ if (player != null) {
+ int ping = getPing(player);
+ if (ping < -1 || ping > TimeAmount.SECOND.ms() * 8L) {
+ // Don't accept bad values
+ return;
+ }
+ history.add(new DateObj<>(time, ping));
+ if (history.size() >= 30) {
+ Processing.submit(new PingInsertProcessor(uuid, new ArrayList<>(history)));
+ history.clear();
+ }
+ } else {
+ loggedOut.add(uuid);
+ }
+ });
+ loggedOut.forEach(playerHistory::remove);
+ }
+
+ public void addPlayer(Player player) {
+ playerHistory.put(player.getUniqueId(), new ArrayList<>());
+ }
+
+ public void removePlayer(Player player) {
+ playerHistory.remove(player.getUniqueId());
+ }
+
+ private int getPing(Player player) {
+ return (int) player.getPing();
+ }
+
+ @Subscribe
+ public void onPlayerJoin(ServerConnectedEvent joinEvent) {
+ Player player = joinEvent.getPlayer();
+ RunnableFactory.createNew("Add Player to Ping list", new AbsRunnable() {
+ @Override
+ public void run() {
+ if (player.isActive()) {
+ addPlayer(player);
+ }
+ }
+ }).runTaskLater(TimeAmount.SECOND.ticks() * (long) Settings.PING_PLAYER_LOGIN_DELAY.getNumber());
+ }
+
+ @Subscribe
+ public void onPlayerQuit(DisconnectEvent quitEvent) {
+ removePlayer(quitEvent.getPlayer());
+ }
+
+ public void clear() {
+ playerHistory.clear();
+ }
+}
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
index 0cbac21ea..c91af39ce 100644
--- 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
@@ -56,18 +56,9 @@ public class SpongeTPSCountTimer extends TPSCountTimer {
* @return the TPS
*/
private TPS calculateTPS(long now) {
- OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
- int availableProcessors = operatingSystemMXBean.getAvailableProcessors();
- double averageCPUUsage = operatingSystemMXBean.getSystemLoadAverage() / availableProcessors * 100.0;
+ double averageCPUUsage = getCPUUsage();
- if (averageCPUUsage < 0) { // If unavailable, getSystemLoadAverage() returns -1
- averageCPUUsage = -1;
- }
-
- Runtime runtime = Runtime.getRuntime();
-
- long totalMemory = runtime.totalMemory();
- long usedMemory = (totalMemory - runtime.freeMemory()) / 1000000;
+ long usedMemory = getUsedMemory();
double tps = Sponge.getGame().getServer().getTicksPerSecond();
int playersOnline = serverProperties.getOnlinePlayers();
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/tasks/velocity/VelocityTPSCountTimer.java b/Plan/src/main/java/com/djrapitops/plan/system/tasks/velocity/VelocityTPSCountTimer.java
new file mode 100644
index 000000000..2121fc14f
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/system/tasks/velocity/VelocityTPSCountTimer.java
@@ -0,0 +1,31 @@
+package com.djrapitops.plan.system.tasks.velocity;
+
+import com.djrapitops.plan.PlanVelocity;
+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;
+
+public class VelocityTPSCountTimer extends TPSCountTimer {
+
+ public VelocityTPSCountTimer(PlanVelocity plugin) {
+ super(plugin);
+ }
+
+ @Override
+ public void addNewTPSEntry(long nanoTime, long now) {
+ int onlineCount = ServerInfo.getServerProperties().getOnlinePlayers();
+ TPS tps = TPSBuilder.get()
+ .date(now)
+ .skipTPS()
+ .playersOnline(onlineCount)
+ .usedCPU(getCPUUsage())
+ .usedMemory(getUsedMemory())
+ .entities(-1)
+ .chunksLoaded(-1)
+ .toTPS();
+
+ history.add(tps);
+ latestPlayersOnline = onlineCount;
+ }
+}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/WebServer.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/WebServer.java
index 3161bc2e5..6024428b0 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/WebServer.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/WebServer.java
@@ -12,6 +12,7 @@ import com.djrapitops.plugin.api.Check;
import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.console.PluginLogger;
import com.djrapitops.plugin.logging.error.ErrorHandler;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsParameters;
@@ -29,9 +30,7 @@ import java.nio.file.Paths;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.*;
/**
* @author Rsl1122
@@ -121,7 +120,11 @@ public class WebServer implements SubSystem {
}
server.createContext("/", requestHandler);
- server.setExecutor(new ThreadPoolExecutor(4, 8, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100)));
+ ExecutorService executor = new ThreadPoolExecutor(
+ 4, 8, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100),
+ new ThreadFactoryBuilder().setNameFormat("Plan WebServer Thread-%d").build()
+ );
+ server.setExecutor(executor);
server.start();
enabled = true;
@@ -212,12 +215,26 @@ public class WebServer implements SubSystem {
@Override
public void disable() {
if (server != null) {
+ shutdown();
logger.info(locale.getString(PluginLang.DISABLED_WEB_SERVER));
- server.stop(0);
}
enabled = false;
}
+ private void shutdown() {
+ server.stop(0);
+ Executor executor = server.getExecutor();
+ if (executor instanceof ExecutorService) {
+ ExecutorService service = (ExecutorService) executor;
+ service.shutdown();
+ try {
+ service.awaitTermination(5, TimeUnit.SECONDS);
+ } catch (InterruptedException timeoutExceededEx) {
+ service.shutdownNow();
+ }
+ }
+ }
+
public String getProtocol() {
return usingHttps ? "https" : "http";
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/cache/ResponseCache.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/cache/ResponseCache.java
index 772e04180..0834953af 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/cache/ResponseCache.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/cache/ResponseCache.java
@@ -1,10 +1,11 @@
package com.djrapitops.plan.system.webserver.cache;
import com.djrapitops.plan.system.webserver.response.Response;
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
-import java.util.HashMap;
-import java.util.Map;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
/**
@@ -19,7 +20,9 @@ import java.util.function.Supplier;
*/
public class ResponseCache {
- private static final Map cache = new HashMap<>();
+ private static final Cache cache = Caffeine.newBuilder()
+ .expireAfterWrite(5, TimeUnit.MINUTES)
+ .build();
/**
* Constructor used to hide the public constructor
@@ -41,17 +44,7 @@ public class ResponseCache {
* @return The Response that was cached or created by the the {@link Response} {@link Supplier}
*/
public static Response loadResponse(String identifier, Supplier loader) {
- Response response = loadResponse(identifier);
-
- if (response != null) {
- return response;
- }
-
- response = loader.get();
-
- cache.put(identifier, response);
-
- return response;
+ return cache.get(identifier, k -> loader.get());
}
/**
@@ -61,7 +54,7 @@ public class ResponseCache {
* @return The Response that was cached or {@code null} if it wasn't
*/
public static Response loadResponse(String identifier) {
- return cache.get(identifier);
+ return cache.getIfPresent(identifier);
}
/**
@@ -84,21 +77,25 @@ public class ResponseCache {
* @return true if the page is cached
*/
public static boolean isCached(String identifier) {
- return cache.containsKey(identifier);
+ return cache.getIfPresent(identifier) != null;
}
/**
* Clears the cache from all its contents.
*/
public static void clearCache() {
- cache.clear();
+ cache.invalidateAll();
}
public static Set getCacheKeys() {
- return cache.keySet();
+ return cache.asMap().keySet();
+ }
+
+ public static long getEstimatedSize() {
+ return cache.estimatedSize();
}
public static void clearResponse(String identifier) {
- cache.remove(identifier);
+ cache.invalidate(identifier);
}
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/Response.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/Response.java
index 8a002a9d6..afc9ae30d 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/Response.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/Response.java
@@ -96,8 +96,10 @@ public abstract class Response {
}
sentContent = theme.replaceThemeColors(sentContent);
- try (GZIPOutputStream out = new GZIPOutputStream(exchange.getResponseBody());
- ByteArrayInputStream bis = new ByteArrayInputStream(sentContent.getBytes(StandardCharsets.UTF_8))) {
+ try (
+ GZIPOutputStream out = new GZIPOutputStream(exchange.getResponseBody());
+ ByteArrayInputStream bis = new ByteArrayInputStream(sentContent.getBytes(StandardCharsets.UTF_8))
+ ) {
byte[] buffer = new byte[2048];
int count;
while ((count = bis.read(buffer)) != -1) {
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 5cd3f4611..92d13e04e 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
@@ -5,7 +5,7 @@
package com.djrapitops.plan.system.webserver.response.errors;
import com.djrapitops.plan.system.file.PlanFiles;
-import com.djrapitops.plan.system.webserver.response.Response;
+import com.djrapitops.plan.system.webserver.response.pages.PageResponse;
import org.apache.commons.text.StringSubstitutor;
import java.io.IOException;
@@ -17,7 +17,7 @@ import java.util.Map;
*
* @author Rsl1122
*/
-public class ErrorResponse extends Response {
+public class ErrorResponse extends PageResponse {
private String title;
private String paragraph;
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/AnalysisPageResponse.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/AnalysisPageResponse.java
index af97a5201..38b533215 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/AnalysisPageResponse.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/AnalysisPageResponse.java
@@ -6,7 +6,7 @@ import com.djrapitops.plan.system.webserver.response.Response;
* @author Rsl1122
* @since 3.5.2
*/
-public class AnalysisPageResponse extends Response {
+public class AnalysisPageResponse extends PageResponse {
public AnalysisPageResponse(String html) {
super.setHeader("HTTP/1.1 200 OK");
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 f11f93823..abd17f53d 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
@@ -8,13 +8,14 @@ import org.apache.commons.text.StringSubstitutor;
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
import java.util.UUID;
/**
* @author Rsl1122
* @since 3.5.2
*/
-public class InspectPageResponse extends Response {
+public class InspectPageResponse extends PageResponse {
private final UUID uuid;
@@ -39,4 +40,18 @@ public class InspectPageResponse extends Response {
private String[] getCalculating() {
return new String[]{" Calculating... ", ""};
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof InspectPageResponse)) return false;
+ if (!super.equals(o)) return false;
+ InspectPageResponse that = (InspectPageResponse) o;
+ return Objects.equals(uuid, that.uuid);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), uuid);
+ }
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/NetworkPageResponse.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/NetworkPageResponse.java
index aa244a08c..7bf6d2523 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/NetworkPageResponse.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/NetworkPageResponse.java
@@ -2,6 +2,8 @@ package com.djrapitops.plan.system.webserver.response.pages;
import com.djrapitops.plan.api.exceptions.ParseException;
import com.djrapitops.plan.system.webserver.response.Response;
+import com.djrapitops.plan.data.store.containers.NetworkContainer;
+import com.djrapitops.plan.system.database.databases.Database;
import com.djrapitops.plan.utilities.html.pages.NetworkPage;
/**
@@ -9,7 +11,7 @@ import com.djrapitops.plan.utilities.html.pages.NetworkPage;
*
* @author Rsl1122
*/
-public class NetworkPageResponse extends Response {
+public class NetworkPageResponse extends PageResponse {
public NetworkPageResponse(NetworkPage networkPage) throws ParseException {
setHeader("HTTP/1.1 200 OK");
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/PageResponse.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/PageResponse.java
new file mode 100644
index 000000000..6b5ceac0e
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/PageResponse.java
@@ -0,0 +1,27 @@
+package com.djrapitops.plan.system.webserver.response.pages;
+
+import com.djrapitops.plan.system.webserver.response.Response;
+import com.djrapitops.plan.system.webserver.response.ResponseType;
+import com.googlecode.htmlcompressor.compressor.HtmlCompressor;
+
+/**
+ * Response for all HTML Page responses.
+ *
+ * @author Rsl1122
+ */
+public class PageResponse extends Response {
+
+ public PageResponse(ResponseType type) {
+ super(type);
+ }
+
+ public PageResponse() {
+ }
+
+ @Override
+ public void setContent(String content) {
+ HtmlCompressor compressor = new HtmlCompressor();
+ compressor.setRemoveIntertagSpaces(true);
+ super.setContent(compressor.compress(content));
+ }
+}
\ No newline at end of file
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 5176f2cc4..6322e9a1a 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
@@ -1,14 +1,13 @@
package com.djrapitops.plan.system.webserver.response.pages;
import com.djrapitops.plan.api.exceptions.ParseException;
-import com.djrapitops.plan.system.webserver.response.Response;
import com.djrapitops.plan.utilities.html.pages.PlayersPage;
/**
* @author Rsl1122
* @since 3.5.2
*/
-public class PlayersPageResponse extends Response {
+public class PlayersPageResponse extends PageResponse {
public PlayersPageResponse(PlayersPage playersPage) throws ParseException {
setHeader("HTTP/1.1 200 OK");
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/parts/InspectPagePluginsContent.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/parts/InspectPagePluginsContent.java
index 2c3ff5d4a..be4fee519 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/parts/InspectPagePluginsContent.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/parts/InspectPagePluginsContent.java
@@ -8,7 +8,7 @@ import com.djrapitops.plan.data.element.InspectContainer;
import com.djrapitops.plan.data.plugin.HookHandler;
import com.djrapitops.plan.data.plugin.PluginData;
import com.djrapitops.plan.system.info.server.ServerInfo;
-import com.djrapitops.plan.system.webserver.response.Response;
+import com.djrapitops.plan.system.webserver.response.pages.PageResponse;
import com.djrapitops.plan.utilities.comparators.PluginDataNameComparator;
import com.djrapitops.plan.utilities.html.Html;
import com.djrapitops.plan.utilities.html.HtmlStructure;
@@ -23,7 +23,7 @@ import java.util.*;
*
* @author Rsl1122
*/
-public class InspectPagePluginsContent extends Response {
+public class InspectPagePluginsContent extends PageResponse {
// ServerUUID, {nav, html}
private final Map pluginsTab;
diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/parts/NetworkPageContent.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/parts/NetworkPageContent.java
index 3eaa8bfb3..16999e6c3 100644
--- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/parts/NetworkPageContent.java
+++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/pages/parts/NetworkPageContent.java
@@ -4,7 +4,7 @@
*/
package com.djrapitops.plan.system.webserver.response.pages.parts;
-import com.djrapitops.plan.system.webserver.response.Response;
+import com.djrapitops.plan.system.webserver.response.pages.PageResponse;
import java.util.*;
@@ -15,7 +15,7 @@ import java.util.*;
*
* @author Rsl1122
*/
-public class NetworkPageContent extends Response {
+public class NetworkPageContent extends PageResponse {
private final Map content;
diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Median.java b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Median.java
new file mode 100644
index 000000000..92abc49cc
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/utilities/analysis/Median.java
@@ -0,0 +1,58 @@
+package com.djrapitops.plan.utilities.analysis;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Math utility for calculating the median from Integer values.
+ *
+ * @author Rsl1122
+ */
+public class Median {
+
+ private final List values;
+ private int size;
+
+ private Median(Collection values, int b) {
+ this(values.stream().map(i -> (long) i).collect(Collectors.toList()));
+ }
+
+ private Median(List values) {
+ this.values = values;
+ Collections.sort(values);
+ size = values.size();
+ }
+
+ public static Median forInt(Collection integers) {
+ return new Median(integers, 0);
+ }
+
+ public static Median forLong(List longs) {
+ return new Median(longs);
+ }
+
+ public double calculate() {
+ if (values.isEmpty()) {
+ return -1;
+ }
+ if (size % 2 == 0) {
+ return calculateEven();
+ } else {
+ return calculateOdd();
+ }
+ }
+
+ private double calculateEven() {
+ int half = size / 2;
+ double x1 = values.get(half);
+ double x2 = values.get(half - 1);
+ return (x1 + x2) / 2;
+ }
+
+ private double calculateOdd() {
+ int half = size / 2;
+ return (double) values.get(half);
+ }
+}
\ No newline at end of file
diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/formatting/time/TimeAmountFormatter.java b/Plan/src/main/java/com/djrapitops/plan/utilities/formatting/time/TimeAmountFormatter.java
index 0b82af52f..872229e08 100644
--- a/Plan/src/main/java/com/djrapitops/plan/utilities/formatting/time/TimeAmountFormatter.java
+++ b/Plan/src/main/java/com/djrapitops/plan/utilities/formatting/time/TimeAmountFormatter.java
@@ -65,20 +65,13 @@ public class TimeAmountFormatter implements Formatter {
return formattedTime;
}
- private void appendSeconds(StringBuilder builder, long seconds, long minutes, long hours, String fHours, String fMinutes, String fSeconds) {
- if (seconds != 0) {
- String s = fSeconds.replace(SECONDS_PH, String.valueOf(seconds));
- if (minutes == 0 && s.contains(MINUTES_PH)) {
- if (hours == 0 && fMinutes.contains(HOURS_PH)) {
- builder.append(fHours.replace(ZERO_PH, "0").replace(HOURS_PH, "0"));
- }
- builder.append(fMinutes.replace(HOURS_PH, "").replace(ZERO_PH, "0").replace(MINUTES_PH, "0"));
- }
- s = s.replace(MINUTES_PH, "");
- if (s.contains(ZERO_PH) && String.valueOf(seconds).length() == 1) {
+ private void appendHours(StringBuilder builder, long hours, String fHours) {
+ if (hours != 0) {
+ String h = fHours.replace(HOURS_PH, String.valueOf(hours));
+ if (h.contains(ZERO_PH) && String.valueOf(hours).length() == 1) {
builder.append('0');
}
- builder.append(s);
+ builder.append(h);
}
}
@@ -97,13 +90,20 @@ public class TimeAmountFormatter implements Formatter {
}
}
- private void appendHours(StringBuilder builder, long hours, String fHours) {
- if (hours != 0) {
- String h = fHours.replace(HOURS_PH, String.valueOf(hours));
- if (h.contains(ZERO_PH) && String.valueOf(hours).length() == 1) {
+ private void appendSeconds(StringBuilder builder, long seconds, long minutes, long hours, String fHours, String fMinutes, String fSeconds) {
+ if (seconds != 0 || fSeconds.contains(ZERO_PH)) {
+ String s = fSeconds.replace(SECONDS_PH, String.valueOf(seconds));
+ if (minutes == 0 && s.contains(MINUTES_PH)) {
+ if (hours == 0 && fMinutes.contains(HOURS_PH)) {
+ builder.append(fHours.replace(ZERO_PH, "0").replace(HOURS_PH, "0"));
+ }
+ builder.append(fMinutes.replace(HOURS_PH, "").replace(ZERO_PH, "0").replace(MINUTES_PH, "0"));
+ }
+ s = s.replace(MINUTES_PH, "");
+ if (s.contains(ZERO_PH) && String.valueOf(seconds).length() == 1) {
builder.append('0');
}
- builder.append(h);
+ builder.append(s);
}
}
diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/html/graphs/ProgressBar.java b/Plan/src/main/java/com/djrapitops/plan/utilities/html/graphs/ProgressBar.java
new file mode 100644
index 000000000..a29ebc932
--- /dev/null
+++ b/Plan/src/main/java/com/djrapitops/plan/utilities/html/graphs/ProgressBar.java
@@ -0,0 +1,39 @@
+package com.djrapitops.plan.utilities.html.graphs;
+
+import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
+
+/**
+ * Utility for creating ProgressBars.
+ *
+ * @author Rsl1122
+ */
+public class ProgressBar {
+
+ private final int obtained;
+ private final int max;
+
+ private final String color;
+
+ public ProgressBar(int obtained, int max) {
+ this(obtained, max, "teal");
+ }
+
+ public ProgressBar(int obtained, int max, String color) {
+ this.obtained = obtained;
+ this.max = max;
+ this.color = color;
+ }
+
+ public String toHtml() {
+ double percentage = obtained * 1.0 / max;
+ int percentageRounded = (int) percentage;
+
+ return "" +
+ obtained + " / " + max + " (" + Formatters.percentage().apply(percentage) + ")" +
+ "
";
+ }
+
+}
\ No newline at end of file
diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/html/pages/NetworkPage.java b/Plan/src/main/java/com/djrapitops/plan/utilities/html/pages/NetworkPage.java
index 5ea0ce2e5..0f46ab045 100644
--- a/Plan/src/main/java/com/djrapitops/plan/utilities/html/pages/NetworkPage.java
+++ b/Plan/src/main/java/com/djrapitops/plan/utilities/html/pages/NetworkPage.java
@@ -10,6 +10,7 @@ import com.djrapitops.plan.data.store.keys.NetworkKeys;
import com.djrapitops.plan.system.file.PlanFiles;
import com.djrapitops.plan.system.info.server.properties.ServerProperties;
import com.djrapitops.plan.utilities.formatting.PlaceholderReplacer;
+import com.djrapitops.plan.utilities.html.structure.AnalysisPluginsTabContentCreator;
import static com.djrapitops.plan.data.store.keys.NetworkKeys.*;
@@ -55,6 +56,14 @@ public class NetworkPage implements Page {
SERVERS_TAB
);
+ // TODO Fix
+ String[] content = AnalysisPluginsTabContentCreator.createContent(networkContainer.getUnsafe(NetworkKeys.PLAYERS_MUTATOR), null);
+ String nav = content[0];
+ String tabs = content[1];
+
+ placeholderReplacer.put("navPluginsTabs", nav);
+ placeholderReplacer.put("tabsPlugins", tabs);
+
return placeholderReplacer.apply(files.readCustomizableResourceFlat("web/network.html"));
} catch (Exception e) {
throw new ParseException(e);
diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/html/structure/AnalysisPluginsTabContentCreator.java b/Plan/src/main/java/com/djrapitops/plan/utilities/html/structure/AnalysisPluginsTabContentCreator.java
index 0bcfd3e1e..c63e4b220 100644
--- a/Plan/src/main/java/com/djrapitops/plan/utilities/html/structure/AnalysisPluginsTabContentCreator.java
+++ b/Plan/src/main/java/com/djrapitops/plan/utilities/html/structure/AnalysisPluginsTabContentCreator.java
@@ -55,7 +55,7 @@ public class AnalysisPluginsTabContentCreator {
com.djrapitops.plan.data.store.containers.AnalysisContainer analysisContainer
) {
PlayersMutator mutator = analysisContainer.getValue(AnalysisKeys.PLAYERS_MUTATOR).orElse(new PlayersMutator(new ArrayList<>()));
-
+
if (mutator.all().isEmpty()) {
return new String[]{"No Data ", ""};
}
@@ -143,6 +143,7 @@ public class AnalysisPluginsTabContentCreator {
errorHandler.log(L.WARN, this.getClass(), e);
} finally {
timings.end(DebugChannels.ANALYSIS, "Source " + source.getSourcePlugin());
+ source.setAnalysisData(null);
}
});
return containers;
diff --git a/Plan/src/main/resources/bungee.yml b/Plan/src/main/resources/bungee.yml
index 3d5049815..b165e7633 100644
--- a/Plan/src/main/resources/bungee.yml
+++ b/Plan/src/main/resources/bungee.yml
@@ -1,4 +1,9 @@
name: Plan
author: Rsl1122
main: com.djrapitops.plan.PlanBungee
-version: 4.4.3
\ No newline at end of file
+version: 4.4.7
+softdepend:
+- AdvancedBan
+- LiteBans
+- LuckPerms
+- ViaVersion
\ No newline at end of file
diff --git a/Plan/src/main/resources/bungeeconfig.yml b/Plan/src/main/resources/bungeeconfig.yml
index f7bb88844..c59c5cb6a 100644
--- a/Plan/src/main/resources/bungeeconfig.yml
+++ b/Plan/src/main/resources/bungeeconfig.yml
@@ -66,6 +66,9 @@ Data:
LogUnknownCommands: false
CombineCommandAliases: true
Geolocations: true
+ Ping:
+ ServerEnableDelaySeconds: 300
+ PlayerLoginDelaySeconds: 30
KeepInactivePlayerDataForDays: 180
# -----------------------------------------------------
Customization:
@@ -144,4 +147,9 @@ Servers:
Example:
WebServerPort: 8034
ServerName: Example
- ThemeBase: Default
\ No newline at end of file
+ ThemeBase: Default
+# -----------------------------------------------------
+Plugins:
+ BuyCraft:
+ # http://help.buycraft.net/article/36-where-to-find-the-secret-key
+ Secret: "-"
\ No newline at end of file
diff --git a/Plan/src/main/resources/config.yml b/Plan/src/main/resources/config.yml
index f8e27d9ed..0344bb904 100644
--- a/Plan/src/main/resources/config.yml
+++ b/Plan/src/main/resources/config.yml
@@ -80,6 +80,9 @@ Data:
LogUnknownCommands: false
CombineCommandAliases: true
Geolocations: true
+ Ping:
+ ServerEnableDelaySeconds: 300
+ PlayerLoginDelaySeconds: 30
KeepInactivePlayerDataForDays: 180
# -----------------------------------------------------
Customization:
diff --git a/Plan/src/main/resources/locale/locale_DE.txt b/Plan/src/main/resources/locale/locale_DE.txt
index 5e0c30a3e..26a694b20 100644
--- a/Plan/src/main/resources/locale/locale_DE.txt
+++ b/Plan/src/main/resources/locale/locale_DE.txt
@@ -17,10 +17,10 @@ Cmd Header - Players || > §2Spieler
Cmd Header - Search || > §2${0} Ergebnisse für §f${1}§2:
Cmd Header - Servers || > §2Server
Cmd Header - Web Users || > §2${0} Accounts
-Cmd Info - Bungee Connection || §2Verbuunden mit Bungee: §f${0}
+Cmd Info - Bungee Connection || §2Verbunden mit Bungee: §f${0}
Cmd Info - Database || §2Genutzte Datenbank: §f${0}
Cmd Info - Reload Complete || §aReload erfolgreich.
-Cmd Info - Reload Failed || §cBeim Reload ist etwas schief gelaufen, ein Neustart wird empfohlen.
+Cmd Info - Reload Failed || §cBeim Reload ist etwas schief gelaufen. Es wird empfohlen, den Server neuzustarten.
Cmd Info - Update || §2Update verfügbar: §f${0}
Cmd Info - Version || §2Version: §f${0}
Cmd Notify - No WebUser || Möglicherweise hast du keinen Account. Erstelle einen mit /plan register
@@ -29,58 +29,58 @@ Cmd Qinspect - Activity Index || §2Aktivitätsindex: §f${0
Cmd Qinspect - Deaths || §2Tode: §f${0}
Cmd Qinspect - Geolocation || §2Eingeloggt aus: §f${0}
Cmd Qinspect - Last Seen || §2Zuletzt gesehen: §f${0}
-Cmd Qinspect - Longest Session || §2Längste Sitzung: §f${0}
+Cmd Qinspect - Longest Session || §2Längste Session: §f${0}
Cmd Qinspect - Mob Kills || §2Getötete Mobs: §f${0}
Cmd Qinspect - Player Kills || §2Getötete Spieler: §f${0}
Cmd Qinspect - Playtime || §Spielzeit: §f${0}
Cmd Qinspect - Registered || §2Registrierung: §f${0}
Cmd Qinspect - Times Kicked || §2Kicks: §f${0}
-Cmd Setup - Allowed || §aSet-up ist nun erlaubt.
-Cmd Setup - Bad Request || §eVerbindung hergestellt, der empfangende Server ist kein Bungee-Server. Nutze stattdessen die Bungee-Adresse.
-Cmd Setup - Disallowed || §cSet-up ist nun nicht mehr erlaubt.
-Cmd Setup - Forbidden || §eVerbindung hergestellt, aber der Bungee-Server hat den Set-up-Modus ausgeschaltet - nutze '/planbungee setup' um ihn zu aktivieren.
-Cmd Setup - Gateway Error || §eVerbindung hergestellt, aber der Bungee-Server konnte sich nicht mit diesem Server verbinden (Wurde der aktuelle Server neugestartet?). Nutze /plan m con & /planbungee con zum debuggen.
+Cmd Setup - Allowed || §aSetupmodus wurde aktiviert.
+Cmd Setup - Bad Request || §eVerbindung hergestellt. Der empfangende Server ist kein Bungeecordserver. Nutze stattdessen die Bungeecord-Adresse.
+Cmd Setup - Disallowed || §cSet-up wurde deaktiviert.
+Cmd Setup - Forbidden || §eVerbindung hergestellt aber der Bungeecordserver hat den Setupmodus nicht aktiviert. Nutze '/planbungee setup' um ihn zu aktivieren.
+Cmd Setup - Gateway Error || §eVerbindung hergestellt, aber der Bungeecordserver konnte sich nicht mit diesem Server verbinden (Wurde der aktuelle Server neugestartet?). Nutze /plan m con & /planbungee con zum debuggen.
Cmd Setup - Generic Fail || §eVerbindung fehlgeschlagen: ${0}
-Cmd Setup - Internal Error || §eVerbindung hergestellt. ${0}, eventuelle Fehler kannst du dem Error-Log auf der Debugseite des empfangenden Servers einsehen.
+Cmd Setup - Internal Error || §eVerbindung hergestellt. ${0}, eventuelle Fehler kannst du dem Error-Log auf der Debugseite des empfangenden Servers entnehmen.
Cmd Setup - Success || §aVerbindung erfolgreich, Plan startet eventuell in ein paar Sekunden neu.
Cmd Setup - Unauthorized || §eVerbindung erfolgreich, aber der empfangende Server hat diesen Server nicht autorisiert. Auf dem Plan-Discord bekommst du Hilfe.
Cmd Setup - Url mistake || §cNutze die gesamte Adresse (Beginnend mit http:// oder https://) - Diese kannst du dem Bungee enable log entnehmen.
Cmd Setup - WebServer not Enabled || §cWebServer ist auf diesem Server deaktiviert! Dies sollte beim Start aktiviert werden!
-Cmd SUCCESS - Feature disabled || §a'${0}' wurde bist zum nächsten Reload des Plugins deaktiviert.
+Cmd SUCCESS - Feature disabled || §a'${0}' wurde bis zum nächsten Reload des Plugins deaktiviert.
Cmd SUCCESS - WebUser register || §aNeuer Account (${0}) erfolgreich hinzugefügt!
-Cmd Update - Cancel Success || §aAbbruch erfolgreich.
+Cmd Update - Cancel Success || §aErfolgreich abgebrochen.
Cmd Update - Cancelled || §cUpdate abgebrochen.
Cmd Update - Change log || Change Log v${0}:
-Cmd Update - Fail Cacnel || §cAuf einem Server war das Update nicht erfolgreich, breche auf allen anderen Servern die Updates ab...
+Cmd Update - Fail Cacnel || §cAuf einem Server war das Update nicht erfolgreich. Das Update wird auf allen Servern abgebrochen
Cmd Update - Fail Force Notify || §e${0} wurde nicht geupdated, -force wurde angegeben, fahre mit Updates fort.
-Cmd Update - Fail Not Online || §cNicht alle Server sind online oder erreichbar, erreichbare Server kannst du mit /plan update -u -force updaten
-Cmd Update - Notify Cancel || §aDu kannst das Update auf Servern, die noch nicht neugestartet wurden verwerfen mit: /plan update cancel.
-Cmd Update - Online Check || Überprüfe, ob alle Server online sind.
+Cmd Update - Fail Not Online || §cNicht alle Server sind online oder erreichbar. Erreichbare Server kannst du mit /plan update -u -force updaten
+Cmd Update - Notify Cancel || §aDu kannst das Update auf Servern, die noch nicht neugestartet wurden, verwerfen mit: /plan update cancel.
+Cmd Update - Online Check || Überprüfe ob alle Server online sind.
Cmd Update - Scheduled || §aUpdate für ${0} geplant.
Cmd Update - Url mismatch || §cDie Download-URL beginnt nicht mit ${0} und ist evtl. nicht vertrauenswürdig. Du kannst diese Version manuell hier downloaden (direkter Download):
Cmd Web - Permission Levels || >\§70: Zugriff auf alle Seiten\§71: Zugriff auf '/players' Und alle Spielerseiten\§72: Zugriff auf alle Spielerseiten mit dem gleichen Username wie der Web-Account\§73+: Keine Berechtigung
Command Help - /plan analyze || Server-Ãœbersicht
Command Help - /plan dev || Entwicklungsmodus-Befehl
-Command Help - /plan help || Zeigt eine Befehlsliste
-Command Help - /plan info || Zeigt die Version von Plan
-Command Help - /plan inspect || Zeigt eine Spielerseite
+Command Help - /plan help || Zeigt eine Befehlsliste an
+Command Help - /plan info || Zeigt die Version von Plan an
+Command Help - /plan inspect || Zeigt eine Spielerseite an
Command Help - /plan manage || Verwaltet die Plan-Datenbank
Command Help - /plan manage backup || Erstellt ein Backup der Datenbank
-Command Help - /plan manage clear || Leer die Datenbank
+Command Help - /plan manage clear || Datenbank leeren
Command Help - /plan manage con || Debug Server-Bungee Verbindungen
Command Help - /plan manage disable || Schalte eine Funktion temporär aus
Command Help - /plan manage hotswap || Ändere die Datenbank schnell
-Command Help - /plan manage import || Importiere Daten
-Command Help - /plan manage move || Bewege die Daten zwischen Datenbanken
+Command Help - /plan manage import || Daten importieren
+Command Help - /plan manage move || Bewege die Daten zwischen den Datenbanken
Command Help - /plan manage remove || Entferne die Daten eines Spielers
Command Help - /plan manage restore || Spiele ein Backup ein
Command Help - /plan manage setup || Stelle die Server-Bungee-Verbindung her
Command Help - /plan network || Netzwerk-Seite
Command Help - /plan players || Spieler-Seite
-Command Help - /plan qinspect || Zeige Spielerinfo im Spiel
+Command Help - /plan qinspect || Zeigt die Spielerinfo im Spiel
Command Help - /plan register || Registriere einen Account
-Command Help - /plan reload || Starte Plan neu
-Command Help - /plan search || Suche nach einem Spieler
+Command Help - /plan reload || Plan neuladen
+Command Help - /plan search || Nach einem Spieler suchen
Command Help - /plan servers || Liste die Server in der Datenbank auf
Command Help - /plan update || Zeige das Änderungsprotokoll oder update den Server
Command Help - /plan web check || Infos über einen Account
@@ -92,11 +92,11 @@ Command Help - /planbungee con || Debug Bungee-Server Verbindun
Command Help - /planbungee disable || Deaktiviert das Plugin temporär
Command Help - /planbungee setup || Schaltet Setup-Modus an oder aus
Database - Apply Patch || Wende Patch an: ${0}..
-Database - Patches Applied || Alle Datenbankpatches wurden erfolgreich angewandt.
-Database - Patches Applied Already || Alle Datenbankpatches wurden bereits angewandt.
+Database - Patches Applied || Alle Datenbankpatches wurden erfolgreich angewendet.
+Database - Patches Applied Already || Alle Datenbankpatches wurden bereits angewendet.
Database MySQL - Launch Options Error || Startoptionen sind falsch, nutze Voreinstellungen (${0})
Database Notify - Clean || Daten von ${0} Spielern gelöscht.
-Database Notify - SQLite No WAL || SQLite WAL auf dieser Serverversion nicht unterstützt, nutze Voreinstellungen. Dies beeinträchtigt möglicherweise die Serverperformance.
+Database Notify - SQLite No WAL || SQLite WAL wird auf dieser Serverversion nicht unterstützt, nutze Voreinstellungen. Dies beeinträchtigt möglicherweise die Serverperformance.
Disable || Player Analytics ausgeschaltet.
Disable - Processing || Verarbeite kritische unverarbeitete Aufgaben. (${0})
Disable - Processing Complete || Verarbeitung komplett.
@@ -104,15 +104,15 @@ Disable - WebServer || Webserver deaktiviert.
Enable || Player Analytics angeschaltet.
Enable - Database || ${0}-dDatenbankverbindung hergestellt.
Enable - Notify Address Confirmation || Versichere dich, dass die Adresse auf DIESEN Server verweist: ${0}
-Enable - Notify Empty IP || IP in der server.properties ist leer & AlternativeIP ist nicht in Verwendung. Falsche Links werden verwendet!
+Enable - Notify Empty IP || IP in der server.properties ist leer & AlternativeIP ist nicht in Verwendung. Es werden falsche Links verwendet!
Enable - Notify Geolocations disabled || Geolocation wird nicht aufgezeichnet (Data.Geolocations: false)
-Enable - Notify Geolocations Internet Required || Plan braucht Internetzugang um die GeoLite2 Geolocation Datenbank runterzuladen.
-Enable - Notify Webserver disabled || WebServer wurde nicht initialisiert. (WebServer.DisableWebServer: true)
+Enable - Notify Geolocations Internet Required || Plan braucht einen Internetzugang um die GeoLite2 Geolocation Datenbank runterzuladen.
+Enable - Notify Webserver disabled || WebServer wurde nicht geladen. (WebServer.DisableWebServer: true)
Enable - WebServer || Webserver läuft auf PORT ${0} (${1})
Enable FAIL - Database || ${0}-Datenbankverbindung fehlgeschlagen: ${1}
-Enable FAIL - Database Patch || Datenbank-Patch ist fehlgeschlagen, Plugin wurde deaktiviert. Bitte melde dies.
+Enable FAIL - Database Patch || Datenbank-Patch ist fehlgeschlagen. Plugin wurde deaktiviert. Wir bitten dich, uns diesen Vorfall mitzuteilen.
Enable FAIL - GeoDB Write || Etwas ist beim Speichern der GeoLite2 Geolocation Datenbank fehlgeschlagen
-Enable FAIL - WebServer (Bungee) || Webserver ist nicht initialisiert!
+Enable FAIL - WebServer (Bungee) || Webserver ist nicht geladen
Enable FAIL - Wrong Database Type || ${0} ist keine gültige Datenbank
HTML - ACTIVITY_INDEX || Aktivitätsindex
HTML - ALL || Gesamt
@@ -166,7 +166,7 @@ HTML - NAV_COMMAND_USAGE || Befehlsverwendung
HTML - NAV_GEOLOCATIONS || Geolocations
HTML - NAV_INFORMATION || Information
HTML - NAV_NETWORK_PLAYERS || Netzwerk Spieler
-HTML - NAV_ONLINE_ACTIVITY || Online Aktivität
+HTML - NAV_ONLINE_ACTIVITY || Onlineaktivität
HTML - NAV_OVERVIEW || Ãœbersicht
HTML - NAV_PERFORMANCE || Performance
HTML - NAV_PLAYERS || Spieler
@@ -205,7 +205,7 @@ HTML - PUNCHCARD || LOCHKARTE
HTML - RECENT_LOGINS || Letzte LOGINS
HTML - REGISTERED || REGISTRIERT
HTML - REGISTERED_TEXT || Registriert
-HTML - REGULAR || REGELMÄSSIG
+HTML - REGULAR || REGELMÄSSIGE
HTML - SEEN_NICKNAMES || Registrierte Nicknames
HTML - SERVER || Server
HTML - SERVER_ANALYSIS || Server Analyse
@@ -221,8 +221,8 @@ HTML - SESSIONS || Sessions
HTML - TIME || Zeit
HTML - TIMES_KICKED || Mal gekickt
HTML - TIMES_USED || Mal benutzt
-HTML - TOTAL_ACTIVE_TEXT || Gesamt Aktiv
-HTML - TOTAL_AFK || Gesamt AFK
+HTML - TOTAL_ACTIVE_TEXT || Gesamte Aktive Spielzeit
+HTML - TOTAL_AFK || Gesamte AFK-Zeit
HTML - TOTAL_PLAYERS || Gesamte Spieler
HTML - TOTAL_PLAYTIME || Gesamte Spielzeit
HTML - UNIQUE || EINZIGARTIG
@@ -252,7 +252,7 @@ HTML ERRORS - NOT_FOUND_404 || Nicht gefunden.
HTML ERRORS - NOT_PLAYED_404 || Der Spieler war nie auf dem Server.
HTML ERRORS - PAGE_NOT_FOUND_404 || Diese Seite existiert nicht.
HTML ERRORS - UNAUTHORIZED_401 || Unautorisiert
-HTML ERRORS - UNKNOWN_PAGE_404 || Stelle sicher, dass du einen Link benutzt, der von einem Command generiert wurde. Beispielsweise:
/player/PlayerName /server/ServerName
+HTML ERRORS - UNKNOWN_PAGE_404 || Stelle sicher, dass du einen Link benutzt, der von einem Befehl generiert wurde. Beispielsweise:
/player/PlayerName /server/ServerName
HTML ERRORS - UUID_404 || Die UUID des Spielers wurde nicht in der Datenbank gefunden.
In Depth Help - /plan ? || > §2Hauptbefehl\ Zugriff auf Unterbefehle und Hilfe\ §2/plan §fListe Unterbefehle\ §2/plan ? §fAusführliche Hilfe
In Depth Help - /plan analyze ? || > §2Analysebefehl\ Aktualisiert die Serverseite und stellt einen Zugriffslink bereit.
diff --git a/Plan/src/main/resources/plugin.yml b/Plan/src/main/resources/plugin.yml
index 196fb25b3..f83a18fa4 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.4.3
+version: 4.4.7
softdepend:
- EssentialsX
- Towny
@@ -20,6 +20,8 @@ softdepend:
- Kingdoms
- RedProtect
- AdvancedBan
+- LuckPerms
+- DiscordSRV
commands:
plan:
@@ -51,13 +53,13 @@ permissions:
plan.?:
description: Help command
default: true
- plan.inspect:
+ plan.inspect.base:
description: Allows you to check your player data.
default: true
plan.inspect.other:
description: Allows you to check other players' player data.
default: op
- plan.qinspect:
+ plan.qinspect.base:
description: Allows you to check your player data.
default: op
plan.qinspect.other:
@@ -88,13 +90,13 @@ permissions:
default: op
plan.webmanage:
description: Manage the webusers, delete, list, check
- default: op;
+ default: op
plan.basic:
children:
plan.?: true
- plan.inspect: true
- plan.qinspect: true
+ plan.inspect.base: true
+ plan.qinspect.base: true
plan.advanced:
childer:
plan.basic: true
diff --git a/Plan/src/main/resources/web/network.html b/Plan/src/main/resources/web/network.html
index 77dfe6b25..869b50233 100644
--- a/Plan/src/main/resources/web/network.html
+++ b/Plan/src/main/resources/web/network.html
@@ -130,6 +130,15 @@
Network Players
+
+
+
+
@@ -487,6 +496,7 @@
+ ${tabsPlugins}
diff --git a/Plan/src/main/resources/web/server.html b/Plan/src/main/resources/web/server.html
index 17a79e9e8..5438fa41a 100644
--- a/Plan/src/main/resources/web/server.html
+++ b/Plan/src/main/resources/web/server.html
@@ -1148,9 +1148,9 @@
-
-
-
+
+
+
diff --git a/Plan/src/test/java/com/djrapitops/plan/data/store/mutators/formatting/TimeAmountFormatterDefaultTest.java b/Plan/src/test/java/com/djrapitops/plan/data/store/mutators/formatting/TimeAmountFormatterDefaultTest.java
new file mode 100644
index 000000000..236388d4d
--- /dev/null
+++ b/Plan/src/test/java/com/djrapitops/plan/data/store/mutators/formatting/TimeAmountFormatterDefaultTest.java
@@ -0,0 +1,130 @@
+package com.djrapitops.plan.data.store.mutators.formatting;
+
+import com.djrapitops.plan.system.settings.Settings;
+import com.djrapitops.plugin.api.TimeAmount;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import utilities.Teardown;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test class for {@link TimeAmountFormatter} that checks extra zeros config example.
+ *
+ * @author Rsl1122
+ */
+public class TimeAmountFormatterDefaultTest {
+
+ private TimeAmountFormatter timeAmountFormatter;
+
+ @BeforeClass
+ public static void setUpClass() {
+ Settings.FORMAT_YEAR.setTemporaryValue("1 year, ");
+ Settings.FORMAT_YEARS.setTemporaryValue("%years% years, ");
+ Settings.FORMAT_MONTH.setTemporaryValue("1 month, ");
+ Settings.FORMAT_MONTHS.setTemporaryValue("%months% months, ");
+ Settings.FORMAT_DAY.setTemporaryValue("1d ");
+ Settings.FORMAT_DAYS.setTemporaryValue("%days%d ");
+ Settings.FORMAT_HOURS.setTemporaryValue("%hours%h ");
+ Settings.FORMAT_MINUTES.setTemporaryValue("%minutes%m ");
+ Settings.FORMAT_SECONDS.setTemporaryValue("%seconds%s");
+ Settings.FORMAT_ZERO_SECONDS.setTemporaryValue("0s");
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ Teardown.resetSettingsTempValues();
+ }
+
+ @Before
+ public void setUp() {
+ timeAmountFormatter = new TimeAmountFormatter();
+ }
+
+ @Test
+ public void exampleOne() {
+ String expected = "1 year, 1 month, 5d 12h 30m 20s";
+
+ long ms = TimeAmount.DAY.ms() * 400L +
+ TimeAmount.HOUR.ms() * 12L +
+ TimeAmount.MINUTE.ms() * 30L +
+ TimeAmount.SECOND.ms() * 20L;
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void exampleTwo() {
+ String expected = "1 year, 1 month, 5d ";
+
+ long ms = TimeAmount.DAY.ms() * 400L;
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void exampleThree() {
+ String expected = "12h 20s";
+
+ long ms = TimeAmount.HOUR.ms() * 12L +
+ TimeAmount.SECOND.ms() * 20L;
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void exampleFour() {
+ String expected = "30m ";
+
+ long ms = TimeAmount.MINUTE.ms() * 30L;
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void exampleFive() {
+ String expected = "20s";
+
+ long ms = TimeAmount.SECOND.ms() * 20L;
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void exampleZero() {
+ String expected = "-";
+
+ long ms = 0L;
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void exampleOneSecond() {
+ String expected = "1s";
+
+ long ms = TimeAmount.SECOND.ms();
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void exampleOneMinute() {
+ String expected = "1m ";
+
+ long ms = TimeAmount.MINUTE.ms();
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+}
\ No newline at end of file
diff --git a/Plan/src/test/java/com/djrapitops/plan/data/store/mutators/formatting/TimeAmountFormatterExtraZerosTest.java b/Plan/src/test/java/com/djrapitops/plan/data/store/mutators/formatting/TimeAmountFormatterExtraZerosTest.java
new file mode 100644
index 000000000..7971d5d9f
--- /dev/null
+++ b/Plan/src/test/java/com/djrapitops/plan/data/store/mutators/formatting/TimeAmountFormatterExtraZerosTest.java
@@ -0,0 +1,130 @@
+package com.djrapitops.plan.data.store.mutators.formatting;
+
+import com.djrapitops.plan.system.settings.Settings;
+import com.djrapitops.plugin.api.TimeAmount;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import utilities.Teardown;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test class for {@link TimeAmountFormatter} that checks extra zeros config example.
+ *
+ * @author Rsl1122
+ */
+public class TimeAmountFormatterExtraZerosTest {
+
+ private TimeAmountFormatter timeAmountFormatter;
+
+ @BeforeClass
+ public static void setUpClass() {
+ Settings.FORMAT_YEAR.setTemporaryValue("1 year, ");
+ Settings.FORMAT_YEARS.setTemporaryValue("%years% years, ");
+ Settings.FORMAT_MONTH.setTemporaryValue("1 month, ");
+ Settings.FORMAT_MONTHS.setTemporaryValue("%months% months, ");
+ Settings.FORMAT_DAY.setTemporaryValue("1d ");
+ Settings.FORMAT_DAYS.setTemporaryValue("%days%d ");
+ Settings.FORMAT_HOURS.setTemporaryValue("%zero%%hours%:");
+ Settings.FORMAT_MINUTES.setTemporaryValue("%hours%%zero%%minutes%:");
+ Settings.FORMAT_SECONDS.setTemporaryValue("%minutes%%zero%%seconds%");
+ Settings.FORMAT_ZERO_SECONDS.setTemporaryValue("00:00:00");
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ Teardown.resetSettingsTempValues();
+ }
+
+ @Before
+ public void setUp() {
+ timeAmountFormatter = new TimeAmountFormatter();
+ }
+
+ @Test
+ public void exampleOne() {
+ String expected = "1 year, 1 month, 5d 12:30:20";
+
+ long ms = TimeAmount.DAY.ms() * 400L +
+ TimeAmount.HOUR.ms() * 12L +
+ TimeAmount.MINUTE.ms() * 30L +
+ TimeAmount.SECOND.ms() * 20L;
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void exampleTwo() {
+ String expected = "1 year, 1 month, 5d 00:00:00";
+
+ long ms = TimeAmount.DAY.ms() * 400L;
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void exampleThree() {
+ String expected = "12:00:20";
+
+ long ms = TimeAmount.HOUR.ms() * 12L +
+ TimeAmount.SECOND.ms() * 20L;
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void exampleFour() {
+ String expected = "00:30:00";
+
+ long ms = TimeAmount.MINUTE.ms() * 30L;
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void exampleFive() {
+ String expected = "00:00:20";
+
+ long ms = TimeAmount.SECOND.ms() * 20L;
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void exampleZero() {
+ String expected = "-";
+
+ long ms = 0L;
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void exampleOneSecond() {
+ String expected = "00:00:01";
+
+ long ms = TimeAmount.SECOND.ms();
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void exampleOneMinute() {
+ String expected = "00:01:00";
+
+ long ms = TimeAmount.MINUTE.ms();
+ String result = timeAmountFormatter.apply(ms);
+
+ assertEquals(expected, result);
+ }
+
+}
\ No newline at end of file
diff --git a/Plan/src/test/java/com/djrapitops/plan/system/cache/SessionCacheTest.java b/Plan/src/test/java/com/djrapitops/plan/system/cache/SessionCacheTest.java
index 1a27c5f90..a10fa50ad 100644
--- a/Plan/src/test/java/com/djrapitops/plan/system/cache/SessionCacheTest.java
+++ b/Plan/src/test/java/com/djrapitops/plan/system/cache/SessionCacheTest.java
@@ -2,10 +2,7 @@ package com.djrapitops.plan.system.cache;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.system.database.databases.Database;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
+import org.junit.*;
import org.junit.rules.TemporaryFolder;
import utilities.TestConstants;
import utilities.mocks.SystemMockUtil;
@@ -40,6 +37,11 @@ public class SessionCacheTest {
sessionCache.cacheSession(uuid, session);
}
+ @After
+ public void tearDown() {
+ SessionCache.clear();
+ }
+
@Test
public void testAtomity() {
SessionCache reloaded = new SessionCache(database);
@@ -47,4 +49,16 @@ public class SessionCacheTest {
assertTrue(cachedSession.isPresent());
assertEquals(session, cachedSession.get());
}
+
+ @Test
+ public void testBungeeReCaching() {
+ SessionCache cache = new ProxyDataCache(null, null);
+ cache.cacheSession(uuid, session);
+ Session expected = new Session(uuid, TestConstants.SERVER_UUID, 0, "", "");
+ cache.cacheSession(uuid, expected);
+
+ Optional result = SessionCache.getCachedSession(uuid);
+ assertTrue(result.isPresent());
+ assertEquals(expected, result.get());
+ }
}
\ No newline at end of file
diff --git a/Plan/src/test/java/com/djrapitops/plan/system/listeners/bukkit/AFKListenerTest.java b/Plan/src/test/java/com/djrapitops/plan/system/listeners/bukkit/AFKListenerTest.java
new file mode 100644
index 000000000..3461abcf4
--- /dev/null
+++ b/Plan/src/test/java/com/djrapitops/plan/system/listeners/bukkit/AFKListenerTest.java
@@ -0,0 +1,67 @@
+package com.djrapitops.plan.system.listeners.bukkit;
+
+import com.djrapitops.plan.system.settings.Settings;
+import org.bukkit.entity.Player;
+import org.bukkit.event.player.PlayerMoveEvent;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mockito;
+import utilities.Teardown;
+import utilities.TestConstants;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+
+/**
+ * Test for {@link AFKListener}
+ *
+ * @author Rsl1122
+ */
+public class AFKListenerTest {
+
+ @BeforeClass
+ public static void setUpClass() {
+ Settings.AFK_THRESHOLD_MINUTES.setTemporaryValue(3);
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ Teardown.resetSettingsTempValues();
+ }
+
+ @Test
+ public void testAfkPermissionCallCaching() {
+ AFKListener afkListener = new AFKListener();
+ Collection calls = new ArrayList<>();
+
+ Player player = mockPlayer(calls);
+ PlayerMoveEvent event = mockMoveEvent(player);
+
+ afkListener.onMove(event);
+ assertEquals(1, calls.size());
+ afkListener.onMove(event);
+ assertEquals(1, calls.size());
+ }
+
+ private PlayerMoveEvent mockMoveEvent(Player player) {
+ PlayerMoveEvent event = Mockito.mock(PlayerMoveEvent.class);
+ doReturn(player).when(event).getPlayer();
+ return event;
+ }
+
+ private Player mockPlayer(Collection calls) {
+ Player player = Mockito.mock(Player.class);
+ doReturn(TestConstants.PLAYER_ONE_UUID).when(player).getUniqueId();
+ doAnswer(perm -> {
+ calls.add(true);
+ return true;
+ }).when(player).hasPermission(Mockito.anyString());
+ return player;
+ }
+
+}
\ No newline at end of file
diff --git a/Plan/src/test/java/com/djrapitops/plan/system/processing/processors/player/PingInsertProcessorTest.java b/Plan/src/test/java/com/djrapitops/plan/system/processing/processors/player/PingInsertProcessorTest.java
new file mode 100644
index 000000000..ba7c40523
--- /dev/null
+++ b/Plan/src/test/java/com/djrapitops/plan/system/processing/processors/player/PingInsertProcessorTest.java
@@ -0,0 +1,66 @@
+package com.djrapitops.plan.system.processing.processors.player;
+
+import com.djrapitops.plan.data.store.objects.DateObj;
+import com.djrapitops.plan.utilities.analysis.Median;
+import com.djrapitops.plugin.api.TimeAmount;
+import org.junit.Before;
+import org.junit.Test;
+import utilities.RandomData;
+import utilities.TestConstants;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test for {@link PingInsertProcessor}.
+ *
+ * @author Rsl1122
+ */
+public class PingInsertProcessorTest {
+
+ private List> testPing;
+
+ @Before
+ public void setUp() {
+ testPing = new ArrayList<>();
+
+ for (int i = 0; i < TimeAmount.MINUTE.ms(); i += TimeAmount.SECOND.ms() * 2L) {
+ testPing.add(new DateObj<>(i, RandomData.randomInt(1, 4000)));
+ }
+ }
+
+ @Test
+ public void testMedian() {
+ List collect = testPing.stream().map(DateObj::getValue).sorted().collect(Collectors.toList());
+ System.out.println(collect);
+ int expected = (int) Median.forInt(collect).calculate();
+ int result = new PingInsertProcessor(TestConstants.PLAYER_ONE_UUID, new ArrayList<>()).getMeanValue(testPing);
+ System.out.println(result);
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void testMedianSingleEntry() {
+ int expected = 50;
+ int result = new PingInsertProcessor(TestConstants.PLAYER_ONE_UUID, new ArrayList<>()).getMeanValue(
+ Collections.singletonList(new DateObj<>(0, expected))
+ );
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void testMedianEmpty() {
+ int expected = -1;
+ int result = new PingInsertProcessor(TestConstants.PLAYER_ONE_UUID, new ArrayList<>()).getMeanValue(
+ Collections.emptyList()
+ );
+
+ assertEquals(expected, result);
+ }
+}
\ No newline at end of file
diff --git a/Plan/src/test/java/com/djrapitops/plan/utilities/analysis/MedianTest.java b/Plan/src/test/java/com/djrapitops/plan/utilities/analysis/MedianTest.java
new file mode 100644
index 000000000..50a0a3656
--- /dev/null
+++ b/Plan/src/test/java/com/djrapitops/plan/utilities/analysis/MedianTest.java
@@ -0,0 +1,90 @@
+package com.djrapitops.plan.utilities.analysis;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for {@link Median}.
+ *
+ * @author Rsl1122
+ */
+public class MedianTest {
+
+ @Test
+ public void simpleOdd() {
+ List testValues = Arrays.asList(1, 3, 3, 6, 7, 8, 9);
+ Collections.shuffle(testValues);
+ double expected = 6;
+ double result = Median.forInt(testValues).calculate();
+
+ assertEquals(expected, result, 0.01);
+ }
+
+ @Test
+ public void simpleEven() {
+ List testValues = Arrays.asList(1, 2, 3, 4, 5, 6, 8, 9);
+ Collections.shuffle(testValues);
+ double expected = 4.5;
+ double result = Median.forInt(testValues).calculate();
+
+ assertEquals(expected, result, 0.01);
+ }
+
+ @Test
+ public void empty() {
+ double expected = -1;
+ double result = Median.forInt(Collections.emptyList()).calculate();
+
+ assertEquals(expected, result, 0.01);
+ }
+
+ @Test
+ public void singleValue() {
+ double expected = 50;
+ double result = Median.forInt(Collections.singletonList((int) expected)).calculate();
+
+ assertEquals(expected, result, 0.01);
+ }
+
+ @Test
+ public void twoValues() {
+ List testValues = Arrays.asList(1, 2);
+ double expected = 1.5;
+ double result = Median.forInt(testValues).calculate();
+
+ assertEquals(expected, result, 0.01);
+ }
+
+ @Test
+ public void overflowOdd() {
+ List testValues = Arrays.asList(Integer.MIN_VALUE, 2, Integer.MAX_VALUE);
+ double expected = 2;
+ double result = Median.forInt(testValues).calculate();
+
+ assertEquals(expected, result, 0.01);
+ }
+
+ @Test
+ public void overflowEven() {
+ List testValues = Arrays.asList(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ double expected = -0.5;
+ double result = Median.forInt(testValues).calculate();
+
+ assertEquals(expected, result, 0.01);
+ }
+
+ @Test
+ public void overflowEven2() {
+ List testValues = Arrays.asList(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ double expected = Integer.MAX_VALUE;
+ double result = Median.forInt(testValues).calculate();
+
+ assertEquals(expected, result, 0.01);
+ }
+
+}
\ No newline at end of file
diff --git a/PlanPluginBridge/PlanPluginBridge-4.4.0.jar b/PlanPluginBridge/PlanPluginBridge-4.4.0.jar
index fdf51327b..6e1a2c5da 100644
Binary files a/PlanPluginBridge/PlanPluginBridge-4.4.0.jar and b/PlanPluginBridge/PlanPluginBridge-4.4.0.jar differ
diff --git a/PlanPluginBridge/install_dependencies.bat b/PlanPluginBridge/install_dependencies.bat
new file mode 100644
index 000000000..4558c418a
--- /dev/null
+++ b/PlanPluginBridge/install_dependencies.bat
@@ -0,0 +1 @@
+mvn install:install-file -Dfile="AAC-3.5.0-b1.jar" -DgroupId=me.konsolas -DartifactId=AAC -Dversion=3.5.0 -Dpackaging=jar & mvn install:install-file -Dfile="AdvancedBan-2.1.5.jar" -DgroupId=me.leoko -DartifactId=advancedban -Dversion=2.1.5 -Dpackaging=jar & mvn install:install-file -Dfile="ASkyBlock-3.0.9.4.jar" -DgroupId=com.wasteofplastic.askyblock -DartifactId=ASkyBlock -Dversion=3.0.9.4 -Dpackaging=jar & mvn install:install-file -Dfile="BanManager-5.15.0.jar" -DgroupId=me.confuser -DartifactId=banmanager -Dversion=5.15.0 -Dpackaging=jar & mvn install:install-file -Dfile="EssentialsX-2.15.0.1.jar" -DgroupId=net.ess3 -DartifactId=EssentialsX -Dversion=2.15.0.1 -Dpackaging=jar & mvn install:install-file -Dfile="Factions-2.14.0.jar" -DgroupId=com.massivecraft -DartifactId=factions -Dversion=2.14.0 -Dpackaging=jar & mvn install:install-file -Dfile="MassiveCore-2.14.0.jar" -DgroupId=com.massivecraft -DartifactId=mcore -Dversion=2.14.0 -Dpackaging=jar & mvn install:install-file -Dfile="GriefPreventionPlus-13.3.jar" -DgroupId=net.kaikk.mc -DartifactId=GriefPreventionPlus -Dversion=13.3 -Dpackaging=jar & mvn install:install-file -Dfile="Jobs4.7.4.jar" -DgroupId=com.gamingmesh -DartifactId=jobs -Dversion=4.7.4 -Dpackaging=jar & mvn install:install-file -Dfile="Kingdoms-13.3.40.jar" -DgroupId=org.kingdoms -DartifactId=kingdoms_demo -Dversion=13.3.40 -Dpackaging=jar & mvn install:install-file -Dfile="LiteBansAPI-0.3.jar" -DgroupId=litebans -DartifactId=api -Dversion=0.3 -Dpackaging=jar & mvn install:install-file -Dfile="mcMMO-1.6.0-SNAPSHOT.jar" -DgroupId=com.gmail.nossr50 -DartifactId=mcMMO -Dversion=1.6.0 -Dpackaging=jar & mvn install:install-file -Dfile="ProtocolSupport-4.28.jar" -DgroupId=com.github.ProtocolSupport -DartifactId=ProtocolSupport -Dversion=4.28 -Dpackaging=jar & mvn install:install-file -Dfile="React-6.573.jar" -DgroupId=com.volmit -DartifactId=react -Dversion=6.573 -Dpackaging=jar & mvn install:install-file -Dfile="SuperbVote-0.5.3.jar" -DgroupId=io.minimum -DartifactId=minecraft.superbvote -Dversion=0.5.3 -Dpackaging=jar & mvn install:install-file -Dfile="Towny-0.92.0.0.jar" -DgroupId=com.palmergames -DartifactId=towny -Dversion=0.92.0.0 -Dpackaging=jar & mvn install:install-file -Dfile="Vault-1.6.7.jar" -DgroupId=net.milkbowl.vault -DartifactId=VaultAPI -Dversion=1.6 -Dpackaging=jar
\ No newline at end of file
diff --git a/PlanPluginBridge/pom.xml b/PlanPluginBridge/pom.xml
index cc4e6edba..329b230d8 100644
--- a/PlanPluginBridge/pom.xml
+++ b/PlanPluginBridge/pom.xml
@@ -41,6 +41,10 @@
+
+ bungeecord-repo
+ https://oss.sonatype.org/content/repositories/snapshots
+
spigot-repo
https://hub.spigotmc.org/nexus/content/repositories/snapshots/
@@ -49,12 +53,16 @@
paper-repo
https://repo.destroystokyo.com/repository/maven-public/
+
+ sponge-repo
+ https://repo.spongepowered.org/maven
+
vault-repo
http://nexus.hc.to/content/repositories/pub_releases
- jitpack.io
+ jitpack.io (GriefPrevention)
https://jitpack.io
@@ -73,6 +81,14 @@
advanced-achievements-repo
https://raw.github.com/PyvesB/AdvancedAchievements/mvn-repo/
+
+ nucleus-repo
+ http://repo.drnaylor.co.uk/artifactory/list/minecraft
+
+
+ discordsrv-repo
+ https://ci.scarsz.me/plugin/repository/everything/
+
@@ -82,14 +98,20 @@
4.3.0-SNAPSHOT
provided