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 AreaConfig struct { Id uint32 `json:"id"` //服务器ID Platform uint32 `json:"platform"` //平台 Channel uint32 `json:"channel"` //渠道 Area string `json:"area"` //大区 Name string `json:"name"` //名称 } type ServerConfig struct { DataDir string `json:"dataDir"` MaxRoles int `json:"maxRoles"` OpenTime string `json:"openTime"` AreaConfig *AreaConfig `json:"areaConfig"` } 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, mongoClient db.MongoClient, config *ServerConfig, eventManager *EventManager) *ServerManager { return &ServerManager{ manager: manager{ server: svr, }, mongoClient: mongoClient, config: config, eventManager: eventManager, } } func (this *ServerManager) Init() error { if this.mongoClient == nil { return errors.Error("'mongoClient' is nil") } 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.NowUnix() 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.NowUnix()%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.NowUnix() } 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) }