如何不依赖标题处理Spigot物品栏点击事件?解决变量标题失效问题
解决Spigot中带变量标题的自定义物品栏点击识别问题
方案1:使用自定义InventoryHolder(推荐)
这是Spigot官方推荐的方式,通过自定义物品栏持有者来标识专属物品栏,完全不受标题变量影响,还能存储额外关联数据。
步骤1:创建自定义InventoryHolder类
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; public class PlayerUniqueInventoryHolder implements InventoryHolder { // 存储需要的变量,比如生成标题时用到的myVar值 private final String playerIdentifier; public PlayerUniqueInventoryHolder(String playerIdentifier) { this.playerIdentifier = playerIdentifier; } @Override public Inventory getInventory() { return null; // Bukkit会自动关联物品栏,无需手动实现 } // 获取存储的变量,供后续逻辑使用 public String getPlayerIdentifier() { return playerIdentifier; } }
步骤2:创建并打开带持有者的物品栏
// 传入myVar作为标识数据,同时生成带变量的标题 Inventory inv = Bukkit.createInventory( new PlayerUniqueInventoryHolder(myVar), 9, "Title " + myVar ); player.openInventory(inv);
步骤3:在点击事件中识别自定义物品栏
@EventHandler public void onPlayerClick(InventoryClickEvent event) { // 空物品直接返回,避免空指针异常 if (event.getCurrentItem() == null) return; // 判断物品栏的持有者是否为我们自定义的类型 if (event.getInventory().getHolder() instanceof PlayerUniqueInventoryHolder) { PlayerUniqueInventoryHolder holder = (PlayerUniqueInventoryHolder) event.getInventory().getHolder(); String targetVar = holder.getPlayerIdentifier(); // 获取当初传入的myVar值 Player player = (Player) event.getWhoClicked(); // 取消默认操作,防止物品被移动/取出 event.setCancelled(true); // 这里编写你的点击逻辑,比如根据targetVar执行不同操作 // ... } }
方案2:使用物品栏元数据
如果不想创建自定义Holder,可以给物品栏添加专属元数据标记,通过元数据来识别。
创建物品栏时添加元数据
Inventory inv = Bukkit.createInventory(null, 9, "Title " + myVar); // 给物品栏加元数据,yourPluginInstance替换成你的插件主类实例 inv.setMetadata("unique_player_inv", new FixedMetadataValue(yourPluginInstance, true)); player.openInventory(inv);
事件中识别元数据
@EventHandler public void onPlayerClick(InventoryClickEvent event) { if (event.getCurrentItem() == null) return; Inventory inv = event.getInventory(); // 检查是否存在我们标记的元数据 if (inv.hasMetadata("unique_player_inv")) { Player player = (Player) event.getWhoClicked(); event.setCancelled(true); // 处理点击逻辑 // ... } }
方案3:标题前缀匹配(不推荐)
如果只是临时应急需求,可以通过标题前缀判断,但该方式容易和其他插件的物品栏冲突,仅作备选:
@EventHandler public void onPlayerClick(InventoryClickEvent event) { if (event.getCurrentItem() == null) return; String title = event.getView().getTitle(); // 判断标题是否以固定前缀开头 if (title.startsWith("Title ")) { Player player = (Player) event.getWhoClicked(); event.setCancelled(true); // 可以通过截取标题拿到后面的变量值 String myVarValue = title.substring(6); // 处理点击逻辑 // ... } }
内容的提问来源于stack exchange,提问作者Elikill58
相关产品推荐
相关产品推荐

