def get_gamer_by_id(self, id_): gamer_index = self._GamerIdIndexMapping.get(id_, None) if gamer_index is None: logger.error('gamer.GamerGroup', f'No such a index mapping for gamer id {id_}') return None return self._Gamers[gamer_index]
def login_thread(self, socket_obj, con_addr): socket_obj.settimeout(None) # 先出于等待登录状态 while True: cmd, vals = recv_cmd(socket_obj, decode=True) if cmd == 'Login': try: user_name = vals['Username'] password = vals['Password'] passed, login_info = self.check_login(user_name, password) except KeyError: logger.error('server.login', 'Login指令中缺少 username 和 password 项!') continue send_cmd(socket_obj, command='Login', LoginStateCode=1 if passed else 0, LoginMessage=login_info, ID=id) if passed: logger.info('server.login', 'sending gamer info...') self.add_gamer(socket_obj, con_addr, user_name) # todo: 修改为Gamer实现 self.sendGamerInfo() return # 玩家主动或者被动放弃登录 elif cmd == 'ExitLogin': return
def handle_inform(engine: ClientEngine, signals: ClientSignal, **kwargs): try: # inform = extract_kwargs(kwargs, ('Content', 'content'), 'client.handlers.handle_inform') inform = parse_inform_command(kwargs) if inform is None: return engine.update_inform(inform) except Exception as e: logger.error('client.handlers.handle_inform', 'err: {}'.format(e))
def decode_length(length_header): try: length_header = json.loads(length_header.decode(CodingFormat)) except json.JSONDecodeError as e: logger.error( 'protocol.decode_length', '[decode_length] Fail to decode length header: {}'.format(e)) return 0 return int(length_header.get('len', 0))
def get_handler(state, cmd): logger.debug('client.handlers', 'getting handler of {}'.format(cmd)) try: handler = __handler_switch[state][cmd] return handler except KeyError: logger.error('client.handlers.get_handler', 'can not get handler for {}.{}'.format(state, cmd)) return handle_none except Exception as e: logger.error('client.handlers.get_handler', 'unknown err: {}'.format(e)) return handle_none
def game(self): while not self.Engine.GameEndFlag: try: cmd, vals = self.Engine.recv_cmd() logger.info('client.core.game', f'cmd: {cmd}, vals: {vals}') handler = get_handler(C_GAME_STATE, cmd) handler(self.Engine, self.Signals, **vals) logger.info('client.core.game', f'cmd: {cmd} executed') except BaseException as e: logger.error('client.core.game', 'err when game: {}'.format(e)) self.exit()
def get_handler(state, cmd, supress_log=False): logger.debug('server.handlers', 'getting handler of {}'.format(cmd)) try: handler = __handler_switch[state][cmd] return handler except KeyError: if not supress_log: logger.warning( 'server.handlers.get_handler', 'can not get handler for {c} in {s}'.format(c=cmd, s=state)) return handle_none except Exception as e: if not supress_log: logger.error('server.handlers.get_handler', 'unknown err: {}'.format(e)) return handle_none
def game_state(self): logger.debug('server.gamer_state', 'entering game state') # 初始化游戏逻辑 self.GameLogic = GameLogic(len(self.Gamers)) for round_index in range(self.GameRoundPerGamer): # 游戏循环次数等于玩家数量 for cur_gamer_index in range(len(self.Gamers)): cur_gamer = self.Gamers[cur_gamer_index] self.GameLogic.init_game_state(cur_gamer.Id) self.send_all_cmd(**make_newround_command()) # 将当前出题者加入到已回答玩家列表中,防止其自己猜自己 self.GameLogic.add_answered_gamer_id(cur_gamer.Id) # 发送开始画图和通告画图者的通知 paint_message = self.ServerMessage.make_paint_inform_message( cur_gamer.UserName) self.send_all_cmd(**make_inform_command(paint_message)) # 当前画图者发出开始画图指令 cur_gamer.send_cmd(**make_begin_paint_command()) # 进入指令处理循环 self.MessageLoopFlag = True while self.MessageLoopFlag: msg = self.CmdQueue.get() # 阻塞队列,处理接受到的命令 try: cmd, cmd_body = decode_msg(msg, raise_exception=True) handler = get_handler(S_GAME_STATE, cmd) handler(self, cur_gamer=cur_gamer, raw_message=msg, **cmd_body) except DecodeError as de: logger.error( 'server.game_state', f'decoding error in game message loop: {de}') except Exception as e: she = ServerHandlingError(cmd, cmd_body, e) logger.error( 'server.game_state', f'unknown error when handling in game state: {she}' ) # 关闭游戏 self.close()
def wait_for_ready(self): while True: try: cmd, vals = self.Engine.recv_cmd() logger.debug('client.core.wait_for_ready', 'recv cmd: {}, {}'.format(cmd, vals)) handler = get_handler(C_WAIT_FOR_READY_STATE, cmd) ret = handler(self.Engine, self.Signals, **vals) if ret is not None and check_game_is_begin(ret): break except Exception as e: logger.error( 'client.core.activate', 'err when handling, cmd: {}, vals: {}, err: {}'.format( cmd, vals, e)) self.game()
def decode_msg(raw_msg_body, raise_exception=False) -> (str, dict): try: msg_body = json.loads(raw_msg_body) command = msg_body.pop('command') return command, msg_body except json.JSONDecodeError as e: if raise_exception: raise DecodeError(raw_msg_body, str(e)) logger.error('protocol.decode_msg', 'Fail to decode msg body: {}'.format(e)) return 'unknown', {} except Exception as ue: if raise_exception: raise DecodeError(raw_msg_body, str(ue)) logger.error('protocol.decode_msg', 'unknown err: {}, raw_msg: {}'.format(ue, msg_body)) return 'unknown', {}
def login(self): try: usrName, password = self.getUsrAndPsw() logger.info('LoginPanel.login', 'username: {}, psw: {}'.format(usrName, password)) self.send_cmd(**make_login_command(usrName, password)) # self.send_cmd(command='Login', Username=usrName, Password=password) # 收取服务器的回复 while True: cmd, body = self.recv_cmd() if cmd == CMD_LOGIN_RESULT: break else: logger.warning( 'LoginPanel.login', 'recv {} cmd with {}, skip'.format(cmd, body)) time.sleep(1) logger.info('LoginPanel.login', 'login success: {}'.format(body)) # login_status_code = body['LoginStateCode'] # login_info = body['LoginMessage'] login_status_code, login_info, ID = parse_login_result_command( body) self.ClientId = ID if login_status_code == 1: self.close() logger.info('LoginPanel.login', 'activating...') self.Activator(self.Socket, self.ClientId, self.UsrName.text()) else: widgets.QMessageBox.warning(self, '登陆失败', login_info) # self.UsrName.clear() self.Psw.clear() except Exception as e: logger.error('LoginPanel.login', 'Fail to login, err: {}'.format(e)) raise e
def handle_begin_paint(engine: ClientEngine, signals: ClientSignal, **kwargs): try: engine.Panel.set_painting(True) engine.Panel.State = 'painting' logger.info('client.handlers.handle_begin_paint', 'getting answer and hint') answer = engine.Panel.get_input_by_dialog('出题', '请输入谜底', '谜底不能为空', True, lambda s: len(s) <= 20, '谜底长度不能超过20个字符') hint = engine.Panel.get_input_by_dialog('出题', '请输入提示', '', False, lambda s: len(s) <= 20, '提示长度不能超过20个字符') logger.info('client.handlers.handle_begin_paint', '谜题: {}, 提示: {}'.format(answer, hint)) # engine.send_cmd(command=CMD_BEGIN_PAINT, answer=answer, hint=hint) engine.send_cmd(**make_make_puzzle_command(answer, hint)) # 只有要画图的人才能看到设置面板 engine.Panel.PaintPanel.set_setting_visible(True) except BaseException as e: logger.error('client.handlers.handle_begin_paint', 'err: {}'.format(e))
def check_gamer_is_enough(self): gl = len(self._Gamers) if gl > self.MaxGamer: logger.error('gamer.check_gamer_is_enough', f'number of gamers is {gl}, greater than max gamer {self.MaxGamer}') return gl >= self.MaxGamer