Minecraft Forge中EntityInteract事件取消失效问题求助
解决PlayerInteractEvent.EntityInteract取消后仍打开马物品栏的问题
我明白你遇到的困扰——事件触发了、消息也发了,但服务器还是执意打开马的物品栏。这大概率是因为你漏处理了一个关键的交互事件,咱们一步步来搞定它:
1. 同时处理EntityInteract和EntityInteractSpecific事件
当玩家精准点击马的身体部位时,Forge会优先触发PlayerInteractEvent.EntityInteractSpecific而非普通的EntityInteract,这是很多开发者容易踩的坑。你需要同时注册这两个事件的处理方法,覆盖所有交互场景。
整理后的代码示例:
// 处理普通实体交互事件 @SubscribeEvent(priority = EventPriority.HIGHEST) public void onEntityInteract(PlayerInteractEvent.EntityInteract event) { handleHorseInteraction(event.getPlayer(), event.getTarget(), event); } // 处理精准实体交互事件(重点!马的交互大多触发这个) @SubscribeEvent(priority = EventPriority.HIGHEST) public void onEntityInteractSpecific(PlayerInteractEvent.EntityInteractSpecific event) { handleHorseInteraction(event.getPlayer(), event.getTarget(), event); } // 提取公共逻辑,避免重复代码 private void handleHorseInteraction(PlayerEntity player, Entity target, PlayerInteractEvent event) { if (player == null || player.world.isClient || !(target instanceof AbstractHorseEntity)) { return; } AbstractHorseEntity horseEntity = (AbstractHorseEntity) target; if (player.isCrouching()) { Item mainItem = player.getHeldItemMainhand().getItem(); for (Item allowedItem : allowed) { if (mainItem.equals(allowedItem)) { String[] result = new HorseStats().getHorseStats(horseEntity); for (String s : result) { if (s != null && !s.isEmpty()) { player.sendMessage(new TranslationTextComponent(s)); } } // 正确设置事件状态,彻底阻止后续处理 event.setResult(Event.Result.DENY); event.setCanceled(true); event.setCancellationResult(ActionResultType.SUCCESS); return; } } } }
2. 确保在服务器端处理取消逻辑
代码里加了player.world.isClient的判断,避免在客户端执行不必要的操作。核心的取消逻辑必须在服务器端执行,这样服务器才会终止打开马栏的请求流程。
3. 额外优化:阻止客户端的交互反馈
如果客户端还会显示打开马栏的动画,你可以在客户端也处理这两个事件并取消,这样客户端既不会向服务器发送交互数据包,也不会有视觉上的多余反馈:
@SubscribeEvent(priority = EventPriority.HIGHEST) @OnlyIn(Dist.CLIENT) public void onClientEntityInteract(PlayerInteractEvent.EntityInteract event) { handleClientHorseInteraction(event.getPlayer(), event.getTarget(), event); } @SubscribeEvent(priority = EventPriority.HIGHEST) @OnlyIn(Dist.CLIENT) public void onClientEntityInteractSpecific(PlayerInteractEvent.EntityInteractSpecific event) { handleClientHorseInteraction(event.getPlayer(), event.getTarget(), event); } @OnlyIn(Dist.CLIENT) private void handleClientHorseInteraction(PlayerEntity player, Entity target, PlayerInteractEvent event) { if (player == null || !(target instanceof AbstractHorseEntity)) { return; } AbstractHorseEntity horseEntity = (AbstractHorseEntity) target; if (player.isCrouching()) { Item mainItem = player.getHeldItemMainhand().getItem(); for (Item allowedItem : allowed) { if (mainItem.equals(allowedItem)) { event.setResult(Event.Result.DENY); event.setCanceled(true); return; } } } }
这样修改后,再蹲下手持允许物品点击马,服务器就不会处理打开马栏的请求,同时还能正常显示马的属性消息啦。
内容的提问来源于stack exchange,提问作者recklessGreed




