From 13a4ffa524775c50cd7c1bb79836a07c2f65ec1c Mon Sep 17 00:00:00 2001 From: fly6516 Date: Mon, 24 Mar 2025 18:30:48 +0800 Subject: [PATCH] =?UTF-8?q?feat(storage):=20=E5=AE=9E=E7=8E=B0=E5=A2=93?= =?UTF-8?q?=E7=A2=91=E6=95=B0=E6=8D=AE=E7=9A=84=E6=8C=81=E4=B9=85=E5=8C=96?= =?UTF-8?q?=E5=AD=98=E5=82=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 TombstoneStorage 类,用于持久化存储墓碑数据 - 在 SimpleTombstone 类中集成 TombstoneStorage - 在玩家死亡时将墓碑数据写入存储 - 在玩家重生时从存储中移除墓碑数据 -每个 tick 检查玩家附近墓碑,并从存储中获取数据 --- .../com/simpletombstone/SimpleTombstone.java | 35 +++--- .../com/simpletombstone/TombstoneStorage.java | 100 ++++++++++++++++++ 2 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/simpletombstone/TombstoneStorage.java diff --git a/src/main/java/com/simpletombstone/SimpleTombstone.java b/src/main/java/com/simpletombstone/SimpleTombstone.java index 09f4013..909ac80 100644 --- a/src/main/java/com/simpletombstone/SimpleTombstone.java +++ b/src/main/java/com/simpletombstone/SimpleTombstone.java @@ -5,6 +5,7 @@ import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.api.EnvType; import net.minecraft.block.*; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -27,16 +28,19 @@ public class SimpleTombstone implements ModInitializer { public void onInitialize() { if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) { LOGGER.info("[SimpleTombstone] 服务器端初始化中..."); + + // 监听玩家死亡事件 ServerLivingEntityEvents.ALLOW_DEATH.register((entity, damageSource, damageAmount) -> { if (entity instanceof ServerPlayerEntity player) { LOGGER.info("[SimpleTombstone] 检测到玩家 {} 死亡,创建墓碑...", player.getName().getString()); createTombstoneForMixin(player); DEAD_PLAYERS.add(player.getUuid()); - return false; + return false; // 阻止默认死亡逻辑,防止玩家直接死亡 } return true; }); + // 监听玩家重生事件 ServerPlayerEvents.AFTER_RESPAWN.register((oldPlayer, newPlayer, alive) -> { UUID playerId = newPlayer.getUuid(); if (DEAD_PLAYERS.contains(playerId)) { @@ -46,16 +50,17 @@ public class SimpleTombstone implements ModInitializer { } }); + // 监听服务器每个 tick 检查玩家是否靠近墓碑 + ServerTickEvents.END_SERVER_TICK.register(server -> { + for (ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) { + if (RESURRECTED_PLAYERS.contains(player.getUuid())) { + checkPlayerNearTombstone(player); + } + } + }); + LOGGER.info("[SimpleTombstone] 服务器端初始化完成"); } - - ServerTickEvents.END_SERVER_TICK.register(server -> { - for (ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) { - if (RESURRECTED_PLAYERS.contains(player.getUuid())) { - checkPlayerNearTombstone(player); - } - } - }); } public static void createTombstoneForMixin(ServerPlayerEntity player) { @@ -76,7 +81,6 @@ public class SimpleTombstone implements ModInitializer { world.setBlockState(deathPos, Blocks.GLASS.getDefaultState()); } - BlockPos tombstonePos = deathPos.up(); List items = new ArrayList<>(); for (int i = 0; i < player.getInventory().size(); i++) { @@ -85,7 +89,12 @@ public class SimpleTombstone implements ModInitializer { items.add(stack); } } - TOMBSTONE_CHESTS.put(tombstonePos, new PlayerTombstoneData(player.getUuid(), items)); + PlayerTombstoneData tombstoneData = new PlayerTombstoneData(player.getUuid(), items); + TOMBSTONE_CHESTS.put(tombstonePos, tombstoneData); + + // Ensure TombstoneStorage is loaded and Tombstone is added immediately + TombstoneStorage storage = TombstoneStorage.load((ServerWorld) world); + storage.addTombstone(tombstonePos, tombstoneData); // Write tombstone data immediately Random random = new Random(); List flowerPots = Arrays.asList( @@ -104,6 +113,7 @@ public class SimpleTombstone implements ModInitializer { private void checkPlayerNearTombstone(ServerPlayerEntity player) { World world = player.getWorld(); BlockPos playerPos = player.getBlockPos(); + TombstoneStorage storage = TombstoneStorage.load((ServerWorld) world); for (BlockPos pos : BlockPos.iterate( playerPos.getX() - 4, playerPos.getY() - 4, playerPos.getZ() - 4, @@ -124,6 +134,7 @@ public class SimpleTombstone implements ModInitializer { world.removeBlock(pos, false); TOMBSTONE_CHESTS.remove(pos); RESURRECTED_PLAYERS.remove(player.getUuid()); + storage.removeTombstone(pos); LOGGER.info("[SimpleTombstone] 移除墓碑 {} 并归还物品。", pos.toShortString()); break; } @@ -131,6 +142,6 @@ public class SimpleTombstone implements ModInitializer { } } - private record PlayerTombstoneData(UUID playerId, List items) { + record PlayerTombstoneData(UUID playerId, List items) { } } diff --git a/src/main/java/com/simpletombstone/TombstoneStorage.java b/src/main/java/com/simpletombstone/TombstoneStorage.java new file mode 100644 index 0000000..eec00b2 --- /dev/null +++ b/src/main/java/com/simpletombstone/TombstoneStorage.java @@ -0,0 +1,100 @@ +package com.simpletombstone; + +import net.minecraft.nbt.*; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.PersistentState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.item.ItemStack; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +public class TombstoneStorage extends PersistentState { + private static final String KEY_TOMBSTONES = "Tombstones"; + private static final String KEY_POS = "Pos"; + private static final String KEY_ITEMS = "Items"; + private static final String KEY_PLAYER_ID = "PlayerId"; + private static final Logger LOGGER = LoggerFactory.getLogger(TombstoneStorage.class); + + private final Map tombstoneData = new HashMap<>(); + + public static TombstoneStorage load(ServerWorld world) { + LOGGER.info("[TombstoneStorage] 加载墓碑数据..."); + TombstoneStorage storage = world.getPersistentStateManager().getOrCreate( + new PersistentState.Type<>( + TombstoneStorage::new, // Supplier + TombstoneStorage::fromNbt, // NBT加载函数 + null // 可选的DataFixTypes(版本升级用) + ), + "simple_tombstone" // 存储名称 + ); + LOGGER.info("[TombstoneStorage] 成功加载墓碑数据."); + return storage; + } + + public void addTombstone(BlockPos pos, SimpleTombstone.PlayerTombstoneData data) { + LOGGER.info("[TombstoneStorage] 添加墓碑数据: {}", pos.toShortString()); + tombstoneData.put(pos, data); + markDirty(); // 确保数据被保存 + } + + public void removeTombstone(BlockPos pos) { + LOGGER.info("[TombstoneStorage] 移除墓碑数据: {}", pos.toShortString()); + tombstoneData.remove(pos); + markDirty(); // 确保数据被保存 + } + + public Map getTombstoneData() { + return tombstoneData; + } + + @Override + public NbtCompound writeNbt(NbtCompound nbt) { + LOGGER.info("[TombstoneStorage] 写入墓碑数据到 NBT..."); + NbtList tombstoneList = new NbtList(); + for (Map.Entry entry : tombstoneData.entrySet()) { + NbtCompound tombstoneTag = new NbtCompound(); + tombstoneTag.put(KEY_POS, NbtHelper.fromBlockPos(entry.getKey())); + tombstoneTag.putUuid(KEY_PLAYER_ID, entry.getValue().playerId()); + + NbtList itemList = new NbtList(); + for (ItemStack stack : entry.getValue().items()) { + NbtCompound stackTag = stack.writeNbt(new NbtCompound()); + itemList.add(stackTag); + } + tombstoneTag.put(KEY_ITEMS, itemList); + tombstoneList.add(tombstoneTag); + } + nbt.put(KEY_TOMBSTONES, tombstoneList); + + // 打印完整的NBT数据以检查格式 + LOGGER.info("[TombstoneStorage] 写入的 NBT 数据: {}", nbt.toString()); + LOGGER.info("[TombstoneStorage] NBT 数据写入成功."); + return nbt; + } + + public static TombstoneStorage fromNbt(NbtCompound nbt) { + //LOGGER.info("[TombstoneStorage] 从 NBT 加载墓碑数据..."); + TombstoneStorage storage = new TombstoneStorage(); + NbtList tombstoneList = nbt.getList(KEY_TOMBSTONES, NbtElement.COMPOUND_TYPE); + + for (NbtElement element : tombstoneList) { + NbtCompound tombstoneTag = (NbtCompound) element; + BlockPos pos = NbtHelper.toBlockPos(tombstoneTag.getCompound(KEY_POS)); + UUID playerId = tombstoneTag.getUuid(KEY_PLAYER_ID); + + List items = new ArrayList<>(); + NbtList itemList = tombstoneTag.getList(KEY_ITEMS, NbtElement.COMPOUND_TYPE); + for (NbtElement itemElement : itemList) { + items.add(ItemStack.fromNbt((NbtCompound) itemElement)); + } + + storage.tombstoneData.put(pos, new SimpleTombstone.PlayerTombstoneData(playerId, items)); + LOGGER.info("[TombstoneStorage] 加载墓碑: {},玩家ID: {}", pos.toShortString(), playerId); + } + + //LOGGER.info("[TombstoneStorage] 成功加载墓碑数据."); + return storage; + } +}