230 lines
13 KiB
Go
230 lines
13 KiB
Go
package routers
|
||
|
||
import (
|
||
"context"
|
||
"sync"
|
||
)
|
||
|
||
var _ = sync.Mutex{}
|
||
var _ = context.Background
|
||
|
||
// Runtime player/combat hydration shared by world entry and character switching.
|
||
func GameRouter_Profiles_PublishSkillBindings(ctx context.Context, rpcCtx *RpcContext, unitId uint64, weapon any, style any) any {
|
||
// Router implementation for GameRouter_Profiles_PublishSkillBindings
|
||
var zero any; return zero
|
||
}
|
||
|
||
func GameRouter_Profiles_PublishCombatResources(ctx context.Context, rpcCtx *RpcContext, unitId uint64) any {
|
||
// Router implementation for GameRouter_Profiles_PublishCombatResources
|
||
var zero any; return zero
|
||
}
|
||
|
||
func GameRouter_Profiles_SpiritFightStyleOverrides(ctx context.Context, state any, templateId uint32) []any {
|
||
// Router implementation for GameRouter_Profiles_SpiritFightStyleOverrides
|
||
return nil
|
||
}
|
||
|
||
//
|
||
// Weapon one character should hold: the instance this account last equipped (replayed from the
|
||
// progress snapshot by RestoreCombatLoadout4229938) when it still resolves in the catalog,
|
||
// otherwise the authored default.
|
||
//
|
||
func GameRouter_Profiles_ResolveEquippedWeapon(ctx context.Context, state any, templateId uint32) any {
|
||
// Router implementation for GameRouter_Profiles_ResolveEquippedWeapon
|
||
var zero any; return zero
|
||
}
|
||
|
||
func GameRouter_Profiles_PublishedWeaponFightStyleId(ctx context.Context, state any, weapon any) uint32 {
|
||
// Router implementation for GameRouter_Profiles_PublishedWeaponFightStyleId
|
||
return 0
|
||
}
|
||
|
||
func GameRouter_Profiles_PublishMinimalActorPresentation4229938(ctx context.Context, rpcCtx *RpcContext, unitId uint64, templateId uint32, reason string) any {
|
||
// Router implementation for GameRouter_Profiles_PublishMinimalActorPresentation4229938
|
||
var zero any; return zero
|
||
}
|
||
|
||
func GameRouter_Profiles_PublishWeaponSnapshot(ctx context.Context, rpcCtx *RpcContext, unitId uint64, templateId uint32, currentWeaponInstanceId uint64) any {
|
||
// Router implementation for GameRouter_Profiles_PublishWeaponSnapshot
|
||
var zero any; return zero
|
||
}
|
||
|
||
func GameRouter_Profiles_PublishSafeRuntimeBuffSnapshot4229938(ctx context.Context, rpcCtx *RpcContext, unitId uint64, templateId uint32, phase string) any {
|
||
// Router implementation for GameRouter_Profiles_PublishSafeRuntimeBuffSnapshot4229938
|
||
var zero any; return zero
|
||
}
|
||
|
||
// gameplay.hackerAbilitySet == "full" (the default). Anything else = safe baseline.
|
||
func GameRouter_Profiles_FullHackerKitEnabled(ctx context.Context, ) bool {
|
||
// Router implementation for GameRouter_Profiles_FullHackerKitEnabled
|
||
return true
|
||
}
|
||
|
||
//
|
||
// gameplay.jobBadgeBuffs == "auto" (the default). Publish the capability buffs carried by
|
||
// every UrbanBadgeConfig row keyed to a career the character owns, instead of relying on
|
||
// per-spirit hard-coding. "off" restores the old shape exactly.
|
||
//
|
||
func GameRouter_Profiles_JobBadgeBuffsEnabled(ctx context.Context, ) bool {
|
||
// Router implementation for GameRouter_Profiles_JobBadgeBuffsEnabled
|
||
return true
|
||
}
|
||
|
||
//
|
||
// Publishes the EonBug app's data backbone: SyncHackerJobInfo (64189208) —
|
||
// BBS handle + the full HackerPostConfig post list + rank + daily counters. Without this
|
||
// packet the app opens with rank "#-" and an empty forum (HackManager.HackerJobInfo stays
|
||
// nil) — exactly what the 7k donor ships, which is why its forum could never open.
|
||
// DTO path (wire re-verified against the lua reader, 2026-09-20): single class parameter,
|
||
// so the frame is [0xFF][fields] — same family as the battery packet. Reader[282] =
|
||
// HackerName -> PostInfos(ReadDict, raw Int32 count) -> Rank -> DailyCounts(Reader[852]:
|
||
// Money/Fan/Tetris). The old hand-written codec wrote 0x00 markers (SerializeObjectMarkNull
|
||
// = 0 — read as null) and omitted DailyCounts entirely.
|
||
//
|
||
func GameRouter_Profiles_PublishHackerJobRuntime4229938(ctx context.Context, rpcCtx *RpcContext, templateId uint32, phase string, handleOverride any) any {
|
||
// Router implementation for GameRouter_Profiles_PublishHackerJobRuntime4229938
|
||
var zero any; return zero
|
||
}
|
||
|
||
//
|
||
// 层 2a — publishes the police phone app's data backbone: SyncSpiritPoliceJobInfo
|
||
// (64349458), i.e. spiritId plus the whole SpiritPoliceJobInfo (duty counters, dispatch
|
||
// slots, live violations, case records, fake-file archive).
|
||
// Client path: GameToClientImpl.SyncSpiritPoliceJobInfo ->
|
||
// gPoliceJobManager.panelMgr:OnSpiritPoliceJobInfoSync (PolicePanelManager.lua:156),
|
||
// which indexes serviceData / weeklyServiceData / violationInfo / dispatchInfo / fakeFileInfo /
|
||
// caseInfo by spiritId and then dereferences DutyBasicInfo.ServiceData with no nil check.
|
||
// So the payload must exist and every complex field inside it must be non-nil, but the
|
||
// collections may legitimately be empty.
|
||
// ⛑️ There is no C2S "give me my police state" request — the whole SyncPolice* family is
|
||
// server-push, and this full snapshot is the one the panel treats as authoritative
|
||
// (SyncPoliceServiceData 64502222, SyncPoliceDispatchInfos 64393704,
|
||
// SyncSpiritPoliceViolationInfos 64812240 and SyncSpiritPoliceCaseInfos 64848107 are the
|
||
// incremental updates).
|
||
// Data-driven on the career class (UrbanJobJobClassConfig 11300003 "NCCA Officer"), so any
|
||
// character published with job 301/302/303 gets it — Richie (15021021) is the authored one.
|
||
// T4-9: the payload is no longer a set of empty containers. <see
|
||
// cref="RuntimePayloadFactory.PoliceJobInfo4229938"/> fills the dispatch chips, a small
|
||
// fabricated case history and the homepage tally out of real tables (PoliceDispatchConfig /
|
||
// PoliceFineConfig / AgentConfig / PoliceConfig.static), which is what makes the Duty Terminal
|
||
// render content instead of a blank panel. Violations and the Mimic Database archive stay empty
|
||
// on purpose — see that method for why.
|
||
//
|
||
func GameRouter_Profiles_PublishPoliceJobRuntime4229938(ctx context.Context, rpcCtx *RpcContext, templateId uint32, phase string) any {
|
||
// Router implementation for GameRouter_Profiles_PublishPoliceJobRuntime4229938
|
||
var zero any; return zero
|
||
}
|
||
|
||
//
|
||
// Republish the combat profile after a direct character switch.
|
||
// PublishCombatProfile is one-shot per world entry (its
|
||
// CombatProfilePublished gate exists so the deferred first-movement hydration cannot
|
||
// run twice), but every character owns a different skill set and the client learns the unique
|
||
// skill only from that profile. Clear the gate and run it again for the new character.
|
||
//
|
||
func GameRouter_Profiles_PublishCombatProfileOnSwitch4229938(ctx context.Context, rpcCtx *RpcContext, unitId uint64, templateId uint32) any {
|
||
// Router implementation for GameRouter_Profiles_PublishCombatProfileOnSwitch4229938
|
||
var zero any; return zero
|
||
}
|
||
|
||
//
|
||
// Publishes the character's authored urban job from FightSpiritConfig.DefaultUrbanJob
|
||
// so the client's job → badge → capability chain resolves on its own. Data-driven on purpose:
|
||
// every character with an authored job gets its record, not just Seymour (the donor build
|
||
// hard-codes three spirit ids, and gets one of them wrong).
|
||
// Only 8 of the 109 playable characters carry a job today; the rest are Jobless and are skipped
|
||
// — which is exactly the point: under the default UrbanJobGrantMode = "single" the
|
||
// career-locked phone apps stay character-exclusive (Seymour/赛默迪斯科球人 → EonBug,
|
||
// Richie → Duty Terminal + Mimic Database, Cheng Niang → 重霄食谱). Switch the config to
|
||
// "multi" to blanket-unlock all 9 apps on every character, or list template ids under
|
||
// UrbanJobOverrides to hand one specific character a career it was not authored with.
|
||
//
|
||
func GameRouter_Profiles_PublishSpiritJobRuntime4229938(ctx context.Context, rpcCtx *RpcContext, templateId uint32, phase string) any {
|
||
// Router implementation for GameRouter_Profiles_PublishSpiritJobRuntime4229938
|
||
var zero any; return zero
|
||
}
|
||
|
||
//
|
||
// Publishes the six-point hacker battery for characters whose authored job is Hacker(401).
|
||
// This is the missing half of the hacking kit on our side: HackerHackTypeConfig (48 rows)
|
||
// prices every hack in battery points, so with no battery the client greys out the middle-mouse
|
||
// hack verb and never emits AskHack — which in turn is the only other place we used to
|
||
// send the battery, so it could never recover on its own. The donor build publishes it from the
|
||
// buff snapshot path for exactly this reason.
|
||
// Data-driven on the same UrbanJobOf lookup as the capability buffs, so any character
|
||
// authored as job 401 gets it without touching a spirit id.
|
||
//
|
||
func GameRouter_Profiles_PublishHackerBatteryRuntime4229938(ctx context.Context, rpcCtx *RpcContext, templateId uint32, phase string) any {
|
||
// Router implementation for GameRouter_Profiles_PublishHackerBatteryRuntime4229938
|
||
var zero any; return zero
|
||
}
|
||
|
||
func GameRouter_Profiles_PublishInitialCapabilityBuffs(ctx context.Context, rpcCtx *RpcContext) any {
|
||
// Router implementation for GameRouter_Profiles_PublishInitialCapabilityBuffs
|
||
var zero any; return zero
|
||
}
|
||
|
||
//
|
||
// 主角原生飞索能力门 —— SyncPaokuLimitChange(68974941) + AbilityLimitConfig 3013。
|
||
// ★ 为什么要这一条(2026-09-26 调研,证据全在我们自己的 dump.cs):
|
||
// · AbilityLimitConfig.HasFeisuoAbility = 3013(dump.cs:1026235),
|
||
// 挂的 GamePlayTag 是 State_HasFeisuoAbility = 2318(dump.cs:1226889);
|
||
// 该配置行还带 ButtonEnum[](C 键)与 QueryId(有效目标查询)
|
||
// ⇒ 它是能力开关,不是「限制」。
|
||
// · 消费方 PlayerParkourLimitModule(dump.cs:585090-585135)的
|
||
// SetParkourLimitConfigState(uint limitId, bool isAdd) → SetGamePlayTagState。
|
||
// · 飞索 buff 一直在发,但本服所有日志里 feisuo 命中恒为 0 ⇒ 客户端
|
||
// 从来没进过飞索蹲伏态(AskEnterFeiSuoCrouch 一次都没发过)⇒ C 键没反应、没有白圈。
|
||
// ⛑⛑ unitId 必须是当前实际控制单位:切人后是新的那个。
|
||
// 上面 PublishInitialCapabilityBuffs 用的是 Profile.InitialUnitId(固定初始单位),
|
||
// 这里不能跟着写死 —— 否则切一次人门就挂在旧身体上(与规则 177 同源的坑)。
|
||
// ⛑ 白圈不用我们画:客户端 LX6.PaoKu.FeiSuoJobManager(dump.cs:242164)
|
||
// 每帧在本地扫静态/动态飞索点,门一开白圈自己出现。别去画假准星、别把任意墙面改成可飞跃点。
|
||
// ⛑ 回滚:gameplay.webTraversal.pushFeisuoAbilityGate = false。
|
||
// ⛑⛑ 2026-09-26 17:5x 补发暗杀门 5051:飞索门 3013 只解决「蹲得下去」,
|
||
// 暗杀检测由另一行 AbilityLimitConfig.UnlockAssassin = 5051
|
||
// (dump.cs:1026213 → State_UnlockAssassin = 1333,dump.cs:1226857)门控。
|
||
// 实机证据:只发 3013 时 AskEnterFeiSuoCrouch 命中 19 次、
|
||
// ReportCanAssassinateEnemies 命中 0 次 ⇒ 光补裁决回包没用,门必须先开。
|
||
// 两张门同表同构,走同一个 SyncPaokuLimitChange 的 limitIds 列表。
|
||
//
|
||
func GameRouter_Profiles_PublishProtagonistGrapnelGate4229938(ctx context.Context, rpcCtx *RpcContext, unitId uint64, templateId uint32) any {
|
||
// Router implementation for GameRouter_Profiles_PublishProtagonistGrapnelGate4229938
|
||
var zero any; return zero
|
||
}
|
||
|
||
//
|
||
// 角色专属能力门 —— 同一条 SyncPaokuLimitChange(68974941),一次可发多张
|
||
// AbilityLimitConfig.Id(gameplay.webTraversal.spiritAbilityGates)。
|
||
// 当前配置:15021040 璎珑 → 3040「虐杀原形跑酷」(ParkourState 10062,动作分支含地面
|
||
// 疾跑 574 / 跳跃 575 / 边缘 577 / 爬墙 2502·2503,所以平地按空格与 shift 都该有反应);
|
||
// 15020990 → 5040 连跳 + 5052 大跳。
|
||
// ★ 为什么不塞进 PublishProtagonistGrapnelGate4229938:那张方法有
|
||
// IsProtagonist 闸,会把所有非主角挡在门外;而这张门只该给璎珑一个人 ——
|
||
// 其余角色的 ABP 未必带 MovementModeType.Yinglong(10) 的动画数据,
|
||
// 挂上 tag 也可能没表现(甚至动作异常)。
|
||
// ⛑ 挂在 PublishCombatProfile 尾部 ⇒ 首次进入与切角色两条路径都覆盖
|
||
// (PublishCombatProfileOnSwitch4229938 先清一次性闸再跑一遍本方法,
|
||
// 此时 unitId/templateId 已经是新的控制单位)。
|
||
// ⛑ 切离璎珑时不补发 isAdd=false 摘门:切角色即换 unit,门是
|
||
// PlayerParkourLimitModule(unit module)上的状态,新单位本来就不带,
|
||
// 补一包只会是 no-op。真要摘就把开关关掉重进。
|
||
// ⛑ 回滚:gameplay.webTraversal.pushKillingAbilityGate = false。
|
||
//
|
||
func GameRouter_Profiles_PublishSpiritKillingGate4229938(ctx context.Context, rpcCtx *RpcContext, unitId uint64, templateId uint32) any {
|
||
// Router implementation for GameRouter_Profiles_PublishSpiritKillingGate4229938
|
||
var zero any; return zero
|
||
}
|
||
|
||
//
|
||
// One-shot combat profile per world entry: HP/attrs/urban/fight-style unlocks,
|
||
// skill charges, resources, battle module, weapon snapshot, skill bindings.
|
||
// Until this runs, OnClientUseSkill rejects skill requests (CombatProfilePublished).
|
||
// Runs on first gameplay movement (deferred hydration), mirroring the reference build.
|
||
//
|
||
func GameRouter_Profiles_PublishCombatProfile(ctx context.Context, rpcCtx *RpcContext, unitId uint64, templateId uint32) any {
|
||
// Router implementation for GameRouter_Profiles_PublishCombatProfile
|
||
var zero any; return zero
|
||
}
|
||
|