def setup_match(self, operator, name, gametype, *players): from thb import modes gid = self.new_gid() gamecls = modes[gametype] if len(players) != gamecls.n_persons: operator.write(['system_msg', [None, u'参赛人数不正确']]) return manager = GameManager(gid, gamecls, name, False) pl = [] for i in players: try: uid = int(i) except: uid = 100000 pl.append(uid if uid < 100000 else i) manager.set_match(pl) self.games[gid] = manager log.info("Create game") @gevent.spawn def pull(): while gid in self.games: users = self.users.values() for u in users: if not (u.account.userid in pl or u.account.username in pl): continue already_in = GameManager.get_by_user(u) is manager if u.state == 'hang': self.join_game(u, gid) elif u.state in ('observing', 'ready', 'inroomwait') and not already_in: self.exit_game(u) gevent.sleep(1) self.join_game(u, gid) elif u.state == 'ingame' and not already_in: gevent.spawn( u.write, ['system_msg', [None, u'你有比赛房间,请尽快结束游戏参与比赛']]) gevent.sleep(30) self.refresh_status() return manager
def handle_admin_cmd(self, user, cmd): args = map(unicode, shlex.split(cmd.encode('utf-8'))) cmd = args[0] args = args[1:] if cmd == 'stacktrace': manager = GameManager.get_by_user(user) manager.record_stacktrace() elif cmd == 'clearzombies': self.clearzombies() elif cmd == 'ping': self.ping(user) elif cmd == 'start_migration': self.start_migration() elif cmd == 'kick': uid, = args self.force_disconnect(int(uid)) elif cmd == 'match': self.setup_match(user, *args) elif cmd == 'kill_game': gid, = args manager = self.games.get(int(gid)) manager and self.force_end_game(manager) elif cmd == 'add_admin': uid, = args self.admins.append(int(uid)) elif cmd == 'remove_admin': uid, = args self.admins.remove(int(uid)) elif cmd == 'bigbrother': self.bigbrothers.append(user.account.userid) elif cmd == 'nobigbrother': try: self.bigbrothers.remove(user.account.userid) except Exception: pass elif cmd == 'give_item': from server.item import backpack uid, sku = args backpack.add(int(uid), sku) elif cmd == 'mute': manager = GameManager.get_by_user(user) if manager: manager.muted = not manager.muted else: return user.write(['system_msg', [None, u'成功的执行了管理命令']])
def ping(self, user): manager = GameManager.get_by_user(user) if manager: clients = manager.get_online_users() else: clients = self.users.values() def ping(p): chan = p.listen_command('pong') b4 = time.time() p.write(['ping', None]) try: chan.get(timeout=5) t = time.time() - b4 t *= 1000 user.write([ 'system_msg', [None, u'%s %fms' % (p.account.username, t)] ]) except QueueEmpty: user.write( ['system_msg', [None, u'%s 超时' % p.account.username]]) for p in clients: gevent.spawn(ping, p)
def worker(): with Timeout(20, False): rst = None other.write(['observe_request', [user.account.userid, user.account.username]]) chan = other.listen_command('observe_grant') while True: rst = chan.get() if rst is None: return try: ob_id, grant = rst except: continue if ob_id != user.account.userid: continue break if not (rst and user.state == 'hang' and other.state in ('ingame', 'inroomwait', 'ready')): return if grant: if other.state not in ('ingame', 'inroomwait', 'ready'): user.write(['message_err', 'user_not_ingame']) else: manager = GameManager.get_by_user(other) manager.observe_user(user, other) self.refresh_status() else: user.write(['observe_refused', other.account.username])
def worker(): if msg.startswith('!!') and (options.freeplay or acc.userid in self.admins): self.handle_admin_cmd(user, msg[2:]) return manager = GameManager.get_by_user(user) if manager.muted: user.write(['system_msg', [None, u'当前房间被管理员禁言']]) return packed = (acc.username, msg) if user.state == 'hang': # lobby chat log.info(u'(Lobby): %s' % msg) for u in self.users.values(): if u.state == 'hang': u.write(['chat_msg', packed]) elif user.state in ('inroomwait', 'ready', 'ingame', 'observing'): # room chat log.info(u'(%s): %s' % (user.current_game.gameid, msg)) ul = manager.users obl = BatchList() map(obl.__iadd__, ul.observers) _type = 'ob_msg' if user.state == 'observing' else 'chat_msg' ul.write([_type, packed]) # should be here? obl.write([_type, packed])
def user_join(self, user): uid = user.account.userid user.state = 'hang' user.observing = None log.info(u'User %s joined, online user %d' % (user.account.username, len(self.users))) if uid in self.users: # squeeze the original one out log.info('%s has been squeezed out' % user.account.username) old = self.users[uid] user.account = old.account old.close() # this forces a drop, will call exit_game manager = GameManager.get_by_user(old) manager and manager.squeeze_out(old, user) if uid in self.dropped_users: log.info(u'%s rejoining dropped game' % user.account.username) old = self.dropped_users.pop(uid) assert isinstance(old, DroppedClient), 'Arghhhhh' @gevent.spawn def reconnect(): self.send_account_info(user) manager = GameManager.get_by_user(old) manager.reconnect(user) self.users[uid] = user self.refresh_status() return True
def set_game_param(self, user, key, value): if user.state != 'inroomwait': return manager = GameManager.get_by_user(user) manager.set_game_param(user, key, value) self.refresh_status()
def change_location(self, user, loc): manager = GameManager.get_by_user(user) if user.state == 'inroomwait': manager.change_location(user, loc) self.refresh_status() elif user.state == 'observing': self.join_game(user, manager.gameid, loc)
def kick_observer(self, user, uid): other = self.users.get(uid) if not other: return manager = GameManager.get_by_user(user) if manager.kick_observer(user, other): self.exit_game(other)
def invite_user(self, user, other_userid): if user.account.userid < 0: gevent.spawn(user.write, ['system_msg', [None, u'毛玉不能使用邀请功能']]) return other = self.users.get(other_userid, None) if not (other and other.state in ('hang', 'observing')): user.write(['message_err', 'no_such_user']) return manager = GameManager.get_by_user(user) manager.add_invited(other) @gevent.spawn def worker(): with Timeout(20, False): other.write(['invite_request', [ user.account.userid, user.account.username, manager.gameid, manager.gamecls.__name__, ]]) rst = None chan = other.listen_command('invite_grant') gid = grant = 0 while True: rst = chan.get() if rst is None: return try: gid, grant = rst except: continue if gid != manager.gameid: continue break if not (grant and gid in self.games and not manager.game_started and other.state != 'ingame'): # granted, game not cancelled or started return if manager.next_free_slot() is None: # no free space return if other.state in ('inroomwait', 'ready') and other.current_game is manager: # same game return self.join_game(other, gid) worker.gr_name = 'Invite:[%r] -> [%r]' % (user, other)
def setup_match(self, operator, name, gametype, *players): from thb import modes gid = self.new_gid() gamecls = modes[gametype] if len(players) != gamecls.n_persons: operator.write(['system_msg', [None, u'参赛人数不正确']]) return manager = GameManager(gid, gamecls, name, False) pl = [] for i in players: try: uid = int(i) except: uid = 100000 pl.append(uid if uid < 100000 else i) manager.set_match(pl) self.games[gid] = manager log.info("Create game") @gevent.spawn def pull(): while gid in self.games: users = self.users.values() for u in users: if not (u.account.userid in pl or u.account.username in pl): continue already_in = GameManager.get_by_user(u) is manager if u.state == 'hang': self.join_game(u, gid) elif u.state in ('observing', 'ready', 'inroomwait') and not already_in: self.exit_game(u) gevent.sleep(1) self.join_game(u, gid) elif u.state == 'ingame' and not already_in: gevent.spawn(u.write, ['system_msg', [None, u'你有比赛房间,请尽快结束游戏参与比赛']]) gevent.sleep(30) self.refresh_status() return manager
def _run(g): g.synctag = 0 g.event_observer = ServerEventHooks() g.game = getcurrent() mgr = GameManager.get_by_game(g) Subsystem.lobby.start_game(mgr) try: g.process_action(g.bootstrap(mgr.game_params, mgr.consumed_game_items)) except GameEnded: pass finally: Subsystem.lobby.end_game(mgr) assert g.ended stats(*g.get_stats())
def exit_game(self, user, is_drop=False): manager = GameManager.get_by_user(user) if user.state == 'observing': manager.observe_leave(user) elif user.state != 'hang': dummy = manager.exit_game(user, is_drop) if is_drop and user.state == 'ingame': self.dropped_users[user.account.userid] = dummy user.state = 'hang' self.clear_observers(user) self.try_remove_empty_game(manager) self.refresh_status() else: user.write(['message_err', 'not_in_a_game'])
def _run(g): g.synctag = 0 g.event_observer = ServerEventHooks() g.game = getcurrent() mgr = GameManager.get_by_game(g) Subsystem.lobby.start_game(mgr) try: g.process_action( g.bootstrap(mgr.game_params, mgr.consumed_game_items)) except GameEnded: pass finally: Subsystem.lobby.end_game(mgr) assert g.ended stats(*g.get_stats())
def pull(): while gid in self.games: users = self.users.values() for u in users: if not (u.account.userid in pl or u.account.username in pl): continue already_in = GameManager.get_by_user(u) is manager if u.state == 'hang': self.join_game(u, gid) elif u.state in ('observing', 'ready', 'inroomwait') and not already_in: self.exit_game(u) gevent.sleep(1) self.join_game(u, gid) elif u.state == 'ingame' and not already_in: gevent.spawn(u.write, ['system_msg', [None, u'你有比赛房间,请尽快结束游戏参与比赛']]) gevent.sleep(30)
def create_game(self, user, gametype, name, invite_only): from thb import modes, modes_maoyu if user and user.account.is_maoyu() and gametype not in modes_maoyu: user.write(['message_err', 'maoyu_limitation']) return if gametype not in modes: user.write(['message_err', 'gametype_not_exist']) return gid = self.new_gid() gamecls = modes[gametype] manager = GameManager(gid, gamecls, name, invite_only) self.games[gid] = manager log.info("Create game") self.refresh_status() return manager
def ping(self, user): manager = GameManager.get_by_user(user) if manager: clients = manager.get_online_users() else: clients = self.users.values() def ping(p): chan = p.listen_command('pong') b4 = time.time() p.write(['ping', None]) try: chan.get(timeout=5) t = time.time() - b4 t *= 1000 user.write(['system_msg', [None, u'%s %fms' % (p.account.username, t)]]) except QueueEmpty: user.write(['system_msg', [None, u'%s 超时' % p.account.username]]) for p in clients: gevent.spawn(ping, p)
def reconnect(): self.send_account_info(user) manager = GameManager.get_by_user(old) manager.reconnect(user)
def observe_user(self, user, other_userid): other = self.users.get(other_userid, None) if not other: user.write(['message_err', 'no_such_user']) return if other.state == 'observing': other = other.observing if other.state not in ('ingame', 'inroomwait', 'ready'): user.write(['message_err', 'user_not_ingame']) return if user.account.userid in self.bigbrothers: gevent.spawn(other.write, ['system_msg', [None, u'管理员对你使用了强制观战,效果拔群。' u'强制观战功能仅用来处理纠纷,如果涉及滥用,请向 Proton 投诉。' ]]) manager = GameManager.get_by_user(other) manager.observe_user(user, other) self.refresh_status() return @gevent.spawn def worker(): with Timeout(20, False): rst = None other.write(['observe_request', [user.account.userid, user.account.username]]) chan = other.listen_command('observe_grant') while True: rst = chan.get() if rst is None: return try: ob_id, grant = rst except: continue if ob_id != user.account.userid: continue break if not (rst and user.state == 'hang' and other.state in ('ingame', 'inroomwait', 'ready')): return if grant: if other.state not in ('ingame', 'inroomwait', 'ready'): user.write(['message_err', 'user_not_ingame']) else: manager = GameManager.get_by_user(other) manager.observe_user(user, other) self.refresh_status() else: user.write(['observe_refused', other.account.username]) worker.gr_name = 'OB:[%r] -> [%r]' % (user, other)
def cancel_ready(self, user): manager = GameManager.get_by_user(user) manager.cancel_ready(user) self.refresh_status()
def use_item(self, user, item): if user.state != 'inroomwait': return manager = GameManager.get_by_user(user) manager.use_item(user, item)
def observe_user(self, user, other_userid): other = self.users.get(other_userid, None) if not other: user.write(['message_err', 'no_such_user']) return if other.state == 'observing': other = other.observing if other.state not in ('ingame', 'inroomwait', 'ready'): user.write(['message_err', 'user_not_ingame']) return if user.account.userid in self.bigbrothers: gevent.spawn(other.write, [ 'system_msg', [ None, u'管理员对你使用了强制观战,效果拔群。' u'强制观战功能仅用来处理纠纷,如果涉及滥用,请向 Proton 投诉。' ] ]) manager = GameManager.get_by_user(other) manager.observe_user(user, other) self.refresh_status() return @gevent.spawn def worker(): with Timeout(20, False): rst = None other.write([ 'observe_request', [user.account.userid, user.account.username] ]) chan = other.listen_command('observe_grant') while True: rst = chan.get() if rst is None: return try: ob_id, grant = rst except: continue if ob_id != user.account.userid: continue break if not (rst and user.state == 'hang' and other.state in ('ingame', 'inroomwait', 'ready')): return if grant: if other.state not in ('ingame', 'inroomwait', 'ready'): user.write(['message_err', 'user_not_ingame']) else: manager = GameManager.get_by_user(other) manager.observe_user(user, other) self.refresh_status() else: user.write(['observe_refused', other.account.username]) worker.gr_name = 'OB:[%r] -> [%r]' % (user, other)
def _record_user_gamedata(client, tag, data): from server.core.game_manager import GameManager manager = GameManager.get_by_user(client) manager.record_user_gamedata(client, tag, data)