def _send_invite_to_player(self): my_lobby = self.parent() user_id = my_lobby.user_id my_entry = users.get_user_entry(user_id) my_avatar = my_entry.avatar player = self.players[self.player_pos] other_entry = users.get_user_entry(player) other_avatar = other_entry.avatar if other_entry.invited_id is not None: my_avatar.send_message( "'{}' has already been invited to a session.".format(player)) self.uninstall_dialog() return if other_entry.joined_id is not None: my_avatar.send_message( "'{}' has already joined a session.".format(player)) self.uninstall_dialog() return if other_entry.app_protocol is None: my_avatar.send_message("'{}' has left the lobby.".format(player)) self.uninstall_dialog() return other_entry.invited_id = my_entry.joined_id other_entry.app_protocol.lobby.receive_invitation() my_avatar.send_message("Sent invite to '{}'.".format(player)) my_lobby.lobby.send_invitation() my_lobby.pending_invitations.add(player) self.uninstall_dialog()
def _invite(self): """ Invite another player or players to join a session. """ this_player = self.user_id my_entry = users.get_user_entry(this_player) fltr = lambda e: (e.invited_id is None) and (e.joined_id is None) and ( not e.app_protocol is None) players = set( [e.user_id for e in users.generate_user_entries(fltr=fltr)]) players.discard(this_player) if len(players) == 0: self.output.append("No other players to invite at this time.") self.update_display() return players = list(players) players.sort() user_entry = users.get_user_entry(this_player) if my_entry.joined_id is None: session_entry = session.create_session() user_entry.joined_id = session_entry.session_id session_entry.owner = this_player session_entry.members.add(this_player) self.lobby.create_session() dialog = ChoosePlayerDialog.make_dialog(players) self.install_dialog(dialog)
def _reject_invitation(self): user_id = self.user_id my_entry = users.get_user_entry(user_id) session_id = my_entry.invited_id my_entry.invited_id = None self.lobby.reject() session_entry = session.get_entry(session_id) owner = session_entry.owner owner_entry = users.get_user_entry(owner) owner_avatar = owner_entry.avatar owner_avatar.send_app_signal(('invite-cancelled', user_id)) owner_avatar.send_message( "{} rejected your invitation.".format(user_id))
def _leave_session(self): user_id = self.user_id my_entry = users.get_user_entry(user_id) session_id = my_entry.joined_id my_entry.joined_id = None session_entry = session.get_entry(session_id) session_entry.members.discard(user_id) self.lobby.cancel() members = set(session_entry.members) members.discard(user_id) msg = "{} left session {}.".format(user_id, session_id) for player in members: user_entry = users.get_user_entry(player) avatar = user_entry.avatar avatar.send_message(msg)
def init_app_protocol(self): """ Initialize an application protocol if one does not exist. The application protocol will be term-based, and it is the thing the client will interact with. E.g. a lobby or a game. All the other components exist only to connect the client to the app protocol. """ user_id = self.user_id entry = users.get_user_entry(user_id) app_protocol = entry.app_protocol if app_protocol is None: app_protocol = lobby.SSHLobbyProtocol.make_instance( self.reactor, self.terminal, user_id, self ) else: app_protocol = app_protocol.produce_compatible_application( ITerminalApplication, parent=self) entry.app_protocol = app_protocol app_protocol = entry.app_protocol app_protocol.reactor = self.reactor app_protocol.terminal = self.terminal app_protocol.term_size = self.term_size self.app_protocol = app_protocol app_protocol.parent = weakref.ref(self) def _request_refresh(terminal, app_protocol): terminal.reset() app_protocol.update_display() self.reactor.callLater(0, _request_refresh, self.terminal, app_protocol)
def _start_session(self): user_id = self.user_id my_entry = users.get_user_entry(user_id) session_id = my_entry.joined_id session_entry = session.get_entry(session_id) for player in self.pending_invitations: player_entry = users.get_user_entry(player) player_entry.app_protocol.lobby.revoke_invitation() msg = "Session '{}' was started. Your invitation has been revoked.".format( session_id) player_entry.app_protocol.output.append(msg) player_entry.invited_id = None player_entry.app_protocol.update_display() members = session_entry.members for member in members: entry = users.get_user_entry(member) entry.app_protocol.lobby.start_session()
def _shutdown_session(self): user_id = self.user_id user_entry = users.get_user_entry(user_id) session_id = user_entry.joined_id if session_id is None: return signal = ('shutdown', {'initiator': user_id}) session.send_signal_to_members(session_id, signal)
def install_application(self, proto): if not ITerminalApplication.providedBy(proto): proto = proto.produce_compatible_application( ITerminalApplication, parent=self) self.app_protocol = proto self.terminal.reset() self.reactor.callLater(0, proto.update_display) user_entry = users.get_user_entry(self.user_id) user_entry.app_protocol = proto
def install_application(self, app_protocol): if not IWebApplication.providedBy(app_protocol): app_protocol = app_protocol.produce_compatible_application( IWebApplication, parent=self) entry = users.get_user_entry(self.user_id) entry.app_protocol = app_protocol data = {'install-app': app_protocol.resource} command_str = json.dumps(data) self.send_event_to_client(command_str)
def _accept_invitation(self): user_id = self.user_id my_entry = users.get_user_entry(user_id) session_id = my_entry.invited_id session_entry = session.get_entry(session_id) owner = session_entry.owner owner_entry = users.get_user_entry(owner) my_entry.joined_id = session_id my_entry.invited_id = None session_entry.members.add(user_id) self.lobby.accept() pending_invitations = owner_entry.app_protocol.pending_invitations pending_invitations.discard(user_id) members = set(session_entry.members) members.discard(user_id) members = members.union(pending_invitations) msg = "{} joined session {}.".format(user_id, session_id) for player in members: user_entry = users.get_user_entry(player) avatar = user_entry.avatar avatar.send_message(msg)
def _send_invite(self, player): my_avatar = self.avatar my_entry = users.get_user_entry(self.user_id) other_entry = users.get_user_entry(player) other_avatar = other_entry.avatar if other_entry.invited_id is not None: my_avatar.send_message( "'{}' has already been invited to a session.".format(player)) self._uninstall_dialog() return if other_entry.joined_id is not None: my_avatar.send_message( "'{}' has already joined a session.".format(player)) self._uninstall_dialog() return other_entry.invited_id = my_entry.joined_id other_entry.app_protocol.appstate.receive_invitation() my_avatar.send_message("Sent invite to '{}'.".format(player)) self.lobby.send_invitation() self.pending_invitations.add(player) self._uninstall_dialog()
def _signal_dialogs_redraw(self): user_id = self.user_id user_entry = users.get_user_entry(user_id) session_id = user_entry.joined_id or user_entry.invited_id if session_id is None: self.uninstall_dialog() return signal = ('chat-message', {'sender': self.user_id}) session.send_signal_to_members(session_id, signal, include_invited=True, exclude=set([user_id]))
def _cancel_session(self): user_id = self.user_id my_entry = users.get_user_entry(user_id) session_id = my_entry.joined_id session_entry = session.get_entry(session_id) members = session_entry.members session.destroy_entry(session_id) msg = "{} cancelled the session.".format(user_id) for member in members: entry = users.get_user_entry(member) entry.joined_id = None entry.invited_id = None entry.avatar.send_message(msg) entry.app_protocol.appstate.cancel() pending_invitations = self.pending_invitations for player in pending_invitations: entry = users.get_user_entry(player) entry.joined_id = None entry.invited_id = None entry.avatar.send_message(msg) entry.app_protocol.appstate.revoke_invitation()
def logoff(self): """ Log off the avatar. This destroys both the avatar and the user application state. """ log.msg("Called `logoff()` for {}".format(self)) user_id = self.user_id user_entry = users.get_user_entry(user_id) user_entry.avatar = None user_entry.app_protocol = None user_entry.joined_id = None user_entry.invited_id = None
def _handle_new_chat(self): user_entry = users.get_user_entry(self.user_id) session_id = user_entry.joined_id if session_id is None: session_id = user_entry.invited_id session_entry = session.get_entry(session_id) output_buf = session_entry.chat_buf sender, msg = output_buf[-1] avatar = user_entry.avatar event = {'chat': {'sender': sender, 'message': msg}} event_str = json.dumps(event) avatar.send_event_to_client(event_str)
def handle_accepted(self): my_entry = users.get_user_entry(self.user_id) self.status = "Joined session '{}'".format(my_entry.joined_id) self.instructions = textwrap.dedent("""\ Valid commands are: * (j)oined - List players that have joined the session. * (c)ancel - Leave the session. """) self.commands = { 'j': self._show_joined, 'c': self._leave_session, } self.update_display()
def handle_invited(self): user_entry = users.get_user_entry(self.user_id) self.status = "Invited to join session '{}'.".format( user_entry.invited_id) self.instructions = textwrap.dedent("""\ Valid commands are: * (a)ccept - Accept invitation to join session. * (r)eject - Reject invitation to join session. """) self.commands = { 'a': self._accept_invitation, 'r': self._reject_invitation, } self.update_display()
def handle_accepted(self): my_entry = users.get_user_entry(self.user_id) self.status = "Joined session '{}'".format(my_entry.joined_id) self._update_client_status() actions = [ ('List players that have joined the session.', 0, 'Members listed.'), ('Leave the session.', 1, 'You left the session.'), ] self.actions = actions self._update_client_actions() self.handlers = { 0: self._show_joined, 1: self._leave_session, }
def _show_chat(self): input_buf = self.input_buf user_id = self.user_id user_entry = users.get_user_entry(user_id) session_id = None if not user_entry.joined_id is None: session_id = user_entry.joined_id elif not user_entry.invited_id is None: session_id = user_entry.invited_id if session_id is None: return session_entry = session.get_entry(session_id) output_buf = session_entry.chat_buf dialog = ChatDialog.make_instance(input_buf, output_buf) self.install_dialog(dialog) self.new_chat_flag = False
def chat(self, request): if not check_authenticated(request): return avatar = get_avatar(request) user_id = avatar.user_id message = request.args.get(b'message')[0]; message = message.decode('utf-8') user_entry = users.get_user_entry(user_id) session_id = user_entry.joined_id or user_entry.invited_id if session_id is None: return session_entry = session.get_entry(session_id) chat_buf = session_entry.chat_buf chat_buf.append((user_id, message)) signal = ('chat-message', {'sender': user_id}) session.send_signal_to_members(session_id, signal, include_invited=True)
def handle_invited(self): user_entry = users.get_user_entry(self.user_id) avatar = self.avatar status = "Invited to join session '{}'.".format(user_entry.invited_id) self.status = status self._update_client_status() actions = [ ('Accept invitation to join session.', 0, 'Invitation accepted.'), ('Reject invitation to join session.', 1, 'Invitation rejected.'), ] self.actions = actions self._update_client_actions() self.handlers = { 0: self._accept_invitation, 1: self._reject_invitation, }
def _show_joined(self): """ List the players that have joined the session. """ user_id = self.user_id my_entry = users.get_user_entry(user_id) session_id = my_entry.joined_id session_entry = session.get_entry(session_id) members = list(session_entry.members) members.sort() lines = [] lines.append("The following players have joined the session:") for n, player in enumerate(members): lines.append("{}) {}".format(n + 1, player)) self.output.append('\n'.join(lines)) self.update_display()
def _invite(self): """ Invite another player or players to join a session. """ this_player = self.user_id my_entry = users.get_user_entry(this_player) my_avatar = my_entry.avatar fltr = lambda e: (e.invited_id is None) and (e.joined_id is None) players = set( [e.user_id for e in users.generate_user_entries(fltr=fltr)]) players.discard(this_player) if len(players) == 0: my_avatar.send_message("No other players to invite at this time.") return players = list(players) players.sort() if my_entry.joined_id is None: session_entry = session.create_session() my_entry.joined_id = session_entry.session_id session_entry.owner = this_player session_entry.members.add(this_player) self.lobby.create_session() actions = [(player, n) for n, player in enumerate(players)] dialog_handlers = {} actions = [] def _make_handler(player): def _invite(): self._send_invite(player) return _invite for n, player in enumerate(players): actions.append((player, n, '')) dialog_handlers[n] = _make_handler(player) quit_action = len(actions) actions.append(("Stop inviting players", quit_action, '')) dialog_handlers[quit_action] = self._uninstall_dialog() self.dialog_handlers = dialog_handlers command = { 'show-dialog': { 'dialog-type': 'choose-players', 'actions': actions, } } command_str = json.dumps(command) my_avatar.send_event_to_client(command_str)
def handle_waiting_for_accepts(self): user_id = self.user_id user_entry = users.get_user_entry(user_id) self.status = "Session {} - Waiting for Responses".format( user_entry.joined_id) self.instructions = textwrap.dedent("""\ Valid commands are: * (s)tart - Start the session with the current members. * (i)nvite - Invite another player. * (j)oined - Show players that have joined the session. * (c)ancel - Cancel the session. """) self.commands = { 's': self._start_session, 'i': self._invite, 'j': self._show_joined, 'c': self._cancel_session, } self.update_display()
def init_app_protocol(self): """ Initialize the default application. """ log.msg("WebAvatar initializing app protocol ...") user_id = self.user_id user_entry = users.get_user_entry(user_id) user_entry.avatar = self app_protocol = user_entry.app_protocol if app_protocol is None: log.msg("User entry has no app protocol-- creating a new one ...") app_protocol = lobby.WebLobbyProtocol.make_instance( self.reactor, user_id, self) else: log.msg("Producing compatible app ...") app_protocol = app_protocol.produce_compatible_application( IWebApplication, parent=self) log.msg("Produced compatible app.") user_entry.app_protocol = app_protocol app_protocol.reactor = self.reactor app_protocol.parent = weakref.ref(self)
def send_signal_to_members(session_id, signal, include_invited=False, exclude=None): """ Send `signal` to the session members. The signal will be propagated by member avatars to their applications. """ session_entry = get_entry(session_id) members = set(session_entry.members) if include_invited: fltr = lambda x: x.invited_id == session_id invited_ids = [x.user_id for x in users.generate_user_entries(fltr)] members = members.union(invited_ids) if not exclude is None: exclude_set = set(exclude) members = members - exclude_set for member in members: entry = users.get_user_entry(member) avatar = entry.avatar avatar.send_app_signal(signal)
def _reset_game(self): role_flags = self._get_role_flags() werewolves = self.werewolves wg = WerewolfGame deck = set([]) roles = [ ('seer', wg.CARD_SEER), ('robber', wg.CARD_ROBBER), ('troublemaker', wg.CARD_TROUBLEMAKER), ('minion', wg.CARD_MINION), ('insomniac', wg.CARD_INSOMNIAC), ('hunter', wg.CARD_HUNTER), ('tanner', wg.CARD_TANNER), ] for name, card in roles: if role_flags[name]: deck.add(card) self._settings.roles = set(deck) self._settings.werewolves = werewolves parent = self.parent() user_id = parent.user_id make_protocol = parent.__class__.make_protocol user_entry = users.get_user_entry(user_id) app_protocol = user_entry.app_protocol proto = make_protocol(user_id=user_id, terminal=app_protocol.terminal, term_size=app_protocol.term_size, parent=app_protocol.parent, reactor=app_protocol.reactor, roles=deck, werewolves=werewolves, reset=True) session_id = user_entry.joined_id avatar = parent.avatar avatar.install_application(proto) signal = ('reset', {'sender': self.user_id}) session.send_signal_to_members(session_id, signal) self.uninstall_dialog() proto.update_display()
def handle_waiting_for_accepts(self): user_id = self.user_id user_entry = users.get_user_entry(user_id) avatar = self.avatar self.status = "Session {} - Waiting for Responses".format( user_entry.joined_id) self._update_client_status() actions = [ ('Start the session with the current members.', 0, 'Session started.'), ('Invite another player', 1, 'Selecting a player ...'), ('Show players that have joined the session.', 2, 'Members listed.'), ('Cancel the session.', 3, 'Session cancelled.'), ] self.actions = actions self._update_client_actions() self.handlers = { 0: self._start_session, 1: self._invite, 2: self._show_joined, 3: self._cancel_session, }
def avatar(self): user_id = self.user_id entry = users.get_user_entry(user_id) return entry.avatar
def application(self): user_id = self.user_id user_entry = users.get_user_entry(user_id) app_protocol = user_entry.app_protocol return app_protocol