跳到主要内容

幕间 • 服务端那些事

欢迎来到幕间栏目!在这里我们会讲述一些插件开发的奇闻轶事。啊,放心放心,我们不需要编写任何代码的。

今天的故事是有关 Minecraft 服务端的演化历史,我们将主要介绍 Bukkit 及其衍生项目这边的时间线,但也会穿插一点 Sponge 和 Forge 相关方面的事件作为参照。

宇宙起源:ModLoader 和 hMod

在最早的时候(多人游戏刚刚提出的那段时间),服务器使用的是 Mojang 官方提供的服务端。原版的服务端称不上性能优良,扩展性更是无从夸赞。那时客户端上的模组已经初具雏形,一位叫做 Risugami 的玩家开发了 ModLoader,它能从 .class 文件(Java 代码编译后的产物)中加载模组,结束了使用 MCP 暴力修改客户端源代码的时代。

在多人游戏提出之后,自然就有人想要将 ModLoader 移植到服务器上,这项工作的成果就是 MPModLoader:只要在服务器和客户端的 .jar 文件中都塞入模组的 .class 文件,就能在多人游戏中使用模组了!

……嗯,好吧,这种做法听上去不怎么靠谱,而且事实上也是如此,尽管 ModLoader 理论上可以支持多人游戏,但要知道那是 2009 年,互联网还只是刚刚起步的阶段,人们普遍使用的浏览器还是 IE9,Windows 7 才刚刚发布,而 Java 7 还要两年才能问世,可用的逆向工程和其它开发技术也非常有限,因此大多数模组能在单人游戏中运行都算烧高香了,真正能在多人游戏中畅玩的模组屈指可数。

同一时期,一个叫做 hMod 的模组被发明出来,与其它模组不同的是,hMod 仅修改服务器,并且提供了与 Minecraft 版本无关的一套 API 供开发者使用。hMod 也是第一个能加载真正意义上的插件的服务端。虽然 hMod 的开发周期仅有短短的几个月,但它在 Minecraft 服务端的桎梏上打开了一道口子,让人们第一次认识到,原来仅靠服务端也能做到这么多事情。

史前时代:Bukkit 和 CraftBukkit

2010 年 9 月,一些参与维护 hMod 的开发者正式决定启动一个叫做 Bukkit 的新项目,在玩家社区内大名鼎鼎的 Dinnerbone 也是开发人员之一。那时的人们还不知道自己在创造历史,不知道在 2011 年 Bukkit 会以怎样的速度发展起来,更不可能知道在未来的 15 年里(或许再过十年仍是如此),Bukkit 会成为 Minecraft 服务端生态的典范之作。

严格来说,Bukkit 只是一套接口的名字,它定义了诸如 Player.sendMessage 这些方法的功能应该是什么,但 Bukkit 本身不实现这些功能,与 Bukkit 同时期创建的 CraftBukkit 项目是一个真正意义上的服务端,它完整地实现了 Bukkit API,允许任何插件通过这一套统一的接口与服务端交互。这是插件开发史上最有纪念意义的里程碑。

在整个 2011 年,Bukkit 取得了飞跃式的发展,插件社区许多奠基项目被陆续开发出来,包括至今仍在使用的 MultiVerse(多世界管理),现代服务器权限管理的前身 Permissions 等,即使在今天的许多插件中也能看到这些先驱者的身影。

2011 年末,著名的 Forge 诞生了,与插件的目的不同,Forge 将工作重心放在了客户端和服务端的协调上,希望能让模组更容易地在多人游戏中运行。尽管继任 Forge 开发的 LexManos 是个 不折不扣的小人,但不可否认,Forge 项目本身仍然是一个伟大的成果,在未来的十年内(直至 Minecraft 1.14 时 Fabric 的发布)都是模组社区毫无争议的代表。

历史风云:Spigot、Paper 和 Sponge

2013 年初,为了进一步改善性能和扩展服务端的功能,CraftBukkit 项目的一个分支 CraftBukkit-- 由 md_5 接续开发,并更名为 Spigot。Spigot 同样完整支持 Bukkit API,但在很多方面都比 Bukkit 更加优秀,许多插件开发者也是从这时起转向 Spigot,而一些仍然留在传统的 Bukkit 项目中。

一年后,2014 年 6 月,基于 Spigot 开发的 Paper 诞生了,Paper 致力于在与 Spigot 同等强大的同时,还拥有远超 Spigot 的性能 —— 这是他们的设想,并且很大程度上他们也做到了。Paper 从这时起开始与 Spigot 分道扬镳,各自精彩。

