关于我写了个Minecraft基岩版服务端这件事(一):动机与目标

Fri, November 4, 2022 - 8 min read

这虽然是游戏,但可不是闹着玩的!
—— 茅场晶彦

引子

作为一款高自由度的沙盒游戏,Minecraft是一代人的童年,也是一群人进入计算机和编程领域的入门阶梯。我就是其中的一员。

由于入坑比较早,还有点折腾服务器的经验,我偶尔会在一些服务器出任技术。近两年也有幸在一些基岩版服务器的技术小组里回答问题,甚至还差点亲自下场,帮忙写插件。

Minecraft有Java版和基岩版两个版本。基岩版由于使用C++编写,给它编写mod,修改代码行为是十分困难的。所以一些追求创新玩法(尤其是开小游戏)的服务器会使用从头编写的开源第三方服务端,例如基于Java的Nukkit系服务端。但很不幸,Nukkit系服务端的代码质量实在是一言难尽,开发运维体验更是令人汗颜。

看着这群人拿着自己本来就不多的时间,去千辛万苦地和这滩屎山战斗,去每次修改都要手动打包换jar,去盯着TPS抓耳挠腮;再看看隔壁现代前端的开发体验,现代后端的运维体系,我不禁开始沉思:难道MC服务端没有更好的架构了吗?难道MC的开发运维体验一定要如此落后?

诸君,我有一个大胆的想法!

目标定义

首先,要让某样东西变得更好,我们就需要知道好长啥样。我们要改良架构和开发运维体验,就必须定义什么是好的架构和体验。

架构质量

架构指系统的总体设计,具体来说就是把系统划分为哪些部分,各个部分应该承担怎样的职责和功能,以及部分之间如何交互。

好的架构是个极难定义的东西,要是摊开来讲写一本书绰绰有余。所以我们缩窄范围,重点考虑架构在控制复杂度和变化影响上的作用。

从这两点出发,好的架构设计应当:

  • 把一个复杂系统拆解为少量简单正交且容易理解的部分
  • 把不同的变化原因拆分给不同的模块

此外,作为一个会被拿来二次开发的软件,这个架构应当拥有相当程度的可扩展性。

开发体验

接下来,什么是好的开发运维体验呢?

让我们先从开发者这边入手。

要讨论开发者体验,我们不妨先考虑开发者在写插件的时候,从头到尾要干些啥:

  • (搭建环境)要写插件,我们首先要把开发环境拉起来,让我们的代码跑起来
  • (理解行为)插件本质上是在改变游戏的行为,所以我们必须理解游戏当前的行为是怎样的
  • (修改行为)我们写点代码,修改游戏的行为,然后再看看我们想要的效果有没有达到,如果没有,就分析原因再改
  • (固化行为)在实现了想要的效果后,我们就用某种工具将其固定下来(一般是测试),让某些行为一定会发生。
  • (打包发布)最后,我们要把修改打包起来发布出去

要达成好的开发体验,就必须降低每一步的难度和耗时,尤其是要缩短从修改行为到看到新行为的耗时。

后面这点也是现代前端开发体验优秀的原因——改完马上就能看到效果。

为了降低难度和耗时,就需要做到这些:

  • (搭建环境)开发环境必须易于搭建,理想情况下应该有一个开箱即用的模板项目
  • (理解行为)我们需要易于理解的架构,简明但完善的文档,同时提供工具来方便快捷地查看游戏世界当前的状态,以便理解行为
  • (修改行为)我们需要简单,快速,可靠的热重启甚至热重载
  • (固化行为)测试必须易于编写,运行快速
  • (打包发布)打包发布最好简单明了,一键完成

运维体验

接下来就是运维体验,站在服务器技术的角度,大概需要做:

  • (架设服务器)把服务器拉起来
  • (获取与安装插件)下载安装现有的插件,或者自己开发新的插件
  • (排查故障)出了问题(服务器崩溃/运行缓慢等)需要诊断是哪里的问题,然后进行处理
  • (更新版本)如果服务端出了新版本,就要考虑如何升版本

要让这些任务更加容易,我们可以:

  • (架设服务器)简化架设服务端的操作流程,最好下下来一个文件,打开就完事
  • (获取与安装插件)改善插件安装与开发体验;同时想办法建设生态,让我们的服务端有大量插件可用(老实讲这是最难的¯\_(ツ)_/¯)
  • (排查故障)提升系统的可观测性(日志,指标等),提供性能分析和debug工具
  • (更新版本)尽可能让版本更新安全平滑

小结

好了,在这篇文章里,我吐槽了现行Minecraft基岩版服务端的开发运维体验,同时定义了好的体验以及如何达成它们。

既然你有这么多意见,你行你上啊!

好,我行,我上!