9
0
mirror of https://github.com/WiIIiam278/HuskSync.git synced 2025-12-26 18:19:10 +00:00

Finish initial implementation of plan

This commit is contained in:
William
2021-10-20 16:59:02 +01:00
parent 2a7371be31
commit 861477f5ae
21 changed files with 921 additions and 169 deletions

View File

@@ -1,6 +1,6 @@
package me.william278.crossserversync;
import java.io.Serializable;
import java.io.*;
import java.util.UUID;
public class PlayerData implements Serializable {
@@ -25,13 +25,13 @@ public class PlayerData implements Serializable {
*/
private final String serializedEnderChest;
//todo add more stuff, like ender chest, player health, max health, hunger and status effects, et cetera
/**
* Create a new PlayerData object; a random data version UUID will be selected.
* @param playerUUID The UUID of the player
*
* @param playerUUID The UUID of the player
* @param serializedInventory The player's serialized inventory data
*/
//todo add more stuff, like player health, max health, hunger, saturation and status effects
public PlayerData(UUID playerUUID, String serializedInventory, String serializedEnderChest) {
this.dataVersionUUID = UUID.randomUUID();
this.playerUUID = playerUUID;
@@ -39,6 +39,19 @@ public class PlayerData implements Serializable {
this.serializedEnderChest = serializedEnderChest;
}
public PlayerData(UUID playerUUID, UUID dataVersionUUID, String serializedInventory, String serializedEnderChest, double health, double maxHealth, double hunger, double saturation, String serializedStatusEffects) {
this.playerUUID = playerUUID;
this.dataVersionUUID = dataVersionUUID;
this.serializedInventory = serializedInventory;
this.serializedEnderChest = serializedEnderChest;
//todo Incorporate more of these
}
public static PlayerData EMPTY_PLAYER_DATA(UUID playerUUID) {
return new PlayerData(playerUUID, "", "");
}
public UUID getPlayerUUID() {
return playerUUID;
}

View File

@@ -4,6 +4,7 @@ import me.william278.crossserversync.Settings;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
import java.io.IOException;
import java.util.logging.Level;
public abstract class RedisListener {
@@ -42,7 +43,11 @@ public abstract class RedisListener {
}
// Handle the message
handleMessage(new RedisMessage(message));
try {
handleMessage(new RedisMessage(message));
} catch (IOException | ClassNotFoundException e) {
log(Level.SEVERE, "Failed to deserialize message target");
}
}
}, RedisMessage.REDIS_CHANNEL), "Redis Subscriber").start();
} else {

View File

@@ -1,12 +1,11 @@
package me.william278.crossserversync.redis;
import me.william278.crossserversync.PlayerData;
import me.william278.crossserversync.Settings;
import redis.clients.jedis.Jedis;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.io.*;
import java.util.Base64;
import java.util.StringJoiner;
import java.util.UUID;
@@ -41,32 +40,27 @@ public class RedisMessage {
* Get a new RedisMessage from an incoming message string
* @param messageString The message string to parse
*/
public RedisMessage(String messageString) {
public RedisMessage(String messageString) throws IOException, ClassNotFoundException {
String[] messageMetaElements = messageString.split(MESSAGE_META_SEPARATOR);
messageType = MessageType.valueOf(messageMetaElements[0]);
messageTarget = (MessageTarget) RedisMessage.deserialize(messageMetaElements[1]);
messageData = messageMetaElements[2];
try (ObjectInputStream stream = new ObjectInputStream(new ByteArrayInputStream(messageMetaElements[1].getBytes()))) {
messageTarget = (MessageTarget) stream.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* Returns the full, formatted message string with type, target & data
* @return The fully formatted message
*/
private String getFullMessage() {
private String getFullMessage() throws IOException {
return new StringJoiner(MESSAGE_META_SEPARATOR)
.add(messageType.toString()).add(messageTarget.toString()).add(messageData)
.add(messageType.toString()).add(RedisMessage.serialize(messageTarget)).add(messageData)
.toString();
}
/**
* Send the redis message
*/
public void send() {
public void send() throws IOException {
try (Jedis publisher = new Jedis(Settings.redisHost, Settings.redisPort)) {
final String jedisPassword = Settings.redisPassword;
if (!jedisPassword.equals("")) {
@@ -77,6 +71,10 @@ public class RedisMessage {
}
}
public String[] getMessageDataSeparated() {
return messageData.split(MESSAGE_DATA_SEPARATOR);
}
public String getMessageData() {
return messageData;
}
@@ -94,17 +92,17 @@ public class RedisMessage {
*/
public enum MessageType {
/**
* Sent by Bukkit servers to proxy when a player disconnects with a player's updated data, alongside the UUID of the last loaded {@link me.william278.crossserversync.PlayerData} for the user
* Sent by Bukkit servers to proxy when a player disconnects with a player's updated data, alongside the UUID of the last loaded {@link PlayerData} for the user
*/
PLAYER_DATA_UPDATE,
/**
* Sent by Bukkit servers to proxy to request {@link me.william278.crossserversync.PlayerData} from the proxy.
* Sent by Bukkit servers to proxy to request {@link PlayerData} from the proxy.
*/
PLAYER_DATA_REQUEST,
/**
* Sent by the Proxy to reply to a {@code MessageType.PLAYER_DATA_REQUEST}, contains the latest {@link me.william278.crossserversync.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
}
@@ -114,4 +112,25 @@ public class RedisMessage {
* For Bukkit servers, the name of the server must also be specified
*/
public record MessageTarget(Settings.ServerType targetServerType, UUID targetPlayerName) implements Serializable { }
/**
* Deserialize an object from a Base64 string
*/
public static Object deserialize(String s) throws IOException, ClassNotFoundException {
byte[] data = Base64.getDecoder().decode(s);
try (ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(data))) {
return objectInputStream.readObject();
}
}
/**
* Serialize an object to a Base64 string
*/
public static String serialize(Serializable o) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) {
objectOutputStream.writeObject(o);
}
return Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
}
}