2014 年末,Bukkit 项目正式终止,原因主要是 Bukkit 使用了 Mojang 的源代码,这有侵犯著作权之嫌。我们猜测这一决定很可能是 Microsoft 收购 Mojang 带来的影响,但我们没有实质性的证据。Bukkit 项目终止的一个月后,Bukkit、CraftBukkit 和 Spigot 的源代码因违反 DMCA 而被从 GitHub 上移除。自此,直接修改 Minecraft 源代码的时代也就宣告落幕了。

共同的损失,让我们更加团结一致!虽然 Bukkit 项目终止了,但继续探索服务端插件的工作不会停下。在 CraftBukkit 的源代码被删除的仅仅两天后,基于 Forge 的 Sponge 诞生了。与 Bukkit 不同,Sponge 计划重新设计一套新的 API 供插件使用,而且能与模组兼容。Sponge 调研了很多插件的需求,并迅速提出了一个堪称完美的 API。

也许 Sponge 差点就取代 Spigot 成为龙头老大了,也许这是我们离那个模组与插件和谐相处的分枝最近的时候,不过更换 API 可不是说说就行,需要有人来实现这些功能。Sponge 在开发真正可用的服务端方面有些落后,而在两个月后,Spigot 又一次推出了新版本,标志着它重回正轨。

现代发展:Fabric 和 NeoForged

2015 至 2017 年是平淡的三年,Spigot 仍然保持着社区的活跃,Sponge 独树一帜努力进行着更新,Paper 依旧在优化性能的道路上。越来越多的现代插件被开发出来,例如 LuckPerms、EssentialsX 等,但总的来说,在服务端技术上并没有进一步的突破。

这样的情况直到 2018 年,Minecraft 1.13 发布,才被打破。Mojang 大幅修改了游戏内部许多数据的表示,这导致 Forge 一时间跟不上如此巨大的发展,因而催生了 Rift 和 Fabric。凭借着轻量化的 API 以及模组与加载器分离技术,Fabric 很快就被投入到模组服务端的应用上,并且逐渐取代 Forge,无论是在客户端还是服务端都一直流行至今。

2023 年,Forge 的核心开发者之一 cpw 宣布正式抛弃 Forge 项目,并带着大多数开发人员和代码另行开启 NeoForged 项目。这主要是 Forge 团队的大多数人无法再继续忍受 LexManos 创造的各种麻烦了。NeoForged 很快提出了新版本,并且在客户端上表现良好,我们期待着有更多的项目能将它应用在各种类型的服务端上。

未来将至:统一的设想

Sponge 希望将插件和模组融合的想法最终由于缺乏生态而落空了 —— 时至今日,尽管 Sponge 已经拥有了相当一批高质量的插件,但与广泛应用的 Bukkit 插件生态相比还有很大的差距。然而,想要将模组和插件同时安装在服务器上的探索一直没有停歇。MCPC+(后更名为 Mohist)、CatServer、Arclight 等支持模组和插件的服务端被陆续开发出来,并且也在一定程度上得到了应用。

遗憾的是,由于模组和插件都非常灵活,而二者的 API 又有很大的差距,因此要让它们稳定地运行是一件非常困难的事情。上述的这些服务端,在模组和插件的数量增加时很容易出错甚至崩溃。由于 Bukkit 从来没想过支持模组,而 Forge 亦视 Bukkit 如大敌(某种程度上也与 Sponge 有些关联),因此尽管现在仍有很多开发者致力于将模组与插件统一起来,但随着 Minecraft 版本的不断更新,这些尝试的结果如何还是个未知数。

Fabric 的提出也给了插件社区一些新的思路,因为 Fabric 的结构不像 Forge 那么复杂,也许有种办法能将它与 Bukkit 结合起来。然而,许多 Fabric 模组高度依赖 Mixin(一种修改 Minecraft 源代码的技术),因此融合 Fabric 和 Bukkit 的过程也艰难无比。尽管人们已经取得了像 Banner 和 Cardboard 这样的成果,但总体来说,至今为止,让模组和插件共存的这一设想,仍然没有在功能、性能和游戏版本上都令人满意的答案。

应该说,这样的结果是有些令人沮丧的,不过笔者在这里想告诉各位,我们的所有工作总是受现在的开发条件所限,但没有理由认为这种限制是不能打破的。现在是 2025 年,低成本的大语言模型 AI 正在迅速普及,使得阅读和更改大批量的史山代码成为可能。也许在不久的将来,我们能探索出一种修改或重构 Bukkit 代码的方式,能让模组和插件更好地结合在一起,或者,有人能提出一组更好的 API,并且能将已有的插件快速地迁移过来。我们相信事在人为,并且绝不放弃前进的脚步。