Add information command

feat/data-edit-commands
William 3 years ago
parent ba8e4ee175
commit 9198cd648f

@ -1,5 +1,5 @@
# CrossServerSync # CrossServerSync
**CrossServerSync** is a robust solution for synchronising player data (inventories, health, hunger & status effects) between servers. It was designed as a lightweight alternative to MySQLPlayerDataBridge, **CrossServerSync** is a robust solution for synchronising player data (inventories, health, hunger & status effects) between servers. It was designed as a much faster alternative to MySQLPlayerDataBridge,
### Installation ### Installation
Install CrossServerSync in the `/plugins/` folder of your Spigot (and derivatives) servers and Proxy (BungeeCord and derivatives) server. Install CrossServerSync in the `/plugins/` folder of your Spigot (and derivatives) servers and Proxy (BungeeCord and derivatives) server.

@ -4,6 +4,7 @@ dependencies {
implementation 'org.bstats:bstats-bukkit:2.2.1' implementation 'org.bstats:bstats-bukkit:2.2.1'
implementation 'redis.clients:jedis:3.7.0' implementation 'redis.clients:jedis:3.7.0'
implementation 'de.themoep:minedown:1.7.1-SNAPSHOT'
compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT' compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT'
} }
@ -11,6 +12,7 @@ dependencies {
shadowJar { shadowJar {
relocate 'redis.clients', 'me.William278.crossserversync.libraries.jedis' relocate 'redis.clients', 'me.William278.crossserversync.libraries.jedis'
relocate 'org.bstats', 'me.William278.crossserversync.libraries.plan' relocate 'org.bstats', 'me.William278.crossserversync.libraries.plan'
relocate 'de.themoep', 'me.William278.crossserversync.libraries.minedown'
} }
tasks.register('prepareKotlinBuildScriptModel'){} tasks.register('prepareKotlinBuildScriptModel'){}

@ -27,7 +27,9 @@ public class PlayerSetter {
player.setMaxHealth(data.getMaxHealth()); player.setMaxHealth(data.getMaxHealth());
player.setFoodLevel(data.getHunger()); player.setFoodLevel(data.getHunger());
player.setSaturation(data.getSaturation()); player.setSaturation(data.getSaturation());
player.setExhaustion(data.getSaturationExhaustion());
player.getInventory().setHeldItemSlot(data.getSelectedSlot()); player.getInventory().setHeldItemSlot(data.getSelectedSlot());
//todo potion effects not working //todo potion effects not working
setPlayerPotionEffects(player, DataSerializer.potionEffectArrayFromBase64(data.getSerializedEffectData())); setPlayerPotionEffects(player, DataSerializer.potionEffectArrayFromBase64(data.getSerializedEffectData()));
} catch (IOException e) { } catch (IOException e) {

@ -1,5 +1,7 @@
package me.william278.crossserversync.bukkit.listener; package me.william278.crossserversync.bukkit.listener;
import de.themoep.minedown.MineDown;
import me.william278.crossserversync.MessageStrings;
import me.william278.crossserversync.PlayerData; import me.william278.crossserversync.PlayerData;
import me.william278.crossserversync.Settings; import me.william278.crossserversync.Settings;
import me.william278.crossserversync.CrossServerSyncBukkit; import me.william278.crossserversync.CrossServerSyncBukkit;
@ -35,19 +37,33 @@ public class BukkitRedisListener extends RedisListener {
// Handle the message for the player // Handle the message for the player
for (Player player : Bukkit.getOnlinePlayers()) { for (Player player : Bukkit.getOnlinePlayers()) {
if (player.getUniqueId().equals(message.getMessageTarget().targetPlayerUUID())) { if (player.getUniqueId().equals(message.getMessageTarget().targetPlayerUUID())) {
if (message.getMessageType().equals(RedisMessage.MessageType.PLAYER_DATA_REPLY)) { switch (message.getMessageType()) {
try { case PLAYER_DATA_SET -> {
// Deserialize the received PlayerData try {
PlayerData data = (PlayerData) RedisMessage.deserialize(message.getMessageData()); // Deserialize the received PlayerData
PlayerData data = (PlayerData) RedisMessage.deserialize(message.getMessageData());
// Set the player's data // Set the player's data
PlayerSetter.setPlayerFrom(player, data); PlayerSetter.setPlayerFrom(player, data);
// Update last loaded data UUID // Update last loaded data UUID
CrossServerSyncBukkit.lastDataUpdateUUIDCache.setVersionUUID(player.getUniqueId(), data.getDataVersionUUID()); CrossServerSyncBukkit.lastDataUpdateUUIDCache.setVersionUUID(player.getUniqueId(), data.getDataVersionUUID());
} catch (IOException | ClassNotFoundException e) { } catch (IOException | ClassNotFoundException e) {
log(Level.SEVERE, "Failed to deserialize PlayerData when handling a reply from the proxy with PlayerData"); log(Level.SEVERE, "Failed to deserialize PlayerData when handling a reply from the proxy with PlayerData");
e.printStackTrace(); e.printStackTrace();
}
}
case SEND_PLUGIN_INFORMATION -> {
String proxyBrand = message.getMessageDataElements()[0];
String proxyVersion = message.getMessageDataElements()[1];
assert plugin.getDescription().getDescription() != null;
player.spigot().sendMessage(new MineDown(MessageStrings.PLUGIN_INFORMATION.toString()
.replaceAll("%plugin_description%", plugin.getDescription().getDescription())
.replaceAll("%proxy_brand%", proxyBrand)
.replaceAll("%proxy_version%", proxyVersion)
.replaceAll("%bukkit_brand%", Bukkit.getName())
.replaceAll("%bukkit_version%", plugin.getDescription().getVersion()))
.toComponent());
} }
} }
return; return;

@ -33,6 +33,7 @@ public class EventListener implements Listener {
player.getMaxHealth(), player.getMaxHealth(),
player.getFoodLevel(), player.getFoodLevel(),
player.getSaturation(), player.getSaturation(),
player.getExhaustion(),
player.getInventory().getHeldItemSlot(), player.getInventory().getHeldItemSlot(),
DataSerializer.getSerializedEffectData(player))); DataSerializer.getSerializedEffectData(player)));
} }

@ -4,6 +4,7 @@ dependencies {
implementation 'redis.clients:jedis:3.7.0' implementation 'redis.clients:jedis:3.7.0'
implementation 'com.zaxxer:HikariCP:5.0.0' implementation 'com.zaxxer:HikariCP:5.0.0'
implementation 'de.themoep:minedown:1.7.1-SNAPSHOT'
compileOnly 'net.md-5:bungeecord-api:1.16-R0.5-SNAPSHOT' compileOnly 'net.md-5:bungeecord-api:1.16-R0.5-SNAPSHOT'
} }
@ -12,6 +13,7 @@ shadowJar {
relocate 'redis.clients', 'me.William278.crossserversync.libraries.jedis' relocate 'redis.clients', 'me.William278.crossserversync.libraries.jedis'
relocate 'com.zaxxer', 'me.William278.crossserversync.libraries.hikari' relocate 'com.zaxxer', 'me.William278.crossserversync.libraries.hikari'
relocate 'org.bstats', 'me.William278.crossserversync.libraries.plan' relocate 'org.bstats', 'me.William278.crossserversync.libraries.plan'
relocate 'de.themoep', 'me.William278.crossserversync.libraries.minedown'
} }
tasks.register('prepareKotlinBuildScriptModel'){} tasks.register('prepareKotlinBuildScriptModel'){}

