Merge pull request #145 from Fugit-5414/fix/sync-failed-when-player-health-is-zero

Fixes #144
This commit is contained in:
mlus 2025-11-24 11:59:04 +08:00 committed by GitHub
commit b062331cce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 269 additions and 27 deletions

View File

@ -4,12 +4,15 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.serialization.Dynamic; import com.mojang.serialization.Dynamic;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.SharedConstants; import net.minecraft.SharedConstants;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.*; import net.minecraft.nbt.*;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.Style; import net.minecraft.network.chat.Style;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.PlayerAdvancements; import net.minecraft.server.PlayerAdvancements;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.datafix.DataFixers; import net.minecraft.util.datafix.DataFixers;
import net.minecraft.util.datafix.fixes.References; import net.minecraft.util.datafix.fixes.References;
@ -20,9 +23,12 @@ import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.storage.WorldData; import net.minecraft.world.level.storage.WorldData;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.OnDatapackSyncEvent; import net.minecraftforge.event.OnDatapackSyncEvent;
import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.living.LivingDeathEvent;
import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.entity.player.PlayerNegotiationEvent; import net.minecraftforge.event.entity.player.PlayerNegotiationEvent;
import net.minecraftforge.event.server.ServerStoppedEvent; import net.minecraftforge.event.server.ServerStoppedEvent;
@ -31,8 +37,13 @@ import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.server.ServerLifecycleHooks; import net.minecraftforge.server.ServerLifecycleHooks;
import top.theillusivec4.curios.api.CuriosApi;
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
import top.theillusivec4.curios.api.type.inventory.IDynamicStackHandler;
import vip.fubuki.playersync.PlayerSync; import vip.fubuki.playersync.PlayerSync;
import vip.fubuki.playersync.config.JdbcConfig; import vip.fubuki.playersync.config.JdbcConfig;
import vip.fubuki.playersync.sync.addons.CuriosCache;
import vip.fubuki.playersync.sync.addons.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;
@ -44,13 +55,16 @@ import java.nio.file.Files;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
@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"));
@ -182,9 +196,51 @@ public class VanillaSync {
} }
} }
// Use string uuid as key
public static Set<String> deadPlayerWhileLogging = ConcurrentHashMap.newKeySet();
public static void doPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) { public static void doPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) {
ServerPlayer joinedPlayer = (ServerPlayer) event.getEntity();
String player_uuid = joinedPlayer.getUUID().toString();
if (joinedPlayer.isDeadOrDying()) {
deadPlayerWhileLogging.add(player_uuid);
joinedPlayer.removeTag("player_synced");
// Simulate normal death behavior
MinecraftServer server = joinedPlayer.getServer();
if (server != null) {
ResourceKey<Level> respawnLevel = joinedPlayer.getRespawnDimension();
BlockPos respawnPos = joinedPlayer.getRespawnPosition();
double respawnX;
double respawnY;
double respawnZ;
if (respawnPos != null && respawnLevel != null) {
ServerLevel level = server.getLevel(respawnLevel);
respawnX = respawnPos.getX();
respawnY = respawnPos.getY();
respawnZ = respawnPos.getZ();
if (level != null) {
joinedPlayer.teleportTo(level, respawnX, respawnY + 1, respawnZ, 0, 0);
}
} else {
PlayerSync.LOGGER.debug("Player " + player_uuid + " has no respawn point");
}
} else {
PlayerSync.LOGGER.warn("Trying to get server,but got a null");
}
joinedPlayer.setHealth(1);
try {
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 + "'");
} catch (SQLException e) {
PlayerSync.LOGGER.error("An error occurred while trying to execute a dead or dying player" + e.getMessage());
}
joinedPlayer.connection.disconnect(Component.translatable("playersync.wrong_entity_status"));
return;
}
try { try {
String player_uuid = event.getEntity().getUUID().toString();
PlayerSync.LOGGER.info("Starting synchronization for player " + player_uuid); PlayerSync.LOGGER.info("Starting synchronization for player " + player_uuid);
// First query: check basic player data // First query: check basic player data
@ -196,11 +252,12 @@ public class VanillaSync {
ModsSupport modsSupport = new ModsSupport(); ModsSupport modsSupport = new ModsSupport();
modsSupport.onPlayerJoin(serverPlayer); modsSupport.onPlayerJoin(serverPlayer);
if (!rs1.next()){ if (!rs1.next()) {
store(event.getEntity(), true); store(event.getEntity(), true);
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 + "'");
rs1.close(); rs1.close();
qr1.close();
return; return;
} }
@ -213,7 +270,12 @@ public class VanillaSync {
if (rs2.next()) { if (rs2.next()) {
// Restore basic attributes // Restore basic attributes
serverPlayer.setHealth(rs2.getInt("health")); int health = rs2.getInt("health");
if (health <= 0) {
serverPlayer.setHealth(1);
} else {
serverPlayer.setHealth(health);
}
serverPlayer.getFoodData().setFoodLevel(rs2.getInt("food_level")); serverPlayer.getFoodData().setFoodLevel(rs2.getInt("food_level"));
setXpForPlayer(serverPlayer, rs2.getInt("xp")); setXpForPlayer(serverPlayer, rs2.getInt("xp"));
@ -268,6 +330,9 @@ public class VanillaSync {
serverPlayer.addTag("player_synced"); serverPlayer.addTag("player_synced");
rs2.close(); rs2.close();
qr2.close();
rs1.close();
qr1.close();
} catch (Exception e) { } catch (Exception e) {
PlayerSync.LOGGER.error("Internal Exception detected!", e); PlayerSync.LOGGER.error("Internal Exception detected!", e);
} }
@ -383,7 +448,7 @@ public class VanillaSync {
loreList.add(StringTag.valueOf(Component.Serializer.toJson(Component.literal("")))); loreList.add(StringTag.valueOf(Component.Serializer.toJson(Component.literal(""))));
String placeholderItemDescriptionOverride = JdbcConfig.ITEM_PLACEHOLDER_DESCRIPTION_OVERRIDE.get(); String placeholderItemDescriptionOverride = JdbcConfig.ITEM_PLACEHOLDER_DESCRIPTION_OVERRIDE.get();
String placeholderItemDescriptionLines = placeholderItemDescriptionOverride != null && ! placeholderItemDescriptionOverride.isBlank() String placeholderItemDescriptionLines = placeholderItemDescriptionOverride != null && !placeholderItemDescriptionOverride.isBlank()
? placeholderItemDescriptionOverride ? placeholderItemDescriptionOverride
: Component.translatable("playersync.item_placeholder_description").getString(); : Component.translatable("playersync.item_placeholder_description").getString();
@ -416,6 +481,7 @@ public class VanillaSync {
/** /**
* Deserializes a string from the database back into an NBT string. * Deserializes a string from the database back into an NBT string.
* Handles both the new Base64 format (prefixed with "B64:") and the old custom format. * Handles both the new Base64 format (prefixed with "B64:") and the old custom format.
*
* @param encoded The string retrieved from the database. * @param encoded The string retrieved from the database.
* @return The deserialized NBT string. * @return The deserialized NBT string.
*/ */
@ -441,6 +507,7 @@ public class VanillaSync {
* Serializes an NBT string for database storage. * Serializes an NBT string for database storage.
* Uses Base64 encoding by default (prefixed with "B64:"). * Uses Base64 encoding by default (prefixed with "B64:").
* If USE_LEGACY_SERIALIZATION config is true, uses the old custom replacement format. * If USE_LEGACY_SERIALIZATION config is true, uses the old custom replacement format.
*
* @param object The NBT string to serialize. * @param object The NBT string to serialize.
* @return The serialized string. * @return The serialized string.
*/ */
@ -449,10 +516,10 @@ public class VanillaSync {
if (JdbcConfig.USE_LEGACY_SERIALIZATION.get()) { if (JdbcConfig.USE_LEGACY_SERIALIZATION.get()) {
// Use old custom replacement logic // Use old custom replacement logic
return object.replace(",", "|") return object.replace(",", "|")
.replace("\"", "^") .replace("\"", "^")
.replace("{", "<") .replace("{", "<")
.replace("}", ">") .replace("}", ">")
.replace("'", "~"); .replace("'", "~");
} }
// Base64 encode with a "B64:" marker for new data // Base64 encode with a "B64:" marker for new data
@ -489,16 +556,23 @@ public class VanillaSync {
@SubscribeEvent @SubscribeEvent
public static void onPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) throws SQLException { public static void onPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) throws SQLException {
// Mod support String player_uuid = event.getEntity().getUUID().toString();
ModsSupport modsSupport = new ModsSupport(); if (deadPlayerWhileLogging.contains(player_uuid)) {
modsSupport.onPlayerLeave(event.getEntity()); PlayerSync.LOGGER.warn("A dead or dying player was kicked,which uuid is:" + player_uuid);
executorService.submit(() -> { JDBCsetUp.executeUpdate("UPDATE player_data SET online= '0' WHERE uuid='" + player_uuid + "'");
try { deadPlayerWhileLogging.remove(player_uuid);
doPlayerLogout(event); } else {
} catch (Exception e) { // Mod support
e.printStackTrace(); ModsSupport modsSupport = new ModsSupport();
} modsSupport.onPlayerLeave(event.getEntity());
}); executorService.submit(() -> {
try {
doPlayerLogout(event);
} catch (Exception e) {
e.printStackTrace();
}
});
}
} }
// Helper function to get the NBT string to be saved // Helper function to get the NBT string to be saved
@ -558,7 +632,7 @@ public class VanillaSync {
ender_chest.put(i, getNbtForStorage(player.getEnderChestInventory().getItem(i))); ender_chest.put(i, getNbtForStorage(player.getEnderChestInventory().getItem(i)));
} }
if(ModList.get().isLoaded("sophisticatedbackpacks")){ if (ModList.get().isLoaded("sophisticatedbackpacks")) {
ModsSupport.storeSophisticatedBackpacks(player); ModsSupport.storeSophisticatedBackpacks(player);
} }
@ -576,7 +650,7 @@ public class VanillaSync {
if (JdbcConfig.SYNC_ADVANCEMENTS.get()) { if (JdbcConfig.SYNC_ADVANCEMENTS.get()) {
File gameDir = Objects.requireNonNull(player.getServer()).getServerDirectory(); File gameDir = Objects.requireNonNull(player.getServer()).getServerDirectory();
final MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); final MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
if (server != null && server.isDedicatedServer() ) { if (server != null && server.isDedicatedServer()) {
PlayerSync.LOGGER.trace("Reading dedicated server advancements"); PlayerSync.LOGGER.trace("Reading dedicated server advancements");
advancements = new File(gameDir, getSyncWorldForServer() + "/advancements" + "/" + player_uuid + ".json"); advancements = new File(gameDir, getSyncWorldForServer() + "/advancements" + "/" + player_uuid + ".json");
} else { } else {
@ -658,6 +732,8 @@ public class VanillaSync {
// New fields for auto-save // New fields for auto-save
private static int autoSaveTickCounter = 0; private static int autoSaveTickCounter = 0;
private static final int AUTO_SAVE_INTERVAL_TICKS = 1200; // Every Minute private static final int AUTO_SAVE_INTERVAL_TICKS = 1200; // Every Minute
private static int autoCleanCuriosCacheTickCounter = 0;
private static final int AUTO_CLEAN_CURIOS_CACHE_INTERVAL_TICKS = 36000; // Every 30 min
//AutoSave //AutoSave
@SubscribeEvent @SubscribeEvent
@ -665,6 +741,7 @@ public class VanillaSync {
// Run at the end phase to avoid interfering with game logic // Run at the end phase to avoid interfering with game logic
if (event.phase == TickEvent.Phase.END) { if (event.phase == TickEvent.Phase.END) {
autoSaveTickCounter++; autoSaveTickCounter++;
autoCleanCuriosCacheTickCounter++;
if (autoSaveTickCounter >= AUTO_SAVE_INTERVAL_TICKS) { if (autoSaveTickCounter >= AUTO_SAVE_INTERVAL_TICKS) {
autoSaveTickCounter = 0; autoSaveTickCounter = 0;
// Retrieve the current server instance // Retrieve the current server instance
@ -687,10 +764,19 @@ public class VanillaSync {
PlayerSync.LOGGER.error("Error auto-saving Curios data for player " + player.getUUID(), e); PlayerSync.LOGGER.error("Error auto-saving Curios data for player " + player.getUUID(), e);
} }
}); });
} }
} }
} }
if (autoCleanCuriosCacheTickCounter >= AUTO_CLEAN_CURIOS_CACHE_INTERVAL_TICKS) {
autoCleanCuriosCacheTickCounter = 0;
executorService.submit(() -> {
try {
CuriosCache.RemoveExpiredCuriosCache();
} catch (Exception e) {
PlayerSync.LOGGER.error("An error occurred while cleaning curios cache:" + e.getMessage());
}
});
}
} }
} }
@ -741,4 +827,12 @@ public class VanillaSync {
return totalXp; return totalXp;
} }
}
@SubscribeEvent
//Don't know what will happen if a fake player is killed,need more test.
public static void onPlayerDeath(LivingDeathEvent event) {
if (event.getEntity() instanceof ServerPlayer player && !deadPlayerWhileLogging.contains(event.getEntity().getUUID().toString())) {
CuriosCache.tryStoreCuriosToCache(player);
}
}
}

