diff --git a/Plan/build.gradle b/Plan/build.gradle
index bc90f4282..b7a1b8d87 100644
--- a/Plan/build.gradle
+++ b/Plan/build.gradle
@@ -12,7 +12,7 @@ allprojects {
wrapper.gradleVersion = "5.0"
group "com.djrapitops"
- version "4.7.1"
+ version "4.7.2"
test {
// useJUnitPlatform()
@@ -103,17 +103,17 @@ subprojects {
testAnnotationProcessor "com.google.dagger:dagger-compiler:$daggerCompilerVersion"
// Test Tooling Dependencies
- testCompile "org.junit.jupiter:junit-jupiter-engine:5.4.0" // JUnit 5
- testCompile "org.junit.platform:junit-platform-runner:1.4.0" // JUnit 4 runner for JUnit 5 tests
- testCompile "org.junit.vintage:junit-vintage-engine:5.4.0" // JUnit 4 compatibility for JUnit 5
- testCompile "org.junit.jupiter:junit-jupiter-params:5.4.0" // JUnit 5, parameterized tests
- testCompile "org.mockito:mockito-core:2.25.0" // Mockito Core
- testCompile "org.mockito:mockito-junit-jupiter:2.25.0" // Mockito JUnit 5 Extension
+ testCompile "org.junit.jupiter:junit-jupiter-engine:5.4.1" // JUnit 5
+ testCompile "org.junit.platform:junit-platform-runner:1.4.1" // JUnit 4 runner for JUnit 5 tests
+ testCompile "org.junit.vintage:junit-vintage-engine:5.4.1" // JUnit 4 compatibility for JUnit 5
+ testCompile "org.junit.jupiter:junit-jupiter-params:5.4.1" // JUnit 5, parameterized tests
+ testCompile "org.mockito:mockito-core:2.25.1" // Mockito Core
+ testCompile "org.mockito:mockito-junit-jupiter:2.25.1" // Mockito JUnit 5 Extension
testCompile "org.seleniumhq.selenium:selenium-java:3.141.59" // Selenium (Browser tests)
testCompile "com.jayway.awaitility:awaitility:1.7.0" // Awaitility (Concurrent wait conditions)
// Testing dependencies required by Plan
- testCompile "org.xerial:sqlite-jdbc:3.25.2" // SQLite
+ testCompile "org.xerial:sqlite-jdbc:3.27.2.1" // SQLite
testCompile "mysql:mysql-connector-java:8.0.15" // MySQL
}
diff --git a/Plan/bungeecord/src/main/java/com/djrapitops/plan/system/info/server/BungeeServerInfo.java b/Plan/bungeecord/src/main/java/com/djrapitops/plan/system/info/server/BungeeServerInfo.java
index 8413b8939..dfa5627b4 100644
--- a/Plan/bungeecord/src/main/java/com/djrapitops/plan/system/info/server/BungeeServerInfo.java
+++ b/Plan/bungeecord/src/main/java/com/djrapitops/plan/system/info/server/BungeeServerInfo.java
@@ -59,7 +59,7 @@ public class BungeeServerInfo extends ServerInfo {
}
@Override
- public Server loadServerInfo() throws EnableException {
+ public void loadServerInfo() throws EnableException {
checkIfDefaultIP();
try {
@@ -76,7 +76,6 @@ public class BungeeServerInfo extends ServerInfo {
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
- return server;
}
private void updateServerInfo(Database db) {
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/command/commands/ManageCommand.java b/Plan/common/src/main/java/com/djrapitops/plan/command/commands/ManageCommand.java
index 2fd1de56b..ad95725d6 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/command/commands/ManageCommand.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/command/commands/ManageCommand.java
@@ -51,6 +51,7 @@ public class ManageCommand extends TreeCmdNode {
ManageSetupCommand setupCommand,
ManageConDebugCommand conDebugCommand,
ManageImportCommand importCommand,
+ ManageExportCommand exportCommand,
ManageDisableCommand disableCommand,
ManageUninstalledCommand uninstalledCommand
) {
@@ -72,6 +73,7 @@ public class ManageCommand extends TreeCmdNode {
setupCommand,
conDebugCommand,
importCommand,
+ exportCommand,
disableCommand,
uninstalledCommand
};
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/command/commands/manage/ManageExportCommand.java b/Plan/common/src/main/java/com/djrapitops/plan/command/commands/manage/ManageExportCommand.java
new file mode 100644
index 000000000..d2a6fd570
--- /dev/null
+++ b/Plan/common/src/main/java/com/djrapitops/plan/command/commands/manage/ManageExportCommand.java
@@ -0,0 +1,157 @@
+/*
+ * This file is part of Player Analytics (Plan).
+ *
+ * Plan is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License v3 as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Plan is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Plan. If not, see .
+ */
+package com.djrapitops.plan.command.commands.manage;
+
+import com.djrapitops.plan.db.Database;
+import com.djrapitops.plan.db.access.queries.objects.UserIdentifierQueries;
+import com.djrapitops.plan.system.database.DBSystem;
+import com.djrapitops.plan.system.export.HtmlExport;
+import com.djrapitops.plan.system.export.JSONExport;
+import com.djrapitops.plan.system.info.server.ServerInfo;
+import com.djrapitops.plan.system.locale.Locale;
+import com.djrapitops.plan.system.locale.lang.CmdHelpLang;
+import com.djrapitops.plan.system.locale.lang.CommandLang;
+import com.djrapitops.plan.system.locale.lang.DeepHelpLang;
+import com.djrapitops.plan.system.locale.lang.ManageLang;
+import com.djrapitops.plan.system.processing.Processing;
+import com.djrapitops.plan.system.settings.Permissions;
+import com.djrapitops.plan.system.settings.config.PlanConfig;
+import com.djrapitops.plan.system.settings.paths.ExportSettings;
+import com.djrapitops.plugin.command.ColorScheme;
+import com.djrapitops.plugin.command.CommandNode;
+import com.djrapitops.plugin.command.CommandType;
+import com.djrapitops.plugin.command.Sender;
+import com.djrapitops.plugin.utilities.Verify;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.UUID;
+import java.util.function.Consumer;
+
+/**
+ * This manage SubCommand is used to import data from 3rd party plugins.
+ *
+ * @author Rsl1122
+ */
+@Singleton
+public class ManageExportCommand extends CommandNode {
+
+ private final Locale locale;
+ private final ColorScheme colorScheme;
+ private final PlanConfig config;
+ private final DBSystem dbSystem;
+ private final ServerInfo serverInfo;
+ private final HtmlExport htmlExport;
+ private final JSONExport jsonExport;
+ private final Processing processing;
+
+ @Inject
+ public ManageExportCommand(
+ Locale locale,
+ ColorScheme colorScheme,
+ PlanConfig config,
+ DBSystem dbSystem,
+ ServerInfo serverInfo,
+ Processing processing,
+ HtmlExport htmlExport,
+ JSONExport jsonExport
+ ) {
+ super("export", Permissions.MANAGE.getPermission(), CommandType.CONSOLE);
+
+ this.locale = locale;
+ this.colorScheme = colorScheme;
+ this.config = config;
+ this.dbSystem = dbSystem;
+ this.serverInfo = serverInfo;
+ this.htmlExport = htmlExport;
+ this.jsonExport = jsonExport;
+ this.processing = processing;
+
+ setArguments("/list");
+ setShortHelp(locale.getString(CmdHelpLang.MANAGE_EXPORT));
+ setInDepthHelp(locale.getArray(DeepHelpLang.MANAGE_EXPORT));
+ }
+
+ @Override
+ public void onCommand(Sender sender, String commandLabel, String[] args) {
+ Verify.isTrue(args.length >= 1,
+ () -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ARGS, "1+", Arrays.toString(this.getArguments()))));
+
+ String exportArg = args[0];
+
+ if ("list".equals(exportArg)) {
+ sender.sendMessage("> " + colorScheme.getMainColor() + "players, server_json");
+ return;
+ }
+
+ Database.State dbState = dbSystem.getDatabase().getState();
+ if (dbState != Database.State.OPEN) {
+ sender.sendMessage(locale.getString(CommandLang.FAIL_DATABASE_NOT_OPEN, dbState.name()));
+ return;
+ }
+
+ getExportFunction(exportArg).accept(sender);
+ }
+
+ private Consumer getExportFunction(String exportArg) {
+ switch (exportArg) {
+ case "players":
+ return this::exportPlayers;
+ case "server_json":
+ return this::exportServerJSON;
+ default:
+ return sender -> sender.sendMessage(locale.getString(ManageLang.FAIL_EXPORTER_NOT_FOUND, exportArg));
+ }
+ }
+
+ private void exportServerJSON(Sender sender) {
+ sender.sendMessage(locale.getString(ManageLang.PROGRESS_START));
+ processing.submitNonCritical(() -> {
+ jsonExport.exportServerJSON(serverInfo.getServerUUID());
+ sender.sendMessage(locale.getString(ManageLang.PROGRESS_SUCCESS));
+ });
+ }
+
+ private void exportPlayers(Sender sender) {
+ sender.sendMessage(locale.getString(ManageLang.PROGRESS_START));
+ if (config.get(ExportSettings.PLAYERS_PAGE)) {
+ processing.submitNonCritical(htmlExport::exportPlayersPage);
+ }
+ Boolean exportPlayerJSON = config.get(ExportSettings.PLAYER_JSON);
+ Boolean exportPlayerHTML = config.get(ExportSettings.PLAYER_PAGES);
+ processing.submitNonCritical(() -> {
+ Map players = dbSystem.getDatabase().query(UserIdentifierQueries.fetchAllPlayerNames());
+ int size = players.size();
+ int i = 1;
+ for (Map.Entry entry : players.entrySet()) {
+ if (exportPlayerJSON) {
+ jsonExport.exportPlayerJSON(entry.getKey());
+ }
+ if (exportPlayerHTML) {
+ htmlExport.exportPlayerPage(entry.getKey(), entry.getValue());
+ }
+ i++;
+ if (i % 1000 == 0) {
+ sender.sendMessage(i + " / " + size + " processed..");
+ }
+ }
+ sender.sendMessage(locale.getString(ManageLang.PROGRESS_SUCCESS));
+ });
+ }
+}
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/data/container/BaseUser.java b/Plan/common/src/main/java/com/djrapitops/plan/data/container/BaseUser.java
index 0d6532cfc..b83985cc3 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/data/container/BaseUser.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/data/container/BaseUser.java
@@ -66,14 +66,21 @@ public class BaseUser {
if (this == o) return true;
if (!(o instanceof BaseUser)) return false;
BaseUser baseUser = (BaseUser) o;
- return registered == baseUser.registered &&
- timesKicked == baseUser.timesKicked &&
- uuid.equals(baseUser.uuid) &&
- name.equals(baseUser.name);
+ return uuid.equals(baseUser.uuid) && name.equals(baseUser.name);
}
@Override
public int hashCode() {
- return Objects.hash(uuid, name, registered, timesKicked);
+ return Objects.hash(uuid, name);
+ }
+
+ @Override
+ public String toString() {
+ return "BaseUser{" +
+ uuid +
+ ", '" + name + '\'' +
+ ", +" + registered +
+ ", kick:" + timesKicked +
+ '}';
}
}
\ No newline at end of file
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/data/container/Session.java b/Plan/common/src/main/java/com/djrapitops/plan/data/container/Session.java
index f85729cab..db1ac4fed 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/data/container/Session.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/data/container/Session.java
@@ -21,7 +21,10 @@ import com.djrapitops.plan.data.store.keys.SessionKeys;
import com.djrapitops.plan.data.store.objects.DateHolder;
import com.djrapitops.plan.data.time.WorldTimes;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
/**
* DataContainer for information about a player's play session.
@@ -91,7 +94,7 @@ public class Session extends DynamicDataContainer implements DateHolder {
*/
public Session(int id, UUID uuid, UUID serverUUID, long sessionStart, long sessionEnd, int mobKills, int deaths, long afkTime) {
this.sessionStart = sessionStart;
- worldTimes = new WorldTimes(new HashMap<>());
+ worldTimes = new WorldTimes();
playerKills = new ArrayList<>();
this.mobKills = mobKills;
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java b/Plan/common/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java
index 8106966b7..29e81b854 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java
@@ -364,7 +364,7 @@ public class AnalysisContainer extends DynamicDataContainer {
private void addGraphSuppliers() {
Key worldPie = new Key<>(WorldPie.class, "WORLD_PIE");
putCachingSupplier(worldPie, () -> graphs.pie().worldPie(
- serverContainer.getValue(ServerKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>()))
+ serverContainer.getValue(ServerKeys.WORLD_TIMES).orElse(new WorldTimes())
));
putSupplier(AnalysisKeys.WORLD_PIE_SERIES, () -> getUnsafe(worldPie).toHighChartsSeries());
putSupplier(AnalysisKeys.GM_PIE_SERIES, () -> getUnsafe(worldPie).toHighChartsDrilldown());
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/data/store/mutators/PerServerMutator.java b/Plan/common/src/main/java/com/djrapitops/plan/data/store/mutators/PerServerMutator.java
index df5bde1b1..2062ac002 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/data/store/mutators/PerServerMutator.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/data/store/mutators/PerServerMutator.java
@@ -46,13 +46,13 @@ public class PerServerMutator {
public List flatMapSessions() {
return data.values().stream()
.filter(container -> container.supports(PerServerKeys.SESSIONS))
- .map(container -> container.getUnsafe(PerServerKeys.SESSIONS))
+ .map(container -> container.getValue(PerServerKeys.SESSIONS).orElse(Collections.emptyList()))
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
public WorldTimes flatMapWorldTimes() {
- WorldTimes total = new WorldTimes(new HashMap<>());
+ WorldTimes total = new WorldTimes();
for (DataContainer container : data.values()) {
if (container.supports(PerServerKeys.WORLD_TIMES)) {
@@ -68,7 +68,7 @@ public class PerServerMutator {
Map timesMap = new HashMap<>();
for (Map.Entry entry : data.entrySet()) {
DataContainer container = entry.getValue();
- timesMap.put(entry.getKey(), container.getValue(PerServerKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>())));
+ timesMap.put(entry.getKey(), container.getValue(PerServerKeys.WORLD_TIMES).orElse(new WorldTimes()));
}
return timesMap;
}
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/data/store/mutators/SessionsMutator.java b/Plan/common/src/main/java/com/djrapitops/plan/data/store/mutators/SessionsMutator.java
index d4a04c050..cf6328dbc 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/data/store/mutators/SessionsMutator.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/data/store/mutators/SessionsMutator.java
@@ -75,7 +75,7 @@ public class SessionsMutator {
}
public WorldTimes toTotalWorldTimes() {
- WorldTimes total = new WorldTimes(new HashMap<>());
+ WorldTimes total = new WorldTimes();
for (Session session : sessions) {
session.getValue(SessionKeys.WORLD_TIMES).ifPresent(total::add);
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/data/time/WorldTimes.java b/Plan/common/src/main/java/com/djrapitops/plan/data/time/WorldTimes.java
index 55902a718..e5bbc3741 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/data/time/WorldTimes.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/data/time/WorldTimes.java
@@ -54,6 +54,10 @@ public class WorldTimes {
this.times = times;
}
+ public WorldTimes() {
+ this(new HashMap<>());
+ }
+
private void addWorld(String worldName, String gameMode, long changeTime) {
if (worldName == null || gameMode == null) return;
times.put(worldName, new GMTimes(gameMode, changeTime));
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/DataStoreQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/DataStoreQueries.java
index 62705088c..a35f6aa9a 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/DataStoreQueries.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/DataStoreQueries.java
@@ -103,9 +103,9 @@ public class DataStoreQueries {
statement.setString(1, session.getUnsafe(SessionKeys.UUID).toString());
statement.setLong(2, session.getUnsafe(SessionKeys.START));
statement.setLong(3, session.getUnsafe(SessionKeys.END));
- statement.setInt(4, session.getUnsafe(SessionKeys.DEATH_COUNT));
- statement.setInt(5, session.getUnsafe(SessionKeys.MOB_KILL_COUNT));
- statement.setLong(6, session.getUnsafe(SessionKeys.AFK_TIME));
+ statement.setInt(4, session.getValue(SessionKeys.DEATH_COUNT).orElse(0));
+ statement.setInt(5, session.getValue(SessionKeys.MOB_KILL_COUNT).orElse(0));
+ statement.setLong(6, session.getValue(SessionKeys.AFK_TIME).orElse(0L));
statement.setString(7, session.getUnsafe(SessionKeys.SERVER_UUID).toString());
}
};
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/LargeStoreQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/LargeStoreQueries.java
index 5d3bd6cee..2846e1b9c 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/LargeStoreQueries.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/LargeStoreQueries.java
@@ -341,9 +341,9 @@ public class LargeStoreQueries {
statement.setString(1, session.getUnsafe(SessionKeys.UUID).toString());
statement.setLong(2, session.getUnsafe(SessionKeys.START));
statement.setLong(3, session.getUnsafe(SessionKeys.END));
- statement.setInt(4, session.getUnsafe(SessionKeys.DEATH_COUNT));
- statement.setInt(5, session.getUnsafe(SessionKeys.MOB_KILL_COUNT));
- statement.setLong(6, session.getUnsafe(SessionKeys.AFK_TIME));
+ statement.setInt(4, session.getValue(SessionKeys.DEATH_COUNT).orElse(0));
+ statement.setInt(5, session.getValue(SessionKeys.MOB_KILL_COUNT).orElse(0));
+ statement.setLong(6, session.getValue(SessionKeys.AFK_TIME).orElse(0L));
statement.setString(7, session.getUnsafe(SessionKeys.SERVER_UUID).toString());
statement.addBatch();
}
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/PerServerContainerQuery.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/PerServerContainerQuery.java
index 3ac493e16..2322319e6 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/PerServerContainerQuery.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/PerServerContainerQuery.java
@@ -63,7 +63,7 @@ public class PerServerContainerQuery implements Query {
// After-values that can be calculated without database.
for (DataContainer serverContainer : perServerContainer.values()) {
serverContainer.putSupplier(PerServerKeys.MOB_DEATH_COUNT, () ->
- serverContainer.getUnsafe(PerServerKeys.DEATH_COUNT) - serverContainer.getUnsafe(PerServerKeys.PLAYER_DEATH_COUNT)
+ serverContainer.getValue(PerServerKeys.DEATH_COUNT).orElse(0) - serverContainer.getValue(PerServerKeys.PLAYER_DEATH_COUNT).orElse(0)
);
}
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/PlayerContainerQuery.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/PlayerContainerQuery.java
index 1850b5c14..415272f45 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/PlayerContainerQuery.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/PlayerContainerQuery.java
@@ -19,6 +19,7 @@ package com.djrapitops.plan.db.access.queries.containers;
import com.djrapitops.plan.data.container.BaseUser;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.Key;
+import com.djrapitops.plan.data.store.containers.PerServerContainer;
import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.store.keys.SessionKeys;
@@ -29,7 +30,7 @@ import com.djrapitops.plan.db.SQLDB;
import com.djrapitops.plan.db.access.Query;
import com.djrapitops.plan.db.access.queries.objects.*;
-import java.util.HashMap;
+import java.util.Collection;
import java.util.List;
import java.util.UUID;
@@ -64,11 +65,11 @@ public class PlayerContainerQuery implements Query {
container.putCachingSupplier(PlayerKeys.NICKNAMES, () -> db.query(NicknameQueries.fetchNicknameDataOfPlayer(uuid)));
container.putCachingSupplier(PlayerKeys.PER_SERVER, () -> db.query(new PerServerContainerQuery(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.BANNED, () -> new PerServerMutator(container.getValue(PlayerKeys.PER_SERVER).orElse(new PerServerContainer())).isBanned());
+ container.putSupplier(PlayerKeys.OPERATOR, () -> new PerServerMutator(container.getValue(PlayerKeys.PER_SERVER).orElse(new PerServerContainer())).isOperator());
container.putCachingSupplier(PlayerKeys.SESSIONS, () -> {
- List sessions = new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).flatMapSessions();
+ List sessions = new PerServerMutator(container.getValue(PlayerKeys.PER_SERVER).orElse(new PerServerContainer())).flatMapSessions();
container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(sessions::add);
return sessions;
}
@@ -77,7 +78,7 @@ public class PlayerContainerQuery implements Query {
{
WorldTimes worldTimes = db.query(WorldTimesQueries.fetchPlayerTotalWorldTimes(uuid));
container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(session -> worldTimes.add(
- session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>())))
+ session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes()))
);
return worldTimes;
});
@@ -86,7 +87,7 @@ public class PlayerContainerQuery implements Query {
container.putSupplier(PlayerKeys.PLAYER_KILLS, () -> SessionsMutator.forContainer(container).toPlayerKillList());
container.putSupplier(PlayerKeys.PLAYER_DEATHS, () -> SessionsMutator.forContainer(container).toPlayerDeathList());
- container.putSupplier(PlayerKeys.PLAYER_KILL_COUNT, () -> container.getUnsafe(PlayerKeys.PLAYER_KILLS).size());
+ container.putSupplier(PlayerKeys.PLAYER_KILL_COUNT, () -> container.getValue(PlayerKeys.PLAYER_KILLS).map(Collection::size).orElse(0));
container.putSupplier(PlayerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount());
container.putSupplier(PlayerKeys.DEATH_COUNT, () -> SessionsMutator.forContainer(container).toDeathCount());
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerContainerQuery.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerContainerQuery.java
index af0620bb8..6c7411769 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerContainerQuery.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerContainerQuery.java
@@ -31,6 +31,7 @@ import com.djrapitops.plan.extension.implementation.storage.queries.ExtensionSer
import com.djrapitops.plan.system.cache.SessionCache;
import com.djrapitops.plan.system.info.server.Server;
+import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@@ -66,7 +67,7 @@ public class ServerContainerQuery implements Query {
container.putRawData(ServerKeys.SERVER_UUID, serverUUID);
container.putRawData(ServerKeys.NAME, serverInfo.get().getName());
container.putCachingSupplier(ServerKeys.PLAYERS, () -> db.query(new ServerPlayerContainersQuery(serverUUID)));
- container.putSupplier(ServerKeys.PLAYER_COUNT, () -> container.getUnsafe(ServerKeys.PLAYERS).size());
+ container.putSupplier(ServerKeys.PLAYER_COUNT, () -> container.getValue(ServerKeys.PLAYERS).map(Collection::size).orElse(0));
container.putCachingSupplier(ServerKeys.TPS, () -> db.query(TPSQueries.fetchTPSDataOfServer(serverUUID)));
container.putCachingSupplier(ServerKeys.PING, () -> PlayersMutator.forContainer(container).pings());
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerPlayerContainersQuery.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerPlayerContainersQuery.java
index 1a27d83bc..d5b757e77 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerPlayerContainersQuery.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerPlayerContainersQuery.java
@@ -103,7 +103,7 @@ public class ServerPlayerContainersQuery implements Query>
WorldTimes worldTimes = new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).flatMapWorldTimes();
container.getValue(PlayerKeys.ACTIVE_SESSION)
.ifPresent(session -> worldTimes.add(
- session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>())))
+ session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes()))
);
return worldTimes;
});
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/BaseUserQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/BaseUserQueries.java
index 69fc945cf..94bf82227 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/BaseUserQueries.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/BaseUserQueries.java
@@ -27,7 +27,10 @@ import com.djrapitops.plan.db.sql.tables.UsersTable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.*;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.UUID;
/**
* Queries for {@link BaseUser} objects.
@@ -126,8 +129,8 @@ public class BaseUserQueries {
}
@Override
- public List processResults(ResultSet set) throws SQLException {
- List users = new ArrayList<>();
+ public Collection processResults(ResultSet set) throws SQLException {
+ Collection users = new HashSet<>();
while (set.next()) {
UUID playerUUID = UUID.fromString(set.getString(UsersTable.USER_UUID));
String name = set.getString(UsersTable.USER_NAME);
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/SessionQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/SessionQueries.java
index 9632e4510..8f9e21046 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/SessionQueries.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/SessionQueries.java
@@ -214,7 +214,7 @@ public class SessionQueries {
set.getLong(SessionsTable.AFK_TIME)
));
- WorldTimes worldTimes = session.getUnsafe(SessionKeys.WORLD_TIMES);
+ WorldTimes worldTimes = session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes());
String worldName = set.getString(WorldTable.NAME);
if (!worldTimes.contains(worldName)) {
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/WorldTimesQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/WorldTimesQueries.java
index 1243ba289..e1fa6ee85 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/WorldTimesQueries.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/objects/WorldTimesQueries.java
@@ -75,7 +75,7 @@ public class WorldTimesQueries {
public WorldTimes processResults(ResultSet set) throws SQLException {
String[] gms = GMTimes.getGMKeyArray();
- WorldTimes worldTimes = new WorldTimes(new HashMap<>());
+ WorldTimes worldTimes = new WorldTimes();
while (set.next()) {
String worldName = set.getString(worldColumn);
@@ -110,7 +110,7 @@ public class WorldTimesQueries {
public WorldTimes processResults(ResultSet set) throws SQLException {
String[] gms = GMTimes.getGMKeyArray();
- WorldTimes worldTimes = new WorldTimes(new HashMap<>());
+ WorldTimes worldTimes = new WorldTimes();
while (set.next()) {
String worldName = set.getString(worldColumn);
@@ -149,7 +149,7 @@ public class WorldTimesQueries {
Map worldTimesMap = new HashMap<>();
while (set.next()) {
UUID serverUUID = UUID.fromString(set.getString(WorldTimesTable.SERVER_UUID));
- WorldTimes worldTimes = worldTimesMap.getOrDefault(serverUUID, new WorldTimes(new HashMap<>()));
+ WorldTimes worldTimes = worldTimesMap.getOrDefault(serverUUID, new WorldTimes());
String worldName = set.getString(worldColumn);
GMTimes gmTimes = extractGMTimes(set, gms);
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/export/HtmlExport.java b/Plan/common/src/main/java/com/djrapitops/plan/system/export/HtmlExport.java
index a41497e00..78abc8897 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/export/HtmlExport.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/export/HtmlExport.java
@@ -33,6 +33,7 @@ import com.djrapitops.plan.system.settings.paths.ExportSettings;
import com.djrapitops.plan.system.settings.theme.Theme;
import com.djrapitops.plan.system.settings.theme.ThemeVal;
import com.djrapitops.plan.utilities.file.FileUtil;
+import com.djrapitops.plan.utilities.html.pages.InspectPage;
import com.djrapitops.plan.utilities.html.pages.PageFactory;
import com.djrapitops.plugin.api.Check;
import com.djrapitops.plugin.logging.L;
@@ -107,7 +108,21 @@ public class HtmlExport extends SpecificExport {
});
}
- public void exportPlayer(UUID playerUUID) {
+ public void exportPlayerPage(UUID playerUUID) {
+ Optional name = dbSystem.getDatabase().query(UserIdentifierQueries.fetchPlayerNameOf(playerUUID));
+ exportPlayerPage(playerUUID, name.orElse("Unknown"));
+ }
+
+ public void exportPlayerPage(UUID playerUUID, String playerName) {
+ InspectPage playerPage = pageFactory.inspectPage(playerUUID);
+ try {
+ exportPlayerPage(playerName, playerPage.toHtml());
+ } catch (ParseException | IOException e) {
+ errorHandler.log(L.ERROR, this.getClass(), e);
+ }
+ }
+
+ public void exportCachedPlayerPage(UUID playerUUID) {
if (Check.isBukkitAvailable() && connectionSystem.isServerAvailable()) {
return;
}
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/export/JSONExport.java b/Plan/common/src/main/java/com/djrapitops/plan/system/export/JSONExport.java
index 4f92cec13..805512eac 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/export/JSONExport.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/export/JSONExport.java
@@ -32,6 +32,7 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.File;
import java.io.IOException;
+import java.net.URLEncoder;
import java.util.Collections;
import java.util.UUID;
@@ -77,7 +78,7 @@ public class JSONExport extends SpecificExport {
try {
File htmlLocation = getPlayerFolder();
htmlLocation.mkdirs();
- File exportFile = new File(htmlLocation, playerName.replace(" ", "%20").replace(".", "%2E") + ".json");
+ File exportFile = new File(htmlLocation, URLEncoder.encode(playerName, "UTF-8") + ".json");
export(exportFile, Collections.singletonList(json));
} catch (IOException e) {
@@ -94,7 +95,7 @@ public class JSONExport extends SpecificExport {
try {
File htmlLocation = getServerFolder();
htmlLocation.mkdirs();
- File exportFile = new File(htmlLocation, serverName.replace(" ", "%20").replace(".", "%2E") + ".json");
+ File exportFile = new File(htmlLocation, URLEncoder.encode(serverName, "UTF-8") + ".json");
export(exportFile, Collections.singletonList(json));
} catch (IOException e) {
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/export/SpecificExport.java b/Plan/common/src/main/java/com/djrapitops/plan/system/export/SpecificExport.java
index 4ab72258f..a84da8e30 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/export/SpecificExport.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/export/SpecificExport.java
@@ -25,6 +25,7 @@ import com.djrapitops.plugin.api.Check;
import java.io.File;
import java.io.IOException;
+import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
@@ -89,20 +90,24 @@ public abstract class SpecificExport {
return player;
}
- protected void exportAvailablePlayerPage(UUID uuid, String name) throws IOException {
- Response response = ResponseCache.loadResponse(PageId.PLAYER.of(uuid));
+ protected void exportPlayerPage(String playerName, String html) throws IOException {
+ List lines = Arrays.asList(html.split("\n"));
+
+ File htmlLocation = new File(getPlayerFolder(), URLEncoder.encode(playerName, "UTF-8").replace(".", "%2E"));
+ htmlLocation.mkdirs();
+ File exportFile = new File(htmlLocation, "index.html");
+
+ export(exportFile, lines);
+ }
+
+ protected void exportAvailablePlayerPage(UUID playerUUID, String name) throws IOException {
+ Response response = ResponseCache.loadResponse(PageId.PLAYER.of(playerUUID));
if (response == null) {
return;
}
String html = response.getContent().replace("../", "../../");
- List lines = Arrays.asList(html.split("\n"));
-
- File htmlLocation = new File(getPlayerFolder(), name.replace(" ", "%20").replace(".", "%2E"));
- htmlLocation.mkdirs();
- File exportFile = new File(htmlLocation, "index.html");
-
- export(exportFile, lines);
+ exportPlayerPage(name, html);
}
protected void exportAvailableServerPage(UUID serverUUID, String serverName) throws IOException {
@@ -123,7 +128,7 @@ public abstract class SpecificExport {
if (serverUUID.equals(serverInfo.getServerUUID())) {
htmlLocation = new File(getFolder(), "network");
} else {
- htmlLocation = new File(getServerFolder(), serverName.replace(" ", "%20").replace(".", "%2E"));
+ htmlLocation = new File(getServerFolder(), URLEncoder.encode(serverName, "UTF-8").replace(".", "%2E"));
html = html.replace("../", "../../");
}
} else {
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/info/request/CacheInspectPageRequest.java b/Plan/common/src/main/java/com/djrapitops/plan/system/info/request/CacheInspectPageRequest.java
index ca68f796f..1d1485b78 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/info/request/CacheInspectPageRequest.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/info/request/CacheInspectPageRequest.java
@@ -105,13 +105,13 @@ public class CacheInspectPageRequest extends InfoRequestWithVariables implements
return DefaultResponses.SUCCESS.get();
}
- private void cache(UUID uuid, String html) {
- ResponseCache.cacheResponse(PageId.PLAYER.of(uuid), () -> new InspectPageResponse(uuid, html));
+ private void cache(UUID playerUUID, String html) {
+ ResponseCache.cacheResponse(PageId.PLAYER.of(playerUUID), () -> new InspectPageResponse(playerUUID, html));
if (config.get(ExportSettings.PLAYER_PAGES)) {
- processing.submitNonCritical(() -> htmlExport.exportPlayer(uuid));
+ processing.submitNonCritical(() -> htmlExport.exportCachedPlayerPage(playerUUID));
}
if (config.get(ExportSettings.PLAYER_JSON)) {
- processing.submitNonCritical(() -> jsonExport.exportPlayerJSON(uuid));
+ processing.submitNonCritical(() -> jsonExport.exportPlayerJSON(playerUUID));
}
}
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/info/server/ServerInfo.java b/Plan/common/src/main/java/com/djrapitops/plan/system/info/server/ServerInfo.java
index 5e8c1113e..4bbb56980 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/info/server/ServerInfo.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/info/server/ServerInfo.java
@@ -53,11 +53,11 @@ public abstract class ServerInfo implements SubSystem {
@Override
public void enable() throws EnableException {
- server = loadServerInfo();
+ loadServerInfo();
Verify.nullCheck(server, () -> new EnableException("Server information did not load!"));
}
- protected abstract Server loadServerInfo() throws EnableException;
+ protected abstract void loadServerInfo() throws EnableException;
@Override
public void disable() {
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/info/server/ServerServerInfo.java b/Plan/common/src/main/java/com/djrapitops/plan/system/info/server/ServerServerInfo.java
index 4cd45feb7..0e1e004a3 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/info/server/ServerServerInfo.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/info/server/ServerServerInfo.java
@@ -23,9 +23,12 @@ import com.djrapitops.plan.db.access.queries.objects.ServerQueries;
import com.djrapitops.plan.db.access.transactions.StoreServerInformationTransaction;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.server.properties.ServerProperties;
+import com.djrapitops.plan.system.processing.Processing;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.PluginSettings;
import com.djrapitops.plan.system.webserver.WebServer;
+import com.djrapitops.plugin.logging.L;
+import com.djrapitops.plugin.logging.error.ErrorHandler;
import dagger.Lazy;
import javax.inject.Inject;
@@ -45,24 +48,31 @@ import java.util.concurrent.ExecutionException;
@Singleton
public class ServerServerInfo extends ServerInfo {
- private final Lazy webServer;
+ private final ServerInfoFile serverInfoFile;
+
private final PlanConfig config;
- private ServerInfoFile serverInfoFile;
- private DBSystem dbSystem;
+ private final Processing processing;
+ private final DBSystem dbSystem;
+ private final Lazy webServer;
+ private final ErrorHandler errorHandler;
@Inject
public ServerServerInfo(
ServerProperties serverProperties,
ServerInfoFile serverInfoFile,
+ Processing processing,
+ PlanConfig config,
DBSystem dbSystem,
Lazy webServer,
- PlanConfig config
+ ErrorHandler errorHandler
) {
super(serverProperties);
this.serverInfoFile = serverInfoFile;
+ this.processing = processing;
this.dbSystem = dbSystem;
this.webServer = webServer;
this.config = config;
+ this.errorHandler = errorHandler;
}
@Override
@@ -76,10 +86,15 @@ public class ServerServerInfo extends ServerInfo {
}
@Override
- protected Server loadServerInfo() throws EnableException {
+ protected void loadServerInfo() throws EnableException {
Optional serverUUID = serverInfoFile.getUUID();
try {
- return serverUUID.isPresent() ? updateDbInfo(serverUUID.get()) : registerServer();
+ if (serverUUID.isPresent()) {
+ server = createServerObject(serverUUID.get());
+ processing.submitNonCritical(() -> updateDbInfo(serverUUID.get()));
+ } else {
+ server = registerServer();
+ }
} catch (DBOpException e) {
String causeMsg = e.getMessage();
throw new EnableException("Failed to read Server information from Database: " + causeMsg, e);
@@ -87,7 +102,6 @@ public class ServerServerInfo extends ServerInfo {
throw new EnableException("Failed to read ServerInfoFile.yml", e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
- return null; // This line is not reached due to the thread interrupt.
} catch (Exception e) {
throw new EnableException("Failed to perform a database transaction to store the server information", e);
}
@@ -98,9 +112,11 @@ public class ServerServerInfo extends ServerInfo {
Optional foundServer = db.query(ServerQueries.fetchServerMatchingIdentifier(serverUUID));
if (!foundServer.isPresent()) {
- return registerServer(serverUUID);
+ server = registerServer(serverUUID);
+ return;
}
- Server server = foundServer.get();
+
+ server = foundServer.get();
// Update information
String name = config.get(PluginSettings.SERVER_NAME).replaceAll("[^a-zA-Z0-9_\\s]", "_");
@@ -114,7 +130,6 @@ public class ServerServerInfo extends ServerInfo {
// Save
db.executeTransaction(new StoreServerInformationTransaction(server));
- return server;
}
private Server registerServer() throws Exception {
@@ -124,11 +139,7 @@ public class ServerServerInfo extends ServerInfo {
private Server registerServer(UUID serverUUID) throws ExecutionException, InterruptedException, IOException {
Database db = dbSystem.getDatabase();
- // Create the server object
- String webAddress = webServer.get().getAccessAddress();
- String name = config.get(PluginSettings.SERVER_NAME).replaceAll("[^a-zA-Z0-9_\\s]", "_");
- int maxPlayers = serverProperties.getMaxPlayers();
- Server server = new Server(-1, serverUUID, name, webAddress, maxPlayers);
+ Server server = createServerObject(serverUUID);
// Save
db.executeTransaction(new StoreServerInformationTransaction(server))
@@ -142,4 +153,11 @@ public class ServerServerInfo extends ServerInfo {
serverInfoFile.saveServerUUID(serverUUID);
return server;
}
+
+ private Server createServerObject(UUID serverUUID) {
+ String webAddress = webServer.get().getAccessAddress();
+ String name = config.get(PluginSettings.SERVER_NAME).replaceAll("[^a-zA-Z0-9_\\s]", "_");
+ int maxPlayers = serverProperties.getMaxPlayers();
+ return new Server(-1, serverUUID, name, webAddress, maxPlayers);
+ }
}
\ No newline at end of file
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/locale/lang/CmdHelpLang.java b/Plan/common/src/main/java/com/djrapitops/plan/system/locale/lang/CmdHelpLang.java
index e7b55bd1c..10ff9c657 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/locale/lang/CmdHelpLang.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/locale/lang/CmdHelpLang.java
@@ -48,6 +48,7 @@ public enum CmdHelpLang implements Lang {
MANAGE_CLEAR("Command Help - /plan manage clear", "Clear a Database"),
MANAGE_CON("Command Help - /plan manage con", "Debug Server-Bungee connections"),
MANAGE_IMPORT("Command Help - /plan manage import", "Import data from elsewhere"),
+ MANAGE_EXPORT("Command Help - /plan manage export", "Trigger export manually"),
MANAGE_DISABLE("Command Help - /plan manage disable", "Disable a feature temporarily"),
MANAGE_SETUP("Command Help - /plan manage setup", "Set-up Server-Bungee connection"),
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/locale/lang/DeepHelpLang.java b/Plan/common/src/main/java/com/djrapitops/plan/system/locale/lang/DeepHelpLang.java
index bc18e9c30..1fb60f935 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/locale/lang/DeepHelpLang.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/locale/lang/DeepHelpLang.java
@@ -41,6 +41,7 @@ public enum DeepHelpLang implements Lang {
MANAGE_CON("In Depth Help - /plan manage con ?", "> §2Connection Debug Subcommand\\ Used to debug connections in the network.\\ Sends a request to each server in the database."),
MANAGE_DISABLE("In Depth Help - /plan manage disable ?", "> §2Disable Subcommand\\ Can disable parts of the plugin until next reload.\\ Accepted arguments:\\ §2kickcount §fDisables kick counts in case /kickall is used on shutdown macro."),
MANAGE_IMPORT("In Depth Help - /plan manage import ?", "> §2Import Subcommand\\ Import data from other sources.\\ Accepted Arguments:\\ §2offline §fBukkit player data, only register date and name."),
+ MANAGE_EXPORT("In Depth Help - /plan manage export ?", "> §2Export Subcommand\\ Trigger export to result folders.\\ Accepted Arguments:\\ §2list §fList possible arguments.\\ §2players §fExport /players, /player pages + /player/raw json depending on config values.\\ §2server_json §fExport /server/raw JSON if enabled in config."),
MANAGE_MOVE("In Depth Help - /plan manage move ?", "> §2Move Subcommand\\ Move data from SQLite to MySQL or other way around.\\ Target database is cleared before transfer."),
MANAGE_REMOVE("In Depth Help - /plan manage remove ?", "> §2Remove Subcommand\\ Remove player's data from the active database."),
MANAGE_RESTORE("In Depth Help - /plan manage restore ?", "> §2Restore Subcommand\\ Restore a previous backup SQLite database (.db file)\\ You can also restore database.db from another server to MySQL.\\ Target database is cleared before transfer."),
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/locale/lang/ManageLang.java b/Plan/common/src/main/java/com/djrapitops/plan/system/locale/lang/ManageLang.java
index 4e4bc4463..7d706ef11 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/locale/lang/ManageLang.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/locale/lang/ManageLang.java
@@ -45,6 +45,7 @@ public enum ManageLang implements Lang {
FAIL_INCORRECT_DB("Manage - Fail Incorrect Database", "> §c'${0}' is not a supported database."),
FAIL_FILE_NOT_FOUND("Manage - Fail File not found", "> §cNo File found at ${0}"),
FAIL_IMPORTER_NOT_FOUND("Manage - Fail No Importer", "§eImporter '${0}' doesn't exist"),
+ FAIL_EXPORTER_NOT_FOUND("Manage - Fail No Exporter", "§eExporter '${0}' doesn't exist"),
NO_SERVER("Manage - Fail No Server", "No server found with given parameters."),
UNINSTALLING_SAME_SERVER("Manage - Fail Same server", "Can not mark this server as uninstalled (You are on it)");
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/processing/processors/info/InfoProcessors.java b/Plan/common/src/main/java/com/djrapitops/plan/system/processing/processors/info/InfoProcessors.java
index 00e9bf2cd..4331bb963 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/processing/processors/info/InfoProcessors.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/processing/processors/info/InfoProcessors.java
@@ -16,8 +16,11 @@
*/
package com.djrapitops.plan.system.processing.processors.info;
+import com.djrapitops.plan.system.export.HtmlExport;
+import com.djrapitops.plan.system.export.JSONExport;
import com.djrapitops.plan.system.info.InfoSystem;
import com.djrapitops.plan.system.info.connection.WebExceptionLogger;
+import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plugin.command.Sender;
import dagger.Lazy;
@@ -34,14 +37,23 @@ import java.util.function.BiConsumer;
@Singleton
public class InfoProcessors {
+ private final Lazy config;
+ private final Lazy htmlExport;
+ private final Lazy jsonExport;
private final Lazy infoSystem;
private final Lazy webExceptionLogger;
@Inject
public InfoProcessors(
+ Lazy config,
+ Lazy htmlExport,
+ Lazy jsonExport,
Lazy infoSystem,
Lazy webExceptionLogger
) {
+ this.config = config;
+ this.htmlExport = htmlExport;
+ this.jsonExport = jsonExport;
this.infoSystem = infoSystem;
this.webExceptionLogger = webExceptionLogger;
}
@@ -58,6 +70,6 @@ public class InfoProcessors {
}
public PlayerPageUpdateProcessor playerPageUpdateProcessor(UUID uuid) {
- return new PlayerPageUpdateProcessor(uuid);
+ return new PlayerPageUpdateProcessor(uuid, config.get(), htmlExport.get(), jsonExport.get());
}
}
\ No newline at end of file
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/processing/processors/info/PlayerPageUpdateProcessor.java b/Plan/common/src/main/java/com/djrapitops/plan/system/processing/processors/info/PlayerPageUpdateProcessor.java
index 3e27c188f..0f80614d9 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/processing/processors/info/PlayerPageUpdateProcessor.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/processing/processors/info/PlayerPageUpdateProcessor.java
@@ -16,6 +16,10 @@
*/
package com.djrapitops.plan.system.processing.processors.info;
+import com.djrapitops.plan.system.export.HtmlExport;
+import com.djrapitops.plan.system.export.JSONExport;
+import com.djrapitops.plan.system.settings.config.PlanConfig;
+import com.djrapitops.plan.system.settings.paths.ExportSettings;
import com.djrapitops.plan.system.webserver.cache.PageId;
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
@@ -23,16 +27,35 @@ import java.util.UUID;
public class PlayerPageUpdateProcessor implements Runnable {
- private final UUID uuid;
+ private final UUID playerUUID;
+
+ private final PlanConfig config;
+ private final HtmlExport htmlExport;
+ private final JSONExport jsonExport;
PlayerPageUpdateProcessor(
- UUID uuid
+ UUID playerUUID,
+ PlanConfig config,
+ HtmlExport htmlExport,
+ JSONExport jsonExport
) {
- this.uuid = uuid;
+ this.playerUUID = playerUUID;
+ this.config = config;
+ this.htmlExport = htmlExport;
+ this.jsonExport = jsonExport;
}
@Override
public void run() {
- ResponseCache.clearResponse(PageId.PLAYER.of(uuid));
+ ResponseCache.clearResponse(PageId.PLAYER.of(playerUUID));
+
+ if (config.get(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE)) {
+ if (config.get(ExportSettings.PLAYER_JSON)) {
+ jsonExport.exportPlayerJSON(playerUUID);
+ }
+ if (config.get(ExportSettings.PLAYER_PAGES)) {
+ htmlExport.exportPlayerPage(playerUUID);
+ }
+ }
}
}
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/settings/config/WorldAliasSettings.java b/Plan/common/src/main/java/com/djrapitops/plan/system/settings/config/WorldAliasSettings.java
index 866af95c2..fab64b193 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/settings/config/WorldAliasSettings.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/settings/config/WorldAliasSettings.java
@@ -165,7 +165,7 @@ public class WorldAliasSettings {
if (!session.supports(SessionKeys.WORLD_TIMES)) {
return "No World Time Data";
}
- WorldTimes worldTimes = session.getUnsafe(SessionKeys.WORLD_TIMES);
+ WorldTimes worldTimes = session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes());
if (!session.supports(SessionKeys.END)) {
return "Current: " + aliases.getOrDefault(worldTimes.getCurrentWorld(), "Unknown");
}
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/settings/paths/ExportSettings.java b/Plan/common/src/main/java/com/djrapitops/plan/system/settings/paths/ExportSettings.java
index 17cf7e851..7a10c4306 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/settings/paths/ExportSettings.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/settings/paths/ExportSettings.java
@@ -35,6 +35,7 @@ public class ExportSettings {
public static final Setting PLAYERS_PAGE = new BooleanSetting("Export.Parts.Players_page");
public static final Setting SERVER_PAGE = new BooleanSetting("Export.Parts.Server_page");
public static final Setting SERVER_JSON = new BooleanSetting("Export.Parts.Server_JSON");
+ public static final Setting EXPORT_ON_ONLINE_STATUS_CHANGE = new BooleanSetting("Export.Export_player_on_login_and_logout");
private ExportSettings() {
/* static variable class */
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/webserver/RequestHandler.java b/Plan/common/src/main/java/com/djrapitops/plan/system/webserver/RequestHandler.java
index 89a7f44c6..3a69977b6 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/webserver/RequestHandler.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/webserver/RequestHandler.java
@@ -104,7 +104,7 @@ public class RequestHandler implements HttpHandler {
// Authentication failed, but was not blocked
if (response instanceof PromptAuthorizationResponse) {
- responseHeaders.set("WWW-Authenticate", response.getHeader("WWW-Authenticate").orElse("Basic realm=\"Plan WebUser (/plan register)\";"));
+ responseHeaders.set("WWW-Authenticate", response.getHeader("WWW-Authenticate").orElse("Basic realm=\"Plan WebUser (/plan register)\""));
}
response.setResponseHeaders(responseHeaders);
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/system/webserver/response/PromptAuthorizationResponse.java b/Plan/common/src/main/java/com/djrapitops/plan/system/webserver/response/PromptAuthorizationResponse.java
index 57a4ce949..69ea8a8c6 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/system/webserver/response/PromptAuthorizationResponse.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/system/webserver/response/PromptAuthorizationResponse.java
@@ -45,7 +45,7 @@ public class PromptAuthorizationResponse extends ErrorResponse {
public static PromptAuthorizationResponse getBasicAuthResponse(VersionCheckSystem versionCheckSystem, PlanFiles files) throws IOException {
PromptAuthorizationResponse response = new PromptAuthorizationResponse(versionCheckSystem, files);
response.setHeader("HTTP/1.1 401 Access Denied\r\n"
- + "WWW-Authenticate: Basic realm=\"Plan WebUser (/plan register)\";");
+ + "WWW-Authenticate: Basic realm=\"Plan WebUser (/plan register)\"");
response.setParagraph("Authentication Failed." + TIPS);
response.replacePlaceholders();
@@ -69,7 +69,7 @@ public class PromptAuthorizationResponse extends ErrorResponse {
}
response.setHeader("HTTP/1.1 401 Access Denied\r\n"
- + "WWW-Authenticate: Basic realm=\"" + failReason.getReason() + "\";");
+ + "WWW-Authenticate: Basic realm=\"" + failReason.getReason() + "\"");
response.setParagraph("Authentication Failed.
Reason: " + reason + "
" + TIPS);
response.replacePlaceholders();
return response;
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/graphs/calendar/PlayerCalendar.java b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/graphs/calendar/PlayerCalendar.java
index 198b6aca8..5fdd255fc 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/graphs/calendar/PlayerCalendar.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/graphs/calendar/PlayerCalendar.java
@@ -118,7 +118,7 @@ public class PlayerCalendar {
.orElse(System.currentTimeMillis()))
.append("}");
- for (PlayerKill kill : session.getUnsafe(SessionKeys.PLAYER_KILLS)) {
+ for (PlayerKill kill : session.getPlayerKills()) {
long time = kill.getDate();
series.append(",{title: 'Killed: ").append(kill.getVictim())
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/graphs/special/PunchCard.java b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/graphs/special/PunchCard.java
index 32339fa29..3cf9fca55 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/graphs/special/PunchCard.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/graphs/special/PunchCard.java
@@ -110,7 +110,7 @@ public class PunchCard implements HighChart {
private List getSessionStarts(Collection data) {
return data.stream()
.filter(Objects::nonNull)
- .map(s -> s.getUnsafe(SessionKeys.START))
+ .map(session -> session.getUnsafe(SessionKeys.START))
.sorted()
.collect(Collectors.toList());
}
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/pages/InspectPage.java b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/pages/InspectPage.java
index c4989bdb6..a8e9eb6bd 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/pages/InspectPage.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/pages/InspectPage.java
@@ -229,7 +229,7 @@ public class InspectPage implements Page {
sessionsAndPlaytime(replacer, sessionsMutator, daySessionsMutator, weekSessionsMutator, monthSessionsMutator);
String punchCardData = graphs.special().punchCard(allSessions).toHighChartsSeries();
- WorldTimes worldTimes = player.getValue(PlayerKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>()));
+ WorldTimes worldTimes = player.getValue(PlayerKeys.WORLD_TIMES).orElse(new WorldTimes());
WorldPie worldPie = graphs.pie().worldPie(worldTimes);
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/RecentLoginList.java b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/RecentLoginList.java
index 9fa72a3ca..b0ca88385 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/RecentLoginList.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/RecentLoginList.java
@@ -25,6 +25,7 @@ import com.djrapitops.plan.utilities.comparators.SessionStartComparator;
import com.djrapitops.plan.utilities.formatting.Formatter;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@@ -85,7 +86,7 @@ public class RecentLoginList {
String name = player.getUnsafe(PlayerKeys.NAME);
long registerDate = player.getValue(PlayerKeys.REGISTERED).orElse(0L);
- List sessions = player.getUnsafe(PlayerKeys.SESSIONS);
+ List sessions = player.getValue(PlayerKeys.SESSIONS).orElse(Collections.emptyList());
if (sessions.isEmpty()) {
continue;
}
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/ServerAccordion.java b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/ServerAccordion.java
index 83e0da852..2f052c905 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/ServerAccordion.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/ServerAccordion.java
@@ -33,7 +33,6 @@ import com.djrapitops.plan.utilities.html.icon.Icon;
import com.djrapitops.plan.utilities.html.icon.Icons;
import com.djrapitops.plugin.utilities.Format;
-import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
@@ -92,7 +91,7 @@ public class ServerAccordion extends Accordion {
UUID serverUUID = entry.getKey();
DataContainer container = entry.getValue();
String serverName = serverNames.getOrDefault(serverUUID, "Unknown");
- WorldTimes worldTimes = container.getValue(PerServerKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>()));
+ WorldTimes worldTimes = container.getValue(PerServerKeys.WORLD_TIMES).orElse(new WorldTimes());
SessionsMutator sessionsMutator = SessionsMutator.forContainer(container);
boolean banned = container.getValue(PerServerKeys.BANNED).orElse(false);
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/SessionAccordion.java b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/SessionAccordion.java
index ed1b1fa58..d4c57c874 100644
--- a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/SessionAccordion.java
+++ b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/SessionAccordion.java
@@ -33,7 +33,10 @@ import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie;
import com.djrapitops.plan.utilities.html.icon.Icons;
import com.djrapitops.plan.utilities.html.tables.HtmlTables;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
import java.util.function.Supplier;
/**
@@ -119,7 +122,7 @@ public class SessionAccordion extends Accordion {
String playerName = playerNames.getOrDefault(session.getValue(SessionKeys.UUID).orElse(null), "Unknown");
String sessionStart = yearFormatter.apply(session);
- WorldTimes worldTimes = session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>()));
+ WorldTimes worldTimes = session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes());
WorldPie worldPie = graphs.pie().worldPie(worldTimes);
String longestWorldPlayed = worldAliasSettings.getLongestWorldPlayed(session);
@@ -191,7 +194,7 @@ public class SessionAccordion extends Accordion {
String serverName = serverNames.getOrDefault(session.getValue(SessionKeys.SERVER_UUID).orElse(null), "Unknown");
String sessionStart = yearFormatter.apply(session);
- WorldTimes worldTimes = session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>()));
+ WorldTimes worldTimes = session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes());
WorldPie worldPie = graphs.pie().worldPie(worldTimes);
String longestWorldPlayed = worldAliasSettings.getLongestWorldPlayed(session);
diff --git a/Plan/common/src/main/resources/bungee.yml b/Plan/common/src/main/resources/bungee.yml
index 99fdbfeb5..ff9e0aa2b 100644
--- a/Plan/common/src/main/resources/bungee.yml
+++ b/Plan/common/src/main/resources/bungee.yml
@@ -1,7 +1,7 @@
name: Plan
author: Rsl1122
main: com.djrapitops.plan.PlanBungee
-version: 4.7.1
+version: 4.7.2
softdepend:
- AdvancedBan
- LiteBans
diff --git a/Plan/common/src/main/resources/bungeeconfig.yml b/Plan/common/src/main/resources/bungeeconfig.yml
index 7a1620e03..7567f6e8e 100644
--- a/Plan/common/src/main/resources/bungeeconfig.yml
+++ b/Plan/common/src/main/resources/bungeeconfig.yml
@@ -163,6 +163,7 @@ Export:
Players_page: false
Server_page: false
Server_JSON: false
+ Export_player_on_login_and_logout: false
# -----------------------------------------------------
# These settings affect Plugin data integration.
# If a plugin is causing issues the integration can be disabled by setting Plugin_name.Enabled: false
diff --git a/Plan/common/src/main/resources/config.yml b/Plan/common/src/main/resources/config.yml
index 09d96755a..30514c56a 100644
--- a/Plan/common/src/main/resources/config.yml
+++ b/Plan/common/src/main/resources/config.yml
@@ -176,6 +176,8 @@ Export:
Players_page: false
Server_page: false
Server_JSON: false
+ # All player pages/JSON can be exported by using /plan m export players
+ Export_player_on_login_and_logout: false
# -----------------------------------------------------
# These settings affect Plugin data integration.
# If a plugin is causing issues the integration can be disabled by setting Plugin_name.Enabled: false
diff --git a/Plan/common/src/main/resources/plugin.yml b/Plan/common/src/main/resources/plugin.yml
index e37486753..4e96517f3 100644
--- a/Plan/common/src/main/resources/plugin.yml
+++ b/Plan/common/src/main/resources/plugin.yml
@@ -1,7 +1,7 @@
name: Plan
author: Rsl1122
main: com.djrapitops.plan.Plan
-version: 4.7.1
+version: 4.7.2
softdepend:
- EssentialsX
- Towny
diff --git a/Plan/common/src/test/java/com/djrapitops/plan/db/CommonDBTest.java b/Plan/common/src/test/java/com/djrapitops/plan/db/CommonDBTest.java
index 1abad4963..02cf890f1 100644
--- a/Plan/common/src/test/java/com/djrapitops/plan/db/CommonDBTest.java
+++ b/Plan/common/src/test/java/com/djrapitops/plan/db/CommonDBTest.java
@@ -32,7 +32,9 @@ import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plan.db.access.Executable;
import com.djrapitops.plan.db.access.Query;
import com.djrapitops.plan.db.access.queries.*;
+import com.djrapitops.plan.db.access.queries.containers.AllPlayerContainersQuery;
import com.djrapitops.plan.db.access.queries.containers.ContainerFetchQueries;
+import com.djrapitops.plan.db.access.queries.containers.ServerPlayerContainersQuery;
import com.djrapitops.plan.db.access.queries.objects.*;
import com.djrapitops.plan.db.access.transactions.BackupCopyTransaction;
import com.djrapitops.plan.db.access.transactions.StoreConfigTransaction;
@@ -73,10 +75,7 @@ import org.junit.rules.TemporaryFolder;
import org.junit.rules.Timeout;
import rules.ComponentMocker;
import rules.PluginComponentMocker;
-import utilities.FieldFetcher;
-import utilities.OptionalAssert;
-import utilities.RandomData;
-import utilities.TestConstants;
+import utilities.*;
import java.io.File;
import java.lang.management.ManagementFactory;
@@ -769,7 +768,7 @@ public abstract class CommonDBTest {
@Test
public void emptyServerWorldTimesIsEmpty() {
WorldTimes worldTimesOfServer = db.query(WorldTimesQueries.fetchServerTotalWorldTimes(serverUUID));
- assertEquals(new WorldTimes(new HashMap<>()), worldTimesOfServer);
+ assertEquals(new WorldTimes(), worldTimesOfServer);
}
@Test
@@ -1036,6 +1035,85 @@ public abstract class CommonDBTest {
assertEquals(expected, result);
}
+ private void executeTransactions(Transaction... transactions) {
+ for (Transaction transaction : transactions) {
+ db.executeTransaction(transaction);
+ }
+ }
+
+ @Test
+ public void baseUsersQueryDoesNotReturnDuplicatePlayers() {
+ db.executeTransaction(TestData.storeServers());
+ executeTransactions(TestData.storePlayerOneData());
+ executeTransactions(TestData.storePlayerTwoData());
+
+ Collection expected = new HashSet<>(Arrays.asList(TestData.getPlayerBaseUser(), TestData.getPlayer2BaseUser()));
+ Collection result = db.query(BaseUserQueries.fetchServerBaseUsers(TestConstants.SERVER_UUID));
+
+ assertEquals(expected, result);
+
+ result = db.query(BaseUserQueries.fetchServerBaseUsers(TestConstants.SERVER_TWO_UUID));
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void serverPlayerContainersQueryDoesNotReturnDuplicatePlayers() {
+ db.executeTransaction(TestData.storeServers());
+ executeTransactions(TestData.storePlayerOneData());
+ executeTransactions(TestData.storePlayerTwoData());
+
+ List expected = Arrays.asList(playerUUID, player2UUID);
+ Collections.sort(expected);
+
+ Collection result = db.query(new ServerPlayerContainersQuery(TestConstants.SERVER_UUID))
+ .stream().map(player -> player.getUnsafe(PlayerKeys.UUID))
+ .sorted()
+ .collect(Collectors.toList());
+
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void allPlayerContainersQueryDoesNotReturnDuplicatePlayers() {
+ db.executeTransaction(TestData.storeServers());
+ executeTransactions(TestData.storePlayerOneData());
+ executeTransactions(TestData.storePlayerTwoData());
+
+ List expected = Arrays.asList(playerUUID, player2UUID);
+ Collections.sort(expected);
+
+ Collection result = db.query(new AllPlayerContainersQuery())
+ .stream().map(player -> player.getUnsafe(PlayerKeys.UUID))
+ .sorted()
+ .collect(Collectors.toList());
+
+ assertEquals(expected, result);
+ }
+
+ // This test is against issue https://github.com/Rsl1122/Plan-PlayerAnalytics/issues/956
+ @Test
+ public void analysisContainerPlayerNamesAreCollectedFromBaseUsersCorrectly() {
+ db.executeTransaction(TestData.storeServers());
+ executeTransactions(TestData.storePlayerOneData());
+ executeTransactions(TestData.storePlayerTwoData());
+
+ BaseUser playerBaseUser = TestData.getPlayerBaseUser();
+ BaseUser player2BaseUser = TestData.getPlayer2BaseUser();
+
+ AnalysisContainer.Factory factory = constructAnalysisContainerFactory();
+ AnalysisContainer analysisContainer = factory.forServerContainer(
+ db.query(ContainerFetchQueries.fetchServerContainer(TestConstants.SERVER_UUID))
+ );
+
+ Map expected = new HashMap<>();
+ expected.put(playerBaseUser.getUuid(), playerBaseUser.getName());
+ expected.put(player2BaseUser.getUuid(), player2BaseUser.getName());
+ Map result = analysisContainer.getValue(AnalysisKeys.PLAYER_NAMES).orElseThrow(AssertionError::new);
+
+ assertEquals(expected, result);
+ }
+
@Test
public void extensionPlayerValuesAreStored() {
ExtensionServiceImplementation extensionService = (ExtensionServiceImplementation) system.getExtensionService();
@@ -1241,5 +1319,4 @@ public abstract class CommonDBTest {
public String stringVal(UUID playerUUID) {
return "Something";
}
- }
}
diff --git a/Plan/common/src/test/java/utilities/TestConstants.java b/Plan/common/src/test/java/utilities/TestConstants.java
index bb94d5aac..7acb2654f 100644
--- a/Plan/common/src/test/java/utilities/TestConstants.java
+++ b/Plan/common/src/test/java/utilities/TestConstants.java
@@ -26,10 +26,12 @@ import java.util.UUID;
public class TestConstants {
public static final UUID SERVER_UUID = UUID.fromString("e4ec2edd-e0ed-3c58-a87d-8a9021899479");
+ public static final UUID SERVER_TWO_UUID = UUID.fromString("c4ec2edd-e0ed-3c58-a87d-8a9024791899");
public static final UUID PLAYER_ONE_UUID = UUID.fromString("45b0dfdb-f71d-4cf3-8c21-27c9d4c651db");
public static final UUID PLAYER_TWO_UUID = UUID.fromString("ec94a954-1fa1-445b-b09b-9b698519af80");
public static final String PLAYER_ONE_NAME = "Test_Player_one";
+ public static final String PLAYER_TWO_NAME = "Test_Player_two";
public static final String WORLD_ONE_NAME = "World One";
diff --git a/Plan/common/src/test/java/utilities/TestData.java b/Plan/common/src/test/java/utilities/TestData.java
new file mode 100644
index 000000000..d1e106cae
--- /dev/null
+++ b/Plan/common/src/test/java/utilities/TestData.java
@@ -0,0 +1,190 @@
+/*
+ * This file is part of Player Analytics (Plan).
+ *
+ * Plan is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License v3 as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Plan is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Plan. If not, see .
+ */
+package utilities;
+
+import com.djrapitops.plan.data.container.BaseUser;
+import com.djrapitops.plan.data.container.GeoInfo;
+import com.djrapitops.plan.data.container.PlayerKill;
+import com.djrapitops.plan.data.container.Session;
+import com.djrapitops.plan.data.time.GMTimes;
+import com.djrapitops.plan.db.access.transactions.StoreServerInformationTransaction;
+import com.djrapitops.plan.db.access.transactions.Transaction;
+import com.djrapitops.plan.db.access.transactions.events.*;
+import com.djrapitops.plan.system.info.server.Server;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Class for saving test data to a database.
+ *
+ * @author Rsl1122
+ */
+public class TestData {
+
+ private static UUID playerUUID = TestConstants.PLAYER_ONE_UUID;
+ private static UUID player2UUID = TestConstants.PLAYER_TWO_UUID;
+ private static UUID serverUUID = TestConstants.SERVER_UUID;
+ private static UUID server2UUID = TestConstants.SERVER_TWO_UUID;
+ private static String playerName = TestConstants.PLAYER_ONE_NAME;
+ private static String player2Name = TestConstants.PLAYER_TWO_NAME;
+
+ private static String[] serverWorldNames = new String[]{
+ TestConstants.WORLD_ONE_NAME, "World Two", "world"
+ };
+ private static String[] server2WorldNames = new String[]{
+ "Foo", "Bar", "Z"
+ };
+
+ private static long playerFirstJoin = 1234500L;
+ private static long playerSecondJoin = 234000L;
+
+ private static List playerSessions = createSessionsForPlayer(playerUUID);
+ private static List player2Sessions = createSessionsForPlayer(player2UUID);
+
+ private static List playerGeoInfo = createGeoInfoForPlayer();
+
+ private static List createGeoInfoForPlayer() {
+ List geoInfos = new ArrayList<>();
+
+ try {
+ geoInfos.add(new GeoInfo(InetAddress.getByName("1.2.3.4"), "Not Known", playerFirstJoin));
+ geoInfos.add(new GeoInfo(InetAddress.getByName("43b9:416b:3cb2:649d:ebaf:872:d89a:343d"), "Not Known", playerFirstJoin));
+ geoInfos.add(new GeoInfo(InetAddress.getByName("127.0.0.1"), "Local Machine", playerFirstJoin));
+ geoInfos.add(new GeoInfo(InetAddress.getByName("181.103.227.78"), "Argentina", playerFirstJoin));
+ } catch (UnknownHostException | NoSuchAlgorithmException e) {
+ Logger.getGlobal().log(Level.WARNING, e, () -> "Failed to create GeoInfo");
+ }
+
+ return geoInfos;
+ }
+
+ private static List createSessionsForPlayer(UUID uuid) {
+ List sessions = new ArrayList<>();
+
+ String[] gms = GMTimes.getGMKeyArray();
+
+ Session sessionOne = new Session(uuid, serverUUID, playerFirstJoin, serverWorldNames[0], gms[0]);
+
+ UUID otherUUID = uuid.equals(playerUUID) ? player2UUID : playerUUID;
+ sessionOne.playerKilled(new PlayerKill(otherUUID, "Iron Sword", 1234750L));
+ sessionOne.playerKilled(new PlayerKill(otherUUID, "Gold Sword", 1234800L));
+
+ sessionOne.endSession(1235000L); // Length 500ms
+ sessions.add(sessionOne);
+
+ Session sessionTwo = new Session(uuid, server2UUID, playerSecondJoin, server2WorldNames[0], gms[1]);
+ sessionTwo.changeState(server2WorldNames[1], gms[0], 334000L); // Length 100s
+ sessionTwo.endSession(434000L); // Length 200s
+ sessions.add(sessionTwo);
+
+ return sessions;
+ }
+
+ public static Transaction storeServers() {
+ return new Transaction() {
+ @Override
+ protected void performOperations() {
+ executeOther(new StoreServerInformationTransaction(new Server(-1, serverUUID, "Server 1", "", 20)));
+ executeOther(new StoreServerInformationTransaction(new Server(-1, server2UUID, "Server 2", "", 50)));
+
+ for (String worldName : serverWorldNames) {
+ executeOther(new WorldNameStoreTransaction(serverUUID, worldName));
+ }
+ for (String worldName : server2WorldNames) {
+ executeOther(new WorldNameStoreTransaction(server2UUID, worldName));
+ }
+ }
+ };
+ }
+
+ public static Transaction[] storePlayerOneData() {
+ return new Transaction[]{
+ new PlayerRegisterTransaction(playerUUID, () -> playerFirstJoin, playerName),
+ new Transaction() {
+ @Override
+ protected void performOperations() {
+ executeOther(new PlayerServerRegisterTransaction(playerUUID, () -> playerFirstJoin, playerName, serverUUID));
+ executeOther(new PlayerServerRegisterTransaction(playerUUID, () -> playerSecondJoin, playerName, server2UUID));
+
+ for (GeoInfo geoInfo : playerGeoInfo) {
+ executeOther(new GeoInfoStoreTransaction(playerUUID, geoInfo));
+ }
+
+ for (Session session : playerSessions) {
+ executeOther(new SessionEndTransaction(session));
+ }
+ }
+ }
+ };
+ }
+
+ public static Transaction[] storePlayerTwoData() {
+ return new Transaction[]{
+ new PlayerRegisterTransaction(player2UUID, () -> playerFirstJoin, player2Name),
+ new Transaction() {
+ @Override
+ protected void performOperations() {
+ executeOther(new PlayerServerRegisterTransaction(player2UUID, () -> playerFirstJoin, player2Name, serverUUID));
+ executeOther(new PlayerServerRegisterTransaction(player2UUID, () -> playerSecondJoin, player2Name, server2UUID));
+
+ for (GeoInfo geoInfo : playerGeoInfo) {
+ executeOther(new GeoInfoStoreTransaction(player2UUID, geoInfo));
+ }
+
+ for (Session session : player2Sessions) {
+ executeOther(new SessionEndTransaction(session));
+ }
+ }
+ }
+ };
+ }
+
+ public static String[] getServerWorldNames() {
+ return serverWorldNames;
+ }
+
+ public static String[] getServer2WorldNames() {
+ return server2WorldNames;
+ }
+
+ public static List getPlayerSessions() {
+ return playerSessions;
+ }
+
+ public static List getPlayer2Sessions() {
+ return player2Sessions;
+ }
+
+ public static List getPlayerGeoInfo() {
+ return playerGeoInfo;
+ }
+
+ public static BaseUser getPlayerBaseUser() {
+ return new BaseUser(playerUUID, playerName, playerFirstJoin, 0);
+ }
+
+ public static BaseUser getPlayer2BaseUser() {
+ return new BaseUser(player2UUID, player2Name, playerFirstJoin, 0);
+ }
+}
\ No newline at end of file
diff --git a/Plan/sponge/src/main/java/com/djrapitops/plan/PlanSponge.java b/Plan/sponge/src/main/java/com/djrapitops/plan/PlanSponge.java
index 127a09ab4..f86998654 100644
--- a/Plan/sponge/src/main/java/com/djrapitops/plan/PlanSponge.java
+++ b/Plan/sponge/src/main/java/com/djrapitops/plan/PlanSponge.java
@@ -42,7 +42,7 @@ import java.io.InputStream;
@Plugin(
id = "plan",
name = "Plan",
- version = "4.7.1",
+ version = "4.7.2",
description = "Player Analytics Plugin by Rsl1122",
authors = {"Rsl1122"},
dependencies = {
diff --git a/Plan/velocity/src/main/java/com/djrapitops/plan/PlanVelocity.java b/Plan/velocity/src/main/java/com/djrapitops/plan/PlanVelocity.java
index 052da5e00..9a2ad8894 100644
--- a/Plan/velocity/src/main/java/com/djrapitops/plan/PlanVelocity.java
+++ b/Plan/velocity/src/main/java/com/djrapitops/plan/PlanVelocity.java
@@ -46,7 +46,7 @@ import java.nio.file.Path;
@Plugin(
id = "plan",
name = "Plan",
- version = "4.7.1",
+ version = "4.7.2",
description = "Player Analytics Plugin by Rsl1122",
authors = {"Rsl1122"}
)
diff --git a/Plan/velocity/src/main/java/com/djrapitops/plan/system/info/server/VelocityServerInfo.java b/Plan/velocity/src/main/java/com/djrapitops/plan/system/info/server/VelocityServerInfo.java
index 8ac96a8f4..04f82ca65 100644
--- a/Plan/velocity/src/main/java/com/djrapitops/plan/system/info/server/VelocityServerInfo.java
+++ b/Plan/velocity/src/main/java/com/djrapitops/plan/system/info/server/VelocityServerInfo.java
@@ -59,7 +59,7 @@ public class VelocityServerInfo extends ServerInfo {
}
@Override
- public Server loadServerInfo() throws EnableException {
+ public void loadServerInfo() throws EnableException {
checkIfDefaultIP();
try {
@@ -76,7 +76,6 @@ public class VelocityServerInfo extends ServerInfo {
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
- return server;
}
private void updateServerInfo(Database db) {
diff --git a/PlanPluginBridge/pom.xml b/PlanPluginBridge/pom.xml
index 5342ffe3f..cf17561ed 100644
--- a/PlanPluginBridge/pom.xml
+++ b/PlanPluginBridge/pom.xml
@@ -180,7 +180,7 @@
io.github.nucleuspowered
nucleus-api
- 1.9.0-S7.1
+ 1.9.2-S7.1
provided