LateJoinSimple
中途加入:让朋友在卡车 / 商店 / 关卡进行中随时加入你的房间。基于Zichen的 LateJoinNow,在其授权下接手修复。更新日志
[0.5.3] - 2026-10-18
修复:加入者「抓不动东西 / 交互不了」
- 修复
PhysGrabber的引用:在PlayerAvatar.Awake后置钩子里,若PhysGrabber.photonView或PhysGrabber.playerAvatar为空则补上(参考实现里的GrabberViewPatch)。中途加入的玩家这两个引用为空时会表现为抓取 / 交互无反应。 - 若
physGrabPoint为空,会打一行 Verbose 提示([抓取器] … physGrabPoint 为空),用于确认是否属于组件级损坏。
说明
- 仅补引用,不改任何交互数值;
spawned强制逻辑此前已存在(客机侧 +PhysGrabObject.Awake)。
[0.5.2] - 2026-10-18
修复 + 诊断
- 修正升级属性的读取位置:0.5.1 读的是
StatsManager.playerUpgrade*字段(实测为空,导致[自身属性]全是 0、0.5.0 的重放也找不到数据)。现在改为优先读游戏真正的存储StatsManager.dictionaryOfDictionaries[升级名][steamID],字段仅作后退。 - 新增
[升级字典]dump:[升级字典] 加入后 3 秒:共 N 个字典;本地(<steamID>) 非零项 M 个;样例: playerUpgradeHealth(2) …—— 可直接确认升级数据是否存在、键是什么。
已确认正常(0.5.1 日志)
- 血量推送:房主推
1300/1300,加入者 12 秒即显示1300/1300(set)✓ - 外观颜色:双方
色[]数组均为真实值且不同(说明颜色同步成功)✓ - 加入者自己的
100/100是真值(其血上限就是 100)✓
[0.5.1] - 2026-10-18
新增诊断(只读)
[自身属性]对照日志:加入后 3 秒(重放前后各一次)与 12 秒,同时打印存档里的升级等级与本机实际生效的字段:[自身属性] 重放前 3 秒 steamID=… | 存档: 跳3 体50 速2 血5 力1 | 生效: JumpExtra=0 EnergyStart=100 SprintSpeed=5 maxHealth=100 grabStrength=1- 用途:区分两种根因 —— 存档有值但没生效(0.5.0 的重放应能修,看重放后那条是否变化)/存档本身没到本机(属存档同步问题,需另查)。
说明
- 0.5.0 的升级重放保留(正常情况无副作用)。
[0.5.0] - 2026-10-18
修复:中途加入者的升级属性一直没被应用(这次找到真正原因)
- 游戏里 跳跃 / 体力 / 冲刺速度 / 抓取力量 / 抓取范围 / 投掷强度 / 攀爬 / 翅膀 / 血量上限 / 蹲伏恢复 / 电池 / 地图人数 这些属性,只在玩家「购买升级」的网络 RPC 里应用:
PunManager.UpgradePlayerX(...)→PunManager.UpdateXRightAway(steamID, value)→ 写入PlayerController.JumpExtra/EnergyStart/SprintSpeed/PhysGrabber.grabStrength/PlayerHealth.maxHealth等。 - 中途加入者错过了历史上所有这类 RPC → 本机这些属性一直是默认值(表现为跳得少、体力短、跑得慢、血上限低)。
- 现在:加入后 3 秒 / 12 秒各重放一次 —— 读出
StatsManager.dictionaryOfDictionaries中每个玩家的每个playerUpgrade*数值,调用游戏自带的PunManager.Update*RightAway(steamID, value)让游戏按原生逻辑应用(这些方法内部会自行判断是否适用于本地玩家,对所有人都安全)。
开关:[玩家属性] ApplyUpgradesOnJoin(默认开)。预期日志:[属性应用] 加入后 3 秒:已按存档重放 N 项升级属性。
说明
- 只调用游戏自带方法,不自己写属性值;不涉及关卡 / 墙 / 门 / 通路。
[0.4.9] - 2026-10-18
对照参考实现后的补充
参考 RepoLateJoin / LateJoinPlus 的同名实现(SendPlayers):他们的「玩家属性」同步就是 死亡状态 + 血量/上限,并且会 跳过加入者自己的 avatar;SendCosmeticHealth 同步的是地图上的化妆品物体血量,不是玩家。他们的分类表里也没有玩家颜色 / 装扮 / 升级属性的同步。
本版据此补上两处:
- 跳过加入者自己的 avatar(不再把本机已有的值推回去,避免污染)。
- 同步死亡状态:对
deadSet == true的玩家发送PlayerAvatar.PlayerDeathRPC(-1)(与参考实现一致);死亡玩家不再推血量。日志形如属性同步:血量 N 个,死亡 M 个,外观颜色 K 个 → 目标 #…。
说明
- 保留 0.4.8 的
healthSet门槛:只在房主侧血量已初始化后才推,避免推默认 100。
[0.4.8] - 2026-10-18
修复(关键)
- 不再推送未就绪的血量(垃圾值):0.4.7 的日志证据 —— 房主自身的真实血上限是 1300,但它推给加入者的却是 100/100(连自己都是 100)。原因是推送时机早于游戏从存档初始化血量(
PlayerHealth.healthSet == false时值仍是默认 100)。现在只在healthSet == true时才推,否则跳过等待后续推送(0~30 秒共 11 次)。加入者因此不会先看到错误的 100,而是直接等到真值。 [属性快照]增强:现在输出<名字> 血量/上限(set|unset) 色[颜色索引…],可同时观察血量是否已初始化、以及外观颜色是否到达。
说明
- 加入者自己的血量(日志中的
100/100)本来就是真值,不是同步失败。
[0.4.7] - 2026-10-18
修复 / 诊断
- 客机落地后自报血量:
BroadcastOwnHealth(加入后 12 秒 / 25 秒)把自己的真实health/maxHealth广播给其他玩家(UpdateHealthRPC允许 owner 发送)。这样房主那边的副本就是正确的,房主再推给新加入者时不会推错值 —— 针对「某一位做房主时同步不到」的方向性问题。 - 房主推送日志带上具体数值:
属性同步:… → 目标 #N '名字';推送值 PlayerAvatar=100/100; PlayerAvatar=180/180;—— 可直接看出房主手里的副本是否已经正确。
已验证
- 0.4.6 的「推送提前 + 加密」生效:客户机日志
[属性快照] 加入后 12 秒 → 绊倒铁盒 180/180(0.4.4 时 12 秒还是 100/100,25 秒才对)。
[0.4.6] - 2026-10-18
修复
- 属性推送改为「一加入就开始」+ 更密(0/2/4/6/8/10/13/16/20/25/30 秒):此前推送协程挂在加入管线末尾,前面还有「补建尸体对象 / 刷新老玩家外观语音」等步骤,可能拖十几秒才开始推 —— 这就是 0.4.4 快照里「12 秒仍是 100/100、25 秒才对」的原因。现在在管线第一行就启动推送,并把窗口从 5 次加密到 11 次,让属性尽早落地。
说明
- 只改推送时机与频率,不新增任何行为;仍只推房主的真实数据、只发给该加入者。
[0.4.5] - 2026-10-18
修复
- 属性推送改为 30 秒内多次(0 / 4 / 10 / 20 / 30 秒):实测(0.4.4 的
[属性快照])显示,加入者落地时PlayerHealth/PlayerCosmetics可能尚未就绪,过早发出的 RPC 会丢失 —— 快照里 12 秒时仍是100/100,25 秒才变成真实的180/180。现在把推送摊开,尽早落地。只在前两次和最后一次打 Info,其余走 Verbose。
已确认的事实(0.4.4 诊断)
[玩家视图] 房间 2 人,本机 avatar 2 个,一致→ 玩家视图完整,不是 avatar 缺失。[属性快照]12 秒100/100→ 25 秒180/180→ 属性最终确实同步到位,此前"同步不了"很可能是看得太早(15~20 秒内才会到位)。
[0.4.4] - 2026-10-18
修复
[属性快照]/[玩家视图]诊断改为必然触发:原先从ClientLateJoinFixesCoroutine启动,但该流程在实际会话中会被跳过(对方 0.4.3 的日志里快捷栏修复有、两条诊断没有,证实未启动)。现在改为从LevelGenerator.Start后置钩子(每关必跑,客机专属)启动,并在 12 秒 / 25 秒各打一次快照,短会话也能拿到。
已确认的事实(本轮日志)
- 房主端推送目标正确:
属性同步:血量 2 个,外观颜色 2 个 → 目标 #2 '绊倒铁盒'。—— 不是"发给不存在的人"。 - 因此方向性同步失败的原因只剩两种:接收端(组件就绪/RPC 被拒)或数值其实已一致。
[属性快照]会给出答案。
[0.4.3] - 2026-10-18
新增(只读诊断,无行为改动)
- 房主端推送目标:
属性同步:血量 N 个,外观颜色 M 个 → 目标 #<actor> '<名字>'。—— 用于确认推送对象是否正确。 - 加入者端属性快照:落地 12 秒后打印
[属性快照] 本机可见 N 人 → 名字 血量/上限;…—— 打印本机实际看到的数值。
为什么加这两条
- 实测存在方向性差异:某位玩家做房主时同步正常,另一位做房主时同步不到。
- 两端对照即可定位:房主显示已推送、加入者数值不对 → 问题在传输/接收;数值一致 → 同步其实正常(属于观感或其它模组干扰)。
[0.4.2] - 2026-10-18
修复
[玩家视图]诊断移到独立协程:原先挂在ClientLateJoinFixesCoroutine里,而该协程前面有「等协同就绪 1 秒」的窗口,可能提前yield break导致诊断不输出。现在改为加入后 12 秒必跑(WaitForSecondsRealtime),不再依赖协同窗口。
说明
- 纯诊断位置调整,无行为改动(0.4.1 的
OwnerOnlyRPC兜底已实测生效:日志出现已拦截 SemiFunc.OwnerOnlyRPC 的异常并放行)。
[0.4.1] - 2026-10-18
修复 / 诊断
SemiFunc.OwnerOnlyRPC的 NRE 兜底:当对象没有 owner 时,游戏自己的OwnerOnlyRPC会在内部抛NullReferenceException(日志中表现为DMD<SemiFunc::OwnerOnlyRPC>←PhysGrabObject.GrabLinkRPC/MapToolController.SetActiveRPC),导致该次抓取链接或地图工具动作失败。现在加了 Finalizer:捕获后放行并只记一次日志。- 新增只读诊断
[玩家视图]:加入修复完成后,比对「房间人数」与「本机可见的PlayerAvatar数量」;若本机 avatar 少于房间人数,会打印一行提示 —— 用于确认「属性同步不了」是否其实是玩家视图缺失(此前日志中的Received RPC "HealOtherRPC" … but this PhotonView does not exist!即属此类)。
说明
- 两项均不改变关卡 / 墙 / 门 / 通路状态;
OwnerOnlyRPC兜底是唯一的行为改动(放行原本会被拒的 RPC)。
[0.4.0] - 2026-10-18
新增
- 外观颜色同步:房主在加入者落地后(并 4 秒后补一次),把每个玩家的
colorsEquipped通过游戏自带的SetupColorsRPC(该 RPC 仅房主可发)推给该加入者 —— 修复加入者看不到别人颜色(日志中PlayerCosmetics: No colors equipped after 10 seconds的表现)。开关PlayerCosmeticsSync(默认开)。 - 血量与颜色两个开关互相独立(只关一个不影响另一个)。
说明
- 游戏内可同步的玩家属性已全部覆盖:血量 / 血上限、外观颜色。
- 升级属性(速度 / 力量 / 体力 / 攀爬 / 翅膀 / 电池 / 地图人数 / 蹲伏恢复)在游戏里没有任何 PunRPC,是各客户端按本地存档计算的,其他玩家本来就看不到 → 不存在「未同步」问题。
- 装扮(帽子等) 暂未推送:其 RPC 需要
int[],本地字段是List,需转换后另版处理。
[0.3.9] - 2026-10-18
修复
- 新加入玩家的血量 / 生命上限不同步:中途加入者看不到其他玩家的血量与上限。原因是
PlayerHealth.playerAvatar只在Awake中赋值,血量同步依赖UpdateHealthRPC广播,而加入者进来时没有拿到当前值。现在房主在加入者落地后(并 4 秒后补一次)把场上每个玩家的health/maxHealth通过游戏自带的UpdateHealthRPC推给该加入者。开关PlayerHealthSync(默认开)。
说明
- 只推送房主的真实数据,不修改任何本地状态;不涉及关卡 / 墙 / 门 / 通路。
[0.3.8] - 2026-10-18
新增
- 检测房主是否为 LateJoinNow(Zichen 原版):当房主未运行本模组、但其玩家属性里带有
LateJoinNow.Version时,打一行明确提示 —— 两套模组房间属性键不同(LateJoinNow.*vsLateJoinSimple.*),协议不通,等效单端。只读检测 + 日志,不改变任何行为。
文档
- README 的「已知问题」补充混合模式:房主用 LateJoinNow、加入者用本模组时,日志会出现
Received RPC … but this …、KeyNotFoundException等,属预期;建议双方统一使用同一个模组。
[0.3.7] - 2026-10-18
修复 / 说明
- 确认
Level Point: Not connected属游戏自身提示,与可见外观无关:协同模式实测中,该提示出现 1 / 15 / 31 条时均未观察到虚空墙、门框没门或通路堵塞,已在 README 的「其它」中注明可忽略。 [光照守卫]日志修正:异常消息为空时改为打印异常类型名(此前会输出一个空冒号)。
说明
- 无行为改动:不涉及关卡 / 墙 / 门 / 通路状态。
[0.3.6] - 2026-10-18
变更(实现清理,无功能新增)
- 移除四段实验性「虚空修复」代码(
LevelPointRelink、RoomConnectionRebuild、WallDoorRefresh、NavMeshRebuildOnJoin)及其配套诊断与 Hook: 这些项在实测配置中一直是关闭状态,而关闭状态下虚空问题未再出现,因此删除以简化实现。旧 cfg 里残留的这四个键会被忽略。 - 快捷栏修复改为独立实现(行为不变):先用「槽位自己上报的索引」建立已登记集合,再把场景里未登记的槽位按索引升序补注册。
- 保留并沿用:模块连接「只发一次」+ 只补发未发送模块、游戏侧 NRE 守卫、配置版本检测非破坏性。
说明
- 移除的均为默认关闭的实验项;
FixInventorySlots、ModuleResendSeconds保持默认生效。
[0.3.5] - 2026-10-18
修复
[墙体诊断]口径改正:原先「有连接标志但未连通」把「模块任一方向有连接」和「该开关是否连通」混在一起比,会产生大量假阳性(连接在 Top、而这个开关负责 Right 时也会被算进去)。现在按每个开关自己那一侧与对应连接标志比对,只统计确实不一致的个数。- 配置版本检测改为非破坏性:旧实现会
config.Clear()+ 删除 cfg +Reload(),而Reload在文件已被删除时会抛Could not find file ...cfg—— 结果既清空了用户设置,又打出「重置配置失败」的误报。现在只提示版本变化并保留设置,随后把新版本号写回配置项。
说明
- 状态更新(据 0.3.4 / 0.3.5 双端实测与日志):
- ✅ 「虚空门 / 缺墙 / 门框里没有门」已不再出现 ——
Level Point: Not connected由 31 降到 1(仅剩入口点Level Path Point)、Ev Destroy Failed由 122 归零、RaiseEvent(202) failed由 4 归零;墙/门开关与本侧连接标志不符为 0。 - ✅ 快捷栏限制已修复(
FixInventorySlots补注册InventorySpot)。
- ✅ 「虚空门 / 缺墙 / 门框里没有门」已不再出现 ——
- 已知未处理:新加入者的生命 / 属性同步(血量 / 生命上限显示不同步)—— 详见 README 的「已知问题」。
- 本版不涉及任何关卡 / 墙 / 门 / 通路状态改动;四个虚空实验项仍为默认关。
- README 更新:补充「生命 / 属性同步」已知问题、测试致谢(排排坐 食果果、Sunshine°),并更正「版本更新会重置配置」的旧说法(0.3.5 起改为保留设置)。
[0.3.4] - 2026-10-17
修复
- 同一模块的连接同步不再重复发送:
Module.ModuleConnectionSetRPC会自增LevelGenerator.ModulesSpawned(已用 IL 核实),而该计数被关卡生成协程读取;原先的后台兜底会对同一加入者把整个模块表重发。现在按加入者记录「已发过的模块」,每个模块只发一次(日志会显示「已发过 N」)。 - 后台只补发「尚未发过」的模块(最多 60 秒、每 5 秒检查一次;开关
ModuleResendSeconds,0 = 关闭):解决「模块在首次同步之后才变为 SetupDone,于是永远没被发出去」的情况 —— 走房主的真实数据,不做任何客户端推算。
新增(只读诊断,不修改任何状态)
[墙体诊断] 模块 N 个:未收到连接数据 X 个;墙/门开关 K 个:未绑定模块 Y 个、有连接标志但未连通 Z 个。每关一次,用于判定「缺墙 / 门框没门」到底是没拿到连接数据还是拿到了但开关状态没更新。
说明
- 四个虚空实验项(
LevelPointRelink、WallDoorRefresh、RoomConnectionRebuild、NavMeshRebuildOnJoin)仍为默认关;FixInventorySlots(快捷栏修复)保持默认开。
[0.3.3] - 2026-10-17
修复
- 快捷栏限制(加入者无法把道具放进快捷栏):中途加入时
Inventory的槽位列表可能留下空位(场景里的InventorySpot没被注册进Inventory),导致GetSpotByIndex返回 null。现在在关卡生成完成后(并重试 3 次)把所有场景里的InventorySpot补注册回去。开关FixInventorySlots(默认开)。
说明
- 「缺墙 / 门框里没有门」仍未修复:相关实验项(
LevelPointRelink、WallDoorRefresh、RoomConnectionRebuild、NavMeshRebuildOnJoin)继续保持默认关。
[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(GUIDcn_xc.LateJoinSimple),房间属性键改为LateJoinSimple.*;与原版 LateJoinNow 不兼容,不可同时启用。 - 房间名前缀改为
[中途加入-小菜]。 - 目标框架 .NET Framework 4.7.2,BepInEx 5.4。
