def waiter(p): try: tle = TimeLimitExceeded(timeout+10) tle.start() data = p.client.gexpect(tagstr) wait_queue.put((p, data)) except (TimeLimitExceeded, EndpointDied) as e: if isinstance(e, TimeLimitExceeded) and e is not tle: raise wait_queue.put((p, None)) finally: tle.cancel()
def user_input(self, tag, attachment=None, timeout=15, g=None, st=None): g = g if g else Game.getgame() st = st if st else g.get_synctag() input = DataHolder() input.tag = tag input.input = None input.attachment = attachment input.timeout = timeout input.player = self class Break(Exception): pass cur_greenlet = gevent.getcurrent() def waiter_func(): rst = Executive.server.gexpect('input_%s_%d' % (tag, st)) cur_greenlet.kill(Break(), block=False) return rst try: tle = TimeLimitExceeded(timeout+1) tle.start() waiter = gevent.spawn(waiter_func) g.emit_event('user_input_start', input) gevent.sleep(0) rst = g.emit_event('user_input', input) Executive.server.gwrite('input_%s_%d' % (tag, st), rst.input) except (Break, TimeLimitExceeded) as e: if isinstance(e, TimeLimitExceeded) and e is not tle: raise g.emit_event('user_input_timeout', input) rst = input except: waiter.kill() raise finally: tle.cancel() g.emit_event('user_input_finish', input) try: waiter.join() gevent.sleep(0) except Break: pass rst.input = waiter.get() g.emit_event('user_input_finish', input) return rst.input
def user_input(self, tag, attachment=None, timeout=15, g=None, st=None): g = g if g else Game.getgame() st = st if st else g.get_synctag() try: # The ultimate timeout with TimeLimitExceeded(timeout + 10): input = self.client.gexpect('input_%s_%d' % (tag, st)) except (TimeLimitExceeded, EndpointDied): # Player hit the red line, he's DEAD. #import gamehall as hall #hall.exit_game(self.client) input = None pl = PlayerList(g.players[:]) pl.client.gwrite('input_%s_%d' % (tag, st), input) # tell other players return input
def waiter(p): try: tle = TimeLimitExceeded(timeout + 10) tle.start() data = p.client.gexpect(tagstr) wait_queue.put((p, data)) except (TimeLimitExceeded, EndpointDied) as e: if isinstance(e, TimeLimitExceeded) and e is not tle: raise wait_queue.put((p, None)) finally: tle.cancel()
def user_input(self, tag, attachment=None, timeout=15, g=None, st=None): g = g if g else Game.getgame() st = st if st else g.get_synctag() input = DataHolder() input.tag = tag input.input = None input.attachment = attachment input.timeout = timeout input.player = self class Break(Exception): pass cur_greenlet = gevent.getcurrent() def waiter_func(): rst = Executive.server.gexpect('input_%s_%d' % (tag, st)) cur_greenlet.kill(Break(), block=False) return rst try: tle = TimeLimitExceeded(timeout + 1) tle.start() waiter = gevent.spawn(waiter_func) g.emit_event('user_input_start', input) gevent.sleep(0) rst = g.emit_event('user_input', input) Executive.server.gwrite('input_%s_%d' % (tag, st), rst.input) except (Break, TimeLimitExceeded) as e: if isinstance(e, TimeLimitExceeded) and e is not tle: raise g.emit_event('user_input_timeout', input) rst = input except: waiter.kill() raise finally: tle.cancel() g.emit_event('user_input_finish', input) try: waiter.join() gevent.sleep(0) except Break: pass rst.input = waiter.get() g.emit_event('user_input_finish', input) return rst.input
def input_func(st): my = ilets[g.me] with TimeLimitExceeded(timeout + 1, False): _, my = g.emit_event('user_input', (trans, my)) g.me.server.gwrite(tag + str(st), my.data())
def user_input_any(self, tag, expects, attachment=None, timeout=15): g = Game.getgame() st = g.get_synctag() tagstr = 'inputany_%s_%d' % (tag, st) g.emit_event('user_input_any_begin', (self, tag, attachment)) input = DataHolder() input.tag = tag input.input = None input.attachment = attachment input.timeout = timeout input.player = g.me class Break(Exception): pass # ('Input: you are too late!') def waiter_func(): pid, data = Executive.server.gexpect(tagstr + '_resp') g.kill(Break(), block=False) return pid, data if isinstance(g.me, TheChosenOne) and g.me in self: try: waiter = gevent.spawn(waiter_func) tle = TimeLimitExceeded(timeout) tle.start() g.emit_event('user_input_start', input) rst = g.emit_event('user_input', input) Executive.server.gwrite(tagstr, rst.input) except (Break, TimeLimitExceeded) as e: if isinstance(e, TimeLimitExceeded) and e is not tle: raise g.emit_event('user_input_timeout', input) rst = input rst.input = None Executive.server.gwrite(tagstr, rst.input) except: waiter.kill() raise finally: tle.cancel() g.emit_event('user_input_finish', input) try: waiter.join() gevent.sleep(0) except Break: pass else: # none of my business, just wait for the result try: waiter = gevent.spawn(waiter_func) waiter.join() gevent.sleep(0) except Break: pass pid, data = waiter.get() g.emit_event('user_input_any_end', tag) if pid is None: return None, None p = g.player_fromid(pid) if not expects(p, data): raise GameError('WTF?! Server cheats!') return p, data
def user_input(players, inputlet, timeout=25, type='single', trans=None): ''' Type can be 'single', 'all' or 'any' ''' assert type in ('single', 'all', 'any') assert not type == 'single' or len(players) == 1 timeout = max(0, timeout) g = Game.getgame() inputlet.timeout = timeout players = players[:] if not trans: with InputTransaction(inputlet.tag(), players) as trans: return user_input(players, inputlet, timeout, type, trans) t = {'single': '', 'all': '&', 'any': '|'}[type] tag = 'I{0}:{1}:'.format(t, inputlet.tag()) ilets = {p: copy(inputlet) for p in players} for p in players: ilets[p].actor = p results = {p: None for p in players} synctags = {p: g.get_synctag() for p in players} orig_players = players[:] input_group = GreenletGroup() g.gr_groups.add(input_group) _input_group = set() till = time.time() + timeout + 5 try: inputany_player = None def get_input_waiter(p, t): try: # should be [tag, <Data for Inputlet.parse>] # tag likes 'I?:ChooseOption:2345' tag, rst = p.client.gexpect(t) return rst except EndpointDied: return None for p in players: t = tag + str(synctags[p]) w = input_group.spawn(get_input_waiter, p, t) _input_group.add(w) w.player = p w.gr_name = 'get_input_waiter: p=%r, tag=%s' % (p, t) for p in players: g.emit_event('user_input_start', (trans, ilets[p])) while players: # NOTICE: This is a must. # TLE would be raised at other part (notably my.post_process) in the original solution # (wrapping large parts of code in 'with TimeLimitExceeded(): ...') with TimeLimitExceeded(max(till - time.time(), 0)): w = waitany(_input_group) _input_group.discard(w) try: rst = w.get() p, data = w.player, rst except: p, data = w.player, None g.players.client.gwrite('R{}{}'.format(tag, synctags[p]), data) my = ilets[p] try: rst = my.parse(data) except: log.error('user_input: exception in .process()', exc_info=1) # ----- FOR DEBUG ----- if g.IS_DEBUG: raise # ----- END FOR DEBUG ----- rst = None rst = my.post_process(p, rst) g.emit_event('user_input_finish', (trans, my, rst)) players.remove(p) results[p] = rst if type == 'any' and rst is not None: inputany_player = p break except TimeLimitExceeded: pass finally: input_group.kill() # timed-out players for p in players: my = ilets[p] rst = my.parse(None) rst = my.post_process(p, rst) results[p] = rst g.emit_event('user_input_finish', (trans, my, rst)) g.players.client.gwrite('R{}{}'.format(tag, synctags[p]), None) if type == 'single': return results[orig_players[0]] elif type == 'any': if not inputany_player: return None, None return inputany_player, results[inputany_player] elif type == 'all': return OrderedDict([(p, results[p]) for p in orig_players]) assert False, 'WTF?!'