MpLib

MpLib

共享的STS2多人兼容API:Neow快照同步、战斗同步队列、对等节点权限、战斗动作和钩子屏障。

支持游戏版本:0.107.1 / 0.109.0 / 0.110.1 / 0.111.0

STS2 联机兼容层:修补官方同步边界,并为内容 mod 提供一套简短约定。不是完整的联机框架。

安装后会自动修补几处官方联机同步边界:战斗玩家同步队列改为保留最新快照并立即应用,远端奖励结算后清除过期的战斗同步,Neow 非共享选项改为使用权威快照,而不是在对端重演 handler。用于减少校验和不同步以及镜像状态被过期快照回滚的问题。

在社区 mod 中,MpLib 目前是唯一修补官方同步器语义的层;它不替代各 mod 自己的消息、UI 或字段同步。它还提供 CombatActions 和 NetBootstrap 等简短约定,供内容 mod 使用。

命名空间:[i]Mp.Core[/i]、[i]Mp.Combat[/i]、[i]Mp.Neow[/i]。

不要对同一批原版方法进行 Harmony 修补,例如 [i]EventSynchronizer.ChooseOptionForEvent[/i] 和 [i]CombatStateSynchronizer.OnSyncPlayerMessageReceived[/i],否则补丁会互相覆盖。

[b]CombatActions[/b]

用于带载荷的玩家输入。游戏会扫描 mod 的 [i]INetAction[/i] 类型;MpLib 注册一个 [i]NetModCombatAction[/i],并通过稳定 key 区分业务。入队方式与打牌相同。

[i]actor[/i] 必须是本地玩家。Host 使用发送方的 NetId 作为 owner,不会读取 action 上的字段。其他身份信息放入 payload。两端登记相同的 key。

[code] using Mp.Combat;

CombatActions.Register("YourMod.DoThing", async ctx => { ulong targetId = ctx.Payload.ReadULong(); Player? target = ctx.Actor.RunState?.GetPlayer(targetId); if (target is null) return; await ApplyAsync(target, ctx.Choice); });

CombatActions.RequestEnqueue( actor: LocalContext.GetMe(runState)!, key: "YourMod.DoThing", writePayload: w => w.WriteULong(target.NetId));[/code]

[b]HookBarrier[/b]

空 [i]GenericHookGameAction[/i] 仅通过网络发送一个 ID。当两端已经处于同一战斗 hook 中时:

[code] await HookBarrier.RunInSharedHookAsync(owner, GameActionType.CombatPlayPhaseOnly, async ctx => { await DoWorkAsync(ctx); });[/code]

当 UI 输入带载荷时使用 [i]CombatActions[/i]。仅当没有载荷时才使用 [i]RegisterInput[/i] 和 [i]EnqueueFromInput[/i]。由 owner 所在端生成 hook;对端在 [i]ExecuteAction[/i] 中执行 work。调用方自行去重。

[b]其他[/b]

在初始化时通过 [i]NetBootstrap.Add[/i] 注册 [i]INetMessage[/i] 处理器。每个 [i]NetService[/i] 只注册一次。

[code] using Mp.Core;

NetBootstrap.Add(new YourNetModule());

sealed class YourNetModule : INetModule { public void RegisterHandlers(RunManager runManager) { runManager.NetService?.RegisterMessageHandler<YourMessage>((msg, senderId) => { /* ... */ }); } }[/code]

同一模块类型重复 Add 会被忽略。

使用 [i]RunAuthority[/i] 修改共享跑局字段;不要使用 [i]LocalContext.IsMe[/i]。[i]IsRemoteMirror[/i] 表示在多人游戏中此客户端不是该玩家的权威端。

[i]PlayerSnapshotHooks.AfterRemotePlayerApplied[/i]:在远端 Neow 或战斗快照应用后,写回原版 [i]SerializablePlayer[/i] 上不存在的 mod 状态。

[i]NeowChoicePolicy[/i]:默认情况下,非权威客户端跳过重演 Neow 类 [i]eventOption.Chosen()[/i],改为接收权威快照。为 [i]ShouldSkipHandlerReplay[/i] 赋值会完全替换默认行为;需要快照的阶段请返回 [i]true[/i]。事件页面的 [i]SetEventState[/i] 以及各 mod 自己的选择或 UI 协议不在此范围内。

[b]范围[/b]

最初为 LustTravel2 联机而构建。难点在于官方边界,而不是角色数据。LustTravel2 仍然依赖它;角色状态保留在 LustTravel2 中。

这是一个临时补丁层。如果原版添加了非共享事件结果同步、战斗最新快照保留或消息注册 API,MpLib 将缩减为薄封装,然后再考虑移除。它不替代各 mod 自己的选择流程、UI 或字段。

[b]运行要求[/b]

[list] []支持 Mod 的《杀戮尖塔 2》:[b]0.107.1[/b] / [b]0.109.0[/b] / [b]0.110.1[/b] / [b]0.111.0[/b][/] [/list]

[b]与 LustTravel2 配合使用[/b]

[list] [][b]LustTravel2 0.50.0+[/b] 需要与主 mod 一并启用 [b]MpLib 0.0.1[/b],以支持多人游戏中的 Neow 和战斗同步。[/] []其他内容 mod 可以引用 [i]Mp.Core[/i] / [i]Mp.Combat[/i] / [i]Mp.Neow[/i],而无需安装 LustTravel2。[/] [/list]

[b]安装[/b]

[list=1] []解压变体包,使 [i]mods/MpLib/[/i] 包含 loader DLL 和 [i]lib/<api>/[/i] 目录。[/] []在 Mod 管理器中启用 [b]MpLib[/b]。[/] []根据你的游戏分支(stable / beta)选用对应的 [i]lib/[/i] API 目录。[/] [/list]

[b]更新日志[/b]

请参阅 [url=https://codeberg.org/WRXinYue/STS2-LustTravel2/src/branch/main/mods/MpLib/CHANGELOG.md]CHANGELOG.md[/url]。

[b]链接[/b]

[list] [][url=https://codeberg.org/WRXinYue/STS2-LustTravel2/]仓库[/url][/] [][url=https://discord.gg/DSDYQKvhSz]Discord[/url][/] [/list]