Async proxy data setting and fetching; add timestamp API to player data; add option for bounceBackSyncrhonization

feat/data-edit-commands
William 3 years ago
parent b7e6861f03
commit c5e0640f83

@ -51,8 +51,9 @@ public class BukkitEventListener implements Listener {
// Mark the player as awaiting data fetch // Mark the player as awaiting data fetch
HuskSyncBukkit.bukkitCache.setAwaitingDataFetch(player.getUniqueId()); HuskSyncBukkit.bukkitCache.setAwaitingDataFetch(player.getUniqueId());
if (!HuskSyncBukkit.handshakeCompleted || HuskSyncBukkit.isMySqlPlayerDataBridgeInstalled) if (!HuskSyncBukkit.handshakeCompleted || HuskSyncBukkit.isMySqlPlayerDataBridgeInstalled) {
return; // If the data handshake has not been completed yet (or MySqlPlayerDataBridge is installed) return; // If the data handshake has not been completed yet (or MySqlPlayerDataBridge is installed)
}
// Send a redis message requesting the player data (if they need to) // Send a redis message requesting the player data (if they need to)
if (HuskSyncBukkit.bukkitCache.isPlayerRequestingOnJoin(player.getUniqueId())) { if (HuskSyncBukkit.bukkitCache.isPlayerRequestingOnJoin(player.getUniqueId())) {
@ -64,7 +65,7 @@ public class BukkitEventListener implements Listener {
} }
}); });
} else { } else {
// If the player's data wasn't set after 20 ticks, ensure it will be // If the player's data wasn't set after the synchronization timeout retry delay ticks, ensure it will be
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, () -> { Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, () -> {
if (player.isOnline()) { if (player.isOnline()) {
try { try {

@ -330,7 +330,7 @@ public class PlayerSetter {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
// Apply the advancements to the player // Apply the advancements to the player
Iterator<Advancement> serverAdvancements = Bukkit.getServer().advancementIterator(); final Iterator<Advancement> serverAdvancements = Bukkit.getServer().advancementIterator();
while (serverAdvancements.hasNext()) { // Iterate through all advancements while (serverAdvancements.hasNext()) { // Iterate through all advancements
boolean correctExperienceCheck = false; // Determines whether the experience might have changed warranting an update boolean correctExperienceCheck = false; // Determines whether the experience might have changed warranting an update
Advancement advancement = serverAdvancements.next(); Advancement advancement = serverAdvancements.next();

@ -60,6 +60,8 @@ public class ConfigLoader {
Settings.hikariKeepAliveTime = config.getLong("data_storage_settings.hikari_pool_settings.keepalive_time", 0); Settings.hikariKeepAliveTime = config.getLong("data_storage_settings.hikari_pool_settings.keepalive_time", 0);
Settings.hikariConnectionTimeOut = config.getLong("data_storage_settings.hikari_pool_settings.connection_timeout", 5000); Settings.hikariConnectionTimeOut = config.getLong("data_storage_settings.hikari_pool_settings.connection_timeout", 5000);
Settings.bounceBackSynchronisation = config.getBoolean("bounce_back_synchronization", true);
// Read cluster data // Read cluster data
Configuration section = config.getSection("clusters"); Configuration section = config.getSection("clusters");
final String settingDatabaseName = Settings.mySQLDatabase != null ? Settings.mySQLDatabase : "HuskSync"; final String settingDatabaseName = Settings.mySQLDatabase != null ? Settings.mySQLDatabase : "HuskSync";

@ -63,37 +63,33 @@ public class BungeeRedisListener extends RedisListener {
} }
switch (message.getMessageType()) { switch (message.getMessageType()) {
case PLAYER_DATA_REQUEST -> { case PLAYER_DATA_REQUEST -> ProxyServer.getInstance().getScheduler().runAsync(plugin, () -> {
// Get the UUID of the requesting player // Get the UUID of the requesting player
final UUID requestingPlayerUUID = UUID.fromString(message.getMessageData()); final UUID requestingPlayerUUID = UUID.fromString(message.getMessageData());
ProxyServer.getInstance().getScheduler().runAsync(plugin, () -> { try {
try { // Send the reply, serializing the message data
// Send the reply, serializing the message data new RedisMessage(RedisMessage.MessageType.PLAYER_DATA_SET,
new RedisMessage(RedisMessage.MessageType.PLAYER_DATA_SET, new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, requestingPlayerUUID, message.getMessageTarget().targetClusterId()),
new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, requestingPlayerUUID, message.getMessageTarget().targetClusterId()), RedisMessage.serialize(getPlayerCachedData(requestingPlayerUUID, message.getMessageTarget().targetClusterId())))
RedisMessage.serialize(getPlayerCachedData(requestingPlayerUUID, message.getMessageTarget().targetClusterId()))) .send();
.send();
// Send an update to all bukkit servers removing the player from the requester cache // Send an update to all bukkit servers removing the player from the requester cache
new RedisMessage(RedisMessage.MessageType.REQUEST_DATA_ON_JOIN, new RedisMessage(RedisMessage.MessageType.REQUEST_DATA_ON_JOIN,
new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, null, message.getMessageTarget().targetClusterId()), new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, null, message.getMessageTarget().targetClusterId()),
RedisMessage.RequestOnJoinUpdateType.REMOVE_REQUESTER.toString(), requestingPlayerUUID.toString()) RedisMessage.RequestOnJoinUpdateType.REMOVE_REQUESTER.toString(), requestingPlayerUUID.toString())
.send(); .send();
// Send synchronisation complete message // Send synchronisation complete message
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(requestingPlayerUUID); ProxiedPlayer player = ProxyServer.getInstance().getPlayer(requestingPlayerUUID);
if (player != null) { if (player != null) {
if (player.isConnected()) { player.sendMessage(ChatMessageType.ACTION_BAR, new MineDown(MessageManager.getMessage("synchronisation_complete")).toComponent());
player.sendMessage(ChatMessageType.ACTION_BAR, new MineDown(MessageManager.getMessage("synchronisation_complete")).toComponent());
}
}
} catch (IOException e) {
log(Level.SEVERE, "Failed to serialize data when replying to a data request");
e.printStackTrace();
} }
}); } catch (IOException e) {
} log(Level.SEVERE, "Failed to serialize data when replying to a data request");
case PLAYER_DATA_UPDATE -> { e.printStackTrace();
}
});
case PLAYER_DATA_UPDATE -> ProxyServer.getInstance().getScheduler().runAsync(plugin, () -> {
// Deserialize the PlayerData received // Deserialize the PlayerData received
PlayerData playerData; PlayerData playerData;
final String serializedPlayerData = message.getMessageData(); final String serializedPlayerData = message.getMessageData();
@ -114,10 +110,10 @@ public class BungeeRedisListener extends RedisListener {
} }
// Reply with the player data if they are still online (switching server) // Reply with the player data if they are still online (switching server)
try { if (Settings.bounceBackSynchronisation) {
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(playerData.getPlayerUUID()); try {
if (player != null) { ProxiedPlayer player = ProxyServer.getInstance().getPlayer(playerData.getPlayerUUID());
if (player.isConnected()) { if (player != null) {
new RedisMessage(RedisMessage.MessageType.PLAYER_DATA_SET, new RedisMessage(RedisMessage.MessageType.PLAYER_DATA_SET,
new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, playerData.getPlayerUUID(), message.getMessageTarget().targetClusterId()), new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, playerData.getPlayerUUID(), message.getMessageTarget().targetClusterId()),
serializedPlayerData) serializedPlayerData)
@ -126,12 +122,12 @@ public class BungeeRedisListener extends RedisListener {
// Send synchronisation complete message // Send synchronisation complete message
player.sendMessage(ChatMessageType.ACTION_BAR, new MineDown(MessageManager.getMessage("synchronisation_complete")).toComponent()); player.sendMessage(ChatMessageType.ACTION_BAR, new MineDown(MessageManager.getMessage("synchronisation_complete")).toComponent());
} }
} catch (IOException e) {
log(Level.SEVERE, "Failed to re-serialize PlayerData when handling a player update request");
e.printStackTrace();
} }
} catch (IOException e) {
log(Level.SEVERE, "Failed to re-serialize PlayerData when handling a player update request");
e.printStackTrace();
} }
} });
case CONNECTION_HANDSHAKE -> { case CONNECTION_HANDSHAKE -> {
// Reply to a Bukkit server's connection handshake to complete the process // Reply to a Bukkit server's connection handshake to complete the process
if (HuskSyncBungeeCord.isDisabling) return; // Return if the Proxy is disabling if (HuskSyncBungeeCord.isDisabling) return; // Return if the Proxy is disabling
@ -198,10 +194,9 @@ public class BungeeRedisListener extends RedisListener {
HuskSyncBungeeCord.dataManager)); HuskSyncBungeeCord.dataManager));
} }
} }
case API_DATA_REQUEST -> { case API_DATA_REQUEST -> ProxyServer.getInstance().getScheduler().runAsync(plugin, () -> {
final UUID playerUUID = UUID.fromString(message.getMessageDataElements()[0]); final UUID playerUUID = UUID.fromString(message.getMessageDataElements()[0]);
final UUID requestUUID = UUID.fromString(message.getMessageDataElements()[1]); final UUID requestUUID = UUID.fromString(message.getMessageDataElements()[1]);
try { try {
final PlayerData data = getPlayerCachedData(playerUUID, message.getMessageTarget().targetClusterId()); final PlayerData data = getPlayerCachedData(playerUUID, message.getMessageTarget().targetClusterId());
@ -221,7 +216,7 @@ public class BungeeRedisListener extends RedisListener {
} catch (IOException e) { } catch (IOException e) {
plugin.getBungeeLogger().log(Level.SEVERE, "Failed to serialize PlayerData requested via the API"); plugin.getBungeeLogger().log(Level.SEVERE, "Failed to serialize PlayerData requested via the API");
} }
} });
} }
} }

