diff orpg/networking/mplay_server.py @ 15:b6c6ec28ba8a grumpy-goblin

Traipse 'OpenRPG' {090807-00} Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on code without fear of sacrifice. 'Grumpy-Goblin' was created as a stablizing branch in an effort to remove bugs from core code. Update Summary: Major improvements in the Server GUI. Server now looks through XML file for password (thanks, david), lobby name, and port. Callbacks and other previous partial implements work.
author sirebral
date Fri, 07 Aug 2009 22:06:09 -0500
parents 4385a7d0efd1
children 281ca8daa911
line wrap: on
line diff
--- a/orpg/networking/mplay_server.py	Thu Aug 06 18:09:36 2009 -0500
+++ b/orpg/networking/mplay_server.py	Fri Aug 07 22:06:09 2009 -0500
@@ -367,34 +367,29 @@
             self.configDom = minidom.parse(self.userPath + 'server_ini.xml')
             self.configDom.normalize()
             self.configDoc = self.configDom.documentElement
-            # Obtain the lobby/server password if it's been specified
-            if self.configDoc.hasAttribute("admin"):
-                self.boot_pwd = self.configDoc.getAttribute("admin")
-            elif self.configDoc.hasAttribute("boot"):
-                self.boot_pwd = self.configDoc.getAttribute("boot")
-            if hasattr(self, 'bootPassword'):
-                self.boot_pwd = self.bootPassword
-            elif len(self.boot_pwd) < 1:
-                self.boot_pwd = raw_input("Enter boot password for the Lobby:  ")
+
+            if hasattr(self, 'bootPassword'): self.boot_pwd = self.bootPassword
+
+            else:
+                if self.configDoc.hasAttribute("admin"): self.boot_pwd = self.configDoc.getAttribute("admin") 
+                elif self.configDoc.hasAttribute("boot"): self.boot_pwd = self.configDoc.getAttribute("boot") 
+
+                if len(self.boot_pwd) < 1: self.boot_pwd = raw_input("Enter admin password:  ")
+
             if not hasattr(self, 'reg') and self.configDoc.hasAttribute("register"):
                 self.reg = self.configDoc.getAttribute("register")
             if not len(self.reg) > 0 or self.reg[0].upper() not in ("Y", "N"):
                 opt = raw_input("Do you want to post your server to the OpenRPG Meta Server list? (y,n) ")
-                if len(opt) and (opt[0].upper() == 'Y'):
-                    self.reg = 'Y'
-                else:
-                    self.reg = 'N'
+                if len(opt) and (opt[0].upper() == 'Y'): self.reg = 'Y'
+                else: self.reg = 'N'
             LobbyName = 'Lobby'
-            if self.configDoc.hasAttribute("lobbyname"):
-                LobbyName = self.configDoc.getAttribute("lobbyname")
+            if self.configDoc.hasAttribute("lobbyname"): LobbyName = self.configDoc.getAttribute("lobbyname")
             map_node = service_node = self.configDoc.getElementsByTagName("map")[0]
             msg_node = service_node = self.configDoc.getElementsByTagName("message")[0]
             mapFile = map_node.getAttribute('file')
             msgFile = msg_node.getAttribute('file')
