| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- package robot
- import (
- "context"
- "encoding/json"
- "fmt"
- "math/rand"
- "sync"
- "time"
- "bet24.com/log"
- "bet24.com/servers/insecureframe/gate"
- "bet24.com/servers/insecureframe/message"
- "bet24.com/servers/transaction"
- "bet24.com/servers/user"
- )
- type robotInfo struct {
- userIndex int32
- lastTick int64
- }
- type RobotManager struct {
- sink gate.GateSink
- gate *gate.Gate
- robotList []robotInfo //保存机器人的index
- lock_robot *sync.RWMutex
- isStopping bool
- }
- var robotMMgr *RobotManager
- func NewRobotManager(s gate.GateSink, g *gate.Gate) *RobotManager {
- r := new(RobotManager)
- r.lock_robot = &sync.RWMutex{}
- r.sink = s
- r.gate = g
- r.isStopping = false
- go r.checkOnline()
- return r
- }
- func (rm *RobotManager) checkOnline() {
- for {
- c, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- select {
- case <-c.Done():
- cancel()
- if rm.isStopping {
- return
- }
- robotCount := rm.sink.GetRobotCount()
- rm.lock_robot.RLock()
- currentCount := len(rm.robotList)
- rm.lock_robot.RUnlock()
- if currentCount > robotCount {
- log.Debug("RobotManager.checkOnline [%d] > [%d]", currentCount, robotCount)
- rm.retireOneRobot(true)
- }
- if currentCount < robotCount {
- rm.oneRobotLogin()
- }
- rm.retireOneRobot(false)
- }
- }
- }
- func (rm *RobotManager) retireOneRobot(force bool) {
- //min, max := rm.sink.GetRobotGoldLimit()
- now := time.Now().Unix()
- var toRemove []int32
- var backupRemove int32
- rm.lock_robot.RLock()
- for _, v := range rm.robotList {
- index := v.userIndex
- usr := gate.GetUserInfo(index)
- if usr == nil {
- toRemove = append(toRemove, index)
- log.Debug("RobotManager.retireOneRobot [%d] usr == nil", index)
- continue
- }
- //还在游戏中,不处理
- if usr.GetUserStatus() == user.UserStatus_Play || usr.GetUserStatus() == user.UserStatus_Ready {
- continue
- }
- //是否超出金币上下限
- /*gold := usr.GetUserGold()
- if gold < min || (max > 0 && gold > max) {
- log.Debug("RobotManager.retireOneRobot [%d] [%d-%d]%d", index, min, max, gold)
- toRemove = append(toRemove, usr.GetUserIndex())
- continue
- }*/
- //在线时长满了
- logonTime := usr.GetLogonTime()
- if int(now-logonTime) >= rm.sink.GetRobotOnlineSec() {
- log.Debug("RobotManager.retireOneRobot [%d] [%d-%d]>=%d", index, now, logonTime, rm.sink.GetRobotOnlineSec())
- toRemove = append(toRemove, usr.GetUserIndex())
- break
- }
- backupRemove = usr.GetUserIndex()
- }
- rm.lock_robot.RUnlock()
- if len(toRemove) == 0 {
- if !force {
- return
- }
- log.Debug("RobotManager.retireOneRobot [%d] forced", backupRemove)
- go rm.oneRobotLogout(backupRemove)
- return
- }
- for _, v := range toRemove {
- go rm.oneRobotLogout(v)
- }
- }
- func (rm *RobotManager) loadRobot() {
- robotCount := rm.sink.GetRobotCount()
- for i := 0; i < robotCount; i++ {
- if !rm.oneRobotLogin() {
- log.Debug("RobotManager.loadRobot failed")
- }
- }
- log.Debug("---------loadRobot: %d ---------", len(rm.robotList))
- }
- func (rm *RobotManager) oneRobotLogin() bool {
- return rm.oneRobotLoginWithGoldLimit(rm.sink.GetRobotGoldLimit())
- }
- func (rm *RobotManager) oneRobotLoginWithGoldLimit(min, max int) bool {
- if max == 0 {
- max = 100000000000
- }
- obj := transaction.NewTransRobotLogin()
- obj.In.GameID = rm.sink.GetGameID()
- obj.In.ServerName = rm.sink.GetGameName()
- obj.In.MinBeans, obj.In.MaxBeans = min, max
- obj.DoAction(nil)
- if !obj.State {
- return false
- }
- log.Debug("---------get one robot from DB: %d,[%d,%d] ---------", obj.Out.UserID, min, max)
- if obj.Out.UserID == 0 {
- return false
- }
- //检查是否有重复机器人
- rm.lock_robot.RLock()
- flag := false
- for _, v := range rm.robotList {
- u := gate.GetUserInfo(v.userIndex)
- if u == nil {
- go rm.userExit(v.userIndex)
- continue
- }
- if u.GetUserId() == obj.Out.UserID {
- flag = true
- break
- }
- }
- rm.lock_robot.RUnlock()
- if gate.GetUserByUserId(obj.Out.UserID) != nil {
- flag = true
- }
- if flag {
- return false
- }
- index := rm.gate.GenUserIndex()
- a := gate.NewClient(index, nil, rm.gate, true)
- go a.Run()
- //模拟登录
- login := transaction.NewCheckUserPassword()
- login.IN.UserID = obj.Out.UserID
- login.IN.Password = obj.Out.Password
- d, _ := json.Marshal(login.IN)
- a.Login("login", string(d))
- usr := gate.GetUserInfo(index)
- if usr == nil {
- return false
- }
- rm.lock_robot.Lock()
- rm.robotList = append(rm.robotList, robotInfo{userIndex: index, lastTick: 0})
- rm.lock_robot.Unlock()
- // 增加机器人随机在线
- usr.SetLogonTime(time.Now().Unix())
- if !rm.sink.IsChipRoom() {
- log.Debug("机器人登录成功 %d Gold:%d", obj.Out.UserID, usr.GetUserGold())
- } else {
- // 筹码场,服务器自行决定筹码数量
- usr.SetChip(rand.Intn(max-min) + min)
- log.Debug("机器人登录成功 %d Chip:%d", obj.Out.UserID, usr.GetChip())
- }
- return true
- }
- func (rm *RobotManager) getOneRobotEnterTable(tableID, min, max int, retry bool, ready bool) bool {
- isChipRoom := rm.sink.IsChipRoom()
- log.Debug("RobotManager.getOneRobotEnterTable : %d [%d-%d] ChipRoom[%v]", tableID, min, max, isChipRoom)
- now := time.Now().Unix()
- var foundUser *user.UserInfo
- rm.lock_robot.Lock()
- robotCount := len(rm.robotList)
- if robotCount == 0 {
- rm.lock_robot.Unlock()
- fmt.Print("游戏阶段=====robotCount",robotCount)
- return false
- }
- rn := rand.Intn(robotCount)
- for i := 0; i < robotCount; i++ {
- index := (rn + i) % robotCount
- v := rm.robotList[index]
- if now-v.lastTick < 5 {
- continue
- }
- usr := gate.GetUserInfo(v.userIndex)
- if usr == nil {
- go rm.userExit(v.userIndex)
- continue
- }
- if int(now-usr.GetLogonTime()) >= rm.sink.GetRobotOnlineSec() {
- //go rm.oneRobotLogout(v.userIndex)
- continue
- }
- if usr.GetUserStatus() == user.UserStatus_Free {
- foundUser = usr
- rm.robotList[index].lastTick = now
- break
- }
- }
- rm.lock_robot.Unlock()
- if foundUser != nil {
- if max <= min {
- max = min * 20
- }
- gold := min + rand.Intn(max-min)
- if isChipRoom {
- foundUser.SetChip(gold)
- } else {
- foundUser.SetUserGold(gold)
- }
- log.Debug("RobotManager.getOneRobotEnterTable: %d enter table: %d -----gold=[%d]", foundUser.GetUserId(), tableID, gold)
- var sit message.SitTable
- sit.TableId = tableID
- sit.ChairId = -1
- d, _ := json.Marshal(sit)
- rm.sink.OnGameMessage(foundUser.GetUserIndex(), foundUser.GetUserId(), message.Frame_Sit, string(d))
- if ready {
- rm.sink.OnGameMessage(foundUser.GetUserIndex(), foundUser.GetUserId(), message.Frame_Ready, "")
- }
- return true
- }
- log.Debug("RobotManager.getOneRobotEnterTable no robot found %d-%d", min, max)
- flag := rm.oneRobotLoginWithGoldLimit(min, max)
- if flag && !retry {
- log.Debug("RobotManager.getOneRobotEnterTable enter a new Robot")
- rm.getOneRobotEnterTable(tableID, min, max, true, ready)
- }
- return false
- }
- func (rm *RobotManager) robotOutTable(userIndex int32, tableID int) {
- rm.lock_robot.RLock()
- l := len(rm.robotList)
- for i := 0; i < l; i++ {
- if rm.robotList[i].userIndex == userIndex {
- rm.lock_robot.RUnlock()
- usr := gate.GetUserInfo(userIndex)
- if usr == nil {
- log.Debug("ERROR: robot is no exist!")
- return
- }
- var sit message.SitTable
- sit.TableId = tableID
- sit.ChairId = -1
- d, _ := json.Marshal(sit)
- rm.sink.OnGameMessage(usr.GetUserIndex(), usr.GetUserId(), message.Frame_Standup, string(d))
- return
- }
- }
- rm.lock_robot.RUnlock()
- }
- func (rm *RobotManager) oneRobotLogout(userIndex int32) {
- usr := gate.GetUserInfo(userIndex)
- if usr == nil {
- rm.userExit(userIndex)
- return
- }
- //还在游戏中,不处理
- if usr.GetUserStatus() == user.UserStatus_Play {
- return
- }
- obj := transaction.NewTransRobotLogout()
- obj.In.GameID = rm.sink.GetGameID()
- obj.In.ServerName = rm.sink.GetGameName()
- obj.In.UserID = usr.GetUserId()
- gate.KickUser(userIndex)
- go obj.DoAction(nil)
- //从机器人列表删除
- rm.lock_robot.Lock()
- defer rm.lock_robot.Unlock()
- for i := 0; i < len(rm.robotList); i++ {
- if rm.robotList[i].userIndex == userIndex {
- rm.robotList = append(rm.robotList[:i], rm.robotList[i+1:]...)
- return
- }
- }
- }
- func (rm *RobotManager) Exit() {
- rm.lock_robot.Lock()
- for _, v := range rm.robotList {
- index := v.userIndex
- usr := gate.GetUserInfo(index)
- if usr == nil {
- continue
- }
- //还在游戏中,不处理
- if usr.GetUserStatus() == user.UserStatus_Play {
- continue
- }
- log.Debug("----------exit kick user: %d ", usr.GetUserId())
- obj := transaction.NewTransRobotLogout()
- obj.In.GameID = rm.sink.GetGameID()
- obj.In.ServerName = rm.sink.GetGameName()
- obj.In.UserID = usr.GetUserId()
- go gate.KickUser(index)
- go obj.DoAction(nil)
- }
- rm.isStopping = true
- rm.lock_robot.Unlock()
- }
- func (rm *RobotManager) Dump() {
- rm.lock_robot.RLock()
- log.Release("++++++++++ Robot List Count: %d +++++++++++++++", len(rm.robotList))
- for _, v := range rm.robotList {
- usr := gate.GetUserInfo(v.userIndex)
- if usr == nil {
- continue
- }
- gold := 0
- golddesc := "Gold"
- if rm.sink.IsChipRoom() {
- gold = usr.GetChip()
- golddesc = "Chip"
- } else {
- gold = usr.GetUserGold()
- }
- log.Release("Robot[%d]: %d, Status: %d, Online: %d 秒 %s: %d ",
- v.userIndex, usr.GetUserId(), usr.GetUserStatus(),
- time.Now().Unix()-usr.GetLogonTime(),
- golddesc, gold)
- }
- log.Release("++++++++++ Robot List End +++++++++++++++")
- rm.lock_robot.RUnlock()
- }
- func (rm *RobotManager) userExit(userIndex int32) {
- rm.lock_robot.Lock()
- defer rm.lock_robot.Unlock()
- for i := 0; i < len(rm.robotList); i++ {
- if rm.robotList[i].userIndex == userIndex {
- rm.robotList = append(rm.robotList[:i], rm.robotList[i+1:]...)
- return
- }
- }
- }
- func (rm *RobotManager) isRetired(userIndex int32) bool {
- usr := gate.GetUserInfo(userIndex)
- if usr == nil {
- return true
- }
- now := time.Now().Unix()
- logonTime := usr.GetLogonTime()
- return int(now-logonTime) >= rm.sink.GetRobotOnlineSec()
- }
|