@ -1,5 +1,6 @@
package me.william278.crossserversync; package me.william278.crossserversync;
import me.william278.crossserversync.bungeecord.command.CrossServerSyncCommand;
import me.william278.crossserversync.bungeecord.config.ConfigLoader; import me.william278.crossserversync.bungeecord.config.ConfigLoader;
import me.william278.crossserversync.bungeecord.config.ConfigManager; import me.william278.crossserversync.bungeecord.config.ConfigManager;
import me.william278.crossserversync.bungeecord.data.DataManager; import me.william278.crossserversync.bungeecord.data.DataManager;
@ -51,9 +52,12 @@ public final class CrossServerSyncBungeeCord extends Plugin {
// Setup player data cache // Setup player data cache
DataManager.playerDataCache = new DataManager.PlayerDataCache(); DataManager.playerDataCache = new DataManager.PlayerDataCache();
// Initialize PreLoginEvent listener // Register listener
getProxy().getPluginManager().registerListener(this, new BungeeEventListener()); getProxy().getPluginManager().registerListener(this, new BungeeEventListener());
// Register command
getProxy().getPluginManager().registerCommand(this, new CrossServerSyncCommand());
// Initialize the redis listener // Initialize the redis listener
new BungeeRedisListener(); new BungeeRedisListener();

@ -0,0 +1,73 @@
package me.william278.crossserversync.bungeecord.command;
import de.themoep.minedown.MineDown;
import me.william278.crossserversync.CrossServerSyncBungeeCord;
import me.william278.crossserversync.MessageStrings;
import me.william278.crossserversync.Settings;
import me.william278.crossserversync.redis.RedisMessage;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.TabExecutor;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Locale;
import java.util.logging.Level;
import java.util.stream.Collectors;
public class CrossServerSyncCommand extends Command implements TabExecutor {
private final static CrossServerSyncBungeeCord plugin = CrossServerSyncBungeeCord.getInstance();
private final static String[] COMMAND_TAB_ARGUMENTS = {"about", "reload"};
private final static String PERMISSION = "crossserversync.command.csc";
public CrossServerSyncCommand() { super("csc", PERMISSION, "crossserversync"); }
@Override
public void execute(CommandSender sender, String[] args) {
if (sender instanceof ProxiedPlayer player) {
if (args.length == 1) {
switch (args[0].toLowerCase(Locale.ROOT)) {
case "about", "info" -> sendAboutInformation(player);
default -> sender.sendMessage(new MineDown(MessageStrings.ERROR_INVALID_SYNTAX.replaceAll("%1%", "/csc <about>")).toComponent());
}
} else {
sendAboutInformation(player);
}
}
}
/**
* Send information about the plugin
* @param player The player to send it to
*/
private void sendAboutInformation(ProxiedPlayer player) {
try {
new RedisMessage(RedisMessage.MessageType.SEND_PLUGIN_INFORMATION,
new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, player.getUniqueId()),
plugin.getProxy().getName(), plugin.getDescription().getVersion()).send();
} catch (IOException e) {
plugin.getLogger().log(Level.WARNING, "Failed to serialize plugin information to send", e);
}
}
@Override
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
if (sender instanceof ProxiedPlayer player) {
if (!player.hasPermission(PERMISSION)) {
return Collections.emptyList();
}
if (args.length == 1) {
return Arrays.stream(COMMAND_TAB_ARGUMENTS).filter(val -> val.startsWith(args[0]))
.sorted().collect(Collectors.toList());
} else {
return Collections.emptyList();
}
}
return Collections.emptyList();
}
}

