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

143 lines
8.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}