服务端(Go): - GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面 - GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新 - 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新) - 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍 - 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0) - 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算 启动器(Python/JS): - 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭 - GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐) - 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
153 lines
4.8 KiB
Go
153 lines
4.8 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
"longheng.io/server/internal/platform/audit"
|
|
"longheng.io/server/internal/platform/bilog"
|
|
"longheng.io/server/internal/platform/config"
|
|
"longheng.io/server/internal/platform/datatable"
|
|
"longheng.io/server/internal/platform/health"
|
|
"longheng.io/server/internal/platform/httpx"
|
|
"longheng.io/server/internal/platform/logiclog"
|
|
"longheng.io/server/internal/platform/logx"
|
|
"longheng.io/server/internal/platform/metrics"
|
|
"longheng.io/server/internal/platform/otelx"
|
|
"longheng.io/server/internal/platform/pvf"
|
|
"longheng.io/server/internal/platform/ratelimit"
|
|
"longheng.io/server/internal/platform/scheduler"
|
|
"longheng.io/server/internal/platform/servergroup"
|
|
"longheng.io/server/internal/platform/statesync"
|
|
"longheng.io/server/internal/platform/tracing"
|
|
)
|
|
|
|
type platformFoundation struct {
|
|
cfg config.ServiceConfig
|
|
logger *slog.Logger
|
|
otelShutdown otelx.Shutdown
|
|
pvfArchive *pvf.Archive
|
|
dataTables *datatable.Registry
|
|
dataTableViews *datatable.ViewManager
|
|
stateSyncStore statesync.Store
|
|
serverGroupManager *servergroup.Manager
|
|
serverGroupStore servergroup.Store
|
|
serverGroupArchives servergroup.MergeArchiveStore
|
|
auditLogger *audit.Logger
|
|
logicLogger *logiclog.Logger
|
|
biLogger *bilog.Logger
|
|
healthSvc *health.Service
|
|
metricsRegistry *metrics.Registry
|
|
tracer *tracing.Tracer
|
|
rateLimiter *ratelimit.Limiter
|
|
adminTimeouts httpx.Timeouts
|
|
adminServer *httpx.Server
|
|
schedulerSvc *scheduler.Scheduler
|
|
}
|
|
|
|
func newPlatformBase(serviceName, configPath string) (*platformFoundation, error) {
|
|
cfg, err := config.Load(configPath, serviceName)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("load config: %w", err)
|
|
}
|
|
|
|
pvfArchive, err := newPVFArchive(cfg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
logger := logx.New(cfg.Service.Name, cfg.Service.NodeID, cfg.Service.Environment)
|
|
otelShutdown, err := setupOTel(cfg, logger)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("setup opentelemetry: %w", err)
|
|
}
|
|
foundation := &platformFoundation{
|
|
cfg: cfg,
|
|
logger: logger,
|
|
otelShutdown: otelShutdown,
|
|
pvfArchive: pvfArchive,
|
|
}
|
|
if foundation.dataTables, err = newDataTables(cfg); err != nil {
|
|
_ = foundation.close(context.Background())
|
|
return nil, err
|
|
}
|
|
if foundation.dataTableViews, err = datatable.NewViewManager(); err != nil {
|
|
_ = foundation.close(context.Background())
|
|
return nil, err
|
|
}
|
|
if foundation.stateSyncStore, err = newStateSyncStore(cfg); err != nil {
|
|
_ = foundation.close(context.Background())
|
|
return nil, err
|
|
}
|
|
foundation.serverGroupManager, foundation.serverGroupStore, foundation.serverGroupArchives, err = newGroupManager(context.Background(), cfg)
|
|
if err != nil {
|
|
_ = foundation.close(context.Background())
|
|
return nil, err
|
|
}
|
|
if foundation.auditLogger, err = newAuditLogger(cfg); err != nil {
|
|
_ = foundation.close(context.Background())
|
|
return nil, err
|
|
}
|
|
if foundation.logicLogger, err = newLogicLogger(cfg); err != nil {
|
|
_ = foundation.close(context.Background())
|
|
return nil, err
|
|
}
|
|
if foundation.biLogger, err = newBILogger(cfg); err != nil {
|
|
_ = foundation.close(context.Background())
|
|
return nil, err
|
|
}
|
|
foundation.healthSvc = health.New(cfg.Service.Name)
|
|
foundation.metricsRegistry = metrics.New()
|
|
foundation.tracer = tracing.New(cfg.Tracing.Enabled || cfg.OTel.Enabled, cfg.Tracing.MaxSpans, logger)
|
|
if foundation.rateLimiter, err = newRateLimiter(cfg); err != nil {
|
|
_ = foundation.close(context.Background())
|
|
return nil, err
|
|
}
|
|
foundation.adminTimeouts = httpx.Timeouts{
|
|
ReadTimeout: cfg.Admin.ReadTimeout(),
|
|
ReadHeaderTimeout: cfg.Admin.ReadHeaderTimeout(),
|
|
WriteTimeout: cfg.Admin.WriteTimeout(),
|
|
IdleTimeout: cfg.Admin.IdleTimeout(),
|
|
}
|
|
foundation.adminServer = httpx.New("admin-http", cfg.Admin.Listen, logger, foundation.adminTimeouts)
|
|
foundation.schedulerSvc = scheduler.New("scheduler", logger)
|
|
return foundation, nil
|
|
}
|
|
|
|
func (f *platformFoundation) close(ctx context.Context) error {
|
|
if f == nil {
|
|
return nil
|
|
}
|
|
if ctx == nil {
|
|
ctx = context.Background()
|
|
}
|
|
var err error
|
|
if f.stateSyncStore != nil {
|
|
err = f.stateSyncStore.Close()
|
|
f.stateSyncStore = nil
|
|
}
|
|
if f.auditLogger != nil {
|
|
if closeErr := f.auditLogger.Close(); closeErr != nil && err == nil {
|
|
err = closeErr
|
|
}
|
|
f.auditLogger = nil
|
|
}
|
|
if f.logicLogger != nil {
|
|
if closeErr := f.logicLogger.Close(); closeErr != nil && err == nil {
|
|
err = closeErr
|
|
}
|
|
f.logicLogger = nil
|
|
}
|
|
if f.biLogger != nil {
|
|
if closeErr := f.biLogger.Close(); closeErr != nil && err == nil {
|
|
err = closeErr
|
|
}
|
|
f.biLogger = nil
|
|
}
|
|
if closeErr := shutdownOTel(ctx, f.otelShutdown); closeErr != nil && err == nil {
|
|
err = closeErr
|
|
}
|
|
f.otelShutdown = nil
|
|
return err
|
|
}
|