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

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

101 lines
3.1 KiB
Go

package pvf
import "time"
// StringTableIndexStats counts actual lazy builds, not cached lookups.
// Durations and payload counts are cumulative for this archive instance.
type StringTableIndexStats struct {
Revision uint64 `json:"revision"`
State string `json:"state"`
ActiveBuilds int `json:"activeBuilds"`
MappingBuilds int `json:"mappingBuilds"`
MappingCount int `json:"mappingCount"`
TableBuilds int `json:"tableBuilds"`
FailedTables int `json:"failedTables"`
Entries int `json:"entries"`
Bytes int64 `json:"bytes"`
MappingDurationMs float64 `json:"mappingDurationMs"`
TableDurationMs float64 `json:"tableDurationMs"`
BuildDurationMs float64 `json:"buildDurationMs"`
}
// StringTableIndexEvent reports one mapping or UTF-16 payload index build.
type StringTableIndexEvent struct {
ArchivePath string `json:"archivePath"`
Kind string `json:"kind"`
Path string `json:"path"`
State string `json:"state"`
DurationMs float64 `json:"durationMs"`
Entries int `json:"entries"`
Bytes int64 `json:"bytes"`
Error string `json:"error"`
Stats StringTableIndexStats `json:"stats"`
}
func (a *Archive) SetStringTableIndexObserver(observer func(StringTableIndexEvent)) {
a.tables.mu.Lock()
a.tables.observer = observer
event := StringTableIndexEvent{
ArchivePath: a.sourcePath, Kind: "snapshot", Stats: a.stringTableIndexStatsLocked(),
}
event.State = event.Stats.State
a.tables.mu.Unlock()
if observer != nil {
observer(event)
}
}
func (a *Archive) StringTableIndexStats() StringTableIndexStats {
a.tables.mu.Lock()
defer a.tables.mu.Unlock()
return a.stringTableIndexStatsLocked()
}
func (a *Archive) stringTableIndexStatsLocked() StringTableIndexStats {
stats := a.tables.stats
stats.State = "idle"
if stats.ActiveBuilds > 0 {
stats.State = "building"
} else if stats.MappingBuilds > 0 || stats.TableBuilds > 0 {
stats.State = "ready"
}
return stats
}
func (a *Archive) reportStringTableIndex(event StringTableIndexEvent) {
a.tables.mu.Lock()
stats := &a.tables.stats
stats.Revision++
if event.State == "building" {
stats.ActiveBuilds++
} else {
stats.ActiveBuilds--
if event.Kind == "mapping" {
stats.MappingBuilds++
stats.MappingCount = event.Entries
stats.MappingDurationMs += event.DurationMs
} else {
stats.TableBuilds++
stats.TableDurationMs += event.DurationMs
stats.Entries += event.Entries
stats.Bytes += event.Bytes
if event.State == "error" {
stats.FailedTables++
}
}
stats.BuildDurationMs = stats.MappingDurationMs + stats.TableDurationMs
}
event.ArchivePath = a.sourcePath
event.Stats = a.stringTableIndexStatsLocked()
observer := a.tables.observer
a.tables.mu.Unlock()
// Observers may inspect the snapshot; never invoke them under tables.mu.
if observer != nil {
observer(event)
}
}
func stringTableElapsedMs(started time.Time) float64 {
return float64(time.Since(started)) / float64(time.Millisecond)
}