feat(storage): 实现墓碑数据的持久化存储

- 新增 TombstoneStorage 类,用于持久化存储墓碑数据
- 在 SimpleTombstone 类中集成 TombstoneStorage
- 在玩家死亡时将墓碑数据写入存储
- 在玩家重生时从存储中移除墓碑数据
-每个 tick 检查玩家附近墓碑,并从存储中获取数据
This commit is contained in:
fly6516 2025-03-24 18:30:48 +08:00
parent c54688ee0f
commit 13a4ffa524
2 changed files with 123 additions and 12 deletions

View File

@ -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<ItemStack> 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<Block> 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<ItemStack> items) {
record PlayerTombstoneData(UUID playerId, List<ItemStack> items) {
}
}

View File

@ -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<BlockPos, SimpleTombstone.PlayerTombstoneData> 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<BlockPos, SimpleTombstone.PlayerTombstoneData> getTombstoneData() {
return tombstoneData;
}
@Override
public NbtCompound writeNbt(NbtCompound nbt) {
LOGGER.info("[TombstoneStorage] 写入墓碑数据到 NBT...");
NbtList tombstoneList = new NbtList();
for (Map.Entry<BlockPos, SimpleTombstone.PlayerTombstoneData> 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<ItemStack> 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;
}
}