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

141 lines
8.9 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
//
// 五子棋**单机**(人机 / 残局)—— EnterGomokuZoneDoubleAI(67614971) 与
// EnterGomokuZoneEndGame(67341006)。
// <para>★ 现象与根因链(四刀,每一刀都有本机取证)</para>
// <list type="number">
// <item>R153 入口未登记:这两条从未进白名单 ⇒ 走 DefaultReturnCatalog4229938
// 兜底(:1611 / :1710)回 8 个 0x00 = **裸 u64 = 0**。客户端
// [warning]StartGomoke AI: TryGetLogicAgent fail, uid=0 /
// StartGomoke EndGame: TryGetLogicAgent fail, uid=0。
// ⇒ 必须登记并回一个**真实存在的**实体 uid。</item>
// <item>R155 只有 uid 装不下身份:SyncLogicAgentEnter 的 interop 签名只有一个 ulong,
// 而 LogicAgent.AgentConfigId 是 uint ⇒ 只注册 uid 会让客户端报
// 创建AgentUnit失败!AgentConfigId为0!。
// 唯一能送 AgentConfig 的通道是 **Aether 静态 NPC**(NpcFormworkId 就是 AgentConfig id),
// 而客户端在请求体第 2 个字段 agentid 里**自己把该填哪个告诉我们了**。</item>
// <item>R156 缺棋局状态推送(本轮真正卡住落子的那一刀):
// 客户端点子链是 TryRayIntersectBoard → PlaceGomokuPiece →
// AskPlaceGomokuPiece,而闸门是 GomokuManager.get_NowMyTurn();
// 唯一能置起"我的回合"的输入就是 SyncGameGroundZoneInfo(68004609)。
// 实测 AskPlaceGomokuPiece / PlaceGomokuPiece / SyncGameGroundZoneInfo
// 在全部历史日志里 **0 命中** ⇒ 客户端从没收到过 ⇒ 闸门恒关 ⇒ **一条落子包都不发**。</item>
// <item>R185 参与方列表不能为空:客户端靠 ipairs(zoneInfo.ParticipantInfos) 拿到
// pendingOpponentAgentId。推空列表 ⇒ 它永远是 0 ⇒ 闸门还是不开。
// 且列表元素是**多态**的,每个元素自带 1B tag = GomokuWire.ParticipantTagGomoku(12);
// 若用裸 [UxContract](默认 0xFF)会被 Dispatch 判成 undefined 分支全部丢弃。</item>
// </list>
// <para>★ 三步法与主线自己的 GameRouter.ChineseChess.cs(SpawnChineseChessAiAsync)
// **完全同形**(那里注释原话:"与五子棋 R153/R155/R157 三步完全同形"):
// ① SyncLogicAgentEnter 注册 uid → ② SendCivilianAsync 送 AgentConfig + 站位
// → ③ 把同一个 uid 回给客户端 / 写进 ParticipantInfos[].AgentInstanceId。</para>
// <para>⛑⛑ 不要加"等 NPC 落地"的延迟:象棋的实测证据是客户端
// TryGetOrConvertToUnit 查不到时**会等待**(10 秒后才打"等待服务器对手 NPC 单位超时"),
// 不是立刻失败 ⇒ 时序不是问题,缺的是状态推送。曾按"时序"假设加过延迟,方向是错的。</para>
// <para>契约 DTO 见 Drmk.RpcTypes/Client4229938/GomokuWireContracts.cs(文件头有逐字段的本机复核)。</para>
//
// ─────────────────────────────────────────────────────────────────────
// 两条单机入口
// ─────────────────────────────────────────────────────────────────────
//
// EnterGomokuZoneDoubleAI(67614971) 人机对战。
// C2S = u64 gadgetuid + u32 agentid + bool useblackpiece + byte difficulty + bool canuseskill。
// RET = **裸 u64**(对手实体的真实 uid)。
//
func GameRouter_GomokuSolo_EnterGomokuZoneDoubleAI4229938(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_GomokuSolo_EnterGomokuZoneDoubleAI4229938
var zero any; return zero
}
//
// EnterGomokuZoneEndGame(67341006) 残局。
// C2S = u64 gadgetuid + u32 agentid + u32 endgameid。RET = **裸 u64**(同上)。
// ⛑ 与 DoubleAI 的差别只有:请求里**没有** useBlack 字段 ⇒ 按残局约定「玩家先手 = 黑」。
//
func GameRouter_GomokuSolo_EnterGomokuZoneEndGame4229938(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_GomokuSolo_EnterGomokuZoneEndGame4229938
var zero any; return zero
}
// 把对手 uid 按「裸 u64」拼成 8 字节小端回给客户端。
func GameRouter_GomokuSolo_ReturnGomokuUidAsync(ctx context.Context, conn any, msg any, uid uint64) any {
// Router implementation for GameRouter_GomokuSolo_ReturnGomokuUidAsync
var zero any; return zero
}
// ─────────────────────────────────────────────────────────────────────
// ★★★ R156 核心:把「棋局已开始、现在轮到谁、对手是谁」推给客户端
// ─────────────────────────────────────────────────────────────────────
//
// 推 SyncGameGroundZoneInfo(68004609) + GomokuZoneInfo(多态 tag 13)。
// 这是「点棋盘没反应」与「能落子」之间缺的那一刀 —— 客户端 get_NowMyTurn()
// 的置位只有这一个输入来源。
// <para>★ 座位/先手(别与象棋的「颜色」混淆):五子棋 CurrentTurn 是 **SeatIndex 座位号**。
// GomokuWire.SeatIndexBlack = 0;客户端两个单机入口都 useBlack=true
// ⇒ 玩家 mySeatIndex = 0、黑棋先手 ⇒ CurrentTurn 必须是 0。
// 玩家 SeatIndex=0 / AI SeatIndex=1 / CurrentTurn=玩家座位 —— **三者必须自洽**,
// 写错任一个都是「点不动」。</para>
// <para>回滚 = 删两个 handler 里对本方法的调用(两行)。</para>
//
func GameRouter_GomokuSolo_PushGomokuZoneInfoAsync(ctx context.Context, conn any, gadgetUid uint64, gameType byte, aiUid uint64, playerUsesBlack bool) any {
// Router implementation for GameRouter_GomokuSolo_PushGomokuZoneInfoAsync
var zero any; return zero
}
// ─────────────────────────────────────────────────────────────────────
// 造对手 —— 三步法,与 GameRouter.ChineseChess.cs 的 SpawnChineseChessAiAsync 同形
// ─────────────────────────────────────────────────────────────────────
//
// 建一个「客户端查得到的 AI 对手」,返回它的**真实 uid**。三步:
// ① SyncLogicAgentEnter 注册 uid(客户端 TryGetLogicAgent 查的就是这张表);
// ② 用**客户端给的 agentId** 走 Aether 静态 NPC 通道(NpcFormworkId = AgentConfig id,
// 不送的话客户端建 Unit 时报 创建AgentUnit失败!AgentConfigId为0!);
// ③ 把同一个 uid 交回调用方(回包 + 写进 ParticipantInfos)。
// <para>★ R157 复用:**同一会话同一张桌只 spawn 一次**。理由(象棋同源注释原话):
// 「旧的那个删不掉(本版客户端无可靠删除通道)⇒ 场上越来越多」。
// 实测本仓 MethodId 里没有 SyncAetherAIStaticNpcRemove*;
// SyncRemoveNpc(68446556) 的 reader 是 Int32 ⇒ 装不下 830… 段的 u64。
// ⇒ 与其猜"怎么删",不如**根本不重复建**。</para>
// <para>缓存键带 gadgetUid(庙会区有多张 WuZiQi 桌,要各有一个对手,不能互相顶掉)。
// 作用域用 TcpSession.Items —— 断线即弃,不会泄漏到别的会话。</para>
//
func GameRouter_GomokuSolo_SpawnGomokuOpponentAsync(ctx context.Context, conn any, gadgetUid uint64, agentId uint32, playerUsesBlack bool, tag string, endGameId uint32) any {
// Router implementation for GameRouter_GomokuSolo_SpawnGomokuOpponentAsync
var zero any; return zero
}
//
// 挑对手模板:优先用客户端请求里带来的 agentId(实测 40131483「廖永强」),
// 它不在 NpcCatalog 里时才退回通用市民(骰子 PickDiceOpponentItem 同款挑法)。
//
func GameRouter_GomokuSolo_PickGomokuOpponentItem(ctx context.Context, agentId uint32) any {
// Router implementation for GameRouter_GomokuSolo_PickGomokuOpponentItem
var zero any; return zero
}
// 摊位表里离玩家最近的那个五子棋机关;表为空时返回 null。
func GameRouter_GomokuSolo_FindGomokuStall(ctx context.Context, px float32, pz float32) any {
// Router implementation for GameRouter_GomokuSolo_FindGomokuStall
var zero any; return zero
}
//
// 造 NPC 失败时的兜底 uid(骰子 FallbackUid 同款)。刻意不是 0 ——
// 0 会被客户端当成「进场失败」(套圈注释的判据),至少让它走到
// 「等待 Agent 实体同步」而不是当场判死,日志里也好区分。
//
func GameRouter_GomokuSolo_GomokuFallbackUid(ctx context.Context, ) uint64 {
// Router implementation for GameRouter_GomokuSolo_GomokuFallbackUid
return 0
}