gameframe.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. package frame
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "math/rand"
  6. "sync"
  7. "time"
  8. //utils2 "bet24.com/servers/insecureframe/gate/Utils"
  9. "bet24.com/log"
  10. "bet24.com/redis"
  11. "bet24.com/servers/insecureframe/gate"
  12. "bet24.com/servers/insecureframe/message"
  13. "bet24.com/servers/insecureframe/robot"
  14. "bet24.com/servers/user"
  15. )
  16. func NewGameFrame(gameSink GameSink) *GameFrame {
  17. f := new(GameFrame)
  18. f.gameSink = gameSink
  19. f.tables = make(map[int]*ThreadsafeTable)
  20. f.lock_table = &sync.RWMutex{}
  21. f.lock_user = &sync.RWMutex{}
  22. f.lock_changeTable = &sync.RWMutex{}
  23. f.tableIndex = 1
  24. f.offlineUsers = make(map[int]offlineUser)
  25. time.AfterFunc(10*time.Second, f.checkOfflineUsers)
  26. f.changeTableCount = make(map[int32]int)
  27. f.roomDatas = gameSink.GetRoomDatas()
  28. if len(f.roomDatas) > 0 {
  29. time.AfterFunc(10*time.Second, f.checkCreateRobotRoom)
  30. }
  31. log.Debug("gameframe running...")
  32. return f
  33. }
  34. type offlineUser struct {
  35. userInfo *user.UserInfo
  36. offlineTime int64
  37. tableId int
  38. userIndex int32
  39. }
  40. type GameFrame struct {
  41. gameSink GameSink
  42. tableIndex int
  43. // --GameTable++
  44. tables map[int]*ThreadsafeTable
  45. lock_table *sync.RWMutex
  46. lock_user *sync.RWMutex
  47. offlineUsers map[int]offlineUser
  48. roomDatas []string
  49. lock_changeTable *sync.RWMutex
  50. changeTableCount map[int32]int
  51. }
  52. func (f *GameFrame) CreateBacTable() {
  53. // 如果是百人游戏,不是私人场
  54. if f.gameSink.GetChairCount() < 2 && !f.gameSink.IsPrivateRoom() {
  55. // 创建一张默认桌子
  56. f.createTable("")
  57. }
  58. }
  59. // implement GateSink
  60. func (f *GameFrame) GetServerPort() int {
  61. return f.gameSink.GetServerPort()
  62. }
  63. func (f *GameFrame) checkCreateRobotRoom() {
  64. if !robot.IsRunning() {
  65. return
  66. }
  67. if stopping {
  68. return
  69. }
  70. for _, v := range f.roomDatas {
  71. minRoomCount := f.gameSink.GetMinRoomCount(v)
  72. //log.Debug("checkCreateRobotRoom %s:%d", v, minRoomCount)
  73. if minRoomCount == 0 {
  74. continue
  75. }
  76. existCount := f.getTableCount(v)
  77. for i := 0; i < minRoomCount-existCount; i++ {
  78. t := f.createTable(v)
  79. if t == nil {
  80. log.Debug("checkCreateRobotRoom creating table failed %s", v)
  81. continue
  82. }
  83. min, max := f.gameSink.GetRoomRobotGoldLimit(v)
  84. enterRobotCount := 2
  85. if f.gameSink.GetChairCount() == 1 {
  86. enterRobotCount = f.gameSink.GetRoomRobotCount(v)
  87. }
  88. for i := 0; i < enterRobotCount; i++ {
  89. go robot.GetOneRobotEnterTableAndReady(t.tableId, min, max)
  90. }
  91. }
  92. }
  93. time.AfterFunc(60*time.Second, f.checkCreateRobotRoom)
  94. }
  95. func (f *GameFrame) checkAndCreateTable(roomData string) {
  96. }
  97. func (f *GameFrame) checkOfflineUsers() {
  98. offlineSeconds := f.gameSink.GetOfflineSeconds()
  99. if offlineSeconds <= 0 {
  100. log.Debug("GameFrame.checkOfflineUsers 不支持断线续玩")
  101. return
  102. }
  103. //log.Debug("GameFrame.checkOfflineUsers offlineSeconds = %d", offlineSeconds)
  104. time.AfterFunc(10*time.Second, f.checkOfflineUsers)
  105. now := time.Now().Unix()
  106. f.lock_user.RLock()
  107. for k, v := range f.offlineUsers {
  108. if now-v.offlineTime >= offlineSeconds {
  109. go f.removeOfflineUser(k, v.userInfo)
  110. }
  111. }
  112. f.lock_user.RUnlock()
  113. }
  114. func (f *GameFrame) OnUserEnter(userIndex int32) {
  115. }
  116. func (f *GameFrame) delayUserWatchTable(userIndex int32, tableId int) {
  117. table := f.getTable(1)
  118. if table == nil {
  119. return
  120. }
  121. //time.Sleep(50 * time.Millisecond)
  122. go table.AddTableUser(userIndex, 0, false, true)
  123. }
  124. func (f *GameFrame) OnUserLogined(userIndex int32) {
  125. // 是否属于断线玩家
  126. usr := gate.GetUserInfo(userIndex)
  127. if usr == nil {
  128. log.Debug("GameFrame.OnUserLogined user not exist")
  129. return
  130. }
  131. // 发送一下自己进入的消息
  132. //user2 := utils2.GetUserInfoData(1)
  133. // fmt.Printf("用户登录成功==",user2)
  134. // usr.SetUserNickName(user2.Data[0].NickName)
  135. // usr.SetUserGold(user2.Data[0].GoldCoins)
  136. info := usr.GetUserInfo_Table(true)
  137. d, _ := json.Marshal(info)
  138. fmt.Println("获取用户信息=====",info)
  139. gate.SendMessage(userIndex, message.Frame_UserEnter, string(d))
  140. // 如果是百人场,直接进入旁观
  141. /*if f.gameSink.GetChairCount() < 2 && !f.gameSink.IsPrivateRoom() {
  142. go f.delayUserWatchTable(userIndex, 1)
  143. return
  144. }*/
  145. //发送场次列表
  146. // d, _ = json.Marshal(f.gameSink.GetRoomList())
  147. // gate.SendMessage(userIndex, message.Frame_GetRoomList, string(d))
  148. userId := usr.GetUserId()
  149. f.lock_user.RLock()
  150. offlineUser, ok := f.offlineUsers[userId]
  151. f.lock_user.RUnlock()
  152. if !ok {
  153. return
  154. }
  155. table := f.getTable(offlineUser.tableId)
  156. if table == nil /*table.tableStatus != TableStatus_Playing*/ {
  157. log.Debug("GameFrame.OnUserLogined replay table[%d] not found", offlineUser.tableId)
  158. return
  159. }
  160. log.Debug("GameFrame.OnUserLogined 用户 %d 断线回来了", userId)
  161. usr.SetUserStatus(user.UserStatus_Offline)
  162. table.userReplay(offlineUser.userInfo.GetUserIndex(), usr)
  163. // 通知完桌子后再删除断线用户信息
  164. f.lock_user.Lock()
  165. delete(f.offlineUsers, userId)
  166. f.lock_user.Unlock()
  167. }
  168. func (f *GameFrame) OnUserExit(userIndex int32) {
  169. if robot.IsRunning() {
  170. robot.UserExit(userIndex)
  171. }
  172. f.lock_changeTable.Lock()
  173. delete(f.changeTableCount, userIndex)
  174. f.lock_changeTable.Unlock()
  175. usr := gate.GetUserInfo(userIndex)
  176. if usr == nil {
  177. log.Debug("GameFrame.OnUserExit user[%d] not exist", userIndex)
  178. return
  179. }
  180. table := f.getTable(usr.GetUserTableId())
  181. if table == nil {
  182. log.Debug("GameFrame.OnUserExit user[%d] table[%d] not found", userIndex, usr.GetUserTableId())
  183. return
  184. }
  185. // 是否断线?
  186. oldStatus := usr.GetUserStatus()
  187. if oldStatus == user.UserStatus_Play {
  188. if f.addOfflineUser(usr) {
  189. table.tableSink.OnUserOffline(usr.GetUserChairId())
  190. // 广播玩家断线状态
  191. d, _ := json.Marshal(message.UserStatusChange{UserId: usr.GetUserId(),
  192. OldStatus: oldStatus,
  193. NewStatus: user.UserStatus_Offline,
  194. TableId: usr.GetUserTableId(),
  195. ChairId: usr.GetUserChairId()})
  196. gate.BroadcastData(message.Frame_UserStatusChange, string(d))
  197. return
  198. }
  199. }
  200. f.setOfflineStatus(usr.GetUserId(), false, table.privateData)
  201. table.RemoveUser(userIndex, false, false)
  202. }
  203. func (f *GameFrame) addOfflineUser(usr *user.UserInfo) bool {
  204. if f.gameSink.GetOfflineSeconds() <= 0 {
  205. return false
  206. }
  207. userId := usr.GetUserId()
  208. f.lock_user.Lock()
  209. defer f.lock_user.Unlock()
  210. _, ok := f.offlineUsers[userId]
  211. if ok {
  212. log.Debug("GameFrame.addOfflineUser userId[%d] already exist", userId)
  213. return false
  214. }
  215. log.Debug("addOfflineUser %d", userId)
  216. usr.SetUserStatus(user.UserStatus_Offline)
  217. f.offlineUsers[userId] = offlineUser{userInfo: usr.GetCopy(), offlineTime: time.Now().Unix(),
  218. tableId: usr.GetUserTableId(), userIndex: usr.GetUserIndex()}
  219. return true
  220. }
  221. func (f *GameFrame) removeOfflineUser(userIdKey int, usr *user.UserInfo) {
  222. userId := usr.GetUserId()
  223. userIndex := usr.GetUserIndex()
  224. f.lock_user.Lock()
  225. ou, ok := f.offlineUsers[userIdKey]
  226. if !ok {
  227. log.Debug("GameFrame.removeOfflineUser userId[%d] not found,userIdKey = %d", userId, userIdKey)
  228. delete(f.offlineUsers, userIdKey)
  229. f.lock_user.Unlock()
  230. return
  231. }
  232. f.lock_user.Unlock()
  233. log.Debug("GameFrame.removeOfflineUser removing %d %d %d ", userId, userIndex, ou.userIndex)
  234. table := f.getTable(ou.tableId)
  235. if table != nil {
  236. table.RemoveUser(userIndex, false, false)
  237. }
  238. log.Debug("GameFrame.removeOfflineUser removed %d ", userId)
  239. f.lock_user.Lock()
  240. delete(f.offlineUsers, userIdKey)
  241. f.lock_user.Unlock()
  242. }
  243. func (f *GameFrame) removeOfflineByTableId(tableId int) {
  244. f.lock_user.RLock()
  245. defer f.lock_user.RUnlock()
  246. for k, v := range f.offlineUsers {
  247. if v.tableId == tableId {
  248. go f.removeOfflineUser(k, v.userInfo)
  249. go f.setOfflineStatus(k, false, "")
  250. }
  251. }
  252. }
  253. func (f *GameFrame) OnGameMessage(userIndex int32, userID int, msg, data string) bool {
  254. switch msg {
  255. case message.Frame_AutoSit:
  256. return f.recvAutoSit(userIndex, data, false, false)
  257. case message.Frame_NewUserAutoSit:
  258. return f.recvAutoSit(userIndex, data, false, true)
  259. case message.Frame_ChangeTable:
  260. return f.recvChangeTable(userIndex, data)
  261. case message.Frame_Sit:
  262. return f.recvSitTable(userIndex, data)
  263. case message.Frame_WatchTable:
  264. return f.recvWatchTable(userIndex, data)
  265. case message.Frame_Standup:
  266. return f.recvStandup(userIndex, data)
  267. case message.Frame_Watch:
  268. return f.recvWatch(userIndex, data)
  269. case message.Frame_Ready:
  270. return f.recvReady(userIndex, true)
  271. case message.Frame_CancelReady:
  272. return f.recvReady(userIndex, false)
  273. // case message.Frame_GetRoomList:
  274. // return f.recvGetRoomList(userIndex, msg)
  275. case message.Frame_ADReward:
  276. return f.recvAdReward(userIndex, data)
  277. case message.Frame_Ping:
  278. return f.recvFramePing(userIndex, data)
  279. /*case message.Frame_CreatePrivateRoom:
  280. return f.createPrivateRoom(userIndex, data)
  281. case message.Frame_PrivateRoom_SetBaseScore:
  282. return f.privateRoomSetBaseScore(userIndex, data)*/
  283. case message.Frame_PrivateRoom_RequestDismiss:
  284. return f.recvPrivateRoomRequestDismiss(userIndex, msg, data)
  285. case message.Frame_PrivateRoom_DismissResp:
  286. return f.recvPrivateRoomDismissResp(userIndex, msg, data)
  287. case message.Frame_Voice:
  288. return f.recvFrameVoiceMessage(userIndex, userID, msg, data)
  289. case message.Frame_PrivateRoom_KickUser:
  290. return f.recvPrivateRoomKick(userIndex, msg, data)
  291. default:
  292. return f.recvTableMessage(userIndex, userID, msg, data)
  293. }
  294. }
  295. func (f *GameFrame) GetGameID() int {
  296. return f.gameSink.GetGameID()
  297. }
  298. func (f *GameFrame) GetGameName() string {
  299. return f.gameSink.GetGameName()
  300. }
  301. func (f *GameFrame) GetRoomName() string {
  302. return f.gameSink.GetRoomName()
  303. }
  304. func (f *GameFrame) GetCertFile() string {
  305. return f.gameSink.GetCertFile()
  306. }
  307. func (f *GameFrame) GetKeyFile() string {
  308. return f.gameSink.GetKeyFile()
  309. }
  310. // 机器人配置
  311. func (f *GameFrame) GetRobotCount() int {
  312. return f.gameSink.GetRobotCount()
  313. }
  314. func (f *GameFrame) GetRobotGoldLimit() (min, max int) {
  315. min, max = f.gameSink.GetRobotGoldLimit()
  316. return
  317. }
  318. func (f *GameFrame) GetRobotOnlineSec() int {
  319. return f.gameSink.GetRobotOnlineSec()
  320. }
  321. func (f *GameFrame) IsChipRoom() bool {
  322. return f.gameSink.IsChipRoom()
  323. }
  324. func (f *GameFrame) IsLadderRoom() bool {
  325. gameSink_LadderRoom, ok := f.gameSink.(GameSink_LadderRoom)
  326. return ok && gameSink_LadderRoom.IsLadderRoom()
  327. }
  328. func (f *GameFrame) GetChipRoom() int {
  329. if f.gameSink.IsChipRoom() {
  330. return 1
  331. } else {
  332. return 0
  333. }
  334. }
  335. func (f *GameFrame) OnPlatformConfig(key string) {
  336. f.gameSink.OnPlatformConfig(key)
  337. }
  338. func (f *GameFrame) IsPrivateRoom() bool {
  339. return f.gameSink.IsPrivateRoom()
  340. }
  341. func (f *GameFrame) GetVersionID() int {
  342. return f.gameSink.GetVersionID()
  343. }
  344. func (f *GameFrame) setUserStatus(userIndex int32, status int) {
  345. usr := gate.GetUserInfo(userIndex)
  346. if usr == nil {
  347. log.Debug("GameFrame.setUserStatus user not exist %d", userIndex)
  348. return
  349. }
  350. if status == user.UserStatus_Free {
  351. usr.SetTableChairId(-1, -1)
  352. }
  353. oldStatus := usr.GetUserStatus()
  354. if oldStatus == status {
  355. log.Debug("GameFrame.setUserStatus user[%d] status not changed status = %d", userIndex, status)
  356. return
  357. }
  358. usr.SetUserStatus(status)
  359. //go func() {
  360. // 取消协程,保证按顺序发送用户状态
  361. d, _ := json.Marshal(message.UserStatusChange{UserId: usr.GetUserId(),
  362. OldStatus: oldStatus,
  363. NewStatus: status,
  364. TableId: usr.GetUserTableId(),
  365. ChairId: usr.GetUserChairId()})
  366. gate.BroadcastData(message.Frame_UserStatusChange, string(d))
  367. if status == user.UserStatus_Play {
  368. t := f.getTable(usr.GetUserTableId())
  369. data := ""
  370. if t != nil {
  371. data = t.privateData
  372. if t.isPrivate() {
  373. // 私人场不写断线信息
  374. return
  375. }
  376. }
  377. f.setOfflineStatus(usr.GetUserId(), true, data)
  378. } else {
  379. f.setOfflineStatus(usr.GetUserId(), false, "")
  380. }
  381. //}()
  382. }
  383. func (f *GameFrame) dump() {
  384. log.Release("----------GameFrame.dump----------")
  385. log.Release(" current table index : %d", f.tableIndex)
  386. defer func() {
  387. log.Release("++++++++++GameFrame.dump++++++++++")
  388. }()
  389. f.lock_table.RLock()
  390. defer f.lock_table.RUnlock()
  391. for _, v := range f.tables {
  392. log.Release(" table[%d] status[%d] usercount[%d] started[%d] Room[%s]", v.tableId, v.tableStatus, v.getUserCount(), v.getStartTime(), v.privateData)
  393. }
  394. }
  395. func (f *GameFrame) dumpTable(tableId int) {
  396. log.Release("----------GameFrame.dumpTable----------")
  397. defer func() {
  398. log.Release("++++++++++GameFrame.dumpTable++++++++++")
  399. }()
  400. table := f.getTable(tableId)
  401. if table == nil {
  402. log.Release(" table %d not exist", tableId)
  403. return
  404. }
  405. table.dump()
  406. }
  407. func (f *GameFrame) dumpTimers(tableId int) {
  408. log.Release("----------GameFrame.dumpTimers----------")
  409. defer func() {
  410. log.Release("++++++++++GameFrame.dumpTimers++++++++++")
  411. }()
  412. table := f.getTable(tableId)
  413. if table == nil {
  414. log.Release(" table %d not exist", tableId)
  415. return
  416. }
  417. table.dumpTimers()
  418. }
  419. func (f *GameFrame) dumpScene(tableId int) {
  420. log.Release("----------GameFrame.dumpScene----------")
  421. defer func() {
  422. log.Release("++++++++++GameFrame.dumpScene++++++++++")
  423. }()
  424. table := f.getTable(tableId)
  425. if table == nil {
  426. log.Release(" table %d not exist", tableId)
  427. return
  428. }
  429. table.dumpScene()
  430. }
  431. func (f *GameFrame) dumpOffline() {
  432. log.Release("----------GameFrame.dumpOffline----------")
  433. defer func() {
  434. log.Release("++++++++++GameFrame.dumpOffline++++++++++")
  435. }()
  436. f.lock_user.RLock()
  437. defer f.lock_user.RUnlock()
  438. log.Release(" count %d", len(f.offlineUsers))
  439. for _, v := range f.offlineUsers {
  440. log.Release(" %d:%d %s offline:%d", v.userIndex, v.userInfo.GetUserId(), v.userInfo.GetUserNickName(), time.Now().Unix()-v.offlineTime)
  441. }
  442. }
  443. func (f *GameFrame) dismissTable(tableId int) {
  444. table := f.getTable(tableId)
  445. if table != nil {
  446. table.dismiss()
  447. }
  448. }
  449. func (f *GameFrame) getOfflineUser(userIndex int32) *user.UserInfo {
  450. f.lock_user.RLock()
  451. defer f.lock_user.RUnlock()
  452. for _, v := range f.offlineUsers {
  453. if v.userIndex == userIndex {
  454. return v.userInfo
  455. }
  456. }
  457. return nil
  458. }
  459. func (f *GameFrame) setOfflineStatus(userId int, offline bool, roomName string) {
  460. keyName := fmt.Sprintf("UserGameStatus:UserID:%v:", userId)
  461. if offline {
  462. o := struct {
  463. GameName string
  464. RoomName string
  465. ServerAddr string
  466. GameId int
  467. }{
  468. GameName: f.gameSink.GetGameName(),
  469. RoomName: roomName,
  470. ServerAddr: f.gameSink.GetServerAddr(),
  471. GameId: f.gameSink.GetGameID(),
  472. }
  473. d, _ := json.Marshal(o)
  474. redis.String_SetEx(keyName, string(d), int(f.gameSink.GetOfflineSeconds()))
  475. } else {
  476. redis.Key_Del(keyName)
  477. }
  478. }
  479. func (f *GameFrame) getUserCount(privateData string) int {
  480. ret := 0
  481. f.lock_table.RLock()
  482. defer f.lock_table.RUnlock()
  483. for _, v := range f.tables {
  484. if v.privateData != privateData {
  485. continue
  486. }
  487. ret += v.getUserCount()
  488. }
  489. return ret
  490. }
  491. func (f *GameFrame) GetVirtualUserCount(userCount int, roomType int) int {
  492. if roomType < 0 {
  493. roomType = 0
  494. } else {
  495. roomType = roomType % 8
  496. }
  497. userCounts := [][]int{}
  498. userCounts = append(userCounts, []int{72, 134, 326, 265, 534})
  499. userCounts = append(userCounts, []int{52, 168, 287, 201, 384})
  500. userCounts = append(userCounts, []int{11, 76, 163, 143, 176})
  501. userCounts = append(userCounts, []int{13, 42, 76, 103, 202})
  502. userCounts = append(userCounts, []int{43, 86, 126, 134, 286})
  503. userCounts = append(userCounts, []int{25, 62, 96, 76, 146})
  504. userCounts = append(userCounts, []int{10, 32, 62, 53, 76})
  505. userCounts = append(userCounts, []int{8, 21, 72, 62, 92})
  506. hour := time.Now().Hour()
  507. hourIndex := 0
  508. if hour >= 18 {
  509. hourIndex = 4
  510. } else if hour >= 14 {
  511. hourIndex = 3
  512. } else if hour >= 11 {
  513. hourIndex = 2
  514. } else if hour >= 6 {
  515. hourIndex = 1
  516. }
  517. param := 10
  518. return userCount*param + userCounts[roomType][hourIndex]*4 - 10 + rand.Intn(20)
  519. }