Esempio n. 1
0
    def worker():
        if msg.startswith('!!') and (options.freeplay
                                     or user.account.userid in (2, )):
            # admin commands
            cmd = msg[2:]
            if cmd == 'stacktrace':
                admin_stacktrace(user.current_game)
                return
            elif cmd == 'clearzombies':
                admin_clearzombies()
                return
            elif cmd == 'ping':
                admin_ping(user)
                return

        packed = (user.account.username, msg)
        if user.state == 'hang':  # hall chat
            for u in users.values():
                if u.state == 'hang':
                    u.write(['chat_msg', packed])

        elif user.state in ('inroomwait', 'ready', 'ingame',
                            'observing'):  # room chat
            ul = user.current_game.players.client
            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])
Esempio n. 2
0
        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])
Esempio n. 3
0
    def __init__(self, gid, gamecls, name, invite_only):
        g = gamecls()

        self.game = g
        self.users = BatchList([ClientPlaceHolder] * g.n_persons)
        self.game_started = False
        self.game_name = name
        self.banlist = defaultdict(set)
        self.ob_banlist = defaultdict(set)
        self.gameid = gid
        self.gamecls = gamecls
        self.game_items = defaultdict(set)  # userid -> {'item:meh', ...}
        self.game_params = {k: v[0] for k, v in gamecls.params_def.items()}
        self.is_match = False
        self.match_users = []
        self.invite_only = invite_only
        self.invite_list = set()
        self.muted = False

        g.gameid = gid
        g._manager = self
        g.rndseed = random.getrandbits(63)
        g.random = random.Random(g.rndseed)
        g.players = BatchList()
        g.gr_groups = WeakSet()
Esempio n. 4
0
        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])
Esempio n. 5
0
    def worker():
        if msg.startswith('!!') and (options.freeplay or user.account.userid in (2,)):
            # admin commands
            cmd = msg[2:]
            if cmd == 'stacktrace':
                admin_stacktrace(user.current_game)
                return
            elif cmd == 'clearzombies':
                admin_clearzombies()
                return
            elif cmd == 'ping':
                admin_ping(user)
                return

        packed = (user.account.username, msg)
        if user.state == 'hang':  # hall chat
            for u in users.values():
                if u.state == 'hang':
                    u.write(['chat_msg', packed])

        elif user.state in ('inroomwait', 'ready', 'ingame', 'observing'):  # room chat
            ul = user.current_game.players.client
            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])
Esempio n. 6
0
 def __init__(self, sock, addr):
     Endpoint.__init__(self, sock, addr)
     Greenlet.__init__(self)
     self.observers = BatchList()
     self.gamedata = Gamedata()
     self.cmd_listeners = defaultdict(WeakSet)
     self.current_game = None
Esempio n. 7
0
 def __init__(self, sock, addr):
     Endpoint.__init__(self, sock, addr)
     Greenlet.__init__(self)
     self.observers = BatchList()
     self.init_gamedata_mixin()
     self.gdhistory = []
     self.usergdhistory = []
Esempio n. 8
0
    def testChooseOptionInputlet(self):
        from game import autoenv
        from game.autoenv import user_input
        from client.core import TheChosenOne, PeerPlayer

        from thb.thb3v3 import THBattle
        from thb.inputlets import ChooseOptionInputlet
        from utils import BatchList

        autoenv.init('Server')
        g = THBattle()
        g.IS_DEBUG = True
        pl = [create_mock_player([]) for i in xrange(6)]
        p = pl[0]
        g.me = p
        p.client.gdlist.extend([
            ['I:ChooseOption:1', True],
            ['I&:ChooseOption:2', False],
            ['I|:ChooseOption:3', True],
        ])
        p.client.gdevent.set()
        g.players = BatchList(pl)
        hook_game(g)
        g.gr_groups = WeakSet()

        ilet = ChooseOptionInputlet(self, (False, True))

        eq_(user_input([p], ilet), True)
        eq_(user_input([p], ilet, type='all'), {p: False})
        eq_(user_input([p], ilet, type='any'), (p, True))

        for p in pl:
            eq_(p.client.gdhistory, [
                ['RI:ChooseOption:1', True],
                ['RI&:ChooseOption:2', False],
                ['RI|:ChooseOption:3', True],
            ])

        autoenv.init('Client')
        g = THBattle()
        pl = [PeerPlayer() for i in xrange(6)]
        svr = MockConnection([
            ['RI:ChooseOption:1', True],
            ['RI&:ChooseOption:2', False],
            ['RI|:ChooseOption:3', True],
        ])
        p = TheChosenOne(svr)
        pl[0] = p
        g.me = p
        svr.gdevent.set()
        g.players = BatchList(pl)
        hook_game(g)
        assert autoenv.Game.getgame() is g

        ilet = ChooseOptionInputlet(self, (False, True))

        eq_(user_input([p], ilet), True)
        eq_(user_input([p], ilet, type='all'), {p: False})
        eq_(user_input([p], ilet, type='any'), (p, True))
Esempio n. 9
0
    def worker():
        packed = (user.account.username, msg)
        if user.state == 'hang':  # hall chat
            for u in users.values():
                if u.state == 'hang':
                    u.write(['chat_msg', packed])

        elif user.state in ('inroomwait', 'ready', 'ingame', 'observing'):  # room chat
            ul = user.current_game.players.client
            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])
Esempio n. 10
0
    def effect_string(act):
        # for LaunchCard.ui_meta.effect_string
        source = act.source
        card = act.card
        tl = BatchList(act.target_list)
        cl = BatchList(card.associated_cards)
        s = u'|G【%s】|r发动了|G变化|r技能,将|G%s|r当作|G%s|r对|G【%s】|r使用。' % (
            source.ui_meta.name,
            u'|r、|G'.join(cl.ui_meta.name),
            card.treat_as.ui_meta.name,
            u'】|r、|G【'.join(tl.ui_meta.name),
        )

        return s
Esempio n. 11
0
    def __init__(self, sock, addr):
        Endpoint.__init__(self, sock, addr)
        Greenlet.__init__(self)
        self.gdqueue = deque(maxlen=100)
        self.gdevent = Event()
        self.observers = BatchList()

        import socket
        try:
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True)
            sock.setsockopt(socket.SOL_TCP, socket.TCP_KEEPIDLE, 30)
            sock.setsockopt(socket.SOL_TCP, socket.TCP_KEEPINTVL, 6)
            sock.setsockopt(socket.SOL_TCP, socket.TCP_KEEPCNT, 3)
        except:
            pass
Esempio n. 12
0
    def worker():
        packed = (user.account.username, msg)
        if user.state == 'hang':  # hall chat
            for u in users.values():
                if u.state == 'hang':
                    u.write(['chat_msg', packed])

        elif user.state in ('inroomwait', 'ready', 'ingame',
                            'observing'):  # room chat
            ul = user.current_game.players.client
            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])
Esempio n. 13
0
    def apply_action(self):
        src = self.source
        tgt = self.target
        g = Game.getgame()

        pl = BatchList([tgt, src])
        pindian_card = {src: None, tgt: None}

        with InputTransaction('Pindian', pl) as trans:
            for p in pl:
                cards = user_choose_cards(self,
                                          p, ('cards', 'showncards'),
                                          trans=trans)
                if cards:
                    card = cards[0]
                else:
                    card = random_choose_card([p.cards, p.showncards])

                pindian_card[p] = card
                detach_cards([card])
                g.emit_event('pindian_card_chosen', (p, card))

        g.players.reveal([pindian_card[src], pindian_card[tgt]])
        g.emit_event('pindian_card_revealed', self)  # for ui.
        migrate_cards([pindian_card[src], pindian_card[tgt]],
                      g.deck.droppedcards,
                      unwrap=True,
                      is_bh=True)

        return pindian_card[src].number > pindian_card[tgt].number
Esempio n. 14
0
    def build_initial_players(self):
        from server.core.game_server import Player, NPCPlayer

        pl = BatchList([Player(u) for u in self.users])
        pl[:0] = [NPCPlayer(NPCClient(i.name), i.input_handler) for i in self.game.npc_players]

        return pl
Esempio n. 15
0
    def __init__(self, gid, gamecls, name, invite_only):
        g = gamecls()

        self.game         = g
        self.users        = BatchList([ClientPlaceHolder] * g.n_persons)
        self.game_started = False
        self.game_name    = name
        self.banlist      = defaultdict(set)
        self.ob_banlist   = defaultdict(set)
        self.gameid       = gid
        self.gamecls      = gamecls
        self.game_items   = defaultdict(set)  # userid -> {'item:meh', ...}
        self.game_params  = {k: v[0] for k, v in gamecls.params_def.items()}
        self.is_match     = False
        self.match_users  = []
        self.invite_only  = invite_only
        self.invite_list  = set()
        self.muted        = False

        g.gameid    = gid
        g._manager  = self
        g.rndseed   = random.getrandbits(63)
        g.random    = random.Random(g.rndseed)
        g.players   = BatchList()
        g.gr_groups = WeakSet()
