222 lines
9.7 KiB
Go
222 lines
9.7 KiB
Go
package routers
|
||||
|
|
|
|||
|
|
import (
|
|||
|
|
"context"
|
|||
|
|
"sync"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
var _ = sync.Mutex{}
|
|||
|
|
var _ = context.Background
|
|||
|
|
|
|||
|
|
//
|
|||
|
|
// 钓鱼玩法(build 4229938)—— 从零接上服务端链路。
|
|||
|
|
// 原版链路(已用 dump.cs + 代理解码器 RPCDeserializeAuto.lua 坐实):
|
|||
|
|
// 走近钓点 → 客户端发 AskFishingSpotFullSync(fishGroupId) 拉鱼池
|
|||
|
|
// → 服务端回 SyncFishingSpotFull(Reader[335]) 推全量鱼池
|
|||
|
|
// → 交互跑 PlayFishingGameAction 小游戏
|
|||
|
|
// → 成功触发 OnFishingSuccess → 客户端发 AskFishingSuccess(fishGroupId, fishId) 记账
|
|||
|
|
// → 百科全书用 SyncFishAdd(Reader[277]) 登记。
|
|||
|
|
// 线格式铁律(UxContract.cs):复杂体只先写 TypeMark 字节(默认 0xFF)再按声明顺序写公共字段,
|
|||
|
|
// 客户端代理端 Auto.Reader[N] 的 N 只是解码索引、对线路字节无意义。所以下面每个 wire DTO 只要
|
|||
|
|
// 「字段顺序 / 类型」对齐代理的 Reader[335]/[338]/[277]/[347] 即可,类名无关。
|
|||
|
|
// 鱼池种子数据 100% 来自真实配置(FishingSpotConfig / FishingFishGroupConfig / FishingFishConfig),
|
|||
|
|
// 已复制进 ClientData/4229938/Configs/。客户端传什么 fishGroupId 都能接:
|
|||
|
|
// - 命中 FishingFishGroupConfig 的组号(1/2) → 用它的 InitGroup(短 id → 10105000+id)
|
|||
|
|
// - 命中 FishingSpotConfig 的 spot id(10105150…) → 用它的 InitGroup(已是全 id)
|
|||
|
|
// - 都不中 → 退回一套通用鱼,保证客户端永远有鱼可钓。
|
|||
|
|
//
|
|||
|
|
// ═══════════════════════════ 常驻:拉鱼池 ═══════════════════════════
|
|||
|
|
func GameRouter_Fishing_AskFishingSpotFullSync(ctx context.Context, conn any, msg any) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_AskFishingSpotFullSync
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ═══════════════════════════ 常驻:钓上鱼记账 ═══════════════════════════
|
|||
|
|
func GameRouter_Fishing_AskFishingSuccess(ctx context.Context, conn any, msg any) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_AskFishingSuccess
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GameRouter_Fishing_TryRecordCatch(ctx context.Context, state any, fishGroupId uint32, fishId uint32, uniqueId uint32, templateId uint32, weight float32, length float32) bool {
|
|||
|
|
// Router implementation for GameRouter_Fishing_TryRecordCatch
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ═══════════════════════════ GM:发 / 收钓竿 ═══════════════════════════
|
|||
|
|
func GameRouter_Fishing_GmAddFishingGear(ctx context.Context, conn any, msg any) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_GmAddFishingGear
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GameRouter_Fishing_GmRemoveFishingGear(ctx context.Context, conn any, msg any) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_GmRemoveFishingGear
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ═══════════════════════════ GM:钓点 / 鱼池维护 ═══════════════════════════
|
|||
|
|
func GameRouter_Fishing_GmInitFishingSpot(ctx context.Context, conn any, msg any) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_GmInitFishingSpot
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GameRouter_Fishing_GmSpawnFishingSpotFish(ctx context.Context, conn any, msg any) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_GmSpawnFishingSpotFish
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GameRouter_Fishing_GmResetAllFishingSpots(ctx context.Context, conn any, msg any) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_GmResetAllFishingSpots
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GameRouter_Fishing_GmClearFishing(ctx context.Context, conn any, msg any) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_GmClearFishing
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ═══════════════════════════ GM:百科全书灌全鱼 ═══════════════════════════
|
|||
|
|
func GameRouter_Fishing_GmAddAllFishes(ctx context.Context, conn any, msg any) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_GmAddAllFishes
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ═══════════════════════════ GM:强制记一笔钓获 ═══════════════════════════
|
|||
|
|
func GameRouter_Fishing_GmOnFishingSuccess(ctx context.Context, conn any, msg any) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_GmOnFishingSuccess
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ═══════════════════════════ GM:调试查看(有 string 返回) ═══════════════════════════
|
|||
|
|
// ⛑⛑ 2026-09-29 修正:这两条**不是 void**,客户端
|
|||
|
|
// `midToReturnMessageReader[GmViewFishingSpot/GmViewFishingInfo]` 都是
|
|||
|
|
// `reader.ReadString(reader)`(裸 string)。原来 `ReturnEmptyOkAsync` 是 **0 字节载荷**
|
|||
|
|
// (Connection.cs:32 `Array.Empty<byte>()`)⇒ 客户端读空 buffer,GM 面板什么都看不到。
|
|||
|
|
// 实测 [FISHING] 一轮 9 次(一直在点)。现在把已经拼好的 dump **真的回给客户端**。
|
|||
|
|
// wire:`UxWriter.UxString` —— null 写 0x00,有值写 `VarInt(len+1)` + UTF8(空串 = 0x01)。
|
|||
|
|
// ⛑ 回滚:把 return 换回 `await conn.ReturnEmptyOkAsync(msg)` + 签名改回 `async Task`。
|
|||
|
|
func GameRouter_Fishing_GmViewFishingSpot(ctx context.Context, conn any, msg any) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_GmViewFishingSpot
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GameRouter_Fishing_GmViewFishingInfo(ctx context.Context, conn any, msg any) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_GmViewFishingInfo
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── wire DTO:字段顺序严格对齐代理 Reader[335] / [338] / [277] / [347] ──────────────────────
|
|||
|
|
type FishingSpotFullSyncPayload4229938 struct {
|
|||
|
|
FishGroupId uint32 `json:"fishGroupId"`
|
|||
|
|
Fishes []FishingSpotFishWire4229938 `json:"fishes"`
|
|||
|
|
LastRefreshTime uint32 `json:"lastRefreshTime"`
|
|||
|
|
LastResetTime uint32 `json:"lastResetTime"`
|
|||
|
|
MaxCount uint32 `json:"maxCount"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
type FishingSpotFishWire4229938 struct {
|
|||
|
|
Id uint32 `json:"id"`
|
|||
|
|
FishConfigId uint32 `json:"fishConfigId"`
|
|||
|
|
Weight float32 `json:"weight"`
|
|||
|
|
Length float32 `json:"length"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
type FishingFishAddWire4229938 struct {
|
|||
|
|
UniqueId uint32 `json:"uniqueId"`
|
|||
|
|
TemplateId uint32 `json:"templateId"`
|
|||
|
|
Weight float32 `json:"weight"`
|
|||
|
|
Length float32 `json:"length"`
|
|||
|
|
IsPlaced bool `json:"isPlaced"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
type FishingGearWire4229938 struct {
|
|||
|
|
UniqueId uint32 `json:"uniqueId"`
|
|||
|
|
TemplateId uint32 `json:"templateId"`
|
|||
|
|
RemainingDurability uint32 `json:"remainingDurability"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//
|
|||
|
|
// 钓鱼配置目录(懒加载一次)。读真实 JSON(FishingSpotConfig / FishingFishGroupConfig /
|
|||
|
|
// FishingFishConfig),找不到文件就退化为通用鱼池,绝不让钓鱼链路崩。
|
|||
|
|
//
|
|||
|
|
type FishingCatalog4229938 struct {
|
|||
|
|
Spots map[uint32]FishingSpotRec `json:"spots"`
|
|||
|
|
Groups map[uint32]FishingGroupRec `json:"groups"`
|
|||
|
|
AllFishIdsField []uint32 `json:"allFishIdsField"`
|
|||
|
|
// fishId → (NormalWeight 克, NormalLength 厘米),取自 FishingFishConfig,用于生成贴近原版的体重/体长。
|
|||
|
|
FishBody map[uint32]any `json:"fishBody"`
|
|||
|
|
Rng any `json:"rng"`
|
|||
|
|
Gate any `json:"gate"`
|
|||
|
|
AllFishIds []uint32 `json:"allFishIds"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GameRouter_Fishing_NowUnix(ctx context.Context, ) uint32 {
|
|||
|
|
// Router implementation for GameRouter_Fishing_NowUnix
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GameRouter_Fishing_EnsurePool(ctx context.Context, state any, fishGroupId uint32) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_EnsurePool
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GameRouter_Fishing_GetOrCreatePool(ctx context.Context, state any, fishGroupId uint32) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_GetOrCreatePool
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GameRouter_Fishing_PickFishConfigId(ctx context.Context, ) uint32 {
|
|||
|
|
// Router implementation for GameRouter_Fishing_PickFishConfigId
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GameRouter_Fishing_BuildPool(ctx context.Context, fishGroupId uint32) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_BuildPool
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// FishingFishGroupConfig 用的是短 id(2/10/3/7…),补成全 id(10105002…);已是全 id 的不动。
|
|||
|
|
func GameRouter_Fishing_NormalizeFishId(ctx context.Context, raw uint32) uint32 {
|
|||
|
|
// Router implementation for GameRouter_Fishing_NormalizeFishId
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//
|
|||
|
|
// 宽容 uint 读取:客户端导出的 JSON 里数字字段混用 number / string(如 "FishId": "2"、
|
|||
|
|
// "Id": 10105001),直接 GetUInt32() 会在 string 上抛 InvalidOperationException。
|
|||
|
|
//
|
|||
|
|
func GameRouter_Fishing_ReadUIntEl(ctx context.Context, el any) uint32 {
|
|||
|
|
// Router implementation for GameRouter_Fishing_ReadUIntEl
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GameRouter_Fishing_LoadSpots(ctx context.Context, path string) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_LoadSpots
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GameRouter_Fishing_LoadGroups(ctx context.Context, path string) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_LoadGroups
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GameRouter_Fishing_LoadFish(ctx context.Context, path string) any {
|
|||
|
|
// Router implementation for GameRouter_Fishing_LoadFish
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
type FishingInitGroup struct {
|
|||
|
|
FishId uint32 `json:"fishId"`
|
|||
|
|
Num uint32 `json:"num"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
type FishingSpotRec struct {
|
|||
|
|
Id uint32 `json:"id"`
|
|||
|
|
InitGroup []FishingInitGroup `json:"initGroup"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
type FishingGroupRec struct {
|
|||
|
|
Id uint32 `json:"id"`
|
|||
|
|
MaxCount uint32 `json:"maxCount"`
|
|||
|
|
InitGroup []FishingInitGroup `json:"initGroup"`
|
|||
|
|
}
|
|||
|
|
|