예제 #1
0
 def __init__(self, user_id, game_name):
     db = DBSession()
     self.user_name = db.query(User.name).filter(User.id == user_id).one()[0]
     self.game_name = game_name
     self.connections = []
     self.game = None
     
     self.mud = MudClient()
     self.mud.on_connected = self.mud_connected
     self.mud.on_failed_to_connect = self.mud_failed_to_connect
     self.mud.on_disconnected = self.mud_disconnected
     self.mud.on_line_received = self.mud_line
     self.mud.on_gmcp_message_received = self.mud_gmcp_message
     
     self.processor = None
     self._loaded_processors = {}
예제 #2
0
class ConsoleSession(object):
    """
    A session of the user with the engine.
    
    User can be connected to the engine through one or more physical consoles,
    which all share the same output and can be treated as one abstract console.
    The connection between such abstract console and the engine is what
    this class represents.
    """
    def __init__(self, user_id, game_name):
        db = DBSession()
        self.user_name = db.query(User.name).filter(User.id == user_id).one()[0]
        self.game_name = game_name
        self.connections = []
        self.game = None
        
        self.mud = MudClient()
        self.mud.on_connected = self.mud_connected
        self.mud.on_failed_to_connect = self.mud_failed_to_connect
        self.mud.on_disconnected = self.mud_disconnected
        self.mud.on_line_received = self.mud_line
        self.mud.on_gmcp_message_received = self.mud_gmcp_message
        
        self.processor = None
        self._loaded_processors = {}
        
    def close(self):
        if self.mud.connecting or self.mud.connected:
            self.mud.disconnect()
        self.game = None
        if self.processor:
            self.processor.shutdown()
            self.processor = None
        
    def send(self, message):
        """Send a raw text message to the console."""
        for c in self.connections:
            c.send(message)
            
    def to_console(self, message):
        """Send a JSON serialized message to the console."""
        serialized_message = json.dumps(message)
        self.send(serialized_message)
     
    def to_mud(self, message, type='raw'):
        try:
            encoded_message = str(message)
        except UnicodeEncodeError:
            return self.system_message("Text messages containing non-ANSI "
                                       "characters are not allowed.")
        if type == 'raw':
            self.mud.send(encoded_message + '\n')
        elif type == 'gmcp':
            self.mud.send_gmcp(encoded_message)
        
    def system_message(self, text):
        self.to_console(dict(type='system', text=text))
    
    def mud_connected(self):
        self.system_message("Connected to the mud.")
        # @@ Check if GMCP is enabled
        # @@ Move the hardcoded values out
        # @@ Probably move the whole line somewhere more suitable
        self.mud.send_gmcp('Core.Hello { "client": "mudwyrm", "version": "0.3" }')
        
    def mud_failed_to_connect(self):
        self.system_message("Couldn't connect to the mud.")
        
    def mud_disconnected(self):
        self.system_message("Disconnected from the mud.")
        
    def mud_line(self, line):
        self.processor.from_mud(line, 'raw')
        
    def mud_gmcp_message(self, message):
        self.processor.from_mud(message, 'gmcp')
    
    def handle_message(self, message):
        message = json.loads(message)
        if message['type'] == 'text':
            s = message['text']
            if s.startswith('/'):
                a = s[1:].split(' ')
                self.execute_command(a[0], *a[1:])
                return
        if self.mud.connected:
            self.processor.from_console(message)
        else:
            self.system_message("Not connected to the mud.")
    
    def execute_command(self, name, *args):
        """Execute a console command."""
        try:
            f = self.__getattribute__(name)
        except AttributeError:
            self.system_message("No such command.")
            return
        try:
            ConsoleCommand.check(f, args)
        except ConsoleCommand.NotACommand:
            self.system_message("No such command.")
            return
        except ConsoleCommand.ArgsMismatch:
            self.system_message("Invalid command arguments provided.")
            return
        f(*args)
            
    def _create_processor(self, user_name, game_name):
        from processor import load_processor
        Processor = load_processor(user_name, game_name, reload=True)
        if Processor is None:
            return None
        return Processor(self.to_mud, self.to_console)
        
    def _get_processor(self, user_name, game_name):
        key = (user_name, game_name)
        processor = self._loaded_processors.get(key, None)
        if not processor:
            processor = self._create_processor(user_name, game_name)
            self._loaded_processors[key] = processor
        else:
            processor.reload()
        return processor
    
    @ConsoleCommand('command')
    def help(self, command):
        """Show a help message about a command."""
        try:
            f = self.__getattribute__(command)
        except AttributeError:
            self.system_message("No such command.")
        try:
            ConsoleCommand.check(f)
        except ConsoleCommand.NotACommand:
            self.system_message("No such command.")
        self.system_message(ConsoleCommand.help_message(f))
        
    @ConsoleCommand()
    def connect(self):
        """Open a game session and connect to the mud server."""
        if self.mud.connected or self.mud.connecting:
            return self.system_message("Close the current session first.")
        db = DBSession()
        game = db.query(Game).filter(Game.name == self.game_name).first()
        if game is None:
            return self.system_message("Game named '%s' does not exist." % self.game_name)
        self.system_message("Loading game session '%s'..." % game.name)
        self.processor = self._get_processor(self.user_name, game.name)
        if self.processor is None:
            return self.system_message("Couldn't load a processor for that session.")
        self.game = game
        self.mud.connect(self.game.address, self.game.port)
        self.system_message("Game session '%s' has been opened." % game.name)
        self.system_message("Trying to connect to the mud...")
        
    @ConsoleCommand()
    def disconnect(self):
        """Disconnect from the mud server and close the current game session."""
        if not self.mud.connecting and not self.mud.connected:
            return self.system_message("Not connected to the mud.")
        if self.mud.connecting:
            self.system_message("Aborting a connection attempt.")
        self.close()
        self.system_message("Game session '%s' has been closed." % self.game_name)

    @ConsoleCommand()
    def reload(self):
        """Reload the scripts for the current game session."""
        if self.game is None:
            return self.system_message("There is no active game session to reload.")
        self.system_message("Reloading scripts...")
        self.processor.reload()
        self.system_message("Scripts have been reloaded.")