robotManager.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. package robot
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "math/rand"
  7. "sync"
  8. "time"
  9. "bet24.com/log"
  10. "bet24.com/servers/insecureframe/gate"
  11. "bet24.com/servers/insecureframe/message"
  12. "bet24.com/servers/transaction"
  13. "bet24.com/servers/user"
  14. )
  15. type robotInfo struct {
  16. userIndex int32
  17. lastTick int64
  18. }
  19. type RobotManager struct {
  20. sink gate.GateSink
  21. gate *gate.Gate
  22. robotList []robotInfo //保存机器人的index
  23. lock_robot *sync.RWMutex
  24. isStopping bool
  25. }
  26. var robotMMgr *RobotManager
  27. func NewRobotManager(s gate.GateSink, g *gate.Gate) *RobotManager {
  28. r := new(RobotManager)
  29. r.lock_robot = &sync.RWMutex{}
  30. r.sink = s
  31. r.gate = g
  32. r.isStopping = false
  33. go r.checkOnline()
  34. return r
  35. }
  36. func (rm *RobotManager) checkOnline() {
  37. for {
  38. c, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  39. select {
  40. case <-c.Done():
  41. cancel()
  42. if rm.isStopping {
  43. return
  44. }
  45. robotCount := rm.sink.GetRobotCount()
  46. rm.lock_robot.RLock()
  47. currentCount := len(rm.robotList)
  48. rm.lock_robot.RUnlock()
  49. if currentCount > robotCount {
  50. log.Debug("RobotManager.checkOnline [%d] > [%d]", currentCount, robotCount)
  51. rm.retireOneRobot(true)
  52. }
  53. if currentCount < robotCount {
  54. rm.oneRobotLogin()
  55. }
  56. rm.retireOneRobot(false)
  57. }
  58. }
  59. }
  60. func (rm *RobotManager) retireOneRobot(force bool) {
  61. //min, max := rm.sink.GetRobotGoldLimit()
  62. now := time.Now().Unix()
  63. var toRemove []int32
  64. var backupRemove int32
  65. rm.lock_robot.RLock()
  66. for _, v := range rm.robotList {
  67. index := v.userIndex
  68. usr := gate.GetUserInfo(index)
  69. if usr == nil {
  70. toRemove = append(toRemove, index)
  71. log.Debug("RobotManager.retireOneRobot [%d] usr == nil", index)
  72. continue
  73. }
  74. //还在游戏中,不处理
  75. if usr.GetUserStatus() == user.UserStatus_Play || usr.GetUserStatus() == user.UserStatus_Ready {
  76. continue
  77. }
  78. //是否超出金币上下限
  79. /*gold := usr.GetUserGold()
  80. if gold < min || (max > 0 && gold > max) {
  81. log.Debug("RobotManager.retireOneRobot [%d] [%d-%d]%d", index, min, max, gold)
  82. toRemove = append(toRemove, usr.GetUserIndex())
  83. continue
  84. }*/
  85. //在线时长满了
  86. logonTime := usr.GetLogonTime()
  87. if int(now-logonTime) >= rm.sink.GetRobotOnlineSec() {
  88. log.Debug("RobotManager.retireOneRobot [%d] [%d-%d]>=%d", index, now, logonTime, rm.sink.GetRobotOnlineSec())
  89. toRemove = append(toRemove, usr.GetUserIndex())
  90. break
  91. }
  92. backupRemove = usr.GetUserIndex()
  93. }
  94. rm.lock_robot.RUnlock()
  95. if len(toRemove) == 0 {
  96. if !force {
  97. return
  98. }
  99. log.Debug("RobotManager.retireOneRobot [%d] forced", backupRemove)
  100. go rm.oneRobotLogout(backupRemove)
  101. return
  102. }
  103. for _, v := range toRemove {
  104. go rm.oneRobotLogout(v)
  105. }
  106. }
  107. func (rm *RobotManager) loadRobot() {
  108. robotCount := rm.sink.GetRobotCount()
  109. for i := 0; i < robotCount; i++ {
  110. if !rm.oneRobotLogin() {
  111. log.Debug("RobotManager.loadRobot failed")
  112. }
  113. }
  114. log.Debug("---------loadRobot: %d ---------", len(rm.robotList))
  115. }
  116. func (rm *RobotManager) oneRobotLogin() bool {
  117. return rm.oneRobotLoginWithGoldLimit(rm.sink.GetRobotGoldLimit())
  118. }
  119. func (rm *RobotManager) oneRobotLoginWithGoldLimit(min, max int) bool {
  120. if max == 0 {
  121. max = 100000000000
  122. }
  123. obj := transaction.NewTransRobotLogin()
  124. obj.In.GameID = rm.sink.GetGameID()
  125. obj.In.ServerName = rm.sink.GetGameName()
  126. obj.In.MinBeans, obj.In.MaxBeans = min, max
  127. obj.DoAction(nil)
  128. if !obj.State {
  129. return false
  130. }
  131. log.Debug("---------get one robot from DB: %d,[%d,%d] ---------", obj.Out.UserID, min, max)
  132. if obj.Out.UserID == 0 {
  133. return false
  134. }
  135. //检查是否有重复机器人
  136. rm.lock_robot.RLock()
  137. flag := false
  138. for _, v := range rm.robotList {
  139. u := gate.GetUserInfo(v.userIndex)
  140. if u == nil {
  141. go rm.userExit(v.userIndex)
  142. continue
  143. }
  144. if u.GetUserId() == obj.Out.UserID {
  145. flag = true
  146. break
  147. }
  148. }
  149. rm.lock_robot.RUnlock()
  150. if gate.GetUserByUserId(obj.Out.UserID) != nil {
  151. flag = true
  152. }
  153. if flag {
  154. return false
  155. }
  156. index := rm.gate.GenUserIndex()
  157. a := gate.NewClient(index, nil, rm.gate, true)
  158. go a.Run()
  159. //模拟登录
  160. login := transaction.NewCheckUserPassword()
  161. login.IN.UserID = obj.Out.UserID
  162. login.IN.Password = obj.Out.Password
  163. d, _ := json.Marshal(login.IN)
  164. a.Login("login", string(d))
  165. usr := gate.GetUserInfo(index)
  166. if usr == nil {
  167. return false
  168. }
  169. rm.lock_robot.Lock()
  170. rm.robotList = append(rm.robotList, robotInfo{userIndex: index, lastTick: 0})
  171. rm.lock_robot.Unlock()
  172. // 增加机器人随机在线
  173. usr.SetLogonTime(time.Now().Unix())
  174. if !rm.sink.IsChipRoom() {
  175. log.Debug("机器人登录成功 %d Gold:%d", obj.Out.UserID, usr.GetUserGold())
  176. } else {
  177. // 筹码场,服务器自行决定筹码数量
  178. usr.SetChip(rand.Intn(max-min) + min)
  179. log.Debug("机器人登录成功 %d Chip:%d", obj.Out.UserID, usr.GetChip())
  180. }
  181. return true
  182. }
  183. func (rm *RobotManager) getOneRobotEnterTable(tableID, min, max int, retry bool, ready bool) bool {
  184. isChipRoom := rm.sink.IsChipRoom()
  185. log.Debug("RobotManager.getOneRobotEnterTable : %d [%d-%d] ChipRoom[%v]", tableID, min, max, isChipRoom)
  186. now := time.Now().Unix()
  187. var foundUser *user.UserInfo
  188. rm.lock_robot.Lock()
  189. robotCount := len(rm.robotList)
  190. if robotCount == 0 {
  191. rm.lock_robot.Unlock()
  192. fmt.Print("游戏阶段=====robotCount",robotCount)
  193. return false
  194. }
  195. rn := rand.Intn(robotCount)
  196. for i := 0; i < robotCount; i++ {
  197. index := (rn + i) % robotCount
  198. v := rm.robotList[index]
  199. if now-v.lastTick < 5 {
  200. continue
  201. }
  202. usr := gate.GetUserInfo(v.userIndex)
  203. if usr == nil {
  204. go rm.userExit(v.userIndex)
  205. continue
  206. }
  207. if int(now-usr.GetLogonTime()) >= rm.sink.GetRobotOnlineSec() {
  208. //go rm.oneRobotLogout(v.userIndex)
  209. continue
  210. }
  211. if usr.GetUserStatus() == user.UserStatus_Free {
  212. foundUser = usr
  213. rm.robotList[index].lastTick = now
  214. break
  215. }
  216. }
  217. rm.lock_robot.Unlock()
  218. if foundUser != nil {
  219. if max <= min {
  220. max = min * 20
  221. }
  222. gold := min + rand.Intn(max-min)
  223. if isChipRoom {
  224. foundUser.SetChip(gold)
  225. } else {
  226. foundUser.SetUserGold(gold)
  227. }
  228. log.Debug("RobotManager.getOneRobotEnterTable: %d enter table: %d -----gold=[%d]", foundUser.GetUserId(), tableID, gold)
  229. var sit message.SitTable
  230. sit.TableId = tableID
  231. sit.ChairId = -1
  232. d, _ := json.Marshal(sit)
  233. rm.sink.OnGameMessage(foundUser.GetUserIndex(), foundUser.GetUserId(), message.Frame_Sit, string(d))
  234. if ready {
  235. rm.sink.OnGameMessage(foundUser.GetUserIndex(), foundUser.GetUserId(), message.Frame_Ready, "")
  236. }
  237. return true
  238. }
  239. log.Debug("RobotManager.getOneRobotEnterTable no robot found %d-%d", min, max)
  240. flag := rm.oneRobotLoginWithGoldLimit(min, max)
  241. if flag && !retry {
  242. log.Debug("RobotManager.getOneRobotEnterTable enter a new Robot")
  243. rm.getOneRobotEnterTable(tableID, min, max, true, ready)
  244. }
  245. return false
  246. }
  247. func (rm *RobotManager) robotOutTable(userIndex int32, tableID int) {
  248. rm.lock_robot.RLock()
  249. l := len(rm.robotList)
  250. for i := 0; i < l; i++ {
  251. if rm.robotList[i].userIndex == userIndex {
  252. rm.lock_robot.RUnlock()
  253. usr := gate.GetUserInfo(userIndex)
  254. if usr == nil {
  255. log.Debug("ERROR: robot is no exist!")
  256. return
  257. }
  258. var sit message.SitTable
  259. sit.TableId = tableID
  260. sit.ChairId = -1
  261. d, _ := json.Marshal(sit)
  262. rm.sink.OnGameMessage(usr.GetUserIndex(), usr.GetUserId(), message.Frame_Standup, string(d))
  263. return
  264. }
  265. }
  266. rm.lock_robot.RUnlock()
  267. }
  268. func (rm *RobotManager) oneRobotLogout(userIndex int32) {
  269. usr := gate.GetUserInfo(userIndex)
  270. if usr == nil {
  271. rm.userExit(userIndex)
  272. return
  273. }
  274. //还在游戏中,不处理
  275. if usr.GetUserStatus() == user.UserStatus_Play {
  276. return
  277. }
  278. obj := transaction.NewTransRobotLogout()
  279. obj.In.GameID = rm.sink.GetGameID()
  280. obj.In.ServerName = rm.sink.GetGameName()
  281. obj.In.UserID = usr.GetUserId()
  282. gate.KickUser(userIndex)
  283. go obj.DoAction(nil)
  284. //从机器人列表删除
  285. rm.lock_robot.Lock()
  286. defer rm.lock_robot.Unlock()
  287. for i := 0; i < len(rm.robotList); i++ {
  288. if rm.robotList[i].userIndex == userIndex {
  289. rm.robotList = append(rm.robotList[:i], rm.robotList[i+1:]...)
  290. return
  291. }
  292. }
  293. }
  294. func (rm *RobotManager) Exit() {
  295. rm.lock_robot.Lock()
  296. for _, v := range rm.robotList {
  297. index := v.userIndex
  298. usr := gate.GetUserInfo(index)
  299. if usr == nil {
  300. continue
  301. }
  302. //还在游戏中,不处理
  303. if usr.GetUserStatus() == user.UserStatus_Play {
  304. continue
  305. }
  306. log.Debug("----------exit kick user: %d ", usr.GetUserId())
  307. obj := transaction.NewTransRobotLogout()
  308. obj.In.GameID = rm.sink.GetGameID()
  309. obj.In.ServerName = rm.sink.GetGameName()
  310. obj.In.UserID = usr.GetUserId()
  311. go gate.KickUser(index)
  312. go obj.DoAction(nil)
  313. }
  314. rm.isStopping = true
  315. rm.lock_robot.Unlock()
  316. }
  317. func (rm *RobotManager) Dump() {
  318. rm.lock_robot.RLock()
  319. log.Release("++++++++++ Robot List Count: %d +++++++++++++++", len(rm.robotList))
  320. for _, v := range rm.robotList {
  321. usr := gate.GetUserInfo(v.userIndex)
  322. if usr == nil {
  323. continue
  324. }
  325. gold := 0
  326. golddesc := "Gold"
  327. if rm.sink.IsChipRoom() {
  328. gold = usr.GetChip()
  329. golddesc = "Chip"
  330. } else {
  331. gold = usr.GetUserGold()
  332. }
  333. log.Release("Robot[%d]: %d, Status: %d, Online: %d 秒 %s: %d ",
  334. v.userIndex, usr.GetUserId(), usr.GetUserStatus(),
  335. time.Now().Unix()-usr.GetLogonTime(),
  336. golddesc, gold)
  337. }
  338. log.Release("++++++++++ Robot List End +++++++++++++++")
  339. rm.lock_robot.RUnlock()
  340. }
  341. func (rm *RobotManager) userExit(userIndex int32) {
  342. rm.lock_robot.Lock()
  343. defer rm.lock_robot.Unlock()
  344. for i := 0; i < len(rm.robotList); i++ {
  345. if rm.robotList[i].userIndex == userIndex {
  346. rm.robotList = append(rm.robotList[:i], rm.robotList[i+1:]...)
  347. return
  348. }
  349. }
  350. }
  351. func (rm *RobotManager) isRetired(userIndex int32) bool {
  352. usr := gate.GetUserInfo(userIndex)
  353. if usr == nil {
  354. return true
  355. }
  356. now := time.Now().Unix()
  357. logonTime := usr.GetLogonTime()
  358. return int(now-logonTime) >= rm.sink.GetRobotOnlineSec()
  359. }