View File

@ -0,0 +1,122 @@
package vip.fubuki.playersync.sync.addons;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.GameRules;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.ModList;
import top.theillusivec4.curios.api.CuriosApi;
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
import top.theillusivec4.curios.api.type.inventory.IDynamicStackHandler;
import vip.fubuki.playersync.PlayerSync;
import vip.fubuki.playersync.sync.VanillaSync;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class CuriosCache {
private static final long CACHE_EXPIRY_MS = 3600000;
public static final ConcurrentHashMap<UUID, CuriosCacheEntry> curiosCache = new ConcurrentHashMap<>();
public static class CuriosCacheEntry {
final long timeStamp;
final String serializedData;
CuriosCacheEntry(String data) {
this.timeStamp = System.currentTimeMillis();
this.serializedData = data;
}
boolean isExpired() {
return System.currentTimeMillis() - timeStamp > CACHE_EXPIRY_MS;
}
}
//If player logged out by "Title Screen" button,you will not be able to get the handlerOpt,and it will make the curios inventory sync failed.
//Create a method to store temporary curios data when player is dead.
//Then check player status in the logged out event,and take a normal sync if player is alive.
//If player is dead or dying,the cache will be used to prevent the empty data from the failure of getting handlerOpt.
public static void tryStoreCuriosToCache(net.minecraft.world.entity.player.Player player) {
if (!ModList.get().isLoaded("curios") || !CuriosCache.isKeepInventoryActive(player)) {
return;
}
try {
LazyOptional<ICuriosItemHandler> handlerOpt = CuriosApi.getCuriosInventory(player);
if (!handlerOpt.isPresent() || handlerOpt.resolve().isEmpty()) {
PlayerSync.LOGGER.error("Obtain the curios api failed,cannot create the cache.");
return;
}
ICuriosItemHandler handler = handlerOpt.resolve().get();
String serializedData = serializeCuriosInventory(handler);
if (serializedData.startsWith("{}")) {
PlayerSync.LOGGER.debug("No curios data found,skipping the step of creating cache");
return;
}
UUID playerUuid = player.getUUID();
curiosCache.put(playerUuid, new CuriosCacheEntry(serializedData));
} catch (Exception e) {
PlayerSync.LOGGER.error("An error occurred while creating curios cache:" + e.getMessage());
}
}
private static String serializeCuriosInventory(ICuriosItemHandler handler) {
Map<String, String> flatMap = new HashMap<>();
try {
handler.getCurios().forEach((slotType, stacksHandler) -> {
IDynamicStackHandler dynStacks = stacksHandler.getStacks();
for (int i = 0; i < dynStacks.getSlots(); i++) {
ItemStack stack = dynStacks.getStackInSlot(i);
if (!stack.isEmpty()) {
String serialized = VanillaSync.serialize(VanillaSync.serializeNBT(stack).toString());
flatMap.put(slotType + ":" + i, serialized);
}
}
});
} catch (Exception e) {
PlayerSync.LOGGER.error("Failed to serialize curios data:" + e.getMessage());
}
return flatMap.isEmpty() ? "{}" : flatMap.toString();
}
public static boolean isKeepInventoryActive(Player player) {
MinecraftServer server = player.getServer();
if (server == null) {
PlayerSync.LOGGER.error("Trying to get the gamerule(KeepInventory),but server is null");
return false;
}
return server.getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY);
}
public static void RemoveExpiredCuriosCache() {
long startMs = System.currentTimeMillis();
int cacheSize = curiosCache.size();
if (cacheSize == 0) {
PlayerSync.LOGGER.debug("No curios caches,skipping cleaning");
return;
}
int removed = 0;
Iterator<Map.Entry<UUID, CuriosCacheEntry>> iterator = curiosCache.entrySet().iterator();
while (iterator.hasNext()) {
if (iterator.next().getValue().isExpired()) {
iterator.remove();;
removed ++;
}
}
if (removed > 0) {
PlayerSync.LOGGER.info("Cleaned {} curios cache(s),{} left,took {} Ms",
removed, curiosCache.size(), System.currentTimeMillis() - startMs);
}
}
}

