feat(storage): 实现墓碑数据的持久化存储
- 新增 TombstoneStorage 类,用于持久化存储墓碑数据 - 在 SimpleTombstone 类中集成 TombstoneStorage - 在玩家死亡时将墓碑数据写入存储 - 在玩家重生时从存储中移除墓碑数据 -每个 tick 检查玩家附近墓碑,并从存储中获取数据
This commit is contained in:
parent
c54688ee0f
commit
13a4ffa524
@ -5,6 +5,7 @@ import net.fabricmc.loader.api.FabricLoader;
|
|||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.minecraft.block.*;
|
import net.minecraft.block.*;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
@ -27,16 +28,19 @@ public class SimpleTombstone implements ModInitializer {
|
|||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) {
|
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) {
|
||||||
LOGGER.info("[SimpleTombstone] 服务器端初始化中...");
|
LOGGER.info("[SimpleTombstone] 服务器端初始化中...");
|
||||||
|
|
||||||
|
// 监听玩家死亡事件
|
||||||
ServerLivingEntityEvents.ALLOW_DEATH.register((entity, damageSource, damageAmount) -> {
|
ServerLivingEntityEvents.ALLOW_DEATH.register((entity, damageSource, damageAmount) -> {
|
||||||
if (entity instanceof ServerPlayerEntity player) {
|
if (entity instanceof ServerPlayerEntity player) {
|
||||||
LOGGER.info("[SimpleTombstone] 检测到玩家 {} 死亡,创建墓碑...", player.getName().getString());
|
LOGGER.info("[SimpleTombstone] 检测到玩家 {} 死亡,创建墓碑...", player.getName().getString());
|
||||||
createTombstoneForMixin(player);
|
createTombstoneForMixin(player);
|
||||||
DEAD_PLAYERS.add(player.getUuid());
|
DEAD_PLAYERS.add(player.getUuid());
|
||||||
return false;
|
return false; // 阻止默认死亡逻辑,防止玩家直接死亡
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 监听玩家重生事件
|
||||||
ServerPlayerEvents.AFTER_RESPAWN.register((oldPlayer, newPlayer, alive) -> {
|
ServerPlayerEvents.AFTER_RESPAWN.register((oldPlayer, newPlayer, alive) -> {
|
||||||
UUID playerId = newPlayer.getUuid();
|
UUID playerId = newPlayer.getUuid();
|
||||||
if (DEAD_PLAYERS.contains(playerId)) {
|
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] 服务器端初始化完成");
|
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) {
|
public static void createTombstoneForMixin(ServerPlayerEntity player) {
|
||||||
@ -76,7 +81,6 @@ public class SimpleTombstone implements ModInitializer {
|
|||||||
world.setBlockState(deathPos, Blocks.GLASS.getDefaultState());
|
world.setBlockState(deathPos, Blocks.GLASS.getDefaultState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BlockPos tombstonePos = deathPos.up();
|
BlockPos tombstonePos = deathPos.up();
|
||||||
List<ItemStack> items = new ArrayList<>();
|
List<ItemStack> items = new ArrayList<>();
|
||||||
for (int i = 0; i < player.getInventory().size(); i++) {
|
for (int i = 0; i < player.getInventory().size(); i++) {
|
||||||
@ -85,7 +89,12 @@ public class SimpleTombstone implements ModInitializer {
|
|||||||
items.add(stack);
|
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();
|
Random random = new Random();
|
||||||
List<Block> flowerPots = Arrays.asList(
|
List<Block> flowerPots = Arrays.asList(
|
||||||
@ -104,6 +113,7 @@ public class SimpleTombstone implements ModInitializer {
|
|||||||
private void checkPlayerNearTombstone(ServerPlayerEntity player) {
|
private void checkPlayerNearTombstone(ServerPlayerEntity player) {
|
||||||
World world = player.getWorld();
|
World world = player.getWorld();
|
||||||
BlockPos playerPos = player.getBlockPos();
|
BlockPos playerPos = player.getBlockPos();
|
||||||
|
TombstoneStorage storage = TombstoneStorage.load((ServerWorld) world);
|
||||||
|
|
||||||
for (BlockPos pos : BlockPos.iterate(
|
for (BlockPos pos : BlockPos.iterate(
|
||||||
playerPos.getX() - 4, playerPos.getY() - 4, playerPos.getZ() - 4,
|
playerPos.getX() - 4, playerPos.getY() - 4, playerPos.getZ() - 4,
|
||||||
@ -124,6 +134,7 @@ public class SimpleTombstone implements ModInitializer {
|
|||||||
world.removeBlock(pos, false);
|
world.removeBlock(pos, false);
|
||||||
TOMBSTONE_CHESTS.remove(pos);
|
TOMBSTONE_CHESTS.remove(pos);
|
||||||
RESURRECTED_PLAYERS.remove(player.getUuid());
|
RESURRECTED_PLAYERS.remove(player.getUuid());
|
||||||
|
storage.removeTombstone(pos);
|
||||||
LOGGER.info("[SimpleTombstone] 移除墓碑 {} 并归还物品。", pos.toShortString());
|
LOGGER.info("[SimpleTombstone] 移除墓碑 {} 并归还物品。", pos.toShortString());
|
||||||
break;
|
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) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
100
src/main/java/com/simpletombstone/TombstoneStorage.java
Normal file
100
src/main/java/com/simpletombstone/TombstoneStorage.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user