MCLF-CN / docs

公开的实现规范/文档
10 stars 0 forks source link

整合包预启动命令(Pre-Launch Command) #13

Open 3TUSK opened 3 months ago

3TUSK commented 3 months ago

检查项

您是什么类型的用户

其他

请简单的说一下您的想法

允许整合包定义一串需要在游戏启动前运行一次的命令(通过当前系统的 Shell,或者说 exec 执行),并随整合包一并导出。

它能解决什么样的问题/带来什么样的帮助

Packwiz-Installer 为代表的一些整合包制作工具提供了基于 MultiMC 的 Pre-Launch Command 实现的整合包自动更新机制,以实现「每次启动游戏时,整合包内容即自动获得更新」。

若能实现该功能,整合包自动更新便可不依赖于特定的启动器而实现,由此给予用户更大的自主权,同时方便任何有「需要短时间内快速更新整合包内容」的服主无需为此自制启动器或相关基础设施。

期望的结果

在「MCBBS 整合包格式」中允许定义一可选新字段,名称待定,其内容为当前操作系统可执行的一串命令。启动器在读取到该字段后,会在每次启动游戏前尝试执行该命令。

命令的执行可以以 Java SE 标准库中的 java.lang.ProcessBuilder 为参考标准。

命令执行时,应以环境变量(Environmental Variable)或其他形式提供一些实用信息,包括但不限于

考虑到以 java.lang.ProcessBuilder 为标准的话,未必会有各种主流 Shell 支持的环境变量展开,有必要明确一套「展开占位符」的约定。

是否有对这个方案的相关链接?

附注

这个建议实际上源自历届 TeaCon 中出现的永恒难题:在参展 Mod 及其他相关资源每天都有更新的情况下,如何应对整合包版本的快速迭代。 我们在 TeaCon 2021 和 2022 中使用了自制的 RemoteSync 来解决这一问题。虽然成功解决了版本快速迭代问题,但我们随后在两届 TeaCon 中发现了由此引发的更多问题,并最终促使我们在 TeaCon 2023 转向 Packwiz。

我曾尝试过其他可能的解决方案,例如使用 Java Agent 搭配 JVM Arguments 来实现类似效果,但我不确定该方案是否最终在 TeaCon 2023 中实装。

利用 Java Agent 的 premain 来更新整合包的想法并非只有我尝试过:在 ModFest 主办的 BlanketCon 23 中,其展示服务器客户端便使用了 unascribed 的 unsup 来实现整合包随游戏启动自动更新,原理即 Java Agent。

抄送 @ustc-zzzz

题外话:「MCBBS 整合包格式」有没有正式的名字和文档?

zyxkad commented 3 months ago

整合包内自定义指令的问题是:

  1. 当前环境不支持所使用的指令
  2. 容易被投放木马病毒
3TUSK commented 3 months ago

一些相关,但过于遥远且复杂的想法:

zyxkad commented 3 months ago

我的建议是如果真的要做这个功能,设置指令前需要向用户弹窗确认

zkitefly commented 3 months ago

或许可以让启动器支持 MultiMC 整合包的 Pre-Launch Command 支持?

3TUSK commented 3 months ago

当前环境不支持所使用的指令

这个问题很有趣。 TeaCon 2023 所使用的 Packwiz 是基于 Kotlin 编写并以 JVM 作为编译目标的。Packwiz-Installer 利用了 MultiMC 的 Pre-Launch Command 执行时注入的 INST_JAVA 环境变量以获取「当前游戏启动时所用的 Java 程序的绝对路径」来运行 Packwiz-Installer-Bootstrap。由此,Packwiz 利用了 JVM 本身即跨平台的特性避免了「针对不同操作系统进行特殊处理」的问题。

不妨允许根据当前操作系统、CPU 架构等的不同来决定该执行哪一个命令。就像这样:

