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
Ananta-ps/internal/gameserver/routers/game_router_npc_chat.go
T

143 lines
7.3 KiB
Go
Raw Normal View History

package routers
import (
"context"
"sync"
)
var _ = sync.Mutex{}
var _ = context.Background
//
// BBChat — AppId 27 "Message" (SystemId 146), the phone's NPC chat app. It is NOT the player IM:
// its red dot comes from gRedDotUtils.CheckNpcChatHasRedDot() (MainPhoneUtils.lua:688) and
// its panels are the NpcChat* stores, i.e. everything here is gNpcChatManager.
// Content half: the conversation list is published by the login frame
// (InfoNpcCultivation.NpcChats / NpcGroupChats, see RuntimePayloadFactory.FillNpcChats
// and NpcChatCatalog4229938). Nothing here refills it — there is no pull request for that list.
// Interaction half: every request below carries exactly one u32 (chatid) and the client
// declares no reply reader for any of them (no midToReader entry in RPCDeserializeAuto for
// 63013781 / 63098840 / 63137850 / 63203620 / 63266674 / 63082065), so the answer must be the
// empty OK — anything else desynchronises nothing the client reads but wastes bytes. What actually
// moves a conversation is the SyncNpcChat push: the next row of NPCChatConfig.
// ⛑ The server owns no chat text. A row is "which config id is unlocked next"; the client resolves
// speaker, side, avatar and body itself via LTConfig.NPCChatConfig.GetConfig(chatItem.ChatId)
// (NpcChatUtils.NewFromNpcChatItem), which drops any id it does not know with a
// "NPCChat表没有查到" error — hence NextChatId always comes from the catalogue's own map.
//
// Leading u32 of every request body here.
func GameRouter_NpcChat_NpcChatRequestId(ctx context.Context, msg any) uint32 {
// Router implementation for GameRouter_NpcChat_NpcChatRequestId
return 0
}
// =================================================================================
// Advancing a conversation
//
// Three different requests do the same thing from three different entry points, and all of them
// mean "take the given row's NextMessage[0] and hand it to the client":
// InteractNpcChat(63098840) NpcChatChattingPanelStore.lua:1035/1055 — tap to continue
// ChatToNpc(63013781) :1169 — the player picked an authored reply
// InviteNpcChat(63137850) :1142 — the player accepted an invite row
// The client arms a timeout before sending (StartChatTimeout) and clears it when the push lands,
// so pushing nothing would leave the panel spinning for its timeout window; pushing the same row
// back would be worse, hence the explicit unknown-row branch below.
// =================================================================================
func GameRouter_NpcChat_InteractNpcChat(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_NpcChat_InteractNpcChat
var zero any; return zero
}
func GameRouter_NpcChat_ChatToNpc(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_NpcChat_ChatToNpc
var zero any; return zero
}
func GameRouter_NpcChat_InviteNpcChat(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_NpcChat_InviteNpcChat
var zero any; return zero
}
func GameRouter_NpcChat_AdvanceNpcChatAsync(ctx context.Context, conn any, msg any, via string) any {
// Router implementation for GameRouter_NpcChat_AdvanceNpcChatAsync
var zero any; return zero
}
//
// InteractNpcChatToEnd(63203620) — "skip to the end" button. The whole remaining tail of the
// thread is pushed as one burst so the panel can render it as history.
// Capped at NpcChatSkipBatch rows: the rows are pushed one SyncNpcChat at a time
// because that is the only framing the client reads for this, and a 60-message thread would
// otherwise hold the gesture hostage for a full row-by-row animation queue.
//
func GameRouter_NpcChat_InteractNpcChatToEnd(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_NpcChat_InteractNpcChatToEnd
var zero any; return zero
}
// =================================================================================
// Bookkeeping requests — nothing persists, everything answers OK
// =================================================================================
// AskMarkNpcChatRead(63266674) — NpcChatChattingPanelStore.lua:132/818, NpcChatN2NChattingPanel.lua:217.
func GameRouter_NpcChat_AskMarkNpcChatRead(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_NpcChat_AskMarkNpcChatRead
var zero any; return zero
}
//
// RequestNpcChatList(63082065) — ChatNpcsPhoneManager.lua:229 / ChattingToNpcPanelStore.lua:375.
// Used by the GM "pull this conversation" route; the player-facing list already arrived in the
// login frame, so there is nothing to stream back — **but the reply still has a shape**:
// ⛑⛑ 2026-09-29 修正:客户端 `midToReturnMessageReader[63082065]` 是
// `Base.ReadList7Bit(reader, …Complex[372])`,即 RET 是 **List<T> 而不是 void**。
// 原来 `ReturnEmptyOkAsync` 是 **0 字节载荷**(Connection.cs:32 `Array.Empty<byte>()`)
// ⇒ 客户端 reader 读不到 presence 字节。实测 [NPCCHAT] 有触发(今日累计 2 次)。
// ⇒ 回**空列表** `FF 01`(0xFF=presence,0x01=Int7(0) 的 +1 偏置,硬规则"空列表 2B")。
// 数据本身仍为空(列表确实走登录包),但 wire 形状正确,客户端不会读空 buffer。
// ⛑ 回滚:把 return 换回 `conn.ReturnEmptyOkAsync(msg)`。
//
func GameRouter_NpcChat_RequestNpcChatList(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_NpcChat_RequestNpcChatList
var zero any; return zero
}
// AskCloseNpcChatWnd(67994672) — NpcChatChattingPanelStore.lua:635/1240, sent on the scene delegate.
func GameRouter_NpcChat_AskCloseNpcChatWnd(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_NpcChat_AskCloseNpcChatWnd
var zero any; return zero
}
// AskClearSpiritGroupChat(63527240) / AskClearNpcUncompletedInviteChat(63639364) — one-shot cleanups.
func GameRouter_NpcChat_AskClearSpiritGroupChat(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_NpcChat_AskClearSpiritGroupChat
var zero any; return zero
}
func GameRouter_NpcChat_AskClearNpcUncompletedInviteChat(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_NpcChat_AskClearNpcUncompletedInviteChat
var zero any; return zero
}
// =================================================================================
// Row construction
// =================================================================================
//
// One pushed/downloaded history row. Field order and the complex root come from the client's own
// reader — Auto.Reader[372] read via Base.ReadComplex, so the push starts with a
// 0xFF marker and no other framing is involved.
//
func GameRouter_NpcChat_BuildNpcChatItem(ctx context.Context, chatId uint32, fromChatId uint32, read bool) any {
// Router implementation for GameRouter_NpcChat_BuildNpcChatItem
var zero any; return zero
}
//
// Best-effort owner for a pushed row. The catalogue only stores owners for published threads, so
// anything else falls back to the owner of the row the player came from — what really matters is
// that it is non-zero and stable for a conversation, because it becomes the dictionary key.
//
func GameRouter_NpcChat_OwnerOf(ctx context.Context, chatId uint32, fromChatId uint32) uint32 {
// Router implementation for GameRouter_NpcChat_OwnerOf
return 0
}