cn_xc-LateJoinSimple icon

LateJoinSimple

中途加入:让朋友在卡车 / 商店 / 关卡进行中随时加入你的房间。基于Zichen的 LateJoinNow,在其授权下接手修复。

By cn_xc

CHANGELOG

更新日志

[0.3.2] - 2026-10-16

修复

  • 纠正上一版会把「本来能通行的门 / 通路封死」的问题:墙 / 门道具重算(WallDoorRefresh)原先无条件执行,会把已经正确的开关翻到另一侧;现在只在房主下发的连接确实发生变化时才重算,连接未变则一个开关都不碰。
  • 实验开关默认值统一为关:WallDoorRefresh、LevelPointRelink、RoomConnectionRebuild、NavMeshRebuildOnJoin 全部默认关 —— 默认状态下本模组不会改动任何墙 / 门 / 通路状态。
  • 内嵌版本号与 manifest 对齐:此前 DLL 内仍报 0.3.0,与 manifest 不一致。

说明

  • 0.3.0 条目里写的「默认开」以本版为准,现在都是默认关。
  • 想试验修复的,请一次只开一个开关(WallDoorRefresh 或 LevelPointRelink),逐关观察;发现异常立刻改回 false。

[0.3.1] - 2026-10-16

  • 仅修正 manifest.json 的版本号;本版未同步更新 README / CHANGELOG,包内 DLL 内嵌版本仍为 0.3.0(0.3.2 已统一)。

[0.3.0] - 2026-10-16

新增

  • 虚空修复(客机侧,需双端都装)
    • NavMeshRebuildOnJoin(默认开):中途加入者落地后调用游戏公开的 LevelGenerator.NavMeshSetup() 本地重建导航网格,改善寻路与卡虚空。
    • RoomConnectionRebuild(默认关,实验):对房主从未下发连接数据的房间(SetupDone == false),按关卡网格布局推算 Top/Bottom/Right/Left/First,再调用游戏自身的 ModuleConnectionSetRPC 把墙 / 门建出来;房主数据到达后以房主为准。 实现说明:该 RPC 带 master-only 校验,这里构造一条「来自房主」的本地 PhotonMessageInfo 只为让校验通过 —— 纯本地调用,不发网络包,也不改房主的权威数据。若出现墙体异常请关闭此项。

修复(内部审计发现)

  • 协同模式下的地图兜底重发:原先该分支只打印「协同模式未移植」,实际是无条件重发;现改为按对端上报的 Module 数判断 —— 已齐则跳过,不足才补发一次。
  • SlowProjectile 销毁:补上「先转让所有权再 PhotonNetwork.Destroy」(原先注释称委托未移植,实际该委托已移植却未使用)。
  • 171 事件处理器加固:房主为 null 时不再抛异常,也不会误报为「撤离点锁定同步失败」。
  • 语音链接自动重试:原版在本地找不到对应语音视图时会直接 NRE,因此只能拦截并等待对方重发;现改为自己起协程重试(最多 2 秒),视图一出现就用游戏自身的 UpdateMyPlayerVoiceChat 补调一次,不再依赖重发。
  • 【关键】墙体 / 门道具刷新 —— 「缺墙 / 门框里没有门」的根本修复:ModulePropSwitch.Setup() 依据 Module.ConnectingTop/Right/Bottom/Left 决定墙与门的两种形态(用 SetActive 切换两组父子物体,并非销毁)。中途加入者这边,这些道具在房主连接数据到达之前就已按默认(错误)连接处理过,所以必须在数据到达后重算。现在对每个道具还原方向 → 复位 Connected → 重跑 Setup()。开关 WallDoorRefresh(默认关,实验):只在连接确实发生变化时才重算;连接未变时绝不动任何开关 —— 无条件重算会把本来正确的墙/门翻到另一侧,可能封死本该通行的路。
  • 【关键】关卡连接点重链接 —— 「虚空墙 / 虚空房间」的根本修复:LevelPoint 之间的链接(LevelPoint.Start → ModuleConnectSetup 协程)只在关卡加载时跑一次、之后永不重跑,而中途加入者的关卡生成早于房主的连接数据 → 模块交界处缺件。现在在 LevelPoint.Start 之后按几何补链接(距离足够近 + 双方朝向相对 + 对方正对我),判据不依赖房主数据,客机可自愈。开关 LevelPointRelink(默认关,实验):按几何补链接可能给本该不通行的位置补上连接,请逐关观察后再决定是否常开。
  • 修正「虚空修复」自身的两个问题(据实测日志,重要):
    • 之前无条件在每关开头调用 LevelGenerator.NavMeshSetup();实测其内部是 PhotonView.RPC,会向整个房间广播,强制所有人重建导航网格并触发导航网格校验(即打印 Module Name / Local Position 那组报错的东西)。现改为:只在本地、且仅在本机确实补建过连接之后,通过私有的 NavMeshSetupRPC 重建一次,绝不广播;开关默认改为关。
    • 之前把「房主引用为空」也算作缺少反射目标,而关卡刚生成时 PhotonNetwork.MasterClient 尚未就绪 → 直接跳过并把该关标记为已处理 → 导致补建连接一次都没执行。现改为:先等到「关卡生成 + 已在房间内 + 房主引用就绪」再执行;条件不满足则不标记,下次触发重试。
  • 新增虚空诊断日志:房主连接数据到达时对比本地原值,不一致会打印 虚空诊断:本地连接与房主不一致,已按房主修正:<模块名> —— 用于确认「虚空」是否属于本地连接错误。
  • 中途加入常见的游戏侧 NRE 守卫(据实测日志新增 6 处):
    • PlayerHealth.Update:头像引用为空时跳过该帧(菜单头像则补上本地头像引用)—— 实测日志中这一条每帧刷了 3255 次 NRE。
    • EnvironmentDirector.AmbientLightLogic / FogLogic:本地头像尚未就绪时跳过(原来只守了前者,FogLogic 仍刷了 9 条)。
    • PlayerDeathHead.UpdateParticleColors:吞掉「头部刚生成、材质还没到」的异常,保持默认粒子色。
    • EnemyOnScreen.GetOnScreen:执行原逻辑前先登记该玩家的 ViewID。
    • LightManager.HandleLightActivation / HandleEmissionActivation:吞掉异常,避免该区域剩余灯光不亮。
  • 协同模式兜底重发误判修复:原先用「进入关卡时抓到的模块数」判断对端是否已齐,关卡还在生成时会误判为已齐而跳过重发(缺的墙就补不上了)。现改为用当前模块数判断,且重发时用最新的模块列表。
  • 房间可见性日志细化:原先只报「补写 N 个,跳过 M 个」,现在区分「已是探索态 / 位置未匹配 / 无地图模块」,便于判断是命中还是匹配失败。同时说明:该功能修的是游戏内地图的房间揭示,与「缺墙 / 虚空墙」不是同一条线。
  • README 配置表补上「模组版本号」只读项。

