Files
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

60 lines
2.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package dnfbridge
// raidRewardJournalLimit 是 raidRewardCompleted / raidRewardPublished 两张表的
// 容量上限。
//
// 这两张表按 {RaidKey, Phase, Token} 记录每次结算的幂等凭据。Token 每次结算递增、
// RaidKey 由单调的 nextRaidSeq 生成且永不复用,所以**每次结算都是一个新键**:
// 没有上限就会随进程生命周期内已结算的攻坚次数一直涨(估算 4~24 MB/天)。
//
// 更麻烦的是它的读取方式:completedSingleRuntimeRaidForLeave(raid_online.go:1824)
// 与 completedTeamRuntimeRaidForLeave(raid_online.go:1866)为了按角色找到那场已结束
// 的攻坚,每次退攻坚请求都要**全表遍历**这张 map,代价 O(已完成攻坚数)。累积一万次
// 结算之后,每次退攻坚都要扫一万项并对命中项做 cloneRuntimeRaidState 深拷贝。
//
// 上限把「内存」和「退攻坚开销」一起封顶。语义上只丢弃很久以前就已结束、客户端
// 早已不可能再点「退出攻坚队」的历史记录;最近 1024 次结算的幂等凭据全部保留。
const raidRewardJournalLimit = 1024
// storeRaidRewardCompletionLocked 写入一条结算凭据,并在超出上限时淘汰最旧的一条。
// 调用方必须已持有 raidRewardCommitMu。
func (s *Service) storeRaidRewardCompletionLocked(
key runtimeRaidRewardCompletionKey,
completion runtimeRaidSettlementRewardCompletion,
) {
if s.raidRewardCompleted == nil {
s.raidRewardCompleted = make(map[runtimeRaidRewardCompletionKey]runtimeRaidSettlementRewardCompletion)
}
if _, exists := s.raidRewardCompleted[key]; !exists {
s.raidRewardCompletedOrder = append(s.raidRewardCompletedOrder, key)
}
s.raidRewardCompleted[key] = completion
for len(s.raidRewardCompleted) > raidRewardJournalLimit &&
len(s.raidRewardCompletedOrder) > 0 {
oldest := s.raidRewardCompletedOrder[0]
s.raidRewardCompletedOrder = s.raidRewardCompletedOrder[1:]
delete(s.raidRewardCompleted, oldest)
}
}
// storeRaidRewardPublicationLocked 同上,作用于 raidRewardPublished。
// 调用方必须已持有 raidRewardFlowMu。
func (s *Service) storeRaidRewardPublicationLocked(
key runtimeRaidRewardCompletionKey,
publication *runtimeRaidRewardPublication,
) {
if s.raidRewardPublished == nil {
s.raidRewardPublished = make(map[runtimeRaidRewardCompletionKey]*runtimeRaidRewardPublication)
}
if _, exists := s.raidRewardPublished[key]; !exists {
s.raidRewardPublishedOrder = append(s.raidRewardPublishedOrder, key)
}
s.raidRewardPublished[key] = publication
for len(s.raidRewardPublished) > raidRewardJournalLimit &&
len(s.raidRewardPublishedOrder) > 0 {
oldest := s.raidRewardPublishedOrder[0]
s.raidRewardPublishedOrder = s.raidRewardPublishedOrder[1:]
delete(s.raidRewardPublished, oldest)
}
}