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

98 lines
5.0 KiB
Go
Raw Permalink Normal View History

package routers
import (
"context"
"sync"
)
var _ = sync.Mutex{}
var _ = context.Background
//
// 巡卫官(里希 / 15021021)盘查链路的最后一步 —— 开罚单出结果。
// <code>
// 客户端 PoliceExamineManager.lua:1163 gPoliceJobManager.cs:AskPoliceFine(pid, fineIdList)
// ⇒ C2S AskPoliceFineNpc(63548238)
// ⇒ 服务端必须回 S2C ShowReceiveRewardDetail(64145515) 且 Reason == ItemReason.PoliceFine(180001)
// ⇒ GameToClientImpl.lua:266 gPoliceJobManager:OnDropPoliceJobExp(msg.Reward)
// ⇒ PoliceExamineManager.lua:618 填 fineMoney / JobExpInfo
// ⇒ PoliceExamineManager.lua:601 ShowFineResult(罚款结果面板)
// </code>
// ⛑⛑ 为什么之前"开罚单没结果":AskPoliceFineNpc 既没进
// Enabled4229938MethodIds(硬规则 94)也没 handler ⇒ 客户端 await 卡死,
// 服务端从来没回过掉落帧 ⇒ needShowFineResult=true 但 OnDropPoliceJobExp
// 永远不触发 ⇒ ShowFineResult 一次都没被调用。
// ⛑ 反编译陷阱(又是同一条,见已作废结论):
// GameToClientImpl.lua:266 里写的是 if msg.Reason ~= ItemReason.PoliceFine then,
// 字面读是"非罚款才回调",但同一函数里 if msg.Reason ~= Mall or msg.Reason ~= MallBundle
// 恒为真会无条件 return ⇒ 字面读整段逻辑自相矛盾 ⇒ 反编译器把 == 翻成了 ~=。
// 真意:Reason == PoliceFine 时才走 OnDropPoliceJobExp。
// ItemReason.PoliceFine = 180001(dump.cs:1737137,enum ItemReason TypeDefIndex:32206)。
// 回滚 = 删本文件 + 从 GameRouter.cs 白名单删掉 MethodId.AskPoliceFineNpc。
//
// =================================================================================
// ① C2S AskPoliceFineNpc(63548238)
// =================================================================================
//
// 玩家在盘查面板里选完罪名、点「开罚单」时由 C# 侧发出来的那条。
// 形状:AskPoliceFine(ulong pid, object data)(dump.cs:673124),data 是 int[]。
// 极性 CSharpOnly ⇒ lua 没有 writer 可抄、count 编码不确定 ⇒ 不硬解析,
// 只把前 8 字节当 u64 pid 记日志,其余原样打 hex 留作取证。
// ⛑ 用 HandlerPacketKind.Both:INVOKE / NOTIFY 都不能漏。
// INVOKE 不回执 ⇒ 客户端 await 到超时(硬规则 94 的同一类坑)。
//
func GameRouter_PoliceFine_AskPoliceFineNpc(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_PoliceFine_AskPoliceFineNpc
var zero any; return zero
}
// =================================================================================
// ② S2C ShowReceiveRewardDetail(64145515) —— 手搓字节
// =================================================================================
//
// 推一帧 ShowReceiveRewardDetail(64145515, LuaOnly),Reason = PoliceFine(180001)。
// 载荷(照 Auto.Reader[308] / Auto.Reader[500],RPCDeserializeAuto.lua:37641 / 37521):
// <code>
// int32 Reason = 180001
// uint32 RewardTemplate = 0
// list FirstItemInfo = FF + int32 count + uint32* (空)
// cplx ExtraInfo = 00(null —— 必须 null!DropManager.lua:126 见 ExtraInfo 非空
// 就会拿 ExtraInfo.Pos 判"掉落物在地上"并 return,罚款结果就没了)
// dict Reward = FF + int32 count + { byte key, cplx RewardDetail }
// </code>
// RewardDetail(Reader[500])28 个字段全按声明顺序写,空的集合一律 FF + int32 0
// (Serializer.ReadList / ReadDict = peek byte FF + 原始 int32 count,不带 +1 偏置;
// 只有 ReadList7Bit / ReadDict7Bit 才走 Int7 +1 偏置)。
// SpiritTalentExpInfo 是 ReadComplex ⇒ 写 00。
// ⛑⛑ 关键判据(PoliceExamineManager.lua:618):
// <code>
// fineMoney = Σ RewardDetail.Money
// if RewardDetail.JobExpInfo[Police] then JobExpInfo = RewardDetail.JobExpInfo end
// if JobExpInfo or fineMoney &lt;= 0 then ShowFineResult() end
// </code>
// ⇒ JobExpInfo 里必须命中 Police(11300003),否则 money&gt;0 时永远不弹。
// 所以这里 money 与 exp 都给,双保险。
//
func GameRouter_PoliceFine_PushFineRewardAsync(ctx context.Context, session *GameSession, money float64, jobExp uint32, token context.Context) any {
// Router implementation for GameRouter_PoliceFine_PushFineRewardAsync
var zero any; return zero
}
// 照 Auto.Reader[308] / Auto.Reader[500] 手搓 ShowReceiveRewardDetail。
func GameRouter_PoliceFine_BuildFineRewardWire(ctx context.Context, money float64, jobExp uint32) []byte {
// Router implementation for GameRouter_PoliceFine_BuildFineRewardWire
return nil
}
// Serializer.ReadList 的空集合:peek FF + 原始 int32 count = 0。
func GameRouter_PoliceFine_EmptyList(ctx context.Context, w any) any {
// Router implementation for GameRouter_PoliceFine_EmptyList
var zero any; return zero
}
// Serializer.ReadDict 的空字典:peek FF + 原始 int32 count = 0。
func GameRouter_PoliceFine_EmptyDict(ctx context.Context, w any) any {
// Router implementation for GameRouter_PoliceFine_EmptyDict
var zero any; return zero
}