Merge pull request #30 from mchivelli/1.20.1
Added Sophisticated Backpack Mod compatibility
This commit is contained in:
commit
d346bd36ae
|
|
@ -128,6 +128,8 @@ dependencies {
|
||||||
|
|
||||||
implementation fg.deobf("curse.maven:curios-309927:5266541")
|
implementation fg.deobf("curse.maven:curios-309927:5266541")
|
||||||
implementation fg.deobf("curse.maven:MySQL-561280:3685108")
|
implementation fg.deobf("curse.maven:MySQL-561280:3685108")
|
||||||
|
implementation fg.deobf("curse.maven:sophisticated-backpacks-422301:6303388")
|
||||||
|
implementation fg.deobf("curse.maven:sophisticated-core-618298:6317048")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example for how to get properties into the manifest for reading at runtime.
|
// Example for how to get properties into the manifest for reading at runtime.
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,17 @@ import vip.fubuki.playersync.sync.ChatSync;
|
||||||
import vip.fubuki.playersync.sync.VanillaSync;
|
import vip.fubuki.playersync.sync.VanillaSync;
|
||||||
import vip.fubuki.playersync.util.JDBCsetUp;
|
import vip.fubuki.playersync.util.JDBCsetUp;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
|
||||||
@Mod(PlayerSync.MODID)
|
@Mod(PlayerSync.MODID)
|
||||||
public class PlayerSync
|
public class PlayerSync {
|
||||||
{
|
|
||||||
public static final String MODID = "playersync";
|
public static final String MODID = "playersync";
|
||||||
public static final Logger LOGGER = LogUtils.getLogger();
|
public static final Logger LOGGER = LogUtils.getLogger();
|
||||||
public PlayerSync()
|
|
||||||
{
|
public PlayerSync() {
|
||||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||||
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, JdbcConfig.COMMON_CONFIG);
|
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, JdbcConfig.COMMON_CONFIG);
|
||||||
modEventBus.addListener(this::commonSetup);
|
modEventBus.addListener(this::commonSetup);
|
||||||
|
|
@ -35,71 +36,106 @@ public class PlayerSync
|
||||||
|
|
||||||
private void commonSetup(final FMLCommonSetupEvent event) {
|
private void commonSetup(final FMLCommonSetupEvent event) {
|
||||||
VanillaSync.register();
|
VanillaSync.register();
|
||||||
if(JdbcConfig.SYNC_CHAT.get()){
|
if (JdbcConfig.SYNC_CHAT.get()) {
|
||||||
ChatSync.register();
|
ChatSync.register();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void onServerStarting(ServerStartingEvent event) throws SQLException {
|
public void onServerStarting(ServerStartingEvent event) throws SQLException {
|
||||||
JDBCsetUp.executeUpdate("CREATE DATABASE IF NOT EXISTS "+JdbcConfig.DATABASE_NAME.get(),1);
|
String dbName = JdbcConfig.DATABASE_NAME.get();
|
||||||
|
|
||||||
JDBCsetUp.executeUpdate("""
|
// Step 1: Create the database using a connection that does not select a database.
|
||||||
CREATE TABLE IF NOT EXISTS `player_data` (
|
JDBCsetUp.executeUpdate("CREATE DATABASE IF NOT EXISTS " + dbName, 1);
|
||||||
`uuid` char(36) NOT NULL,
|
|
||||||
`inventory` mediumblob,
|
|
||||||
`armor` blob,
|
|
||||||
`advancements` blob,
|
|
||||||
`enderchest` mediumblob,
|
|
||||||
`effects` blob,
|
|
||||||
`left_hand` blob,
|
|
||||||
`cursors` blob,
|
|
||||||
`xp` int DEFAULT NULL,
|
|
||||||
`food_level` int DEFAULT NULL,
|
|
||||||
`score` int DEFAULT NULL,
|
|
||||||
`health` int DEFAULT NULL,
|
|
||||||
`online` tinyint(1) DEFAULT NULL,
|
|
||||||
`last_server` int DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`uuid`)
|
|
||||||
);""");
|
|
||||||
|
|
||||||
JDBCsetUp.QueryResult queryResult = JDBCsetUp.executeQuery("""
|
// Step 2: Explicitly select the database on a connection obtained without default database.
|
||||||
SELECT COUNT(*) AS column_count
|
try (Connection conn = JDBCsetUp.getConnection(false);
|
||||||
FROM INFORMATION_SCHEMA.COLUMNS
|
Statement st = conn.createStatement()) {
|
||||||
WHERE TABLE_NAME = 'player_data';
|
st.execute("USE " + dbName);
|
||||||
""");
|
} catch (SQLException e) {
|
||||||
|
LOGGER.error("Error selecting database " + dbName, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: Create and alter tables using fully qualified names.
|
||||||
|
// Create player_data table
|
||||||
|
JDBCsetUp.executeUpdate(
|
||||||
|
"CREATE TABLE IF NOT EXISTS " + dbName + ".`player_data` (" +
|
||||||
|
"`uuid` char(36) NOT NULL," +
|
||||||
|
"`inventory` mediumblob," +
|
||||||
|
"`armor` blob," +
|
||||||
|
"`advancements` blob," +
|
||||||
|
"`enderchest` mediumblob," +
|
||||||
|
"`effects` blob," +
|
||||||
|
"`left_hand` blob," +
|
||||||
|
"`cursors` blob," +
|
||||||
|
"`xp` int DEFAULT NULL," +
|
||||||
|
"`food_level` int DEFAULT NULL," +
|
||||||
|
"`score` int DEFAULT NULL," +
|
||||||
|
"`health` int DEFAULT NULL," +
|
||||||
|
"`online` tinyint(1) DEFAULT NULL," +
|
||||||
|
"`last_server` int DEFAULT NULL," +
|
||||||
|
"PRIMARY KEY (`uuid`)" +
|
||||||
|
");"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check and alter player_data table if columns are missing
|
||||||
|
JDBCsetUp.QueryResult queryResult = JDBCsetUp.executeQuery(
|
||||||
|
"SELECT COUNT(*) AS column_count " +
|
||||||
|
"FROM INFORMATION_SCHEMA.COLUMNS " +
|
||||||
|
"WHERE TABLE_SCHEMA = '" + dbName + "' " +
|
||||||
|
"AND TABLE_NAME = 'player_data';"
|
||||||
|
);
|
||||||
ResultSet resultSet = queryResult.resultSet();
|
ResultSet resultSet = queryResult.resultSet();
|
||||||
int columnCount = 0;
|
int columnCount = 0;
|
||||||
if(resultSet.next()) {
|
if (resultSet.next()) {
|
||||||
columnCount = resultSet.getInt("column_count");
|
columnCount = resultSet.getInt("column_count");
|
||||||
}
|
}
|
||||||
|
if (columnCount < 14) {
|
||||||
if(columnCount<14){
|
JDBCsetUp.executeUpdate(
|
||||||
JDBCsetUp.executeUpdate("""
|
"ALTER TABLE " + dbName + ".player_data " +
|
||||||
ALTER TABLE player_data
|
"ADD COLUMN left_hand blob, " +
|
||||||
ADD COLUMN left_hand blob,
|
"ADD COLUMN cursors blob;"
|
||||||
ADD COLUMN cursors blob;
|
);
|
||||||
""");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JDBCsetUp.executeUpdate("""
|
// Create server_info table
|
||||||
CREATE TABLE IF NOT EXISTS server_info (
|
JDBCsetUp.executeUpdate(
|
||||||
`id` INT NOT NULL,
|
"CREATE TABLE IF NOT EXISTS " + dbName + ".server_info (" +
|
||||||
`enable` boolean NOT NULL,
|
"`id` INT NOT NULL," +
|
||||||
`last_update` BIGINT NOT NULL,
|
"`enable` boolean NOT NULL," +
|
||||||
PRIMARY KEY (`id`));""");
|
"`last_update` BIGINT NOT NULL," +
|
||||||
|
"PRIMARY KEY (`id`)" +
|
||||||
|
");"
|
||||||
|
);
|
||||||
long current = System.currentTimeMillis();
|
long current = System.currentTimeMillis();
|
||||||
JDBCsetUp.executeUpdate("INSERT INTO server_info(id,enable,last_update) " +
|
JDBCsetUp.executeUpdate(
|
||||||
"VALUES(" + JdbcConfig.SERVER_ID.get() + ",true," + current + ") " +
|
"INSERT INTO " + dbName + ".server_info(id,enable,last_update) " +
|
||||||
"ON DUPLICATE KEY UPDATE id= " + JdbcConfig.SERVER_ID.get() +",enable = 1," +
|
"VALUES(" + JdbcConfig.SERVER_ID.get() + ",true," + current + ") " +
|
||||||
"last_update=" + current + ";");
|
"ON DUPLICATE KEY UPDATE id= " + JdbcConfig.SERVER_ID.get() + ",enable = 1," +
|
||||||
JDBCsetUp.executeUpdate("UPDATE server_info SET enable= 1 WHERE id= "+ JdbcConfig.SERVER_ID.get());
|
"last_update=" + current + ";"
|
||||||
|
);
|
||||||
|
JDBCsetUp.executeUpdate(
|
||||||
|
"UPDATE " + dbName + ".server_info SET last_update=" + System.currentTimeMillis() +
|
||||||
|
" WHERE id='" + JdbcConfig.SERVER_ID.get() + "'"
|
||||||
|
);
|
||||||
|
|
||||||
if(ModList.get().isLoaded("curios")) {
|
// Create curios table if the Curios mod is loaded
|
||||||
JDBCsetUp.executeUpdate("CREATE TABLE IF NOT EXISTS curios (uuid CHAR(36) NOT NULL,curios_item BLOB, PRIMARY KEY (uuid))");
|
if (ModList.get().isLoaded("curios")) {
|
||||||
|
JDBCsetUp.executeUpdate(
|
||||||
|
"CREATE TABLE IF NOT EXISTS " + dbName + ".curios (" +
|
||||||
|
"uuid CHAR(36) NOT NULL, curios_item BLOB, PRIMARY KEY (uuid)" +
|
||||||
|
")"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create backpack_data table
|
||||||
|
JDBCsetUp.executeUpdate(
|
||||||
|
"CREATE TABLE IF NOT EXISTS " + dbName + ".backpack_data (" +
|
||||||
|
"uuid CHAR(36) NOT NULL, backpack_nbt MEDIUMBLOB, PRIMARY KEY (uuid)" +
|
||||||
|
");", 1
|
||||||
|
);
|
||||||
|
|
||||||
LOGGER.info("PlayerSync is ready!");
|
LOGGER.info("PlayerSync is ready!");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ public class ChatSync {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void reconnectClient() {
|
private static void reconnectClient() {
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,10 @@ public class ModsSupport {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
resultSet.close();
|
resultSet.close();
|
||||||
queryResult.connection().close();
|
queryResult.connection().close();
|
||||||
}else{
|
}else{
|
||||||
StoreCurios(player,true);
|
StoreCurios(player,true);
|
||||||
}
|
}
|
||||||
|
|
@ -60,7 +60,7 @@ public class ModsSupport {
|
||||||
|
|
||||||
public void onPlayerLeave(Player player) throws SQLException {
|
public void onPlayerLeave(Player player) throws SQLException {
|
||||||
if (ModList.get().isLoaded("curios")) {
|
if (ModList.get().isLoaded("curios")) {
|
||||||
StoreCurios(player, false);
|
StoreCurios(player, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,20 @@
|
||||||
package vip.fubuki.playersync.sync;
|
package vip.fubuki.playersync.sync;
|
||||||
|
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtUtils;
|
import net.minecraft.nbt.NbtUtils;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
@ -17,164 +31,227 @@ import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||||
import net.minecraftforge.event.server.ServerStoppedEvent;
|
import net.minecraftforge.event.server.ServerStoppedEvent;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
import vip.fubuki.playersync.PlayerSync;
|
||||||
import vip.fubuki.playersync.config.JdbcConfig;
|
import vip.fubuki.playersync.config.JdbcConfig;
|
||||||
|
import vip.fubuki.playersync.sync.ModsSupport;
|
||||||
import vip.fubuki.playersync.util.JDBCsetUp;
|
import vip.fubuki.playersync.util.JDBCsetUp;
|
||||||
import vip.fubuki.playersync.util.LocalJsonUtil;
|
import vip.fubuki.playersync.util.LocalJsonUtil;
|
||||||
import vip.fubuki.playersync.util.PSThreadPoolFactory;
|
import vip.fubuki.playersync.util.PSThreadPoolFactory;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
@Mod.EventBusSubscriber
|
@Mod.EventBusSubscriber
|
||||||
public class VanillaSync {
|
public class VanillaSync {
|
||||||
|
|
||||||
public static void register(){}
|
public static void register() {}
|
||||||
|
|
||||||
static ExecutorService executorService = Executors.newCachedThreadPool(new PSThreadPoolFactory("PlayerSync"));
|
static ExecutorService executorService = Executors.newCachedThreadPool(new PSThreadPoolFactory("PlayerSync"));
|
||||||
|
|
||||||
public static void doPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) throws SQLException, CommandSyntaxException, IOException {
|
public static void doPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) throws SQLException, CommandSyntaxException, IOException {
|
||||||
String player_uuid = event.getEntity().getUUID().toString();
|
String player_uuid = event.getEntity().getUUID().toString();
|
||||||
JDBCsetUp.QueryResult queryResult=JDBCsetUp.executeQuery("SELECT online, last_server FROM player_data WHERE uuid='"+player_uuid+"'");
|
PlayerSync.LOGGER.info("Starting synchronization for player " + player_uuid);
|
||||||
ResultSet resultSet=queryResult.resultSet();
|
|
||||||
|
// First query: check basic player data
|
||||||
|
JDBCsetUp.QueryResult qr1 = JDBCsetUp.executeQuery("SELECT online, last_server FROM player_data WHERE uuid='" + player_uuid + "'");
|
||||||
|
ResultSet rs1 = qr1.resultSet();
|
||||||
ServerPlayer serverPlayer = (ServerPlayer) event.getEntity();
|
ServerPlayer serverPlayer = (ServerPlayer) event.getEntity();
|
||||||
if(!resultSet.next()){
|
if (!rs1.next()){
|
||||||
store(event.getEntity(),true,Dist.CLIENT.isDedicatedServer());
|
store(event.getEntity(), true, Dist.CLIENT.isDedicatedServer());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean online = resultSet.getBoolean("online");
|
boolean online = rs1.getBoolean("online");
|
||||||
int lastServer = resultSet.getInt("last_server");
|
int lastServer = rs1.getInt("last_server");
|
||||||
queryResult=JDBCsetUp.executeQuery("SELECT * FROM player_data WHERE uuid='"+player_uuid+"'");
|
|
||||||
resultSet= queryResult.resultSet();
|
|
||||||
if(online && lastServer != JdbcConfig.SERVER_ID.get()) {
|
|
||||||
|
|
||||||
queryResult=JDBCsetUp.executeQuery("SELECT last_update,enable FROM server_info WHERE id='"+lastServer+"'");
|
// Second query: retrieve full player data
|
||||||
ResultSet getServerInfo = queryResult.resultSet();
|
JDBCsetUp.QueryResult qr2 = JDBCsetUp.executeQuery("SELECT * FROM player_data WHERE uuid='" + player_uuid + "'");
|
||||||
if(getServerInfo.next()){
|
ResultSet rs2 = qr2.resultSet();
|
||||||
long last_update = getServerInfo.getLong("last_update");
|
|
||||||
boolean enable = getServerInfo.getBoolean("enable");
|
// Check if player is already online on another server
|
||||||
if(enable && System.currentTimeMillis() < last_update + 300000.0){
|
if (online && lastServer != JdbcConfig.SERVER_ID.get()) {
|
||||||
|
JDBCsetUp.QueryResult qr3 = JDBCsetUp.executeQuery("SELECT last_update,enable FROM server_info WHERE id='" + lastServer + "'");
|
||||||
|
ResultSet rs3 = qr3.resultSet();
|
||||||
|
if (rs3.next()){
|
||||||
|
long last_update = rs3.getLong("last_update");
|
||||||
|
boolean enable = rs3.getBoolean("enable");
|
||||||
|
if (enable && System.currentTimeMillis() < last_update + 300000.0){
|
||||||
event.getEntity().removeTag("player_synced");
|
event.getEntity().removeTag("player_synced");
|
||||||
serverPlayer.connection.disconnect(Component.translatable("playersync.already_online"));
|
serverPlayer.connection.disconnect(Component.translatable("playersync.already_online"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
JDBCsetUp.executeUpdate("UPDATE server_info SET enable= '0' WHERE id=" + lastServer);
|
JDBCsetUp.executeUpdate("UPDATE server_info SET enable= '0' WHERE id=" + lastServer);
|
||||||
}
|
}
|
||||||
|
rs3.close();
|
||||||
getServerInfo.close();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
JDBCsetUp.executeUpdate("UPDATE server_info SET last_update=" + System.currentTimeMillis() + " WHERE id=" + JdbcConfig.SERVER_ID.get());
|
JDBCsetUp.executeUpdate("UPDATE server_info SET last_update=" + System.currentTimeMillis() + " WHERE id=" + JdbcConfig.SERVER_ID.get());
|
||||||
JDBCsetUp.executeUpdate("UPDATE player_data SET online= '1',last_server=" + JdbcConfig.SERVER_ID.get() + " WHERE uuid='"+player_uuid+"'");
|
JDBCsetUp.executeUpdate("UPDATE player_data SET online= '1',last_server=" + JdbcConfig.SERVER_ID.get() + " WHERE uuid='" + player_uuid + "'");
|
||||||
if(resultSet.next()) {
|
|
||||||
//Easy Part
|
if (rs2.next()) {
|
||||||
serverPlayer.setHealth(resultSet.getInt("health"));
|
// Restore basic attributes
|
||||||
serverPlayer.getFoodData().setFoodLevel(resultSet.getInt("food_level"));
|
serverPlayer.setHealth(rs2.getInt("health"));
|
||||||
serverPlayer.totalExperience=0;
|
serverPlayer.getFoodData().setFoodLevel(rs2.getInt("food_level"));
|
||||||
serverPlayer.experienceLevel=0;
|
serverPlayer.totalExperience = 0;
|
||||||
serverPlayer.experienceProgress=0;
|
serverPlayer.experienceLevel = 0;
|
||||||
serverPlayer.giveExperiencePoints(resultSet.getInt("xp"));
|
serverPlayer.experienceProgress = 0;
|
||||||
serverPlayer.setScore(resultSet.getInt("score"));
|
serverPlayer.giveExperiencePoints(rs2.getInt("xp"));
|
||||||
//Left Hand
|
serverPlayer.setScore(rs2.getInt("score"));
|
||||||
serverPlayer.setItemInHand(InteractionHand.OFF_HAND,ItemStack.of(NbtUtils.snbtToStructure(resultSet.getString("left_hand").replace("|",",").replace("^","\"").replace("<","{").replace(">","}").replace("~", "'"))));
|
|
||||||
//Cursor
|
// Restore left-hand item
|
||||||
serverPlayer.containerMenu.setCarried(ItemStack.of(NbtUtils.snbtToStructure(resultSet.getString("cursors").replace("|",",").replace("^","\"").replace("<","{").replace(">","}").replace("~", "'"))));
|
String leftHandEncoded = rs2.getString("left_hand");
|
||||||
//Equipment
|
String leftHandNBT = deserializeString(leftHandEncoded);
|
||||||
String armor_data=resultSet.getString("armor");
|
serverPlayer.setItemInHand(InteractionHand.OFF_HAND,
|
||||||
if(armor_data.length()>2) {
|
ItemStack.of(NbtUtils.snbtToStructure(leftHandNBT)));
|
||||||
|
|
||||||
|
// Restore cursor item
|
||||||
|
String cursorsEncoded = rs2.getString("cursors");
|
||||||
|
String cursorsNBT = deserializeString(cursorsEncoded);
|
||||||
|
serverPlayer.containerMenu.setCarried(
|
||||||
|
ItemStack.of(NbtUtils.snbtToStructure(cursorsNBT))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Restore armor
|
||||||
|
String armor_data = rs2.getString("armor");
|
||||||
|
if (armor_data.length() > 2) {
|
||||||
Map<Integer, String> equipment = LocalJsonUtil.StringToEntryMap(armor_data);
|
Map<Integer, String> equipment = LocalJsonUtil.StringToEntryMap(armor_data);
|
||||||
for (Map.Entry<Integer, String> entry : equipment.entrySet()) {
|
for (Map.Entry<Integer, String> entry : equipment.entrySet()) {
|
||||||
serverPlayer.getInventory().armor.set(entry.getKey(), deserialize(entry));
|
serverPlayer.getInventory().armor.set(entry.getKey(), deserialize(entry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Inventory
|
|
||||||
Map<Integer,String> inventory = LocalJsonUtil.StringToEntryMap(resultSet.getString("inventory"));
|
// Restore inventory
|
||||||
|
Map<Integer, String> inventory = LocalJsonUtil.StringToEntryMap(rs2.getString("inventory"));
|
||||||
for (Map.Entry<Integer, String> entry : inventory.entrySet()) {
|
for (Map.Entry<Integer, String> entry : inventory.entrySet()) {
|
||||||
serverPlayer.getInventory().setItem(entry.getKey(), deserialize(entry));
|
serverPlayer.getInventory().setItem(entry.getKey(), deserialize(entry));
|
||||||
}
|
}
|
||||||
//Ender chest
|
|
||||||
Map<Integer,String> ender_chest = LocalJsonUtil.StringToEntryMap(resultSet.getString("enderchest"));
|
// Restore Ender Chest
|
||||||
|
Map<Integer, String> ender_chest = LocalJsonUtil.StringToEntryMap(rs2.getString("enderchest"));
|
||||||
for (Map.Entry<Integer, String> entry : ender_chest.entrySet()) {
|
for (Map.Entry<Integer, String> entry : ender_chest.entrySet()) {
|
||||||
serverPlayer.getEnderChestInventory().setItem(entry.getKey(), deserialize(entry));
|
serverPlayer.getEnderChestInventory().setItem(entry.getKey(), deserialize(entry));
|
||||||
}
|
}
|
||||||
//Effects
|
|
||||||
String effectData=resultSet.getString("effects");
|
// Restore Effects
|
||||||
if(effectData.length()>2) {
|
String effectData = rs2.getString("effects");
|
||||||
|
if (effectData.length() > 2) {
|
||||||
serverPlayer.removeAllEffects();
|
serverPlayer.removeAllEffects();
|
||||||
Map<Integer, String> effects = LocalJsonUtil.StringToEntryMap(effectData);
|
Map<Integer, String> effects = LocalJsonUtil.StringToEntryMap(effectData);
|
||||||
for (Map.Entry<Integer, String> entry : effects.entrySet()) {
|
for (Map.Entry<Integer, String> entry : effects.entrySet()) {
|
||||||
CompoundTag effectTag = NbtUtils.snbtToStructure(entry.getValue().replace("|", ","));
|
CompoundTag effectTag = NbtUtils.snbtToStructure(deserializeString(entry.getValue()));
|
||||||
MobEffectInstance mobEffectInstance = MobEffectInstance.load(effectTag);
|
MobEffectInstance mobEffectInstance = MobEffectInstance.load(effectTag);
|
||||||
assert mobEffectInstance != null;
|
if (mobEffectInstance != null) {
|
||||||
serverPlayer.addEffect(mobEffectInstance);
|
serverPlayer.addEffect(mobEffectInstance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Advancements
|
|
||||||
|
// Restore Advancements
|
||||||
File gameDir = Objects.requireNonNull(serverPlayer.getServer()).getServerDirectory();
|
File gameDir = Objects.requireNonNull(serverPlayer.getServer()).getServerDirectory();
|
||||||
if(Dist.CLIENT.isDedicatedServer()){
|
if (Dist.CLIENT.isDedicatedServer()){
|
||||||
File advancements = new File(gameDir, JdbcConfig.SYNC_WORLD.get().get(0)+"/advancements"+"/"+player_uuid+".json");
|
File advancements = new File(gameDir, JdbcConfig.SYNC_WORLD.get().get(0) + "/advancements" + "/" + player_uuid + ".json");
|
||||||
if (!advancements.exists()) {
|
if (!advancements.exists()) {
|
||||||
advancements.createNewFile();
|
advancements.createNewFile();
|
||||||
}
|
}
|
||||||
byte [] bytes=resultSet.getString("advancements").getBytes();
|
byte[] bytes = rs2.getString("advancements").getBytes();
|
||||||
Files.write(advancements.toPath(),bytes);
|
Files.write(advancements.toPath(), bytes);
|
||||||
}else{
|
} else {
|
||||||
File[] files= scanAdvancementsFile(player_uuid, gameDir);
|
File[] files = scanAdvancementsFile(player_uuid, gameDir);
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
if(file==null) continue;
|
if (file == null) continue;
|
||||||
byte [] bytes=resultSet.getString("advancements").getBytes();
|
byte[] bytes = rs2.getString("advancements").getBytes();
|
||||||
Files.write(file.toPath(),bytes);
|
Files.write(file.toPath(), bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Mod support
|
|
||||||
|
// Mod support
|
||||||
ModsSupport modsSupport = new ModsSupport();
|
ModsSupport modsSupport = new ModsSupport();
|
||||||
modsSupport.onPlayerJoin(serverPlayer);
|
modsSupport.onPlayerJoin(serverPlayer);
|
||||||
serverPlayer.addTag("player_synced");
|
serverPlayer.addTag("player_synced");
|
||||||
|
|
||||||
resultSet.close();
|
// --- Begin Backpack Data Restore ---
|
||||||
|
PlayerSync.LOGGER.info("Restoring backpack data for player " + player_uuid);
|
||||||
|
net.p3pp3rf1y.sophisticatedbackpacks.util.PlayerInventoryProvider.get().runOnBackpacks(serverPlayer, (ItemStack backpackItem, String handler, String identifier, int slot) -> {
|
||||||
|
backpackItem.getCapability(net.p3pp3rf1y.sophisticatedbackpacks.api.CapabilityBackpackWrapper.getCapabilityInstance())
|
||||||
|
.ifPresent(wrapper -> {
|
||||||
|
// Retrieve the contents UUID from the backpack's NBT using NBTHelper
|
||||||
|
Optional<UUID> uuidOpt = net.p3pp3rf1y.sophisticatedcore.util.NBTHelper.getUniqueId(wrapper.getBackpack(), "contentsUuid");
|
||||||
|
if (uuidOpt.isPresent()) {
|
||||||
|
UUID contentsUuid = uuidOpt.get();
|
||||||
|
try {
|
||||||
|
JDBCsetUp.QueryResult qrBackpack = JDBCsetUp.executeQuery("SELECT backpack_nbt FROM backpack_data WHERE uuid='" + contentsUuid.toString() + "'");
|
||||||
|
ResultSet rsBackpack = qrBackpack.resultSet();
|
||||||
|
if (rsBackpack.next()) {
|
||||||
|
String serialized = rsBackpack.getString("backpack_nbt");
|
||||||
|
String nbtString = deserializeString(serialized);
|
||||||
|
CompoundTag backpackNbt = NbtUtils.snbtToStructure(nbtString);
|
||||||
|
// Update BackpackStorage with the retrieved NBT
|
||||||
|
net.p3pp3rf1y.sophisticatedbackpacks.backpack.BackpackStorage.get().setBackpackContents(contentsUuid, backpackNbt);
|
||||||
|
PlayerSync.LOGGER.info("Restored backpack data for UUID " + contentsUuid);
|
||||||
|
}
|
||||||
|
rsBackpack.close();
|
||||||
|
qrBackpack.connection().close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
PlayerSync.LOGGER.error("Error restoring backpack data for UUID " + contentsUuid, e);
|
||||||
|
} catch (CommandSyntaxException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PlayerSync.LOGGER.warn("Backpack item in slot " + slot + " has no contentsUuid during restore");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
// --- End Backpack Data Restore ---
|
||||||
|
|
||||||
|
rs2.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onPlayerJoin(PlayerEvent.PlayerLoggedInEvent event){
|
public static void onPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) {
|
||||||
executorService.submit(()->{
|
executorService.submit(() -> {
|
||||||
try {
|
try {
|
||||||
doPlayerJoin(event);
|
doPlayerJoin(event);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack deserialize(Map.Entry<Integer, String> entry) throws CommandSyntaxException {
|
public static ItemStack deserialize(Map.Entry<Integer, String> entry) throws CommandSyntaxException {
|
||||||
String nbt= entry.getValue().replace("|",",").replace("^","\"").replace("<","{").replace(">","}").replace("~", "'");
|
String nbt = deserializeString(entry.getValue());
|
||||||
CompoundTag compoundTag = NbtUtils.snbtToStructure(nbt);
|
CompoundTag compoundTag = NbtUtils.snbtToStructure(nbt);
|
||||||
return ItemStack.of(compoundTag);
|
return ItemStack.of(compoundTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String serialize(String object){
|
public static String deserializeString(String encoded) {
|
||||||
return object.replace(",","|").replace("\"","^").replace("{","<").replace("}",">").replace("'","~");
|
if (encoded.startsWith("B64:")) {
|
||||||
|
String base64 = encoded.substring(4);
|
||||||
|
try {
|
||||||
|
return new String(Base64.getDecoder().decode(base64), StandardCharsets.UTF_8);
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
PlayerSync.LOGGER.error("Base64 decoding failed for data: " + encoded, ex);
|
||||||
|
// fallback to legacy decoding below
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Legacy fallback using custom replacement
|
||||||
|
return encoded.replace("|", ",")
|
||||||
|
.replace("^", "\"")
|
||||||
|
.replace("<", "{")
|
||||||
|
.replace(">", "}")
|
||||||
|
.replace("~", "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String serialize(String object) {
|
||||||
|
// Base64 encode with a "B64:" marker for new data
|
||||||
|
return "B64:" + Base64.getEncoder().encodeToString(object.getBytes(StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void doPlayerSaveToFile(PlayerEvent.SaveToFile event) throws SQLException, IOException {
|
public static void doPlayerSaveToFile(PlayerEvent.SaveToFile event) throws SQLException, IOException {
|
||||||
JDBCsetUp.executeUpdate("UPDATE server_info SET last_update=" + System.currentTimeMillis() + " WHERE id=" + JdbcConfig.SERVER_ID.get());
|
JDBCsetUp.executeUpdate("UPDATE server_info SET last_update=" + System.currentTimeMillis() + " WHERE id=" + JdbcConfig.SERVER_ID.get());
|
||||||
if(!event.getEntity().getTags().contains("player_synced")) return;
|
if (!event.getEntity().getTags().contains("player_synced")) return;
|
||||||
store(event.getEntity(),false,Dist.CLIENT.isDedicatedServer());
|
store(event.getEntity(), false, Dist.CLIENT.isDedicatedServer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onPlayerSaveToFile(PlayerEvent.SaveToFile event) {
|
public static void onPlayerSaveToFile(PlayerEvent.SaveToFile event) {
|
||||||
executorService.submit(()->{
|
executorService.submit(() -> {
|
||||||
try {
|
try {
|
||||||
doPlayerSaveToFile(event);
|
doPlayerSaveToFile(event);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
@ -190,77 +267,102 @@ public class VanillaSync {
|
||||||
|
|
||||||
public static void doPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) throws SQLException, IOException {
|
public static void doPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) throws SQLException, IOException {
|
||||||
String player_uuid = event.getEntity().getUUID().toString();
|
String player_uuid = event.getEntity().getUUID().toString();
|
||||||
JDBCsetUp.executeUpdate("UPDATE player_data SET online= '0' WHERE uuid='"+player_uuid+"'");
|
JDBCsetUp.executeUpdate("UPDATE player_data SET online= '0' WHERE uuid='" + player_uuid + "'");
|
||||||
store(event.getEntity(),false,Dist.CLIENT.isDedicatedServer());
|
store(event.getEntity(), false, Dist.CLIENT.isDedicatedServer());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) throws SQLException {
|
public static void onPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) throws SQLException {
|
||||||
//Mod support
|
// Mod support
|
||||||
ModsSupport modsSupport = new ModsSupport();
|
ModsSupport modsSupport = new ModsSupport();
|
||||||
modsSupport.onPlayerLeave(event.getEntity());
|
modsSupport.onPlayerLeave(event.getEntity());
|
||||||
executorService.submit(()->{
|
executorService.submit(() -> {
|
||||||
try {
|
try {
|
||||||
doPlayerLogout(event);
|
doPlayerLogout(event);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void store(Player player, boolean init, boolean isServer) throws SQLException, IOException {
|
public static void store(Player player, boolean init, boolean isServer) throws SQLException, IOException {
|
||||||
String player_uuid = player.getUUID().toString();
|
String player_uuid = player.getUUID().toString();
|
||||||
//Easy part
|
PlayerSync.LOGGER.info("Storing data for player " + player_uuid + " (init=" + init + ")");
|
||||||
|
|
||||||
|
// Basic Attributes
|
||||||
int XP = player.totalExperience;
|
int XP = player.totalExperience;
|
||||||
int score=player.getScore();
|
int score = player.getScore();
|
||||||
int food_level=player.getFoodData().getFoodLevel();
|
int food_level = player.getFoodData().getFoodLevel();
|
||||||
int health=(int) player.getHealth();
|
int health = (int) player.getHealth();
|
||||||
//Left hand
|
// Left Hand
|
||||||
String left_hand = serialize(player.getItemInHand(InteractionHand.OFF_HAND).serializeNBT().toString());
|
String left_hand = serialize(player.getItemInHand(InteractionHand.OFF_HAND).serializeNBT().toString());
|
||||||
//Cursor
|
// Cursor
|
||||||
String cursors = serialize(player.containerMenu.getCarried().serializeNBT().toString());
|
String cursors = serialize(player.containerMenu.getCarried().serializeNBT().toString());
|
||||||
//Equipment
|
// Equipment (Armor)
|
||||||
Map<Integer,String> equipment =new HashMap<>() ;
|
Map<Integer, String> equipment = new HashMap<>();
|
||||||
for (int i = 0; i < player.getInventory().armor.size(); i++) {
|
for (int i = 0; i < player.getInventory().armor.size(); i++) {
|
||||||
ItemStack itemStack = player.getInventory().armor.get(i);
|
ItemStack itemStack = player.getInventory().armor.get(i);
|
||||||
if(itemStack.isEmpty()) continue;
|
if (itemStack.isEmpty()) continue;
|
||||||
equipment.put(i,serialize(itemStack.serializeNBT().toString()));
|
equipment.put(i, serialize(itemStack.serializeNBT().toString()));
|
||||||
}
|
}
|
||||||
//inventory
|
// Inventory
|
||||||
Inventory inventory = player.getInventory();
|
Inventory inventory = player.getInventory();
|
||||||
Map<Integer,String> inventoryMap = new HashMap<>();
|
Map<Integer, String> inventoryMap = new HashMap<>();
|
||||||
for (int i = 0; i < inventory.items.size(); i++) {
|
for (int i = 0; i < inventory.items.size(); i++) {
|
||||||
CompoundTag itemNBT = inventory.items.get(i).serializeNBT();
|
CompoundTag itemNBT = inventory.items.get(i).serializeNBT();
|
||||||
inventoryMap.put(i,serialize(itemNBT.toString()));
|
inventoryMap.put(i, serialize(itemNBT.toString()));
|
||||||
}
|
}
|
||||||
//EnderChest
|
// Ender Chest
|
||||||
Map<Integer, String> ender_chest = new HashMap<>();
|
Map<Integer, String> ender_chest = new HashMap<>();
|
||||||
for (int i=0;i< player.getEnderChestInventory().getContainerSize();i++) {
|
for (int i = 0; i < player.getEnderChestInventory().getContainerSize(); i++) {
|
||||||
CompoundTag itemNBT = player.getEnderChestInventory().getItem(i).serializeNBT();
|
CompoundTag itemNBT = player.getEnderChestInventory().getItem(i).serializeNBT();
|
||||||
ender_chest.put(i,serialize(itemNBT.toString()));
|
ender_chest.put(i, serialize(itemNBT.toString()));
|
||||||
}
|
}
|
||||||
//Effects
|
|
||||||
Map<MobEffect,MobEffectInstance> effects= player.getActiveEffectsMap();
|
// --- Begin Backpack Data Sync (Store) ---
|
||||||
Map<Integer,String> effectMap=new HashMap<>();
|
PlayerSync.LOGGER.info("Storing backpack data for player " + player.getUUID());
|
||||||
|
net.p3pp3rf1y.sophisticatedbackpacks.util.PlayerInventoryProvider.get().runOnBackpacks(player, (ItemStack backpackItem, String handler, String identifier, int slot) -> {
|
||||||
|
backpackItem.getCapability(net.p3pp3rf1y.sophisticatedbackpacks.api.CapabilityBackpackWrapper.getCapabilityInstance())
|
||||||
|
.ifPresent(wrapper -> {
|
||||||
|
// Retrieve the contents UUID from the backpack's NBT using NBTHelper
|
||||||
|
Optional<UUID> uuidOpt = net.p3pp3rf1y.sophisticatedcore.util.NBTHelper.getUniqueId(wrapper.getBackpack(), "contentsUuid");
|
||||||
|
if (uuidOpt.isPresent()) {
|
||||||
|
UUID contentsUuid = uuidOpt.get();
|
||||||
|
// Get internal backpack data from BackpackStorage (creates it if missing)
|
||||||
|
CompoundTag backpackNbt = net.p3pp3rf1y.sophisticatedbackpacks.backpack.BackpackStorage.get().getOrCreateBackpackContents(contentsUuid);
|
||||||
|
String serialized = VanillaSync.serialize(backpackNbt.toString());
|
||||||
|
try {
|
||||||
|
// Use REPLACE INTO so existing records are updated
|
||||||
|
JDBCsetUp.executeUpdate("REPLACE INTO backpack_data (uuid, backpack_nbt) VALUES ('" + contentsUuid.toString() + "', '" + serialized + "')");
|
||||||
|
PlayerSync.LOGGER.info("Saved backpack data for UUID " + contentsUuid);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
PlayerSync.LOGGER.error("Error saving backpack data for UUID " + contentsUuid, e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PlayerSync.LOGGER.warn("Backpack item in slot " + slot + " has no contentsUuid");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false; // Continue processing all backpack items.
|
||||||
|
});
|
||||||
|
// --- End Backpack Data Sync (Store) ---
|
||||||
|
|
||||||
|
// Effects
|
||||||
|
Map<MobEffect, MobEffectInstance> effects = player.getActiveEffectsMap();
|
||||||
|
Map<Integer, String> effectMap = new HashMap<>();
|
||||||
for (Map.Entry<MobEffect, MobEffectInstance> entry : effects.entrySet()) {
|
for (Map.Entry<MobEffect, MobEffectInstance> entry : effects.entrySet()) {
|
||||||
CompoundTag effectTag= entry.getValue().save(new CompoundTag());
|
CompoundTag effectTag = entry.getValue().save(new CompoundTag());
|
||||||
effectMap.put(MobEffect.getId(entry.getKey()),effectTag.toString().replace(",","|"));
|
effectMap.put(MobEffect.getId(entry.getKey()), serialize(effectTag.toString()));
|
||||||
}
|
}
|
||||||
//Advancements
|
// Advancements
|
||||||
//File root = serverPlayer.getServer().getServerDirectory();
|
|
||||||
File advancements = null;
|
File advancements = null;
|
||||||
File gameDir = Objects.requireNonNull(player.getServer()).getServerDirectory();
|
File gameDir = Objects.requireNonNull(player.getServer()).getServerDirectory();
|
||||||
if(isServer){
|
if (isServer) {
|
||||||
advancements = new File(gameDir, JdbcConfig.SYNC_WORLD.get().get(0)+"/advancements"+"/"+player_uuid+".json");
|
advancements = new File(gameDir, JdbcConfig.SYNC_WORLD.get().get(0) + "/advancements" + "/" + player_uuid + ".json");
|
||||||
}else{
|
} else {
|
||||||
// File gameDir = Minecraft.getInstance().gameDirectory;
|
File[] files = scanAdvancementsFile(player_uuid, gameDir);
|
||||||
File[] files= scanAdvancementsFile(player_uuid, gameDir);
|
|
||||||
//Get LastModified
|
|
||||||
long latestModifiedDate = 0;
|
long latestModifiedDate = 0;
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
if(file==null) continue;
|
if (file == null) continue;
|
||||||
if (file.lastModified() > latestModifiedDate) {
|
if (file.lastModified() > latestModifiedDate) {
|
||||||
latestModifiedDate = file.lastModified();
|
latestModifiedDate = file.lastModified();
|
||||||
advancements = file;
|
advancements = file;
|
||||||
|
|
@ -273,17 +375,19 @@ public class VanillaSync {
|
||||||
}
|
}
|
||||||
String json = new String(bytes, StandardCharsets.UTF_8);
|
String json = new String(bytes, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
//SQL Operation
|
// SQL Operation for player data
|
||||||
if(init){
|
if (init) {
|
||||||
JDBCsetUp.executeUpdate("INSERT INTO player_data (uuid,armor,inventory,enderchest,advancements,effects,xp,food_level,health,score,left_hand,cursors,online) VALUES ('"+player_uuid+"','"+equipment+"','"+inventoryMap+"','"+ender_chest+"','"+advancements+"','"+effectMap+"','"+XP+"','"+food_level+"','"+health+"','"+score+"','"+left_hand+"','"+cursors+"',online=true)");
|
JDBCsetUp.executeUpdate("INSERT INTO player_data (uuid,armor,inventory,enderchest,advancements,effects,xp,food_level,health,score,left_hand,cursors,online) VALUES ('" + player_uuid + "','" + equipment + "','" + inventoryMap + "','" + ender_chest + "','" + advancements + "','" + effectMap + "','" + XP + "','" + food_level + "','" + health + "','" + score + "','" + left_hand + "','" + cursors + "',online=true)");
|
||||||
}else JDBCsetUp.executeUpdate("UPDATE player_data SET inventory = '"+inventoryMap+"',armor='"+equipment+"' ,xp='"+XP+"',effects='"+effectMap+"',enderchest='"+ender_chest+"',score='"+score+"',food_level='"+food_level+"',health='"+health+"',advancements='"+json+"',left_hand='"+left_hand+"',cursors='"+cursors+"' WHERE uuid = '"+player_uuid+"'");
|
} else {
|
||||||
|
JDBCsetUp.executeUpdate("UPDATE player_data SET inventory = '" + inventoryMap + "',armor='" + equipment + "' ,xp='" + XP + "',effects='" + effectMap + "',enderchest='" + ender_chest + "',score='" + score + "',food_level='" + food_level + "',health='" + health + "',advancements='" + json + "',left_hand='" + left_hand + "',cursors='" + cursors + "' WHERE uuid = '" + player_uuid + "'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static File[] scanAdvancementsFile(String player_uuid, File gameDir) {
|
private static File[] scanAdvancementsFile(String player_uuid, File gameDir) {
|
||||||
File[] files = new File[JdbcConfig.SYNC_WORLD.get().size()];
|
File[] files = new File[JdbcConfig.SYNC_WORLD.get().size()];
|
||||||
for (int i = 0; i < JdbcConfig.SYNC_WORLD.get().size(); i++) {
|
for (int i = 0; i < JdbcConfig.SYNC_WORLD.get().size(); i++) {
|
||||||
File advanceFile=new File(gameDir, "saves/"+JdbcConfig.SYNC_WORLD.get().get(i)+"/advancements"+"/"+player_uuid+".json");
|
File advanceFile = new File(gameDir, "saves/" + JdbcConfig.SYNC_WORLD.get().get(i) + "/advancements" + "/" + player_uuid + ".json");
|
||||||
if(!advanceFile.exists()) continue;
|
if (!advanceFile.exists()) continue;
|
||||||
files[i] = advanceFile;
|
files[i] = advanceFile;
|
||||||
}
|
}
|
||||||
return files;
|
return files;
|
||||||
|
|
@ -294,12 +398,10 @@ public class VanillaSync {
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onUpdate(TickEvent.LevelTickEvent event) throws SQLException {
|
public static void onUpdate(TickEvent.LevelTickEvent event) throws SQLException {
|
||||||
tick++;
|
tick++;
|
||||||
if(tick == 1800) {
|
if (tick == 1800) {
|
||||||
tick=0;
|
tick = 0;
|
||||||
long current = System.currentTimeMillis();
|
long current = System.currentTimeMillis();
|
||||||
JDBCsetUp.executeUpdate("UPDATE server_info SET last_update ="+current+" WHERE id= "+ JdbcConfig.SERVER_ID.get());
|
JDBCsetUp.executeUpdate("UPDATE server_info SET last_update =" + current + " WHERE id= " + JdbcConfig.SERVER_ID.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,61 +4,84 @@ import vip.fubuki.playersync.config.JdbcConfig;
|
||||||
|
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
|
|
||||||
|
|
||||||
public class JDBCsetUp {
|
public class JDBCsetUp {
|
||||||
|
|
||||||
public static Connection getConnection() throws SQLException {
|
/**
|
||||||
String url= "jdbc:mysql://"+JdbcConfig.HOST.get()+":"+JdbcConfig.PORT.get()+"?useUnicode=true&characterEncoding=utf-8&useSSL="+JdbcConfig.USE_SSL.get()+"&serverTimezone=UTC&allowPublicKeyRetrieval=true";
|
* Returns a connection to the MySQL server.
|
||||||
return DriverManager.getConnection(url, JdbcConfig.USERNAME.get(), JdbcConfig.PASSWORD.get());
|
* @param selectDatabase if true, the returned URL includes the configured database name.
|
||||||
|
* @return a Connection object with the database explicitly selected.
|
||||||
|
* @throws SQLException if a database access error occurs.
|
||||||
|
*/
|
||||||
|
public static Connection getConnection(boolean selectDatabase) throws SQLException {
|
||||||
|
String dbName = JdbcConfig.DATABASE_NAME.get();
|
||||||
|
// Build the base URL
|
||||||
|
String url = "jdbc:mysql://" + JdbcConfig.HOST.get() + ":" + JdbcConfig.PORT.get();
|
||||||
|
if (selectDatabase && dbName != null && !dbName.isEmpty()) {
|
||||||
|
url += "/" + dbName;
|
||||||
|
}
|
||||||
|
url += "?useUnicode=true&characterEncoding=utf-8&useSSL=" + JdbcConfig.USE_SSL.get()
|
||||||
|
+ "&serverTimezone=UTC&allowPublicKeyRetrieval=true";
|
||||||
|
Connection conn = DriverManager.getConnection(url, JdbcConfig.USERNAME.get(), JdbcConfig.PASSWORD.get());
|
||||||
|
// Ensure that the connection uses the desired database by explicitly issuing "USE dbName"
|
||||||
|
if (selectDatabase && dbName != null && !dbName.isEmpty()) {
|
||||||
|
try (Statement st = conn.createStatement()) {
|
||||||
|
st.execute("USE " + dbName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static QueryResult executeQuery(String sql) throws SQLException{
|
// Default connection always includes the database.
|
||||||
Connection connection = getConnection();
|
public static Connection getConnection() throws SQLException {
|
||||||
|
return getConnection(true);
|
||||||
|
}
|
||||||
|
|
||||||
try (Statement useStatement = connection.createStatement()) {
|
/**
|
||||||
useStatement.execute("USE " + JdbcConfig.DATABASE_NAME.get());
|
* Executes a query using a connection that includes the database.
|
||||||
}
|
*/
|
||||||
|
public static QueryResult executeQuery(String sql) throws SQLException {
|
||||||
|
Connection connection = getConnection(); // With database selected (and "USE" already run)
|
||||||
PreparedStatement queryStatement = connection.prepareStatement(sql);
|
PreparedStatement queryStatement = connection.prepareStatement(sql);
|
||||||
ResultSet resultSet = queryStatement.executeQuery();
|
ResultSet resultSet = queryStatement.executeQuery();
|
||||||
return new QueryResult(connection,resultSet);
|
return new QueryResult(connection, resultSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void executeUpdate(String sql) throws SQLException{
|
/**
|
||||||
try (Connection connection = getConnection()) {
|
* Executes an update using a connection that includes the database.
|
||||||
|
*/
|
||||||
try (Statement useStatement = connection.createStatement()) {
|
public static void executeUpdate(String sql) throws SQLException {
|
||||||
useStatement.execute("USE " + JdbcConfig.DATABASE_NAME.get());
|
try (Connection connection = getConnection()) { // With database selected
|
||||||
}
|
|
||||||
|
|
||||||
try (PreparedStatement updateStatement = connection.prepareStatement(sql)) {
|
try (PreparedStatement updateStatement = connection.prepareStatement(sql)) {
|
||||||
updateStatement.executeUpdate();
|
updateStatement.executeUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void update(String sql, String... argument) throws SQLException{
|
/**
|
||||||
Connection connection = getConnection();
|
* Executes an update using a connection that does NOT include a default database.
|
||||||
|
* This method is used for commands like "CREATE DATABASE IF NOT EXISTS ..."
|
||||||
try (Statement useStatement = connection.createStatement()) {
|
*/
|
||||||
useStatement.execute("USE " + JdbcConfig.DATABASE_NAME.get());
|
public static void executeUpdate(String sql, int dummy) throws SQLException {
|
||||||
}
|
try (Connection connection = getConnection(false)) { // Without default database
|
||||||
|
|
||||||
PreparedStatement updateStatement = connection.prepareStatement(sql);
|
|
||||||
for (int i = 1; i <= argument.length; i++) {
|
|
||||||
updateStatement.setString(i,argument[i]);
|
|
||||||
}
|
|
||||||
updateStatement.executeUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void executeUpdate(String sql, int i) throws SQLException{
|
|
||||||
try (Connection connection = getConnection()) {
|
|
||||||
|
|
||||||
try (PreparedStatement updateStatement = connection.prepareStatement(sql)) {
|
try (PreparedStatement updateStatement = connection.prepareStatement(sql)) {
|
||||||
updateStatement.executeUpdate();
|
updateStatement.executeUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper method for updates with parameters.
|
||||||
|
*/
|
||||||
|
public static void update(String sql, String... argument) throws SQLException {
|
||||||
|
try (Connection connection = getConnection()) { // With database selected
|
||||||
|
PreparedStatement updateStatement = connection.prepareStatement(sql);
|
||||||
|
for (int i = 0; i < argument.length; i++) {
|
||||||
|
updateStatement.setString(i + 1, argument[i]);
|
||||||
|
}
|
||||||
|
updateStatement.executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public record QueryResult(Connection connection, ResultSet resultSet) {
|
public record QueryResult(Connection connection, ResultSet resultSet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user