This repository has been archived on 2026-10-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files

142 lines
8.0 KiB
Go
Raw Permalink Normal View History

package routers
import (
"context"
"sync"
)
var _ = sync.Mutex{}
var _ = context.Background
// Generic character switching. No protagonist-specific switch path lives here.
//
// 面板「切人演出」指定要播的那一条 SwitchSpiritConfig 行;0 = 照老规矩自己挑
// (距离 / DisperseAnchorsByCharacter / 权重)。
//
//
// true = 真的把切人演出(SyncPreSwitchSpirit / SyncSwitchSpiritConfigId)推出去了;
// false = 什么演出都没播(世界没就绪 / 上一次还 pending / 角色不在可控花名册 /
// 目标就是当前角色 / 演出开关关着 / 退化成静默换皮 / 锚点超限)。
// 面板「切人演出」卡靠这个返回值给玩家一句人话,而不是一律回「已播放」。
//
func GameRouter_Switching_OnSwitchSpirit(ctx context.Context, rpcCtx *RpcContext, requestedSpiritId uint32, allowShow bool, forcedSwitchShowId uint32) bool {
// Router implementation for GameRouter_Switching_OnSwitchSpirit
return true
}
//
// Phase 2:客户端播完 pre-switch Timeline。落点早已定好(见 OnSwitchSpirit),
// 这里只把控制权交给已经站在落点上的那个角色,不再把它挪回玩家发起切人时的位置。
//
func GameRouter_Switching_OnPreSwitchSpiritFinish(ctx context.Context, rpcCtx *RpcContext) any {
// Router implementation for GameRouter_Switching_OnPreSwitchSpiritFinish
var zero any; return zero
}
//
// 撤掉这出演出 spawn 出来的演员(WorldEntryState.PendingSwitchShowActors)。
// ⛑ 移除通道与召唤物一致:SyncLogicAgentLeave(68281244) —— 这类单位是
// SpawnAgentAsync 出来的,用 SyncAetherAINpcRemove(ambient 行人通道)发了等于没发。
// 幂等:列表清空后重复调用无副作用。
//
func GameRouter_Switching_DismissSwitchShowActorsAsync(ctx context.Context, rpcCtx *RpcContext, state any, why string) any {
// Router implementation for GameRouter_Switching_DismissSwitchShowActorsAsync
var zero any; return zero
}
// 演出没等到回执(丢包 / 客户端没播):按已定好的落点直接完成移交。
func GameRouter_Switching_CompleteSwitchWithoutTimelineAsync(ctx context.Context, rpcCtx *RpcContext, state any, reason string) any {
// Router implementation for GameRouter_Switching_CompleteSwitchWithoutTimelineAsync
var zero any; return zero
}
func GameRouter_Switching_ClearPendingSwitch(ctx context.Context, state any) any {
// Router implementation for GameRouter_Switching_ClearPendingSwitch
var zero any; return zero
}
//
// Server-driven character switch, used by the admin panel instead of the in-game wheel.
// The wheel (Z) is client-side only: it lists FightSpiritConfig rows whose CanJoin is true
// (15 of 40 here) and switching from it never tells the server anything. Publishing a
// SyncTaskRoleTeam roster cannot widen it either — a non-empty team greys out every entry the
// team does not name (see TOPIC_切换角色.md §6), which is worse than leaving it alone.
// So the panel drives OnSwitchSpirit directly: same handoff the client's own
// AskSwitchSpirit takes, but without the client having to offer the character first. That
// means every roster row is reachable, including the CanJoin=false ones (Bansy, Aileen,
// Mimiko, Ringo, ...) and rows kept out of the roster by the placeholder-icon filter until
// they are added through content.roster.additionalTemplateIds (15021042 Lemon Sour).
//
func GameRouter_Switching_SwitchSpiritAsync(ctx context.Context, session *GameSession, spiritId uint32) any {
// Router implementation for GameRouter_Switching_SwitchSpiritAsync
var zero any; return zero
}
//
// 面板「切人演出」卡片专用:**指定**要播的那一条 SwitchSpiritConfig 行。
// ⛑ 与上面的 SwitchSpiritAsync 唯一的区别就是 allowShow:true +
// forcedSwitchShowId —— 那条是「静默换皮」(面板挑人用),这条是「播演出」
// (会发 SyncPreSwitchSpirit / SyncSwitchSpiritConfigId,并把玩家落到该行的 Position 锚点)。
// ⛑ 201 行里 AgentId 非空的行服务端这条链路补不出随从(见 ClientConfigRepository 注释),
// 面板默认不列这类行;真指定了也只是演出里少了那几个陪衬角色,不会崩。
//
func GameRouter_Switching_SwitchSpiritWithShowAsync(ctx context.Context, session *GameSession, spiritId uint32, switchShowId uint32) any {
// Router implementation for GameRouter_Switching_SwitchSpiritWithShowAsync
var zero any; return zero
}
//
// 客户端 GM 控制台的「就地切人」:GmSwitchSpiritHere(69758035),
// 参数是 uint32 的 FightSpirit id(ClientToGameSceneGMDelegate.lua:2132)。
// 抓包样本(logs/unknown-methods.log):hex=D337E500 → 15020499、
// hex=2C7D6402、hex=00000000。共 3 次 INVOKE,此前一直是
// unimplemented —— 控制台按下去只回一个空 ack,什么都不会发生。
// ⛑ 这是客户端自己的原生入口(GM 面板 324 个方法之一),不是我们造的:
// 它证明官方确实有一条「不播演出、就地换人」的切人路径。接上它等于拿到一条
// 完全原生的切人通道,可以拿来跟 AskSwitchSpirit 那条 14 秒演出路径做对照。
// "Here" = 就地:走与 AskSwitchSpirit 完全相同的身份移交,但
// allowShow:false ⇒ 不发 SyncPreSwitchSpirit / SyncSwitchSpiritConfigId,
// 不播 LiftOff 演出、不传送到演出锚点(换皮 + 原地移交)。
//
func GameRouter_Switching_GmSwitchSpiritHere(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_Switching_GmSwitchSpiritHere
var zero any; return zero
}
//
// Publish the character-wheel roster through SyncTaskRoleTeam (64534724).
// Pressing Z sends nothing to the server — the rotation list is built entirely client-side, and
// because retail never called this method the client has always used its own fallback: the
// FightSpiritConfig rows with CanJoin=true (exactly the 15 characters the player sees, including
// Yinglong but not Mimiko). This notify is the one server-side handle on that list
// (SpiritManager.lua:233 <- GameToClientImpl.lua:2311 fills taskRoleTeam from enableRoleIds).
// Opt-in only: an empty roster config means nothing is sent and the client keeps its default.
// Non-empty takes the list over wholesale, so anything to keep has to be listed too.
// Re-published on every scene load because lua does table.clear + refill — it is idempotent by
// design, and re-sending is how the list survives a scene change.
//
func GameRouter_Switching_PublishSwitchRoleTeamAsync(ctx context.Context, rpcCtx *RpcContext) any {
// Router implementation for GameRouter_Switching_PublishSwitchRoleTeamAsync
var zero any; return zero
}
func GameRouter_Switching_SwitchSpiritDirectSameScene4229938(ctx context.Context, rpcCtx *RpcContext, state any, templateId uint32, unitId uint64, switchPosition Vec3, switchFacing float32, switchShowId uint32, targetInWorld bool) any {
// Router implementation for GameRouter_Switching_SwitchSpiritDirectSameScene4229938
var zero any; return zero
}
//
// ★ AskSwitchSpiritComplete(67272187) —— 客户端「整条切人演出播完了」的回执。
// ⛑⛑ 以前它是**空转**的:`GameRouter.UnhandledBatch.cs` 把它挂在 SkillNeutralAccepts
// 那个「只打一行 [COMBAT] accept 就 ReturnEmptyOkAsync」的兜底处理器上
// ⇒ 演出到底播没播完、播了多久,服务端完全不知道(09-26 00:2x 评估 CBT3 资料时发现的盲区)。
// CBT3 那份 `切人传送时机_apex传送实现.md` 用它标定 apexDelay;我们现在没有 apex 传送,
// 但这条时间戳本身就是「演出真实时长」的唯一实测来源 —— 先记下来,别再丢。
// ⛑ 客户端在切人流程里一共只发两个 C2S:这个 + ReportPreSwitchSpiritFinish(67654364)。
// ReportPreTeleportFinish(63032762) **不发**(那是传送流程的),别拿它当切人信号。
//
func GameRouter_Switching_AskSwitchSpiritComplete(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_Switching_AskSwitchSpiritComplete
var zero any; return zero
}