Conic Launcher 是一个我已经开发三年半的 Minecraft 启动器项目。经历了漫长的开发过程,它的第一个 Alpha 版本终于发布了。
项目位于 conic-apps/launcher ,截止到文章发布,官方网站还没有做。
本项目的亮点已经在项目的 README 中介绍了,这里不再重复,对本项目不了解的话可以先前往项目主页阅读一下 README。本文并非常见的产品发布广告,而是借此机会谈谈它的开发历程和有趣的设计,因此会更偏向“讲故事”。如果你对这些内容不感兴趣,你也可以直接前往 GitHub Release 页面下载体验它。
开发历程
起初我只是闲着没事干,想快速做个能用的启动器,对质量和体积不是特别在意,于是直接使用 Electron 作为框架。项目创建初期,我几乎没有任何经验,只是略微会写一点 JavaScript,因此当时最开始写的前端代码全都是原生 JavaScript + jQuery ,页面的组件切换全部是用 jQuery 操作元素类名实现的。安装游戏等流程则是直接使用现成的库。不得不说 JavaScript 生态真的很全,什么奇怪的东西都有人做。
不久之后,我注意到了 Vue,不禁感叹,“哇,这也太方便了吧。”于是 UI 开始转向 Vue 。使用 Vue 的过程也不是一帆风顺的。最开始用 Vue 的时候,我只看了网上的老旧过时教程,于是直接 script 标签全局引入 Vue,然后拿字符串写 DOM。后来看了 Vue 的官方文档,发现 Vue 的正确使用方式应该是用单文件组件才对,于是又重构了一次。慢慢地,UI 部分就实现了最基本的功能。
到这里,我开始更关注项目的质量,于是 Electron 就不再能满足需求了,毕竟仅仅为了启动 Minecraft 就往用户电脑上多装一个浏览器,这种做法实在不能接受。这时,我注意到了 Tauri,发现它简直完美符合我的需求。首先它迁移简单,因为除了 UI 我几乎还啥也没写,基本上全是调用现有的接口。其次,当时 Tauri 还比较新,真把它用到正式项目中的人并不多,于是我决定体验一下。
迁移现有代码并不难,但核心代码都要自己用 Rust 写。反正也是闲着没事干,就稍微学了学就尝试上手了。从此往后,后端就改用 Rust 了,在构建整个核心代码的过程中,我先后知道了 Rust 中的 future,更加深入地理解了 trait 等概念,也逐渐接触到计算机更底层的知识。
在项目开发过程中,后端的结构也经历过很多变动。有一段时间,我打算将后端部分,比如游戏安装、启动等逻辑放到单独的 crate 中,以便别人都能更简单地用 Rust 实现自己的启动器。但后来我发现这会难以维护,于是就又合并回去了。
再后来,项目有了更多的功能,Tauri command 也越来越多,为了解决此问题,我参考 Tauri 的一个 Discussion,将后端拆成多个 Inline Plugin,这样就整洁很多了,前端调用 Tauri 命令也不怕输错了。具体过程可以看我上一篇文章。
一些有趣的功能
起因是想实现基本的存档属性编辑,但看到 HMCL 已经出了此功能,于是为了做得更高级,干脆更进一步,直接做成存档预览功能。
这个特性从项目最开始就是这样。起因是看到b站上居然有人对比启动器安装游戏的速度,我感到十分好笑。但转念一想,如果把安装推迟,不在创建实例时安装,那不就等于立刻安装完游戏了吗?(笑)不过其实官方启动器也是这个流程,把下载游戏和启动游戏合并为一个「开始游戏」按钮。
加入这个功能,一开始是因为我感觉标题栏空荡荡的,想加点什么,于是像 Visual Studio Code 那样放了个搜索框。本身这个组件只是还没想好用来占位的,后来我注意到了 Raycast,决定在启动器里做个丐版的,以便用户可以使用键盘快速完成基本操作。后续可能我真的会推出 Raycast 插件,这样启动游戏就不需要先打开启动器了,直接按快捷键打开 Raycast 就行了。
有一天刷 bilibili 的时候看到一条评论,说比较喜欢 MultiMC 的实例分组展示功能,于是本项目也实现了分组显示。不过目前 Alpha 1 暂不支持自定义分组,因为做完分组显示之后拖延症犯了(咕咕咕~)。
咦,有的地方怎么这么像 osu! 呢?
没错,you are absolutely right! 你的直觉很敏锐!
这里要特别感谢 osu! 在我发愁 UI 设计时给了我巨大的灵感,不过且听我辩解!
目前很多不那么知名的启动器的 UI 布局都是左边放个侧边栏,右边放一堆页面。为了不让自己的项目死得太快,我就只能在外观上费心思了。于是在胡思乱想了很长时间后,决定干脆砍掉侧边栏吧,这样可以给页面布局带来更高的自由度。于是,主页变成了这个样子:

但这样的主页看久了会感觉很简陋。在这时,我开始关注 osu!,果然要说有特色的 UI,还得是游戏里的 UI。很多音游的选歌界面都有一个长长的列表,而 osu! 的谱面列表的弯曲效果一下子吸引住了我。于是我就给主页右侧装了个“实例列表”,并复刻了弯曲的滚动效果。
最开始的实现思路是让浏览器原生滚动控制纵向滚动,通过事件侦听器给卡片按照公式添加横向的 transform 样式。但显然这种拿横向位移去追纵向滚动的做法是失败的——横向的位移永远慢一步,因为浏览器肯定会优先处理原生的滚动操作
后来我发现了 lenis.js,它的滚动效果相当丝滑。加上以后,由于横向位移与纵向滚动全部由 JavaScript 处理,这次就同步了。
随着项目的进一步开发,我发现 osu! 的设计有很多可以学习的点,于是就在更多地方也使用了与它相似的设计风格。这里可以和纠结 UI 的读者提个醒:如果你追求有特色的 UI,不妨去看看游戏中的 UI 设计,它们往往能给你带来不一样的灵感。
未来或许会实现的功能(不知道要咕咕到什么时候)
工具箱
集成附魔计算器、种子地图等花里胡哨的功能,把玩 Minecraft 需要用到的工具直接递到手边
插件系统?
这个功能具有很低的优先级。原因有很多:首先,我没有精力运营一个官方的插件仓库,因为这涉及社区治理,需要考虑如何防范有害插件。其次,这需要启动器封装一套权限清晰的接口,以便用户能够放心使用陌生插件。由于项目还处于前期阶段,现在难以提供稳定的 API,过早实现此功能也会给未来埋下兼容性顾虑。待项目成熟后,此功能将会被重新考虑
永远不会实现的功能
尽管启动器会包含修改配色方案的功能,但大幅魔改 UI,比如移动组件位置、随意更改文本之类的功能永远不会实现。如果我们把一切都做成可配置的选项,等于放弃了设计责任,把决策负担推给用户。
测试反馈
目前项目仍然处于 Alpha 阶段,可能存在较多 bug,你可以从 GitHub Release 下载最新发布的 Alpha 版本体验一下,或加入 Discord 服务器 参与讨论。如果你也能参与开发,那就更好了!