DNF90 服务端与启动器完整源码(含 GM 工具功能增强)

服务端(Go):
- GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面
- GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新
- 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新)
- 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍
- 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0)
- 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算

启动器(Python/JS):
- 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭
- GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐)
- 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
This commit is contained in:
hanfuit committed 2026-11-04 14:31:55 +08:00
commit 645b64fe21
4388 files changed
+1405457

No files matched your search

+141
View File
@@ -0,0 +1,141 @@
package annotations
import (
"reflect"
"strings"
"testing"
"pvfine/internal/pvf"
)
func TestPVFVersionRulesAndSourceRoundTrip(t *testing.T) {
document := Document{Version: 1}
for i, versions := range [][]string{nil, {}, {"90US"}, {"90CN", "110US"}, {"115US"}, {"100CN"}, {"TW"}, {"115CN"}} {
document.Rules = append(document.Rules, Rule{ID: string(rune('a' + i)), PVFVersions: versions,
Target: TargetSpec{Kind: "path"}, Annotation: AnnotationSpec{Title: string(rune('a' + i)), Type: "text"}})
}
engine, err := Compile(document)
if err != nil {
t.Fatal(err)
}
for _, tc := range []struct {
version string
want int
}{{"90US", 3}, {"90CN", 3}, {"110US", 3}, {"115US", 3}, {"115CN", 3}, {"", 2}, {"future", 2}, {"100CN", 3}, {"TW", 3}} {
t.Run(tc.version, func(t *testing.T) {
runtime := engine.ForVersion(tc.version)
if got := len(runtime.AnnotatePath("a.equ", false)[0].RuleIDs); got != tc.want {
t.Fatalf("got %d, want %d", got, tc.want)
}
if !reflect.DeepEqual(runtime.Document(), engine.Document()) {
t.Fatal("runtime lost original document")
}
data, err := Marshal(runtime.Document())
if err != nil {
t.Fatal(err)
}
restored, err := Parse(data)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(restored.Rules[3].PVFVersions, []string{"90CN", "110US"}) {
t.Fatal("serialization lost versions")
}
if !reflect.DeepEqual(restored.Rules[4].PVFVersions, []string{"115US"}) {
t.Fatal("serialization lost 115US scope")
}
if got := runtime.ForVersion("115US").AnnotatePath("a.equ", false)[0].RuleIDs; !reflect.DeepEqual(got, []string{"a", "b", "e"}) {
t.Fatalf("115US enabled rules from a different version: %v", got)
}
if got := runtime.ForVersion("100CN").AnnotatePath("a.equ", false)[0].RuleIDs; !reflect.DeepEqual(got, []string{"a", "b", "f"}) {
t.Fatalf("100CN enabled rules from a different version: %v", got)
}
if got := len(runtime.ForVersion("90US").AnnotatePath("a.equ", false)[0].RuleIDs); got != 3 {
t.Fatal("switching versions lost rules")
}
})
}
}
func TestPVFVersionFieldIntersectionAndImplicitFallback(t *testing.T) {
for _, tc := range []struct {
name string
field, rule []string
version string
want string
previews int
}{
{"intersection", []string{"90US", "90CN"}, []string{"90CN", "110US"}, "90CN", "explicit", 1},
{"field excludes rule", []string{"90US", "90CN"}, []string{"90CN", "110US"}, "110US", "", 0},
{"rule excludes field falls back", []string{"90US", "90CN"}, []string{"90CN", "110US"}, "90US", "field:shared", 1},
{"empty intersection", []string{"90US"}, []string{"110US"}, "110US", "", 0},
{"115US intersection", []string{"110US", "115US"}, []string{"115US"}, "115US", "explicit", 1},
{"110US field excludes 115US", []string{"110US"}, []string{"115US"}, "115US", "", 0},
{"115US field excludes 110US", []string{"115US"}, []string{"110US"}, "110US", "", 0},
{"unrestricted rule restricted field", []string{"90CN"}, nil, "90US", "", 0},
{"restricted rule unrestricted field", nil, []string{"110US"}, "90CN", "field:shared", 1},
{"unknown restricted field", []string{"90US"}, nil, "", "", 0},
{"unknown unrestricted field", nil, []string{"90US"}, "", "field:shared", 1},
{"all unrestricted", nil, nil, "", "explicit", 1},
} {
t.Run(tc.name, func(t *testing.T) {
engine, err := Compile(Document{Version: 1,
Fields: []FieldDefinition{{ID: "shared", PVFVersions: tc.field, Target: TargetSpec{Kind: "token", Section: "name", Index: intPtr(0)}, Annotation: AnnotationSpec{Title: "name", Type: "text"}, Preview: &PreviewSpec{Provider: "equ", Role: "name", Group: "header", Format: "text"}}},
Rules: []Rule{{ID: "explicit", Field: "shared", PVFVersions: tc.rule}},
})
if err != nil {
t.Fatal(err)
}
runtime := engine.ForVersion(tc.version)
view := pvf.ParseScriptView("[name]\n`example`")
results := runtime.Annotate("a.equ", view, nil)
if tc.want == "" {
if len(results) != 0 {
t.Fatalf("unexpected results: %#v", results)
}
} else if len(results) != 1 || !reflect.DeepEqual(results[0].RuleIDs, []string{tc.want}) {
t.Fatalf("results = %#v", results)
}
if got := len(runtime.ExtractPreviewFields("a.equ", view, "equ")); got != tc.previews {
t.Fatalf("preview fields = %d", got)
}
})
}
}
func TestPVFVersionNonReferenceRuleDoesNotSuppressField(t *testing.T) {
field := FieldDefinition{ID: "shared", Target: TargetSpec{Kind: "path"}, Annotation: AnnotationSpec{Title: "shared", Type: "text"}}
engine, err := Compile(Document{Version: 1, Fields: []FieldDefinition{field}, Rules: []Rule{{ID: "explicit", PVFVersions: []string{"110US"}, Target: field.Target, Annotation: field.Annotation}}})
if err != nil {
t.Fatal(err)
}
for _, version := range []string{"90US", "110US"} {
results := engine.ForVersion(version).AnnotatePath("a.equ", false)
want := "explicit"
if version == "90US" {
want = "field:shared"
}
if len(results) != 1 || !reflect.DeepEqual(results[0].RuleIDs, []string{want}) {
t.Fatalf("%s: %#v", version, results)
}
}
}
func TestPVFVersionValidation(t *testing.T) {
for _, value := range []string{"90us", "unknown", "", "120US"} {
for _, field := range []bool{false, true} {
document := Document{Version: 1}
if field {
document.Fields = []FieldDefinition{{ID: "f", PVFVersions: []string{value}, Target: TargetSpec{Kind: "path"}, Annotation: AnnotationSpec{Title: "f", Type: "text"}}}
} else {
document.Rules = []Rule{{ID: "r", PVFVersions: []string{value}, Target: TargetSpec{Kind: "path"}, Annotation: AnnotationSpec{Title: "r", Type: "text"}}}
}
if _, err := Compile(document); err == nil || !strings.Contains(err.Error(), "pvfVersions") {
t.Fatalf("invalid version accepted: %q, field=%v, err=%v", value, field, err)
}
if _, err := Marshal(document); err == nil {
t.Fatal("invalid version serialized")
}
}
}
}