You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

为何我的Spigot插件在玩家击杀玩家时无法处理PlayerDeathEvent

解决Spigot插件PlayerDeathEvent空指针异常问题

你遇到的核心问题是PlayerDeathEvent处理时的NullPointerException,控制台已经明确指出错误出在JoinMessage.java:54,咱们一步步拆解修复:

1. 直接触发空指针的核心错误

看你onPlayerDeath方法里这段代码:

PlayerDeathEvent deathe = null;
deathe.setDeathMessage(null);

你把deathe赋值为null后立刻调用它的方法,这必然会抛出空指针异常!其实完全不需要新建PlayerDeathEvent对象,直接用方法参数里的e就可以修改死亡消息。

2. 隐藏的配置键名大小写问题

你的config.yml里写的是firstJoin_message(J大写),但代码里调用的是firstjoin_message(j小写),这会导致首次加入服务器的玩家无法读取到正确的配置消息,会显示null,这个细节必须修正。

3. 自杀场景的逻辑补全

当玩家自杀时,e.getEntity().getKiller()会返回null,所以你现有代码里killer == p的判断永远不会成立,需要调整逻辑来识别自杀场景。


修正后的完整代码

JoinMessage.java 修正版

package JoinMessage;

import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import Utilities.utility;
import me.GraczBezNicku.Introduction.Main;

public class JoinMessage implements Listener {
    private static Main plugin;

    public JoinMessage(Main plugin) {
        this.plugin = plugin;
        Bukkit.getPluginManager().registerEvents(this, plugin);
    }

    @EventHandler
    public void onJoin(PlayerJoinEvent e) {
        Player p = e.getPlayer();
        if(!p.hasPlayedBefore()) {
            // 修正配置键名的大小写问题
            Bukkit.broadcastMessage(utility.chat(plugin.getConfig().getString("firstJoin_message").replace("<player>", p.getName())));
        } else {
            Bukkit.broadcastMessage(utility.chat(plugin.getConfig().getString("join_message").replace("<player>", p.getName())));
        }
    }

    @EventHandler
    public void onExit(PlayerQuitEvent e) {
        Player p = e.getPlayer();
        Bukkit.broadcastMessage(utility.chat(plugin.getConfig().getString("leave_message").replace("<player>", p.getName())));
    }

    @EventHandler
    public void onPlayerDeath(PlayerDeathEvent e) {
        // 先取消默认死亡消息,避免重复显示
        e.setDeathMessage(null);
        Player p = e.getEntity();
        Player killer = e.getEntity().getKiller();

        if(killer instanceof Player) {
            if(p != killer) {
                killer.sendMessage(utility.chat("You have killed &7" + p.getDisplayName() + "!"));
                p.sendMessage(utility.chat("You have been killed by &7" + killer.getDisplayName()+ "!"));
                Bukkit.broadcastMessage(utility.chat("&7" + p.getDisplayName() + " was killed by &7" + killer.getDisplayName()));
            }
        } else {
            // 通过死亡消息判断是否为自杀场景(也可以用DamageCause更精准判断)
            boolean isSuicide = e.getDeathMessage() != null && 
                (e.getDeathMessage().contains("fell out of the world") 
                || e.getDeathMessage().contains("blew up")
                || e.getDeathMessage().contains("starved to death"));
            
            if(isSuicide) {
                Bukkit.broadcastMessage(utility.chat("&7" + p.getDisplayName() + " killed himself!"));
            } else {
                Bukkit.broadcastMessage(utility.chat("&7" + p.getDisplayName() + " has died."));
            }
        }
    }
}

额外优化建议

  • 如果需要更精准的自杀判断,可以结合DamageCause
    if(p.getLastDamageCause() != null && p.getLastDamageCause().getCause() == org.bukkit.event.entity.EntityDamageEvent.DamageCause.SUICIDE) {
        // 处理自杀逻辑
    }
    
  • 重启服务器时记得重新加载插件,确保配置文件的修改生效
  • 确认utility类的包导入路径正确,避免类找不到的问题

这样修改后,玩家击杀玩家的场景不会再抛出空指针异常,首次加入的消息能正确读取配置,自杀场景也能正常识别处理了。

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

火山引擎 最新活动