Bukkit插件教程篇之处理报错

开始

对于一个程序员来说,程序出错是常有的事,码字五分钟,纠错两小时~

**↑不来一首BGM吗?**

本章要求

  • 学会看报错信息
  • 学会解决问题

插件报错信息

当我兴高采烈地去测试上一章节我写的插件时,却发现:我右键放置方块事件并没有被阻止!
直觉告诉我:我的插件出bug了!
好在控制台输出了报错信息……(很多情况下一些令人头疼的bug并不会在后台输出报错信息,不过这里是由于异常而引起的漏洞,所以在后台会有输出
让我们先喝口水,冷静下来,开始分析错误。
先上控制台错误信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[19:45:38 ERROR]: Could not pass event BlockPlaceEvent to TeachingPlugin v1.0
org.bukkit.event.EventException
at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:306) ~[spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:502) [spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:487) [spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at org.bukkit.craftbukkit.v1_11_R1.event.CraftEventFactory.callBlockPlaceEvent(CraftEventFactory.java:149) [spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at net.minecraft.server.v1_11_R1.ItemStack.placeItem(ItemStack.java:201) [spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at net.minecraft.server.v1_11_R1.PlayerInteractManager.a(PlayerInteractManager.java:495) [spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at net.minecraft.server.v1_11_R1.PlayerConnection.a(PlayerConnection.java:913) [spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at net.minecraft.server.v1_11_R1.PacketPlayInUseItem.a(PacketPlayInUseItem.java:37) [spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at net.minecraft.server.v1_11_R1.PacketPlayInUseItem.a(PacketPlayInUseItem.java:1) [spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at net.minecraft.server.v1_11_R1.PlayerConnectionUtils$1.run(SourceFile:13) [spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_131]
at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_131]
at net.minecraft.server.v1_11_R1.SystemUtils.a(SourceFile:46) [spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at net.minecraft.server.v1_11_R1.MinecraftServer.D(MinecraftServer.java:747) [spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at net.minecraft.server.v1_11_R1.DedicatedServer.D(DedicatedServer.java:399) [spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at net.minecraft.server.v1_11_R1.MinecraftServer.C(MinecraftServer.java:678) [spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at net.minecraft.server.v1_11_R1.MinecraftServer.run(MinecraftServer.java:576) [spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at java.lang.Thread.run(Unknown Source) [?:1.8.0_131]
Caused by: java.lang.IllegalArgumentException: Health must be between 0 and 20.0(21.0)
at org.bukkit.craftbukkit.v1_11_R1.entity.CraftLivingEntity.setHealth(CraftLivingEntity.java:99) ~[spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
at cn.viosin.minecraft.Listener.BlockPlaceListener.BlockPlaceHandler(BlockPlaceListener.java:13) ~[?:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_131]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_131]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_131]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_131]
at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:302) ~[spigot-1.11.2.jar:git-Spigot-3fb9445-6e3cec8]
... 18 more

我们需要找出其中的关键信息:

  • 抛出的异常类型
  • 抛错原因
  • 错误代码所在位置

根据我们的报错信息,找到了对应位置:
第2行:org.bukkit.event.EventException
解释:抛出了一个EventException(不知道EventException的同学请去查看bukkitdoc)
第22行:Caused by: java.lang.IllegalArgumentException: Health must be between 0 and 20.0(21.0)
错误原因:抛出了一个IllegalArgumentException:生命值必须在020.0之间
第23
29行中写出了出错的代码,我们这里只看我们的代码:
at cn.viosin.minecraft.Listener.BlockPlaceListener.BlockPlaceHandler(BlockPlaceListener.java:13) ~[?:?]
解释:BlockPlaceListener.java中的第13行出错了!

找到问题

根据上一小节中报错中的关键信息,我们知道我们的BlockPlaceListener.java中的代码出了点小毛病!而且它准确的告诉了你出错的代码在第13行!马上去看看怎么回事!

BlockPlaceListener.java中第十三行代码为p.setHealth(++health);,注释上写着:让该玩家的生命值 + 1
再看看出错原因,不难想到为什么了:我们的玩家生命值已是满的,但是我却仍让它+1,于是就报错了!

解决问题

知道了错误原因,解决问题也就不难了,我们只需要看这个玩家的生命值是否等于玩家的最大生命值就行了。
在这一行代码上面加上if(health < player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue())就行了。
这样当我们玩家当前生命值小于玩家最大生命值时,下面那一段代码才会执行。

本章完

点我返回目录

感谢各位的阅读!

人生不易,仓鼠断气