def _leave(self, userId, reason, needSendRes): ftlog.hinfo("_leave << |roomId, userId, reason: ", self.roomId, userId, reason, caller=self) self._remoteTableLeave(userId, reason) locList = onlinedata.getOnlineLocList(userId) if ftlog.is_debug(): ftlog.debug("<< |roomId, userId: ", self.roomId, userId, "|locList:", locList, caller=self) for loc in locList: onlineRoomId, onlineTableId = loc[0], loc[1] if strutil.getBigRoomIdFromInstanceRoomId( onlineRoomId) == self.bigRoomId: return False return True
def _wdecodeFromDictImpl(self, d): super(TodoTaskWinBuyTemplate, self)._decodeFromDictImpl(d) self.tip = d.get('tip', '') self.confparams = d ftlog.hinfo("TodoTaskWinBuyTemplate", d) if not isstring(self.tip): raise TYBizConfException(d, 'TodoTaskWinBuyTemplate.tip must be string')
def delHallNotifyInfo(ntimeId, uuid, hall, ntime): if ntimeId == NOTIFY_TIME_TIMER_ID: dtList = ntime.split('|') date = dtList[0] mtime = dtList[1] if date == getNowDateStr(): if mtime > getNowTimeStr(): argd = daobase.executeRankCmd('HGET', notify_timer_key % hall, uuid) if argd: daobase.executeRankCmd('HSET', notify_todaydel_key, uuid, json.dumps(argd)) return daobase.executeRankCmd('HDEL', notify_timer_key % hall, uuid) elif ntimeId in NOTIFY_TIME_REDIS_KEY_LIST: if ntimeId == getNowWeekdayStr() or ntimeId == NOTIFY_TIME_EVERYDAY_ID: if ntime > getNowTimeStr(): argd = daobase.executeRankCmd('HGET', notify_key % (ntimeId, hall), uuid) if argd: daobase.executeRankCmd('HSET', notify_todaydel_key, uuid, json.dumps(argd)) return daobase.executeRankCmd('HDEL', notify_key % (ntimeId, hall), uuid) elif ntimeId == NOTIFY_TIME_ATONCE_ID: # 这个分支属于防御性的,因为查询接口没有提供查询立即消息的功能 ftlog.hinfo('delHallNotifyInfo atonce', ntimeId, uuid, hall, ntime) return True ftlog.hinfo('delHallNotifyInfo error', ntimeId, uuid, hall, ntime) return False
def _initialize(): ftlog.hinfo('notifytodaylist initialize begin', datetime.now()) global _inited if not _inited: _inited = True resetNotifyTodayList() ftlog.hinfo('notifytodaylist initialize end', datetime.now())
def doQuickStart(self, msg): """ Note: 1> 由于不同游戏评分机制不同,例如德州会根据游戏阶段评分,所以把桌子评分存到redis里,方便各游戏服务器自由刷新。 2> 为了防止同一张桌子同时被选出来分配座位,选桌时会把tableScore里选出的桌子删除,玩家坐下成功后再添加回去,添回去之前无需刷新该桌子的评分。 3> 玩家自选桌时,可能选中一张正在分配座位的桌子,此时需要休眠后重试,只到该桌子完成分配或者等待超时。 """ assert self.roomId == msg.getParam("roomId") userId = msg.getParam("userId") shadowRoomId = msg.getParam("shadowRoomId") tableId = msg.getParam("tableId") clientId = msg.getParam("clientId") extParams = msg.getKey("params") ftlog.hinfo("doQuickStart->", "userId =", userId, "clientId =", clientId, "roomId =", self.roomId, "shadowRoomId =", shadowRoomId, "tableId =", tableId, "extParams =", extParams) if self.runStatus != self.ROOM_STATUS_RUN: FishQuickStart.onQuickStartFailed( FishQuickStart.ENTER_ROOM_REASON_MAINTENANCE, userId, clientId, self.roomId) return self.quickStartInGR(shadowRoomId, tableId, userId, clientId, extParams)
def doCancelCodeCheck(self, gameId, userId, clientId): ''' 取消code_check ''' try: timestamp = pktimestamp.getCurrentTimestamp() status = neituiguang.loadStatus(userId, timestamp) neituiguang.setInviter(status, 0) ftlog.hinfo('neituiguang.statics eventId=', 'CANCEL_INPUT_PRMOTE_CODE', 'userId=', userId, 'clientId=', clientId, 'result=', 'ok') mo = MsgPack() mo.setCmd('promote_info') mo.setResult('action', 'cancel_code_check') mo.setResult('code', 0) router.sendToUser(mo, userId) except Exception, e: if not isinstance(e, TYBizException): ftlog.error() ec, info = (e.errorCode, e.message) if isinstance(e, TYBizException) else (-1, '系统错误') ftlog.hinfo('neituiguang.statics eventId=', 'CANCEL_INPUT_PRMOTE_CODE', 'userId=', userId, 'clientId=', clientId, 'result=', 'failed') router.sendToUser(self.makeErrorResponse('cancel_code_check', ec, info), userId)
def sendNotify_message(gameId, userId, argd): results = {} results['pic'] = argd['iconAddr'] results['des'] = argd['context'] results['buttonType'] = argd['buttonType'] if argd['buttonType'] in ( '1', '2') else '1' results['todo'] = argd['passthrough'] results['closeTime'] = argd['timelimit'] results['alarmime'] = '0' results['action'] = 'notify_message' results['hideIcon'] = argd.get('hideIcon', '0') if len(argd['passthrough']) > 5: todoTask = eval(argd['passthrough']) results['todo'] = todoTask ftlog.hinfo('notify sendNotify_message passthrough todoTask', gameId, userId, todoTask, type(todoTask), argd['passthrough']) mp = MsgPack() mp.setCmd('game_notice') mp.setResult('gameId', gameId) mp.setResult('userId', userId) mp.updateResult(results) router.sendToUser(mp, userId) ftlog.hinfo('notify sendNotify_message', gameId, userId, results)
def _enter(self, userId): ftlog.hinfo("_enter << |roomId, userId, _roomUsersN: ", self.roomId, userId, len(self._roomUsers), caller=self) isOk, checkResult = self.checkSitCondition(userId) if not isOk: return False, checkResult if userId in self._roomUsers: return False, TYRoom.ENTER_ROOM_REASON_CONFLICT if not self.scheduler.enter(userId): return False, TYRoom.ENTER_ROOM_REASON_CONFLICT self._roomUsers.add(userId) if ftlog.is_debug(): ftlog.info("_enter add to _roomUsers.add |roomId, userId, _roomUsersN: ", self.roomId, userId, len(self._roomUsers), caller=self) if ftlog.is_debug(): ftlog.debug(">> |roomId, userId, _roomUsersN: ", self.roomId, userId, len(self._roomUsers), caller=self) ftlog.debug(">> |roomId, userId, _roomUsers: ", self.roomId, userId, self._roomUsers, caller=self) locList = onlinedata.getOnlineLocList(userId) ftlog.debug(">> |roomId, userId, locList:", self.roomId, userId, locList) PlayerRoomDao.clear(userId, self.bigRoomId) # 防止因系统错误造成的数据遗留问题 return True, TYRoom.ENTER_ROOM_REASON_OK
def doCancelCodeCheck(self, gameId, userId, clientId): ''' 取消code_check ''' try: timestamp = pktimestamp.getCurrentTimestamp() status = neituiguang.loadStatus(userId, timestamp) neituiguang.setInviter(status, 0) ftlog.hinfo('neituiguang.statics eventId=', 'CANCEL_INPUT_PRMOTE_CODE', 'userId=', userId, 'clientId=', clientId, 'result=', 'ok') mo = MsgPack() mo.setCmd('promote_info') mo.setResult('action', 'cancel_code_check') mo.setResult('code', 0) router.sendToUser(mo, userId) except Exception, e: if not isinstance(e, TYBizException): ftlog.error() ec, info = (e.errorCode, e.message) if isinstance( e, TYBizException) else (-1, '系统错误') ftlog.hinfo('neituiguang.statics eventId=', 'CANCEL_INPUT_PRMOTE_CODE', 'userId=', userId, 'clientId=', clientId, 'result=', 'failed') router.sendToUser( self.makeErrorResponse('cancel_code_check', ec, info), userId)
def doSilverLottery(userId, gameId, clientId): ''' 银盘抽奖 ''' # 减少抽奖卡 timestamp = pktimestamp.getCurrentTimestamp() userAssets = hallitem.itemSystem.loadUserAssets(userId) _, consumeCount, _final = userAssets.consumeAsset(gameId, hallitem.ASSET_ITEM_LOTTERY_CARD_ID, 1, timestamp, 'ROULETTE_SILVER', 0) if consumeCount < 1: # 去金盘抽奖 result = doGetGoldUpdate(userId, gameId, clientId) from hall.servers.util.roulette_handler import rouletteHelper mo = rouletteHelper.makeRouletteQueryResponse(gameId, userId, clientId, 'roulette_goldUpdate', result) from poker.protocol import router router.sendToUser(mo, userId) return datachangenotify.sendDataChangeNotify(gameId, userId, 'item') # 抽奖 result = {} result['items'] = doRouletteSilverLottery(userId, gameId, clientId) # 判断下次的抽奖为金盘还是银盘 result['rouletteType'] = 'silver' result['cardNumber'] = userAssets.balance(gameId, hallitem.ASSET_ITEM_LOTTERY_CARD_ID, timestamp) # 返回信息,判断是否有抽奖卡,没有的话,改为金盘抽奖 ftlog.hinfo('doSilverLottery.userId=', userId, 'gameId=', gameId, 'clientId=', clientId, 'items=', result.get('items', []), 'rouletteType=', 1, 'number=', 1) sendGiftsToUser(userId, gameId, clientId, [result['items']]) return result
def doQuickStart(self, msg): ''' Note: 1> 由于不同游戏评分机制不同,例如德州会根据游戏阶段评分,所以把桌子评分存到redis里,方便各游戏服务器自由刷新。 2> 为了防止同一张桌子同时被选出来分配座位,选桌时会把tableScore里选出的桌子删除,玩家坐下成功后再添加回去,添回去之前无需刷新该桌子的评分。 3> 玩家自选桌时,可能选中一张正在分配座位的桌子,此时需要休眠后重试,只到该桌子完成分配或者等待超时。 ''' assert self.roomId == msg.getParam("roomId") userId = msg.getParam("userId") shadowRoomId = msg.getParam("shadowRoomId") tableId = msg.getParam("tableId") exceptTableId = msg.getParam('exceptTableId') clientId = msg.getParam("clientId") ftlog.hinfo(getMethodName(), "<<", "|userId, clientId, roomId, shadowRoomId, tableId:", userId, clientId, self.roomId, shadowRoomId, tableId) if tableId == 0: # 服务器为玩家选择桌子并坐下 shadowRoomId = choice(self.roomDefine.shadowRoomIds) tableId = self.getBestTableId(userId, shadowRoomId, exceptTableId) else: # 玩家自选桌子坐下 assert isinstance(shadowRoomId, int) and gdata.roomIdDefineMap()[ shadowRoomId].bigRoomId == self.roomDefine.bigRoomId tableId = self.enterOneTable(userId, shadowRoomId, tableId) if not tableId: ftlog.error(getMethodName(), "getFreeTableId timeout", "|userId, roomId, tableId:", userId, self.roomId, tableId) return if ftlog.is_debug(): ftlog.info(getMethodName(), "after choose table", "|userId, shadowRoomId, tableId:", userId, shadowRoomId, tableId) extParams = msg.getKey('params') self.querySitReq(userId, shadowRoomId, tableId, clientId, extParams)
def onSitOk(self, userId, idleSeatId, result): '''坐下条件成功后的处理 ''' if ftlog.is_debug(): ftlog.debug('onSitOk << |userId, tableId, seatId:', userId, self.tableId, idleSeatId, "|observers:", self.observers, caller=self) # 设置玩家坐在座位上 seat = self.table.seats[idleSeatId - 1] seat.userId = userId seat.setWaitingState() if ftlog.is_debug(): ftlog.debug("|seats:", self.table.seats, caller=self) if userId in self.table.observers: del self.table.observers[userId] onlinedata.removeOnlineLoc(userId, self.roomId, self.tableId) # 设置玩家的在线状态 if ftlog.is_debug(): ftlog.debug("before addOnlineLoc. |tableId, onlineSeatId:", self.tableId, onlinedata.getOnlineLocSeatId(userId, self.roomId, self.tableId), caller=self) onlinedata.addOnlineLoc(userId, self.roomId, self.tableId, idleSeatId) if ftlog.is_debug(): ftlog.debug("after addOnlineLoc. |tableId, onlineSeatId:", self.tableId, onlinedata.getOnlineLocSeatId(userId, self.roomId, self.tableId), caller=self) result["seatId"] = idleSeatId result["reason"] = TYRoom.ENTER_ROOM_REASON_OK ftlog.hinfo('onSitOk >> |userId, tableId, seatId:', userId, self.tableId, idleSeatId, "|observers:", self.observers, caller=self)
def doSilverLottery(userId, gameId, clientId): ''' 银盘抽奖 ''' # 减少抽奖卡 timestamp = pktimestamp.getCurrentTimestamp() userAssets = hallitem.itemSystem.loadUserAssets(userId) _, consumeCount, _final = userAssets.consumeAsset( gameId, hallitem.ASSET_ITEM_LOTTERY_CARD_ID, 1, timestamp, 'ROULETTE_SILVER', 0) if consumeCount < 1: # 去金盘抽奖 result = doGetGoldUpdate(userId, gameId, clientId) from hall.servers.util.roulette_handler import rouletteHelper mo = rouletteHelper.makeRouletteQueryResponse(gameId, userId, clientId, 'roulette_goldUpdate', result) from poker.protocol import router router.sendToUser(mo, userId) return datachangenotify.sendDataChangeNotify(gameId, userId, 'item') # 抽奖 result = {} result['items'] = doRouletteSilverLottery(userId, gameId, clientId) # 判断下次的抽奖为金盘还是银盘 result['rouletteType'] = 'silver' result['cardNumber'] = userAssets.balance( gameId, hallitem.ASSET_ITEM_LOTTERY_CARD_ID, timestamp) # 返回信息,判断是否有抽奖卡,没有的话,改为金盘抽奖 ftlog.hinfo('doSilverLottery.userId=', userId, 'gameId=', gameId, 'clientId=', clientId, 'items=', result.get('items', []), 'rouletteType=', 1, 'number=', 1) sendGiftsToUser(userId, gameId, clientId, [result['items']]) return result
def __linit__(self, desc, tip, payOrderProduct, payOrderText=None, confparams=None): super(TodoTaskLuckBuy, self).__init__('pop_lucky_buy') self.setParam('desc', desc) self.setParam('tip', tip) # hall4.01以上客户端使用的新字段 productParams = TodoTaskHelper.getParamsByProduct(payOrderProduct) self.setParam('price', productParams['price']) self.setParam('productDesc', productParams['desc']) ftlog.hinfo("TodoTaskLuckBuy|v4.56|confparams", confparams) if confparams: pickey = 'pic_' + productParams['price'] if pickey in confparams: self.setParam('pic', confparams[pickey]) self.setParam('action', 'pop_lucky_buy') ftlog.hinfo("TodoTaskLuckBuy|v4.56|pic", productParams['price'], confparams[pickey]) if payOrderProduct: self.setSubCmdWithText(TodoTaskPayOrder(payOrderProduct), payOrderText)
def _leave(self, userId, reason, needSendRes): ftlog.hinfo("_leave << |roomId, userId, reason:", self.roomId, userId, reason, caller=self) if reason == TYRoom.LEAVE_ROOM_REASON_LOST_CONNECTION: return False if not self._remoteTableLeave(userId, reason): return False for shadowRoomId in self.roomUsers: if userId in self.roomUsers[shadowRoomId]: break if userId in self.roomUsers[shadowRoomId]: self.roomUsers[shadowRoomId].remove(userId) self.userCountTotal -= 1 if ftlog.is_debug(): ftlog.debug( "|shadowRoomId, userId, self.roomUsers[shadowRoomId]", shadowRoomId, userId, self.roomUsers[shadowRoomId], "|self.userCountTotal, self.isActive:", self.userCountTotal, self.isActive, caller=self) # 关闭active room if len(self.isActive) > 1 and \ self.roomConf["closeTableRatio"] * self.tableConf["maxSeatN"] * ( len(self.isActive) - 1) > self.userCountTotal: minUserRoomId = 0 for rid in self.roomDefine.shadowRoomIds[1:]: if rid in self.isActive: if not minUserRoomId or len(self.roomUsers[rid]) < len( self.roomUsers[minUserRoomId]): minUserRoomId = rid self.isActive.remove(minUserRoomId) if ftlog.is_debug(): ftlog.debug( "remove active room |minUserRoomId, userId, self.roomUsers[minUserRoomId]", minUserRoomId, userId, self.roomUsers[minUserRoomId], "|self.userCountTotal, self.isActive:", self.userCountTotal, self.isActive, caller=self) # PlayerRoomDao.clear(userId, self.bigRoomId) return True
def doQuickStart(self, msg): ''' Note: 1> 每个房间一张桌子 2> 房间分为激活和非激活状态 3> 选择激活房间中人数最少的 ''' assert self.roomId == msg.getParam("roomId") userId = msg.getParam("userId") shadowRoomId = msg.getParam("shadowRoomId") tableId = msg.getParam("tableId") clientId = msg.getParam("clientId") ftlog.hinfo("doQuickStart <<", "|userId, clientId, roomId, shadowRoomId, tableId:", userId, clientId, self.roomId, shadowRoomId, tableId, caller=self) if tableId == 0: # 选择激活房间中人数最少的 shadowRoomId = self.roomDefine.shadowRoomIds[0] for rid in self.roomDefine.shadowRoomIds[1:]: if rid in self.isActive and \ len(self.roomUsers[rid]) < len(self.roomUsers[shadowRoomId]): shadowRoomId = rid break tableId = shadowRoomId * 10000 + 1 if not tableId: ftlog.error(getMethodName(), "getFreeTableId timeout", "|userId, roomId, tableId:", userId, self.roomId, tableId) return if ftlog.is_debug(): ftlog.info("after choose table", "|userId, shadowRoomId, tableId:", userId, shadowRoomId, tableId, caller=self) self.doEnter(userId) self.roomUsers[shadowRoomId].add(userId) self.userCountTotal += 1 if ftlog.is_debug(): ftlog.debug("|shadowRoomId, userId, self.roomUsers[shadowRoomId]", shadowRoomId, userId, self.roomUsers[shadowRoomId], "|self.userCountTotal:", self.userCountTotal, caller=self) # 增加active room if self.roomConf["openTableRatio"] * self.tableConf["maxSeatN"] * len(self.isActive) <= self.userCountTotal: if ftlog.is_debug(): ftlog.debug("|userId, self.roomDefine.shadowRoomIds[1:]:", userId, self.roomDefine.shadowRoomIds[1:], caller=self) for rid in self.roomDefine.shadowRoomIds[1:]: if rid not in self.isActive: self.isActive.add(rid) if ftlog.is_debug(): ftlog.debug("add active room |shadowRoomId, userId, self.roomUsers[shadowRoomId]", shadowRoomId, userId, self.roomUsers[shadowRoomId], "|self.userCountTotal, self.isActive:", self.userCountTotal, self.isActive, caller=self) break extParams = msg.getKey('params') self.sendSitReq(userId, shadowRoomId, tableId, clientId, extParams)
def _leave(self, userId, reason, needSendRes): ftlog.hinfo("_leave << |roomId, userId, _roomUsersN, reason: ", self.roomId, userId, len(self._roomUsers), reason, caller=self) if ftlog.is_debug(): ftlog.debug("<< |roomId, userId, _roomUsers: ", self.roomId, userId, self._roomUsers, caller=self) ftlog.debug("<< |roomId, userId, scheduler.users: ", self.roomId, userId, self.scheduler.users.keys(), caller=self) if reason == TYRoom.LEAVE_ROOM_REASON_LOST_CONNECTION: return False if not userId in self._roomUsers: locList = onlinedata.getOnlineLocList(userId) if locList: ftlog.error("_leave >> not userId in self._roomUsers ", "|roomId, userId, _roomUsersN: ", self.roomId, userId, len(self._roomUsers)) self._remoteTableLeave(userId, reason, locList) return True if userId in self.scheduler.sittingUsers: # 从队列分配玩家进牌桌时,该玩家不允许离开队列。 ftlog.warn("can't leave when start table!", caller=self) return False if userId not in self.scheduler.users: self._remoteTableLeave(userId, reason) if userId in self.scheduler.users: self.scheduler.leave(userId) self._onLeaveQueueOk(userId) self._roomUsers.remove(userId) if ftlog.is_debug(): ftlog.debug(">> |roomId, userId, _roomUsersN: ", self.roomId, userId, len(self._roomUsers), caller=self) ftlog.debug(">> |roomId, userId, _roomUsers: ", self.roomId, userId, self._roomUsers, caller=self) PlayerRoomDao.clear(userId, self.bigRoomId) return True
def _remoteTableLeave(self, userId, reason=LEAVE_ROOM_REASON_ACTIVE, locList=None): if not locList: locList = onlinedata.getOnlineLocList(userId) if ftlog.is_debug(): ftlog.debug("<< |roomId, userId: ", self.roomId, userId, "|locList:", locList, caller=self) for loc in locList: onlineRoomId, onlineTableId = loc[0], loc[1] if not onlineRoomId in gdata.roomIdDefineMap(): onlinedata.removeOnlineLoc(userId, onlineRoomId, onlineTableId) continue ctrlRoomId = gdata.roomIdDefineMap()[onlineRoomId].parentId if ctrlRoomId == self.roomId: ftlog.hinfo( "table leave |userId, onlineRoomId, onlineTableId:", userId, onlineRoomId, onlineTableId, caller=self) clientId = sessiondata.getClientId(userId) tableLeaveResultStr = self.queryTableManageTableLeaveReq( userId, onlineRoomId, onlineTableId, clientId, {"reason": reason}) if not tableLeaveResultStr: ftlog.warn( "table leave timeout, |userId, onlineRoomId, onlineTableId, reason:", userId, onlineRoomId, onlineTableId, reason, caller=self) # 玩家离开牌桌只返回成功 # tableLeaveResult = json.loads(tableLeaveResultStr) # ftlog.debug("|tableLeaveResult:", tableLeaveResult) # if tableLeaveResult.get("error"): # return False # if not tableLeaveResult["result"]["isOK"]: # return False if ftlog.is_debug(): locList = onlinedata.getOnlineLocList(userId) ftlog.debug(">> |roomId, userId: ", self.roomId, userId, "|locList:", locList, caller=self) # return True return True
def _doSit(self, msg, userId, seatId, clientId): ''' 玩家操作, 尝试在当前的某个座位上坐下 ''' if ftlog.is_debug(): ftlog.info("_doSit << |tableId, userId, seatId:", self.tableId, userId, seatId, caller=self) if ftlog.is_debug(): locList = onlinedata.getOnlineLocList(userId) ftlog.debug(self._baseLogStr("<<", userId), "|locList:", locList, caller=self) result = {"isOK": True, "userId": userId, "gameId": self.gameId, "roomId": self.bigRoomId, "tableId": self.tableId} idleSeatId = self._getValidIdleSeatId(userId, seatId - 1, result) if idleSeatId < 0: # self.room.sendTableClothRes(self.gameId, userId, self.tableType, self.tableTheme) self.sendTableInfoRes(result["seatId"], userId) self._onReSit(userId, -idleSeatId, clientId) return result if idleSeatId == 0: return result # rid, tid, sid = getOnlineLoc(userId, self.gameId) # 为了支持并发坐下,self.getValidIdleSeatId()到此函数执行前,不应该有异步操作 self.onSitOk(userId, idleSeatId, result) # if rid == 0: #旁观坐下时rid!=0 # TYPluginCenter.event(TYPluginUtils.updateMsg(cmd='EV_USER_FIRST_SIT', params={ # 'table': self, 'userId': userId}), self.gameId) player = self.players[idleSeatId - 1] self._playerSit(player) self.sendQuickStartRes(userId, clientId, result) self.sendTableInfoRes(result["seatId"], userId) # 发送 newUser 消息, 客户端通过该协议显示新玩家 mpNewUserRes = self.createMsgPackRes("newUser") playerInfo = player.getInfo() mpNewUserRes.updateResult(playerInfo) self.sendToAllTableUser(mpNewUserRes, exclude=[userId]) # 扩展事件. TYPluginCenter.event(TYPluginUtils.updateMsg(cmd=PluginEvents.EV_AFTER_SITDOWN, params=TYPluginUtils.mkdict( table=self, userId=userId, player=player)), self.gameId) if ftlog.is_debug(): ftlog.debug(self._baseLogStr(">>", userId), "|locList:", onlinedata.getOnlineLocList(userId), caller=self) ftlog.hinfo("_doSit >> get new seat, |tableId, userId, seatId:", self.tableId, userId, player.seatId, caller=self) return result
def doCheckCode(self, gameId, userId, clientId, promoteCode): ''' 确立推广关系,也就是领取红包 校验通过 设置推荐人 将用户加到推荐人的推广员名单里 ''' try: timestamp = pktimestamp.getCurrentTimestamp() status = neituiguang.loadStatus(userId, timestamp) # 检查是否能成为推荐人 # 转到promoteCode所在的UT进程中去处理 ec, info = neituiguang_remote.canBeInviter(promoteCode, userId) if ec != 0: raise NeituiguangException(ec, info) # 设置推荐人 neituiguang.setInviter(status, promoteCode) try: # 添加invitee,此处不需要处理失败的情况,前面已经检查了 ec, info = neituiguang_remote.addInvitee( promoteCode, userId, status.isBindMobile) if ec != 0: ftlog.warn('NeiTuiGuangTcpHandler.doCheckCode gameId=', gameId, 'userId=', userId, 'clientId=', clientId, 'promoteCode=', promoteCode, 'call=', 'neituiguang_remote.addInvitee', 'ec=', ec, 'info=', info) except: ftlog.error('NeiTuiGuangTcpHandler.doCheckCode gameId=', gameId, 'userId=', userId, 'clientId=', clientId, 'promoteCode=', promoteCode, 'call=', 'neituiguang_remote.addInvitee', 'ec=', ec, 'info=', info) ftlog.hinfo('neituiguang.statics eventId=', 'INPUT_PRMOTE_CODE', 'userId=', userId, 'clientId=', clientId, 'promoteCode=', promoteCode, 'result=', 'ok') mo = MsgPack() mo.setCmd('promote_info') mo.setResult('action', 'code_check') mo.setResult('code', 0) router.sendToUser(mo, userId) except Exception, e: if not isinstance(e, TYBizException): ftlog.error() ec, info = (e.errorCode, e.message) if isinstance( e, TYBizException) else (-1, '系统错误') ftlog.hinfo('neituiguang.statics eventId=', 'INPUT_PRMOTE_CODE', 'userId=', userId, 'clientId=', clientId, 'promoteCode=', promoteCode, 'result=', 'failed', 'ec=', ec, 'info=', info) router.sendToUser(self.makeErrorResponse('code_check', ec, info), userId)
def ppsCountRedisCmd(): global _REDIS_CMDS_, _REDIS_COUNT_, _REDIS_COUNT_TIME_ ct = datetime.now() dt = ct - _REDIS_COUNT_TIME_ dt = dt.seconds + dt.microseconds / 1000000.0 pps = '%0.2f' % (_REDIS_COUNT_ / dt) ftlog.hinfo("REDIS_PPS", pps, 'CMDCOUNT', _REDIS_COUNT_, 'DT %0.2f' % (dt), 'CMDS', json.dumps(_REDIS_CMDS_)) _REDIS_COUNT_TIME_ = ct _REDIS_CMDS_ = {} _REDIS_COUNT_ = 0
def ppsCountConfigCmds(): global _CONFIG_CMDS_, _CONFIG_COUNT_, _CONFIG_COUNT_TIME_ ct = datetime.now() dt = ct - _CONFIG_COUNT_TIME_ dt = dt.seconds + dt.microseconds / 1000000.0 pps = '%0.2f' % (_CONFIG_COUNT_ / dt) ftlog.hinfo("CONFIG_PPS", pps, 'CMDCOUNT', _CONFIG_COUNT_, 'DT %0.2f' % (dt), 'CMDS', strutil.dumps(_CONFIG_CMDS_)) _CONFIG_COUNT_TIME_ = ct _CONFIG_CMDS_ = {} _CONFIG_COUNT_ = 0
def resetNotifyTodayList(): global _update date = datetime.now().strftime('%Y-%m-%d') if _update != date: _update = date global _pushed _pushed = False initNotifyFromRedis() _pushed = True ftlog.hinfo('resetNotifyTodayList')
def _startTable(self, tableId, playerN=0, recyclePlayersN=0): ''' 不锁队列,启动一张桌子 recyclePlayersN表示需要从牌桌回收到队列的人数 ''' ftlog.hinfo("_startTable <<", self.baseLogStr(tableId), "|sittingUsers:", self.sittingUsers, "|playerN, recyclePlayersN:", playerN, recyclePlayersN, caller=self) sittedN = 0 userIds = set() try: while sittedN < playerN and len(self.users) > 0: # 确保无异步操作 userId = self._popOneUser() if not userId: # 队列里没有可以参与分桌的玩家 break userIds.add(userId) sittedN += 1 if ftlog.is_debug(): ftlog.debug("bring user to table", self.baseLogStr(tableId, userId), "|userIds:", userIds, caller=self) # 移到GT处理,节约GT时间 # for userId in userIds: # onlinedata.removeOnlineLoc(userId, self.room.roomId, self.room.roomId * 10000) # if ftlog.is_debug() : # ftlog.debug("|userId, locList:", userId, onlinedata.getOnlineLocList(userId), caller=self) shadowRoomId = tableId / 10000 self.room.sendTableManageGameStartReq(shadowRoomId, tableId, list(userIds), recyclePlayersN) # resultStr = self.room.queryTableManageGameStartReq(shadowRoomId, tableId, list(userIds)) # result = json.loads(resultStr) # ftlog.debug("|result:", result) except: ftlog.exception() self.sittingUsers.difference_update(userIds) ftlog.hinfo("_startTable >>", self.baseLogStr(tableId), "|sittingUsers:", self.sittingUsers, "|len(userIds):", len(userIds), caller=self)
def end(self): self.endTimer.cancel() self._alive = False if self.argd['ntimeId'] == NOTIFY_TIME_TIMER_ID: daobase.executeRankCmd('HDEL', notify_timer_key % self.argd['hall'], self.uuid) ftlog.hinfo('HDEL.notify timer', self.argd) ftlog.hinfo('Notify.end', self.argd['uuid'])
def ppsCountRedisCmd(): global _REDIS_CMDS_, _REDIS_COUNT_, _REDIS_COUNT_TIME_ ct = datetime.now() dt = ct - _REDIS_COUNT_TIME_ dt = dt.seconds + dt.microseconds / 1000000.0 pps = '%0.2f' % (_REDIS_COUNT_ / dt) ftlog.hinfo("REDIS_PPS", pps, 'CMDCOUNT', _REDIS_COUNT_, 'DT %0.2f' % (dt), 'CMDS', json.dumps(_REDIS_CMDS_)) _REDIS_COUNT_TIME_ = ct _REDIS_CMDS_ = {} _REDIS_COUNT_ = 0
def addChip(userId, gameId, clientId, chip, leagueId, homewin, winPos): trueDelta, final = userchip.incrChip( userId, gameId, chip, userchip.ChipNotEnoughOpMode.NOOP, pokerconf.biEventIdToNumber("HALL_SPORTLOTTERY"), leagueId, clientId, 0, int(homewin * 100), winPos) if trueDelta != 0: datachangenotify.sendDataChangeNotify(gameId, userId, 'udata') ftlog.hinfo('sportlottery addchip', 'userId=', userId, 'chip=', chip, 'trueDelta=', trueDelta, 'final=', final) return trueDelta, final
def sendNotify_announce(gameId, userId, argd): results = {} results['context'] = argd['context'] results['action'] = 'notify_announce' mp = MsgPack() mp.setCmd('game_notice') mp.setResult('gameId', gameId) mp.setResult('userId', userId) mp.updateResult(results) router.sendToUser(mp, userId) ftlog.hinfo('notify sendNotify_announce', gameId, userId, results)
def sendQuickStartRes(cls, gameId, userId, reason, roomId=0, tableId=0, info=""): mpQuickRes = MsgPack() mpQuickRes.setCmd('quick_start') mpQuickRes.setResult('info', info) mpQuickRes.setResult('userId', userId) mpQuickRes.setResult('gameId', gameId) mpQuickRes.setResult('roomId', roomId) mpQuickRes.setResult('tableId', tableId) mpQuickRes.setResult('seatId', 0) # 兼容检查seatId参数的地主客户端 mpQuickRes.setResult('reason', reason) router.sendToUser(mpQuickRes, userId) ftlog.hinfo("|mpQuickRes:", mpQuickRes, caller=cls)
def logTableChat(gameId, roomId, tableId, senderUserId, chatText): if not chatText: return if senderUserId <= 0: return try: username = unicode(str(userdata.getAttr(senderUserId, 'name'))) roomName = unicode(str(gdata.getRoomConfigure(roomId)['name'])) ftlog.hinfo('tableChatLog gameId=%s; room="%s"; table=%s; userId=%s; name="%s"; msg="%s"' % ( gameId, roomName, tableId, senderUserId, username, chatText)) except Exception, e: ftlog.exception('exception locals():', locals())
def _startTable(self, tableId, playerIds, cardLevel): # 开桌 ftlog.hinfo("_startTable", self.baseLogStr(None, None), '|tableId, playerIds:', tableId, playerIds) params = {} params["bankerSeatIndex"] = -1 params["cardLevel"] = cardLevel for userId in playerIds: del self.users[userId] shadowRoomId = tableId / 10000 self.room.sendTableManageGameStartReq(shadowRoomId, tableId, playerIds, params=params)
def doQuickStart(self, msg): assert self.roomId == msg.getParam("roomId") userId = msg.getParam("userId") shadowRoomId = msg.getParam("shadowRoomId") tableId = msg.getParam("tableId") clientId = msg.getParam("clientId") ftlog.hinfo("doQuickStart <<", "|userId, clientId, roomId, shadowRoomId, tableId:", userId, clientId, self.roomId, shadowRoomId, tableId) # msg = TYPluginCenter.event(TYPluginUtils.updateMsg(cmd='EV_QUICK_START', params=TYPluginUtils.mkdict( # userId=userId, roomId=self.roomId), result={}), self.gameId) # # if msg.getResult("reason") != None: # info = u'玩家需要验证' # self.sendQuickStartRes(self.gameId, userId, msg.getResult("reason"), self.bigRoomId, 0, info) # return if tableId == 0: isOk, reason = self.doEnter(userId) elif tableId == self.roomId * 10000: if userId in self._roomUsers: isOk = True # 玩家在队列里时断线重连 reason = TYRoom.ENTER_ROOM_REASON_OK else: # 服务器重启造成玩家已经不在房间对象里了 onlinedata.removeOnlineLoc(userId, self.roomId, tableId) isOk = False reason = TYRoom.ENTER_ROOM_REASON_CONFLICT else: # 防御性代码,处理快速开始online错乱 onlineSeat = onlinedata.getOnlineLocSeatId(userId, shadowRoomId, tableId) if onlineSeat == 0: # 断线重连过程中玩家因为超时、金币不足或比赛淘汰等原因已被踢出房间 isOk = False reason = TYRoom.ENTER_ROOM_REASON_CONFLICT ftlog.warn("doQuickStart conflict!", "|userId, onlineLocList:", userId, onlinedata.getOnlineLocList(userId), "|shadowRoomId, tableId:", shadowRoomId, tableId) else: ftlog.error("doQuickStart conflict!", "|onlineSeat:", onlineSeat) if onlineSeat == gdata.roomIdDefineMap()[shadowRoomId].configure['tableConf']['maxSeatN'] + 1: # 牌桌里旁观的玩家断线重连,请求转给GT self.sendTableCallObserveReq(userId, shadowRoomId, tableId, clientId) elif onlineSeat > 0: # 牌桌里坐着的玩家断线重连,请求转给GT self.querySitReq(userId, shadowRoomId, tableId, clientId) return if isOk: self._onQuickStartOk(userId) elif reason == TYRoom.ENTER_ROOM_REASON_CONFLICT: info = u'玩家已经在游戏中,状态冲突' self.sendQuickStartRes(self.gameId, userId, reason, self.bigRoomId, 0, info) else: self.sendQuickStartRes(self.gameId, userId, reason, self.bigRoomId, 0, '')
def _leave(self, userId, reason, needSendRes): ftlog.hinfo("_leave << |roomId, userId, reason:", self.roomId, userId, reason, caller=self) if reason == TYRoom.LEAVE_ROOM_REASON_LOST_CONNECTION: return False if not self._remoteTableLeave(userId, reason): return False PlayerRoomDao.clear(userId, self.bigRoomId) return True
def start(self): self.startTimer.cancel() if self.argd['rmTag'] == 1: ftlog.hinfo('Notify.start error because be removed', self.argd['uuid']) return self._alive = True self.endTimer = FTTimer(NOTIFY_TIMER_LIFE, self.end) ftlog.hinfo('Notify.start', NOTIFY_TIMER_LIFE, self.argd['uuid'])
def logTableChat(gameId, roomId, tableId, senderUserId, chatText): if not chatText: return if senderUserId <= 0: return try: username = unicode(str(userdata.getAttr(senderUserId, 'name'))) roomName = unicode(str(gdata.getRoomConfigure(roomId)['name'])) ftlog.hinfo( 'tableChatLog gameId=%s; room="%s"; table=%s; userId=%s; name="%s"; msg="%s"' % (gameId, roomName, tableId, senderUserId, username, chatText)) except Exception, e: ftlog.exception('exception locals():', locals())
def sendTableManageGameStartReq(self, shadowRoomId, tableId, userIds, recyclePlayersN=0, params=None): '''recyclePlayersN表示需要从牌桌回收到队列的人数 ''' mpReq = self.makeTableManageReq(0, shadowRoomId, tableId, None, 'game_start', {'recyclePlayersN': recyclePlayersN}) mpReq.setParam("userIds", userIds) from poker.entity.game.rooms import tyRoomConst if self.roomConf['typeName'] == tyRoomConst.ROOM_TYPE_NAME_MTT and self.state == self.MTT_STATE_FINALS: mpReq.setParam("isFinalTable", True) if params: mpReq.updateParam(params) ftlog.hinfo(str(mpReq), caller=self) router.sendTableServer(mpReq, shadowRoomId)
def clientReqCheckin(userId, clientId, gameId): from hall.entity.localservice import localservice ftlog.debug("|clientReqCheckin|freeItemId|", userId, gameId, clientId) if not localservice.checkClientVer(userId, gameId, clientId): if ftlog.is_debug(): ftlog.debug("clientReqCheckin|less|clientVer", userId, gameId, clientId, clientId) return info = gamedata.getGameAttr(userId, HALL_GAMEID, 'checkin_new') if not info: ftlog.hinfo("clientReqCheckin|redis|havenot|checkin_new|", userId, gameId, clientId) return checkinImpl(userId, json.loads(info), clientId, gameId, True, '', WHERE_REQ)
def _leave(self, userId, reason, needSendRes): ftlog.hinfo("_leave << |roomId, userId, reason, state, _roomUsersN: ", self.roomId, userId, reason, self.getStateStr(), len(self._roomUsers), caller=self) if ftlog.is_debug(): ftlog.debug("<< |roomId, userId, _roomUsers: ", self.roomId, userId, self._roomUsers, caller=self) if reason == TYRoom.LEAVE_ROOM_REASON_LOST_CONNECTION: return False if self.state == self.MTT_STATE_START: return False if not userId in self._roomUsers: locList = onlinedata.getOnlineLocList(userId) if locList: ftlog.error("_leave >> not userId in self._roomUsers ", "|roomId, userId, _roomUsersN: ", self.roomId, userId, len(self._roomUsers)) self._remoteTableLeave(userId, reason, locList) return True if userId in self.scheduler.sittingUsers: # 从队列分配玩家进牌桌时,该玩家不允许离开队列。 ftlog.warn("can't leave when start table!", caller=self) return False if userId not in self.scheduler.users: self._remoteTableLeave(userId, reason) if userId in self.scheduler.users: self.scheduler.leave(userId) self._roomUsers.remove(userId) if ftlog.is_debug(): ftlog.debug(">> |roomId, userId, _roomUsersN: ", self.roomId, userId, len(self._roomUsers), caller=self) ftlog.debug(">> |roomId, userId, _roomUsers: ", self.roomId, userId, self._roomUsers, caller=self) if len(self._roomUsers) < 10: ftlog.hinfo("_leave >> |roomId, userId, _roomUsers: ", self.roomId, userId, self._roomUsers, caller=self) PlayerRoomDao.clear(userId, self.bigRoomId) needSendRewardTodoTask = True if reason == TYRoom.LEAVE_ROOM_REASON_ACTIVE: self.matchCounter['usersLeaveMatchCount'] += 1 needSendRewardTodoTask = False if self.state > self.MTT_STATE_START: if ftlog.is_debug(): ftlog.debug("|needSendRewardTodoTask:", needSendRewardTodoTask, caller=self) self.__leaveMatch(userId, needSendRewardTodoTask=needSendRewardTodoTask) # 此函数会检查玩家是否已经离开比赛, 主动离赛不弹奖状 return True
def doQuickStart(self, msg): ''' Note: 1> 由于不同游戏评分机制不同,例如德州会根据游戏阶段评分,所以把桌子评分存到redis里,方便各游戏服务器自由刷新。 2> 为了防止同一张桌子同时被选出来分配座位,选桌时会把tableScore里选出的桌子删除,玩家坐下成功后再添加回去,添回去之前无需刷新该桌子的评分。 3> 玩家自选桌时,可能选中一张正在分配座位的桌子,此时需要休眠后重试,只到该桌子完成分配或者等待超时。 4> 贵宾室为了凑桌,当一张桌子被取走需要等待返回,这样需要锁一下房间对象。 ''' assert self.roomId == msg.getParam("roomId") userId = msg.getParam("userId") shadowRoomId = msg.getParam("shadowRoomId") tableId = msg.getParam("tableId") clientId = msg.getParam("clientId") ftlog.hinfo("doQuickStart <<", "|userId, clientId, roomId, shadowRoomId, tableId:", userId, clientId, self.roomId, shadowRoomId, tableId, caller=self) # if tableId and tableId not in self._activeTables: #此方法不可行,GR的_activeTables是空的,实际数据在GT里 # ftlog.warn("tableId not in self._activeTables, tableId:", tableId) # tableId = 0 if tableId == 0: # 服务器为玩家选择桌子并坐下 shadowRoomId = choice(self.roomDefine.shadowRoomIds) tableId = self.getBestTableId(userId, shadowRoomId) # else: # 玩家自选桌子坐下 # assert isinstance(shadowRoomId, int) and gdata.roomIdDefineMap()[shadowRoomId].bigRoomId == self.roomDefine.bigRoomId # tableId = self.enterOneTable(userId, shadowRoomId, tableId) if not tableId: ftlog.error(getMethodName(), "getFreeTableId timeout", "|userId, roomId, tableId:", userId, self.roomId, tableId) return if ftlog.is_debug(): ftlog.info("after choose table", "|userId, shadowRoomId, tableId:", userId, shadowRoomId, tableId, caller=self) extParams = msg.getKey('params') self.doEnter(userId) self.querySitReq(userId, shadowRoomId, tableId, clientId, extParams)
def do_gdss_sport_end(self): matchId = runhttp.getParamInt('matchId', 0) leagueId = runhttp.getParamInt('leagueId', 0) homeTeamId = runhttp.getParamInt('homeTeamId', 0) awayTeamId = runhttp.getParamInt('awayTeamId', 0) timestamp = runhttp.getParamInt('timestamp', 0) scoreh = runhttp.getParamInt('scoreh', 0) scorea = runhttp.getParamInt('scorea', 0) oddsw = runhttp.getParamStr('oddsw', 0) oddsa = runhttp.getParamStr('oddsa', 0) oddsl = runhttp.getParamStr('oddsl', 0) status = runhttp.getParamInt('status', 0) try: import freetime.util.log as ftlog ftlog.hinfo('HttpGameHandler.do_gdss_sport_end enter', matchId, leagueId, homeTeamId, \ awayTeamId, timestamp, scoreh, scorea, oddsw, oddsa, oddsl, status) from hall.servers.center.rpc import newnotify_remote ret = newnotify_remote.doSportEnd(matchId, leagueId, homeTeamId, awayTeamId, timestamp, [scoreh, scorea], [oddsw, oddsa, oddsl], status) if ret == 0: ftlog.hinfo('HttpGameHandler.do_gdss_sport_end ok') return {'retmsg': 1} else: ftlog.hinfo('HttpGameHandler.do_gdss_sport_end failed') return {'retmsg': 0} except: ftlog.hinfo('HttpGameHandler.do_gdss_sport_end error') return {'error': 404}
def addAssetnpw(userId, itemId, count, biEventId): timestamp = pktimestamp.getCurrentTimestamp() userAssets = hallitem.itemSystem.loadUserAssets(userId) assetKind, _consumecount, _finalcount = userAssets.addAsset( HALL_GAMEID, itemId, count, timestamp, pokerconf.biEventIdToNumber(biEventId), 0) ftlog.hinfo("addAssetnpw|reward|addAsset|", biEventId, userId, itemId, count) # 通知用户道具和消息存在改变 if assetKind.keyForChangeNotify: datachangenotify.sendDataChangeNotify( HALL_GAMEID, userId, [assetKind.keyForChangeNotify, 'message'])
def onStandUpOk(self, userId, seatId): '''坐下条件成功后的处理 note: 站起后没有自动进入旁观列表 ''' if ftlog.is_debug(): ftlog.debug('<< |userId, tableId, seatId:', userId, self.tableId, seatId, caller=self) # 清理在线信息 onlinedata.removeOnlineLoc(userId, self.roomId, self.tableId) seat = self.table.seats[seatId - 1] seat.userId = 0 ftlog.hinfo('onStandUpOk >> |userId, tableId, seatId:', userId, self.tableId, seatId, "|observers:", self.observers, caller=self)
def _tryStartNewTable(self, minPlayersN): # self._state = self.STATE_START_TABLE # TODO: 约束:没法同时开桌 # 开桌 ftlog.hinfo("_tryStartNewTable", self.baseLogStr(None, None), '|minPlayersN:', minPlayersN) if len(self.users) < minPlayersN: # 不够开局 ftlog.warn(self.baseLogStr(None, None), 'users & robots not enough') elif len(self.idleTableIds) == 0: ftlog.error(self.baseLogStr(None, None), 'idle tables not enough') else: tableId = self.idleTableIds.pop() self.activeTableIds.add(tableId) # self._seatNPlayers(tableId, minPlayersN) self._startTable(tableId, minPlayersN)
def doGoldLottery(userId, gameId, clientId, number): ''' 金盘抽奖 ''' if number <= 0 or number > 50: ftlog.error('doGoldLottery number best be > 0 or <= 50, the msg is fake') return if ftlog.is_debug(): ftlog.debug('hallroulette.doGoldLottery userId:', userId, ' gameId:', gameId, ' clientId:', clientId, ' number:', number ) # 减少钻石 result = {} count = -(number * 20) trueDelta, _finalCount = userchip.incrDiamond(userId, gameId, count, daoconst.CHIP_NOT_ENOUGH_OP_MODE_NONE, 'HALL_ROULETTE', 0, 0) if not trueDelta: # 消费失败 return toShop() # 将抽奖数进行存储,满足bigRewardNumber,使用大奖概率,否则使用小奖概率 addBigRewardToPool(userId, gameId, clientId, number) # 抽奖 items = [] for _num in range(0, number): items.append(doRouletteLottery(userId, gameId, clientId)) result['items'] = items # 对抽奖进行修改,连抽的话进行统一的数据库操作 sendGiftsToUser(userId, gameId, clientId, items) # 更新钻石 datachangenotify.sendDataChangeNotify(gameId, userId, ['udata']) # 抽奖成功,进行小兵的下发 for _ in range(0, number): daobase.executeMixCmd('RPUSH', CURKEY, userId) # 统计需求 ftlog.hinfo('doGoldLottery.userId=', userId, 'gameId=', gameId, 'clientId=', clientId, 'number=', number, 'rouletteType=', 2, 'rewardItem=', items) TGHall.getEventBus().publishEvent(TYEventRouletteDiamond(userId, gameId, number)) return result
def ppsCountProtocolPack(): global _COUNT_COUNT, _COUNT_TIME, _COUNT_PACKS ct = datetime.now() dt = ct - _COUNT_TIME dt = dt.seconds + dt.microseconds / 1000000.0 pps = '%0.2f' % (_COUNT_COUNT / dt) plist = [] for k, v in _COUNT_PACKS.items(): plist.append('%s=%0.2f|%d' % (k, v / dt, v)) plist = ','.join(plist) ftlog.hinfo("NET_PPS", pps, 'TASKCOUNT', FTTasklet.concurrent_task_count, 'DT %0.2f' % (dt), 'TASKPEAK', FTTasklet.PEAKVALUE, 'PEAKTIME', FTTasklet.PEAKTIME.strftime('%m-%d %H:%M:%S'), 'ALLCOUNT', _COUNT_COUNT, 'PROTS', plist) _COUNT_TIME = ct _COUNT_PACKS = {} _COUNT_COUNT = 0
def doAdjustTablePlayers(self, msg): if ftlog.is_debug(): ftlog.debug("<<", "|roomId, state:", self.roomId, self.getStateStr(), caller=self) if self.state == self.MTT_STATE_START or self.state == self.MTT_STATE_QUALIFIER: self.scheduler.adjustTablePlayers(msg) elif self.state == self.MTT_STATE_PREFINALS: # tableId = msg.getParam("tableId") msg.setParam("playersN", 0) # 强制回收牌桌 self.scheduler.adjustTablePlayers(msg) activeTableIds = self.scheduler.activeTableIds ftlog.hinfo("before final |roomId:", self.roomId, "|activityTables, queueUsers:", activeTableIds, self.scheduler.users.keys(), caller=self) if len(activeTableIds) == 0 \ or len(self.scheduler.users) >= self.tableConf["maxSeatN"] - 1: # 第二个条件是防御代码,为了防止有桌子没有回收时导致决赛开不了。 if len(activeTableIds) > 0: ftlog.error("before final len(activeTableIds) > 0") self.__startFinalTableLater() else: self.__notifyFinalTable() elif self.state == self.MTT_STATE_FINALS: self.scheduler.adjustTablePlayers(msg, isFinal=True) # elif self.state == self.MTT_STATE_IDLE: #recycle决赛桌 # self.scheduler.adjustTablePlayers(msg) # self.state = self.MTT_STATE_READY elif self.state == self.MTT_STATE_DAY1_END: msg.setParam("playersN", 0) # 强制回收牌桌 self.scheduler.adjustTablePlayers(msg) day1WinnerIds = strutil.cloneData(self.scheduler.users.keys()) self.matchPlugin.rewardEnterDay2Match(self, day1WinnerIds) for userId in day1WinnerIds: self._leave(userId, TYRoom.LEAVE_ROOM_REASON_MATCH_END, needSendRes=False) activeTableIds = self.scheduler.activeTableIds ftlog.hinfo("before day1 match end |roomId:", self.roomId, "|activityTables, queueUsers:", activeTableIds, self.scheduler.users.keys(), caller=self)
def _leave(self, userId, reason, needSendRes): ftlog.hinfo("_leave << |roomId, userId, reason:", self.roomId, userId, reason, caller=self) if reason == TYRoom.LEAVE_ROOM_REASON_LOST_CONNECTION: return False if not self._remoteTableLeave(userId, reason): return False for shadowRoomId in self.roomUsers: if userId in self.roomUsers[shadowRoomId]: break if userId in self.roomUsers[shadowRoomId]: self.roomUsers[shadowRoomId].remove(userId) self.userCountTotal -= 1 if ftlog.is_debug(): ftlog.debug("|shadowRoomId, userId, self.roomUsers[shadowRoomId]", shadowRoomId, userId, self.roomUsers[shadowRoomId], "|self.userCountTotal, self.isActive:", self.userCountTotal, self.isActive, caller=self) # 关闭active room if len(self.isActive) > 1 and \ self.roomConf["closeTableRatio"] * self.tableConf["maxSeatN"] * ( len(self.isActive) - 1) > self.userCountTotal: minUserRoomId = 0 for rid in self.roomDefine.shadowRoomIds[1:]: if rid in self.isActive: if not minUserRoomId or len(self.roomUsers[rid]) < len(self.roomUsers[minUserRoomId]): minUserRoomId = rid self.isActive.remove(minUserRoomId) if ftlog.is_debug(): ftlog.debug("remove active room |minUserRoomId, userId, self.roomUsers[minUserRoomId]", minUserRoomId, userId, self.roomUsers[minUserRoomId], "|self.userCountTotal, self.isActive:", self.userCountTotal, self.isActive, caller=self) # PlayerRoomDao.clear(userId, self.bigRoomId) return True
def _startTable(self, tableId, playerN=0, recyclePlayersN=0): ''' 不锁队列,启动一张桌子 recyclePlayersN表示需要从牌桌回收到队列的人数 ''' ftlog.hinfo("_startTable <<", self.baseLogStr(tableId), "|sittingUsers:", self.sittingUsers, "|playerN, recyclePlayersN:", playerN, recyclePlayersN, caller=self) sittedN = 0 userIds = set() try: while sittedN < playerN and len(self.users) > 0: # 确保无异步操作 userId = self._popOneUser() if not userId: # 队列里没有可以参与分桌的玩家 break userIds.add(userId) sittedN += 1 if ftlog.is_debug(): ftlog.debug("bring user to table", self.baseLogStr(tableId, userId), "|userIds:", userIds, caller=self) # 移到GT处理,节约GT时间 # for userId in userIds: # onlinedata.removeOnlineLoc(userId, self.room.roomId, self.room.roomId * 10000) # if ftlog.is_debug() : # ftlog.debug("|userId, locList:", userId, onlinedata.getOnlineLocList(userId), caller=self) shadowRoomId = tableId / 10000 self.room.sendTableManageGameStartReq(shadowRoomId, tableId, list(userIds), recyclePlayersN) # resultStr = self.room.queryTableManageGameStartReq(shadowRoomId, tableId, list(userIds)) # result = json.loads(resultStr) # ftlog.debug("|result:", result) except: ftlog.exception() self.sittingUsers.difference_update(userIds) ftlog.hinfo("_startTable >>", self.baseLogStr(tableId), "|sittingUsers:", self.sittingUsers, "|len(userIds):", len(userIds), caller=self)
def onStandUpOk(self, userId, seatId): '''坐下条件成功后的处理 note: 站起后没有自动进入旁观列表 ''' if ftlog.is_debug(): ftlog.debug('<< |userId, tableId, seatId:', userId, self.tableId, seatId, caller=self) # 清理在线信息 onlinedata.removeOnlineLoc(userId, self.roomId, self.tableId) # 清理当前座位的userId self.recordSeatUserId(seatId, 0) seat = self.table.seats[seatId - 1] seat.userId = 0 # 更新当前桌子的快速开始积分, 如果此时桌子正在分配玩家,刷新将失败 # self.room.updateTableScore(self.getTableScore(), self.tableId) ftlog.hinfo('onStandUpOk >> |userId, tableId, seatId:', userId, self.tableId, seatId, "|observers:", self.observers, caller=self)
def _leave(self, userId, reason, needSendRes): ftlog.hinfo("_leave << |roomId, userId, _roomUsersN, reason: ", self.roomId, userId, len(self._roomUsers), reason, caller=self) if ftlog.is_debug(): ftlog.debug("<< |roomId, userId, _roomUsers: ", self.roomId, userId, self._roomUsers, caller=self) ftlog.debug("<< |roomId, userId, scheduler.users: ", self.roomId, userId, self.scheduler.users.keys(), caller=self) if reason == TYRoom.LEAVE_ROOM_REASON_LOST_CONNECTION: return False if not userId in self._roomUsers: locList = onlinedata.getOnlineLocList(userId) if locList: ftlog.error("_leave >> not userId in self._roomUsers ", "|roomId, userId, _roomUsersN: ", self.roomId, userId, len(self._roomUsers)) self._remoteTableLeave(userId, reason, locList) return True # if userId in self.scheduler.sittingUsers: # 从队列分配玩家进牌桌时,该玩家不允许离开队列。 # ftlog.warn("can't leave when start table!", caller=self) # return False if userId not in self.scheduler.users: self._remoteTableLeave(userId, reason) if userId in self.scheduler.users: self.scheduler.leave(userId) self._onLeaveQueueOk(userId) self._roomUsers.remove(userId) if ftlog.is_debug(): ftlog.debug(">> |roomId, userId, _roomUsersN: ", self.roomId, userId, len(self._roomUsers), caller=self) ftlog.debug(">> |roomId, userId, _roomUsers: ", self.roomId, userId, self._roomUsers, caller=self) PlayerRoomDao.clear(userId, self.bigRoomId) return True
def doQuickStart(self, msg): ''' Note: 1> 由于不同游戏评分机制不同,例如德州会根据游戏阶段评分,所以把桌子评分存到redis里,方便各游戏服务器自由刷新。 2> 为了防止同一张桌子同时被选出来分配座位,选桌时会把tableScore里选出的桌子删除,玩家坐下成功后再添加回去,添回去之前无需刷新该桌子的评分。 3> 玩家自选桌时,可能选中一张正在分配座位的桌子,此时需要休眠后重试,只到该桌子完成分配或者等待超时。 4> 贵宾室为了凑桌,当一张桌子被取走需要等待返回,这样需要锁一下房间对象。 ''' assert self.roomId == msg.getParam("roomId") userId = msg.getParam("userId") shadowRoomId = msg.getParam("shadowRoomId") tableId = msg.getParam("tableId") clientId = msg.getParam("clientId") ftlog.hinfo("doQuickStart <<", "|userId, clientId, roomId, shadowRoomId, tableId:", userId, clientId, self.roomId, shadowRoomId, tableId, caller=self) # if tableId and tableId not in self._activeTables: #此方法不可行,GR的_activeTables是空的,实际数据在GT里 # ftlog.warn("tableId not in self._activeTables, tableId:", tableId) # tableId = 0 if tableId == 0: # 服务器为玩家选择桌子并坐下 shadowRoomId = choice(self.roomDefine.shadowRoomIds) tableId = self.getBestTableId(userId, shadowRoomId) # else: # 玩家自选桌子坐下 # assert isinstance(shadowRoomId, int) and gdata.roomIdDefineMap()[shadowRoomId].bigRoomId == self.roomDefine.bigRoomId # tableId = self.enterOneTable(userId, shadowRoomId, tableId) if not tableId: ftlog.error(getMethodName(), "getFreeTableId timeout", "|userId, roomId, tableId:", userId, self.roomId, tableId) return if ftlog.is_debug(): ftlog.info("after choose table", "|userId, shadowRoomId, tableId:", userId, shadowRoomId, tableId, caller=self) extParams = msg.getKey('params') self.doEnter(userId) self.querySitReq(userId, shadowRoomId, tableId, clientId, extParams)
def threadInfo(): if _myps: mem = _myps.memory_info_ex() infos = [] infos.append('pid') infos.append(str(_myps.pid)) infos.append('ppid') infos.append(str(_myps.ppid())) infos.append('cpu') infos.append(str(_myps.cpu_percent())) infos.append('threads') infos.append(str(_myps.num_threads())) infos.append('rss') infos.append('%dM' % (int(mem.rss / 1024 / 1024))) infos.append('vms') infos.append('%dM' % (int(mem.vms / 1024 / 1024))) infos.append('shr') # PATCH: osx下没有shared infos.append('%dM' % (int(getattr(mem, 'shared', 0) / 1024 / 1024))) ftlog.hinfo('THREADINFO', ','.join(infos)) else: ftlog.hinfo('THREADINFO psutil not install')
def startLoop(self, needShuffleQueue=True): ftlog.hinfo("startLoop <<", self.baseLogStr(), "|needShuffleQueue:", needShuffleQueue, caller=self) if needShuffleQueue: self.shuffleQueue() while len(self.users) >= self.n_start * 3: self._tryStartNewTable(self.n_start) leftQueueLen = len(self.users) if leftQueueLen > self.n_start * 2: oneThirdQueueLen = leftQueueLen / 3 if ftlog.is_debug(): ftlog.info(self.baseLogStr(), 'divice last three tables.', '|leftQueueLen, oneThirdQueueLen:', leftQueueLen, oneThirdQueueLen) self._tryStartNewTable(oneThirdQueueLen) leftQueueLen -= oneThirdQueueLen halfQueueLen = leftQueueLen / 2 if ftlog.is_debug(): ftlog.info(self.baseLogStr(), 'deuce last two tables.', '|leftQueueLen, halfQueueLen:', leftQueueLen, halfQueueLen) self._tryStartNewTable(halfQueueLen) self._tryStartNewTable(leftQueueLen - halfQueueLen) elif leftQueueLen > self.n_start: halfQueueLen = leftQueueLen / 2 if ftlog.is_debug(): ftlog.info(self.baseLogStr(), 'deuce last two tables.', '|leftQueueLen, halfQueueLen:', leftQueueLen, halfQueueLen) self._tryStartNewTable(halfQueueLen) self._tryStartNewTable(leftQueueLen - halfQueueLen) elif leftQueueLen > 0: self._tryStartNewTable(leftQueueLen) super(TYSMttQueueScheduler, self).startLoop()
def loginGame(self, userId, gameId, clientId, iscreate, isdayfirst): ''' 用户登录一个游戏, 游戏自己做一些其他的业务或数据处理 例如: 1. IOS大厅不发启动资金的补丁, 2. 麻将的记录首次登录时间 3. 游戏插件道具合并至大厅道具 ''' ftlog.hinfo('loginGame <<|userId=', userId, 'gameId=', gameId, 'clientId=', clientId, 'isdayfirst=', isdayfirst, caller=self) self.AccountClass.loginGame(userId, gameId, clientId, iscreate, isdayfirst) # 获取前端代码版本号。以这个版本号判断前端功能 # msg = runcmd.getMsgPack() # codeVer = msg.getParam('v', 0) # gamedata.setGameAttr(userId, gameId, 'codeVer', codeVer) TYPluginCenter.event(TYPluginUtils.updateMsg(cmd='EV_USER_LOGIN', params={ 'userId': userId, 'isCreate': iscreate, 'clientId': clientId, 'dayFirst': isdayfirst, # 'codeVer': codeVer, }), gameId)
def onSitOk(self, userId, idleSeatId, result): '''坐下条件成功后的处理 Return: player:新空座位上的player ''' ftlog.hinfo('onSitOk << |userId, tableId, seatId:', userId, self.tableId, idleSeatId, "|observers:", self.observers, caller=self) # 设置玩家坐在座位上, 为了支持并发坐下,此设置需要在异步操作前完成!!! seat = self.table.seats[idleSeatId - 1] seat.userId = userId seat.setWaitingState() if ftlog.is_debug(): ftlog.debug("|seats:", self.table.seats, caller=self) if userId in self.table.observers: del self.table.observers[userId] onlinedata.removeOnlineLoc(userId, self.roomId, self.tableId) # 设置玩家的在线状态 if ftlog.is_debug(): ftlog.debug("before addOnlineLoc. |tableId, onlineSeatId:", self.tableId, onlinedata.getOnlineLocSeatId(userId, self.roomId, self.tableId), caller=self) onlinedata.addOnlineLoc(userId, self.roomId, self.tableId, idleSeatId) if ftlog.is_debug(): ftlog.debug("after addOnlineLoc. |tableId, onlineSeatId:", self.tableId, onlinedata.getOnlineLocSeatId(userId, self.roomId, self.tableId), caller=self) # 记录当前座位的userId, 以便对玩家的金币做恢复处理 self.table.recordSeatUserId(idleSeatId, userId) result["seatId"] = idleSeatId result["reason"] = TYRoom.ENTER_ROOM_REASON_OK ftlog.hinfo('onSitOk >> |userId, tableId, seatId:', userId, self.tableId, idleSeatId, "|observers:", self.observers, caller=self)
def _tryStartNewTable(self, playerIds): # 开桌 ftlog.hinfo("_tryStartNewTable", self.baseLogStr(None, None), '|playerIds:', playerIds) if len(self.idleTableIds) == 0: ftlog.error(self.baseLogStr(None, None), 'idle tables not enough') return # 决定打几和庄家 params = {} params["bankerSeatIndex"] = -1 params["cardLevel"] = 2 for seatIndex, userId in enumerate(playerIds): if self.users[userId]["cardLevel"] > params["cardLevel"]: params["cardLevel"] = self.users[userId]["cardLevel"] if self.users[userId]["isWinner"] and \ (self.users[userId]["isToBeBanker"] or params["bankerSeatIndex"] == -1): params["bankerSeatIndex"] = seatIndex del self.users[userId] tableId = self.idleTableIds.pop() self.activeTableIds.add(tableId) shadowRoomId = tableId / 10000 self.room.sendTableManageGameStartReq(shadowRoomId, tableId, playerIds, params=params)
def doHeartBeat(self): '''定时循环调用,负责比赛状态转移''' FTTimer(1, self.doHeartBeat) if self.MTT_STATE_IDLE == self.state: return if self.MTT_STATE_READY == self.state: # self.matchPlugin.refreshMatchStartTime(self.bigRoomId) self.matchPlugin.prepareNewMatch(self) # 会改状态为 MTT_STATE_SIGNIN ftlog.hinfo("doHeartBeat >>", "|roomId, state, startTimeStamp:", self.roomId, self.getStateStr(), self.matchPlugin.match_room_confs[self.bigRoomId].get("start_timestamp", "closed"), caller=self) return # ftlog.debug("<<", "|roomId, state:", self.roomId, self.getStateStr()) startTimeStamp = self.matchPlugin.match_room_confs[self.bigRoomId]["start_timestamp"] nowTimeStamp = int(time.time()) if nowTimeStamp % 30 == 0: if ftlog.is_debug(): ftlog.info("doHeartBeat <<", "|roomId, state:", self.roomId, self.getStateStr(), "|nowTimeStamp, startTimeStamp:", nowTimeStamp, startTimeStamp, caller=self) if self.MTT_STATE_SIGNIN == self.state: if nowTimeStamp + self.matchPlugin.timedeltaEnterMatch >= startTimeStamp: self.state = self.MTT_STATE_ENTER self.matchPlugin.notifyPlayersToEnterMatch(self) ftlog.hinfo("doHeartBeat >>", "|roomId, state:", self.roomId, self.getStateStr(), caller=self) return if self.MTT_STATE_ENTER == self.state: if nowTimeStamp + self.matchPlugin.timedeltaForbidSignout >= startTimeStamp: self.state = self.MTT_STATE_FORBIT_SIGNOUT self.matchPlugin.notifyPlayersToEnterMatch(self) ftlog.hinfo("doHeartBeat >>", "|roomId, state:", self.roomId, self.getStateStr(), caller=self) return if self.MTT_STATE_FORBIT_SIGNOUT == self.state: if nowTimeStamp >= startTimeStamp: self.matchPlugin.checkStartMatch(self) ftlog.hinfo("doHeartBeat >>", "|roomId, state:", self.roomId, self.getStateStr(), caller=self) return
def doCheckCode(self, gameId, userId, clientId, promoteCode): ''' 确立推广关系,也就是领取红包 校验通过 设置推荐人 将用户加到推荐人的推广员名单里 ''' try: timestamp = pktimestamp.getCurrentTimestamp() status = neituiguang.loadStatus(userId, timestamp) # 检查是否能成为推荐人 # 转到promoteCode所在的UT进程中去处理 ec, info = neituiguang_remote.canBeInviter(promoteCode, userId) if ec != 0: raise NeituiguangException(ec, info) # 设置推荐人 neituiguang.setInviter(status, promoteCode) try: # 添加invitee,此处不需要处理失败的情况,前面已经检查了 ec, info = neituiguang_remote.addInvitee(promoteCode, userId, status.isBindMobile) if ec != 0: ftlog.warn('NeiTuiGuangTcpHandler.doCheckCode gameId=', gameId, 'userId=', userId, 'clientId=', clientId, 'promoteCode=', promoteCode, 'call=', 'neituiguang_remote.addInvitee', 'ec=', ec, 'info=', info) except: ftlog.error('NeiTuiGuangTcpHandler.doCheckCode gameId=', gameId, 'userId=', userId, 'clientId=', clientId, 'promoteCode=', promoteCode, 'call=', 'neituiguang_remote.addInvitee', 'ec=', ec, 'info=', info) ftlog.hinfo('neituiguang.statics eventId=', 'INPUT_PRMOTE_CODE', 'userId=', userId, 'clientId=', clientId, 'promoteCode=', promoteCode, 'result=', 'ok') mo = MsgPack() mo.setCmd('promote_info') mo.setResult('action', 'code_check') mo.setResult('code', 0) router.sendToUser(mo, userId) except Exception, e: if not isinstance(e, TYBizException): ftlog.error() ec, info = (e.errorCode, e.message) if isinstance(e, TYBizException) else (-1, '系统错误') ftlog.hinfo('neituiguang.statics eventId=', 'INPUT_PRMOTE_CODE', 'userId=', userId, 'clientId=', clientId, 'promoteCode=', promoteCode, 'result=', 'failed', 'ec=', ec, 'info=', info) router.sendToUser(self.makeErrorResponse('code_check', ec, info), userId)