def doSit(self, msg, userId, seatId, clientId): ''' 桌子同步安全操作方法 玩家操作, 尝试再当前的某个座位上坐下 若 seatId为0, 那么需要桌子自动未玩家挑选一个座位 通常此方法由客户端发送quick_start进行快速开始触发: AppClient->ConnServer->UtilServer->RoomServer->ThisTableServer 或: AppClient->ConnServer->RoomServer->ThisTableServer 若 seatId为有效的座位号, 那么桌子需要保证玩家能够正常的坐下 通常此方法由客户端发送quick_start进行断线重连触发: AppClient->ConnServer->ThisTableServer 实例桌子可以覆盖 _doSit 方法来进行自己的业务逻辑处理 无论sit是否成功,都需要调用room.updateTableScore ''' if ftlog.is_debug(): ftlog.debug("<< |params:", userId, seatId, clientId, msg, caller=self) try: return self._doSit(msg, userId, seatId, clientId) except: ftlog.exception() return { "isOK": False, "reason": TYRoom.ENTER_ROOM_REASON_INNER_ERROR } finally: self.room.updateTableScore(self.getTableScore(), self.tableId, force=True)
def getIpLocation(ipstr): try: global _IPLocAll if _IPLocAll is None: _IPLocAll = IPLoc('ip_locality_all.txt') return _IPLocAll.find(ipstr) except: ftlog.exception('find iploc->' + str(ipstr)) return None
def isFilterUser(userId): try: global _filterUsers if _filterUsers is None: _filterUsers = FilterUser('filter_user_list.txt') if _filterUsers.find(userId): return 1 return 0 except: ftlog.exception('find users->' + userId) return 1 #满足条件,可以继续玩的玩家
def isBjSzIp(ipstr): try: global _IPLocBjSz if _IPLocBjSz is None: _IPLocBjSz = IPLocKeyArea('ip_locality_all.txt') if _IPLocBjSz.find(ipstr): return 1 return 0 except: ftlog.exception('find iploc->' + str(ipstr)) return 1 # 如果异常我们认为是北京的IP
def doTableManage(self, msg, action): ''' 桌子同步安全操作方法 桌子内部处理所有的table_manage命令 实例桌子可以覆盖 _doTableManage 方法来进行自己的业务逻辑处理 ''' if ftlog.is_debug(): ftlog.debug("<< |params:", action, msg, caller=self) try: return self._doTableManage(msg, action) except: ftlog.exception() return {"isOK":False, "reason":TYRoom.ENTER_ROOM_REASON_INNER_ERROR}
def loadHistory(cls, gameId, userId, matchId): try: # jstr = gamedata.getGameAttr(userId, gameId, cls.__buildField(matchId,"histories")) jstr = "" if ftlog.is_debug(): ftlog.debug('MatchRecord.loadRecord gameId=', gameId, 'userId=', userId, 'matchId=', matchId, 'data=', jstr, caller=cls) if jstr: return json.loads(jstr) else: return [] except: ftlog.exception() return None
def loadRecord(cls, gameId, userId, matchId, mixId=None): try: # jstr = gamedata.getGameAttr(userId, gameId, cls.__buildField(matchId, mixId)) # TODO histories # pluginCross.halldata.getUpdateToVersion511flag(userId) jstr ="" if ftlog.is_debug(): ftlog.debug('MatchRecord.loadRecord gameId=', gameId, 'userId=', userId, 'matchId=', matchId, 'data=', jstr, caller=cls) if jstr: return MatchRecordDaoRedis.Record.fromDict(json.loads(jstr)) except: ftlog.exception() return None
def event(cls, msg, gameId): """ 发布事件 """ if gameId not in cls.map_events: return msg # cls.map_events = { # 8: {"EV_PLAYER_GAME_FRAME_END": [("Winner", onEvPlayerGameFrameEnd), ("Shark",onEvPlayerGameFrameEnd)]}, # 30: {} # } cmd = msg.getCmd() action = msg.getParam('action') ev = (cmd, action) if action else cmd receiver_plugins = msg.getKey('receiver_plugins') or [] for plugin_name, handler in cls.map_events[gameId].get(ev, []): if receiver_plugins and plugin_name not in receiver_plugins: continue if _DEBUG: debug( 'TYPluginCenter.event| run handler <<|gameId, ev, plugin:', gameId, ev, plugin_name) try: if handler(gameId, msg) == cls.EV_CHAIN_STOP: if _DEBUG: debug( 'TYPluginCenter.event| chain break |gameId, ev, plugin:', gameId, ev, plugin_name) return msg except: ftlog.exception() if _DEBUG: debug( 'TYPluginCenter.event| run handler >>|gameId, ev, plugin:', gameId, ev, plugin_name) return msg
def safetyCall(*args, **kwargs): try: return method(*args, **kwargs) except: ftlog.exception()
def reload(cls, gameId, handler_name='', handler_names=[], handlers_config=None): ''' reload 某个 gameId 的插件 @handlers_names: 指定要reload哪些plugin。不指定就reload所有(plugins越来越多,会比较慢) 不管有没有指定 reload 哪些插件,都会重新 build 事件表。 为什么不优化为只处理指定的plugins的事件? 没有必要,性能瓶颈不在这,而且全部重新build一定不会出问题,而且的而且,那样做会增加复杂性。 ''' if not cls.needLoadPlugin(): ftlog.info('reload >> |this type of server not need load plugin', '|serverId, gameId:', tyglobal.serverId(), gameId, caller=cls) return if cls.isOtherGameServer(gameId): ftlog.info('reload >> |', 'do not reload in other game GR/GT', '|serverId, gameId:', tyglobal.serverId(), gameId, caller=cls) return if not handlers_config: handlers_config = tyconfig.getCacheGame0Data( gameId, 'plugins', None, None, {}) if not handlers_config: return # handlers_config = dict([(hc['name'], hc) for hc in handlers_config]) handlers_config_dict = dict([(hc['name'], hc) for hc in handlers_config['handlers']]) ftlog.info('<< |', cls.plugins, handlers_config, caller=cls) if handler_name: handler_names = [handler_name] handlers_config_list = [] # to be reload cls.map_events[gameId] = {} # 事件表 if handler_names: for handler_name in handler_names: if handler_name in handlers_config_dict: handlers_config_list.append( handlers_config_dict.get(handler_name)) if handler_name in cls.plugins[gameId]: del cls.plugins[gameId][handler_name] else: handlers_config_list = handlers_config['handlers'] cls.plugins[gameId] = {} # plugins 表 # 先 reload modules plugins = cls.plugins[gameId] reloadPlugins = [] for cfg in handlers_config_list: try: plugin = TYPlugin(gameId, cfg) if plugin.handlers: plugins[cfg['name']] = plugin reloadPlugins.append(plugin) except Exception as e: ftlog.exception(e) cls.buildEventMap(gameId, plugins, handlers_config, cls.map_events[gameId]) ftlog.info("TYPluginCenter.reload | " "reloadPlugins:", [plugin.name for plugin in reloadPlugins]) # onReload 时可能会有阻塞操作而让出CPU, 这时有可能会产生新的事件 # 如果在 onReload 后才 buildEventMap,则这个事件会丢(因为eventMap在build之前是空的) # 所以,把 onReload 移到 build Event Map 之后 for plugin in reloadPlugins: try: plugin.onReload() except Exception as e: ftlog.exception(e)