roominfo.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. package handler
  2. import (
  3. "bet24.com/log"
  4. "bet24.com/servers/common"
  5. coreservice "bet24.com/servers/coreservice/client"
  6. cash "bet24.com/servers/micros/money/proto"
  7. notification "bet24.com/servers/micros/notification/proto"
  8. pb "bet24.com/servers/micros/privateroom/proto"
  9. "encoding/json"
  10. "fmt"
  11. "sync"
  12. "time"
  13. //db2 "bet24.com/servers/micros/privateroom/config"
  14. )
  15. const (
  16. room_timeout_none = iota // 没有超时
  17. room_timeout_empty // 人走光了
  18. room_timeout // 超时了
  19. )
  20. type roomUserInfo struct {
  21. pb.RoomUser
  22. isUserEntered bool
  23. requestSitTime int64
  24. tax int
  25. prize int
  26. }
  27. func newRoomInfo(roomNo int, serverAddr string, tableId int, creator int, gameId int, gameName string) *roomInfo {
  28. ri := &roomInfo{
  29. RoomInfo: pb.RoomInfo{
  30. RoomNo: roomNo,
  31. ServerAddr: serverAddr,
  32. GameId: gameId,
  33. GameName: gameName,
  34. TableId: tableId,
  35. },
  36. Owner: creator,
  37. createTime: time.Now().Unix(),
  38. }
  39. ri.ctor()
  40. return ri
  41. }
  42. type roomInfo struct {
  43. pb.RoomInfo
  44. userList []*roomUserInfo
  45. Owner int
  46. StartTime string
  47. RuleData string
  48. RoomType string
  49. service_addr string
  50. lock *sync.RWMutex
  51. createTime int64
  52. endedTime int64
  53. createFee int
  54. isDual bool
  55. Winners []int
  56. gameStartTime int64
  57. changeChairFlag []bool
  58. Room *GameRoom
  59. }
  60. type GameRoom struct {
  61. Status int `xorm:"INT(11)" ` //1代表空闲 2代表使用中
  62. Id int `xorm:"not null pk autoincr INT(11)" json:"id"`
  63. PlayerNum int `xorm:"INT(11)" ` //加入游戏房间人数
  64. GameEnd int `xorm:"INT(11)" ` //0未开始,1进行中,2已结束
  65. Mode int `xorm:"INT(11)" ` //游戏模式,1是经典,2是匹配
  66. Logo string `xorm:"VARCHAR(255)"` //游戏logo
  67. Type int `xorm:"INT(11)" ` //1是lodo,2 baloot
  68. TableId int `xorm:"INT(11)" ` //1是lodo,2 baloot
  69. }
  70. func (ri *roomInfo) ctor() {
  71. ri.lock = &sync.RWMutex{}
  72. }
  73. func (ri *roomInfo) isTimeout(timeoutFree, timeoutPlay, timeoutEnd int64) int {
  74. // 如果是百人场,不计入超时
  75. if len(ri.userList) < 2 {
  76. return room_timeout_none
  77. }
  78. now := time.Now().Unix()
  79. // 如果是比赛房间,不判断用户超时
  80. if !ri.isMatch() {
  81. ri.lock.RLock()
  82. var toRemove []int
  83. for i := 0; i < len(ri.userList); i++ {
  84. if ri.userList[i] == nil {
  85. continue
  86. }
  87. if ri.userList[i].isUserEntered {
  88. continue
  89. }
  90. if now-ri.userList[i].requestSitTime >= 60 {
  91. toRemove = append(toRemove, ri.userList[i].UserId)
  92. }
  93. }
  94. ri.lock.RUnlock()
  95. if len(toRemove) > 0 {
  96. log.Debug("roomInfo.isTimeout[%d] removing user %v", ri.RoomNo, toRemove)
  97. for _, v := range toRemove {
  98. ri.removeUser(v)
  99. }
  100. if ri.isEmpty() {
  101. return room_timeout_empty
  102. }
  103. }
  104. }
  105. if ri.Status == pb.PrivateRoomStatus_Playing {
  106. if now-ri.createTime >= timeoutPlay {
  107. return room_timeout
  108. }
  109. } else if ri.Status == pb.PrivateRoomStatus_Ended {
  110. if now-ri.endedTime >= timeoutEnd {
  111. return room_timeout
  112. }
  113. } else {
  114. if now-ri.createTime >= timeoutFree {
  115. return room_timeout
  116. }
  117. }
  118. return room_timeout_none
  119. }
  120. func (ri *roomInfo) getIdle() int64 {
  121. return time.Now().Unix() - ri.createTime
  122. }
  123. func (ri *roomInfo) isMatch() bool {
  124. return ri.RoomType == pb.RoomType_SimpleMatch
  125. }
  126. func (ri *roomInfo) dump() {
  127. log.Release(" Room[%d] Owner[%d] Idled[%d] Rule[%s] UserCount[%d] Fee[%d] Stats[%d] IsPublic[%v]",
  128. ri.RoomNo, ri.Owner, ri.getIdle(), ri.RuleName, ri.UserCount, ri.Fee, ri.Status, ri.IsPublic)
  129. for k, v := range ri.userList {
  130. if v == nil {
  131. log.Release(" [%d:]nil", k)
  132. continue
  133. }
  134. log.Release(" [%d:]User [%d:%s ChairId:%d Score:%d] entered?%v Prize[%d]",
  135. k, v.UserId, v.NickName, v.ChairId, v.Score, v.isUserEntered, v.prize)
  136. }
  137. if len(ri.Winners) > 0 {
  138. log.Release(" Winners :%v", ri.Winners)
  139. }
  140. }
  141. func (ri *roomInfo) setExtra(ruleName string, ruleData string, userCount int, fee int, target int, serviceAddr string, isDual bool, playTime int) {
  142. ri.RuleName = ruleName
  143. ri.RuleData = ruleData
  144. ri.UserCount = userCount
  145. ri.Fee = fee
  146. ri.Target = target
  147. ri.service_addr = serviceAddr
  148. ri.isDual = isDual
  149. ri.userList = make([]*roomUserInfo, userCount)
  150. ri.UserList = make([]*pb.RoomUser, userCount)
  151. ri.PlayTime = playTime
  152. ri.changeChairFlag = make([]bool, userCount)
  153. }
  154. func (ri *roomInfo) getUserChair(userId int) int {
  155. ri.lock.RLock()
  156. defer ri.lock.RUnlock()
  157. for _, v := range ri.userList {
  158. if v == nil {
  159. break
  160. }
  161. if v.UserId == userId {
  162. return v.ChairId
  163. }
  164. }
  165. return -1
  166. }
  167. // 请求进入,输出椅子号,椅子号为-1表示没有空位了
  168. func (ri *roomInfo) userRequestSit(userId int, nickName string, faceId int, faceUrl string,
  169. prefferedChairId int, score, baseScore, setCount int,yyfUid int) (chairId int, errMsg string, blackUsers []int) {
  170. log.Debug("roomInfo.onUserEnter %d prefered chairId %d,score[%d],baseScore[%d]", userId, prefferedChairId, score, baseScore)
  171. chairId = -1
  172. errMsg = "ok"
  173. blackUsers = []int{}
  174. index := -1
  175. var existUserIds []int
  176. ri.lock.RLock()
  177. // 如果不是随机椅子
  178. for _, v := range ri.userList {
  179. if v != nil {
  180. existUserIds = append(existUserIds, v.UserId)
  181. }
  182. }
  183. if prefferedChairId < 0 || prefferedChairId >= len(ri.userList) {
  184. for k, v := range ri.userList {
  185. if v == nil {
  186. chairId = k
  187. index = k
  188. continue
  189. }
  190. if v.UserId == userId {
  191. ri.lock.RUnlock()
  192. log.Release("privateroom.roomInfo.onUserEnter userId[%d] or chairId[%d] already exist", userId, chairId)
  193. chairId = v.ChairId
  194. return
  195. }
  196. }
  197. } else {
  198. if ri.userList[prefferedChairId] == nil {
  199. // 有空位
  200. index = prefferedChairId
  201. chairId = prefferedChairId
  202. }
  203. }
  204. ri.lock.RUnlock()
  205. if chairId == -1 {
  206. log.Release("privateroom.roomInfo.onUserEnter roomNo[%d] no empty chair", ri.RoomNo)
  207. errMsg = "no empty chair"
  208. return
  209. }
  210. if ri.isDual && 1 == chairId {
  211. chairId = 2
  212. index = 1
  213. }
  214. ri.lock.Lock()
  215. ru := roomUserInfo{
  216. RoomUser: pb.RoomUser{
  217. UserId: userId,
  218. NickName: nickName,
  219. ChairId: chairId,
  220. FaceId: faceId,
  221. FaceUrl: faceUrl,
  222. Score: score,
  223. BaseScore: baseScore,
  224. SetCount: setCount,
  225. YyfUid: yyfUid,
  226. },
  227. requestSitTime: time.Now().Unix(),
  228. }
  229. ri.userList[index] = &ru
  230. ri.UserList[index] = &ru.RoomUser
  231. // ri.Room.PlayerNum=ri.Room.PlayerNum+1
  232. // db2.Engine.ID(ri.Room.Id).Update(ri.Room)
  233. ri.lock.Unlock()
  234. if len(existUserIds) > 0 {
  235. blackUsers = coreservice.FriendGetBlackListUserIn(userId, existUserIds)
  236. if len(blackUsers) > 0 {
  237. log.Debug("userRequestSit blackUserIn userId[%d] existUserIds%v blacklist%v", userId, existUserIds, blackUsers)
  238. }
  239. }
  240. return
  241. }
  242. func (ri *roomInfo) removeUser(userId int) bool {
  243. log.Debug("roomInfo.removeUser %d", userId)
  244. idx := -1
  245. ri.lock.RLock()
  246. for k, v := range ri.userList {
  247. if v == nil {
  248. continue
  249. }
  250. if v.UserId == userId {
  251. idx = k
  252. break
  253. }
  254. }
  255. // ri.Room.PlayerNum=ri.Room.PlayerNum-1
  256. // fmt.Printf("减少玩家人数")
  257. // db2.Engine.ID(ri.Room.Id).Update(ri.Room)
  258. ri.lock.RUnlock()
  259. if idx == -1 {
  260. log.Release("privateroom.roomInfo.removeUser userId[%d] not exist", userId)
  261. return false
  262. }
  263. ri.lock.Lock()
  264. ri.UserList[idx] = nil
  265. ri.userList[idx] = nil
  266. ri.lock.Unlock()
  267. return true
  268. }
  269. func (ri *roomInfo) updateUserScore(userId int, scoreDelta int) bool {
  270. var u *roomUserInfo
  271. ri.lock.RLock()
  272. for _, v := range ri.userList {
  273. if v == nil {
  274. continue
  275. }
  276. if v.UserId == userId {
  277. u = v
  278. break
  279. }
  280. }
  281. ri.lock.RUnlock()
  282. if u == nil {
  283. log.Release("privateroom.roomInfo.addUserScore userId[%d] not exist", userId)
  284. return false
  285. }
  286. if ri.Owner == -1 {
  287. u.Score += scoreDelta
  288. } else {
  289. u.Score = scoreDelta
  290. }
  291. ri.postUserScore(userId, scoreDelta)
  292. return true
  293. }
  294. func (ri *roomInfo) userSit(userId int, chairId int) int {
  295. ret := 0
  296. ri.lock.RLock()
  297. defer ri.lock.RUnlock()
  298. for _, v := range ri.userList {
  299. if v == nil {
  300. continue
  301. }
  302. if v.UserId == userId && v.ChairId == chairId {
  303. v.isUserEntered = true
  304. ret = 1
  305. }
  306. // 如果是换桌就不提示黑名单
  307. if ri.changeChairFlag[chairId] {
  308. continue
  309. }
  310. if coreservice.FriendIsBlackListUser(v.UserId, userId) {
  311. go ri.sendBlackUserEnterNotification(v.UserId, userId)
  312. }
  313. }
  314. if ret == 0 {
  315. log.Release("privateroom.roomInfo.userSit [%d] not found", userId)
  316. ri.dump()
  317. } else {
  318. ri.changeChairFlag[chairId] = false
  319. }
  320. return ret
  321. }
  322. func (ri *roomInfo) sendBlackUserEnterNotification(userId int, enteredUserId int) {
  323. log.Debug("sendBlackUserEnterNotification userId[%d],enteredUserId[%d]", userId, enteredUserId)
  324. msg := Match_notificationInfo{Msg: room_blasklist_user, UserId: enteredUserId}
  325. d, _ := json.Marshal(msg)
  326. notification.AddNotification(userId, notification.Notification_PrivateRoom, string(d))
  327. }
  328. func (ri *roomInfo) changeChair(userId int, chairId int) bool {
  329. // 比赛房间不允许换椅子
  330. if ri.Owner == -1 {
  331. return false
  332. }
  333. if chairId < 0 || chairId >= len(ri.userList) {
  334. log.Release("roomInfo.changeChair [%d] chairId[%d] invalid", userId, chairId)
  335. return false
  336. }
  337. ri.lock.RLock()
  338. oldChairId := -1
  339. for _, v := range ri.userList {
  340. if v == nil {
  341. continue
  342. }
  343. if v.UserId == userId {
  344. oldChairId = v.ChairId
  345. }
  346. }
  347. ri.lock.RUnlock()
  348. if oldChairId == -1 {
  349. log.Release("privateroom.roomInfo.changeChair [%d] not found", userId)
  350. ri.dump()
  351. return false
  352. }
  353. if oldChairId == chairId {
  354. log.Release("roomInfo.changeChair [%d] chairId[%d] same chair", userId, chairId)
  355. return false
  356. }
  357. ri.lock.Lock()
  358. defer ri.lock.Unlock()
  359. if ri.userList[chairId] != nil {
  360. log.Release("roomInfo.changeChair [%d] chairId[%d] chair taken", userId, chairId)
  361. return false
  362. }
  363. ri.userList[chairId] = ri.userList[oldChairId]
  364. ri.userList[chairId].isUserEntered = false
  365. ri.userList[chairId].ChairId = chairId
  366. ri.userList[oldChairId] = nil
  367. ri.UserList[oldChairId] = nil
  368. ri.UserList[chairId] = &ri.userList[chairId].RoomUser
  369. log.Debug("roomInfo.changeChair [%d] chairId[%d] changed to [%d]", userId, oldChairId, chairId)
  370. ri.changeChairFlag[chairId] = true
  371. return true
  372. }
  373. func (ri *roomInfo) isUserExist(userId int) bool {
  374. ri.lock.RLock()
  375. defer ri.lock.RUnlock()
  376. for _, v := range ri.userList {
  377. if v == nil {
  378. continue
  379. }
  380. if v.UserId == userId {
  381. return true
  382. }
  383. }
  384. return false
  385. }
  386. func (ri *roomInfo) isUserPlaying(userId int) bool {
  387. if ri.Status != pb.PrivateRoomStatus_Playing &&
  388. ri.Status != pb.PrivateRoomStatus_Free {
  389. return false
  390. }
  391. return ri.isUserExist(userId)
  392. }
  393. func (ri *roomInfo) roomStart() {
  394. now := time.Now()
  395. ri.gameStartTime = now.Unix()
  396. ri.StartTime = now.Format(common.Layout)
  397. // 房主不设置奖金,表示奖金为报名费
  398. if ri.Fee > 0 && ri.Prize > 0 && ri.createFee > 0 {
  399. //cash.GiveMoney(ri.Owner, ri.Fee*len(ri.userList), common.LOGTYPE_PRIVATEROOM_OWNER, "privateroom", "owner", "")
  400. for _, v := range ri.UserList {
  401. if v.UserId==ri.Owner{
  402. //cash.GiveMoney2(r.Owner, r.Fee, common.LOGTYPE_PRIVATEROOM_ENTER, "privateroom", "fee return", "",r.Owner.yyfUid)
  403. cash.GiveMoney2(v.UserId, ri.Fee, common.LOGTYPE_PRIVATEROOM_ENTER, "privateroom", "fee return", "",v.YyfUid)
  404. }
  405. }
  406. }
  407. ri.postRoomStart()
  408. }
  409. func (ri *roomInfo) getWinners() []int {
  410. return ri.Winners
  411. }
  412. func (ri *roomInfo) setWinners(winners []int) bool {
  413. // 如果是百人场
  414. if len(ri.userList) < 2 {
  415. ri.postRoomEnd()
  416. return true
  417. }
  418. if len(ri.Winners) > 0 {
  419. log.Release("roomInfo.setWinners already set")
  420. return false
  421. }
  422. for _, v := range winners {
  423. if !ri.isUserExist(v) {
  424. log.Release("roomInfo.setWinners user[%d] not found", v)
  425. ri.dump()
  426. return false
  427. }
  428. }
  429. ri.Winners = winners
  430. ri.postRoomEnd()
  431. return true
  432. }
  433. func (ri *roomInfo) getTotalTax() int {
  434. ret := 0
  435. ri.lock.RLock()
  436. defer ri.lock.RUnlock()
  437. for _, v := range ri.userList {
  438. if v == nil {
  439. continue
  440. }
  441. ret += v.tax
  442. }
  443. return ret
  444. }
  445. func (ri *roomInfo) setPrizeAndTax(userId int, prize, tax int) {
  446. ri.lock.Lock()
  447. defer ri.lock.Unlock()
  448. for _, v := range ri.userList {
  449. if v == nil {
  450. continue
  451. }
  452. if v.UserId == userId {
  453. v.tax = tax
  454. v.prize = prize
  455. return
  456. }
  457. }
  458. }
  459. func (ri *roomInfo) getUsersDesc() string {
  460. type userDesc struct {
  461. UserId int
  462. ChairId int
  463. Score int
  464. Prize int
  465. }
  466. var users []userDesc
  467. ri.lock.Lock()
  468. for _, v := range ri.userList {
  469. if v == nil {
  470. continue
  471. }
  472. users = append(users, userDesc{UserId: v.UserId, ChairId: v.ChairId, Score: v.Score, Prize: v.prize})
  473. }
  474. ri.lock.Unlock()
  475. d, _ := json.Marshal(users)
  476. return string(d)
  477. }
  478. func (ri *roomInfo) getUsersDescForDB() string {
  479. var ret string
  480. ri.lock.Lock()
  481. for _, v := range ri.userList {
  482. if v == nil {
  483. continue
  484. }
  485. ret = fmt.Sprintf("%s%d,%d,%d,%d,%d,%d;", ret, v.ChairId, v.UserId, ri.Fee, v.tax, v.prize, v.Score)
  486. }
  487. ri.lock.Unlock()
  488. return ret
  489. }
  490. func (ri *roomInfo) postRoomStart() {
  491. getRoomManager().postRoomStart(ri.RoomNo)
  492. }
  493. func (ri *roomInfo) postRoomEnd() {
  494. getRoomManager().postRoomEnd(ri.RoomNo, ri.Winners)
  495. }
  496. func (ri *roomInfo) postUserScore(userId int, scoreDelta int) {
  497. getRoomManager().postUserScore(ri.RoomNo, userId, scoreDelta)
  498. }
  499. func (ri *roomInfo) postAllUserScores() {
  500. for i := 0; i < len(ri.userList); i++ {
  501. if ri.userList[i] == nil {
  502. continue
  503. }
  504. ri.postUserScore(ri.userList[i].UserId, ri.userList[i].Score)
  505. }
  506. }
  507. func (ri *roomInfo) getAUserId() int {
  508. ret := 0
  509. ri.lock.RLock()
  510. for i := 0; i < len(ri.userList); i++ {
  511. if ri.userList[i] == nil {
  512. continue
  513. }
  514. if ri.userList[i].isUserEntered {
  515. ret = ri.userList[i].UserId
  516. }
  517. }
  518. if ret == 0 {
  519. for i := 0; i < len(ri.userList); i++ {
  520. if ri.userList[i] == nil {
  521. continue
  522. }
  523. ret = ri.userList[i].UserId
  524. }
  525. }
  526. ri.lock.RUnlock()
  527. return ret
  528. }
  529. func (ri *roomInfo) isEmpty() bool {
  530. for i := 0; i < len(ri.userList); i++ {
  531. if ri.userList[i] != nil {
  532. return false
  533. }
  534. }
  535. return true
  536. }
  537. func (ri *roomInfo) getUserInfo(userId int) *pb.RoomUser {
  538. ri.lock.RLock()
  539. defer ri.lock.RUnlock()
  540. for _, v := range ri.userList {
  541. if v == nil {
  542. continue
  543. }
  544. if v.UserId == userId {
  545. return &v.RoomUser
  546. }
  547. }
  548. return nil
  549. }
  550. func (ri *roomInfo) getPrize(userId int) int {
  551. ri.lock.RLock()
  552. defer ri.lock.RUnlock()
  553. for _, v := range ri.userList {
  554. if v == nil {
  555. continue
  556. }
  557. if v.UserId == userId {
  558. return v.prize
  559. }
  560. }
  561. return 0
  562. }