package handler import ( "bet24.com/log" "bet24.com/servers/common" coreservice "bet24.com/servers/coreservice/client" cash "bet24.com/servers/micros/money/proto" notification "bet24.com/servers/micros/notification/proto" pb "bet24.com/servers/micros/privateroom/proto" "encoding/json" "fmt" "sync" "time" //db2 "bet24.com/servers/micros/privateroom/config" ) const ( room_timeout_none = iota // 没有超时 room_timeout_empty // 人走光了 room_timeout // 超时了 ) type roomUserInfo struct { pb.RoomUser isUserEntered bool requestSitTime int64 tax int prize int } func newRoomInfo(roomNo int, serverAddr string, tableId int, creator int, gameId int, gameName string) *roomInfo { ri := &roomInfo{ RoomInfo: pb.RoomInfo{ RoomNo: roomNo, ServerAddr: serverAddr, GameId: gameId, GameName: gameName, TableId: tableId, }, Owner: creator, createTime: time.Now().Unix(), } ri.ctor() return ri } type roomInfo struct { pb.RoomInfo userList []*roomUserInfo Owner int StartTime string RuleData string RoomType string service_addr string lock *sync.RWMutex createTime int64 endedTime int64 createFee int isDual bool Winners []int gameStartTime int64 changeChairFlag []bool Room *GameRoom } type GameRoom struct { Status int `xorm:"INT(11)" ` //1代表空闲 2代表使用中 Id int `xorm:"not null pk autoincr INT(11)" json:"id"` PlayerNum int `xorm:"INT(11)" ` //加入游戏房间人数 GameEnd int `xorm:"INT(11)" ` //0未开始,1进行中,2已结束 Mode int `xorm:"INT(11)" ` //游戏模式,1是经典,2是匹配 Logo string `xorm:"VARCHAR(255)"` //游戏logo Type int `xorm:"INT(11)" ` //1是lodo,2 baloot TableId int `xorm:"INT(11)" ` //1是lodo,2 baloot } func (ri *roomInfo) ctor() { ri.lock = &sync.RWMutex{} } func (ri *roomInfo) isTimeout(timeoutFree, timeoutPlay, timeoutEnd int64) int { // 如果是百人场,不计入超时 if len(ri.userList) < 2 { return room_timeout_none } now := time.Now().Unix() // 如果是比赛房间,不判断用户超时 if !ri.isMatch() { ri.lock.RLock() var toRemove []int for i := 0; i < len(ri.userList); i++ { if ri.userList[i] == nil { continue } if ri.userList[i].isUserEntered { continue } if now-ri.userList[i].requestSitTime >= 60 { toRemove = append(toRemove, ri.userList[i].UserId) } } ri.lock.RUnlock() if len(toRemove) > 0 { log.Debug("roomInfo.isTimeout[%d] removing user %v", ri.RoomNo, toRemove) for _, v := range toRemove { ri.removeUser(v) } if ri.isEmpty() { return room_timeout_empty } } } if ri.Status == pb.PrivateRoomStatus_Playing { if now-ri.createTime >= timeoutPlay { return room_timeout } } else if ri.Status == pb.PrivateRoomStatus_Ended { if now-ri.endedTime >= timeoutEnd { return room_timeout } } else { if now-ri.createTime >= timeoutFree { return room_timeout } } return room_timeout_none } func (ri *roomInfo) getIdle() int64 { return time.Now().Unix() - ri.createTime } func (ri *roomInfo) isMatch() bool { return ri.RoomType == pb.RoomType_SimpleMatch } func (ri *roomInfo) dump() { log.Release(" Room[%d] Owner[%d] Idled[%d] Rule[%s] UserCount[%d] Fee[%d] Stats[%d] IsPublic[%v]", ri.RoomNo, ri.Owner, ri.getIdle(), ri.RuleName, ri.UserCount, ri.Fee, ri.Status, ri.IsPublic) for k, v := range ri.userList { if v == nil { log.Release(" [%d:]nil", k) continue } log.Release(" [%d:]User [%d:%s ChairId:%d Score:%d] entered?%v Prize[%d]", k, v.UserId, v.NickName, v.ChairId, v.Score, v.isUserEntered, v.prize) } if len(ri.Winners) > 0 { log.Release(" Winners :%v", ri.Winners) } } func (ri *roomInfo) setExtra(ruleName string, ruleData string, userCount int, fee int, target int, serviceAddr string, isDual bool, playTime int) { ri.RuleName = ruleName ri.RuleData = ruleData ri.UserCount = userCount ri.Fee = fee ri.Target = target ri.service_addr = serviceAddr ri.isDual = isDual ri.userList = make([]*roomUserInfo, userCount) ri.UserList = make([]*pb.RoomUser, userCount) ri.PlayTime = playTime ri.changeChairFlag = make([]bool, userCount) } func (ri *roomInfo) getUserChair(userId int) int { ri.lock.RLock() defer ri.lock.RUnlock() for _, v := range ri.userList { if v == nil { break } if v.UserId == userId { return v.ChairId } } return -1 } // 请求进入,输出椅子号,椅子号为-1表示没有空位了 func (ri *roomInfo) userRequestSit(userId int, nickName string, faceId int, faceUrl string, prefferedChairId int, score, baseScore, setCount int,yyfUid int) (chairId int, errMsg string, blackUsers []int) { log.Debug("roomInfo.onUserEnter %d prefered chairId %d,score[%d],baseScore[%d]", userId, prefferedChairId, score, baseScore) chairId = -1 errMsg = "ok" blackUsers = []int{} index := -1 var existUserIds []int ri.lock.RLock() // 如果不是随机椅子 for _, v := range ri.userList { if v != nil { existUserIds = append(existUserIds, v.UserId) } } if prefferedChairId < 0 || prefferedChairId >= len(ri.userList) { for k, v := range ri.userList { if v == nil { chairId = k index = k continue } if v.UserId == userId { ri.lock.RUnlock() log.Release("privateroom.roomInfo.onUserEnter userId[%d] or chairId[%d] already exist", userId, chairId) chairId = v.ChairId return } } } else { if ri.userList[prefferedChairId] == nil { // 有空位 index = prefferedChairId chairId = prefferedChairId } } ri.lock.RUnlock() if chairId == -1 { log.Release("privateroom.roomInfo.onUserEnter roomNo[%d] no empty chair", ri.RoomNo) errMsg = "no empty chair" return } if ri.isDual && 1 == chairId { chairId = 2 index = 1 } ri.lock.Lock() ru := roomUserInfo{ RoomUser: pb.RoomUser{ UserId: userId, NickName: nickName, ChairId: chairId, FaceId: faceId, FaceUrl: faceUrl, Score: score, BaseScore: baseScore, SetCount: setCount, YyfUid: yyfUid, }, requestSitTime: time.Now().Unix(), } ri.userList[index] = &ru ri.UserList[index] = &ru.RoomUser // ri.Room.PlayerNum=ri.Room.PlayerNum+1 // db2.Engine.ID(ri.Room.Id).Update(ri.Room) ri.lock.Unlock() if len(existUserIds) > 0 { blackUsers = coreservice.FriendGetBlackListUserIn(userId, existUserIds) if len(blackUsers) > 0 { log.Debug("userRequestSit blackUserIn userId[%d] existUserIds%v blacklist%v", userId, existUserIds, blackUsers) } } return } func (ri *roomInfo) removeUser(userId int) bool { log.Debug("roomInfo.removeUser %d", userId) idx := -1 ri.lock.RLock() for k, v := range ri.userList { if v == nil { continue } if v.UserId == userId { idx = k break } } // ri.Room.PlayerNum=ri.Room.PlayerNum-1 // fmt.Printf("减少玩家人数") // db2.Engine.ID(ri.Room.Id).Update(ri.Room) ri.lock.RUnlock() if idx == -1 { log.Release("privateroom.roomInfo.removeUser userId[%d] not exist", userId) return false } ri.lock.Lock() ri.UserList[idx] = nil ri.userList[idx] = nil ri.lock.Unlock() return true } func (ri *roomInfo) updateUserScore(userId int, scoreDelta int) bool { var u *roomUserInfo ri.lock.RLock() for _, v := range ri.userList { if v == nil { continue } if v.UserId == userId { u = v break } } ri.lock.RUnlock() if u == nil { log.Release("privateroom.roomInfo.addUserScore userId[%d] not exist", userId) return false } if ri.Owner == -1 { u.Score += scoreDelta } else { u.Score = scoreDelta } ri.postUserScore(userId, scoreDelta) return true } func (ri *roomInfo) userSit(userId int, chairId int) int { ret := 0 ri.lock.RLock() defer ri.lock.RUnlock() for _, v := range ri.userList { if v == nil { continue } if v.UserId == userId && v.ChairId == chairId { v.isUserEntered = true ret = 1 } // 如果是换桌就不提示黑名单 if ri.changeChairFlag[chairId] { continue } if coreservice.FriendIsBlackListUser(v.UserId, userId) { go ri.sendBlackUserEnterNotification(v.UserId, userId) } } if ret == 0 { log.Release("privateroom.roomInfo.userSit [%d] not found", userId) ri.dump() } else { ri.changeChairFlag[chairId] = false } return ret } func (ri *roomInfo) sendBlackUserEnterNotification(userId int, enteredUserId int) { log.Debug("sendBlackUserEnterNotification userId[%d],enteredUserId[%d]", userId, enteredUserId) msg := Match_notificationInfo{Msg: room_blasklist_user, UserId: enteredUserId} d, _ := json.Marshal(msg) notification.AddNotification(userId, notification.Notification_PrivateRoom, string(d)) } func (ri *roomInfo) changeChair(userId int, chairId int) bool { // 比赛房间不允许换椅子 if ri.Owner == -1 { return false } if chairId < 0 || chairId >= len(ri.userList) { log.Release("roomInfo.changeChair [%d] chairId[%d] invalid", userId, chairId) return false } ri.lock.RLock() oldChairId := -1 for _, v := range ri.userList { if v == nil { continue } if v.UserId == userId { oldChairId = v.ChairId } } ri.lock.RUnlock() if oldChairId == -1 { log.Release("privateroom.roomInfo.changeChair [%d] not found", userId) ri.dump() return false } if oldChairId == chairId { log.Release("roomInfo.changeChair [%d] chairId[%d] same chair", userId, chairId) return false } ri.lock.Lock() defer ri.lock.Unlock() if ri.userList[chairId] != nil { log.Release("roomInfo.changeChair [%d] chairId[%d] chair taken", userId, chairId) return false } ri.userList[chairId] = ri.userList[oldChairId] ri.userList[chairId].isUserEntered = false ri.userList[chairId].ChairId = chairId ri.userList[oldChairId] = nil ri.UserList[oldChairId] = nil ri.UserList[chairId] = &ri.userList[chairId].RoomUser log.Debug("roomInfo.changeChair [%d] chairId[%d] changed to [%d]", userId, oldChairId, chairId) ri.changeChairFlag[chairId] = true return true } func (ri *roomInfo) isUserExist(userId int) bool { ri.lock.RLock() defer ri.lock.RUnlock() for _, v := range ri.userList { if v == nil { continue } if v.UserId == userId { return true } } return false } func (ri *roomInfo) isUserPlaying(userId int) bool { if ri.Status != pb.PrivateRoomStatus_Playing && ri.Status != pb.PrivateRoomStatus_Free { return false } return ri.isUserExist(userId) } func (ri *roomInfo) roomStart() { now := time.Now() ri.gameStartTime = now.Unix() ri.StartTime = now.Format(common.Layout) // 房主不设置奖金,表示奖金为报名费 if ri.Fee > 0 && ri.Prize > 0 && ri.createFee > 0 { //cash.GiveMoney(ri.Owner, ri.Fee*len(ri.userList), common.LOGTYPE_PRIVATEROOM_OWNER, "privateroom", "owner", "") for _, v := range ri.UserList { if v.UserId==ri.Owner{ //cash.GiveMoney2(r.Owner, r.Fee, common.LOGTYPE_PRIVATEROOM_ENTER, "privateroom", "fee return", "",r.Owner.yyfUid) cash.GiveMoney2(v.UserId, ri.Fee, common.LOGTYPE_PRIVATEROOM_ENTER, "privateroom", "fee return", "",v.YyfUid) } } } ri.postRoomStart() } func (ri *roomInfo) getWinners() []int { return ri.Winners } func (ri *roomInfo) setWinners(winners []int) bool { // 如果是百人场 if len(ri.userList) < 2 { ri.postRoomEnd() return true } if len(ri.Winners) > 0 { log.Release("roomInfo.setWinners already set") return false } for _, v := range winners { if !ri.isUserExist(v) { log.Release("roomInfo.setWinners user[%d] not found", v) ri.dump() return false } } ri.Winners = winners ri.postRoomEnd() return true } func (ri *roomInfo) getTotalTax() int { ret := 0 ri.lock.RLock() defer ri.lock.RUnlock() for _, v := range ri.userList { if v == nil { continue } ret += v.tax } return ret } func (ri *roomInfo) setPrizeAndTax(userId int, prize, tax int) { ri.lock.Lock() defer ri.lock.Unlock() for _, v := range ri.userList { if v == nil { continue } if v.UserId == userId { v.tax = tax v.prize = prize return } } } func (ri *roomInfo) getUsersDesc() string { type userDesc struct { UserId int ChairId int Score int Prize int } var users []userDesc ri.lock.Lock() for _, v := range ri.userList { if v == nil { continue } users = append(users, userDesc{UserId: v.UserId, ChairId: v.ChairId, Score: v.Score, Prize: v.prize}) } ri.lock.Unlock() d, _ := json.Marshal(users) return string(d) } func (ri *roomInfo) getUsersDescForDB() string { var ret string ri.lock.Lock() for _, v := range ri.userList { if v == nil { continue } ret = fmt.Sprintf("%s%d,%d,%d,%d,%d,%d;", ret, v.ChairId, v.UserId, ri.Fee, v.tax, v.prize, v.Score) } ri.lock.Unlock() return ret } func (ri *roomInfo) postRoomStart() { getRoomManager().postRoomStart(ri.RoomNo) } func (ri *roomInfo) postRoomEnd() { getRoomManager().postRoomEnd(ri.RoomNo, ri.Winners) } func (ri *roomInfo) postUserScore(userId int, scoreDelta int) { getRoomManager().postUserScore(ri.RoomNo, userId, scoreDelta) } func (ri *roomInfo) postAllUserScores() { for i := 0; i < len(ri.userList); i++ { if ri.userList[i] == nil { continue } ri.postUserScore(ri.userList[i].UserId, ri.userList[i].Score) } } func (ri *roomInfo) getAUserId() int { ret := 0 ri.lock.RLock() for i := 0; i < len(ri.userList); i++ { if ri.userList[i] == nil { continue } if ri.userList[i].isUserEntered { ret = ri.userList[i].UserId } } if ret == 0 { for i := 0; i < len(ri.userList); i++ { if ri.userList[i] == nil { continue } ret = ri.userList[i].UserId } } ri.lock.RUnlock() return ret } func (ri *roomInfo) isEmpty() bool { for i := 0; i < len(ri.userList); i++ { if ri.userList[i] != nil { return false } } return true } func (ri *roomInfo) getUserInfo(userId int) *pb.RoomUser { ri.lock.RLock() defer ri.lock.RUnlock() for _, v := range ri.userList { if v == nil { continue } if v.UserId == userId { return &v.RoomUser } } return nil } func (ri *roomInfo) getPrize(userId int) int { ri.lock.RLock() defer ri.lock.RUnlock() for _, v := range ri.userList { if v == nil { continue } if v.UserId == userId { return v.prize } } return 0 }