Java开发Minecraft插件时WorldGuard区域判断else分支异常触发问题
问题根因
你的代码在for循环中对每个生效区域单独做if/else判断,而玩家当前位置同时处于arena和safezone两个重叠区域内:
- 遍历到
arena区域时不匹配safezone,触发else分支 - 遍历到
safezone区域时匹配成功,触发if分支
因此会出现两个分支都执行的现象。
修复方案
先全局判断玩家所在的所有区域中是否包含safezone,再根据判断结果执行对应逻辑,不要把分支判断写在遍历区域的循环内部。
修复后的代码如下:
@EventHandler public void entityDamageEvent(EntityDamageByEntityEvent event) { // 新增伤害来源类型判断,避免非玩家伤害触发时出现类型转换异常 if (event.getEntity() instanceof Player && event.getDamager() instanceof Player) { Player attacker = (Player) event.getDamager(); Player player = (Player) event.getEntity(); Location location = player.getLocation(); WorldGuardPlatform platform = com.sk89q.worldguard.WorldGuard.getInstance().getPlatform(); RegionContainer container = platform.getRegionContainer(); if (location.getWorld() != null) { RegionManager regionManager = container.get(BukkitAdapter.adapt(location.getWorld())); ApplicableRegionSet set = regionManager.getApplicableRegions(BukkitAdapter.asBlockVector(location)); boolean isInSafeZone = false; // 先遍历确认是否处于安全区 for (ProtectedRegion r : set) { if (r.getId().equals("safezone")) { isInSafeZone = true; break; // 匹配到安全区后直接跳出循环,减少冗余遍历 } } // 统一执行对应分支逻辑 if (isInSafeZone) { event.setCancelled(true); // 安全区取消伤害事件,符合业务逻辑 player.sendMessage("true"); attacker.sendMessage(ChatColor.RED + "此处不能攻击其他玩家"); } else { attacker.sendMessage(ChatColor.RED + "你现在处于战斗状态,下线会受到惩罚!"); player.sendMessage(ChatColor.RED + "你现在处于战斗状态,下线会受到惩罚!"); } } } }
优化说明
- 补充了伤害来源的类型校验,避免怪物攻击、环境伤害等非玩家伤害场景下抛出
ClassCastException - 安全区逻辑新增事件取消操作,避免安全区内玩家依然受到伤害
- 匹配到安全区后直接终止循环,降低不必要的性能开销
内容的提问来源于stack exchange,提问作者Bas Kruithof
相关产品推荐
相关产品推荐

