双客户端
双客户端用于在 Windows 或 Apple Silicon macOS 本机联调两名玩家。两个客户端组成一个“组”,可以统一查询状态、看日志、热更代码和停止。
动手前先确认已安装的 CLI 真的支持:查看 doctor --capabilities 和命令帮助里是否有 --clients、--group。不要只凭文档或 Skill 版本推断。
| 想做的事 | 用法 |
|---|---|
| 同一个本地世界里两名玩家 | run --clients 2。第一名玩家是主机,第二个客户端加入主机。加 --new 表示新建世界 |
| 两个客户端进入同一外服 | connect <host> --port <port> --clients 2。服务器须允许无认证开发客户端;工具不部署或修改外部服务器的 Mod |
| 两个独立世界 | 分别运行指定实例。同一份代码可以共享,运行中改了依赖要先退出相关世界再重新运行 |
run --clients 2 得到的不是两个独立世界,也不是历史代码快照。
- 本地主客机需要
local-dual-client-manual能力,目前由 Windows 后端提供。macOS 运行包尚未完成同等适配,会在启动前拒绝本地双客户端。 - 外服双客户端按运行包的独立身份能力判断,不由本地主客机是否支持来推断。macOS 双外服需要支持独立开发身份的原生运行包,旧运行包会明确拒绝。
全局参数都放在子命令之前:
# 本地世界:主机 + 客机mcpy --local --project <项目目录> --non-interactive run --clients 2 --no-gui --detach --json
# 同一外服:两个客户端mcpy --local --project <会话目录> --non-interactive connect <服务器> --port 19132 --clients 2 --detach --json先保存返回的 group 和 members,再看 ok。部分失败时主机可能已经启动,不要丢掉它的会话 ID 或重新创建另一个世界。
| 组类型 | 角色 | 能力 |
|---|---|---|
| 本地组 | host、guest |
主机还有服务端执行能力;客机只有客户端能力 |
| 外服组 | client1、client2 |
只有客户端能力 |
每个成员都有自己的 session。不同客户端的实体 ID 可能重复,选择操作对象时按组角色、会话 ID 和返回的玩家名称,不要跨客户端复用实体 ID。
本地主客机:手动加入
Section titled “本地主客机:手动加入”本地主客机采用手动加入。工具启动主机和客户端 2 后返回 waiting_for_join,这不是启动失败,而是在等你操作:
- 在客户端 2 选择“开始游戏”。首次菜单若只有“开始”和“更多选项”,先选“更多选项”进入正常菜单。
- 点击提示中目标名称的“局域网世界”卡片,不要打开同名的本地存档。
- 按需下载资源后加入。
工具会自动核验加入结果。没点卡片不需要重启客户端;加入了错误的世界时,先退出该世界,再选择指定主机。不要猜测本地联机端口,也不要另开独立世界来代替第二名玩家。
确认联机成功
Section titled “确认联机成功”mcpy --local --project <项目目录> status --group <组ID> --jsonmcpy --local --project <项目目录> runtime capabilities --group <组ID> --jsonmcpy --local --project <项目目录> logs --group <组ID> --source game --tail 100 --jsonrunning 只说明进程阶段。只有 connection_verified=true 才表示已确认两个不同玩家加入同一世界,但这仍不证明玩法正确。建议在两个客户端分别执行一次验收脚本,并在主机服务端核对玩家列表或权威状态。两个窗口、两张 HUD 截图不能代替联机验证。
冷启动等待超时后,游戏可能仍在加载。先用 status --group 重新核验;两名玩家已经就绪的话不必重开。
明确操作对象
Section titled “明确操作对象”Python、输入、截图等操作都要指定具体成员的 --session,不会自动广播:
mcpy --local --project <项目目录> runtime py --session <主机会话> --side server --file <服务端验收.py> --jsonmcpy --local --project <项目目录> runtime py --session <客机会话> --side client --file <客户端验收.py> --json执行前查询目标成员的能力,不要对客机发送服务端脚本。切换玩家后使用新的会话 ID。结果与未知请求的处理见 运行时调试,玩家与 UI 动作见 统一输入,画面采集见 截图与录屏。
普通源码变化可以按组热更:
mcpy --local --project <项目目录> runtime reload python --group <组ID> --module MyMod.client.logic --side client --jsonmcpy --local --project <项目目录> runtime reload python --group <组ID> --module MyMod.server.logic --side server --jsonmcpy --local --project <项目目录> runtime watch --group <组ID> --side clientclient更新两名玩家的客户端;server只更新主机服务端一次。both只用于确认可在两端执行的公共模块,不要用它来猜端侧。- 逐项检查每个成员、每个端侧的结果。部分失败或未知不等于整组成功,也不要自动重复执行有副作用的脚本。
- 依赖增删、包身份或目录结构改变后,保存进度并重新运行整组。
- 停止 watch 只停止监控,不退出游戏;关闭管理面板也会保留游戏。
runtime watch/reload不执行项目预处理,脚本的执行时机见 项目脚本。
mcpy --local --project <项目目录> restart --session <失败客机会话> --jsonmcpy --local --project <项目目录> restart --group <组ID> --jsonmcpy --local --project <项目目录> stop --session <客机会话> --jsonmcpy --local --project <项目目录> stop --group <组ID> --json- 重启后重新保存返回的会话 ID,旧 ID 只用于查历史。
- 客机失败时优先重试客机,不必重建主机世界。主机有关联客机时,停止或重启整个组;工具会先处理客机,再处理主机。
- 同一联调组的玩家身份会保留。主机代码或依赖改变后,客机重新加入时可能需要再次下载资源;不要手动清理全局包或修改运行记录。
- 客机重试会加入主机当前已加载的版本,源码改动是否已应用要另看提示;要应用依赖变化就重启整个组。
- 只结束自己启动或用户明确指定的会话。接管已有组用于观察,并不自动获得退出其中所有游戏的授权。
- 重要世界先在游戏里保存。Windows 上进程退出本身不保证新增内容已存档。
- 响应丢失时先用
status --list --json找回组与成员;脚本结果为unknown时先检查原请求和日志,不要盲目重发。 - 常见错误码(
waiting_for_join、group_not_ready、partial等)的处理见 故障排查。