gamemgr.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. package game
  2. import (
  3. "bet24.com/log"
  4. "bet24.com/servers/common"
  5. "bet24.com/servers/micros/audioroom/handler/config"
  6. "bet24.com/servers/micros/audioroom/handler/income"
  7. pb "bet24.com/servers/micros/audioroom/proto"
  8. micro_common "bet24.com/servers/micros/common"
  9. item "bet24.com/servers/micros/item_inventory/proto"
  10. privateroom "bet24.com/servers/micros/privateroom/proto"
  11. "bet24.com/servers/zego"
  12. "encoding/json"
  13. "fmt"
  14. "math/rand"
  15. "strconv"
  16. "sync"
  17. "time"
  18. )
  19. var mgr *gamemgr
  20. type gameRoom struct {
  21. pb.GameRoomInfo
  22. RoomId int // 属于哪个语聊房
  23. }
  24. type removedGameRoom struct {
  25. gameRoom
  26. removeTime int64
  27. }
  28. type gamemgr struct {
  29. roomlist map[int]*gameRoom
  30. lock *sync.RWMutex
  31. onRoomEnd func(roomId int, roomNo int)
  32. onRoomInfo func(roomId int) *pb.RoomInfo
  33. removedRooms map[int]*removedGameRoom
  34. lockRemovedRooms *sync.RWMutex
  35. }
  36. func getGameManager() *gamemgr {
  37. if mgr == nil {
  38. mgr = new(gamemgr)
  39. mgr.ctor()
  40. }
  41. return mgr
  42. }
  43. func (this *gamemgr) ctor() {
  44. this.lock = &sync.RWMutex{}
  45. this.roomlist = make(map[int]*gameRoom)
  46. this.lockRemovedRooms = &sync.RWMutex{}
  47. this.removedRooms = make(map[int]*removedGameRoom)
  48. go privateroom.RegisterServerStatus(this, this, micro_common.GetServicePort(), "audioroom_game")
  49. this.checkRemovedRoom()
  50. }
  51. func (this *gamemgr) setRoomEndSubscriber(onRoomEnd func(roomId int, roomNo int)) {
  52. this.onRoomEnd = onRoomEnd
  53. }
  54. // 设置房间信息订阅
  55. func (this *gamemgr) setRoomInfoSubscriber(onRoomInfo func(roomId int) *pb.RoomInfo) {
  56. this.onRoomInfo = onRoomInfo
  57. }
  58. // 获取房间信息
  59. func (this *gamemgr) getRoomInfo(roomId int) *pb.RoomInfo {
  60. if this.onRoomInfo == nil {
  61. return nil
  62. }
  63. return this.onRoomInfo(roomId)
  64. }
  65. func (this *gamemgr) dump(cmd, param2 string) {
  66. switch cmd {
  67. case "rule":
  68. this.dumpRules()
  69. case "user":
  70. this.dumpUser(param2)
  71. default:
  72. this.dumpRoom(param2)
  73. }
  74. }
  75. func (this *gamemgr) dumpUser(param string) {
  76. log.Release("-------------------------------")
  77. log.Release("gamemgr.dumpUser %s", param)
  78. defer func() {
  79. log.Release("+++++++++++++++++++++++++++++++")
  80. log.Release("")
  81. }()
  82. userId, err := strconv.Atoi(param)
  83. if err != nil {
  84. log.Release(" atoi error %v", err)
  85. return
  86. }
  87. rooms := this.getRoomsByRoomId(userId)
  88. if len(rooms) == 0 {
  89. log.Release(" no room")
  90. return
  91. }
  92. for _, v := range rooms {
  93. log.Release(" RoomId[%d]:RoomNo[%d]Addr[%s]Table[%d]Rule[%s]", v.RoomId, v.RoomNo, v.ServerAddr, v.TableId, v.RuleName)
  94. }
  95. }
  96. func (this *gamemgr) dumpRules() {
  97. log.Release("-------------------------------")
  98. log.Release("gamemgr.dumpRules")
  99. defer func() {
  100. log.Release("+++++++++++++++++++++++++++++++")
  101. log.Release("")
  102. }()
  103. gameList := config.Mgr.GetGameList()
  104. for _, v := range gameList {
  105. log.Release(" Id[%d]Name[%s]Rules%v", v.Id, v.Name, v.GameRules)
  106. }
  107. }
  108. func (this *gamemgr) dumpRoom(param string) {
  109. log.Release("-------------------------------")
  110. log.Release("gamemgr.dumpRoom %s", param)
  111. defer func() {
  112. log.Release("+++++++++++++++++++++++++++++++")
  113. log.Release("")
  114. }()
  115. if param == "" {
  116. this.lock.RLock()
  117. for _, v := range this.roomlist {
  118. log.Release(" RoomId[%d]RoomNo[%d]Addr[%s]Table[%d]Rule[%s]", v.RoomId, v.RoomNo, v.ServerAddr, v.TableId, v.RuleName)
  119. }
  120. this.lock.RUnlock()
  121. return
  122. }
  123. roomNo, err := strconv.Atoi(param)
  124. if err != nil {
  125. log.Release(" atoi error %v", err)
  126. return
  127. }
  128. this.lock.RLock()
  129. v, ok := this.roomlist[roomNo]
  130. this.lock.RUnlock()
  131. if v == nil || !ok {
  132. log.Release(" roomNo[%d] not found", roomNo)
  133. return
  134. }
  135. log.Release(" RoomNo[%d]Addr[%s]Table[%d]Rule[%s]", v.RoomNo, v.ServerAddr, v.TableId, v.RuleName)
  136. }
  137. func (this *gamemgr) getRoomsByRoomId(roomId int) []*gameRoom {
  138. var ret []*gameRoom
  139. this.lock.RLock()
  140. for k, v := range this.roomlist {
  141. if v.RoomId == roomId {
  142. ret = append(ret, this.roomlist[k])
  143. }
  144. }
  145. this.lock.RUnlock()
  146. return ret
  147. }
  148. func (this *gamemgr) getRoom(roomNo int) *gameRoom {
  149. this.lock.RLock()
  150. gr, ok := this.roomlist[roomNo]
  151. this.lock.RUnlock()
  152. if !ok {
  153. return nil
  154. }
  155. return gr
  156. }
  157. func (this *gamemgr) getRoomByRoomIdAndRuleName(roomId int, gameId int, ruleName string) *gameRoom {
  158. if ruleName == "" || !config.Mgr.IsGameRuleExist(gameId, ruleName) {
  159. newRuleName := config.Mgr.GetDefaultGameRule(gameId)
  160. log.Debug("gamemgr.createGameRoom gameId[%d] ruleName[%s] changed to [%s]", gameId, ruleName, newRuleName)
  161. ruleName = newRuleName
  162. }
  163. this.lock.RLock()
  164. defer this.lock.RUnlock()
  165. for k, v := range this.roomlist {
  166. if v.RoomId == roomId && v.GameId == gameId && v.RuleName == ruleName {
  167. return this.roomlist[k]
  168. }
  169. }
  170. return nil
  171. }
  172. func (this *gamemgr) createGameRoom(roomId int, gameId int, ruleName string) (bool, *gameRoom) {
  173. if ruleName == "" || !config.Mgr.IsGameRuleExist(gameId, ruleName) {
  174. newRuleName := config.Mgr.GetDefaultGameRule(gameId)
  175. log.Debug("gamemgr.createGameRoom gameId[%d] ruleName[%s] changed to [%s]", gameId, ruleName, newRuleName)
  176. ruleName = newRuleName
  177. }
  178. log.Debug("gamemgr.createGameRoom roomId[%d],gameId[%d],ruleName[%s]", roomId, gameId, ruleName)
  179. roomNo, errMsg := privateroom.CreatePrivateRoomByUser(roomId, gameId, ruleName, 0, 1, 0, 0, "audio_game_room", 0, false, "")
  180. if roomNo <= 0 {
  181. log.Release("gamemgr.createGameRoom CreatePrivateRoomByUser failed %s", errMsg)
  182. return false, nil
  183. }
  184. roomInfoStr := privateroom.GetPrivateRoomInfo(roomNo)
  185. var roomInfo privateroom.RoomInfo
  186. err := json.Unmarshal([]byte(roomInfoStr), &roomInfo)
  187. if err != nil {
  188. log.Release("gamemgr.createGameRoom GetPrivateRoomInfo Unmarshal failed [%s] %v", roomInfoStr, err)
  189. return false, nil
  190. }
  191. gr := &gameRoom{
  192. RoomId: roomId,
  193. GameRoomInfo: pb.GameRoomInfo{
  194. GameId: gameId,
  195. RuleName: ruleName,
  196. RoomNo: roomNo,
  197. ServerAddr: roomInfo.ServerAddr,
  198. TableId: roomInfo.TableId,
  199. },
  200. }
  201. this.lock.Lock()
  202. this.roomlist[roomNo] = gr
  203. this.lock.Unlock()
  204. return true, gr
  205. }
  206. // 上报战绩
  207. func (this *gamemgr) reportUserBet(roomId, roomNo, gameId int, roomName string, isChipRoom bool, userBets []pb.UserBet, roomOwner int) {
  208. gr := this.getRoom(roomNo)
  209. if gr == nil {
  210. gr = this.getRemovedRoom(roomNo)
  211. }
  212. if gr == nil || gr.RoomId != roomId {
  213. return
  214. }
  215. // 道具类型
  216. itemType := item.Item_Gold
  217. if isChipRoom {
  218. itemType = item.Item_Chip
  219. }
  220. // 给房主加分成
  221. for _, v := range userBets {
  222. income.TriggerGameIncome(v.UserId, pb.TriggerData{
  223. RoomId: roomId,
  224. GameId: gameId,
  225. RoomOwner: roomOwner,
  226. ItemType: itemType,
  227. Amount: v.TotalBet,
  228. })
  229. }
  230. }
  231. func (this *gamemgr) getGameRoomInfo(roomId, gameId int, ruleName string) *pb.GameRoomInfo {
  232. gr := this.getRoomByRoomIdAndRuleName(roomId, gameId, ruleName)
  233. if gr == nil {
  234. return nil
  235. }
  236. return &gr.GameRoomInfo
  237. /*
  238. if gr == nil {
  239. var ok bool
  240. ok, gr = this.createGameRoom(roomId, gameId, ruleName)
  241. if !ok {
  242. log.Release("gamemgr.getGameRoomInfo createGameRoom failed")
  243. return nil
  244. }
  245. }
  246. */
  247. }
  248. // 开始小游戏
  249. func (this *gamemgr) startGame(userId, roomId, gameId, playType, scene int, messageContent string, roomOwner int) (retCode int, message string, result int) {
  250. // 游戏信息
  251. g := config.Mgr.GetGameInfo(gameId)
  252. if g.Id <= 0 {
  253. retCode, message = 11, "Fail, gameId is invalid"
  254. return
  255. }
  256. var (
  257. isExist bool
  258. items []item.ItemPack
  259. )
  260. // 玩法
  261. for _, v := range g.Plays {
  262. if v.PlayType != playType {
  263. continue
  264. }
  265. // 判断数值范围是否有效
  266. if len(v.Numbers) < 2 {
  267. log.Error("gamemgr.StartGame config error, userId=%d roomId=%d gameId=%d playType=%d scene=%d",
  268. userId, roomId, gameId, playType, scene)
  269. retCode, message = 14, "Fail, config.Numbers is invalid"
  270. return
  271. }
  272. // 取值范围
  273. min, max := v.Numbers[0], v.Numbers[1]
  274. // 小-->大进行赋值
  275. if min > max {
  276. min, max = max, min
  277. }
  278. // 生成随机结果
  279. result = rand.Intn(max-min) + min
  280. // 场景
  281. for _, s := range v.Fees {
  282. if s.Scene != scene {
  283. continue
  284. }
  285. // 存在
  286. isExist = true
  287. // 费用
  288. items = append(items, s.Items...)
  289. break
  290. }
  291. break
  292. }
  293. // 没有找到配置信息
  294. if !isExist {
  295. retCode, message = 12, "Fail, no information found"
  296. return
  297. }
  298. // 扣除道具
  299. if items != nil {
  300. if success := item.ConsumeBulk(userId, items, common.LOGTYPE_AUDIOROOM_GAME_START); !success {
  301. retCode, message = 13, "Insufficient expense deduction failed"
  302. return
  303. }
  304. }
  305. // 给房主加分成
  306. for _, v := range items {
  307. income.TriggerGameIncome(userId, pb.TriggerData{
  308. RoomId: roomId,
  309. GameId: gameId,
  310. RoomOwner: roomOwner,
  311. ItemType: v.ItemId,
  312. Amount: v.Count,
  313. })
  314. }
  315. // 替换数字
  316. messageContent = fmt.Sprintf(messageContent, result, playType)
  317. // 发送广播
  318. go zego.SendBroadcastMessage(strconv.Itoa(roomId), strconv.Itoa(-userId), zego.MessageCategory_Chat, messageContent)
  319. // 成功
  320. retCode, message = 1, "success"
  321. return
  322. }
  323. func (this *gamemgr) closeGameRoom(roomId, roomNo int) bool {
  324. r := this.getRoom(roomNo)
  325. if r == nil {
  326. log.Release("gamemgr.closeGameRoom roomId[%d] roomNo[%d] not found", roomId, roomNo)
  327. return false
  328. }
  329. if r.RoomId != roomId {
  330. log.Release("gamemgr.closeGameRoom roomId[%d] roomNo[%d] not equal to r.RoomId[%d]", roomId, roomNo, r.RoomId)
  331. return false
  332. }
  333. if !privateroom.ClosePrivateRoom(roomNo) {
  334. log.Release("gamemgr.closeGameRoom roomId[%d] roomNo[%d] ClosePrivateRoom failed", roomId, roomNo)
  335. return false
  336. }
  337. this.removeRoom(r)
  338. return true
  339. }
  340. func (this *gamemgr) removeRoom(room *gameRoom) {
  341. log.Debug("gamemgr.removeRoom %d", room.RoomNo)
  342. this.lockRemovedRooms.Lock()
  343. this.removedRooms[room.RoomNo] = &removedGameRoom{gameRoom: *room, removeTime: time.Now().Unix()}
  344. this.lockRemovedRooms.Unlock()
  345. this.lock.Lock()
  346. delete(this.roomlist, room.RoomNo)
  347. this.lock.Unlock()
  348. }
  349. func (this *gamemgr) getRemovedRoom(roomNo int) *gameRoom {
  350. this.lockRemovedRooms.RLock()
  351. gr, ok := this.removedRooms[roomNo]
  352. this.lockRemovedRooms.RUnlock()
  353. if !ok {
  354. return nil
  355. }
  356. return &gr.gameRoom
  357. }
  358. func (this *gamemgr) removeRoomsByGameRule(gameId int, gameRule string) {
  359. var toRemove []*gameRoom
  360. this.lock.RLock()
  361. for k, v := range this.roomlist {
  362. if v.GameId == gameId && v.RuleName == gameRule {
  363. toRemove = append(toRemove, this.roomlist[k])
  364. }
  365. }
  366. this.lock.RUnlock()
  367. if len(toRemove) == 0 {
  368. return
  369. }
  370. if this.onRoomEnd != nil {
  371. for _, r := range toRemove {
  372. this.onRoomEnd(r.RoomId, r.RoomNo)
  373. }
  374. }
  375. this.lock.Lock()
  376. for _, r := range toRemove {
  377. delete(this.roomlist, r.RoomNo)
  378. }
  379. this.lock.Unlock()
  380. }
  381. func (this *gamemgr) checkRemovedRoom() {
  382. time.AfterFunc(10*time.Minute, this.checkRemovedRoom)
  383. var toRemove []int
  384. now := time.Now().Unix()
  385. this.lockRemovedRooms.RLock()
  386. for _, v := range this.removedRooms {
  387. if now-v.removeTime >= 600 {
  388. toRemove = append(toRemove, v.RoomNo)
  389. }
  390. }
  391. this.lockRemovedRooms.RUnlock()
  392. if len(toRemove) == 0 {
  393. return
  394. }
  395. log.Debug("gamemgr.checkRemovedRoom removing %v", toRemove)
  396. this.lockRemovedRooms.Lock()
  397. for _, v := range toRemove {
  398. delete(this.removedRooms, v)
  399. }
  400. this.lockRemovedRooms.Unlock()
  401. }