ecs/servers/game/logic/manager_server.go
2025-06-04 18:17:39 +08:00

239 lines
5.9 KiB
Go

package logic
import (
"fmt"
"github.com/oylshe1314/framework/client/db"
"github.com/oylshe1314/framework/config"
"github.com/oylshe1314/framework/errors"
"github.com/oylshe1314/framework/server"
"github.com/oylshe1314/framework/util"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"time"
)
const TableServer string = "server"
func TableServerKey(name string, appId uint32) string {
return fmt.Sprint(name, "_", appId)
}
type ServerInfo struct {
Key string `bson:"_id"`
Name string `bson:"name"`
AppId uint32 `bson:"app_id"`
CreateTime int64 `bson:"create_time"`
Creations uint32 `bson:"creations"`
MaxOnline uint32 `bson:"max_online"`
MaxOnlineTime int64 `bson:"max_online_time"`
}
type ServerConfig struct {
err error
dataDir string
maxRoles int
openTime int64
}
func (this *ServerConfig) DataDir() string { return this.dataDir }
func (this *ServerConfig) MaxRoles() int { return this.maxRoles }
func (this *ServerConfig) OpenTime() int64 { return this.openTime }
func (this *ServerConfig) WithDataDir(dataDir string) {
this.dataDir = dataDir
}
func (this *ServerConfig) WithMaxRoles(maxRoles int) {
this.maxRoles = maxRoles
if this.maxRoles < 1 {
this.maxRoles = 1
}
}
func (this *ServerConfig) WithOpenTime(openTime string) {
if openTime != "" {
this.openTime, this.err = util.ParseUnix(openTime, time.DateTime)
}
}
func (this *ServerConfig) Init() (err error) {
if this.err != nil {
return this.err
}
if len(this.dataDir) == 0 {
return errors.Error("'dataDir' can not be empty")
}
return nil
}
type ServerManager struct {
manager
closed bool
mongoClient *db.MongoClient
//eventManager *EventManager
info *ServerInfo
config *ServerConfig
dirty bool //数据是否有更新
creations uint32 //服务器总创建人数
online uint32 //当前在线人数
maxOnline uint32 //历史最大在线人数
maxOnlineTime int64 //历史最大在线时间人数
}
func NewServerManager(svr server.Server, config *ServerConfig, mongoClient *db.MongoClient /*, eventManager *EventManager*/) *ServerManager {
return &ServerManager{manager: manager{logger: svr.Logger(), server: svr}, config: config, mongoClient: mongoClient /*, eventManager: eventManager*/}
}
func (this *ServerManager) SetEventManager( /*eventManager *EventManager*/ ) {
//this.eventManager = eventManager
}
func (this *ServerManager) Init() error {
//if this.eventManager == nil {
// return errors.Error("'eventManager' is nil")
//}
var err = this.initData()
if err != nil {
return err
}
this.run()
return nil
}
func (this *ServerManager) initData() error {
var info = &ServerInfo{Key: TableServerKey(this.server.Name(), this.server.AppId())}
var err = this.mongoClient.Collection(TableServer).FindOne(this.mongoClient.Context(), bson.M{"_id": info.Key}).Decode(info)
if err != nil {
if !errors.Is(err, mongo.ErrNoDocuments) {
return err
}
info.Name = this.server.Name()
info.AppId = this.server.AppId()
info.CreateTime = util.Unix()
info.Creations = 0
info.MaxOnline = 0
info.MaxOnlineTime = 0
_, err = this.mongoClient.Collection(TableServer).InsertOne(this.mongoClient.Context(), info)
if err != nil {
return err
}
//TODO 其他数据库初始化操作
// 创建玩家昵称索引
//_, err = this.mongoClient.Collection(TablePlayer).Indexes().CreateOne(this.mongoClient.Context(), mongo.IndexModel{Keys: bson.M{"role.name": 1}})
//if err != nil {
// return err
//}
}
this.info = info
return nil
}
func (this *ServerManager) Close() error {
this.closed = true
return nil
}
func (this *ServerManager) saveData() {
var set = bson.M{}
if this.creations != this.info.Creations {
this.info.Creations = this.creations
set["creations"] = this.info.Creations
}
if this.maxOnline != this.info.MaxOnline {
this.info.MaxOnline = this.maxOnline
set["max_online"] = this.info.MaxOnline
}
if this.maxOnlineTime != this.info.MaxOnlineTime {
this.info.MaxOnlineTime = this.maxOnlineTime
set["max_online_time"] = this.info.MaxOnlineTime
}
if len(set) > 0 {
go func(set bson.M) {
_, err := this.mongoClient.Collection(TableServer).UpdateByID(this.mongoClient.Context(), this.info.Key, bson.M{"$set": set})
if err != nil {
this.logger.Error("Save server data error, ", err)
}
}(set)
}
}
func (this *ServerManager) run() {
go func() {
var rt = 60 - util.Unix()%60
if rt > 0 {
time.Sleep(time.Second * time.Duration(rt))
}
var ticker = time.NewTicker(time.Minute)
defer ticker.Stop()
for {
if this.closed {
return
}
if this.dirty {
this.dirty = false
this.saveData()
//this.eventManager.ServerOnline(LogTypeServerOnline, this.server.AppId(), this.creations, this.online, this.offline, this.maxOnline, this.maxOnlineTime)
}
_, ok := <-ticker.C
if !ok {
return
}
}
}()
}
func (this *ServerManager) Info() *ServerInfo { return this.info }
func (this *ServerManager) Config() *ServerConfig { return this.config }
func (this *ServerManager) Creations() uint32 { return this.creations }
func (this *ServerManager) MaxOnline() uint32 { return this.maxOnline }
func (this *ServerManager) MaxOnlineTime() int64 { return this.maxOnlineTime }
func (this *ServerManager) AddCreations(value uint32) {
this.creations += value
this.dirty = true
}
func (this *ServerManager) AddOnline(value uint32) {
this.online += value
if this.online > this.maxOnline {
this.maxOnline = this.online
this.maxOnlineTime = util.Unix()
}
this.dirty = true
}
func (this *ServerManager) ReduceOnline(value uint32) {
if this.online > 0 {
this.online -= value
this.dirty = true
}
}
func (this *ServerManager) Online() uint32 {
return this.online
}
func (this *ServerManager) Reload() error {
configServer, ok := this.server.(config.Server)
if !ok {
return errors.Error("Unsupported data reload")
}
return configServer.Load(this.config.DataDir())
}