R.E.P.O.
Install with App

Details

Latest version
0.5.3
Last Updated
First Uploaded
Downloads
2.1K
Likes
1
Size
230KB
Dependants

更新日志

[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.* vs LateJoinSimple.*),协议不通,等效单端。只读检测 + 日志,不改变任何行为。

文档

  • 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(GUID cn_xc.LateJoinSimple),房间属性键改为 LateJoinSimple.*;与原版 LateJoinNow 不兼容,不可同时启用。
  • 房间名前缀改为 [中途加入-小菜]。
  • 目标框架 .NET Framework 4.7.2,BepInEx 5.4。
Thunderstore development is made possible with ads. Please consider making an exception to your adblock.