-            if mapFile == '':
-                mapFile = 'Lobby_map.xml'
-            if msgFile == '':
-                msgFile = 'LobbyMessage.html'
+            if mapFile == '': mapFile = 'Lobby_map.xml'
+            if msgFile == '': msgFile = 'LobbyMessage.html'
             # Update the lobby with the passwords if they've been specified
             if len(self.boot_pwd):
                 self.groups = {'0': game_group( '0', LobbyName, "", 'The game lobby', self.boot_pwd, "",
@@ -406,19 +401,15 @@
             service_node = self.configDoc.getElementsByTagName("service")[0]
             address = service_node.getAttribute("address")
             address = address.lower()
-            if address == "" or address == "hostname/address" or address == "localhost":
-                self.server_address = None
-            else:
-                self.server_address = address
+            if address == "" or address == "hostname/address" or address == "localhost": self.server_address = None
+            else: self.server_address = address
             self.server_port = OPENRPG_PORT
-            if service_node.hasAttribute("port"):
-                self.server_port = int(service_node.getAttribute("port"))
+            if service_node.hasAttribute("port"): self.server_port = int(service_node.getAttribute("port"))
             if self.configDoc.hasAttribute("name") and len(self.configDoc.getAttribute("name")) > 0 :
                 self.name = self.configDoc.getAttribute("name")
             else:
                 if self.reg[0].upper() == "Y":
-                    if self.name == None:
-                       self.name = raw_input("Server Name? ")
+                    if self.name == None: self.name = raw_input("Server Name? ")
                     self.register()
 
             # Get the minimum openrpg version from config if available
@@ -429,8 +420,7 @@
             try:
                 mver = self.configDoc.getElementsByTagName("version")[0]
                 self.minClientVersion = mver.getAttribute("min")
-            except:
-                self.minClientVersion = SERVER_MIN_CLIENT_VERSION #from orpg/orpg_version.py
+            except: self.minClientVersion = SERVER_MIN_CLIENT_VERSION #from orpg/orpg_version.py
             self.defaultMessageFile = ""
             # This try/except bit is to allow older versions of python to continue without a list error.
 
@@ -446,10 +436,8 @@
             try:
                 ak = self.configDoc.getElementsByTagName("autokick")[0]
                 if ak.hasAttribute("silent"):
-                    if ((ak.getAttribute("silent")).lower() == "yes"):
-                        self.silent_auto_kick = 1
-                    else:
-                        self.silent_auto_kick = 0
+                    if ((ak.getAttribute("silent")).lower() == "yes"): self.silent_auto_kick = 1
+                    else: self.silent_auto_kick = 0
                 if ak.hasAttribute("delay"):
                     try:
                         delay = int(ak.getAttribute("delay"))
@@ -497,10 +485,8 @@
                     if rpw == "no" or rpw == "0":
                         roomdefault_pass = 0
                         self.log_msg("Room Defaults: Disallowing Passworded Rooms")
-                    else:
-                        self.log_msg("Room Defaults: Allowing Passworded Rooms")
-                except:
-                    self.log_msg("Room Defaults: [Warning] Allowing Passworded Rooms")
+                    else: self.log_msg("Room Defaults: Allowing Passworded Rooms")
+                except: self.log_msg("Room Defaults: [Warning] Allowing Passworded Rooms")
                 try:
                     setting = roomdefaults.getElementsByTagName('map')[0]
                     map = setting.getAttribute('file')
@@ -514,13 +500,10 @@
                     setting = roomdefaults.getElementsByTagName('message')[0]
                     msg = setting.getAttribute('file')
                     if msg != "":
-                        if msg[:4].lower() == 'http':
-                            roomdefault_msg = msg
-                        else:
-                            roomdefault_msg = self.userPath + msg.replace("myfiles/", "")
+                        if msg[:4].lower() == 'http': roomdefault_msg = msg
+                        else: roomdefault_msg = self.userPath + msg.replace("myfiles/", "")
                         self.log_msg("Room Defaults: Using " + str(msg) + " for room messages")
-                except:
-                    print ("Room Defaults: [Warning] Using Default Message")
+                except: print ("Room Defaults: [Warning] Using Default Message")
             except:
                 traceback.print_exc()
                 self.log_msg("**WARNING** Error loading default room settings from configuration file. Using internal defaults.")
@@ -529,13 +512,11 @@
             #set the defaults
             if roomdefault_msg != "" or roomdefault_msg != None:
                 self.defaultMessageFile = roomdefault_msg  #<room_defaults> tag superceeds older <newrooms> tag
-            else:
-                self.defaultMessageFile = None
+            else: self.defaultMessageFile = None
 
             if roomdefault_map != "" or roomdefault_map != None:
                 self.defaultMapFile = roomdefault_map  #<room_defaults> tag superceeds older <newrooms> tag
-            else:
-                self.defaultMapFile = None
+            else: self.defaultMapFile = None
 
             ##### room default map not handled yet. SETTING IGNORED
             if roomdefault_pass == 0: self.allow_room_passwords = 0
@@ -559,10 +540,8 @@
 
             self.validate_protocol = 1
 
-            if(validate_protocol_node):
-                self.validate_protocol = (validate_protocol_node[0].getAttribute("value") == "True")
-            if(self.validate_protocol != 1):
-                self.log_msg("Protocol Validation: OFF")
+            if(validate_protocol_node): self.validate_protocol = (validate_protocol_node[0].getAttribute("value") == "True")
+            if(self.validate_protocol != 1): self.log_msg("Protocol Validation: OFF")
             self.makePersistentRooms()
 
             self.log_msg("Server Configuration File: Processing Completed.")
@@ -581,10 +560,8 @@
             bootPassword = element.getAttribute('boot')
 
             # Conditionally check for minVersion attribute
-            if element.hasAttribute('minVersion'):
-                minVersion = element.getAttribute('minVersion')
-            else:
-                minVersion = ""
+            if element.hasAttribute('minVersion'): minVersion = element.getAttribute('minVersion')
+            else: minVersion = ""
 
             # Extract the map filename attribute from the map node
             # we only care about the first map element found -- others are ignored
@@ -594,19 +571,15 @@
             messageElement = element.getElementsByTagName('message')[0]
             messageFile = messageElement.getAttribute('file')
 
-            if messageFile[:4] != 'http':
-                messageFile = self.userPath + messageFile.replace("myfiles/", "")
+            if messageFile[:4] != 'http': messageFile = self.userPath + messageFile.replace("myfiles/", "")
 
             # Make sure we have a message to even mess with
-            if(len(messageFile) == 0):
-                messageFile = self.defaultMessageFile
-
-            if(len(mapFile) == 0):
-                mapFile = self.defaultMapFile
+            if(len(messageFile) == 0): messageFile = self.defaultMessageFile
+
+            if(len(mapFile) == 0): mapFile = self.defaultMapFile
 
             moderated = 0
-            if element.hasAttribute('moderated') and element.getAttribute('moderated').lower() == "true":
-                moderated = 1
+            if element.hasAttribute('moderated') and element.getAttribute('moderated').lower() == "true": moderated = 1
 
             #create the new persistant group
             self.new_group(roomName, roomPassword, bootPassword, minVersion, mapFile, messageFile, persist = 1, moderated=moderated)
@@ -658,10 +631,8 @@
         else: return
         #when log mode changes update all connection stubs
         for n in self.players:
-            try:
-                self.players[n].EnableMessageLogging = mode
-            except:
-                self.log_msg("Error changing Message Logging Mode for client #" + str(self.players[n].id))
+            try: self.players[n].EnableMessageLogging = mode
+            except: self.log_msg("Error changing Message Logging Mode for client #" + str(self.players[n].id))
     def NetworkLoggingStatus(self):
         if self.log_network_messages == 0: return "Network Traffic Log: Off"
         elif self.log_network_messages == 1: return "Network Traffic Log: Logging (composite file)"
@@ -683,12 +654,11 @@
                     metacache_lock.release()
 
                 if newlist != curlist:          #  If the two lists aren't identical
-                                               #  then something has changed.
+                                                #  then something has changed.
                     instance.register()             #  Call self.register()
                                                 #  which will force a re-read of the meta cache and
                                                 #  redo the registerThreads
-        else:
-            instance.register()
+        else: instance.register()
 
                 # Eventually, reset the MetaServerBaseURL here
 
@@ -699,8 +669,7 @@
     def clean_published_servername(self, name):
         #clean name of all apostrophes and quotes
         badchars = "\"\\`><"
-        for c in badchars:
-            name = name.replace(c,"")
+        for c in badchars: name = name.replace(c,"")
         return name
 
     def registerRooms(self, args=None):
@@ -724,25 +693,20 @@
 
 
     def register(self,name_given=None):
-        if name_given == None:
-            name = self.name
-        else:
-            self.name = name = name_given
+        if name_given == None: name = self.name
+        else: self.name = name = name_given
 
         name = self.clean_published_servername(name)
 
         #  Set up the value for num_users
-        if self.players:
-            num_players = len(self.players)
-        else:
-            num_players = 0
+        if self.players: num_players = len(self.players)
+        else: num_players = 0
 
         #  request only Meta servers compatible with version 2
         metalist = getMetaServers(versions=["2"])
         if self.show_meta_messages != 0:
             self.log_msg("Found these valid metas:")
-            for meta in metalist:
-                self.log_msg("Meta:" + meta)
+            for meta in metalist: self.log_msg("Meta:" + meta)
 
         #  Go through the list and see if there is already a running register
         #  thread for the meta.
@@ -759,7 +723,7 @@
                 if self.show_meta_messages != 0: self.log_msg( "Outdated.  Unregistering and removing")
                 self.metas[meta].unregister()
                 del self.metas[meta]
-            else:
+            else: 
                 if self.show_meta_messages != 0: self.log_msg( "Found in current meta list.  Leaving intact.")
 
         #  Now call register() for alive metas or start one if we need one
@@ -786,26 +750,20 @@
         #  Instead, loop through all existing meta threads and unregister them
 
         for meta in self.metas.values():
-            if meta and meta.isAlive():
-                meta.unregister()
-
+            if meta and meta.isAlive(): meta.unregister()
         self.be_registered = 0
 
-
-
-
-    #  This method runs as it's own thread and does the group_member_check every
-    #    sixty seconds.  This should eliminate zombies that linger when no one is
-    #    around to spook them.  GC: Frequency has been reduced as I question how valid
-    #    the implementation is as it will only catch a very small segment of lingering
-    #    connections.
+        #  This method runs as it's own thread and does the group_member_check every
+        #    sixty seconds.  This should eliminate zombies that linger when no one is
+        #    around to spook them.  GC: Frequency has been reduced as I question how valid
+        #    the implementation is as it will only catch a very small segment of lingering
+        #    connections.
     def player_reaper_thread_func(self,arg):
         while self.alive:
             time.sleep(60)
 
             self.p_lock.acquire()
-            for group in self.groups.keys():
-                self.check_group_members(group)
+            for group in self.groups.keys(): self.check_group_members(group)
             self.p_lock.release()
 
     #This thread runs ever 250 miliseconds, and checks various plugin stuff
@@ -815,12 +773,8 @@
             players = ServerPlugins.getPlayer()
 
             for player in players:
-                if player is not None:
-                    #Do something here so they can show up in the chat room for non web users'
-                    pass
-
+                if player is not None: pass #Do something here so they can show up in the chat room for non web users'
             data = ServerPlugins.preParseOutgoing()
-
             for msg in data:
                 try:
                     xml_dom = parseXml(msg)
@@ -832,8 +786,7 @@
                     xml_dom.setAttribute('to', 'all')
                     self.incoming_msg_handler(xml_dom, msg)
                     xml_dom.unlink()
-                except:
-                    pass
+                except: pass
 
             self.p_lock.release()
             time.sleep(0.250)
@@ -854,25 +807,14 @@
                 sent = sock.send(slice)
                 offset += sent
             sentm = offset
-        else:
-            # Calculate our message length
-            length = len( msg )
-
-            # Encode the message length into network byte order
-            lp = pack('!i', length)
-
+        else: 
+            length = len( msg ) # Calculate our message length
+            lp = pack('!i', length) # Encode the message length into network byte order
             try:
-                # Send the encoded length
-                sentl = sock.send( lp )
-
-                # Now, send the message the the length was describing
-                sentm = sock.send( msg )
-
-            except socket.error, e:
-                self.log_msg( e )
-
-            except Exception, e:
-                self.log_msg( e )
+                sentl = sock.send( lp ) # Send the encoded length
+                sentm = sock.send( msg ) # Now, send the message the the length was describing
+            except socket.error, e: self.log_msg( e )
+            except Exception, e: self.log_msg( e )
 
 
     def recvData( self, sock, readSize ):
@@ -885,26 +827,19 @@
         try:
             while offset != readSize:
                 frag = sock.recv( readSize - offset )
-
-                # See if we've been disconnected
-                rs = len( frag )
+                rs = len( frag ) # See if we've been disconnected
                 if rs <= 0:
                     # Loudly raise an exception because we've been disconnected!
                     raise IOError, "Remote closed the connection!"
-
-                else:
-                    # Continue to build complete message
+                else: # Continue to build complete message
                     offset += rs
                     data += frag
 
         except socket.error, e:
             self.log_msg("Socket Error: recvData(): " +  e )
             data = ""
-
         return data
 
-
-
     def recvMsg(self, sock, useCompression=False, cmpType=None):
         """This method now expects to receive a message having a 4-byte prefix length.  It will ONLY read
         completed messages.  In the event that the remote's connection is terminated, it will throw an
@@ -918,26 +853,18 @@
         msgData = ""
         try:
             lenData = self.recvData( sock, MPLAY_LENSIZE )
-
             # Now, convert to a usable form
             (length,) = unpack('!i', lenData)
-
             # Read exactly the remaining amount of data
             msgData = self.recvData( sock, length )
-
             try:
-                if useCompression and cmpType != None:
-                    msgData = cmpType.decompress(msgData)
-            except:
-                traceback.print_exc()
-
-        except Exception, e:
-            self.log_msg( "Exception: recvMsg(): " + str(e) )
-
+                if useCompression and cmpType != None: msgData = cmpType.decompress(msgData)
+            except: traceback.print_exc()
+
+        except Exception, e: self.log_msg( "Exception: recvMsg(): " + str(e) )
         return msgData
 
 
-
     def kill_server(self):
         self.alive = 0
         self.log_msg("Server stopping...")
@@ -1358,6 +1285,8 @@
 
                 cmsg = "Client Connect: (" + str(props['id']) + ") " + str(props['name']) + " [" + str(props['ip']) + "]"
                 self.log_msg(cmsg)
+                cmsg = ("connect", props) #################################################
+                self.log_msg(cmsg)
 
                 #  If already registered then re-register, thereby updating the Meta
                 #    on the number of players
@@ -1864,7 +1793,7 @@
 
             #notify user about others in the room
             self.return_room_roles(from_id,group_id)
-            self.log_msg(("join_group", (from_id, group_id)))
+            self.log_msg(("join_group", (self.groups[group_id].name, group_id, from_id)))
             self.handle_role("set", from_id, self.players[from_id].role, self.groups[group_id].boot_pwd, group_id)
 
         except Exception, e:
@@ -1887,13 +1816,13 @@
     def new_group( self, name, pwd, boot, minVersion, mapFile, messageFile, persist = 0, moderated=0 ):
         group_id = str( self.next_group_id )
         self.next_group_id += 1
-
         self.groups[group_id] = game_group( group_id, name, pwd, "", boot, minVersion, mapFile, messageFile, persist )
         self.groups[group_id].moderated = moderated
         ins = ""
         if persist !=0: ins="Persistant "
         lmsg = "Creating " + ins + "Group... (" + str(group_id) + ") " + str(name)
         self.log_msg( lmsg )
+        self.log_msg(("create_group", (str(name), int(group_id), 0) )) ##-99 works, could be better.
 
 
     def change_group_name(self,gid,name,pid):
@@ -2008,6 +1937,7 @@
             self.log_msg( lmsg )
             jmsg = "moving to room " + str(group_id) + "."
             self.log_msg( jmsg )
+            self.log_msg(("create_group", (str(name), group_id, from_id)))
             #even creators of the room should see the HTML --akoman
             #edit: jan10/03 - was placed in the except statement. Silly me.
             if self.defaultMessageFile != None:
@@ -2038,7 +1968,7 @@
             if not self.isPersistentRoom(group_id)  and self.groups[group_id].get_num_players() == 0:
                 self.send_to_all("0",self.groups[group_id].toxml('del'))
                 del self.groups[group_id]
-                self.log_msg(("delete_group", (from_id, group_id)))
+                self.log_msg(("delete_group", (group_id, from_id)))
 
             else:
                 self.send_to_all("0",self.groups[group_id].toxml('update'))
@@ -2056,6 +1986,7 @@
             self.groups[group_id].remove_player(id)
             del self.players[id]
             self.log_msg(dmsg)
+            self.log_msg(("disconnect",id))
 
 
             #  If already registered then re-register, thereby updating the Meta
@@ -2465,6 +2396,7 @@
 
     def send_to_all(self,from_id,data):
         try:
+            print data
             self.p_lock.acquire()
             keys = self.players.keys()
             self.p_lock.release()
@@ -2475,15 +2407,18 @@
             traceback.print_exc()
             self.log_msg("Exception: send_to_all(): " + str(e))
 
-
-
     def send_to_group(self, from_id, group_id, data):
-        data = ServerPlugins.postParseIncoming(data)
+        msg = ("<msg to='all' from='0' group_id='"+group_id+"'><font color='#FF0000'>" + data + "</font>")
+        #data = ServerPlugins.postParseIncoming(data)
         try:
+            print data
+            self.p_lock.acquire()
             keys = self.groups[group_id].get_player_ids()
+            self.p_lock.release()
+            print keys
             for k in keys:
                 if k != from_id:
-                    self.players[k].outbox.put(data)
+                    self.players[k].outbox.put(msg)
         except Exception, e:
             traceback.print_exc()
             self.log_msg("Exception: send_to_group(): " + str(e))