Files
90CNServer/server/internal/modules/dnf/repository/account_shared_materials.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

88 lines
5.1 KiB
Go
Raw 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 repository
// ─────────────────────────────────────────────────────────────────────────────
// 账号共享仓库(晶体仓库 354..359 + 灵魂仓库 360..365)的**唯一权威表**
//
// 这 12 个道具在自己账号里只有一个家:list 0 的槽 354..365,由账号记录持有,
// 客户端照旧按普通 list-0 格子寻址(见 account_inventory_repository.go 的
// IsAccountSharedInventorySlot / MergeAccountSharedInventory)。
//
// 为什么集中到这里(2026-09-21 事故复盘):
// 同一张表一度在三个互不相干的包里各写了一份 ——
// internal/modules/dnf/inventory/owner.go upgradeAccountSharedMaterialSlot
// internal/services/dnfbridge/disjoint_compound_projection.go currentDisjointWarehouseFixedSlots
// internal/services/dnfbridge/equipment_regeneration_pvf.go equipmentRegenerationAccountSharedItem
// 而"获取时查不查这张表"又是逐个功能各写一遍(已打补丁 8 处、未打补丁 30 余处),
// 于是 NPC 商店的**金币购买**那条漏了:1111 买了 20 个无色小晶块落在角色背包 0:154,
// 同时账号槽 0:358 另有 43890 个 —— 同一条 list-0 报文里出现两行同 itemID,
// 客户端把背包那一行显示成了仓库的数量,小退才恢复。
//
// 三处副本现已全部改为调用本表。今后新增道具或调整槽位**只改这里**。
//
// 运营口径(用户 2026-09-21 明确):
// * 获取(购买/掉落/奖励/兑换/邮件/交易…)必须落进 354..365,不允许落角色背包;
// * 玩家手动把它们存进个人仓库(list 2)或账号金库(list 12)是**允许**的,保留该逻辑;
// * 从这些仓库**取回**时仍要回到 354..365,不允许落进背包。
// ─────────────────────────────────────────────────────────────────────────────
// 六个晶块。ID 顺序对应 90 客户端晶体仓库的固定格序(354..359)。
const (
AccountSharedCubeBlackItemID int64 = 3033 // 黑色小晶块 → 354
AccountSharedCubeWhiteItemID int64 = 3034 // 白色小晶块 → 355
AccountSharedCubeRedItemID int64 = 3035 // 红色小晶块 → 356
AccountSharedCubeBlueItemID int64 = 3036 // 蓝色小晶块 → 357
AccountSharedCubeClearItemID int64 = 3037 // 无色小晶块 → 358
AccountSharedCubeGoldItemID int64 = 3262 // 金色小晶块 → 359
)
// 六个灵魂。ID 顺序对应灵魂仓库的固定格序(360..365)。
const (
AccountSharedSoulCommonItemID int64 = 10100115 // 普通灵魂 → 360
AccountSharedSoulAdvancedItemID int64 = 10100116 // 高级灵魂 → 361
AccountSharedSoulRareItemID int64 = 10099773 // 稀有灵魂 → 362
AccountSharedSoulUniqueItemID int64 = 10099774 // 独有灵魂 → 363
AccountSharedSoulLegendaryItemID int64 = 10099775 // 传说灵魂 → 364
AccountSharedSoulEpicItemID int64 = 10158124 // 史诗灵魂 → 365
)
// accountSharedWarehouseFixedSlots 是权威映射:一个道具 ID 对应唯一一个账号共享槽。
// 该映射的槽位序是 90 客户端布局,2026-07-15 实测并经运营确认。
var accountSharedWarehouseFixedSlots = map[int64]int16{
AccountSharedCubeBlackItemID: CrystalWarehouseFirstSlot + 0,
AccountSharedCubeWhiteItemID: CrystalWarehouseFirstSlot + 1,
AccountSharedCubeRedItemID: CrystalWarehouseFirstSlot + 2,
AccountSharedCubeBlueItemID: CrystalWarehouseFirstSlot + 3,
AccountSharedCubeClearItemID: CrystalWarehouseFirstSlot + 4,
AccountSharedCubeGoldItemID: CrystalWarehouseFirstSlot + 5,
AccountSharedSoulCommonItemID: SoulWarehouseFirstSlot + 0,
AccountSharedSoulAdvancedItemID: SoulWarehouseFirstSlot + 1,
AccountSharedSoulRareItemID: SoulWarehouseFirstSlot + 2,
AccountSharedSoulUniqueItemID: SoulWarehouseFirstSlot + 3,
AccountSharedSoulLegendaryItemID: SoulWarehouseFirstSlot + 4,
AccountSharedSoulEpicItemID: SoulWarehouseFirstSlot + 5,
}
// AccountSharedWarehouseFixedSlots 返回权威表的副本,供需要整体遍历的调用方使用
// (例如 bridge 侧构造自己的 uint32 视图)。返回副本,避免调用方改写权威表。
func AccountSharedWarehouseFixedSlots() map[int64]int16 {
out := make(map[int64]int16, len(accountSharedWarehouseFixedSlots))
for itemID, slot := range accountSharedWarehouseFixedSlots {
out[itemID] = slot
}
return out
}
// AccountSharedWarehouseSlotForItem 给出该道具在账号共享仓库里的唯一固定槽。
// 非成员(含 <=0、超出物品 ID 位宽的入参)返回 (0, false),不 panic、不猜。
func AccountSharedWarehouseSlotForItem(itemID int64) (int16, bool) {
slot, ok := accountSharedWarehouseFixedSlots[itemID]
return slot, ok
}
// IsAccountSharedWarehouseItem 判断该道具是否属于账号共享仓库(六个晶块 + 六个灵魂)。
func IsAccountSharedWarehouseItem(itemID int64) bool {
_, ok := accountSharedWarehouseFixedSlots[itemID]
return ok
}