diff --git a/api/src/main/java/net/william278/husksync/bukkit/api/HuskSyncAPI.java b/api/src/main/java/net/william278/husksync/bukkit/api/HuskSyncAPI.java
index 375f4ded..48a4df32 100644
--- a/api/src/main/java/net/william278/husksync/bukkit/api/HuskSyncAPI.java
+++ b/api/src/main/java/net/william278/husksync/bukkit/api/HuskSyncAPI.java
@@ -33,7 +33,7 @@ public class HuskSyncAPI {
}
/**
- * (INTERNAL) Map of API requests that are processed by the bukkit plugin that implements the API.
+ * (Internal only) Map of API requests that are processed by the bukkit plugin that implements the API.
*/
public static HashMap> apiRequests = new HashMap<>();
@@ -47,7 +47,7 @@ public class HuskSyncAPI {
public CompletableFuture getPlayerData(UUID playerUUID) throws IOException {
// Create the request to be completed
final UUID requestUUID = UUID.randomUUID();
- apiRequests.put(requestUUID, new CompletableFuture<>());
+ apiRequests.put(requestUUID, new CompletableFuture<>());
// Remove the request from the map on completion
apiRequests.get(requestUUID).whenComplete((playerData, throwable) -> apiRequests.remove(requestUUID));
diff --git a/bukkit/src/main/java/net/william278/husksync/HuskSyncBukkit.java b/bukkit/src/main/java/net/william278/husksync/HuskSyncBukkit.java
index 164d07e9..4757bc31 100644
--- a/bukkit/src/main/java/net/william278/husksync/HuskSyncBukkit.java
+++ b/bukkit/src/main/java/net/william278/husksync/HuskSyncBukkit.java
@@ -144,7 +144,7 @@ public final class HuskSyncBukkit extends JavaPlugin {
if (HuskSyncBukkit.handshakeCompleted && !HuskSyncBukkit.isMySqlPlayerDataBridgeInstalled && Bukkit.getOnlinePlayers().size() > 0) {
getLogger().info("Saving data for remaining online players...");
for (Player player : Bukkit.getOnlinePlayers()) {
- PlayerSetter.updatePlayerData(player);
+ PlayerSetter.updatePlayerData(player, false);
}
getLogger().info("Data save complete!");
}
diff --git a/bukkit/src/main/java/net/william278/husksync/bukkit/config/ConfigLoader.java b/bukkit/src/main/java/net/william278/husksync/bukkit/config/ConfigLoader.java
index 82a38d27..52d50cd7 100644
--- a/bukkit/src/main/java/net/william278/husksync/bukkit/config/ConfigLoader.java
+++ b/bukkit/src/main/java/net/william278/husksync/bukkit/config/ConfigLoader.java
@@ -27,6 +27,7 @@ public class ConfigLoader {
Settings.syncFlight = config.getBoolean("synchronisation_settings.flight", false);
Settings.useNativeImplementation = config.getBoolean("native_advancement_synchronization", false);
+ Settings.saveOnWorldSave = config.getBoolean("save_on_world_save", true);
Settings.synchronizationTimeoutRetryDelay = config.getLong("synchronization_timeout_retry_delay", 15L);
}
diff --git a/bukkit/src/main/java/net/william278/husksync/bukkit/listener/BukkitEventListener.java b/bukkit/src/main/java/net/william278/husksync/bukkit/listener/BukkitEventListener.java
index a823aeea..0f16ddb7 100644
--- a/bukkit/src/main/java/net/william278/husksync/bukkit/listener/BukkitEventListener.java
+++ b/bukkit/src/main/java/net/william278/husksync/bukkit/listener/BukkitEventListener.java
@@ -15,6 +15,7 @@ import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.*;
+import org.bukkit.event.world.WorldSaveEvent;
import java.io.IOException;
import java.util.logging.Level;
@@ -38,7 +39,7 @@ public class BukkitEventListener implements Listener {
return; // If the plugin has not been initialized correctly
// Update the player's data
- Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> PlayerSetter.updatePlayerData(player));
+ Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> PlayerSetter.updatePlayerData(player, true));
}
@EventHandler(priority = EventPriority.LOWEST)
@@ -145,4 +146,14 @@ public class BukkitEventListener implements Listener {
event.setCancelled(true); // If the plugin / player has not been set
}
}
+
+ @EventHandler(priority = EventPriority.NORMAL)
+ public void onWorldSave(WorldSaveEvent event) {
+ if (!plugin.isEnabled() || !HuskSyncBukkit.handshakeCompleted) {
+ return;
+ }
+ for (Player playerInWorld : event.getWorld().getPlayers()) {
+ PlayerSetter.updatePlayerData(playerInWorld, false);
+ }
+ }
}
diff --git a/bukkit/src/main/java/net/william278/husksync/bukkit/util/PlayerSetter.java b/bukkit/src/main/java/net/william278/husksync/bukkit/util/PlayerSetter.java
index 00434b3d..ec819ed6 100644
--- a/bukkit/src/main/java/net/william278/husksync/bukkit/util/PlayerSetter.java
+++ b/bukkit/src/main/java/net/william278/husksync/bukkit/util/PlayerSetter.java
@@ -95,15 +95,16 @@ public class PlayerSetter {
/**
* Update a {@link Player}'s data, sending it to the proxy
*
- * @param player {@link Player} to send data to proxy
+ * @param player {@link Player} to send data to proxy
+ * @param bounceBack whether the plugin should bounce-back the updated data to the player (used for server switching)
*/
- public static void updatePlayerData(Player player) {
+ public static void updatePlayerData(Player player, boolean bounceBack) {
// Send a redis message with the player's last updated PlayerData version UUID and their new PlayerData
try {
final String serializedPlayerData = getNewSerializedPlayerData(player);
new RedisMessage(RedisMessage.MessageType.PLAYER_DATA_UPDATE,
new RedisMessage.MessageTarget(Settings.ServerType.PROXY, null, Settings.cluster),
- serializedPlayerData).send();
+ serializedPlayerData, Boolean.toString(bounceBack)).send();
} catch (IOException e) {
plugin.getLogger().log(Level.SEVERE, "Failed to send a PlayerData update to the proxy", e);
}
@@ -280,7 +281,7 @@ public class PlayerSetter {
final Object playerAdvancements = AdvancementUtils.getPlayerAdvancements(player);
// Clear
- AdvancementUtils.clearPlayerAdvancements(playerAdvancements);
+ AdvancementUtils.clearPlayerAdvancements(playerAdvancements);
AdvancementUtils.clearVisibleAdvancements(playerAdvancements);
advancementRecords.forEach(advancementRecord -> {
diff --git a/bukkit/src/main/resources/config.yml b/bukkit/src/main/resources/config.yml
index d0c7e7e2..1fb6a37b 100644
--- a/bukkit/src/main/resources/config.yml
+++ b/bukkit/src/main/resources/config.yml
@@ -18,4 +18,5 @@ synchronisation_settings:
cluster_id: 'main'
check_for_updates: true
synchronization_timeout_retry_delay: 15
+save_on_world_save: true
native_advancement_synchronization: false
\ No newline at end of file
diff --git a/bungeecord/src/main/java/net/william278/husksync/bungeecord/listener/BungeeRedisListener.java b/bungeecord/src/main/java/net/william278/husksync/bungeecord/listener/BungeeRedisListener.java
index 377acb42..966726a3 100644
--- a/bungeecord/src/main/java/net/william278/husksync/bungeecord/listener/BungeeRedisListener.java
+++ b/bungeecord/src/main/java/net/william278/husksync/bungeecord/listener/BungeeRedisListener.java
@@ -92,7 +92,8 @@ public class BungeeRedisListener extends RedisListener {
case PLAYER_DATA_UPDATE -> ProxyServer.getInstance().getScheduler().runAsync(plugin, () -> {
// Deserialize the PlayerData received
PlayerData playerData;
- final String serializedPlayerData = message.getMessageData();
+ final String serializedPlayerData = message.getMessageDataElements()[0];
+ final boolean bounceBack = Boolean.parseBoolean(message.getMessageDataElements()[1]);
try {
playerData = (PlayerData) RedisMessage.deserialize(serializedPlayerData);
} catch (IOException | ClassNotFoundException e) {
@@ -110,7 +111,7 @@ public class BungeeRedisListener extends RedisListener {
}
// Reply with the player data if they are still online (switching server)
- if (Settings.bounceBackSynchronisation) {
+ if (Settings.bounceBackSynchronisation && bounceBack) {
try {
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(playerData.getPlayerUUID());
if (player != null) {
diff --git a/common/src/main/java/net/william278/husksync/Settings.java b/common/src/main/java/net/william278/husksync/Settings.java
index 7e0cea9c..19712f90 100644
--- a/common/src/main/java/net/william278/husksync/Settings.java
+++ b/common/src/main/java/net/william278/husksync/Settings.java
@@ -70,8 +70,8 @@ public class Settings {
public static boolean syncAdvancements;
public static boolean syncLocation;
public static boolean syncFlight;
-
public static long synchronizationTimeoutRetryDelay;
+ public static boolean saveOnWorldSave;
public static boolean useNativeImplementation;
// This Cluster ID
diff --git a/velocity/src/main/java/net/william278/husksync/velocity/listener/VelocityRedisListener.java b/velocity/src/main/java/net/william278/husksync/velocity/listener/VelocityRedisListener.java
index 5ac95d91..e37eec47 100644
--- a/velocity/src/main/java/net/william278/husksync/velocity/listener/VelocityRedisListener.java
+++ b/velocity/src/main/java/net/william278/husksync/velocity/listener/VelocityRedisListener.java
@@ -89,7 +89,8 @@ public class VelocityRedisListener extends RedisListener {
case PLAYER_DATA_UPDATE -> plugin.getProxyServer().getScheduler().buildTask(plugin, () -> {
// Deserialize the PlayerData received
PlayerData playerData;
- final String serializedPlayerData = message.getMessageData();
+ final String serializedPlayerData = message.getMessageDataElements()[0];
+ final boolean bounceBack = Boolean.parseBoolean(message.getMessageDataElements()[1]);
try {
playerData = (PlayerData) RedisMessage.deserialize(serializedPlayerData);
} catch (IOException | ClassNotFoundException e) {
@@ -107,7 +108,7 @@ public class VelocityRedisListener extends RedisListener {
}
// Reply with the player data if they are still online (switching server)
- if (Settings.bounceBackSynchronisation) {
+ if (Settings.bounceBackSynchronisation && bounceBack) {
Optional updatingPlayer = plugin.getProxyServer().getPlayer(playerData.getPlayerUUID());
updatingPlayer.ifPresent(player -> {
try {