From 69c54fb5cbef3fac3a5ee3c4651af7b82248389e Mon Sep 17 00:00:00 2001 From: Aurora Lahtela <24460436+AuroraLS3@users.noreply.github.com> Date: Mon, 11 Apr 2022 19:07:52 +0300 Subject: [PATCH] Fix some issues with data registering for new users --- .../bukkit/PlayerOnlineListener.java | 46 ++++++++++--------- .../bungee/PlayerOnlineListener.java | 24 +++++----- .../exceptions/database/DBOpException.java | 9 ++++ .../plan/storage/database/Database.java | 4 +- .../plan/storage/database/SQLDB.java | 7 ++- .../queries/analysis/PlayerCountQueries.java | 2 +- .../fabric/PlayerOnlineListener.java | 45 +++++++++--------- .../nukkit/PlayerOnlineListener.java | 46 ++++++++++--------- .../sponge/PlayerOnlineListener.java | 44 +++++++++--------- .../velocity/PlayerOnlineListener.java | 25 +++++----- 10 files changed, 139 insertions(+), 113 deletions(-) diff --git a/Plan/bukkit/src/main/java/com/djrapitops/plan/gathering/listeners/bukkit/PlayerOnlineListener.java b/Plan/bukkit/src/main/java/com/djrapitops/plan/gathering/listeners/bukkit/PlayerOnlineListener.java index 043a9e0a8..eac71670c 100644 --- a/Plan/bukkit/src/main/java/com/djrapitops/plan/gathering/listeners/bukkit/PlayerOnlineListener.java +++ b/Plan/bukkit/src/main/java/com/djrapitops/plan/gathering/listeners/bukkit/PlayerOnlineListener.java @@ -177,32 +177,34 @@ public class PlayerOnlineListener implements Listener { String playerName = player.getName(); String displayName = player.getDisplayName(); - boolean gatheringGeolocations = config.isTrue(DataGatheringSettings.GEOLOCATIONS); - if (gatheringGeolocations) { - database.executeTransaction( - new GeoInfoStoreTransaction(playerUUID, address, time, geolocationCache::getCountry) - ); - } - database.executeTransaction(new PlayerServerRegisterTransaction(playerUUID, - player::getFirstPlayed, playerName, serverUUID, getHostName)); - database.executeTransaction(new OperatorStatusTransaction(playerUUID, serverUUID, player.isOp())); + player::getFirstPlayed, playerName, serverUUID, getHostName)) + .thenRunAsync(() -> { + boolean gatheringGeolocations = config.isTrue(DataGatheringSettings.GEOLOCATIONS); + if (gatheringGeolocations) { + database.executeTransaction( + new GeoInfoStoreTransaction(playerUUID, address, time, geolocationCache::getCountry) + ); + } - ActiveSession session = new ActiveSession(playerUUID, serverUUID, time, world, gm); - session.getExtraData().put(PlayerName.class, new PlayerName(playerName)); - session.getExtraData().put(ServerName.class, new ServerName(serverInfo.getServer().getIdentifiableName())); - sessionCache.cacheSession(playerUUID, session) - .ifPresent(previousSession -> database.executeTransaction(new SessionEndTransaction(previousSession))); + database.executeTransaction(new OperatorStatusTransaction(playerUUID, serverUUID, player.isOp())); - database.executeTransaction(new NicknameStoreTransaction( - playerUUID, new Nickname(displayName, time, serverUUID), - (uuid, name) -> nicknameCache.getDisplayName(playerUUID).map(name::equals).orElse(false) - )); + ActiveSession session = new ActiveSession(playerUUID, serverUUID, time, world, gm); + session.getExtraData().put(PlayerName.class, new PlayerName(playerName)); + session.getExtraData().put(ServerName.class, new ServerName(serverInfo.getServer().getIdentifiableName())); + sessionCache.cacheSession(playerUUID, session) + .ifPresent(previousSession -> database.executeTransaction(new SessionEndTransaction(previousSession))); - processing.submitNonCritical(() -> extensionService.updatePlayerValues(playerUUID, playerName, CallEvents.PLAYER_JOIN)); - if (config.isTrue(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE)) { - processing.submitNonCritical(() -> exporter.exportPlayerPage(playerUUID, playerName)); - } + database.executeTransaction(new NicknameStoreTransaction( + playerUUID, new Nickname(displayName, time, serverUUID), + (uuid, name) -> nicknameCache.getDisplayName(playerUUID).map(name::equals).orElse(false) + )); + + processing.submitNonCritical(() -> extensionService.updatePlayerValues(playerUUID, playerName, CallEvents.PLAYER_JOIN)); + if (config.isTrue(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE)) { + processing.submitNonCritical(() -> exporter.exportPlayerPage(playerUUID, playerName)); + } + }); } private String getHostname(Player player) { diff --git a/Plan/bungeecord/src/main/java/com/djrapitops/plan/gathering/listeners/bungee/PlayerOnlineListener.java b/Plan/bungeecord/src/main/java/com/djrapitops/plan/gathering/listeners/bungee/PlayerOnlineListener.java index 17185f6cb..59f25e3ef 100644 --- a/Plan/bungeecord/src/main/java/com/djrapitops/plan/gathering/listeners/bungee/PlayerOnlineListener.java +++ b/Plan/bungeecord/src/main/java/com/djrapitops/plan/gathering/listeners/bungee/PlayerOnlineListener.java @@ -108,18 +108,20 @@ public class PlayerOnlineListener implements Listener { sessionCache.cacheSession(playerUUID, session); Database database = dbSystem.getDatabase(); - boolean gatheringGeolocations = config.isTrue(DataGatheringSettings.GEOLOCATIONS); - if (gatheringGeolocations) { - database.executeTransaction( - new GeoInfoStoreTransaction(playerUUID, address, time, geolocationCache::getCountry) - ); - } + database.executeTransaction(new PlayerRegisterTransaction(playerUUID, () -> time, playerName)) + .thenRunAsync(() -> { + boolean gatheringGeolocations = config.isTrue(DataGatheringSettings.GEOLOCATIONS); + if (gatheringGeolocations) { + database.executeTransaction( + new GeoInfoStoreTransaction(playerUUID, address, time, geolocationCache::getCountry) + ); + } - database.executeTransaction(new PlayerRegisterTransaction(playerUUID, () -> time, playerName)); - processing.submitNonCritical(() -> extensionService.updatePlayerValues(playerUUID, playerName, CallEvents.PLAYER_JOIN)); - if (config.isTrue(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE)) { - processing.submitNonCritical(() -> exporter.exportPlayerPage(playerUUID, playerName)); - } + processing.submitNonCritical(() -> extensionService.updatePlayerValues(playerUUID, playerName, CallEvents.PLAYER_JOIN)); + if (config.isTrue(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE)) { + processing.submitNonCritical(() -> exporter.exportPlayerPage(playerUUID, playerName)); + } + }); } @EventHandler(priority = EventPriority.NORMAL) diff --git a/Plan/common/src/main/java/com/djrapitops/plan/exceptions/database/DBOpException.java b/Plan/common/src/main/java/com/djrapitops/plan/exceptions/database/DBOpException.java index c415d5a69..7f4dffa54 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/exceptions/database/DBOpException.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/exceptions/database/DBOpException.java @@ -53,6 +53,10 @@ public class DBOpException extends IllegalStateException implements ExceptionWit context.related("Error code: " + errorCode) .related(sql); switch (errorCode) { + case 0: + context.related("Connection aquisition error") + .whatToDo("Failed to aquire connection. Try increasing 'Database.MySQL.Max_connections' setting."); + break; // SQLite Corrupt case 10: case 523: @@ -129,6 +133,11 @@ public class DBOpException extends IllegalStateException implements ExceptionWit context.related("Incorrect character encoding in MySQL") .whatToDo("Convert your MySQL database and tables to use utf8mb4: https://www.a2hosting.com/kb/developer-corner/mysql/convert-mysql-database-utf-8"); break; + case 1048: + // MySQL + context.related("Not null constraint violation") + .whatToDo("Report this error. NOT NULL constraint violation occurred."); + break; default: context.related("Unknown SQL Error code"); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/Database.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/Database.java index 13eeaf013..ae2086ee3 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/Database.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/Database.java @@ -21,7 +21,7 @@ import com.djrapitops.plan.storage.database.queries.Query; import com.djrapitops.plan.storage.database.sql.building.Sql; import com.djrapitops.plan.storage.database.transactions.Transaction; -import java.util.concurrent.Future; +import java.util.concurrent.CompletableFuture; /** * Interface for interacting with a Plan SQL database. @@ -58,7 +58,7 @@ public interface Database { * @param transaction Transaction to execute. * @return Future that is finished when the transaction has been executed. */ - Future executeTransaction(Transaction transaction); + CompletableFuture executeTransaction(Transaction transaction); /** * Used to get the {@code DBType} of the Database diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/SQLDB.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/SQLDB.java index 761be24c0..1ab0aa09b 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/SQLDB.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/SQLDB.java @@ -49,7 +49,10 @@ import org.apache.commons.lang3.concurrent.BasicThreadFactory; import java.sql.Connection; import java.sql.SQLException; import java.util.*; -import java.util.concurrent.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.Supplier; @@ -305,7 +308,7 @@ public abstract class SQLDB extends AbstractDatabase { } @Override - public Future executeTransaction(Transaction transaction) { + public CompletableFuture executeTransaction(Transaction transaction) { if (getState() == State.CLOSED) { throw new DBOpException("Transaction tried to execute although database is closed."); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/analysis/PlayerCountQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/analysis/PlayerCountQueries.java index 5cd6d994c..04c6529f4 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/analysis/PlayerCountQueries.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/analysis/PlayerCountQueries.java @@ -343,7 +343,7 @@ public class PlayerCountQueries { } public static Query> newPlayerCounts(long after, long before) { - String sql = SELECT + ServerTable.SERVER_UUID + ",COUNT(1) as player_count" + + String sql = SELECT + "s." + ServerTable.SERVER_UUID + ",COUNT(1) as player_count" + FROM + UserInfoTable.TABLE_NAME + INNER_JOIN + ServerTable.TABLE_NAME + " s on s." + ServerTable.ID + '=' + UserInfoTable.TABLE_NAME + '.' + UserInfoTable.SERVER_ID + WHERE + UserInfoTable.REGISTERED + "<=?" + diff --git a/Plan/fabric/src/main/java/net/playeranalytics/plan/gathering/listeners/fabric/PlayerOnlineListener.java b/Plan/fabric/src/main/java/net/playeranalytics/plan/gathering/listeners/fabric/PlayerOnlineListener.java index d449ba979..bc36926d0 100644 --- a/Plan/fabric/src/main/java/net/playeranalytics/plan/gathering/listeners/fabric/PlayerOnlineListener.java +++ b/Plan/fabric/src/main/java/net/playeranalytics/plan/gathering/listeners/fabric/PlayerOnlineListener.java @@ -188,32 +188,35 @@ public class PlayerOnlineListener implements FabricListener { String playerName = player.getEntityName(); String displayName = player.getDisplayName().asString(); - boolean gatheringGeolocations = config.isTrue(DataGatheringSettings.GEOLOCATIONS); - if (gatheringGeolocations) { - database.executeTransaction( - new GeoInfoStoreTransaction(playerUUID, address, time, geolocationCache::getCountry) - ); - } database.executeTransaction(new PlayerServerRegisterTransaction(playerUUID, - System::currentTimeMillis, playerName, serverUUID, getHostName)); - database.executeTransaction(new OperatorStatusTransaction(playerUUID, serverUUID, server.getPlayerManager().getOpList().isOp(player.getGameProfile()))); + System::currentTimeMillis, playerName, serverUUID, getHostName)) + .thenRunAsync(() -> { + boolean gatheringGeolocations = config.isTrue(DataGatheringSettings.GEOLOCATIONS); + if (gatheringGeolocations) { + database.executeTransaction( + new GeoInfoStoreTransaction(playerUUID, address, time, geolocationCache::getCountry) + ); + } - ActiveSession session = new ActiveSession(playerUUID, serverUUID, time, world, gm); - session.getExtraData().put(PlayerName.class, new PlayerName(playerName)); - session.getExtraData().put(ServerName.class, new ServerName(serverInfo.getServer().getIdentifiableName())); - sessionCache.cacheSession(playerUUID, session) - .ifPresent(previousSession -> database.executeTransaction(new SessionEndTransaction(previousSession))); + database.executeTransaction(new OperatorStatusTransaction(playerUUID, serverUUID, server.getPlayerManager().getOpList().isOp(player.getGameProfile()))); - database.executeTransaction(new NicknameStoreTransaction( - playerUUID, new Nickname(displayName, time, serverUUID), - (uuid, name) -> nicknameCache.getDisplayName(playerUUID).map(name::equals).orElse(false) - )); + ActiveSession session = new ActiveSession(playerUUID, serverUUID, time, world, gm); + session.getExtraData().put(PlayerName.class, new PlayerName(playerName)); + session.getExtraData().put(ServerName.class, new ServerName(serverInfo.getServer().getIdentifiableName())); + sessionCache.cacheSession(playerUUID, session) + .ifPresent(previousSession -> database.executeTransaction(new SessionEndTransaction(previousSession))); - processing.submitNonCritical(() -> extensionService.updatePlayerValues(playerUUID, playerName, CallEvents.PLAYER_JOIN)); - if (config.isTrue(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE)) { - processing.submitNonCritical(() -> exporter.exportPlayerPage(playerUUID, playerName)); - } + database.executeTransaction(new NicknameStoreTransaction( + playerUUID, new Nickname(displayName, time, serverUUID), + (uuid, name) -> nicknameCache.getDisplayName(playerUUID).map(name::equals).orElse(false) + )); + + processing.submitNonCritical(() -> extensionService.updatePlayerValues(playerUUID, playerName, CallEvents.PLAYER_JOIN)); + if (config.isTrue(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE)) { + processing.submitNonCritical(() -> exporter.exportPlayerPage(playerUUID, playerName)); + } + }); } private String getHostname(ServerPlayerEntity player) { diff --git a/Plan/nukkit/src/main/java/com/djrapitops/plan/gathering/listeners/nukkit/PlayerOnlineListener.java b/Plan/nukkit/src/main/java/com/djrapitops/plan/gathering/listeners/nukkit/PlayerOnlineListener.java index 9ba9a6af1..f59165c1f 100644 --- a/Plan/nukkit/src/main/java/com/djrapitops/plan/gathering/listeners/nukkit/PlayerOnlineListener.java +++ b/Plan/nukkit/src/main/java/com/djrapitops/plan/gathering/listeners/nukkit/PlayerOnlineListener.java @@ -167,33 +167,35 @@ public class PlayerOnlineListener implements Listener { String playerName = player.getName(); String displayName = player.getDisplayName(); - boolean gatheringGeolocations = config.isTrue(DataGatheringSettings.GEOLOCATIONS); - if (gatheringGeolocations) { - database.executeTransaction( - new GeoInfoStoreTransaction(playerUUID, address, time, geolocationCache::getCountry) - ); - } - long registerDate = TimeUnit.SECONDS.toMillis(player.getFirstPlayed()); database.executeTransaction(new PlayerServerRegisterTransaction(playerUUID, () -> registerDate, - playerName, serverUUID, getHostName)); - dbSystem.getDatabase().executeTransaction(new OperatorStatusTransaction(playerUUID, serverUUID, player.isOp())); + playerName, serverUUID, getHostName)) + .thenRunAsync(() -> { + boolean gatheringGeolocations = config.isTrue(DataGatheringSettings.GEOLOCATIONS); + if (gatheringGeolocations) { + database.executeTransaction( + new GeoInfoStoreTransaction(playerUUID, address, time, geolocationCache::getCountry) + ); + } - ActiveSession session = new ActiveSession(playerUUID, serverUUID, time, world, gm); - session.getExtraData().put(PlayerName.class, new PlayerName(playerName)); - session.getExtraData().put(ServerName.class, new ServerName(serverInfo.getServer().getIdentifiableName())); - sessionCache.cacheSession(playerUUID, session) - .ifPresent(previousSession -> database.executeTransaction(new SessionEndTransaction(previousSession))); + dbSystem.getDatabase().executeTransaction(new OperatorStatusTransaction(playerUUID, serverUUID, player.isOp())); - database.executeTransaction(new NicknameStoreTransaction( - playerUUID, new Nickname(displayName, time, serverUUID), - (uuid, name) -> nicknameCache.getDisplayName(playerUUID).map(name::equals).orElse(false) - )); + ActiveSession session = new ActiveSession(playerUUID, serverUUID, time, world, gm); + session.getExtraData().put(PlayerName.class, new PlayerName(playerName)); + session.getExtraData().put(ServerName.class, new ServerName(serverInfo.getServer().getIdentifiableName())); + sessionCache.cacheSession(playerUUID, session) + .ifPresent(previousSession -> database.executeTransaction(new SessionEndTransaction(previousSession))); - processing.submitNonCritical(() -> extensionService.updatePlayerValues(playerUUID, playerName, CallEvents.PLAYER_JOIN)); - if (config.isTrue(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE)) { - processing.submitNonCritical(() -> exporter.exportPlayerPage(playerUUID, playerName)); - } + database.executeTransaction(new NicknameStoreTransaction( + playerUUID, new Nickname(displayName, time, serverUUID), + (uuid, name) -> nicknameCache.getDisplayName(playerUUID).map(name::equals).orElse(false) + )); + + processing.submitNonCritical(() -> extensionService.updatePlayerValues(playerUUID, playerName, CallEvents.PLAYER_JOIN)); + if (config.isTrue(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE)) { + processing.submitNonCritical(() -> exporter.exportPlayerPage(playerUUID, playerName)); + } + }); } @EventHandler(priority = EventPriority.NORMAL) diff --git a/Plan/sponge/src/main/java/com/djrapitops/plan/gathering/listeners/sponge/PlayerOnlineListener.java b/Plan/sponge/src/main/java/com/djrapitops/plan/gathering/listeners/sponge/PlayerOnlineListener.java index f5dd4cf22..acd08447a 100644 --- a/Plan/sponge/src/main/java/com/djrapitops/plan/gathering/listeners/sponge/PlayerOnlineListener.java +++ b/Plan/sponge/src/main/java/com/djrapitops/plan/gathering/listeners/sponge/PlayerOnlineListener.java @@ -170,30 +170,32 @@ public class PlayerOnlineListener { String playerName = player.getName(); String displayName = player.getDisplayNameData().displayName().get().toPlain(); - boolean gatheringGeolocations = config.isTrue(DataGatheringSettings.GEOLOCATIONS); - if (gatheringGeolocations) { - database.executeTransaction( - new GeoInfoStoreTransaction(playerUUID, address, time, geolocationCache::getCountry) - ); - } - database.executeTransaction(new PlayerServerRegisterTransaction(playerUUID, () -> time, - playerName, serverUUID, getHostName)); - ActiveSession session = new ActiveSession(playerUUID, serverUUID, time, world, gm); - session.getExtraData().put(PlayerName.class, new PlayerName(playerName)); - session.getExtraData().put(ServerName.class, new ServerName(serverInfo.getServer().getIdentifiableName())); - sessionCache.cacheSession(playerUUID, session) - .ifPresent(previousSession -> database.executeTransaction(new SessionEndTransaction(previousSession))); + playerName, serverUUID, getHostName)) + .thenRunAsync(() -> { + boolean gatheringGeolocations = config.isTrue(DataGatheringSettings.GEOLOCATIONS); + if (gatheringGeolocations) { + database.executeTransaction( + new GeoInfoStoreTransaction(playerUUID, address, time, geolocationCache::getCountry) + ); + } - database.executeTransaction(new NicknameStoreTransaction( - playerUUID, new Nickname(displayName, time, serverUUID), - (uuid, name) -> nicknameCache.getDisplayName(playerUUID).map(name::equals).orElse(false) - )); + ActiveSession session = new ActiveSession(playerUUID, serverUUID, time, world, gm); + session.getExtraData().put(PlayerName.class, new PlayerName(playerName)); + session.getExtraData().put(ServerName.class, new ServerName(serverInfo.getServer().getIdentifiableName())); + sessionCache.cacheSession(playerUUID, session) + .ifPresent(previousSession -> database.executeTransaction(new SessionEndTransaction(previousSession))); - processing.submitNonCritical(() -> extensionService.updatePlayerValues(playerUUID, playerName, CallEvents.PLAYER_JOIN)); - if (config.isTrue(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE)) { - processing.submitNonCritical(() -> exporter.exportPlayerPage(playerUUID, playerName)); - } + database.executeTransaction(new NicknameStoreTransaction( + playerUUID, new Nickname(displayName, time, serverUUID), + (uuid, name) -> nicknameCache.getDisplayName(playerUUID).map(name::equals).orElse(false) + )); + + processing.submitNonCritical(() -> extensionService.updatePlayerValues(playerUUID, playerName, CallEvents.PLAYER_JOIN)); + if (config.isTrue(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE)) { + processing.submitNonCritical(() -> exporter.exportPlayerPage(playerUUID, playerName)); + } + }); } @Listener(order = Order.DEFAULT) diff --git a/Plan/velocity/src/main/java/com/djrapitops/plan/gathering/listeners/velocity/PlayerOnlineListener.java b/Plan/velocity/src/main/java/com/djrapitops/plan/gathering/listeners/velocity/PlayerOnlineListener.java index e951e54f3..75070bc47 100644 --- a/Plan/velocity/src/main/java/com/djrapitops/plan/gathering/listeners/velocity/PlayerOnlineListener.java +++ b/Plan/velocity/src/main/java/com/djrapitops/plan/gathering/listeners/velocity/PlayerOnlineListener.java @@ -113,18 +113,21 @@ public class PlayerOnlineListener { Database database = dbSystem.getDatabase(); - boolean gatheringGeolocations = config.isTrue(DataGatheringSettings.GEOLOCATIONS); - if (gatheringGeolocations) { - database.executeTransaction( - new GeoInfoStoreTransaction(playerUUID, address, time, geolocationCache::getCountry) - ); - } - database.executeTransaction(new PlayerRegisterTransaction(playerUUID, () -> time, playerName)); - processing.submitNonCritical(() -> extensionService.updatePlayerValues(playerUUID, playerName, CallEvents.PLAYER_JOIN)); - if (config.isTrue(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE)) { - processing.submitNonCritical(() -> exporter.exportPlayerPage(playerUUID, playerName)); - } + database.executeTransaction(new PlayerRegisterTransaction(playerUUID, () -> time, playerName)) + .thenRunAsync(() -> { + boolean gatheringGeolocations = config.isTrue(DataGatheringSettings.GEOLOCATIONS); + if (gatheringGeolocations) { + database.executeTransaction( + new GeoInfoStoreTransaction(playerUUID, address, time, geolocationCache::getCountry) + ); + } + + processing.submitNonCritical(() -> extensionService.updatePlayerValues(playerUUID, playerName, CallEvents.PLAYER_JOIN)); + if (config.isTrue(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE)) { + processing.submitNonCritical(() -> exporter.exportPlayerPage(playerUUID, playerName)); + } + }); } @Subscribe(order = PostOrder.NORMAL)