CD Code Digest Hub /GTA V

多人会话与模式切换

8 分钟阅读 7 个章节 1 张图

返回总览。多人架构必须同时理解会话控制、玩法脚本实例、实体同步和在线服务。本文聚焦前两层的建立与退出;数据复制详见多人同步与实体所有权。

1. 架构判断与证据边界#

本地代码具有会话 owner、peer、主机迁移、脚本参与者握手、实体 clone 和各对象 owner 等机制。因此,实时玩法表现为客户端之间协作、分布持有实体并由脚本主机协调的架构,不能当成所有玩法都在一台权威专用服务器执行。[S4][S5]

另一方面,账户资格、匹配/邀请、云内容、角色统计、商品目录和交易有服务接口。这些服务不是脚本主机的别名。客户端中的 serverBD 或 PROCESS_SERVER 一般表示当前网络脚本的主机逻辑;NET_GAMESERVER_* 交易接口则属于在线服务链路。仓库不能据此证明包含完整后端实现。

2. 会话和脚本实例不是一回事#

层次所需身份/状态可发生的变化
平台/在线资格登录、订阅/权限、服务可用性下线、权限变化、服务失败
游戏会话session、会话 owner、活动玩家加入、离开、会话迁移
网络脚本script ID、instance ID、participants、script host加入某活动、活动主机迁移、脚本终止
网络实体network ID、owner、clone复制、控制权转移、移除

一个玩家已进入在线会话,不代表已经成为某任务脚本的 participant。CNetworkSession 分别绑定 Physical 和 Transition session 的加入及迁移回调,说明会话层内部也有多种用途。[S4,L924]

注意“migration”在代码中还可能指旧平台存档/角色迁移。例如 Transition 控制头中的 save transfer 与会话 host migration 不是同一机制,阅读时必须看对象和调用链。

3. Transition 是跨系统状态机#

MainTransition.sc、Transition_Controller.sch、Transition_Joining.sch 把目标模式、HUD 状态和切换状态分别维护。切换中涉及天空镜头、界面、角色选择、在线资格、会话确认、脚本加载、玩家创建和落地恢复。[S1][S2][S3]

这是主要路径的概括,不是完整枚举。源码有重试、邀请、角色创建、不同模式和平台分支,不能把切换视为一次阻塞的 Join()。

Transition_Joining 中可沿 PREJOINING_FM_SESSION_CHECKS → LOOK_FOR_FRESH_JOIN_FM → 等待/确认加入 → PRE_FM_LAUNCH_SCRIPT → START_FM_LAUNCH_SCRIPT 阅读。这能区分卡在资格、网络、资源还是玩家初始化阶段。

4. 错误处理必须与正常路径同等完整#

MainTransition 的 IS_PROCESSING_A_BAIL_EVENT 处理网络连接、在线登录、权限、服务拒绝等条件;DO_BAIL_CLEANUP 会关闭/复位相关前端状态,通知 creator 清理,执行玩家离开清理,并在特定视频切换路径恢复 streaming 和音频场景。[S1]

这表明用户看到的“连接失败返回单机”实际是一段补偿流程:屏幕、输入、玩家可见性、资源加载暂停、音频、活动脚本都可能已被部分改变。单纯退出网络连接不会自动恢复所有这些状态。

失败处理也不能无限重复触发。源码使用当前 bailing 状态和目标切换状态避免同时运行互相冲突的退出流程。设计新切换入口时,应复用现有状态管理,而不是另建只覆盖成功分支的快捷路径。

5. 网络脚本的启动屏障#

脚本登记 NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT 后,需要等待网络运行状态。HANDLE_NET_SCRIPT_INITIALISATION 持续查询 NETWORK_GET_SCRIPT_STATUS,直到 NETSCRIPT_PLAYING;终止、会话满、禁止中途加入、队伍满等状态走失败路径。[S6]

一个容易误读的细节是:该函数中 50000 毫秒相关超时逻辑主要用于调试/最终日志提示,旧的“超过时间主动终止”代码已被注释,当前注释要求等待原生层给出结论。因此不能把这里写成固定 50 秒后必定退出。

原生 scriptHandlerNetComponent 维护 candidates、participants、slot、ACK、host token 和内部加入状态。没有主机时会在满足条件的候选中决定谁主持;加入过程中原主机离开还可能使本地退回候选重新加入。[S5] 玩法初始化必须等这一身份稳定,不能仅看 script 已加载。

6. 迟加入和迁移对内容的要求#

迟加入玩家需要当前任务阶段、选定变体、目标实体和参与规则,不能依赖“开始时给所有人发过一次事件”。玩法退出时还要处理玩家离开脚本与离开会话两种不同通知。

迁移期间原生组件允许暂时没有有效脚本主机,并维护 pending host 与迁移间隔。内容层应按当前主机身份执行全局推进,依赖同步状态恢复,而不是假定最初启动任务的玩家永久主持。

本文没有运行匹配、邀请或断网测试,也未验证各平台后端可用性。会话机制由本地代码支持,真实网络拓扑中的中继、平台服务和部署细节不在本次证据范围内。

源码证据#

编号位置
[S1]MainTransition.sc:DO_BAIL_CLEANUP、IS_PROCESSING_A_BAIL_EVENT
[S2]Transition_Controller.sch L855/860 HUD 状态,以及 Transition/Gamemode 状态接口
[S3]Transition_Joining.sch L2975、L3233、L3706、L3964、L4079、L4293
[S4]NetworkSession.cpp L924–934,Physical/Transition 会话回调
[S5]scripthandlernetcomponent.cpp L194、L222、L256 握手/参与者;L612 迁移
[S6]net_include.sch L7514,初始化等待与失败处理

[S1]: <../../../GTAV Source/script/dev_ng/multiplayer/scripts/Transition/MainTransition.sc> [S2]: <../../../GTAV Source/script/dev_ng/multiplayer/scripts/Transition/Transition_Controller.sch> [S3]: <../../../GTAV Source/script/dev_ng/multiplayer/scripts/Transition/Transition_Joining.sch> [S4]: <../../../GTAV Source/src/dev_ng/game/network/Sessions/NetworkSession.cpp> [S5]: <../../../GTAV Source/src/dev_ng/rage/framework/src/fwscript/scripthandlernetcomponent.cpp> [S6]: <../../../GTAV Source/script/dev_ng/multiplayer/include/public/net_include.sch>