Esempio n. 16
0
        def observe_started(self, data):
            Executive.server.gclear()
            if self.last_game:
                self.last_game.kill(ForcedKill)
                self.last_game.get()
                self.last_game = None

            params, tgtid, pldata = data
            from client.core import PeerPlayer, TheLittleBrother
            pl = [PeerPlayer.parse(i) for i in pldata]
            pid = [i.account.userid for i in pl]
            i = pid.index(tgtid)
            self.last_game_info = params, i, pldata
            g = self.game
            g.players = BatchList(pl)
            me = g.players[i]
            me.__class__ = TheLittleBrother
            me.server = Executive.server
            g.me = me
            g.game_params = params
            # g.start()  Starts by UI
            log.info('=======OBSERVE STARTED=======')
            log.info(g)

            @g.link_exception
            def crash(*a):
                self.event_cb('game_crashed', g)

            @g.link_value
            def finish(*a):
                v = g.get()
                if not isinstance(v, ForcedKill):
                    self.event_cb('client_game_finished', g)

            self.event_cb('game_started', (g, params, pldata, g.players[:]))
Esempio n. 17
0
 def __init__(self, sock, addr):
     Endpoint.__init__(self, sock, addr)
     Greenlet.__init__(self)
     self.observers = BatchList()
     self.init_gamedata_mixin()
     self.gdhistory = []
     self.usergdhistory = []
Esempio n. 18
0
        def game_started(self, pldata):
            Executive.server.gclear()
            if self.last_game:
                self.last_game.kill(ForcedKill)
                self.last_game.get()
                self.last_game = None

            from client.core import PeerPlayer, TheChosenOne
            pl = [PeerPlayer.parse(i) for i in pldata]
            pid = [i.account.userid for i in pl]
            me = TheChosenOne(Executive.server)
            me.account = self.account
            i = pid.index(me.account.userid)
            pl[i] = me
            g = self.game
            g.me = me
            g.players = BatchList(pl)
            #g.start()
            log.info('=======GAME STARTED: %d=======' % g.gameid)
            log.info(g)

            @g.link_exception
            def crash(*a):
                self.event_cb('game_crashed', g)

            @g.link_value
            def finish(*a):
                v = g.get()
                if not isinstance(v, ForcedKill):
                    self.event_cb('client_game_finished', g)

            self.event_cb('game_started', g)
Esempio n. 19
0
    def __init__(self):
        Greenlet.__init__(self)
        game.base.Game.__init__(self)
        self.players = BatchList()
        self.game_params = {}
        self.game_items = {}

        self._my_user_input = (None, None)
Esempio n. 20
0
class ClientPlaceHolder(object):
    state     = 'left'
    account   = None
    observers = BatchList()
    raw_write = write = lambda *a: False

    def __data__(self):
        return (None, None, 'left')
Esempio n. 21
0
    def user_input_all(self, tag, process, attachment=None, timeout=15):
        g = Game.getgame()
        st = g.get_synctag()
        workers = BatchList()
        try:
            def worker(p, i):
                retry = 0
                while True:
                    input = p.user_input(
                        tag, attachment=attachment, timeout=timeout,
                        g=g, st=100000 + st*1000 + i*10 + retry,
                    )

                    try:
                        input = process(p, input)
                    except ValueError:
                        retry += 1
                        if retry >= 3:
                            input = None
                            break

                        continue

                    break

            for i, p in enumerate(self):
                w = gevent.spawn(worker, p, i)
                w.game = g
                workers.append(w)

            workers.join()
        finally:
            workers.kill()
Esempio n. 22
0
    def effect_string(act):
        # for LaunchCard.ui_meta.effect_string
        source = act.source
        tl = BatchList(act.target_list)

        return u'全人类的绯想天,当然不能只打一个!于是|G【%s】|r选了|G【%s】|r一共%d个目标!' % (
            source.ui_meta.name,
            u'】|r、|G【'.join(tl.ui_meta.name),
            len(tl),
        )
Esempio n. 23
0
 def effect_string_before(act):
     s, tl = act.source, BatchList(act.target_list)
     c = act.card
     from gamepack.thb.cards import Skill
     if isinstance(c, Skill):
         return c.ui_meta.effect_string(act)
     elif c:
         return u'|G【%s】|r对|G【%s】|r使用了|G%s|r。' % (
             s.ui_meta.char_name, u'】|r、|G【'.join(
                 tl.ui_meta.char_name), act.card.ui_meta.name)
Esempio n. 24
0
 def __init__(self, target, dmgact):
     self.source = self.target = target
     self.dmgact = dmgact
     g = Game.getgame()
     if target.dead:
         log.error('TryRevive buggy condition, __init__')
         return
     self.asklist = BatchList(
         p for p in g.players if not p.dead
     ).rotate_to(target)
Esempio n. 25
0
    def end_game(self):
        if self.is_match and not self.game.suicide:
            gevent.spawn(lambda: interconnect.publish(
                'speaker', [u'文文', u'“%s”结束了!获胜玩家:%s' % (
                    self.game_name,
                    u','.join(BatchList(self.game.winners).account.username)
                )]
            ))

        for u in self.users:
            u.write(['end_game', None])
            u.observers and u.observers.write(['end_game', None])
            u.state = 'hang'
Esempio n. 26
0
    def effect_string_before(act):
        s, tl = act.source, BatchList(act.target_list)
        c = act.card
        if not c:
            return

        meta = getattr(c, 'ui_meta', None)
        effect_string = getattr(meta, 'effect_string', None)
        if effect_string:
            return effect_string(act)

        return u'|G【%s】|r对|G【%s】|r使用了|G%s|r。' % (
            s.ui_meta.name, u'】|r、|G【'.join(
                tl.ui_meta.name), act.card.ui_meta.name)
Esempio n. 27
0
    def __init__(self, sock, addr):
        Endpoint.__init__(self, sock, addr)
        Greenlet.__init__(self)
        self.gdqueue = deque(maxlen=100)
        self.gdevent = Event()
        self.observers = BatchList()

        import socket
        try:
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True)
            sock.setsockopt(socket.SOL_TCP, socket.TCP_KEEPIDLE, 30)
            sock.setsockopt(socket.SOL_TCP, socket.TCP_KEEPINTVL, 6)
            sock.setsockopt(socket.SOL_TCP, socket.TCP_KEEPCNT, 3)
        except:
            pass
Esempio n. 28
0
    def effect_string(act):
        # for LaunchCard.ui_meta.effect_string
        source = act.source
        card = act.card.associated_cards[0]
        tl = BatchList(act.target_list)

        if card.is_card(cards.AttackCard):
            s = u'弹幕掺了金坷垃,攻击范围一千八!'
        else:
            s = u'符卡掺了金坷垃,一张能顶两张用!'

        return u'|G【%s】|r:“%s|G【%s】|r接招吧!”' % (
            source.ui_meta.name,
            s,
            u'】|r、|G【'.join(tl.ui_meta.name),
        )
Esempio n. 29
0
    def handle(self, evt_type, act):
        if evt_type == 'action_before' and isinstance(act, SpellCardAction):
            if act.cancelled: return act  # some other thing have done the job
            if act.non_responsive:
                return act

            g = Game.getgame()

            has_reject = False
            while g.SERVER_SIDE:
                from ..characters.baseclasses import Character
                from ..characters.reimu import SpiritualAttack
                for p in g.players:
                    if isinstance(p,
                                  Character) and p.has_skill(SpiritualAttack):
                        has_reject = True
                        break

                if has_reject: break

                from .definition import RejectCard
                for c in flatten([[p.cards, p.showncards] for p in g.players]):
                    if isinstance(c, RejectCard):
                        has_reject = True
                        break

                break

            has_reject = sync_primitive(has_reject, g.players)
            if not has_reject: return act

            self.target_act = act

            pl = BatchList(p for p in g.players if not p.dead)

            with InputTransaction('AskForRejectAction', pl) as trans:
                p, rst = ask_for_action(self, pl, ('cards', 'showncards'), [],
                                        trans)

            if not p: return act
            cards, _ = rst
            assert cards and self.cond(cards)
            g.process_action(
                LaunchCard(p, [act.target], cards[0], Reject(p, act)))

        return act