[0.2.0] - 2026-10-16

新增

  • 房间 / 地图可见性同步(需房主与加入者都装):房主把本局 RoomVolume 中已探索的房间位置发给中途加入者(加入后 3 秒 / 9 秒各一次),加入者按位置就近匹配后调用游戏自带的 RoomVolume.SetExplored() 补写,避免加入者看到空白 / 全黑房间。 实现为自研:复用撤离点锁的 171 事件码(用载荷标签 LJS.Rooms 区分),不新增事件码,不反射私有字段写入(只反射读取 Explored 判断哪些房间已探索)。
  • 光照守卫:给 LightManager.Update / LogicUpdate / Setup 与 EnvironmentDirector.AmbientLightLogic 加 Harmony Finalizer,吞掉异常让同一帧剩余的光照逻辑继续执行(首次记录 Info,之后记 Verbose)。

说明

  • 房间可见性同步与外观 / 语音刷新一样,只在双端都装本模组(协同模式)时生效;单端模式(加入者为原版)仍受原版底层限制。

[0.1.1] - 2026-10-16

修复

  • 修复冲突检测漏检(双装同类模组时不弹冲突警告):原先只在自己的 Awake 里扫描一次 Chainloader.PluginInfos,而加载顺序排在后面的同类模组此时还没登记进去 —— 实测表现为「Zichen 的 LateJoinNow 能检测到本模组,本模组却检测不到它」,所以不弹窗。现在改为启动时 → 延迟 5 秒 → 进入房间时各检测一次,并输出「扫描 N 个插件、命中 M 个」日志便于确认;冲突弹窗等待菜单的时间由 15 秒放宽到 60 秒,超时会留下日志。

[0.1.0] - 2026-10-16

首个公开测试版:基于Zichen的 LateJoinNow 1.1.0,在其授权下接手修复与重新发布。

新增

  • 中途加入完整流程:场景判定 → 排队调度 → 地图模块 / 宝物 / 物品属性 / 22 项场景状态同步 → 落地动画补发 → 虚空兜底重发 → 移动检测。
  • 房间信息 HUD(房间类型 / 名称 / 人数,字号与透明度可调)与中途加入进度显示。
  • 公开房名自动前缀、切关冷却锁房、双端协同优化、冲突检测与弹窗、运行时兼容性自检。

修复

  • 修复原版 PhysGrabber.Update 空值守卫 Transpiler 完全失效:原版用 AccessTools.PropertyGetter(..., "instance") 去查一个字段(必然返回 null),且匹配 OpCodes.Call 而实际 IL 是 ldsfld,该补丁从未生效。现改为 AccessTools.Field + ldsfld 匹配,对 4 处调用点生效。
  • 不再销毁带铰链的门:原版在「强制 spawned」流程中对所有带 PhysGrabHinge 的对象执行 Destroy,会导致加入者看到「只有门框、门没了」。现改为仅记录、不销毁。
  • 冲突检测改为 AND 匹配:原版只要名称含 late 或 join 任一即报警,误报率高;现要求同时包含,并修正了自身识别。
  • 协同模式下等待加入者就绪的超时由 8 秒放宽到 15 秒。

变更

  • 移除双语配置面板与 I18N 机制。
  • 插件更名为 LateJoinSimple(GUID cn_xc.LateJoinSimple),房间属性键改为 LateJoinSimple.*;与原版 LateJoinNow 不兼容,不可同时启用。
  • 房间名前缀改为 [中途加入-小菜]。
  • 目标框架 .NET Framework 4.7.2,BepInEx 5.4。