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

@@ -0,0 +1,75 @@
package annotations
import (
"fmt"
"strings"
"testing"
"pvfine/internal/pvf"
)
func BenchmarkAnnotateManyRules(b *testing.B) {
for _, count := range []int{100, 1000, 10000} {
b.Run(fmt.Sprint(count), func(b *testing.B) {
rules := make([]Rule, count)
for i := range rules {
rules[i] = Rule{
ID: fmt.Sprint(i), Match: MatchSpec{Extensions: []string{".equ"}},
Target: TargetSpec{Kind: "token", Section: fmt.Sprintf("section%d", i), Index: intPtr(0)},
Annotation: AnnotationSpec{Title: "说明", Type: "text"},
}
}
engine, err := Compile(Document{Version: 1, Rules: rules})
if err != nil {
b.Fatal(err)
}
var text strings.Builder
for i := 0; i < 100; i++ {
fmt.Fprintf(&text, "[section%d]\n1 2 3 4 5\n", i)
}
view := pvf.ParseScriptView(text.String())
b.ResetTimer()
for i := 0; i < b.N; i++ {
engine.Annotate("a.equ", view, nil)
}
})
}
}
// BenchmarkAnnotatePathManyRules guards the bulk path note lookup: without the
// literal glob and "<dir>/**" buckets every tree node would scan all rules.
func BenchmarkAnnotatePathManyRules(b *testing.B) {
const files, directories = 15000, 2000
rules := make([]Rule, 0, files+directories+4)
for i := 0; i < files; i++ {
rules = append(rules, Rule{
ID: fmt.Sprintf("file.%d", i), Match: MatchSpec{Glob: fmt.Sprintf("dir%02d/sub%02d/file%05d.ani", i%40, i%50, i)},
Target: TargetSpec{Kind: "path"}, Annotation: AnnotationSpec{Title: "文件说明", Type: "text"},
})
}
for i := 0; i < directories; i++ {
rules = append(rules, Rule{
ID: fmt.Sprintf("dir.%d", i), Match: MatchSpec{Glob: fmt.Sprintf("dir%02d/sub%02d/**", i%40, i%50)},
Target: TargetSpec{Kind: "path"}, Annotation: AnnotationSpec{Title: "目录说明", Type: "text"},
})
}
rules = append(rules,
Rule{ID: "star", Match: MatchSpec{Glob: "**/*.ani"}, Target: TargetSpec{Kind: "path"}, Annotation: AnnotationSpec{Title: "通配", Type: "text"}},
Rule{ID: "all", Target: TargetSpec{Kind: "path"}, Annotation: AnnotationSpec{Title: "全部", Type: "text"}},
)
engine, err := Compile(Document{Version: 1, Rules: rules})
if err != nil {
b.Fatal(err)
}
paths := []string{
"dir01/sub01/file00001.ani",
"dir01/sub01/file00001.ani.bak",
"dir39/sub49/deep/deeper/1.ani",
"unknown/path.dat",
"dir01/sub01",
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
engine.AnnotatePath(paths[i%len(paths)], false)
}
}