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,95 @@
|
||||
package statbuff
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
dnfrepo "longheng.io/server/internal/modules/dnf/repository"
|
||||
)
|
||||
|
||||
// 强化/增幅成功率窗口:与爆率窗口同一套 fail-closed 语义,但**按种类分开存**
|
||||
// (强化与增幅是两件不同的道具,各自生效、互不覆盖)。
|
||||
func TestRateWindowsAreKindScopedAndFailClosed(t *testing.T) {
|
||||
now := time.Date(2026, 10, 3, 14, 0, 0, 0, time.UTC)
|
||||
character := dnfrepo.CharacterRecord{CharacterID: "11"}
|
||||
|
||||
if _, ok := ActiveRate(character, KindUpgradeSuccess, now); ok {
|
||||
t.Fatal("an empty character must not report an active upgrade window")
|
||||
}
|
||||
if _, ok := ActiveRate(character, Kind("unknown"), now); ok {
|
||||
t.Fatal("an unknown kind must not report an active window")
|
||||
}
|
||||
|
||||
upgrade, err := ActivateRate(&character, KindUpgradeSuccess, 10008220, 1099, 30, 10*time.Minute, now)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
amplify, err := ActivateRate(&character, KindAmplifySuccess, 490001534, 0, 10, 30*time.Minute, now)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if upgrade.Percent != 30 || upgrade.BuffID != 1099 || !upgrade.ExpireAt.Equal(now.Add(10*time.Minute)) {
|
||||
t.Fatalf("upgrade window=%+v", upgrade)
|
||||
}
|
||||
if amplify.Percent != 10 || amplify.BuffID != 0 || !amplify.ExpireAt.Equal(now.Add(30*time.Minute)) {
|
||||
t.Fatalf("amplify window=%+v", amplify)
|
||||
}
|
||||
|
||||
// 两族互不覆盖:读强化拿到的必须是 30/1099,读增幅拿到的是 10/0。
|
||||
gotUpgrade, ok := ActiveRate(character, KindUpgradeSuccess, now.Add(time.Minute))
|
||||
if !ok || gotUpgrade.Percent != 30 || gotUpgrade.BuffID != 1099 || gotUpgrade.ItemID != 10008220 {
|
||||
t.Fatalf("upgrade read=%+v ok=%t", gotUpgrade, ok)
|
||||
}
|
||||
gotAmplify, ok := ActiveRate(character, KindAmplifySuccess, now.Add(time.Minute))
|
||||
if !ok || gotAmplify.Percent != 10 || gotAmplify.ItemID != 490001534 {
|
||||
t.Fatalf("amplify read=%+v ok=%t", gotAmplify, ok)
|
||||
}
|
||||
|
||||
// 过期即视为没有(fail-closed),另一种类不受影响。
|
||||
if _, ok := ActiveRate(character, KindUpgradeSuccess, now.Add(11*time.Minute)); ok {
|
||||
t.Fatal("an expired upgrade window must not stay active")
|
||||
}
|
||||
if _, ok := ActiveRate(character, KindAmplifySuccess, now.Add(11*time.Minute)); !ok {
|
||||
t.Fatal("the amplify window must survive the upgrade window expiring")
|
||||
}
|
||||
|
||||
// 字段缺失/非法同样按"没有增益"处理,绝不 fail-open。
|
||||
broken := dnfrepo.CharacterRecord{CharacterID: "11", Stats: map[string]int64{
|
||||
"upgrade_success_rate_buff_percent": 10, // 没有到期时间
|
||||
}}
|
||||
if _, ok := ActiveRate(broken, KindUpgradeSuccess, now); ok {
|
||||
t.Fatal("a window without an expiry must not be active")
|
||||
}
|
||||
negative := dnfrepo.CharacterRecord{CharacterID: "11", Stats: map[string]int64{
|
||||
"amplify_success_rate_buff_percent": -5,
|
||||
"amplify_success_rate_buff_expire_at": now.Add(time.Hour).Unix(),
|
||||
}}
|
||||
if _, ok := ActiveRate(negative, KindAmplifySuccess, now); ok {
|
||||
t.Fatal("a non-positive bonus must not be active")
|
||||
}
|
||||
if _, err := ActivateRate(&character, KindUpgradeSuccess, 0, 0, 10, time.Minute, now); err == nil {
|
||||
t.Fatal("activating with a zero item id must fail")
|
||||
}
|
||||
if _, err := ActivateRate(&character, KindUpgradeSuccess, 1, 0, 10, 0, now); err == nil {
|
||||
t.Fatal("activating with a zero duration must fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestKindForUpgradeMode(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
mode string
|
||||
want Kind
|
||||
ok bool
|
||||
}{
|
||||
{mode: "reinforce", want: KindUpgradeSuccess, ok: true},
|
||||
{mode: "amplify", want: KindAmplifySuccess, ok: true},
|
||||
{mode: " Reinforce ", want: KindUpgradeSuccess, ok: true},
|
||||
{mode: "", ok: false},
|
||||
{mode: "normal", ok: false},
|
||||
} {
|
||||
got, ok := KindForUpgradeMode(tc.mode)
|
||||
if ok != tc.ok || got != tc.want {
|
||||
t.Fatalf("KindForUpgradeMode(%q)=%q,%t want %q,%t", tc.mode, got, ok, tc.want, tc.ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user