game_sync/robot/base/clientmgr.go

185 lines
5.2 KiB
Go

package base
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"math/rand"
"os"
"strconv"
"time"
"github.com/globalsign/mgo/bson"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/goserver/core/timer"
"mongo.games.com/game/common"
"mongo.games.com/game/model"
"mongo.games.com/game/proto"
loginproto "mongo.games.com/game/protocol/login"
serverproto "mongo.games.com/game/protocol/server"
)
/*
登录及机器人账号更新
*/
var ClientMgrSingleton = &ClientMgr{
sessionPool: make(map[string]*netlib.Session),
Running: true,
CycleTimeEvent: [24][]HourEvent{},
}
type HourEvent struct {
newAcc string //wait to open
oldAcc string //wait to close
session *netlib.Session
}
type InvalidAcc struct {
Acc string
Session *netlib.Session
}
type ClientMgr struct {
sessionPool map[string]*netlib.Session
Running bool
CycleTimeEvent [24][]HourEvent
}
// 发送登录消息
func (this *ClientMgr) startLogin(acc string, s *netlib.Session) {
ts := time.Now().UnixNano()
csLogin := &loginproto.CSLogin{
Username: proto.String(acc),
TimeStamp: proto.Int64(ts),
Platform: proto.String(common.Platform_Rob),
Channel: proto.String(common.Channel_Rob),
}
params := &model.PlayerParams{
Ip: fmt.Sprintf("%v.%v.%v.%v", 1+rand.Int31n(255), 1+rand.Int31n(255), 1+rand.Int31n(255), 1+rand.Int31n(255)),
City: RandZone(),
Platform: 1,
Logininmodel: "app",
}
data, err := json.Marshal(params)
if err == nil {
csLogin.Params = proto.String(string(data[:]))
}
h := md5.New()
io.WriteString(h, fmt.Sprintf("%v%v", acc, Config.AppId))
pwd := hex.EncodeToString(h.Sum(nil))
h.Reset()
io.WriteString(h, fmt.Sprintf("%v%v%v", pwd, Config.AppId, ts))
pwd = hex.EncodeToString(h.Sum(nil))
csLogin.Password = pwd
csLogin.LoginType = proto.Int32(0)
csLogin.Sign = proto.String(common.MakeMd5String(csLogin.GetUsername(), csLogin.GetPassword(),
strconv.Itoa(int(csLogin.GetTimeStamp())), csLogin.GetParams(), Config.AppId))
s.Send(int(loginproto.LoginPacketID_PACKET_CS_LOGIN), csLogin)
logger.Logger.Infof("账号 [%v] 开始登录", acc)
}
func (this *ClientMgr) RegisterSession(acc string, s *netlib.Session) {
this.sessionPool[acc] = s
StartSessionLoginTimer(s, timer.TimerActionWrapper(func(h timer.TimerHandle, ud interface{}) bool {
if !s.IsConned() || !this.Running {
StopSessionLoginTimer(s)
return false
}
this.startLogin(acc, s)
return true
}), nil, time.Second*time.Duration(2+rand.Int31n(3)), -1)
}
func (this *ClientMgr) UnRegisterSession(acc string) {
delete(this.sessionPool, acc)
}
func (this *ClientMgr) HourChange() {
fileModify := false
eventArr := this.CycleTimeEvent[time.Now().Hour()]
for _, event := range eventArr {
accChan[event.newAcc] = true //使用新的账号
cfg := NewSessionConfig()
netlib.Connect(cfg) //创建新的连接
if session, ok := this.sessionPool[event.oldAcc]; ok && session != nil {
//删除旧有账号数据
pack := &serverproto.RWAccountInvalid{
Acc: proto.String(event.oldAcc),
}
session.Send(int(loginproto.LoginPacketID_PACKET_CS_ACCOUNTINVALID), pack) // 删除机器人账号
//删号标记,不要在断线重连了
session.SetAttribute(SessionAttributeDelAccount, true)
//关闭连接
session.Close()
}
//更新本地账号数据信息
for key, value := range accPool {
if value.Acc == event.oldAcc {
accPool[key] = &AccountData{
Acc: event.newAcc,
Create: time.Now().UnixNano(),
Time: time.Now(),
}
fileModify = true
break
}
}
}
this.CycleTimeEvent[time.Now().Hour()] = []HourEvent{}
if fileModify == true {
//持久化本次的账号数据
buff, err := json.Marshal(accPool)
if err != nil {
logger.Logger.Error("Marshal account data error:", err)
} else {
err := os.WriteFile(accountFileName, buff, os.ModePerm)
if err != nil {
logger.Logger.Error("Write robot account file error:", err)
}
}
}
}
func (this *ClientMgr) DayChange() {
invalidCount := 0 //过期账号数量
updateLimit := len(accPool) * model.GameParamData.InvalidRobotAccRate / 100 //可更新的账号数量
invalidAccs := []InvalidAcc{}
if updateLimit > 0 {
invalideTime := time.Now().AddDate(0, 0, -model.GameParamData.InvalidRobotDay).UnixNano()
for _, value := range accPool {
//检查过期账号
if value.Create < invalideTime {
//过期账号
invalidAccs = append(invalidAccs, InvalidAcc{
Acc: value.Acc,
Session: this.sessionPool[value.Acc],
})
invalidCount++
j := rand.Intn(invalidCount)
i := invalidCount - 1
if i != j {
invalidAccs[i], invalidAccs[j] = invalidAccs[j], invalidAccs[i]
}
}
}
if len(invalidAccs) >= updateLimit {
invalidAccs = invalidAccs[:updateLimit]
}
}
//本次需要生成的新账号
cnt := len(invalidAccs)
for i := 0; i < cnt; i++ {
timePoint := i % 24
eventArr := this.CycleTimeEvent[timePoint]
eventArr = append(eventArr, HourEvent{
newAcc: bson.NewObjectId().Hex(),
oldAcc: invalidAccs[i].Acc,
session: invalidAccs[i].Session,
})
this.CycleTimeEvent[timePoint] = eventArr
}
}