{
  "pre-launch-command": {
    "windows-amd64": "paint.exe",
    "macos-arm64": "say hello from macOS",
    "linux-loongarch": "uname -a"
  }
}
zyxkad commented 3 months ago

或许可以让启动器支持 MultiMC 整合包的 Pre-Launch Command 支持?

不,modrinth整合包并没有此功能,这个功能是MultiMC启动器的

ustc-zzzz commented 3 months ago

木马病毒的说法纯属无稽之谈:无论是整合包模组,还是整合包启动参数里的 Java Agent,在植入木马病毒的难度方面和预启动命令上没有显著差别,而一般用户也根本不会去逐个检查,换言之用户是因为信任的是整合包本身,而不是因为信任了整合包的哪些部件。既然用户已经信任了这个整合包,那么额外增加所谓的确认流程也不会让用户更加信任什么东西,而如果用户本来就不信任这个整合包,他也一定会额外检查这个预启动命令是否安全。

zyxkad commented 3 months ago

整合包模组一般是从modrinth或curseforge平台上下载的,可以避免多数注入

ustc-zzzz commented 3 months ago

当前环境不支持所使用的指令

另一个可能的解决方案是让启动命令默认为 java,整合包只记录启动参数(例如 ["-jar", "xxx.jar"]),可以在制作整合包的时候提供一些便利,当然也不需要关心跨平台的问题。

ustc-zzzz commented 3 months ago

整合包模组一般是从modrinth或curseforge平台上下载的,可以避免多数注入

用户可不会逐个检查整合包模组的链接是否真的来源于 cf 或者 modrinth,这个整合包格式也没有强制所有模组都从 cf 或者 modrinth 下载。

burningtnt commented 3 months ago

木马病毒完全就是无稽之谈。

我倾向于支持两大格式,pre-launch-command可以直接为一个命令,或为一个结构体,指明不同操作系统上的具体执行的命令。 而对于一个命令,可以是一个 string[],或直接是一个 string。前者可直接传入 ProcessBuilder 作为参数,后者则由启动器自行 tokenize 后再做处理。

这样,既可以保证支持不同平台执行不同命令的功能,也可以让跨平台命令更加方便执行。 同时,string 模式则提供较为简便的写法;string[] 模式则给予作者更多自由度,与启动器的 tokenize 算法解耦。

问题:目前绝大部分启动器均支持 INST_JAVA 环境变量。但环境变量插入的规则不同。 我倾向于使用 "$INST_JAVA" 的风格,但这样会导致:

zkitefly commented 3 months ago

$INST_JAVA 的风格好像也是 MultiMC 的 Pre-Launch Command 风格

Pigeon0v0 commented 3 months ago

要做自动更新不如把 MCBBS 整合包格式 v2 的文档搞完了来,启动前执行命令风险太大了

burningtnt commented 3 months ago

要做自动更新不如把 MCBBS 整合包格式 v2 的文档搞完了来,启动前执行命令风险太大了

风险何在?如果我要投毒,随意往一个 JAR 里面塞点东西不是更好?何必一定要走启动前执行的命令呢?

zyxkad commented 3 months ago

要做自动更新不如把 MCBBS 整合包格式 v2 的文档搞完了来,启动前执行命令风险太大了

风险何在?如果我要投毒,随意往一个 JAR 里面塞点东西不是更好?何必一定要走启动前执行的命令呢?

不能因为另一件事情"也有风险"而否认一件事的风险

zyxkad commented 3 months ago

相对于启动指令,jar的毒更容易被扫描,比如检测有无使用关键包,调用关键函数等

ustc-zzzz commented 3 months ago

相对于启动指令,jar的毒更容易被扫描,比如检测有无使用关键包,调用关键函数等

JVM 又不是沙箱,Jar 内部也可以执行命令,关键包/关键函数又从何谈起?启动命令直接以文本形式写入整合包配置,而 Jar 内部代码编译后以二进制中间码形式执行,何种方案更容易发现安全问题?