Esempio n. 30
0
    def user_input_all(self, tag, process, attachment=None, timeout=15):
        g = Game.getgame()
        g.emit_event('user_input_all_begin', (self, tag, attachment))
        st = g.get_synctag()
        workers = BatchList()
        try:

            def worker(p, i):
                retry = 0
                while True:
                    input = p.user_input(
                        tag,
                        attachment=attachment,
                        timeout=timeout,
                        g=g,
                        st=100000 + st * 1000 + i * 10 + retry,
                    )
                    try:
                        input = process(p, input)
                    except ValueError:
                        retry += 1
                        if retry >= 3:
                            input = None
                            break

                        continue

                    g.emit_event('user_input_all_data', (tag, p, input))

                    break

            for i, p in enumerate(self):
                w = gevent.spawn(worker, p, i)
                w.game = g
                workers.append(w)

            workers.join()
        finally:
            workers.kill()

        g.emit_event('user_input_all_end', tag)
Esempio n. 31
0
    def makeGame(self):
        from game import autoenv

        from thb.thb3v3 import THBattle
        from thb.cards import Deck, CardList
        from thb.characters.eirin import FirstAid, Medic

        from utils import BatchList

        autoenv.init('Server')
        g = THBattle()
        g.IS_DEBUG = True
        g.random = random
        hook_game(g)
        deck = Deck()
        g.deck = deck
        g.action_stack = [autoenv.Action(None, None)]
        g.gr_groups = WeakSet()

        pl = [create_mock_player([]) for i in xrange(6)]
        for p in pl:
            p.skills = [FirstAid, Medic]

            p.cards = CardList(p, 'cards')  # Cards in hand
            p.showncards = CardList(
                p, 'showncard'
            )  # Cards which are shown to the others, treated as 'Cards in hand'
            p.equips = CardList(p, 'equips')  # Equipments
            p.fatetell = CardList(p, 'fatetell')  # Cards in the Fatetell Zone
            p.faiths = CardList(p, 'faiths')  # Cards in the Fatetell Zone
            p.special = CardList(p, 'special')  # used on special purpose

            p.showncardlists = [p.showncards, p.fatetell]

            p.tags = defaultdict(int)

            p.dead = False

        p = pl[0]
        p.client.gdevent.set()
        g.players = BatchList(pl)

        return g, p
Esempio n. 32
0
def create_game(user, gametype, gamename):
    from gamepack import gamemodes
    if not gametype in gamemodes:
        user.write(['gamehall_error', 'gametype_not_exist'])
        return

    g = gamemodes[gametype]()
    g.game_started = False
    g.game_name = gamename
    g.players = BatchList([PlayerPlaceHolder] * g.n_persons)
    g.players_original = None
    g.rndseed = random.randint(1, 10**20)
    g.random = random.Random(g.rndseed)
    g.banlist = defaultdict(set)
    g.gr_groups = WeakSet()
    gid = new_gameid()
    g.gameid = gid
    games[gid] = g
    log.info("create game")
    evt_datachange.set()
    return g
Esempio n. 33
0
    def handle(self, evt_type, act):
        if evt_type == 'action_before' and isinstance(act, SpellCardAction):
            if act.cancelled: return act  # some other thing have done the job
            if isinstance(act, NonResponsiveInstantSpellCardAction):
                return act

            g = Game.getgame()

            has_reject = False
            while g.SERVER_SIDE:
                from ..characters.reimu import Reimu
                for p in g.players:
                    if isinstance(p, Reimu):
                        has_reject = True
                        break

                if has_reject: break

                from .definition import RejectCard
                for c in flatten([[p.cards, p.showncards] for p in g.players]):
                    if isinstance(c, RejectCard):
                        has_reject = True
                        break

                break

            has_reject = sync_primitive(has_reject, g.players)
            if not has_reject: return act

            self.target_act = act  # for ui

            pl = BatchList(p for p in g.players if not p.dead)

            p, rst = ask_for_action(self, pl, ['cards', 'showncards'], [])
            if not p: return act
            cards, _ = rst
            assert cards and self.cond(cards)
            g.process_action(LaunchReject(p, act, cards[0]))

        return act
Esempio n. 34
0
    def start_replay(self, rep, event_cb):
        assert self.state == 'initial'

        self.state = 'replay'

        from client.core import PeerPlayer, TheLittleBrother
        from thb import modes

        g = modes[rep.game_mode]()
        self.server = ReplayEndpoint(rep, g)

        pl = [PeerPlayer.parse(i) for i in rep.users]

        g.players = BatchList(pl)
        me = g.players[rep.me_index]
        me.__class__ = TheLittleBrother
        me.server = self.server
        g.me = me
        g.game_params = rep.game_params
        g.game_items = rep.game_items
        log.info('=======REPLAY STARTED=======')

        # g.start()  Starts by UI

        @g.link_exception
        def crash(*a):
            self.state = 'initial'
            event_cb('game_crashed', g)

        @g.link_value
        def finish(*a):
            self.state = 'initial'
            v = g.get()
            if not isinstance(v, ForcedKill):
                event_cb('client_game_finished', g)

            event_cb('end_game', g)

        return g
Esempio n. 35
0
def start_game(g):
    log.info("game started")
    g.game_started = True
    g.players_original = BatchList(g.players)
    g.usergdhistory = ugh = []
    g.gdhistory = [list() for p in g.players]

    for i, (u, l) in enumerate(zip(g.players.client, g.gdhistory)):
        u.player_index = i
        u.usergdhistory = ugh
        u.gdhistory = l

    g.start_time = time.time()
    for u in g.players.client:
        u.write(["game_started", g.players])
        u.gclear()
        if u.observers:
            u.observers.gclear()
            u.observers.write(
                ['observe_started', [u.account.userid, g.players]])
        u.state = 'ingame'
    evt_datachange.set()