@ -1,6 +1,7 @@
package me.william278.husksync; package me.william278.husksync;
import java.io.*; import java.io.*;
import java.time.Instant;
import java.util.UUID; import java.util.UUID;
/** /**
@ -18,6 +19,11 @@ public class PlayerData implements Serializable {
*/ */
private final UUID dataVersionUUID; private final UUID dataVersionUUID;
/**
* Epoch time identifying when the data was last updated or created
*/
private long timestamp;
/** /**
* A special flag that will be {@code true} if the player is new to the network and should not have their data set when joining the Bukkit * A special flag that will be {@code true} if the player is new to the network and should not have their data set when joining the Bukkit
*/ */
@ -70,6 +76,7 @@ public class PlayerData implements Serializable {
String serializedStatusEffects, int totalExperience, int expLevel, float expProgress, String gameMode, String serializedStatusEffects, int totalExperience, int expLevel, float expProgress, String gameMode,
String serializedStatistics, boolean isFlying, String serializedAdvancements, String serializedLocation) { String serializedStatistics, boolean isFlying, String serializedAdvancements, String serializedLocation) {
this.dataVersionUUID = UUID.randomUUID(); this.dataVersionUUID = UUID.randomUUID();
this.timestamp = Instant.now().getEpochSecond();
this.playerUUID = playerUUID; this.playerUUID = playerUUID;
this.serializedInventory = serializedInventory; this.serializedInventory = serializedInventory;
this.serializedEnderChest = serializedEnderChest; this.serializedEnderChest = serializedEnderChest;
@ -109,16 +116,17 @@ public class PlayerData implements Serializable {
* @param totalExperience Their total experience points ("Score") * @param totalExperience Their total experience points ("Score")
* @param expLevel Their exp level * @param expLevel Their exp level
* @param expProgress Their exp progress to the next level * @param expProgress Their exp progress to the next level
* @param gameMode Their game mode ({@code SURVIVAL}, {@code CREATIVE}, etc) * @param gameMode Their game mode ({@code SURVIVAL}, {@code CREATIVE}, etc.)
* @param serializedStatistics Their serialized statistics data (Displayed in Statistics menu in ESC menu) * @param serializedStatistics Their serialized statistics data (Displayed in Statistics menu in ESC menu)
*/ */
public PlayerData(UUID playerUUID, UUID dataVersionUUID, String serializedInventory, String serializedEnderChest, public PlayerData(UUID playerUUID, UUID dataVersionUUID, long timestamp, String serializedInventory, String serializedEnderChest,
double health, double maxHealth, double healthScale, int hunger, float saturation, float saturationExhaustion, double health, double maxHealth, double healthScale, int hunger, float saturation, float saturationExhaustion,
int selectedSlot, String serializedStatusEffects, int totalExperience, int expLevel, float expProgress, int selectedSlot, String serializedStatusEffects, int totalExperience, int expLevel, float expProgress,
String gameMode, String serializedStatistics, boolean isFlying, String serializedAdvancements, String gameMode, String serializedStatistics, boolean isFlying, String serializedAdvancements,
String serializedLocation) { String serializedLocation) {
this.playerUUID = playerUUID; this.playerUUID = playerUUID;
this.dataVersionUUID = dataVersionUUID; this.dataVersionUUID = dataVersionUUID;
this.timestamp = timestamp;
this.serializedInventory = serializedInventory; this.serializedInventory = serializedInventory;
this.serializedEnderChest = serializedEnderChest; this.serializedEnderChest = serializedEnderChest;
this.health = health; this.health = health;
@ -172,6 +180,15 @@ public class PlayerData implements Serializable {
return dataVersionUUID; return dataVersionUUID;
} }
/**
* Get the timestamp when this data was created or last updated
*
* @return time since epoch of last data update or creation
*/
public long getDataTimestamp() {
return timestamp;
}
/** /**
* Returns the serialized player {@code ItemStack[]} inventory * Returns the serialized player {@code ItemStack[]} inventory
* *
@ -341,6 +358,7 @@ public class PlayerData implements Serializable {
*/ */
public void setSerializedInventory(String serializedInventory) { public void setSerializedInventory(String serializedInventory) {
this.serializedInventory = serializedInventory; this.serializedInventory = serializedInventory;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -350,6 +368,7 @@ public class PlayerData implements Serializable {
*/ */
public void setSerializedEnderChest(String serializedEnderChest) { public void setSerializedEnderChest(String serializedEnderChest) {
this.serializedEnderChest = serializedEnderChest; this.serializedEnderChest = serializedEnderChest;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -359,6 +378,7 @@ public class PlayerData implements Serializable {
*/ */
public void setHealth(double health) { public void setHealth(double health) {
this.health = health; this.health = health;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -368,6 +388,7 @@ public class PlayerData implements Serializable {
*/ */
public void setMaxHealth(double maxHealth) { public void setMaxHealth(double maxHealth) {
this.maxHealth = maxHealth; this.maxHealth = maxHealth;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -377,6 +398,7 @@ public class PlayerData implements Serializable {
*/ */
public void setHealthScale(double healthScale) { public void setHealthScale(double healthScale) {
this.healthScale = healthScale; this.healthScale = healthScale;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -386,6 +408,7 @@ public class PlayerData implements Serializable {
*/ */
public void setHunger(int hunger) { public void setHunger(int hunger) {
this.hunger = hunger; this.hunger = hunger;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -395,6 +418,7 @@ public class PlayerData implements Serializable {
*/ */
public void setSaturation(float saturation) { public void setSaturation(float saturation) {
this.saturation = saturation; this.saturation = saturation;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -404,6 +428,7 @@ public class PlayerData implements Serializable {
*/ */
public void setSaturationExhaustion(float saturationExhaustion) { public void setSaturationExhaustion(float saturationExhaustion) {
this.saturationExhaustion = saturationExhaustion; this.saturationExhaustion = saturationExhaustion;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -413,6 +438,7 @@ public class PlayerData implements Serializable {
*/ */
public void setSelectedSlot(int selectedSlot) { public void setSelectedSlot(int selectedSlot) {
this.selectedSlot = selectedSlot; this.selectedSlot = selectedSlot;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -422,6 +448,7 @@ public class PlayerData implements Serializable {
*/ */
public void setSerializedEffectData(String serializedEffectData) { public void setSerializedEffectData(String serializedEffectData) {
this.serializedEffectData = serializedEffectData; this.serializedEffectData = serializedEffectData;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -431,6 +458,7 @@ public class PlayerData implements Serializable {
*/ */
public void setTotalExperience(int totalExperience) { public void setTotalExperience(int totalExperience) {
this.totalExperience = totalExperience; this.totalExperience = totalExperience;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -440,6 +468,7 @@ public class PlayerData implements Serializable {
*/ */
public void setExpLevel(int expLevel) { public void setExpLevel(int expLevel) {
this.expLevel = expLevel; this.expLevel = expLevel;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -449,6 +478,7 @@ public class PlayerData implements Serializable {
*/ */
public void setExpProgress(float expProgress) { public void setExpProgress(float expProgress) {
this.expProgress = expProgress; this.expProgress = expProgress;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -458,6 +488,7 @@ public class PlayerData implements Serializable {
*/ */
public void setGameMode(String gameMode) { public void setGameMode(String gameMode) {
this.gameMode = gameMode; this.gameMode = gameMode;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -467,6 +498,7 @@ public class PlayerData implements Serializable {
*/ */
public void setSerializedStatistics(String serializedStatistics) { public void setSerializedStatistics(String serializedStatistics) {
this.serializedStatistics = serializedStatistics; this.serializedStatistics = serializedStatistics;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -476,6 +508,7 @@ public class PlayerData implements Serializable {
*/ */
public void setFlying(boolean flying) { public void setFlying(boolean flying) {
isFlying = flying; isFlying = flying;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -485,6 +518,7 @@ public class PlayerData implements Serializable {
*/ */
public void setSerializedAdvancements(String serializedAdvancements) { public void setSerializedAdvancements(String serializedAdvancements) {
this.serializedAdvancements = serializedAdvancements; this.serializedAdvancements = serializedAdvancements;
this.timestamp = Instant.now().getEpochSecond();
} }
/** /**
@ -494,5 +528,6 @@ public class PlayerData implements Serializable {
*/ */
public void setSerializedLocation(String serializedLocation) { public void setSerializedLocation(String serializedLocation) {
this.serializedLocation = serializedLocation; this.serializedLocation = serializedLocation;
this.timestamp = Instant.now().getEpochSecond();
} }
} }

@ -36,6 +36,9 @@ public class Settings {
// SQL settings // SQL settings
public static DataStorageType dataStorageType; public static DataStorageType dataStorageType;
// Bounce-back synchronisation (default)
public static boolean bounceBackSynchronisation;
// MySQL specific settings // MySQL specific settings
public static String mySQLHost; public static String mySQLHost;
public static String mySQLDatabase; public static String mySQLDatabase;

@ -184,7 +184,7 @@ public class DataManager {
ResultSet resultSet = statement.executeQuery(); ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) { if (resultSet.next()) {
final UUID dataVersionUUID = UUID.fromString(resultSet.getString("version_uuid")); final UUID dataVersionUUID = UUID.fromString(resultSet.getString("version_uuid"));
//final Timestamp dataSaveTimestamp = resultSet.getTimestamp("timestamp"); final Timestamp dataSaveTimestamp = resultSet.getTimestamp("timestamp");
final String serializedInventory = resultSet.getString("inventory"); final String serializedInventory = resultSet.getString("inventory");
final String serializedEnderChest = resultSet.getString("ender_chest"); final String serializedEnderChest = resultSet.getString("ender_chest");
final double health = resultSet.getDouble("health"); final double health = resultSet.getDouble("health");
@ -204,10 +204,10 @@ public class DataManager {
final String serializedLocationData = resultSet.getString("location"); final String serializedLocationData = resultSet.getString("location");
final String serializedStatisticData = resultSet.getString("statistics"); final String serializedStatisticData = resultSet.getString("statistics");
data.put(cluster, new PlayerData(playerUUID, dataVersionUUID, serializedInventory, serializedEnderChest, data.put(cluster, new PlayerData(playerUUID, dataVersionUUID, dataSaveTimestamp.toInstant().getEpochSecond(),
health, maxHealth, healthScale, hunger, saturation, saturationExhaustion, selectedSlot, serializedStatusEffects, serializedInventory, serializedEnderChest, health, maxHealth, healthScale, hunger, saturation,
totalExperience, expLevel, expProgress, gameMode, serializedStatisticData, isFlying, saturationExhaustion, selectedSlot, serializedStatusEffects, totalExperience, expLevel, expProgress,
serializedAdvancementData, serializedLocationData)); gameMode, serializedStatisticData, isFlying, serializedAdvancementData, serializedLocationData));
} else { } else {
data.put(cluster, PlayerData.DEFAULT_PLAYER_DATA(playerUUID)); data.put(cluster, PlayerData.DEFAULT_PLAYER_DATA(playerUUID));
} }

@ -19,6 +19,7 @@ data_storage_settings:
maximum_lifetime: 1800000 maximum_lifetime: 1800000
keepalive_time: 0 keepalive_time: 0
connection_timeout: 5000 connection_timeout: 5000
bounce_back_synchronization: true
clusters: clusters:
main: main:
player_table: 'husksync_players' player_table: 'husksync_players'

@ -75,6 +75,8 @@ public class ConfigLoader {
Settings.hikariKeepAliveTime = getConfigLong(config, 0, "data_storage_settings", "hikari_pool_settings", "keepalive_time"); Settings.hikariKeepAliveTime = getConfigLong(config, 0, "data_storage_settings", "hikari_pool_settings", "keepalive_time");
Settings.hikariConnectionTimeOut = getConfigLong(config, 5000, "data_storage_settings", "hikari_pool_settings", "connection_timeout"); Settings.hikariConnectionTimeOut = getConfigLong(config, 5000, "data_storage_settings", "hikari_pool_settings", "connection_timeout");
Settings.bounceBackSynchronisation = getConfigBoolean(config, true,"bounce_back_synchronization");
// Read cluster data // Read cluster data
ConfigurationNode clusterSection = config.getNode("clusters"); ConfigurationNode clusterSection = config.getNode("clusters");
final String settingDatabaseName = Settings.mySQLDatabase != null ? Settings.mySQLDatabase : "HuskSync"; final String settingDatabaseName = Settings.mySQLDatabase != null ? Settings.mySQLDatabase : "HuskSync";

@ -62,33 +62,31 @@ public class VelocityRedisListener extends RedisListener {
} }
switch (message.getMessageType()) { switch (message.getMessageType()) {
case PLAYER_DATA_REQUEST -> { case PLAYER_DATA_REQUEST -> plugin.getProxyServer().getScheduler().buildTask(plugin, () -> {
// Get the UUID of the requesting player // Get the UUID of the requesting player
final UUID requestingPlayerUUID = UUID.fromString(message.getMessageData()); final UUID requestingPlayerUUID = UUID.fromString(message.getMessageData());
plugin.getProxyServer().getScheduler().buildTask(plugin, () -> { try {
try { // Send the reply, serializing the message data
// Send the reply, serializing the message data new RedisMessage(RedisMessage.MessageType.PLAYER_DATA_SET,
new RedisMessage(RedisMessage.MessageType.PLAYER_DATA_SET, new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, requestingPlayerUUID, message.getMessageTarget().targetClusterId()),
new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, requestingPlayerUUID, message.getMessageTarget().targetClusterId()), RedisMessage.serialize(getPlayerCachedData(requestingPlayerUUID, message.getMessageTarget().targetClusterId())))
RedisMessage.serialize(getPlayerCachedData(requestingPlayerUUID, message.getMessageTarget().targetClusterId()))) .send();
.send();
// Send an update to all bukkit servers removing the player from the requester cache // Send an update to all bukkit servers removing the player from the requester cache
new RedisMessage(RedisMessage.MessageType.REQUEST_DATA_ON_JOIN, new RedisMessage(RedisMessage.MessageType.REQUEST_DATA_ON_JOIN,
new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, null, message.getMessageTarget().targetClusterId()), new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, null, message.getMessageTarget().targetClusterId()),
RedisMessage.RequestOnJoinUpdateType.REMOVE_REQUESTER.toString(), requestingPlayerUUID.toString()) RedisMessage.RequestOnJoinUpdateType.REMOVE_REQUESTER.toString(), requestingPlayerUUID.toString())
.send(); .send();
// Send synchronisation complete message // Send synchronisation complete message
Optional<Player> player = plugin.getProxyServer().getPlayer(requestingPlayerUUID); Optional<Player> player = plugin.getProxyServer().getPlayer(requestingPlayerUUID);
player.ifPresent(value -> value.sendActionBar(new MineDown(MessageManager.getMessage("synchronisation_complete")).toComponent())); player.ifPresent(value -> value.sendActionBar(new MineDown(MessageManager.getMessage("synchronisation_complete")).toComponent()));
} catch (IOException e) { } catch (IOException e) {
log(Level.SEVERE, "Failed to serialize data when replying to a data request"); log(Level.SEVERE, "Failed to serialize data when replying to a data request");
e.printStackTrace(); e.printStackTrace();
} }
}).schedule(); }).schedule();
} case PLAYER_DATA_UPDATE -> plugin.getProxyServer().getScheduler().buildTask(plugin, () -> {
case PLAYER_DATA_UPDATE -> {
// Deserialize the PlayerData received // Deserialize the PlayerData received
PlayerData playerData; PlayerData playerData;
final String serializedPlayerData = message.getMessageData(); final String serializedPlayerData = message.getMessageData();
@ -109,23 +107,24 @@ public class VelocityRedisListener extends RedisListener {
} }
// Reply with the player data if they are still online (switching server) // Reply with the player data if they are still online (switching server)
Optional<Player> updatingPlayer = plugin.getProxyServer().getPlayer(playerData.getPlayerUUID()); if (Settings.bounceBackSynchronisation) {
updatingPlayer.ifPresent(player -> { Optional<Player> updatingPlayer = plugin.getProxyServer().getPlayer(playerData.getPlayerUUID());
try { updatingPlayer.ifPresent(player -> {
new RedisMessage(RedisMessage.MessageType.PLAYER_DATA_SET, try {
new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, playerData.getPlayerUUID(), message.getMessageTarget().targetClusterId()), new RedisMessage(RedisMessage.MessageType.PLAYER_DATA_SET,
RedisMessage.serialize(playerData)) new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, playerData.getPlayerUUID(), message.getMessageTarget().targetClusterId()),
.send(); RedisMessage.serialize(playerData))
.send();
// Send synchronisation complete message
player.sendActionBar(new MineDown(MessageManager.getMessage("synchronisation_complete")).toComponent()); // Send synchronisation complete message
} catch (IOException e) { player.sendActionBar(new MineDown(MessageManager.getMessage("synchronisation_complete")).toComponent());
log(Level.SEVERE, "Failed to re-serialize PlayerData when handling a player update request"); } catch (IOException e) {
e.printStackTrace(); log(Level.SEVERE, "Failed to re-serialize PlayerData when handling a player update request");
} e.printStackTrace();
}); }
});
} }
}).schedule();
case CONNECTION_HANDSHAKE -> { case CONNECTION_HANDSHAKE -> {
// Reply to a Bukkit server's connection handshake to complete the process // Reply to a Bukkit server's connection handshake to complete the process
if (HuskSyncVelocity.isDisabling) return; // Return if the Proxy is disabling if (HuskSyncVelocity.isDisabling) return; // Return if the Proxy is disabling
@ -191,7 +190,7 @@ public class VelocityRedisListener extends RedisListener {
migrator.loadIncomingData(migrator.incomingPlayerData, HuskSyncVelocity.dataManager); migrator.loadIncomingData(migrator.incomingPlayerData, HuskSyncVelocity.dataManager);
} }
} }
case API_DATA_REQUEST -> { case API_DATA_REQUEST -> plugin.getProxyServer().getScheduler().buildTask(plugin, () -> {
final UUID playerUUID = UUID.fromString(message.getMessageDataElements()[0]); final UUID playerUUID = UUID.fromString(message.getMessageDataElements()[0]);
final UUID requestUUID = UUID.fromString(message.getMessageDataElements()[1]); final UUID requestUUID = UUID.fromString(message.getMessageDataElements()[1]);
@ -214,7 +213,7 @@ public class VelocityRedisListener extends RedisListener {
} catch (IOException e) { } catch (IOException e) {
plugin.getVelocityLogger().log(Level.SEVERE, "Failed to serialize PlayerData requested via the API"); plugin.getVelocityLogger().log(Level.SEVERE, "Failed to serialize PlayerData requested via the API");
} }
} }).schedule();
} }
} }

Loading…
Cancel
Save