diff --git a/src/main/java/vip/fubuki/playersync/sync/VanillaSync.java b/src/main/java/vip/fubuki/playersync/sync/VanillaSync.java index d55b669..e0e779f 100644 --- a/src/main/java/vip/fubuki/playersync/sync/VanillaSync.java +++ b/src/main/java/vip/fubuki/playersync/sync/VanillaSync.java @@ -24,6 +24,7 @@ import net.minecraft.world.level.storage.WorldData; import net.minecraftforge.event.OnDatapackSyncEvent; import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.entity.player.PlayerEvent; +import net.minecraftforge.event.entity.player.PlayerNegotiationEvent; import net.minecraftforge.event.server.ServerStoppedEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.ModList; @@ -137,106 +138,150 @@ public class VanillaSync { } } - public static void doPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) throws SQLException, CommandSyntaxException, IOException { - String player_uuid = event.getEntity().getUUID().toString(); - PlayerSync.LOGGER.info("Starting synchronization for player " + player_uuid); + public static void doPlayerConnect(PlayerNegotiationEvent event) { + try { + String player_uuid = event.getProfile().getId().toString(); + PlayerSync.LOGGER.info("Detected connection from player" + player_uuid + ",starting checking"); + boolean online = false; + int lastServer = -1; - // 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(); + // First query: check basic player data and check whether player can join into server. + JDBCsetUp.QueryResult qr1 = JDBCsetUp.executeQuery("SELECT online, last_server FROM player_data WHERE uuid='" + player_uuid + "'"); - // Mod support - ModsSupport modsSupport = new ModsSupport(); - modsSupport.onPlayerJoin(serverPlayer); - - if (!rs1.next()){ - store(event.getEntity(), true); - return; - } - boolean online = rs1.getBoolean("online"); - int lastServer = rs1.getInt("last_server"); - - // Second query: retrieve full player data - JDBCsetUp.QueryResult qr2 = JDBCsetUp.executeQuery("SELECT * FROM player_data WHERE uuid='" + player_uuid + "'"); - ResultSet rs2 = qr2.resultSet(); - - // Check if player is already online on another server - 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"); - serverPlayer.connection.disconnect(Component.translatable("playersync.already_online")); + try (ResultSet rs1 = qr1.resultSet()) { + if (!rs1.next()) { + PlayerSync.LOGGER.info("A new-player connection detected"); + qr1.connection().close(); return; } - JDBCsetUp.executeUpdate("UPDATE server_info SET enable= '0' WHERE id=" + lastServer); + online = rs1.getBoolean("online"); + lastServer = rs1.getInt("last_server"); + qr1.connection().close(); } - rs3.close(); - } - 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 + "'"); - if (rs2.next()) { - // Restore basic attributes - serverPlayer.setHealth(rs2.getInt("health")); - serverPlayer.getFoodData().setFoodLevel(rs2.getInt("food_level")); - - setXpForPlayer(serverPlayer, rs2.getInt("xp")); - serverPlayer.setScore(rs2.getInt("score")); - - // Restore left-hand item - String leftHandEncoded = rs2.getString("left_hand"); - serverPlayer.setItemInHand(InteractionHand.OFF_HAND, - deserializeAndCreatePlaceholderIfNeeded(leftHandEncoded)); - - // Restore cursor item - String cursorsEncoded = rs2.getString("cursors"); - serverPlayer.containerMenu.setCarried( - deserializeAndCreatePlaceholderIfNeeded(cursorsEncoded)); - - // Restore armor - String armor_data = rs2.getString("armor"); - if (armor_data.length() > 2) { - Map equipment = LocalJsonUtil.StringToEntryMap(armor_data); - for (Map.Entry entry : equipment.entrySet()) { - serverPlayer.getInventory().armor.set(entry.getKey(), deserializeAndCreatePlaceholderIfNeeded(entry.getValue())); + // Second query: Check if player is already online on another server + if (online && lastServer != JdbcConfig.SERVER_ID.get()) { + JDBCsetUp.QueryResult qr2 = JDBCsetUp.executeQuery("SELECT last_update,enable FROM server_info WHERE id='" + lastServer + "'"); + try (ResultSet rs2 = qr2.resultSet()) { + if (rs2.next()) { + long last_update = rs2.getLong("last_update"); + boolean enable = rs2.getBoolean("enable"); + if (enable && System.currentTimeMillis() < last_update + 300000.0) { + event.getConnection().disconnect(Component.translatable("playersync.already_online")); + qr2.connection().close(); + return; + } + JDBCsetUp.executeUpdate("UPDATE server_info SET enable= '0' WHERE id=" + lastServer); + } + qr2.connection().close(); } } + } catch (Exception e) { + PlayerSync.LOGGER.error("SqlException detected!", e); + event.getConnection().disconnect(Component.translatable("playersync.sqlexception")); + } + } - // Restore inventory - Map inventory = LocalJsonUtil.StringToEntryMap(rs2.getString("inventory")); - for (Map.Entry entry : inventory.entrySet()) { - serverPlayer.getInventory().setItem(entry.getKey(), deserializeAndCreatePlaceholderIfNeeded(entry.getValue())); + public static void doPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) { + try { + String player_uuid = event.getEntity().getUUID().toString(); + PlayerSync.LOGGER.info("Starting synchronization for player " + player_uuid); + + // 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(); + + // Mod support + ModsSupport modsSupport = new ModsSupport(); + modsSupport.onPlayerJoin(serverPlayer); + + if (!rs1.next()){ + store(event.getEntity(), true); + 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 + "'"); + rs1.close(); + return; } - // Restore Ender Chest - Map ender_chest = LocalJsonUtil.StringToEntryMap(rs2.getString("enderchest")); - for (Map.Entry entry : ender_chest.entrySet()) { - serverPlayer.getEnderChestInventory().setItem(entry.getKey(), deserializeAndCreatePlaceholderIfNeeded(entry.getValue())); - } + // Second query: retrieve full player data + JDBCsetUp.QueryResult qr2 = JDBCsetUp.executeQuery("SELECT * FROM player_data WHERE uuid='" + player_uuid + "'"); + ResultSet rs2 = qr2.resultSet(); - // Restore Effects - String effectData = rs2.getString("effects"); - if (effectData.length() > 2) { - serverPlayer.removeAllEffects(); - Map effects = LocalJsonUtil.StringToEntryMap(effectData); - for (Map.Entry entry : effects.entrySet()) { - CompoundTag effectTag = NbtUtils.snbtToStructure(deserializeString(entry.getValue())); - MobEffectInstance mobEffectInstance = MobEffectInstance.load(effectTag); - if (mobEffectInstance != null) { - serverPlayer.addEffect(mobEffectInstance); + 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 + "'"); + + if (rs2.next()) { + // Restore basic attributes + serverPlayer.setHealth(rs2.getInt("health")); + serverPlayer.getFoodData().setFoodLevel(rs2.getInt("food_level")); + + setXpForPlayer(serverPlayer, rs2.getInt("xp")); + serverPlayer.setScore(rs2.getInt("score")); + + // Restore left-hand item + String leftHandEncoded = rs2.getString("left_hand"); + serverPlayer.setItemInHand(InteractionHand.OFF_HAND, + deserializeAndCreatePlaceholderIfNeeded(leftHandEncoded)); + + // Restore cursor item + String cursorsEncoded = rs2.getString("cursors"); + serverPlayer.containerMenu.setCarried( + deserializeAndCreatePlaceholderIfNeeded(cursorsEncoded)); + + // Restore armor + String armor_data = rs2.getString("armor"); + if (armor_data.length() > 2) { + Map equipment = LocalJsonUtil.StringToEntryMap(armor_data); + for (Map.Entry entry : equipment.entrySet()) { + serverPlayer.getInventory().armor.set(entry.getKey(), deserializeAndCreatePlaceholderIfNeeded(entry.getValue())); + } + } + + // Restore inventory + Map inventory = LocalJsonUtil.StringToEntryMap(rs2.getString("inventory")); + for (Map.Entry entry : inventory.entrySet()) { + serverPlayer.getInventory().setItem(entry.getKey(), deserializeAndCreatePlaceholderIfNeeded(entry.getValue())); + } + + // Restore Ender Chest + Map ender_chest = LocalJsonUtil.StringToEntryMap(rs2.getString("enderchest")); + for (Map.Entry entry : ender_chest.entrySet()) { + serverPlayer.getEnderChestInventory().setItem(entry.getKey(), deserializeAndCreatePlaceholderIfNeeded(entry.getValue())); + } + + // Restore Effects + String effectData = rs2.getString("effects"); + if (effectData.length() > 2) { + serverPlayer.removeAllEffects(); + Map effects = LocalJsonUtil.StringToEntryMap(effectData); + for (Map.Entry entry : effects.entrySet()) { + CompoundTag effectTag = NbtUtils.snbtToStructure(deserializeString(entry.getValue())); + MobEffectInstance mobEffectInstance = MobEffectInstance.load(effectTag); + if (mobEffectInstance != null) { + serverPlayer.addEffect(mobEffectInstance); + } } } } + + serverPlayer.addTag("player_synced"); + + rs2.close(); + } catch (Exception e) { + PlayerSync.LOGGER.error("Internal Exception detected!", e); } + } - serverPlayer.addTag("player_synced"); - - rs2.close(); + @SubscribeEvent + public static void onPlayerConnect(PlayerNegotiationEvent event) { + executorService.submit(() -> { + try { + doPlayerConnect(event); + } catch (Exception e) { + e.printStackTrace(); + } + }); } @SubscribeEvent diff --git a/src/main/resources/assets/playersync/lang/en_us.json b/src/main/resources/assets/playersync/lang/en_us.json index 4b03f8e..410c86b 100644 --- a/src/main/resources/assets/playersync/lang/en_us.json +++ b/src/main/resources/assets/playersync/lang/en_us.json @@ -1,5 +1,7 @@ { "playersync.item_placeholder_description": "Item is unknown on this server. This can either\nbe a modded item, an added, or a removed vanilla\nitem.\nThis voucher will automatically be replaced with\nthe corresponding item when joining a server\nwhere the item is known.", + "playersync.placeholder_titel_override": "Item Voucher", "playersync.item_placeholder_title": "Item Voucher", - "playersync.already_online": "You can't join more than one synchronization server at the same time." + "playersync.already_online": "You can't join more than one synchronization server at the same time.", + "playersync.sqlexception": "SqlException detected!Connection lost,please contact with your admin." } diff --git a/src/main/resources/assets/playersync/lang/zh_cn.json b/src/main/resources/assets/playersync/lang/zh_cn.json index f206090..ee22b73 100644 --- a/src/main/resources/assets/playersync/lang/zh_cn.json +++ b/src/main/resources/assets/playersync/lang/zh_cn.json @@ -1,5 +1,7 @@ { - "playersync.item_placeholder_description": "物品在此服务器未知。这可能是一个模组物品,或是不同版本的原版物品。\n这张券将会在加入可识别此物品的服务器后自动替换为对应物品。", - "playersync.item_placeholder_title": "物品券", - "playersync.already_online": "你不能同时加入多个同步的服务器。" -} + "playersync.item_placeholder_description": "在这个服务器上,该物品是未知的\n它可能曾是一个其他已被移除的mod的物品,或者被移除的原版物品\n这一凭证将在加入拥有该物品的服务器时自动转换为对应物品", + "playersync.placeholder_titel_override": "未知物品凭证", + "playersync.item_placeholder_title": "未知物品凭证", + "playersync.already_online": "你不能同时加入多个在线的数据互通的服务器", + "playersync.sqlexception": "检测到Sql异常!连接已中断,请联系管理员" +} \ No newline at end of file