Esempio n. 36
0
class Client(Endpoint, Greenlet):
    def __init__(self, sock, addr):
        Endpoint.__init__(self, sock, addr)
        Greenlet.__init__(self)
        self.gdqueue = deque(maxlen=100)
        self.gdevent = Event()
        self.observers = BatchList()

        import socket
        try:
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True)
            sock.setsockopt(socket.SOL_TCP, socket.TCP_KEEPIDLE, 30)
            sock.setsockopt(socket.SOL_TCP, socket.TCP_KEEPINTVL, 6)
            sock.setsockopt(socket.SOL_TCP, socket.TCP_KEEPCNT, 3)
        except:
            pass

    def _run(self):
        cmds = {}
        self.account = None

        def handler(*state):
            def register(f):
                for s in state:
                    d = cmds.setdefault(s, {})
                    d[f.__name__] = f
            return register

        # --------- Handlers ---------
        @handler('connected')
        def register(self,data):
            self.write(['not_impl', None])

        @handler('connected')
        def auth(self, cred):
            login, password = cred
            acc = Account.authenticate(login, password)
            if acc:
                self.account = acc
                if not acc.available():
                    self.write(['auth_result', 'not_available'])
                    self.close()
                else:
                    self.write(['auth_result', 'success'])
                    self.account = acc
                    hall.new_user(self)

            else:
                self.write(['auth_result', 'invalid_credential'])

        @handler('hang')
        def create_game(self, arg):
            _type, name = arg
            g = hall.create_game(self, _type, name)
            hall.join_game(self, g.gameid)

        @handler('hang')
        def join_game(self, gameid):
            hall.join_game(self, gameid)

        @handler('hang')
        def get_hallinfo(self, _):
            hall.send_hallinfo(self)

        @handler('hang')
        def quick_start_game(self, _):
            hall.quick_start_game(self)

        @handler('hang')
        def observe_user(self, uid):
            hall.observe_user(self, uid)

        @handler('inroomwait', 'ready', 'ingame')
        def observe_grant(self, rst):
            hall.observe_grant(self, rst)

        @handler('hang')
        def query_gameinfo(self, gid):
            hall.query_gameinfo(self, gid)

        @handler('inroomwait')
        def get_ready(self, _):
            hall.get_ready(self)

        @handler('inroomwait', 'ready', 'ingame', 'observing')
        def exit_game(self, _):
            hall.exit_game(self)

        @handler('inroomwait', 'ready')
        def kick_user(self, uid):
            hall.kick_user(self, uid)

        @handler('inroomwait')
        def change_location(self, loc):
            hall.change_location(self, loc)

        @handler('ready')
        def cancel_ready(self, _):
            hall.cancel_ready(self)

        @handler('ingame')
        def gamedata(self, data):
            p = Packet(data)
            p.scan_count = 0
            self.gdqueue.append(p)
            self.gdevent.set()

        @handler('__any__')
        def _disconnect(self, _):
            self.write(['bye', None])
            self.close()

        @handler('hang', 'inroomwait', 'ready', 'ingame', 'observing')
        def chat(self, data):
            hall.chat(self, data)

        @handler('hang', 'inroomwait', 'ready', 'ingame', 'observing')
        def speaker(self, data):
            hall.speaker(self, data)

        # --------- End ---------

        # ----- Banner -----
        from settings import VERSION
        self.write(['thbattle_greeting', VERSION])
        # ------------------

        self.state = 'connected'
        while True:
            try:
                cmd, data = self.read()
                f = cmds[self.state].get(cmd)
                if not f:
                    f = cmds['__any__'].get(cmd)

                if (self.account or cmd == 'auth') and f:
                    f(self, data)
                else:
                    self.write(['invalid_command', [cmd, data]])

            except EndpointDied as e:
                self.gdqueue.append(e)
                self.gdevent.set()
                break

        # client died, do clean ups
        if self.state not in ('connected', 'hang'):
            hall.exit_game(self, drops=True)

        if self.state != 'connected':
            hall.user_exit(self)

    def gexpect(self, tag):
        log.debug('GAME_EXPECT: %s', repr(tag))
        l = self.gdqueue
        e = self.gdevent
        while True:
            for i in xrange(len(l)):
                d = l.popleft()
                if isinstance(d, EndpointDied):
                    raise d

                elif d[0] == tag:
                    log.debug('GAME_READ: %s', repr(d))
                    self.usergdhistory.append((self.player_index, d[0], d[1]))
                    return d[1]

                else:
                    d.scan_count += 1
                    if d.scan_count >= 15:
                        log.debug('Dropped gamedata: %s' % d)
                    else:
                        log.debug('GAME_DATA_MISS: %s', repr(d))
                        log.debug('EXPECTS: %s' % tag)
                        l.append(d)
            e.clear()
            e.wait()

    def gwrite(self, tag, data):
        log.debug('GAME_WRITE: %s', repr([tag, data]))
        encoded = self.encode(['gamedata', [tag, data]])
        self.raw_write(encoded)
        self.gdhistory.append([tag, json.loads(self.encode(data))])
        if self.observers: self.observers.raw_write(encoded)

    def replay(self, ob):
        for data in self.gdhistory:
            ob.raw_write(json.dumps(['gamedata', data]) + '\n')

    def __data__(self):
        return [self.account.userid, self.account.username, self.state]

    def gbreak(self):
        # is it a hack?
        # XXX: definitly, and why it's here?! can't remember
        # Explanation:
        # Well, when sb. exit game in input state,
        # the others must wait until his timeout exceeded.
        # called by gamehall.exit_game to break such condition.
        self.gdqueue.append(EndpointDied())
        self.gdevent.set()

    def gclear(self):
        '''
        Clear the gamedata queue,
        used when a game starts, to eliminate data from last game,
        which confuses the new game.
        '''
        self.gdqueue.clear()

    def close(self):
        Endpoint.close(self)
        self.kill(EndpointDied)

    def __repr__(self):
        acc = self.account
        if not acc:
            return Endpoint.__repr__(self)
        
        return '%s:%s:%s' % (
            self.__class__.__name__,
            self.address[0],
            acc.username.encode('utf-8'),
        )
Esempio n. 37
0
    def apply_action(self):
        g = Game.getgame()
        params = self.params

        from thb.cards import Deck

        g.picks = []
        g.deck = Deck()

        g.ehclasses = list(action_eventhandlers) + g.game_ehs.values()

        H, M = Identity.TYPE.HAKUREI, Identity.TYPE.MORIYA
        if params['random_seat']:
            # reseat
            seed = get_seed_for(g.players)
            random.Random(seed).shuffle(g.players)
            g.emit_event('reseat', None)

            L = [[H, H, M, M, H, M], [H, M, H, M, H, M]]
            rnd = random.Random(get_seed_for(g.players))
            L = rnd.choice(L) * 2
            s = rnd.randrange(0, 6)
            idlist = L[s:s+6]
            del L, s, rnd
        else:
            idlist = [H, M, H, M, H, M]

        del H, M

        for p, identity in zip(g.players, idlist):
            p.identity = Identity()
            p.identity.type = identity
            g.process_action(RevealIdentity(p, g.players))

        force_hakurei      = BatchList()
        force_moriya       = BatchList()
        force_hakurei.pool = []
        force_moriya.pool  = []

        for p in g.players:
            if p.identity.type == Identity.TYPE.HAKUREI:
                force_hakurei.append(p)
                p.force = force_hakurei
            elif p.identity.type == Identity.TYPE.MORIYA:
                force_moriya.append(p)
                p.force = force_moriya

        g.forces = BatchList([force_hakurei, force_moriya])

        roll_rst = roll(g, self.items)
        first = roll_rst[0]

        # choose girls -->
        from . import characters
        chars = characters.get_characters('common', 'faith')

        choices, _ = build_choices(
            g, self.items,
            candidates=chars, players=g.players,
            num=[4] * 6, akaris=[1] * 6,
            shared=False,
        )

        rst = user_input(g.players, SortCharacterInputlet(g, choices, 2), timeout=30, type='all')

        for p in g.players:
            a, b = [choices[p][i] for i in rst[p][:2]]
            b.chosen = None
            p.force.reveal(b)
            g.switch_character(p, a)
            p.force.pool.append(b)

        for p in g.players:
            if p.player is first:
                first = p
                break

        pl = g.players
        first_index = pl.index(first)
        order = BatchList(range(len(pl))).rotate_to(first_index)

        for p in pl:
            g.process_action(RevealIdentity(p, pl))

        g.emit_event('game_begin', g)

        for p in pl:
            g.process_action(DistributeCards(p, amount=4))

        pl = g.players.rotate_to(first)
        rst = user_input(pl[1:], ChooseOptionInputlet(DeathHandler(), (False, True)), type='all')

        for p in pl[1:]:
            rst.get(p) and g.process_action(RedrawCards(p, p))

        pl = g.players
        for i, idx in enumerate(cycle(order)):
            if i >= 6000: break
            p = pl[idx]
            if p.dead: continue

            g.emit_event('player_turn', p)
            try:
                g.process_action(PlayerTurn(p))
            except InterruptActionFlow:
                pass

        return True
Esempio n. 38
0
    def testBuildChoices(self):
        import logging
        from thb.common import build_choices
        import random
        from thb.characters.baseclasses import get_characters
        from thb import characters
        from game import autoenv
        # def build_choices(g, items, candidates, players, num, akaris, shared):

        log = logging.getLogger('test')

        g = ObjectDict({
            'players':
            BatchList([
                ObjectDict({
                    'account':
                    ObjectDict({'userid': i}),
                    'reveal':
                    lambda o, i=i: log.info('Reveal to %s: %s', i, o),
                }) for i in xrange(8)
            ]),
            'random':
            random.Random(12341234),
            'SERVER_SIDE':
            True,
            'CLIENT_SIDE':
            False,
        })
        autoenv.Game.getgame = staticmethod(lambda: g)
        chars = get_characters('common', '3v3')
        assert chars

        choices, imperial = build_choices(g, {}, chars, g.players, 10, 3, True)
        eq_(len(choices.items()), len(g.players))
        eq_(len(set([id(i) for i in choices.values()])), 1)
        eq_(set(choices.keys()), set(g.players))
        eq_(imperial, [])

        choices, imperial = build_choices(
            g, {0: ['imperial-choice:SpAya', 'foo']}, chars, g.players, 10, 3,
            True)
        eq_(len(choices.items()), len(g.players))
        eq_(len(set([id(i) for i in choices.values()])), 1)
        eq_(set(choices.keys()), set(g.players))
        p, c = imperial[0]
        eq_((p, c.char_cls), (g.players[0], characters.sp_aya.SpAya))
        assert c in choices[p]
        del c
        eq_(sum([c.akari for c in choices[p]]), 3)

        choices, imperial = build_choices(
            g, {0: ['imperial-choice:SpAya', 'foo']}, chars, g.players,
            [4] * 8, [1] * 8, False)
        eq_(len(choices.items()), len(g.players))
        eq_(len(set([id(i) for i in choices.values()])), 8)
        eq_(set(choices.keys()), set(g.players))
        eq_([len(i) for i in choices.values()], [4] * 8)
        eq_([len([j for j in i if j.akari]) for i in choices.values()],
            [1] * 8)

        p, c = imperial[0]
        eq_((p, c.char_cls), (g.players[0], characters.sp_aya.SpAya))
        assert c in choices[p]
Esempio n. 39
0
from client.core import game_client
game_client.Executive = Executive  # Hack

GameMode = modes[mode]
npcs = len(GameMode.npc_players)

players = [PeerPlayer() for i in xrange(GameMode.n_persons + npcs)]
players[loc + npcs].__class__ = TheLittleBrother
players[loc + npcs].server = server

