服务端(Go): - GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面 - GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新 - 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新) - 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍 - 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0) - 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算 启动器(Python/JS): - 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭 - GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐) - 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
85 lines
2.1 KiB
Go
85 lines
2.1 KiB
Go
package playerloop
|
|
|
|
import (
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// OnlineRecord 记录账号在线状态和最近变更时间。
|
|
type OnlineRecord struct {
|
|
AccountID string `json:"account_id"`
|
|
Online bool `json:"online"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|
|
// OnlineRegistry 在内存中维护账号在线状态。
|
|
type OnlineRegistry struct {
|
|
mu sync.RWMutex
|
|
records map[string]OnlineRecord
|
|
now func() time.Time
|
|
}
|
|
|
|
// NewOnlineRegistry 使用系统时钟创建在线状态表。
|
|
func NewOnlineRegistry() *OnlineRegistry {
|
|
return NewOnlineRegistryWithClock(time.Now)
|
|
}
|
|
|
|
// NewOnlineRegistryWithClock 使用指定时钟创建在线状态表,便于测试和回放。
|
|
func NewOnlineRegistryWithClock(now func() time.Time) *OnlineRegistry {
|
|
if now == nil {
|
|
now = time.Now
|
|
}
|
|
return &OnlineRegistry{
|
|
records: make(map[string]OnlineRecord),
|
|
now: now,
|
|
}
|
|
}
|
|
|
|
// MarkOnline 标记账号在线并返回新状态。
|
|
func (r *OnlineRegistry) MarkOnline(accountID string) OnlineRecord {
|
|
return r.set(accountID, true)
|
|
}
|
|
|
|
// MarkOffline 标记账号离线并返回新状态。
|
|
func (r *OnlineRegistry) MarkOffline(accountID string) OnlineRecord {
|
|
return r.set(accountID, false)
|
|
}
|
|
|
|
// IsOnline 判断账号当前是否在线。
|
|
func (r *OnlineRegistry) IsOnline(accountID string) bool {
|
|
accountID = strings.TrimSpace(accountID)
|
|
if r == nil || accountID == "" {
|
|
return false
|
|
}
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
return r.records[accountID].Online
|
|
}
|
|
|
|
// Snapshot 返回在线状态表的当前副本。
|
|
func (r *OnlineRegistry) Snapshot() []OnlineRecord {
|
|
if r == nil {
|
|
return nil
|
|
}
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
out := make([]OnlineRecord, 0, len(r.records))
|
|
for _, record := range r.records {
|
|
out = append(out, record)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (r *OnlineRegistry) set(accountID string, online bool) OnlineRecord {
|
|
accountID = strings.TrimSpace(accountID)
|
|
if r == nil || accountID == "" {
|
|
return OnlineRecord{}
|
|
}
|
|
record := OnlineRecord{AccountID: accountID, Online: online, UpdatedAt: r.now().UTC()}
|
|
r.mu.Lock()
|
|
r.records[accountID] = record
|
|
r.mu.Unlock()
|
|
return record
|
|
}
|