Expand logging for User class methods
[mudpy.git] / mudpy / misc.py
index 3cd8e64..6b24e1b 100644 (file)
@@ -64,8 +64,9 @@ class Element:
 
     def reload(self):
         """Create a new element and replace this one."""
-        Element(self.key, self.universe, self.origin)
-        del(self)
+        args = (self.key, self.universe, self.origin)
+        self.destroy()
+        Element(*args)
 
     def destroy(self):
         """Remove an element from the universe and destroy it."""
@@ -363,23 +364,9 @@ class Universe:
         # it's possible for this to enter before logging configuration is read
         pending_loglines = []
 
-        # the files dict must exist and filename needs to be read-only
-        if not hasattr(
-           self, "files"
-           ) or not (
-            self.filename in self.files and self.files[
-                self.filename
-            ].is_writeable()
-        ):
-
-            # clear out all read-only files
-            if hasattr(self, "files"):
-                for data_filename in list(self.files.keys()):
-                    if not self.files[data_filename].is_writeable():
-                        del self.files[data_filename]
-
-            # start loading from the initial file
-            mudpy.data.Data(self.filename, self)
+        # start populating the (re)files dict from the base config
+        self.files = {}
+        mudpy.data.Data(self.filename, self)
 
         # load default storage locations for groups
         if hasattr(self, "contents") and "mudpy.filing" in self.contents:
@@ -404,17 +391,6 @@ class Universe:
             if user.avatar in inactive_avatars:
                 inactive_avatars.remove(user.avatar)
 
-        # go through all elements to clear out inactive avatar locations
-        for element in self.contents.values():
-            area = element.get("location")
-            if element in inactive_avatars and area:
-                if area in self.contents and element.key in self.contents[
-                   area
-                   ].contents:
-                    del self.contents[area].contents[element.key]
-                element.set("default_location", area)
-                element.remove_facet("location")
-
         # another pass to straighten out all the element contents
         for element in self.contents.values():
             element.update_location()
@@ -531,15 +507,10 @@ class User:
     def quit(self):
         """Log, close the connection and remove."""
         if self.account:
-            name = self.account.get("name")
+            name = self.account.get("name", self)
         else:
-            name = ""
-        if name:
-            message = "User " + name
-        else:
-            message = "An unnamed user"
-        message += " logged out."
-        log(message, 2)
+            name = self
+        log("Logging out %s" % name, 2)
         self.deactivate_avatar()
         self.connection.close()
         self.remove()
@@ -584,26 +555,30 @@ class User:
     def reload(self):
         """Save, load a new user and relocate the connection."""
 
+        # copy old attributes
+        attributes = self.__dict__
+
         # get out of the list
         self.remove()
 
+        # get rid of the old user object
+        del(self)
+
         # create a new user object
         new_user = User()
 
         # set everything equivalent
-        for attribute in vars(self).keys():
-            exec("new_user." + attribute + " = self." + attribute)
+        new_user.__dict__ = attributes
 
         # the avatar needs a new owner
         if new_user.avatar:
+            new_user.account = universe.contents[new_user.account.key]
+            new_user.avatar = universe.contents[new_user.avatar.key]
             new_user.avatar.owner = new_user
 
         # add it to the list
         universe.userlist.append(new_user)
 
-        # get rid of the old user object
-        del(self)
-
     def replace_old_connections(self):
         """Disconnect active users with the same name."""
 
@@ -668,8 +643,8 @@ class User:
                 log("Administrator %s authenticated." %
                     self.account.get("name"), 2)
             else:
-                # log("User %s authenticated." % self.account.get("name"), 2)
-                log("User %s authenticated." % self.account.subkey, 2)
+                log("User %s authenticated for account %s." % (
+                        self, self.account.subkey), 2)
 
     def show_menu(self):
         """Send the user their current menu."""
@@ -697,6 +672,7 @@ class User:
 
     def remove(self):
         """Remove a user from the list of connected users."""
+        log("Disconnecting account %s." % self, 0)
         universe.userlist.remove(self)
 
     def send(
@@ -863,11 +839,15 @@ class User:
             mudpy.telnet.negotiate_telnet_options(self)
 
             # separate multiple input lines
-            new_input_lines = self.partial_input.split(b"\n")
+            new_input_lines = self.partial_input.split(b"\r\0")
+            if len(new_input_lines) == 1:
+                new_input_lines = new_input_lines[0].split(b"\r\n")
 
             # if input doesn't end in a newline, replace the
             # held partial input with the last line of it
-            if not self.partial_input.endswith(b"\n"):
+            if not (
+                    self.partial_input.endswith(b"\r\0") or
+                    self.partial_input.endswith(b"\r\n")):
                 self.partial_input = new_input_lines.pop()
 
             # otherwise, chop off the extra null input and reset
@@ -924,11 +904,15 @@ class User:
             universe)
         self.avatar.append("inherit", "archetype.avatar")
         self.account.append("avatars", self.avatar.key)
+        log("Created new avatar %s for user %s." % (
+                self.avatar.key, self.account.get("name")), 0)
 
     def delete_avatar(self, avatar):
         """Remove an avatar from the world and from the user's list."""
         if self.avatar is universe.contents[avatar]:
             self.avatar = None
+        log("Deleting avatar %s for user %s." % (
+                avatar, self.account.get("name")), 0)
         universe.contents[avatar].destroy()
         avatars = self.account.get("avatars")
         avatars.remove(avatar)
@@ -940,11 +924,16 @@ class User:
             self.account.get("avatars")[index]]
         self.avatar.owner = self
         self.state = "active"
+        log("Activated avatar %s (%s)." % (
+                self.avatar.get("name"), self.avatar.key), 0)
         self.avatar.go_home()
 
     def deactivate_avatar(self):
         """Have the active avatar leave the world."""
         if self.avatar:
+            log("Deactivating avatar %s (%s) for user %s." % (
+                    self.avatar.get("name"), self.avatar.key,
+                    self.account.get("name")), 0)
             current = self.avatar.get("location")
             if current:
                 self.avatar.set("default_location", current)
@@ -962,6 +951,8 @@ class User:
         """Destroy the user and associated avatars."""
         for avatar in self.account.get("avatars"):
             self.delete_avatar(avatar)
+        log("Destroying account %s for user %s." % (
+                self.account.get("name"), self), 0)
         self.account.destroy()
 
     def list_avatar_names(self):
@@ -1414,12 +1405,13 @@ def on_pulse():
 
 def reload_data():
     """Reload all relevant objects."""
-    for user in universe.userlist[:]:
-        user.reload()
-    for element in universe.contents.values():
-        if element.origin.is_writeable():
-            element.reload()
+    universe.save()
+    old_userlist = universe.userlist[:]
+    for element in list(universe.contents.values()):
+        element.destroy()
     universe.load()
+    for user in old_userlist:
+        user.reload()
 
 
 def check_for_connection(listening_socket):
@@ -1432,13 +1424,14 @@ def check_for_connection(listening_socket):
         return None
 
     # note that we got one
-    log("Connection from " + address[0], 2)
+    log("New connection from %s." % address[0], 2)
 
     # disable blocking so we can proceed whether or not we can send/receive
     connection.setblocking(0)
 
     # create a new user object
     user = User()
+    log("Instantiated %s for %s." % (user, address[0]), 0)
 
     # associate this connection with it
     user.connection = connection