Skip to content

Commit

Permalink
Minor fix
Browse files Browse the repository at this point in the history
  • Loading branch information
William-Shi233 committed Oct 22, 2023
1 parent 5edfcd3 commit c024147
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 30 deletions.
47 changes: 18 additions & 29 deletions docs/Volume4/AC-1-4.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

![BUG.png](https://s2.loli.net/2023/07/24/Pkzg2ZbfevIhURj.png)

只要知道了一位玩家下线时所处的坐标,再在该位置建造一个下界传送门,就能让这个账号无法登录。因为依据原版游戏设定,当玩家处于下界传送门方块中时,无法打开聊天窗口。想要执行登录指令,必须离开传送门。又因为玩家没有登录,所以无法移动。这下就形成了死循环,玩家会被卡死在传送门内。
只要知道了一位玩家下线时所处的坐标,再在该位置建造一个下界传送门,就能让这个账号无法登录。因为依据原版游戏设定,当玩家处于下界传送门方块中时,无法打开聊天窗口。想要执行登录指令,就必须离开传送门。但我们的插件又禁止了未登录的玩家移动。这下就形成了死循环,玩家会被卡死在传送门内。

一般的处理方式是,在玩家上线时,将其传送到一个安全的位置,以排除下界传送门的影响。

Expand Down Expand Up @@ -81,7 +81,7 @@ public static void restoreLocation(@Nonnull Player player) {
}
```

`ensureSafety` 方法用广度优先算法来寻找玩家近处的安全位置,然后将玩家传送到那里。如果在 256 次尝试以后仍寻找不到安全位置,就把玩家传送到自身正上方 Y = 512 的地方。由于原版游戏有最大建筑高度限制,这一高度不可能有下界传送门方块存在,故是安全的
`ensureSafety` 方法用广度优先算法来寻找玩家近处的安全位置,然后将玩家传送到那里。如果在 256 次尝试以后仍寻找不到安全位置,就把玩家传送到自身正上方 Y = 512 的地方。由于原版游戏有最大建筑高度限制,这一高度不可能有下界传送门方块存在,是安全的

`restoreLocation` 方法用于将玩家传送回原来的位置,以免登录后从高空坠落或迷路。

Expand Down Expand Up @@ -113,7 +113,7 @@ public void onPlayerJoin(PlayerJoinEvent e) {

IDEA 提供了调试器(Debugger),我们可以用它来调试插件。在调试前,要将调试器附加(Attach)到 Minecraft 服务端的进程上。

首先,要在启动服务端时设置 Java 代理。在 EX-0-2 中,我们用 `java -jar spigot-1.16.5.jar` 命令来开启服务端。现在要改成这样:
首先,要在启动服务端时设置 Java 代理。之前,我们用 `java -jar spigot-1.16.5.jar` 命令来开启服务端。现在要改成这样(记得把 `spigot-1.16.5.jar` 换成你的服务端核心文件名)

```bash
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8342 -jar spigot-1.16.5.jar
Expand All @@ -134,39 +134,27 @@ java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8342 -jar spi

如果你按照上述步骤操作,那么现在 IDEA 就应该进入到调试模式了。

### 添加 NMS 的 Jar 包
### 初识断点

如果你之前没有在依赖中添加过 NMS 的 Jar 包,那么现在需要添加。不然,IDEA 就无法找到 NMS 中的类,你就无法在其上打断点,后续调试会变得很不方便
在代码的左侧、行号的右侧,那一小片空白处点击,会出现一个红色的圆点,这就是断点。执行到断点所在的那一行时,程序会暂停,等待你的调试操作

打开「Project Structure」,在「Libraries」中添加服务端根目录 `versions` 文件夹中的 `.jar` 文件。服务端根目录 `libraries` 文件夹中的文件不一定会被用到,而且数量较多,可以有选择地添加。

注意,我们一般选择 Mojang Mapping 反混淆的服务端来调试,因为它的可读性更好。

::: info <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' transform='scale(0.6)' fill='%23fff'%3E%3Cpath d='M9.1 0C10.2 0 10.7 0.7 10.7 1.6 10.7 2.6 9.8 3.6 8.6 3.6 7.6 3.6 7 3 7 2 7 1.1 7.7 0 9.1 0Z'/%3E%3Cpath d='M5.8 16C5 16 4.4 15.5 5 13.2L5.9 9.1C6.1 8.5 6.1 8.2 5.9 8.2 5.7 8.2 4.6 8.6 3.9 9.1L3.5 8.4C5.6 6.6 7.9 5.6 8.9 5.6 9.8 5.6 9.9 6.6 9.5 8.2L8.4 12.5C8.2 13.2 8.3 13.5 8.5 13.5 8.7 13.5 9.6 13.2 10.4 12.5L10.9 13.2C8.9 15.2 6.7 16 5.8 16Z'/%3E%3C/svg%3E" style="background-color:#0B87DA; clip-path: circle();" width="24px" height="24px"> **注意兼容性**
本节中的部分内容可能不与旧版本(1.16.5 及以下)兼容,请使用 1.17 或更高版本!

对 1.16.5 以及更低版本的服务端而言,NMS 的 Jar 包可能出现在服务端根目录 `caches` 文件夹里。也可能是运行的 Jar 文件自身,比如 `spigot-1.16.5.jar`
:::
打断点,是开发者的基本能力。不仅 Java 程序可以打断点调试,其它很多语言也可以。就插件开发而言,在程序暂停以后,你便接管了整个服务端。你可以让程序恢复正常运转,也可以让程序向下跑一行后暂停。你可以让服务端开始运行一个方法,或强制 `return` 退出当前方法。你可以查看各个变量在暂停那一刻的实际值,还可以输入一段表达式并要求服务端当场计算其结果。总之,打上了断点,服务端就在你的掌握之中。

### 关闭看门狗(WatchDog)线程

看门狗是一个特殊的线程,它时刻检查服务端主线程是否在正常运转。如果主线程卡住了,看门狗会让服务端直接崩溃。

但是断点调试,就是要让线程卡住。为了防止看门狗干扰,我们需要把它关掉。

找到 `org.spigot.WatchdogThread#run` 方法,在 `while` 循环内第一行打个断点。执行到此处时,在 IDEA 调试窗口左侧的栈帧中点击右键,唤出菜单,选择「Force Return」,然后点左边的继续(绿色三角加一竖线)。
但是断点调试,就是要让线程卡住。在这种暂停状态下调试。为了防止看门狗干扰,我们需要把它关掉。

::: info <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' transform='scale(0.6)' fill='%23fff'%3E%3Cpath d='M9.1 0C10.2 0 10.7 0.7 10.7 1.6 10.7 2.6 9.8 3.6 8.6 3.6 7.6 3.6 7 3 7 2 7 1.1 7.7 0 9.1 0Z'/%3E%3Cpath d='M5.8 16C5 16 4.4 15.5 5 13.2L5.9 9.1C6.1 8.5 6.1 8.2 5.9 8.2 5.7 8.2 4.6 8.6 3.9 9.1L3.5 8.4C5.6 6.6 7.9 5.6 8.9 5.6 9.8 5.6 9.9 6.6 9.5 8.2L8.4 12.5C8.2 13.2 8.3 13.5 8.5 13.5 8.7 13.5 9.6 13.2 10.4 12.5L10.9 13.2C8.9 15.2 6.7 16 5.8 16Z'/%3E%3C/svg%3E" style="background-color:#0B87DA; clip-path: circle();" width="24px" height="24px"> **设置断点的方法**
在代码行号的左侧点击,会出现一个红色的圆点,这就是断点。执行到断点处时,程序会暂停执行,等待你的调试操作。
:::
找到 `org.spigotmc.WatchdogThread#run` 方法,在 `while` 循环内第一行打个断点。执行到此处时,在 IDEA 调试窗口左侧的栈帧中点击右键,唤出菜单,选择「Force Return」,然后点左边的继续(绿色三角加一竖线)。

这样看门狗就失去作用了。

### 初识调试界面

![IDEA-DEBUG-SCREEN.png](https://s2.loli.net/2023/07/25/syNQzYV1fD48MRt.png)

如图,代码区域发生了一些变化。蓝色高亮的,是即将被执行的代码行。右侧显示的是一些变量。变量的值,反映程序执行到这一行时的情况
如图,在调试模式下,代码区域不同以往。蓝色高亮的,是即将被执行的代码行。该行的右侧显示了一些变量。变量的值,反映此刻程序执行到这一行时的情况

底部是调试器区域,下面内容均介绍此区域。

Expand Down Expand Up @@ -212,7 +200,7 @@ java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8342 -jar spi
很快,程序执行到了 `solution = loc`,观察底部变量显示可知,找到的这个解是正确的,它向 X 轴正方向移动了一格。

::: info <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' transform='scale(0.6)' fill='%23fff'%3E%3Cpath d='M9.1 0C10.2 0 10.7 0.7 10.7 1.6 10.7 2.6 9.8 3.6 8.6 3.6 7.6 3.6 7 3 7 2 7 1.1 7.7 0 9.1 0Z'/%3E%3Cpath d='M5.8 16C5 16 4.4 15.5 5 13.2L5.9 9.1C6.1 8.5 6.1 8.2 5.9 8.2 5.7 8.2 4.6 8.6 3.9 9.1L3.5 8.4C5.6 6.6 7.9 5.6 8.9 5.6 9.8 5.6 9.9 6.6 9.5 8.2L8.4 12.5C8.2 13.2 8.3 13.5 8.5 13.5 8.7 13.5 9.6 13.2 10.4 12.5L10.9 13.2C8.9 15.2 6.7 16 5.8 16Z'/%3E%3C/svg%3E" style="background-color:#0B87DA; clip-path: circle();" width="24px" height="24px"> **找到了错误的解**
也许你在调试的时候发现,找到的解是错误的。或者该程序错误地认为,玩家站立的位置没有传送门。这两种情况都是正常的,因为代码中的错误不止一个。我们先讨论找到正确解的情况,其它漏洞会在后面调试、修复。如果你不幸地遇到了上述两个漏洞,可以暂停调试,先读本文
也许你在调试的时候发现,找到的解是错误的。或者该程序错误地认为,玩家站立的位置没有传送门。这两种情况都是正常的,因为代码中的错误不止一个。我们先讨论找到正确解的情况,其它漏洞会在后面调试、修复。如果你不幸地遇到了上述两个漏洞,可以暂缓调试,先依本文的思路往下阅读
:::

当运行到函数的末尾时,发现 `solution` 是安全位置,而 `player` 却没有传送到 `solution` 位置上。
Expand Down Expand Up @@ -248,9 +236,10 @@ RuntimeDataManager.addRestrictUUID(player.getUniqueId());
::: info <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' transform='scale(0.6)' fill='%23fff'%3E%3Cpath d='M9.1 0C10.2 0 10.7 0.7 10.7 1.6 10.7 2.6 9.8 3.6 8.6 3.6 7.6 3.6 7 3 7 2 7 1.1 7.7 0 9.1 0Z'/%3E%3Cpath d='M5.8 16C5 16 4.4 15.5 5 13.2L5.9 9.1C6.1 8.5 6.1 8.2 5.9 8.2 5.7 8.2 4.6 8.6 3.9 9.1L3.5 8.4C5.6 6.6 7.9 5.6 8.9 5.6 9.8 5.6 9.9 6.6 9.5 8.2L8.4 12.5C8.2 13.2 8.3 13.5 8.5 13.5 8.7 13.5 9.6 13.2 10.4 12.5L10.9 13.2C8.9 15.2 6.7 16 5.8 16Z'/%3E%3C/svg%3E" style="background-color:#0B87DA; clip-path: circle();" width="24px" height="24px"> **Reload Changed Classes 何时有效**
必须同时满足以下几个条件:

- 不新增 / 删除方法、字段,或者修改其类型。
- 不新增类。
- 修改的类不是需要运行期 ASM 改写才能加载的类。
- 不新增 / 删除类、方法、字段。
- 不修改字段的类型。
- 不修改方法的返回值类型、参数的个数、参数的类型。
- 被修改的类不是需要运行期 ASM 改写才能加载的类。
- 没有修改初始化步骤(例如你在 `onEnable` 中写的内容,必须重启服务器才能调用到,IDEA 的调试操作重新加载类没有用)。
:::

Expand All @@ -266,7 +255,7 @@ RuntimeDataManager.addRestrictUUID(player.getUniqueId());

又发现 `player.getLocation().clone().add(1, 0, 1).getBlock().getType()` 返回 `NETHER_PORTAL`,说明玩家站立在传送门旁边。

所以,我们要判断的不是玩家所在位置(脚部的中心,一个一维的点)是否处于传送门中,而是玩家的长方体碰撞箱有没有碰到传送门。通俗地说,玩家脚部的中心也许没碰到传送门,但是玩家的脚尖可能碰到了传送门。这时候,玩家仍然打不开聊天栏。
`Player#getLocation` 方法的返回值,是玩家脚部的中心。当玩家站在传送门的边缘时,玩家脚部中心没碰到传送门。但是玩家的脚尖碰到了传送门。这时候,玩家仍然打不开聊天栏。所以,我们要判断的不是 `player.getLocation()` 是否处于传送门中,而是玩家的长方体碰撞箱有没有碰到传送门

经过一番思考,编者决定把代码改成下面这样:

Expand Down Expand Up @@ -352,7 +341,7 @@ public static void restoreLocation(@Nonnull Player player) {
}
```

Reload Changed Classes?不,我们需要重启服务端。
Reload Changed Classes?不,`isSafe` 方法的参数有变化。我们需要重启服务端。

再次 Build Artifact,把构建产物扔进 `plugins` 文件夹,启动服务端。

Expand All @@ -362,7 +351,7 @@ Reload Changed Classes?不,我们需要重启服务端。
因为我们给 `isSafe` 方法增加了一个 `Player` 类型的参数,改变了方法的类型。这种情况下,Reload Changed Classes 是无效的。
:::

### 拓展知识:断点
### 其它种类的断点

IDEA 提供了多种类型的断点,除了上面使用过的行号断点,常见的还有以下三种:

Expand Down Expand Up @@ -403,7 +392,7 @@ HarmonyAuth SMART 有一套命令白名单系统,防止未登录的玩家随

就这么多了。也许还有更多的漏洞等待读者去发现。

本插件还有许多奇怪的问题,比如未登录的玩家无法受到伤害,却能吸引怪物的火力,甚至能打怪。于是玩家可以轻易进入无敌状态。另外,玩家在载具上或者在空中登录时,插件发来的警告会刷屏。玩家在未登录时也可以聊天……受篇幅所限就不再修改了。
本插件还有许多奇怪的问题,比如未登录的玩家无法受到伤害,却能吸引怪物的火力,甚至能打怪。另外,玩家在载具上或者在空中登录时,插件发来的警告会刷屏。玩家在未登录时也可以聊天……受篇幅所限就不再修改了。

有些项目没来得及测试,例如登录时取消已经创建的请求,重新创建请求时自动覆盖。当然,笔者事后测试成功了(查数据库可知)。至于钩子能否运行……既然配置空命令也没出错,我们就权且相信它可以正常运行吧——开玩笑的,笔者测试过没有问题的啦~

Expand Down
2 changes: 1 addition & 1 deletion docs/Volume9/END-8-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
- ……

::: tip <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1028 1024' transform='scale(0.6)' fill='%23fff'%3E%3Cpath d='M1018.319924 112.117535q4.093748 9.210934 6.652341 21.492179t2.558593 25.585928-5.117186 26.609365-16.374994 25.585928q-12.281245 12.281245-22.003898 21.492179t-16.886712 16.374994q-8.187497 8.187497-15.351557 14.32812l-191.382739-191.382739q12.281245-11.257808 29.167958-27.121083t28.144521-25.074209q14.32812-11.257808 29.679676-15.863275t30.191395-4.093748 28.656239 4.605467 24.050772 9.210934q21.492179 11.257808 47.589826 39.402329t40.425766 58.847634zM221.062416 611.554845q6.140623-6.140623 28.656239-29.167958t56.289041-56.80076l74.710909-74.710909 82.898406-82.898406 220.038979-220.038979 191.382739 192.406177-220.038979 220.038979-81.874969 82.898406q-40.937484 39.914047-73.687472 73.175753t-54.242167 54.753885-25.585928 24.562491q-10.234371 9.210934-23.539054 19.445305t-27.632802 16.374994q-14.32812 7.16406-41.960921 17.398431t-57.824197 19.957024-57.312478 16.886712-40.425766 9.210934q-27.632802 3.070311-36.843736-8.187497t-5.117186-37.867173q2.046874-14.32812 9.722653-41.449203t16.374994-56.289041 16.886712-53.730448 13.304682-33.773425q6.140623-14.32812 13.816401-26.097646t22.003898-26.097646z'/%3E%3C/svg%3E" style="background-color:#057E3D; clip-path: circle();" width="24px" height="24px"> **编者注**
ThatRarityEG 道席推荐的 Bukkit 插件开发人员站点是 dev.bukkit.org。但是随着 CraftBukkit 被 DMCA Takedown 取缔,该网站也日渐没落。目前最大的插件开发交流社区是 [Spigot 论坛](https://www.spigotmc.org/forums/spigot-plugin-development.52/)但小马只言旧站点而不言新站点,是提醒读者饮水思源,椎轮为大辂之始也。
ThatRarityEG 道席推荐的 Bukkit 插件开发人员站点是 dev.bukkit.org。但是随着 CraftBukkit 被 DMCA Takedown 取缔,该网站也日渐没落。目前最大的插件开发交流社区是 [Spigot 论坛](https://www.spigotmc.org/forums/spigot-plugin-development.52/)只言旧站点而不言新站点,是小马提醒读者饮水思源、不忘初心。盖闻「椎轮为大辂之始」,良有以也。如果不是 CraftBukkit 打下了基础,又怎么会有今天的 Spigot、Paper 等服务端呢?
:::

## 自由软件
Expand Down

0 comments on commit c024147

Please sign in to comment.