From 2364ddee97a17ac6dbb3062886731e7ee80a570f Mon Sep 17 00:00:00 2001 From: Coldsmile_7 Date: Wed, 15 Apr 2026 01:20:05 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=20README=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=BD=9C=E5=BD=B1=E7=9B=92=E5=92=8C=E6=9C=AB=E5=BD=B1?= =?UTF-8?q?=E7=AE=B1=E5=8A=9F=E8=83=BD=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 18 ++++- .../commands/EnderChestCommand.java | 20 ++--- .../listeners/InventoryTitleListener.java | 77 ------------------- 3 files changed, 22 insertions(+), 93 deletions(-) delete mode 100644 src/main/java/cn/infstar/essentialsC/listeners/InventoryTitleListener.java diff --git a/README.md b/README.md index d20d01b..ae005c6 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,14 @@ - 锻造台 (`/smithingtable`, `/st`) - 切石机 (`/stonecutter`, `/sc`) +### 📦 容器管理 +- **末影箱** (`/enderchest`, `/ec`) - 随时访问末影箱(参考 EssentialsX 实现) +- **潜影盒快捷打开** - 潜行+右键点击潜影盒直接打开内容(类似 CMI) + - 支持自定义标题 + - 防刷物品机制 + - 防止套娃(不能在潜影盒中放入另一个潜影盒) + ### 🔧 实用工具 -- **末影箱** (`/enderchest`, `/ec`) - 随时访问末影箱 - **帽子** (`/hat`) - 将手中物品戴在头上 - **自杀** (`/suicide`, `/die`) - 快速自杀 - **飞行** (`/fly`) - 切换飞行模式 @@ -41,7 +47,6 @@ - 帮助菜单智能显示(只显示有权限的命令) - 默认仅 OP 可用,可通过权限插件授权 - CMI 风格的命令别名支持 -- 潜行+右键潜影盒直接打开(无需放置) ## 📦 安装 @@ -178,7 +183,9 @@ mvn clean package - ✅ 智能权限过滤的帮助菜单 - ✅ 完整的多语言支持 - ✅ 功能方块权限菜单 -- ✅ 潜行+右键潜影盒直接打开 +- ✅ 潜行+右键潜影盒直接打开(防刷机制) +- ✅ 末影箱参考 EssentialsX 实现(100% 安全) +- ✅ 潜影盒自定义标题配置 - ✅ 轻量级无依赖设计 - ✅ 现代化的 Paper API 支持 @@ -186,6 +193,11 @@ mvn clean package ### v1.2.0 - ✨ 新增潜行+右键潜影盒直接打开功能(类似 CMI) + - 支持自定义标题(config.yml 配置) + - 防刷物品机制(快照验证 + 数量检查) + - 防止套娃(不能放入另一个潜影盒) + - 异常恢复(物品丢失自动掉落) +- ✨ 末影箱改用 EssentialsX 实现方式(100% 安全) - ✨ 功能方块菜单配置化(从 config.yml 读取) - ✨ 功能方块菜单添加音效反馈 - ✨ CMI 风格命令别名系统 diff --git a/src/main/java/cn/infstar/essentialsC/commands/EnderChestCommand.java b/src/main/java/cn/infstar/essentialsC/commands/EnderChestCommand.java index 099e644..ce1947b 100644 --- a/src/main/java/cn/infstar/essentialsC/commands/EnderChestCommand.java +++ b/src/main/java/cn/infstar/essentialsC/commands/EnderChestCommand.java @@ -1,8 +1,11 @@ package cn.infstar.essentialsC.commands; -import cn.infstar.essentialsC.EssentialsC; import org.bukkit.entity.Player; +/** + * 末影箱命令 - 参考 EssentialsX 实现 + * 直接打开玩家的末影箱,确保数据安全 + */ public class EnderChestCommand extends BaseCommand { public EnderChestCommand() { @@ -11,18 +14,9 @@ public class EnderChestCommand extends BaseCommand { @Override protected boolean execute(Player player, String[] args) { - EssentialsC plugin = EssentialsC.getInstance(); - - // 如果启用了 ProtocolLib,使用自定义标题 - if (plugin.isProtocolLibEnabled()) { - // 从配置读取标题 - String title = plugin.getConfig().getString("enderchest.title", "&5随身末影箱"); - - // 标记下一个打开的 inventory 需要修改标题 - plugin.getInventoryTitleListener().markForTitleChange(player, title); - } - - // 直接打开玩家的末影箱(参考 EssentialsX 实现) + // 直接打开玩家的末影箱(EssentialsX 方式) + // 优点:100% 安全,不会吞物品或刷物品 + // 缺点:标题显示为 "Ender Chest"(由客户端语言决定) player.openInventory(player.getEnderChest()); return true; } diff --git a/src/main/java/cn/infstar/essentialsC/listeners/InventoryTitleListener.java b/src/main/java/cn/infstar/essentialsC/listeners/InventoryTitleListener.java deleted file mode 100644 index a4c0eee..0000000 --- a/src/main/java/cn/infstar/essentialsC/listeners/InventoryTitleListener.java +++ /dev/null @@ -1,77 +0,0 @@ -package cn.infstar.essentialsC.listeners; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.events.ListenerPriority; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.events.PacketEvent; -import com.comphenix.protocol.wrappers.WrappedChatComponent; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -/** - * 使用 ProtocolLib 修改 Inventory 标题 - * 通过拦截 OPEN_WINDOW 数据包实现自定义标题 - */ -public class InventoryTitleListener extends PacketAdapter { - - // 存储需要修改标题的玩家和对应的新标题 - private final Map pendingTitleChanges = new HashMap<>(); - - public InventoryTitleListener(Plugin plugin) { - super(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.OPEN_WINDOW); - } - - /** - * 标记玩家需要修改下一个打开的 inventory 标题 - * @param player 玩家 - * @param title 新标题(支持颜色代码) - */ - public void markForTitleChange(Player player, String title) { - pendingTitleChanges.put(player.getUniqueId(), title); - } - - @Override - public void onPacketSending(PacketEvent event) { - Player player = event.getPlayer(); - UUID playerId = player.getUniqueId(); - - // 检查该玩家是否有待处理的标题修改 - String newTitle = pendingTitleChanges.remove(playerId); - if (newTitle == null) { - return; - } - - try { - PacketContainer packet = event.getPacket(); - - // Paper 1.21+ 使用 WrappedChatComponent 作为标题 - // 将颜色代码 & 转换为 § - String formattedTitle = newTitle.replace('&', '§'); - - // 创建聊天组件 - WrappedChatComponent titleComponent = WrappedChatComponent.fromText(formattedTitle); - - // 修改数据包中的标题字段 - // 在 1.21+ 中,标题是第二个字段(索引1) - packet.getChatComponents().write(0, titleComponent); - - } catch (Exception e) { - // 如果修改失败,记录错误但不影响正常流程 - Bukkit.getLogger().warning("[EssentialsC] 修改 inventory 标题失败: " + e.getMessage()); - } - } - - /** - * 清理所有待处理的标题修改(防止内存泄漏) - */ - public void cleanup() { - pendingTitleChanges.clear(); - } -}