@ -73,12 +73,13 @@ public class DataManager {
final double maxHealth = resultSet.getDouble("max_health"); final double maxHealth = resultSet.getDouble("max_health");
final int hunger = resultSet.getInt("hunger"); final int hunger = resultSet.getInt("hunger");
final float saturation = resultSet.getFloat("saturation"); final float saturation = resultSet.getFloat("saturation");
final float saturationExhaustion = resultSet.getFloat("saturation_exhaustion");
final int selectedSlot = resultSet.getInt("selected_slot"); final int selectedSlot = resultSet.getInt("selected_slot");
final String serializedStatusEffects = resultSet.getString("status_effects"); final String serializedStatusEffects = resultSet.getString("status_effects");
return new PlayerData(playerUUID, dataVersionUUID, serializedInventory, serializedEnderChest, health, maxHealth, hunger, saturation, selectedSlot, serializedStatusEffects); return new PlayerData(playerUUID, dataVersionUUID, serializedInventory, serializedEnderChest, health, maxHealth, hunger, saturation, saturationExhaustion, selectedSlot, serializedStatusEffects);
} else { } else {
return PlayerData.EMPTY_PLAYER_DATA(playerUUID); return PlayerData.DEFAULT_PLAYER_DATA(playerUUID);
} }
} }
} catch (SQLException e) { } catch (SQLException e) {
@ -104,7 +105,7 @@ public class DataManager {
private static void updatePlayerSQLData(PlayerData playerData) { private static void updatePlayerSQLData(PlayerData playerData) {
try (Connection connection = CrossServerSyncBungeeCord.getConnection()) { try (Connection connection = CrossServerSyncBungeeCord.getConnection()) {
try (PreparedStatement statement = connection.prepareStatement( try (PreparedStatement statement = connection.prepareStatement(
"UPDATE " + Database.DATA_TABLE_NAME + " SET `version_uuid`=?, `timestamp`=?, `inventory`=?, `ender_chest`=?, `health`=?, `max_health`=?, `hunger`=?, `saturation`=?, `selected_slot`=?, `status_effects`=? WHERE `player_id`=(SELECT `id` FROM " + Database.PLAYER_TABLE_NAME + " WHERE `uuid`=?);")) { "UPDATE " + Database.DATA_TABLE_NAME + " SET `version_uuid`=?, `timestamp`=?, `inventory`=?, `ender_chest`=?, `health`=?, `max_health`=?, `hunger`=?, `saturation`=?, `saturation_exhaustion`=?, `selected_slot`=?, `status_effects`=? WHERE `player_id`=(SELECT `id` FROM " + Database.PLAYER_TABLE_NAME + " WHERE `uuid`=?);")) {
statement.setString(1, playerData.getDataVersionUUID().toString()); statement.setString(1, playerData.getDataVersionUUID().toString());
statement.setTimestamp(2, new Timestamp(Instant.now().getEpochSecond())); statement.setTimestamp(2, new Timestamp(Instant.now().getEpochSecond()));
statement.setString(3, playerData.getSerializedInventory()); statement.setString(3, playerData.getSerializedInventory());
@ -113,9 +114,10 @@ public class DataManager {
statement.setDouble(6, playerData.getMaxHealth()); // Max health statement.setDouble(6, playerData.getMaxHealth()); // Max health
statement.setInt(7, playerData.getHunger()); // Hunger statement.setInt(7, playerData.getHunger()); // Hunger
statement.setFloat(8, playerData.getSaturation()); // Saturation statement.setFloat(8, playerData.getSaturation()); // Saturation
statement.setInt(9, playerData.getSelectedSlot()); statement.setFloat(9, playerData.getSaturationExhaustion()); // Saturation exhaustion
statement.setString(10, playerData.getSerializedEffectData()); // Status effects statement.setInt(10, playerData.getSelectedSlot()); // Current selected slot
statement.setString(11, playerData.getPlayerUUID().toString()); statement.setString(11, playerData.getSerializedEffectData()); // Status effects
statement.setString(12, playerData.getPlayerUUID().toString());
statement.executeUpdate(); statement.executeUpdate();
} }
} catch (SQLException e) { } catch (SQLException e) {
@ -126,7 +128,7 @@ public class DataManager {
private static void insertPlayerData(PlayerData playerData) { private static void insertPlayerData(PlayerData playerData) {
try (Connection connection = CrossServerSyncBungeeCord.getConnection()) { try (Connection connection = CrossServerSyncBungeeCord.getConnection()) {
try (PreparedStatement statement = connection.prepareStatement( try (PreparedStatement statement = connection.prepareStatement(
"INSERT INTO " + Database.DATA_TABLE_NAME + " (`player_id`,`version_uuid`,`timestamp`,`inventory`,`ender_chest`,`health`,`max_health`,`hunger`,`saturation`,`selected_slot`,`status_effects`) VALUES((SELECT `id` FROM " + Database.PLAYER_TABLE_NAME + " WHERE `uuid`=?),?,?,?,?,?,?,?,?,?,?);")) { "INSERT INTO " + Database.DATA_TABLE_NAME + " (`player_id`,`version_uuid`,`timestamp`,`inventory`,`ender_chest`,`health`,`max_health`,`hunger`,`saturation`,`saturation_exhaustion`,`selected_slot`,`status_effects`) VALUES((SELECT `id` FROM " + Database.PLAYER_TABLE_NAME + " WHERE `uuid`=?),?,?,?,?,?,?,?,?,?,?,?);")) {
statement.setString(1, playerData.getPlayerUUID().toString()); statement.setString(1, playerData.getPlayerUUID().toString());
statement.setString(2, playerData.getDataVersionUUID().toString()); statement.setString(2, playerData.getDataVersionUUID().toString());
statement.setTimestamp(3, new Timestamp(Instant.now().getEpochSecond())); statement.setTimestamp(3, new Timestamp(Instant.now().getEpochSecond()));
@ -136,8 +138,9 @@ public class DataManager {
statement.setDouble(7, playerData.getMaxHealth()); // Max health statement.setDouble(7, playerData.getMaxHealth()); // Max health
statement.setInt(8, playerData.getHunger()); // Hunger statement.setInt(8, playerData.getHunger()); // Hunger
statement.setFloat(9, playerData.getSaturation()); // Saturation statement.setFloat(9, playerData.getSaturation()); // Saturation
statement.setInt(10, playerData.getSelectedSlot()); statement.setFloat(10, playerData.getSaturationExhaustion()); // Saturation exhaustion
statement.setString(11, playerData.getSerializedEffectData()); // Status effects statement.setInt(11, playerData.getSelectedSlot()); // Current selected slot
statement.setString(12, playerData.getSerializedEffectData()); // Status effects
statement.executeUpdate(); statement.executeUpdate();
} }

@ -29,6 +29,7 @@ public class MySQL extends Database {
"`max_health` double NOT NULL," + "`max_health` double NOT NULL," +
"`hunger` integer NOT NULL," + "`hunger` integer NOT NULL," +
"`saturation` float NOT NULL," + "`saturation` float NOT NULL," +
"`saturation_exhaustion` float NOT NULL," +
"`selected_slot` integer NOT NULL," + "`selected_slot` integer NOT NULL," +
"`status_effects` longtext NOT NULL," + "`status_effects` longtext NOT NULL," +

@ -37,6 +37,7 @@ public class SQLite extends Database {
"`max_health` double NOT NULL," + "`max_health` double NOT NULL," +
"`hunger` integer NOT NULL," + "`hunger` integer NOT NULL," +
"`saturation` float NOT NULL," + "`saturation` float NOT NULL," +
"`saturation_exhaustion` float NOT NULL," +
"`selected_slot` integer NOT NULL," + "`selected_slot` integer NOT NULL," +
"`status_effects` longtext NOT NULL," + "`status_effects` longtext NOT NULL," +

@ -54,7 +54,7 @@ public class BungeeRedisListener extends RedisListener {
ProxyServer.getInstance().getScheduler().runAsync(plugin, () -> { 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_REPLY, new RedisMessage(RedisMessage.MessageType.PLAYER_DATA_SET,
new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, requestingPlayerUUID), new RedisMessage.MessageTarget(Settings.ServerType.BUKKIT, requestingPlayerUUID),
RedisMessage.serialize(getPlayerCachedData(requestingPlayerUUID))).send(); RedisMessage.serialize(getPlayerCachedData(requestingPlayerUUID))).send();
} catch (IOException e) { } catch (IOException e) {

@ -0,0 +1,14 @@
package me.william278.crossserversync;
public class MessageStrings {
public static final StringBuilder PLUGIN_INFORMATION = new StringBuilder().append("[CrossServerSync](#00fb9a bold) [| %proxy_brand% Version %proxy_version% | %bukkit_brand% Version %bukkit_version%](#00fb9a)\n")
.append("[%plugin_description%](gray)\n")
.append("[• Author:](white) [William278](gray show_text=&7Click to pay a visit open_url=https://youtube.com/William27528)\n")
.append("[• Help Wiki:](white) [[Link]](#00fb9a show_text=&7Click to open link open_url=https://github.com/WiIIiam278/CrossServerSync/wiki/)\n")
.append("[• Report Issues:](white) [[Link]](#00fb9a show_text=&7Click to open link open_url=https://github.com/WiIIiam278/CrossServerSync/issues)\n")
.append("[• Support Discord:](white) [[Link]](#00fb9a show_text=&7Click to join open_url=https://discord.gg/tVYhJfyDWG)");
public static final String ERROR_INVALID_SYNTAX = "[Error:](#ff3300) [Incorrect syntax. Usage: %1%](#ff7e5e)";
}

@ -23,10 +23,10 @@ public class PlayerData implements Serializable {
private final double maxHealth; private final double maxHealth;
private final int hunger; private final int hunger;
private final float saturation; private final float saturation;
private final float saturationExhaustion;
private final int selectedSlot; private final int selectedSlot;
private final String serializedEffectData; private final String serializedEffectData;
/** /**
* Create a new PlayerData object; a random data version UUID will be selected. * Create a new PlayerData object; a random data version UUID will be selected.
* @param playerUUID UUID of the player * @param playerUUID UUID of the player
@ -39,7 +39,7 @@ public class PlayerData implements Serializable {
* @param selectedSlot Player selected slot * @param selectedSlot Player selected slot
* @param serializedStatusEffects Serialized status effect data * @param serializedStatusEffects Serialized status effect data
*/ */
public PlayerData(UUID playerUUID, String serializedInventory, String serializedEnderChest, double health, double maxHealth, int hunger, float saturation, int selectedSlot, String serializedStatusEffects) { public PlayerData(UUID playerUUID, String serializedInventory, String serializedEnderChest, double health, double maxHealth, int hunger, float saturation, float saturationExhaustion, int selectedSlot, String serializedStatusEffects) {
this.dataVersionUUID = UUID.randomUUID(); this.dataVersionUUID = UUID.randomUUID();
this.playerUUID = playerUUID; this.playerUUID = playerUUID;
this.serializedInventory = serializedInventory; this.serializedInventory = serializedInventory;
@ -48,11 +48,12 @@ public class PlayerData implements Serializable {
this.maxHealth = maxHealth; this.maxHealth = maxHealth;
this.hunger = hunger; this.hunger = hunger;
this.saturation = saturation; this.saturation = saturation;
this.saturationExhaustion = saturationExhaustion;
this.selectedSlot = selectedSlot; this.selectedSlot = selectedSlot;
this.serializedEffectData = serializedStatusEffects; this.serializedEffectData = serializedStatusEffects;
} }
public PlayerData(UUID playerUUID, UUID dataVersionUUID, String serializedInventory, String serializedEnderChest, double health, double maxHealth, int hunger, float saturation, int selectedSlot, String serializedStatusEffects) { public PlayerData(UUID playerUUID, UUID dataVersionUUID, String serializedInventory, String serializedEnderChest, double health, double maxHealth, int hunger, float saturation, float saturationExhaustion, int selectedSlot, String serializedStatusEffects) {
this.playerUUID = playerUUID; this.playerUUID = playerUUID;
this.dataVersionUUID = dataVersionUUID; this.dataVersionUUID = dataVersionUUID;
this.serializedInventory = serializedInventory; this.serializedInventory = serializedInventory;
@ -61,13 +62,14 @@ public class PlayerData implements Serializable {
this.maxHealth = maxHealth; this.maxHealth = maxHealth;
this.hunger = hunger; this.hunger = hunger;
this.saturation = saturation; this.saturation = saturation;
this.saturationExhaustion = saturationExhaustion;
this.selectedSlot = selectedSlot; this.selectedSlot = selectedSlot;
this.serializedEffectData = serializedStatusEffects; this.serializedEffectData = serializedStatusEffects;
} }
public static PlayerData EMPTY_PLAYER_DATA(UUID playerUUID) { public static PlayerData DEFAULT_PLAYER_DATA(UUID playerUUID) {
return new PlayerData(playerUUID, "", "", 20, return new PlayerData(playerUUID, "", "", 20,
20, 20, 20, 0, ""); 20, 20, 10, 1, 0, "");
} }
public UUID getPlayerUUID() { public UUID getPlayerUUID() {
@ -102,6 +104,8 @@ public class PlayerData implements Serializable {
return saturation; return saturation;
} }
public float getSaturationExhaustion() { return saturationExhaustion; }
public int getSelectedSlot() { public int getSelectedSlot() {
return selectedSlot; return selectedSlot;
} }

@ -75,6 +75,8 @@ public class RedisMessage {
return messageData; return messageData;
} }
public String[] getMessageDataElements() { return messageData.split(MESSAGE_DATA_SEPARATOR); }
public MessageType getMessageType() { public MessageType getMessageType() {
return messageType; return messageType;
} }
@ -100,7 +102,12 @@ public class RedisMessage {
/** /**
* Sent by the Proxy to reply to a {@code MessageType.PLAYER_DATA_REQUEST}, contains the latest {@link PlayerData} for the requester. * Sent by the Proxy to reply to a {@code MessageType.PLAYER_DATA_REQUEST}, contains the latest {@link PlayerData} for the requester.
*/ */
PLAYER_DATA_REPLY PLAYER_DATA_SET,
/**
* Sent by the proxy to ask the Bukkit server to send the full plugin information, contains information about the proxy brand and version
*/
SEND_PLUGIN_INFORMATION
} }
/** /**

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 182 KiB

Loading…
Cancel
Save