346 lines
8.2 KiB
Go
346 lines
8.2 KiB
Go
package logic
|
|
|
|
import (
|
|
"ecs/proto"
|
|
"github.com/oylshe1314/framework/client/db"
|
|
"github.com/oylshe1314/framework/client/rpc"
|
|
"github.com/oylshe1314/framework/errors"
|
|
"github.com/oylshe1314/framework/log"
|
|
"github.com/oylshe1314/framework/server"
|
|
"github.com/oylshe1314/framework/util"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
"sort"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type manager struct {
|
|
server server.Server
|
|
}
|
|
|
|
func (this *manager) Logger() log.Logger {
|
|
return this.server.Logger()
|
|
}
|
|
|
|
const tableSetting = "setting"
|
|
|
|
type Setting struct {
|
|
Id uint32 `bson:"_id"`
|
|
Version string `bson:"version"`
|
|
LoginClosed bool `bson:"login_closed"`
|
|
TimedClose bool `bson:"timed_closed"`
|
|
CloseTime int64 `bson:"close_time"`
|
|
ClosedList []uint32 `bson:"closed_list"`
|
|
WhiteList []uint64 `bson:"white_list"`
|
|
}
|
|
|
|
const tableNotice = "notice"
|
|
|
|
type Notice struct {
|
|
Id uint64 `bson:"_id"`
|
|
Type string `json:"type"`
|
|
Title string `bson:"title"`
|
|
Content string `bson:"content"`
|
|
BeginTime int64 `bson:"begin_time"`
|
|
EndTime int64 `bson:"end_time"`
|
|
}
|
|
|
|
type GateManager struct {
|
|
manager
|
|
|
|
setting *Setting
|
|
|
|
closeTime int64
|
|
closeMutex sync.Mutex
|
|
closeTimer *time.Timer
|
|
|
|
mongoClient db.MongoClient
|
|
httpRpcClient rpc.HttpRpcClient
|
|
}
|
|
|
|
func NewGateManager(svr server.Server, mongoClient db.MongoClient, httpRpcClient rpc.HttpRpcClient) *GateManager {
|
|
return &GateManager{
|
|
manager: manager{
|
|
server: svr,
|
|
},
|
|
mongoClient: mongoClient,
|
|
httpRpcClient: httpRpcClient,
|
|
}
|
|
}
|
|
|
|
func (this *GateManager) Init() error {
|
|
setting, err := this.querySetting()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if setting != nil {
|
|
this.setSetting(setting)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (this *GateManager) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func (this *GateManager) querySetting() (*Setting, error) {
|
|
var setting = &Setting{Id: this.server.AppId()}
|
|
var err = this.mongoClient.Collection(tableSetting).FindOne(this.mongoClient.Context(), bson.M{"_id": setting.Id}).Decode(setting)
|
|
if err != nil {
|
|
if errors.Is(err, mongo.ErrNoDocuments) {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
return setting, nil
|
|
}
|
|
|
|
func (this *GateManager) GetSetting() *Setting {
|
|
return this.setting
|
|
}
|
|
|
|
func (this *GateManager) SetSetting(setting *Setting) error {
|
|
var err = this.saveSetting(setting)
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
return proto.ErrInternalError
|
|
}
|
|
this.setSetting(setting)
|
|
return nil
|
|
}
|
|
|
|
func (this *GateManager) saveSetting(setting *Setting) error {
|
|
var updateOption = options.Update().SetUpsert(true)
|
|
_, err := this.mongoClient.Collection(tableSetting).UpdateByID(this.mongoClient.Context(), setting.Id, bson.M{"$set": setting}, updateOption)
|
|
return err
|
|
}
|
|
|
|
func (this *GateManager) setSetting(setting *Setting) {
|
|
|
|
this.setting = setting
|
|
|
|
if setting.LoginClosed {
|
|
var now = util.NowUnix()
|
|
|
|
this.closeMutex.Lock()
|
|
if this.closeTimer != nil {
|
|
if this.closeTime == setting.CloseTime || now >= setting.CloseTime {
|
|
this.closeMutex.Unlock()
|
|
return
|
|
}
|
|
this.closeTimer.Stop()
|
|
this.closeTime = 0
|
|
this.closeTimer = nil
|
|
}
|
|
this.closeMutex.Unlock()
|
|
|
|
var f = func() {
|
|
this.closeMutex.Lock()
|
|
this.closeTime = 0
|
|
this.closeTimer = nil
|
|
this.closeMutex.Unlock()
|
|
|
|
ar, err := this.httpRpcClient.AllPost("game", "/server/close", nil, nil, nil)
|
|
if err != nil {
|
|
this.Logger().Errorf("Http get error, error: %v", err)
|
|
} else {
|
|
for appId, result := range ar {
|
|
if result.Err != nil {
|
|
this.Logger().Errorf("[game_1:%d] <- Server offline error, %v", appId, result.Err)
|
|
continue
|
|
}
|
|
|
|
if result.Res.Status != errors.StatusSuccessful {
|
|
this.Logger().Errorf("[game_1:%d] <- Server offline failed, %s", appId, result.Res.Message)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if !setting.TimedClose || util.NowUnix() >= setting.CloseTime {
|
|
f()
|
|
} else {
|
|
this.closeMutex.Lock()
|
|
this.closeTime = setting.CloseTime
|
|
this.closeTimer = time.AfterFunc(time.Second*time.Duration(setting.CloseTime-now), f)
|
|
this.closeMutex.Unlock()
|
|
}
|
|
} else {
|
|
this.closeMutex.Lock()
|
|
if this.closeTimer != nil {
|
|
this.closeTimer.Stop()
|
|
this.closeTime = 0
|
|
this.closeTimer = nil
|
|
}
|
|
this.closeMutex.Unlock()
|
|
}
|
|
}
|
|
|
|
type gameServerInfo struct {
|
|
appId uint32
|
|
address string
|
|
online uint32
|
|
}
|
|
|
|
type gameServerList struct {
|
|
id uint32
|
|
platform uint32
|
|
channel uint32
|
|
area string
|
|
name string
|
|
online uint32
|
|
roleLv uint32
|
|
|
|
serverList []*gameServerInfo
|
|
}
|
|
|
|
func (this *GateManager) GetServerList(platform uint32, channel uint32, userId uint64, recentServer uint32) ([]*proto.GameServer, error) {
|
|
var setting = this.GetSetting()
|
|
|
|
var whiteList = map[uint64]struct{}{}
|
|
var closedList = map[uint32]struct{}{}
|
|
if setting != nil && setting.LoginClosed {
|
|
if !setting.TimedClose || util.NowUnix() >= setting.CloseTime {
|
|
for _, whiteId := range setting.WhiteList {
|
|
whiteList[whiteId] = struct{}{}
|
|
}
|
|
|
|
if len(setting.ClosedList) == 0 {
|
|
if _, ok := whiteList[userId]; !ok {
|
|
return nil, proto.ErrServerMaintain
|
|
}
|
|
}
|
|
|
|
for _, closedId := range setting.ClosedList {
|
|
closedList[closedId] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
|
|
ar, err := this.httpRpcClient.AllPost("game", "/server/info", nil, &proto.MsgServerInfoReq{UserId: userId}, &proto.MsgServerInfoAck{})
|
|
if err != nil {
|
|
return nil, proto.ErrServerMaintain
|
|
}
|
|
|
|
var listMap = map[uint32]*gameServerList{}
|
|
for appId, reply := range ar {
|
|
if reply.Err != nil {
|
|
this.Logger().Error("Get server online failed, ", reply.Err)
|
|
continue
|
|
}
|
|
|
|
if reply.Res.Error() != nil {
|
|
this.Logger().Errorf("Get server online failed, status: %d, message: %s", reply.Res.Status, reply.Res.Message)
|
|
continue
|
|
}
|
|
|
|
var node = this.httpRpcClient.Node("game", appId)
|
|
if node == nil {
|
|
continue
|
|
}
|
|
|
|
var infoAck = reply.Res.Data.(*proto.MsgServerInfoAck)
|
|
|
|
if platform != 0 {
|
|
if infoAck.Platform != platform {
|
|
continue
|
|
}
|
|
}
|
|
|
|
if channel != 0 {
|
|
if infoAck.Channel != channel {
|
|
continue
|
|
}
|
|
}
|
|
|
|
if _, closed := closedList[infoAck.Id]; closed {
|
|
if _, white := whiteList[userId]; !white {
|
|
continue
|
|
}
|
|
}
|
|
|
|
var gsl = listMap[infoAck.Id]
|
|
if gsl == nil {
|
|
gsl = &gameServerList{
|
|
id: infoAck.Id,
|
|
platform: infoAck.Platform,
|
|
channel: infoAck.Channel,
|
|
area: infoAck.Area,
|
|
name: infoAck.Name,
|
|
roleLv: infoAck.RoleLv,
|
|
}
|
|
listMap[infoAck.Id] = gsl
|
|
}
|
|
gsl.online += infoAck.Online
|
|
gsl.serverList = append(gsl.serverList, &gameServerInfo{appId: appId, address: node.Exter.Address, online: infoAck.Online})
|
|
}
|
|
|
|
var serverList []*proto.GameServer
|
|
for _, gsl := range listMap {
|
|
if len(gsl.serverList) == 0 {
|
|
continue
|
|
}
|
|
|
|
sort.Slice(gsl.serverList, func(i, j int) bool {
|
|
if gsl.serverList[i].online == gsl.serverList[j].online {
|
|
return gsl.serverList[i].appId < gsl.serverList[j].appId
|
|
} else {
|
|
return gsl.serverList[i].online < gsl.serverList[j].online
|
|
}
|
|
})
|
|
|
|
serverList = append(serverList, &proto.GameServer{
|
|
Id: gsl.id,
|
|
Area: gsl.area,
|
|
Name: gsl.name,
|
|
Address: gsl.serverList[0].address,
|
|
Online: gsl.online,
|
|
Recent: gsl.id == recentServer,
|
|
RoleLv: gsl.roleLv,
|
|
})
|
|
}
|
|
|
|
sort.Slice(serverList, func(i, j int) bool {
|
|
return serverList[i].Id < serverList[j].Id
|
|
})
|
|
|
|
return serverList, nil
|
|
}
|
|
|
|
func (this *GateManager) GetNotice() ([]*Notice, error) {
|
|
var now = util.NowUnix()
|
|
cur, err := this.mongoClient.Collection(tableNotice).Find(this.mongoClient.Context(), bson.M{"begin_time": bson.M{"$lt": now}, "end_time": bson.M{"$gt": now}})
|
|
if err != nil {
|
|
if errors.Is(err, mongo.ErrNoDocuments) {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
defer cur.Close(this.mongoClient.Context())
|
|
|
|
var notices []*Notice
|
|
for cur.Next(this.mongoClient.Context()) {
|
|
var notice = new(Notice)
|
|
err = cur.Decode(notice)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
notices = append(notices, notice)
|
|
}
|
|
return notices, nil
|
|
}
|
|
|
|
func (this *GateManager) AddNotice(notice *Notice) error {
|
|
_, err := this.mongoClient.Collection(tableNotice).InsertOne(this.mongoClient.Context(), notice)
|
|
return err
|
|
}
|
|
|
|
func (this *GateManager) DeleteNotice(id uint64) error {
|
|
_, err := this.mongoClient.Collection(tableNotice).DeleteOne(this.mongoClient.Context(), bson.M{"_id": id})
|
|
return err
|
|
}
|