View File

@ -1,4 +1,4 @@
package vip.fubuki.playersync.sync; package vip.fubuki.playersync.sync.addons;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@ -12,6 +12,7 @@ import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
import top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler; import top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler;
import top.theillusivec4.curios.api.type.inventory.IDynamicStackHandler; import top.theillusivec4.curios.api.type.inventory.IDynamicStackHandler;
import vip.fubuki.playersync.PlayerSync; import vip.fubuki.playersync.PlayerSync;
import vip.fubuki.playersync.sync.VanillaSync;
import vip.fubuki.playersync.util.JDBCsetUp; import vip.fubuki.playersync.util.JDBCsetUp;
import vip.fubuki.playersync.util.LocalJsonUtil; import vip.fubuki.playersync.util.LocalJsonUtil;
@ -135,7 +136,30 @@ public class ModsSupport {
*/ */
public void onPlayerLeave(net.minecraft.world.entity.player.Player player) throws SQLException { public void onPlayerLeave(net.minecraft.world.entity.player.Player player) throws SQLException {
if (ModList.get().isLoaded("curios")) { if (ModList.get().isLoaded("curios")) {
StoreCurios(player, false); if (player.isDeadOrDying()) {
if (!CuriosCache.curiosCache.isEmpty()) {
UUID playerUuid = player.getUUID();
if (CuriosCache.curiosCache.get(playerUuid) != null) {
CuriosCache.CuriosCacheEntry cacheEntry = CuriosCache.curiosCache.get(playerUuid);
String serializedData = cacheEntry.serializedData;
JDBCsetUp.executeUpdate("UPDATE curios SET curios_item = '" + serializedData + "' WHERE uuid = '" + player.getUUID() + "'");
CuriosCache.curiosCache.remove(playerUuid);
PlayerSync.LOGGER.info("Saving curios data for a dead-or-dying player {} Successfully", player.getStringUUID());
} else {
PlayerSync.LOGGER.error("Failed to find the cache of the logged out dead-or-dying player");
PlayerSync.LOGGER.error("The dead-or-dying player uuid is" + player.getStringUUID());
PlayerSync.LOGGER.error("Using default data...");
StoreCurios(player, false);
}
} else {
PlayerSync.LOGGER.warn("No curios cache found while executing a dead-or-dying player logout event.you can ignore this warning if keep-inventory is false");
PlayerSync.LOGGER.warn("The dead-or-dying player uuid is" + player.getStringUUID());
PlayerSync.LOGGER.warn("Using default data...");
StoreCurios(player, false);
}
} else {
StoreCurios(player, false);
}
} }
} }

View File

@ -3,5 +3,6 @@
"playersync.placeholder_titel_override": "Item Voucher", "playersync.placeholder_titel_override": "Item Voucher",
"playersync.item_placeholder_title": "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." "playersync.sqlexception": "SqlException detected!Connection lost,please contact with your admin.",
"playersync.wrong_entity_status": "An error occurred while creating playerEntity in the world,please login again."
} }

View File

@ -3,5 +3,6 @@
"playersync.placeholder_titel_override": "未知物品凭证", "playersync.placeholder_titel_override": "未知物品凭证",
"playersync.item_placeholder_title": "未知物品凭证", "playersync.item_placeholder_title": "未知物品凭证",
"playersync.already_online": "你不能同时加入多个在线的数据互通的服务器", "playersync.already_online": "你不能同时加入多个在线的数据互通的服务器",
"playersync.sqlexception": "检测到Sql异常!连接已中断,请联系管理员" "playersync.sqlexception": "检测到Sql异常!连接已中断,请联系管理员",
"playersync.wrong_entity_status": "在世界中尝试创建玩家实体时发生了错误,请尝试重新进入"
} }