You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Bukkit插件中于ArrayList移除玩家时触发重新启用摔落伤害的逻辑

实现方案

第一步:修复列表作用域问题

你当前把nofalldmg定义在命令执行方法内部,每次触发命令都会创建新的空列表,之前存储的玩家数据会完全丢失,需要把它改成插件主类的全局成员,建议用HashSet替代ArrayList,查询/删除效率更高:

// 放在你的插件主类中,作为全局静态变量
public static HashSet<Player> noFallDmgImmune = new HashSet<>();

第二步:注册摔落伤害拦截监听器

在主类onEnable方法中注册事件监听器,逻辑为:只要玩家在免疫列表内,就取消摔落伤害事件:

@EventHandler
public void onPlayerFallDamage(EntityDamageEvent event) {
    // 仅处理摔落伤害、且受伤害对象为玩家的场景
    if (event.getCause() != EntityDamageEvent.DamageCause.FALL || !(event.getEntity() instanceof Player)) {
        return;
    }
    Player player = (Player) event.getEntity();
    if (你的主类名.noFallDmgImmune.contains(player)) {
        event.setCancelled(true);
    }
}

第三步:调整延迟任务逻辑

只要玩家被移出免疫列表,监听器就不会再拦截他的摔落伤害,自动恢复默认逻辑。如果需要避免移除瞬间玩家因为之前累计的掉落高度掉血,可以额外清理掉落距离:

// 你原有的命令逻辑调整后
Player p = (Player) sender;
if (p.hasPermission("custome.fly")) {
    if (p.isFlying()) {
        p.setAllowFlight(false);
        p.setFlying(false);
        你的主类名.noFallDmgImmune.add(p);
        Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
            @Override
            public void run() {
                你的主类名.noFallDmgImmune.remove(p);
                // 清理累计掉落距离,避免移除瞬间掉血
                p.setFallDistance(0);
            }
        }, 60);
    }
}

补充优化建议

  • 加一个玩家退出事件的监听器,玩家下线时自动从免疫列表移除,避免内存泄漏
  • 如果你使用的是1.17+版本的Spigot API,可以直接调用p.setFallDamageImmuneTicks(60),不需要自己维护免疫列表,逻辑更简洁

内容的提问来源于stack exchange,提问作者Zavage

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 18:48:00