for p in players:
    p.account = Account.authenticate('Proton', '123')

g = GameMode()
g.players = BatchList(players)
g.game_params = params
g.game_items = items
g.me = players[loc + npcs]
g.replay_file = options.replay_file


@hook(g)
def pause(*a):
    pass


@hook(g)
def get_synctag(ori):
    tag = ori()
    if options.print_synctag:
Esempio n. 40
0
class GameManager(object):

    def __init__(self, gid, gamecls, name, invite_only):
        g = gamecls()

        self.game         = g
        self.users        = BatchList([ClientPlaceHolder] * g.n_persons)
        self.game_started = False
        self.game_name    = name
        self.banlist      = defaultdict(set)
        self.ob_banlist   = defaultdict(set)
        self.gameid       = gid
        self.gamecls      = gamecls
        self.game_params  = {k: v[0] for k, v in gamecls.params_def.items()}
        self.is_match     = False
        self.match_users  = []
        self.invite_only  = invite_only
        self.invite_list  = set()

        g.gameid    = gid
        g.manager   = self
        g.rndseed   = random.getrandbits(63)
        g.random    = random.Random(g.rndseed)
        g.players   = BatchList()
        g.gr_groups = WeakSet()

    def __data__(self):
        return {
            'id':       self.gameid,
            'type':     self.gamecls.__name__,
            'started':  self.game_started,
            'name':     self.game_name,
            'nplayers': len(self.get_online_users()),
            'params':   self.game_params,
        }

    @classmethod
    def get_by_user(cls, user):
        '''
        Get GameManager object for user.

        :rtype: GameManager
        '''

        return user.current_game

    def send_gameinfo(self, user):
        g = self.game
        user.write(['gameinfo', [g.gameid, g.players]])

    def set_match(self, match_users):
        self.is_match = True
        self.match_users = match_users

        gevent.spawn(lambda: [gevent.sleep(1), interconnect.publish(
            'speaker', [u'文文', u'“%s”房间已经建立,请相关玩家就位!' % self.game_name]
        )])

    @throttle(0.1)
    def notify_playerchange(self):
        @gevent.spawn
        def notify():
            from server.core.game_server import Player

            pl = self.game.players if self.game_started else map(Player, self.users)
            s = Client.encode(['player_change', pl])
            for cl in self.users:
                cl.raw_write(s)
                cl.observers and cl.observers.raw_write(s)

    def next_free_slot(self):
        try:
            return self.users.index(ClientPlaceHolder)
        except ValueError:
            return None

    def archive(self):
        g = self.game
        if not options.archive_path:
            return

        data = []

        data.append('# ' + ', '.join([
            p.account.username.encode('utf-8')
            for p in self.users
        ]))

        data.append('# Ver: ' + VERSION)
        data.append('# GameId: ' + str(self.gameid))
        s, e = int(self.start_time), int(time.time())
        data.append('# Time: start = %d, end = %d, elapsed = %d' % (s, e, e - s))

        data.append(self.gamecls.__name__)
        data.append(json.dumps(self.game_params))
        data.append(str(g.rndseed))
        data.append(json.dumps(self.usergdhistory))
        data.append(json.dumps(self.gdhistory))

        f = gzip.open(os.path.join(options.archive_path, '%s-%s.gz' % (options.node, str(self.gameid))), 'wb')
        f.write('\n'.join(data))
        f.close()

    def get_ready(self, user):
        if user.state not in ('inroomwait',):
            return

        g = self.game
        if user not in self.users:
            log.error('User not in player list')
            return

        user.state = 'ready'
        self.notify_playerchange()

        if all(u.state == 'ready' for u in self.users):
            if not g.started:
                # race condition here.
                # wrap in 'if g.started' to prevent double starting.
                log.info("game starting")
                g.start()

    def cancel_ready(self, user):
        if user.state not in ('ready',):
            return

        if user not in self.users:
            log.error('User not in player list')
            return

        user.state = 'inroomwait'
        self.notify_playerchange()

    def set_game_param(self, user, key, value):
        if user.state != 'inroomwait':
            return

        if user not in self.users:
            log.error('User not in this game!')
            return

        cls = self.gamecls
        if key not in cls.params_def:
            log.error('Invalid option "%s"', key)
            return

        if value not in cls.params_def[key]:
            log.error('Invalid value "%s" for key "%s"', value, key)
            return

        if self.game_params[key] == value:
            return

        self.game_params[key] = value

        for u in self.users:
            if u.state == 'ready':
                self.cancel_ready(u)

            u.write(['set_game_param', [user, key, value]])
            u.write(['game_params', self.game_params])

        self.notify_playerchange()

    def update_game_param(self, params):
        self.game_params.update(params)
        self.users.write(['game_params', self.game_params])
        self.notify_playerchange()

    def change_location(self, user, loc):
        if user.state not in ('inroomwait', ):
            return

        pl = self.users
        if (not 0 <= loc < len(pl)) or (pl[loc] is not ClientPlaceHolder):
            user.write(['change_loc_failed', None])
            return

        # observing: should send join game
        i = pl.index(user)
        pl[loc], pl[i] = pl[i], pl[loc]
        self.notify_playerchange()

    def kick_user(self, user, other):
        if user.state not in ('inroomwait', 'ready'):
            return

        cl = self.users

        bl = self.banlist[other]
        bl.add(user)

        s = Client.encode(['kick_request', [user, other, len(bl)]])
        for cl in self.users:
            cl.raw_write(s)
            cl.observers and cl.observers.raw_write(s)

        return len(bl) >= len(self.users) // 2

    def kick_observer(self, user, other):
        if user not in self.users:
            return False

        if GameManager.get_by_user(other) is not self:
            return False

        if other.state != 'observing':
            return False

        bl = self.ob_banlist[other]
        bl.add(user)

        s = Client.encode(['ob_kick_request', [user, other, len(bl)]])
        for cl in self.users:
            cl.raw_write(s)
            cl.observers and cl.observers.raw_write(s)

        return len(bl) >= len(self.users) // 2

    def observe_leave(self, user, no_move=False):
        assert user.state == 'observing'

        tgt = user.observing
        tgt.observers.remove(user)
        try:
            del self.ob_banlist[user]
        except KeyError:
            pass
        user.state = 'hang'
        user.observing = None
        user.current_game = None
        user.gclear()
        no_move or user.write(['game_left', None])

        @gevent.spawn
        def notify_observer_leave():
            ul = self.users
            info = [user.account.userid, user.account.username, tgt.account.username]
            ul.write(['observer_leave', info])
            for obl in ul.observers:
                obl and obl.write(['observer_leave', info])

    def observe_user(self, user, observee):
        g = self.game
        assert observee in self.users
        assert user.state == 'hang'

        log.info("observe game")

        observee.observers.append(user)

        user.state = 'observing'
        user.current_game = self
        user.observing = observee
        user.write(['game_joined', self])
        user.gclear()  # clear stale gamedata

        self.notify_playerchange()

        @gevent.spawn
        def notify_observer():
            ul = self.users
            info = [user.account.userid, user.account.username, observee.account.username]
            ul.write(['observer_enter', info])
            for obl in ul.observers:
                obl and obl.write(['observer_enter', info])

        if g.started:
            user.write(['observe_started', [self.game_params, observee.account.userid, self.build_initial_players()]])
            self.replay(user, observee)
        else:
            self.notify_playerchange()

    def is_banned(self, user):
        if self.is_match:
            return not (user.account.userid in self.match_users or user.account.username in self.match_users)

        return len(self.banlist[user]) >= max(self.game.n_persons // 2, 1)

    def is_invited(self, user):
        return not self.invite_only or user.account.userid in self.invite_list

    def add_invited(self, user):
        self.invite_list.add(user.account.userid)

    def copy_invited(self, mgr):
        self.invite_list = set(mgr.invite_list)

    def join_game(self, user, slot, observing=False):
        assert user not in self.users
        assert user.state == ('observing' if observing else 'hang')

        if slot is None:
            slot = self.next_free_slot()
        elif self.users[slot] is not ClientPlaceHolder:
            slot = None

        if slot is None:
            return

        self.users[slot] = user

        if observing:
            origin = self.get_by_user(user)
            origin.observe_leave(user, no_move=origin is self)

        user.current_game = self
        user.state = 'inroomwait'
        user.write(['game_joined', self])
        if user.observers:
            for ob in user.observers:
                ob.write(['game_joined', self])
                ob.current_game = self
                ob.state = 'observing'

        self.notify_playerchange()

    def start_game(self):
        g = self.game
        assert ClientPlaceHolder not in self.users
        assert all([u.state == 'ready' for u in self.users])

        if self.is_match:
            gevent.spawn(lambda: interconnect.publish(
                'speaker', [u'文文', u'“%s”开始了!参与玩家:%s' % (
                    self.game_name,
                    u','.join(self.users.account.username)
                )]
            ))

        self.game_started = True

        g.players = self.build_initial_players()

        self.usergdhistory = []
        self.gdhistory     = [list() for p in self.users]

        self.start_time = time.time()
        for u in self.users:
            u.write(["game_started", [self.game_params, g.players]])
            u.gclear()
            if u.observers:
                u.observers.gclear()
                u.observers.write(['observe_started', [self.game_params, u.account.userid, g.players]])
            u.state = 'ingame'

    def build_initial_players(self):
        from server.core.game_server import Player, NPCPlayer

        pl = BatchList([Player(u) for u in self.users])
        pl[:0] = [NPCPlayer(NPCClient(i.name), i.input_handler) for i in self.game.npc_players]

        return pl

    def record_gamedata(self, user, tag, data):
        idx = self.users.index(user)
        self.gdhistory[idx].append((tag, Client.decode(Client.encode(data))))

    def record_user_gamedata(self, user, tag, data):
        idx = self.users.index(user)
        self.usergdhistory.append((idx, tag, Client.decode(Client.encode(data))))

    def replay(self, observer, observee):
        idx = self.users.index(observee)
        for data in self.gdhistory[idx]:
            observer.write(['gamedata', data])

    def squeeze_out(self, old, new):
        old.write(['others_logged_in', None])
        if old.state == 'ingame':
            self.reconnect(new)

    def reconnect(self, new):
        g = self.game
        new.state = 'ingame'
        new.current_game = self

        for p in g.players:
            if p.client.account.userid == new.account.userid:
                p.reconnect(new)
                break
        else:
            assert False, 'Oops'

        for i, u in enumerate(self.users):
            if u.account.userid == new.account.userid:
                self.users[i] = new
                break
        else:
            assert False, 'Oops'

        new.write(['game_joined',  self])
        self.notify_playerchange()

        players = self.build_initial_players()
        new.write(['game_started', [self.game_params, players]])

        self.replay(new, new)

    def exit_game(self, user, is_drop):
        rst = None
        assert user in self.users
        is_drop or user.gclear()
        g = self.game
        if self.game_started:
            i = g.players.client.index(user)
            p = g.players[i]
            log.info('player dropped')
            can_leave = g.can_leave(p)

            if can_leave:
                user.write(['game_left', None])
                p.set_fleed(False)
            else:
                p.set_dropped()
                if not is_drop:
                    user.write(['fleed', None])
                    p.set_fleed(True)
                else:
                    p.set_fleed(False)

            p.client.gbreak()  # XXX: f**k I forgot why it's here. Exp: see comment on Client.gbreak

            dummy = DroppedClient(g.players[i].client)
            p.set_client(dummy)
            self.users.replace(user, dummy)
            rst = dummy
        else:
            log.info('player leave')
            self.users.replace(user, ClientPlaceHolder)
            user.write(['game_left', None])

        self.notify_playerchange()

        for bl in self.banlist.values():
            bl.discard(user)

        return rst

    def end_game(self):
        if self.is_match and not self.game.suicide:
            gevent.spawn(lambda: interconnect.publish(
                'speaker', [u'文文', u'“%s”结束了!获胜玩家:%s' % (
                    self.game_name,
                    u','.join(BatchList(self.game.winners).account.username)
                )]
            ))

        for u in self.users:
            u.write(['end_game', None])
            u.observers and u.observers.write(['end_game', None])
            u.state = 'hang'

    def get_online_users(self):
        return [p for p in self.users if (p is not ClientPlaceHolder and not isinstance(p, DroppedClient))]

    def kill_game(self):
        if self.is_match and self.game.started:
            gevent.spawn(lambda: interconnect.publish(
                'speaker', [u'文文', u'“%s”意外终止了!' % self.game_name]
            ))

        self.game.suicide = True  # game will kill itself in get_synctag()

    def get_bonus(self):
        assert self.get_online_users()

        t = time.time()
        g = self.game
        percent = min(1.0, (t - self.start_time) / 1200)
        import math
        rate = math.sin(math.pi / 2 * percent)
        winners = g.winners
        bonus = g.n_persons * 5 / len(winners) if winners else 0

        rst = []

        for p in g.players:
            u = p.client

            if isinstance(u, NPCClient):
                continue

            rst.append((u, 'games', 1))
            if p.dropped or p.fleed:
                if not options.no_counting_flee:
                    rst.append((u, 'drops', 1))
            else:
                s = 5 + bonus if p in winners else 5
                rst.append((u, 'credits', int(s * rate * options.credit_multiplier)))

        return rst

    def record_stacktrace(self):
        g = self.game
        log.info('>>>>> GAME STACKTRACE <<<<<')

        def logtraceback(gr):
            import traceback
            log.info('----- %r -----\n%s', gr, ''.join(traceback.format_stack(gr.gr_frame)))

        logtraceback(g)
        for i in g.gr_groups:
            for j in i:
                logtraceback(j)

        for cl in g.players.client:
            if isinstance(cl, Client):
                logtraceback(cl)

        log.info('===========================')
Esempio n. 41
0
class Client(Endpoint):
    def __init__(self, sock, addr, greenlet):
        Endpoint.__init__(self, sock, addr)
        self.observers = BatchList()
        self.gamedata = Gamedata()
        self.cmd_listeners = defaultdict(WeakSet)
        self.current_game = None
        self.greenlet = greenlet

        self.account = None

    @classmethod
    def serve(cls, sock, addr):
        c = getcurrent()
        cli = cls(sock, addr, c)
        c.gr_name = repr(cli)
        cli._serve()

    @log_failure(log)
    def _serve(self):
        # ----- Banner -----
        from settings import VERSION
        self.write(['thbattle_greeting', (options.node, VERSION)])
        # ------------------

        self.state = 'connected'
        while True:
            try:
                hasdata = False
                with Timeout(90, False):
                    cmd, data = self.read()
                    hasdata = True

                if not hasdata:
                    self.close()
                    # client should send heartbeat periodically
                    raise EndpointDied

                self.handle_command(cmd, data)

            except EndpointDied:
                self.gbreak()
                break

            except Exception:
                log.exception("Error occurred when handling client command")

        # client died, do clean ups
        self.handle_drop()

    def close(self):
        Endpoint.close(self)
        gr = self.greenlet
        self.greenlet = None
        gr and gr.kill(EndpointDied)

    def __repr__(self):
        acc = self.account
        if not acc:
            return Endpoint.__repr__(self)

        return '%s:%s:%s' % (
            self.__class__.__name__,
            self.address[0],
            acc.username.encode('utf-8'),
        )

    def __data__(self):
        return dict(
            account=self.account,
            state=self.state,
        )

    def __eq__(self, other):
        return self.account is other.account

    def listen_command(self, *cmds):
        listeners_set = self.cmd_listeners
        q = Queue(100)
        for cmd in cmds:
            listeners_set[cmd].add(q)

        return q

    def handle_command(self, cmd, data):
        if cmd == 'gamedata':
            self.gamedata.feed(data)
            return

        f = getattr(self, 'command_' + str(cmd), None)
        if not f:
            listeners = self.cmd_listeners[cmd]
            if listeners:
                [l.put(data) for l in listeners]
                return

            log.debug('No command %s', cmd)
            self.write(['invalid_command', [cmd, data]])
            return

        if not isinstance(data, (list, tuple)):
            log.error('Malformed command: %s %s', cmd, data)
            return

        n = f.__code__.co_argcount - 1
        if n != len(data):
            log.error(
                'Command "%s" argcount mismatch, expect %s, got %s',
                cmd, n, len(data)
            )
        else:
            f(*data)

    def handle_drop(self):
        if self.state not in ('connected', 'hang'):
            Subsystem.lobby.exit_game(self, is_drop=True)

        if self.state != 'connected':
            Subsystem.lobby.user_leave(self)

    def gexpect(self, tag, blocking=True):
        tag, data = self.gamedata.gexpect(tag, blocking)
        tag and _record_user_gamedata(self, tag, data)
        return tag, data

    def gwrite(self, tag, data):
        log.debug('GAME_WRITE: %s -> %s', self.account.username, repr([tag, data]))

        _record_gamedata(self, tag, data)

        encoded = self.encode(['gamedata', [tag, data]])
        self.raw_write(encoded)
        self.observers and self.observers.raw_write(encoded)

    def gbreak(self):
        return self.gamedata.gbreak()

    def gclear(self):
        self.gamedata = Gamedata()

    # --------- Handlers ---------
    def command_auth(self, login, password):
        if self.state != 'connected' or self.account:
            self.write(['invalid_command', ['auth', '']])
            return

        acc = Account.authenticate(login, password)
        if acc:
            self.account = acc
            if not acc.available():
                self.write(['auth_result', 'not_available'])
                self.close()
            else:
                self.write(['auth_result', 'success'])
                self.account = acc
                Subsystem.lobby.user_join(self)

        else:
            self.write(['auth_result', 'invalid_credential'])

    def command_lobby(self, cmd, args):
        Subsystem.lobby.process_command(self, cmd, args)

    def command_item(self, cmd, args):
        Subsystem.item.process_command(self, cmd, args)

    def command_heartbeat(self):
        pass
Esempio n. 42
0
    def apply_action(self):
        g = Game.getgame()
        params = self.params

        from cards import Deck

        g.picks = []
        g.deck = Deck()

        g.ehclasses = list(action_eventhandlers) + g.game_ehs.values()

        H, M = Identity.TYPE.HAKUREI, Identity.TYPE.MORIYA
        if params['random_seat']:
            # reseat
            seed = get_seed_for(g.players)
            random.Random(seed).shuffle(g.players)
            g.emit_event('reseat', None)

            L = [[H, H, M, M, H, M], [H, M, H, M, H, M]]
            rnd = random.Random(get_seed_for(g.players))
            L = rnd.choice(L) * 2
            s = rnd.randrange(0, 6)
            idlist = L[s:s+6]
            del L, s, rnd
        else:
            idlist = [H, M, H, M, H, M]

        del H, M

        for p, identity in zip(g.players, idlist):
            p.identity = Identity()
            p.identity.type = identity
            g.process_action(RevealIdentity(p, g.players))

        force_hakurei      = BatchList()
        force_moriya       = BatchList()
        force_hakurei.pool = []
        force_moriya.pool  = []

        for p in g.players:
            if p.identity.type == Identity.TYPE.HAKUREI:
                force_hakurei.append(p)
                p.force = force_hakurei
            elif p.identity.type == Identity.TYPE.MORIYA:
                force_moriya.append(p)
                p.force = force_moriya

        g.forces = BatchList([force_hakurei, force_moriya])

        # ----- roll ------
        roll = range(len(g.players))
        g.random.shuffle(roll)
        pl = g.players
        roll = sync_primitive(roll, pl)
        roll = [pl[i] for i in roll]
        g.emit_event('game_roll', roll)
        first = roll[0]
        g.emit_event('game_roll_result', first)
        # ----

        # choose girls -->
        from . import characters
        chars = characters.get_characters('faith')
        g.random.shuffle(chars)

        # ANCHOR(test)
        testing = list(settings.TESTING_CHARACTERS)
        testing = filter_out(chars, lambda c: c.__name__ in testing)
        chars = g.random.sample(chars, 30 - len(testing))
        chars.extend(testing)

        if Game.SERVER_SIDE:
            choices = [CharChoice(cls) for cls in chars[-24:]]
        else:
            choices = [CharChoice(None) for _ in xrange(24)]

        del chars[-24:]

        for p in g.players:
            c = choices[-3:]
            del choices[-3:]
            akari = CharChoice(characters.akari.Akari)
            akari.real_cls = chars.pop()
            c.append(akari)
            p.choices = c
            p.choices_chosen = []
            p.reveal(c)

        mapping = {p: p.choices for p in g.players}

        rst = user_input(g.players, SortCharacterInputlet(g, mapping, 2), timeout=30, type='all')
        for p in g.players:
            p.choices_chosen = [mapping[p][i] for i in rst[p][:2]]

        for p in g.players:
            a, b = p.choices_chosen
            b.chosen = None
            p.force.reveal(b)
            g.switch_character(p, a)
            p.force.pool.append(b)
            del p.choices_chosen

        for p in g.players:
            if p.player is first:
                first = p
                break

        pl = g.players
        first_index = pl.index(first)
        order = BatchList(range(len(pl))).rotate_to(first_index)

        for p in pl:
            g.process_action(RevealIdentity(p, pl))

        g.emit_event('game_begin', g)

        for p in pl:
            g.process_action(DistributeCards(p, amount=4))

        pl = g.players.rotate_to(first)
        rst = user_input(pl[1:], ChooseOptionInputlet(DeathHandler(), (False, True)), type='all')

        for p in pl[1:]:
            rst.get(p) and g.process_action(RedrawCards(p, p))

        pl = g.players
        for i, idx in enumerate(cycle(order)):
            if i >= 6000: break
            p = pl[idx]
            if p.dead: continue

            g.emit_event('player_turn', p)
            try:
                g.process_action(PlayerTurn(p))
            except InterruptActionFlow:
                pass

        return True
Esempio n. 43
0
 def sysmsg():
     while True:
         users = BatchList(self.users.values())
         users.write(['system_msg', [None, u'游戏已经更新,当前的游戏结束后将会被自动踢出,请更新后重新游戏']])
         gevent.sleep(30)
Esempio n. 44
0
    def game_start(g):
        # game started, init state
        from cards import Deck

        g.deck = Deck()

        g.ehclasses = list(action_eventhandlers) + g.game_ehs.values()

        # reseat
        seed = get_seed_for(g.players)
        random.Random(seed).shuffle(g.players)
        g.emit_event('reseat', None)

        H, M = Identity.TYPE.HAKUREI, Identity.TYPE.MORIYA
        L = [[H, H, M, M, H, M], [H, M, H, M, H, M]]
        rnd = random.Random(get_seed_for(g.players))
        L = rnd.choice(L) * 2
        s = rnd.randrange(0, 6)
        idlist = L[s:s+6]
        del H, M, L, s, rnd

        for p, identity in zip(g.players, idlist):
            p.identity = Identity()
            p.identity.type = identity
            g.process_action(RevealIdentity(p, g.players))

        force_hakurei = BatchList()
        force_moriya = BatchList()
        force_hakurei.pool = []
        force_moriya.pool = []

        for p in g.players:
            if p.identity.type == Identity.TYPE.HAKUREI:
                force_hakurei.append(p)
                p.force = force_hakurei
            elif p.identity.type == Identity.TYPE.MORIYA:
                force_moriya.append(p)
                p.force = force_moriya

        g.forces = BatchList([force_hakurei, force_moriya])

        # ----- roll ------
        roll = range(len(g.players))
        g.random.shuffle(roll)
        pl = g.players
        roll = sync_primitive(roll, pl)
        roll = [pl[i] for i in roll]
        g.emit_event('game_roll', roll)
        first = roll[0]
        g.emit_event('game_roll_result', first)
        # ----

        # choose girls -->
        from . import characters
        chars = list(characters.characters)
        g.random.shuffle(chars)

        if Game.SERVER_SIDE:
            choices = [CharChoice(cls) for cls in chars[-24:]]
        else:
            choices = [CharChoice(None) for _ in xrange(24)]

        del chars[-24:]

        for p in g.players:
            c = choices[-3:]
            del choices[-3:]
            akari = CharChoice(characters.akari.Akari)
            akari.real_cls = chars.pop()
            c.append(akari)
            p.choices = c
            p.choices_chosen = []
            p.reveal(c)

        mapping = {p: p.choices for p in g.players}
        remaining = {p: 2 for p in g.players}

        deadline = time.time() + 30
        with InputTransaction('ChooseGirl', g.players, mapping=mapping) as trans:
            while True:
                pl = [p for p in g.players if remaining[p]]
                if not pl: break

                p, c = user_input(
                    pl, ChooseGirlInputlet(g, mapping),
                    timeout=deadline - time.time(),
                    trans=trans, type='any'
                )
                p = p or pl[0]

                c = c or [_c for _c in p.choices if not _c.chosen][0]
                c.chosen = p
                p.choices.remove(c)
                p.choices_chosen.append(c)
                remaining[p] -= 1

                trans.notify('girl_chosen', c)

        for p in g.players:
            a, b = p.choices_chosen
            b.chosen = None
            p.force.reveal(b)
            g.switch_character(p, a)
            p.force.pool.append(b)
            del p.choices_chosen

        for p in g.players:
            if p.player is first:
                first = p
                break

        try:
            pl = g.players
            first_index = pl.index(first)
            order = BatchList(range(len(pl))).rotate_to(first_index)

            for p in pl:
                g.process_action(RevealIdentity(p, pl))

            g.emit_event('game_begin', g)

            for p in pl:
                g.process_action(DrawCards(p, amount=4))

            pl = g.players.rotate_to(first)
            rst = user_input(pl[1:], ChooseOptionInputlet(DeathHandler(), (False, True)), type='all')

            for p in pl[1:]:
                rst.get(p) and g.process_action(RedrawCards(p, p))

            pl = g.players
            for i, idx in enumerate(cycle(order)):
                if i >= 6000: break
                p = pl[idx]
                if p.dead: continue

                g.emit_event('player_turn', p)
                try:
                    g.process_action(PlayerTurn(p))
                except InterruptActionFlow:
                    pass

        except GameEnded:
            pass

        log.info(u'>> Winner: %s', Identity.TYPE.rlookup(g.winners[0].identity.type))
Esempio n. 45
0
class Client(Endpoint, Greenlet):
    def __init__(self, sock, addr):
        Endpoint.__init__(self, sock, addr)
        Greenlet.__init__(self)
        self.observers = BatchList()
        self.gamedata = Gamedata()
        self.cmd_listeners = defaultdict(WeakSet)
        self.current_game = None

    @log_failure(log)
    def _run(self):
        self.account = None

        # ----- Banner -----
        from settings import VERSION
        self.write(['thbattle_greeting', (options.node, VERSION)])
        # ------------------

        self.state = 'connected'
        while True:
            try:
                hasdata = False
                with Timeout(90, False):
                    cmd, data = self.read()
                    hasdata = True

                if not hasdata:
                    self.close()
                    # client should send heartbeat periodically
                    raise EndpointDied

                if cmd == 'gamedata':
                    self.gamedata.feed(data)
                else:
                    self.handle_command(cmd, data)

            except EndpointDied:
                self.gbreak()
                break

            except Exception:
                log.exception("Error occurred when handling client command")

        # client died, do clean ups
        self.handle_drop()

    def close(self):
        Endpoint.close(self)
        self.kill(EndpointDied)

    def __repr__(self):
        acc = self.account
        if not acc:
            return Endpoint.__repr__(self)

        return '%s:%s:%s' % (
            self.__class__.__name__,
            self.address[0],
            acc.username.encode('utf-8'),
        )

    def __data__(self):
        return dict(
            account=self.account,
            state=self.state,
        )

    def __eq__(self, other):
        return self.account is other.account

    def listen_command(self, *cmds):
        listeners_set = self.cmd_listeners
        q = Queue(100)
        for cmd in cmds:
            listeners_set[cmd].add(q)

        return q

    def handle_command(self, cmd, data):
        f = getattr(self, 'command_' + str(cmd), None)
        if not f:
            listeners = self.cmd_listeners[cmd]
            if listeners:
                [l.put(data) for l in listeners]
                return

            log.debug('No command %s', cmd)
            self.write(['invalid_command', [cmd, data]])
            return

        for_state = getattr(f, 'for_state', None)
        if for_state and self.state not in for_state:
            log.debug('Command %s is for state %s, called in %s', cmd, for_state, self.state)
            self.write(['invalid_command', [cmd, data]])
            return

        if not isinstance(data, (list, tuple)):
            log.error('Malformed command: %s %s', cmd, data)
            return

        n = f.__code__.co_argcount - 1
        if n != len(data):
            log.error(
                'Command "%s" argcount mismatch, expect %s, got %s',
                cmd, n, len(data)
            )
        else:
            f(*data)

    def handle_drop(self):
        if self.state not in ('connected', 'hang'):
            lobby.exit_game(self, is_drop=True)

        if self.state != 'connected':
            lobby.user_leave(self)

    def gexpect(self, tag, blocking=True):
        tag, data = self.gamedata.gexpect(tag, blocking)
        if tag:
            manager = GameManager.get_by_user(self)
            manager.record_user_gamedata(self, tag, data)

        return tag, data

    def gwrite(self, tag, data):
        log.debug('GAME_WRITE: %s -> %s', self.account.username, repr([tag, data]))

        manager = GameManager.get_by_user(self)
        manager.record_gamedata(self, tag, data)

        encoded = self.encode(['gamedata', [tag, data]])
        self.raw_write(encoded)
        self.observers and self.observers.raw_write(encoded)

    def gbreak(self):
        return self.gamedata.gbreak()

    def gclear(self):
        self.gamedata = Gamedata()

    def for_state(*state):
        def register(f):
            f.for_state = state
            return f

        return register

    # --------- Handlers ---------
    @for_state('connected')
    def command_auth(self, login, password):
        if self.account:
            self.write(['invalid_command', ['auth', '']])
            return

        acc = Account.authenticate(login, password)
        if acc:
            self.account = acc
            if not acc.available():
                self.write(['auth_result', 'not_available'])
                self.close()
            else:
                self.write(['auth_result', 'success'])
                self.account = acc
                lobby.user_join(self)

        else:
            self.write(['auth_result', 'invalid_credential'])

    @for_state('hang')
    def command_create_game(self, _type, name, invite_only):
        manager = lobby.create_game(self, _type, name, invite_only)
        manager.add_invited(self)
        manager and lobby.join_game(self, manager.gameid)

    @for_state('hang')
    def command_quick_start_game(self):
        lobby.quick_start_game(self)

    @for_state('hang')
    def command_join_game(self, gameid):
        lobby.join_game(self, gameid)

    def command_get_lobbyinfo(self):
        lobby.send_lobbyinfo([self])

    @for_state('hang')
    def command_observe_user(self, uid):
        lobby.observe_user(self, uid)

    @for_state('hang')
    def command_query_gameinfo(self, gid):
        lobby.send_gameinfo(self, gid)

    @for_state('inroomwait')
    def command_get_ready(self):
        lobby.get_ready(self)

    @for_state('inroomwait')
    def command_set_game_param(self, key, value):
        lobby.set_game_param(self, key, value)

    @for_state('inroomwait', 'ready', 'ingame', 'observing')
    def command_exit_game(self):
        lobby.exit_game(self)

    @for_state('inroomwait', 'ready')
    def command_kick_user(self, uid):
        lobby.kick_user(self, uid)

    @for_state('inroomwait', 'ready')
    def command_invite_user(self, uid):
        lobby.invite_user(self, uid)

    @for_state('inroomwait', 'ready', 'ingame')
    def command_kick_observer(self, uid):
        lobby.kick_observer(self, uid)

    @for_state('inroomwait', 'observing')
    def command_change_location(self, loc):
        lobby.change_location(self, loc)

    @for_state('ready')
    def command_cancel_ready(self):
        lobby.cancel_ready(self)

    def command_heartbeat(self):
        pass

    @for_state('hang', 'inroomwait', 'ready', 'ingame', 'observing')
    def command_chat(self, text):
        lobby.chat(self, text)

    @for_state('hang', 'inroomwait', 'ready', 'ingame', 'observing')
    def command_speaker(self, text):
        lobby.speaker(self, text)

    del for_state
Esempio n. 46
0
class Client(Endpoint, GamedataMixin, Greenlet):
    def __init__(self, sock, addr):
        Endpoint.__init__(self, sock, addr)
        Greenlet.__init__(self)
        self.observers = BatchList()
        self.init_gamedata_mixin()
        self.gdhistory = []
        self.usergdhistory = []

    @log_failure(log)
    def _run(self):
        self.account = None

        # ----- Banner -----
        from settings import VERSION
        self.write(['thbattle_greeting', VERSION])
        # ------------------

        self.state = 'connected'
        while True:
            try:
                hasdata = False
                with Timeout(30, False):
                    cmd, data = self.read()
                    hasdata = True

                if not hasdata:
                    self.close()
                    # client should send heartbeat periodically
                    raise EndpointDied

                if cmd == 'gamedata':
                    self.gamedata(data)
                else:
                    self.handle_command(cmd, data)

            except EndpointDied:
                self.gbreak()
                break

        # client died, do clean ups
        self.handle_drop()

    def gexpect(self, tag, blocking=True):
        tag, data = GamedataMixin.gexpect(self, tag, blocking)
        tag and self.usergdhistory.append((self.player_index, tag, data))
        return tag, data

    def gwrite(self, tag, data):
        log.debug('GAME_WRITE: %s', repr([tag, data]))
        encoded = self.encode(['gamedata', [tag, data]])
        self.raw_write(encoded)
        self.gdhistory.append([tag, json.loads(self.encode(data))])
        self.observers and self.observers.raw_write(encoded)

    def replay(self, ob):
        for data in self.gdhistory:
            ob.raw_write(json.dumps(['gamedata', data]) + '\n')

    def __data__(self):
        return [self.account.userid, self.account.username, self.state]

    def close(self):
        Endpoint.close(self)
        self.kill(EndpointDied)

    def __repr__(self):
        acc = self.account
        if not acc:
            return Endpoint.__repr__(self)

        return '%s:%s:%s' % (
            self.__class__.__name__,
            self.address[0],
            acc.username.encode('utf-8'),
        )