为何我的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




