DNF90 服务端与启动器完整源码(含 GM 工具功能增强)
服务端(Go): - GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面 - GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新 - 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新) - 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍 - 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0) - 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算 启动器(Python/JS): - 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭 - GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐) - 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
This commit is contained in:
commit
645b64fe21
4388 files changed
+1405457
No files matched your search
@@ -0,0 +1,65 @@
|
||||
package dnfbridge
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"longheng.io/server/internal/modules/dnf/channelcatalog"
|
||||
dnfproto "longheng.io/server/internal/modules/dnf/protocol"
|
||||
)
|
||||
|
||||
// 这两个慢请求诊断事件是现网延迟排查的唯一手段:玩家侧无法复现,只能靠服务器
|
||||
// 自己把超过门限的请求记下来。因此必须锁死「事件不会被 suppressPacketLogEvent
|
||||
// 静默丢弃」这一条。
|
||||
//
|
||||
// 关键点:本测试调用的是**生产代码同一个字段构造函数**(slowUpperRequestFields /
|
||||
// slowLegacyRequestFields),而不是照抄一份字段列表。照抄的版本改坏线上代码也不会
|
||||
// 失败——这一点已用 mutation test 实测验证过,所以字段定义必须共用。
|
||||
//
|
||||
// 曾经踩过的坑:字段名用过 "msg_id",而 suppressPacketLogEvent 会按 msg_id 命中
|
||||
// 1276/1516/1518 直接返回 true;那三个恰恰是最可能变慢的高频 opcode,等于诊断在
|
||||
// 最需要的时候哑火。
|
||||
func TestSlowRequestDiagnosticEventsAreNotSuppressed(t *testing.T) {
|
||||
session := &gameSession{connID: "game-000001", channel: channelcatalog.Channel{ID: 93}}
|
||||
|
||||
// game-slow-upper-request:含最高风险的 1276/1516/1518 与 msg_id 13。
|
||||
for _, riskyMsgID := range []uint16{1276, 1516, 1518, 13, 4, 476, 1, 593} {
|
||||
packet := dnfproto.ChannelPacket{
|
||||
Header: dnfproto.ChannelHeader{MsgID: riskyMsgID, Classification: 1, Seq: 7},
|
||||
Body: []byte{1, 2, 3},
|
||||
}
|
||||
fields := slowUpperRequestFields(session, packet, "ENUM_CMDPACKET_TEST", true, 3, 250*time.Millisecond)
|
||||
if suppressPacketLogEvent("game-slow-upper-request", fields...) {
|
||||
t.Fatalf("game-slow-upper-request 被抑制(request_msg_id=%d);诊断会哑火", riskyMsgID)
|
||||
}
|
||||
}
|
||||
|
||||
// game-slow-legacy-request:含 type 35(被抑制的 legacy-meta 值)与进游戏主力的 8/197。
|
||||
for _, riskyType := range []uint16{35, 8, 197, 1425, 1345, 4} {
|
||||
fields := slowLegacyRequestFields(session, byte(1), riskyType, 16, 250*time.Millisecond)
|
||||
if suppressPacketLogEvent("game-slow-legacy-request", fields...) {
|
||||
t.Fatalf("game-slow-legacy-request 被抑制(request_type=%d);诊断会哑火", riskyType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 反向确认:抑制规则本身仍然生效,本测试不是靠「suppressPacketLogEvent 永远
|
||||
// 返回 false」蒙过去的。
|
||||
func TestSuppressionRulesStillApplyToKnownChattyEvents(t *testing.T) {
|
||||
if !suppressPacketLogEvent("game-upper-send-meta", "msg_id", uint16(1276)) {
|
||||
t.Fatal("msg_id 1276 的 game-upper-send-meta 应仍被抑制")
|
||||
}
|
||||
if !suppressPacketLogEvent("game-upper-send-meta", "msg_id", uint16(13)) {
|
||||
t.Fatal("msg_id 13 的 game-upper-send-meta 应仍被抑制")
|
||||
}
|
||||
if !suppressPacketLogEvent("game-legacy-meta", "type", uint16(35)) {
|
||||
t.Fatal("type 35 的 game-legacy-meta 应仍被抑制")
|
||||
}
|
||||
if !suppressPacketLogEvent("game-town-set-user-position-captured") {
|
||||
t.Fatal("game-town-set-user-position-captured 应仍被抑制")
|
||||
}
|
||||
// 证明抑制是靠 "msg_id"/"type" 这两个字段名触发的:换成别的名字就不该被抑制。
|
||||
if suppressPacketLogEvent("game-upper-send-meta", "request_msg_id", uint16(1276)) {
|
||||
t.Fatal("字段名不是 msg_id 时不应触发抑制——这正是诊断事件改用 request_msg_id 的原因")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user