feat(simple-tombstone):优化墓碑生成逻辑并添加物品归还功能

- 改进墓碑生成逻辑,确保在非空气方块位置也能生成墓碑
- 新增物品归还功能,玩家重生后可从墓碑取回物品
- 增加玩家死亡和重生时的日志记录
- 优化代码结构,提高可维护性
This commit is contained in:
fly6516 2025-03-24 16:20:40 +08:00
parent e1adba7ded
commit c1a7c1c62d

View File

@ -4,72 +4,133 @@ import net.fabricmc.api.ModInitializer;
import net.fabricmc.loader.api.FabricLoader; 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.block.entity.BlockEntityType;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import net.minecraft.block.entity.ChestBlockEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
// 新增导入语句 import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents; import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
import java.util.*;
public class SimpleTombstone implements ModInitializer { public class SimpleTombstone implements ModInitializer {
public static final String MOD_ID = "simple-tombstone"; public static final String MOD_ID = "simple-tombstone";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
private static final Map<BlockPos, PlayerTombstoneData> TOMBSTONE_CHESTS = new HashMap<>();
// 自定义墓碑方块 private static final Set<UUID> DEAD_PLAYERS = new HashSet<>();
public static final Block LOOT_CHEST = Blocks.CHEST; // 修改为原版箱子 private static final Set<UUID> RESURRECTED_PLAYERS = new HashSet<>();
@Override @Override
public void onInitialize() { public void onInitialize() {
// 将事件注册移到服务端环境判断块内
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) { if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) {
ServerPlayerEvents.ALLOW_DEATH.register((player, damageSource, damageAmount) -> { LOGGER.info("[SimpleTombstone] 服务器端初始化中...");
ServerLivingEntityEvents.ALLOW_DEATH.register((entity, damageSource, damageAmount) -> {
if (entity instanceof ServerPlayerEntity player) {
LOGGER.info("[SimpleTombstone] 检测到玩家 {} 死亡,创建墓碑...", player.getName().getString());
createTombstoneForMixin(player); createTombstoneForMixin(player);
player.getInventory().clear(); // 需要手动清空背包 DEAD_PLAYERS.add(player.getUuid());
return false; // 阻止物品掉落 return false;
});
LOGGER.info("服务端初始化完成");
} else {
LOGGER.info("客户端初始化完成");
} }
return true;
});
ServerPlayerEvents.AFTER_RESPAWN.register((oldPlayer, newPlayer, alive) -> {
UUID playerId = newPlayer.getUuid();
if (DEAD_PLAYERS.contains(playerId)) {
LOGGER.info("[SimpleTombstone] 玩家 {} 已重生,物品归还功能已启用。", newPlayer.getName().getString());
DEAD_PLAYERS.remove(playerId);
RESURRECTED_PLAYERS.add(playerId);
}
});
LOGGER.info("[SimpleTombstone] 服务器端初始化完成");
}
ServerTickEvents.END_SERVER_TICK.register(server -> {
for (ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) {
if (RESURRECTED_PLAYERS.contains(player.getUuid())) {
checkPlayerNearTombstone(player);
}
}
});
} }
/**
* Mixin 调用在玩家死亡时创建物品箱
*/
public static void createTombstoneForMixin(ServerPlayerEntity player) { public static void createTombstoneForMixin(ServerPlayerEntity player) {
BlockPos deathPos = player.getBlockPos(); BlockPos deathPos = player.getBlockPos();
World world = player.getWorld(); World world = player.getWorld();
// 检查位置是否为空 while (world.isAir(deathPos.down())) {
if (!world.isAir(deathPos)) { deathPos = deathPos.down();
return;
} }
// 放置箱子方块 if (!world.getBlockState(deathPos).isSolid()) {
world.setBlockState(deathPos, LOOT_CHEST.getDefaultState()); LOGGER.warn("[SimpleTombstone] 位置 {} 处为液体,替换为玻璃。", deathPos.toShortString());
world.setBlockState(deathPos, Blocks.GLASS.getDefaultState());
}
// 存储物品到箱子 BlockPos tombstonePos = deathPos.up();
if (world.getBlockEntity(deathPos) instanceof ChestBlockEntity chestEntity) { List<ItemStack> items = new ArrayList<>();
for (int i = 0; i < player.getInventory().size(); i++) { for (int i = 0; i < player.getInventory().size(); i++) {
ItemStack stack = player.getInventory().removeStack(i, Integer.MAX_VALUE); ItemStack stack = player.getInventory().removeStack(i, Integer.MAX_VALUE);
if (!stack.isEmpty()) { if (!stack.isEmpty()) {
chestEntity.setStack(i,stack); items.add(stack);
}
}
TOMBSTONE_CHESTS.put(tombstonePos, new PlayerTombstoneData(player.getUuid(), items));
Random random = new Random();
List<Block> flowerPots = Arrays.asList(
Blocks.POTTED_OAK_SAPLING,
Blocks.POTTED_DANDELION,
Blocks.POTTED_POPPY,
Blocks.POTTED_BLUE_ORCHID
);
Block chosenFlowerPot = flowerPots.get(random.nextInt(flowerPots.size()));
world.setBlockState(tombstonePos, chosenFlowerPot.getDefaultState());
player.sendMessage(Text.of("A loot chest has been placed at " + deathPos.toShortString()), false);
LOGGER.info("[SimpleTombstone] 为玩家 {} 在 {} 创建了墓碑。", player.getName().getString(), deathPos.toShortString());
}
private void checkPlayerNearTombstone(ServerPlayerEntity player) {
World world = player.getWorld();
BlockPos playerPos = player.getBlockPos();
for (BlockPos pos : BlockPos.iterate(
playerPos.getX() - 4, playerPos.getY() - 4, playerPos.getZ() - 4,
playerPos.getX() + 4, playerPos.getY() + 4, playerPos.getZ() + 4
)) {
PlayerTombstoneData data = TOMBSTONE_CHESTS.get(pos);
if (data != null && data.getPlayerId().equals(player.getUuid())) {
Block block = world.getBlockState(pos).getBlock();
if (block instanceof FlowerPotBlock) {
LOGGER.info("[SimpleTombstone] 玩家 {} 靠近墓碑,恢复物品。", player.getName().getString());
for (ItemStack stack : data.getItems()) {
player.getInventory().offerOrDrop(stack);
}
world.removeBlock(pos, false);
TOMBSTONE_CHESTS.remove(pos);
RESURRECTED_PLAYERS.remove(player.getUuid());
LOGGER.info("[SimpleTombstone] 移除墓碑 {} 并归还物品。", pos.toShortString());
break;
}
} }
} }
} }
// 发送消息和日志 private static class PlayerTombstoneData {
player.sendMessage(Text.of("A loot chest has been placed at " + deathPos.toShortString()), false); private final UUID playerId;
LOGGER.info("为玩家 {} 在 {} 创建了物品箱。", player.getName().getString(), deathPos.toShortString()); private final List<ItemStack> items;
public PlayerTombstoneData(UUID playerId, List<ItemStack> items) {
this.playerId = playerId;
this.items = items;
}
public UUID getPlayerId() { return playerId; }
public List<ItemStack> getItems() { return items; }
} }
} }