changeset 228:24769389a7ba alpha

Traipse Alpha 'OpenRPG' {100612-01} 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. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc's main goal is to offer more advanced features and enhance the productivity of the user. Update Summary (Preparing to close updates) New Features: New to Map, can re-order Grid, Miniatures, and Whiteboard layer draw order Fixes: Fix to InterParse that was causing an Infernal Loop with Namespace Internal Fix to XML data, removed old Minidom and switched to Element Tree Fix to Server that was causing eternal attempt to find a Server ID, in Register Rooms thread Fix to metaservers.xml file not being created
author sirebral
date Sat, 12 Jun 2010 04:38:29 -0500
parents 2c6db2043764
children 1645a78a33a4
files orpg/dieroller/base.py orpg/dieroller/rollers/d20.py orpg/dieroller/rollers/std.py orpg/gametree/gametree.py orpg/gametree/nodehandlers/chatmacro.py orpg/gametree/nodehandlers/core.py orpg/gametree/nodehandlers/forms.py orpg/gametree/nodehandlers/minilib.py orpg/gametree/nodehandlers/voxchat.py orpg/main.py orpg/mapper/background.py orpg/mapper/base_msg.py orpg/mapper/fog.py orpg/mapper/fog_msg.py orpg/mapper/grid.py orpg/mapper/map.py orpg/mapper/map_msg.py orpg/mapper/miniatures.py orpg/mapper/miniatures_msg.py orpg/mapper/whiteboard.py orpg/mapper/whiteboard_msg.py orpg/networking/meta_server_lib.py orpg/networking/mplay_client.py orpg/networking/mplay_server.py orpg/networking/mplay_server_gui.py orpg/orpg_version.py orpg/orpg_windows.py orpg/orpg_xml.py orpg/templates/default_settings.xml orpg/templates/feature.xml orpg/templates/metaservers.cache orpg/templates/nodes/4e_char_sheet.xml orpg/templates/nodes/Traipse_User_Guide.xml orpg/tools/FlatNotebook.py orpg/tools/InterParse.py orpg/tools/orpg_settings.py orpg/tools/scriptkit.py orpg/tools/settings.py plugins/xxstdnamespace.py
diffstat 39 files changed, 823 insertions(+), 769 deletions(-) [+]
line wrap: on
line diff
--- a/orpg/dieroller/base.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/dieroller/base.py	Sat Jun 12 04:38:29 2010 -0500
@@ -76,6 +76,8 @@
         return self.__lshift__(other)
 
     def __str__(self):
+        try: print "MY STRING", myStr
+        except: pass
         if len(self.data) > 0:
             myStr = "[" + str(self.data[0])
             for a in self.data[1:]:
--- a/orpg/dieroller/rollers/d20.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/dieroller/rollers/d20.py	Sat Jun 12 04:38:29 2010 -0500
@@ -41,19 +41,20 @@
 class d20dc(std):
     def __init__(self,source=[],DC=10,mod=0):
         std.__init__(self,source)
+        print "Source", source
         self.DC = DC
         self.mod = mod
-        self.append(static_di(mod))
+        #self.append(static_di(mod))
 
     def is_success(self):
-        return ((self.sum() >= self.DC or self.data[0] == 20) and self.data[0] != 1)
+        return ((self.sum()+self.mod >= self.DC or self.data[0] == 20) and self.data[0] != 1)
 
     def __str__(self):
         myStr = "[" + str(self.data[0])
         for a in self.data[1:]:
-            myStr += ","
+            myStr += ", "
             myStr += str(a)
-        myStr += "] = (" + str(self.sum()) + ")"
+        myStr += ", "+str(self.mod)+ "] = (" + str(self.sum()+self.mod) + ")"
         myStr += " vs DC " + str(self.DC)
         if self.is_success(): myStr += " Success!"
         else: myStr += " Failure!"
--- a/orpg/dieroller/rollers/std.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/dieroller/rollers/std.py	Sat Jun 12 04:38:29 2010 -0500
@@ -38,7 +38,7 @@
             if self.data[i].lastroll() >= num:
                 self.data[i].extraroll()
                 done = 0
-        if done: return self
+        if done: print self; return self
         else: return self.open(num)
 
     def minroll(self,min):
--- a/orpg/gametree/gametree.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/gametree/gametree.py	Sat Jun 12 04:38:29 2010 -0500
@@ -47,7 +47,7 @@
 import string, urllib, time, os
 from shutil import copytree, copystat, copy, copyfile
 
-from orpg.orpg_xml import xml
+#from orpg.orpg_xml import xml
 from orpg.tools.validate import validate
 from orpg.tools.orpg_log import logger, debug
 from orpg.tools.orpg_settings import settings
--- a/orpg/gametree/nodehandlers/chatmacro.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/gametree/nodehandlers/chatmacro.py	Sat Jun 12 04:38:29 2010 -0500
@@ -42,15 +42,12 @@
     def __init__(self,xml,tree_node):
         node_handler.__init__(self,xml,tree_node)
         self.xml = xml
-        self.text_elem = self.xml.find('text')
-        self.text = self.text_elem.text
 
-    def set_text(self,txt):
-        self.text = txt
+    def set_text(self, txt):
+        self.xml.find('text').text = txt
 
     def on_use(self,evt):
-        txt = self.text
-        actionlist = txt.split("\n")
+        actionlist = self.xml.find('text').text.split("\n")
         for line in actionlist:
             if(line != ""):
                 if line[0] != "/": ## it's not a slash command
@@ -65,8 +62,7 @@
 
     def tohtml(self):
         title = self.xml.get("name")
-        txt = self.text
-        txt = string.replace(txt,'\n',"<br />")
+        txt = string.replace(self.xml.find('text').text,'\n',"<br />")
         return "<P><b>"+title+":</b><br />"+txt
 
 P_TITLE = wx.NewId()
@@ -80,7 +76,7 @@
         sizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Chat Macro"), wx.VERTICAL)
         self.text = {}
         self.text[P_TITLE] = wx.TextCtrl(self, P_TITLE, handler.xml.get('name'))
-        self.text[P_BODY] = wx.TextCtrl(self, P_BODY, handler.text, style=wx.TE_MULTILINE)
+        self.text[P_BODY] = wx.TextCtrl(self, P_BODY, handler.xml.find('text').text, style=wx.TE_MULTILINE)
         sizer.Add(wx.StaticText(self, -1, "Title:"), 0, wx.EXPAND)
         sizer.Add(self.text[P_TITLE], 0, wx.EXPAND)
         sizer.Add(wx.StaticText(self, -1, "Text Body:"), 0, wx.EXPAND)
--- a/orpg/gametree/nodehandlers/core.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/gametree/nodehandlers/core.py	Sat Jun 12 04:38:29 2010 -0500
@@ -345,6 +345,7 @@
             if bad_txt_found:
                 wx.MessageBox("Some non 7-bit ASCII characters found and stripped","Warning!")
             txt = u_txt
+            print txt, self.handler, self.handler.xml
             self.handler.text._set_nodeValue(txt)
 
 
--- a/orpg/gametree/nodehandlers/forms.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/gametree/nodehandlers/forms.py	Sat Jun 12 04:38:29 2010 -0500
@@ -30,7 +30,7 @@
 
 from containers import *
 import orpg.minidom as minidom
-from orpg.orpg_xml import xml
+#from orpg.orpg_xml import xml
 from wx.lib.scrolledpanel import ScrolledPanel
 from orpg.tools.settings import settings
 from orpg.tools.InterParse import Parse
--- a/orpg/gametree/nodehandlers/minilib.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/gametree/nodehandlers/minilib.py	Sat Jun 12 04:38:29 2010 -0500
@@ -37,6 +37,7 @@
 import map_miniature_nodehandler
 import orpg.mapper.map_msg
 import orpg.minidom as minidom
+from orpg.tools.InterParse import Parse
 # import scriptkit
 
 # Constants
@@ -44,17 +45,6 @@
 FROM_MINILIB_MAP = {'url':'path', 'name':'label', 'unique':None}
 CORE_ATTRIBUTES = ['name', 'url', 'unique', 'posy', 'posx', 'hide', 'face', 'heading', 'align', 'locked', 'width', 'height']
 
-ATTRIBUTE_NAME = 'name'
-ATTRIBUTE_URL = 'url'
-ATTRIBUTE_UNIQUE = 'unique'
-ATTRIBUTE_ID = 'id'
-ATTRIBUTE_POSX = 'posx'
-ATTRIBUTE_POSY = 'posy'
-
-TAG_MINIATURE = 'miniature'
-
-COMPONENT_MAP = 'map'
-COMPONENT_SESSION = 'session'
 # <nodehandler name='?' module='minilib' class='minilib_handler'>
 #     <miniature name='?' url='?' unique='?'></miniature>
 # </nodehandler>
@@ -100,11 +90,11 @@
         """
         str = '<table border="2" >'
         str += "<tr><th width='20%'>Label</th><th>Image</th><th width='65%'>URL</th><th>Unique</th></tr>"
-        for mini in self.xml.findall(TAG_MINIATURE):
-            url = mini.get(ATTRIBUTE_URL)
-            label = mini.get(ATTRIBUTE_NAME)
+        for mini in self.xml.findall('miniature'):
+            url = mini.get('url')
+            label = mini.get('name')
             flag = 0
-            try: flag = eval( mini.get(ATTRIBUTE_UNIQUE) )
+            try: flag = eval( mini.get('unique') )
             except: pass
             show = 'yes'
             if flag: show = 'no'
@@ -133,13 +123,13 @@
             for attrib in obj.keys():
                 key = TO_MINILIB_MAP.get( attrib, attrib )
                 if key != None: dict[ key ] = obj.get( attrib )
-            dict[ ATTRIBUTE_UNIQUE ] = unique
+            dict[ 'unique' ] = unique
             self.new_mini( dict )
         else: node_handler.on_drop(self, evt)
 
 
     def new_mini( self, data={}, add=1 ):
-        mini = Element( TAG_MINIATURE )
+        mini = Element( 'miniature' )
         for key in data.keys(): mini.set( key, data[ key ] )
         for key in CORE_ATTRIBUTES:
             if mini.get( key ) == ('' or None): mini.set( key, '0' )
@@ -154,37 +144,39 @@
     def add_leaf( self, mini, icon='gear' ):
         tree = self.tree
         icons = tree.icons
-        key = mini.get( ATTRIBUTE_NAME )
+        key = mini.get( 'name' )
         self.mydata.append( mini )
 
     def update_leaves( self ):
         self.mydata = []
-        for n in self.xml.findall(TAG_MINIATURE): self.add_leaf( n )
+        for n in self.xml.findall('miniature'): self.add_leaf( n )
 
     def on_drag( self, evt ):
         print 'drag event caught'
 
     def send_mini_to_map( self, mini, count=1, addName=True ):
         if mini == None: return
-        if mini.get( ATTRIBUTE_URL ) == '' or mini.get( ATTRIBUTE_URL ) == 'http://':
-            self.chat.ParsePost( self.chat.colorize(self.chat.syscolor, '"%s" is not a valid URL, the mini "%s" will not be added to the map' % ( mini.get( ATTRIBUTE_URL ), mini.get( ATTRIBUTE_NAME ) )) )
+        if mini.get( 'url' ) == '' or mini.get( 'url' ) == 'http://':
+            Parse.Post( self.chat.colorize(self.chat.syscolor, 
+                        '"%s" is not a valid URL, the mini "%s" will not be added to the map' % ( 
+                        mini.get( 'url' ), mini.get( 'name' ) )) )
             return
-        session = component.get( COMPONENT_SESSION )
+        session = component.get( 'session' )
         if (session.my_role() != session.ROLE_GM) and (session.my_role() != session.ROLE_PLAYER):
             component.get("chat").InfoPost("You must be either a player or GM to use the miniature Layer")
             return
-        map = component.get(COMPONENT_MAP)
+        canvas = component.get('map')
         for loop in range( count ):
             msg = self.get_miniature_XML( mini, addName)
             msg = str("<map action='update'><miniatures>" + msg + "</miniatures></map>")
-            map.new_data( msg )
+            canvas.new_data( msg )
             session.send( msg )
 
     def get_miniature_XML( self, mini_xml, addName = True ):
         msg = orpg.mapper.map_msg.mini_msg()
-        map = component.get( COMPONENT_MAP )
-        session = component.get( COMPONENT_SESSION )
-        msg.init_prop( ATTRIBUTE_ID, session.get_next_id() )
+        canvas = component.get( 'map' )
+        session = component.get( 'session' )
+        msg.init_prop( 'id', session.get_next_id() )
         msg.init_prop('selected', '1')# this will make the mini initially selected
         for k in mini_xml.keys():
             # translate our attributes to map attributes
@@ -193,24 +185,24 @@
                 if not addName and k == 'name': pass
                 else: msg.init_prop( key, mini_xml.get( k ) )
         unique = self.is_unique( mini_xml )
-        if addName: label = mini_xml.get( ATTRIBUTE_NAME )
+        if addName: label = mini_xml.get( 'name' )
         else: label = ''
         return msg.get_all_xml()
 
     def is_unique( self, mini ):
-        unique = mini.get( ATTRIBUTE_UNIQUE )
+        unique = mini.get( 'unique' )
         val = 0
         try: val = eval( unique )
         except: val = len( unique )
         return val
 
     def sanity_check_nodes( self ):
-        for node in self.xml.findall(TAG_MINIATURE):
-            if node.get( ATTRIBUTE_POSX ) == '': node.set( ATTRIBUTE_POSX, '0' )
-            if node.get( ATTRIBUTE_POSY ) == '': node.set( ATTRIBUTE_POSY, '0' )
+        for node in self.xml.findall('miniature'):
+            if node.get( 'posx' ) == '': node.set( 'posx', '0' )
+            if node.get( 'posy' ) == '': node.set( 'posy', '0' )
 
     def get_mini( self, index ):
-        try: return self.xml.findall(TAG_MINIATURE)[index]
+        try: return self.xml.findall('miniature')[index]
         except: return None
 
 class mini_handler( node_handler ):
@@ -279,7 +271,7 @@
         """Returns a dictionary of label => game tree miniature DOM node mappings.
         """
         self.list = []
-        for mini in self.handler.xml.findall(TAG_MINIATURE): self.list.append( mini.get( ATTRIBUTE_NAME ) )
+        for mini in self.handler.xml.findall('miniature'): self.list.append( mini.get( 'name' ) )
         return self.list
 
     def on_close(self, evt):
@@ -407,7 +399,7 @@
         self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.select_cell)
 
     def update_cols( self ):
-        for n in self.handler.xml.findall(TAG_MINIATURE):
+        for n in self.handler.xml.findall('miniature'):
             for k in n.keys():
                 if k not in self.keys: self.keys.append( k )
 
@@ -426,7 +418,7 @@
         """Returns the list of 'miniature' DOM elements associated with this
         miniature library.
         """
-        return self.handler.xml.findall( TAG_MINIATURE )
+        return self.handler.xml.findall( 'miniature' )
 
     def add_row( self, count = 1 ):
         """creates a new miniature node, and then adds it to the current
@@ -434,8 +426,8 @@
         """
         self.AppendRows( count )
         node = self.handler.new_mini( {
-          ATTRIBUTE_NAME :' ',
-          ATTRIBUTE_URL :'http://'} )# minidom.Element( TAG_MINIATURE )
+          'name' :' ',
+          'url' :'http://'} )# minidom.Element( 'miniature' )
         self.update_all()
         #self.handler.xml.append( node )
 
@@ -446,7 +438,7 @@
         """
         if self.selectedRow > -1:
             pos = self.selectedRow
-            list = self.handler.xml.findall(TAG_MINIATURE)
+            list = self.handler.xml.findall('miniature')
             self.handler.xml.remove( list[pos] )
             self.DeleteRows( pos, 1 )
 
@@ -492,7 +484,7 @@
         return self.GetTable().GetValue( self.selectedRow, 1 )
 
     def getSelectedSerial( self ):
-        """Returns the ATTRIBUTE_UNIQUE value for the selected row
+        """Returns the 'unique' value for the selected row
         """
         return self.GetTable().GetValue( self.selectedRow, 2 )
 
--- a/orpg/gametree/nodehandlers/voxchat.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/gametree/nodehandlers/voxchat.py	Sat Jun 12 04:38:29 2010 -0500
@@ -31,7 +31,6 @@
 import re, os, string, core
 
 from orpg.orpg_windows import *
-import core
 import orpg.tools.scriptkit
 import orpg.tools.predTextCtrl
 import orpg.tools.rgbhex
--- a/orpg/main.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/main.py	Sat Jun 12 04:38:29 2010 -0500
@@ -63,7 +63,7 @@
 
 from xml.etree.ElementTree import ElementTree, Element, parse
 from xml.etree.ElementTree import fromstring, tostring
-from orpg.orpg_xml import xml #to be replaced by etree
+#from orpg.orpg_xml import xml #to be replaced by etree
 
 
 ####################################
@@ -162,6 +162,11 @@
             settings.add('Tip of the Day', 'tipotday_enabled', '1', '0|1', 'Show Tip of the Day on startup')
             logger.info('New Settings added', True)
             self.TraipseSuiteWarn('debug')
+        if setting == 'Meta Servers':
+            settings.add('Networking', 'MetaServers', 'metaservers.xml', '.xml file', 'Contains a list of Meta Servers')
+            logger.info('New Settings added', True)
+            self.validate.config_file("metaservers.xml","default_metaservers.xml")
+            self.TraipseSuiteWarn('debug')
 
     def get_activeplugins(self):
         try: tmp = self.pluginsFrame.get_activeplugins()
@@ -202,7 +207,7 @@
                     ['  -'],
                     ['  Tab Styles'],
                     ['    Slanted'],
-                    ['      Colorful', "check"],
+                    #['      Colorful', "check"],
                     ['      Black and White', "check"],
                     ['      Aqua', "check"],
                     ['      Custom', "check"],
@@ -252,7 +257,8 @@
 
         self.mainmenu.SetMenuState('ToolsPasswordManager', True if settings.get('PWMannager') == 'On' else False)
         tabtheme = settings.get('TabTheme')  #This change is stable. TaS.
-        self.mainmenu.SetMenuState("OpenRPGTabStylesSlantedColorful", tabtheme == 'slanted&colorful')
+        if tabtheme == 'slanted&colorful': tabtheme = 'customflat'; settings.change('TabTheme', 'customflat')
+        #self.mainmenu.SetMenuState("OpenRPGTabStylesSlantedColorful", tabtheme == 'slanted&colorful')
         self.mainmenu.SetMenuState("OpenRPGTabStylesSlantedBlackandWhite", tabtheme == 'slanted&bw')
         self.mainmenu.SetMenuState("OpenRPGTabStylesSlantedAqua", tabtheme == 'slanted&aqua')
         self.mainmenu.SetMenuState("OpenRPGTabStylesFlatBlackandWhite", tabtheme == 'flat&bw')
@@ -318,9 +324,8 @@
     #Tab Styles Menus
     
     def SetTabStyles(self, *args, **kwargs):
-
         tabtheme = settings.get('TabTheme')  #This change is stable. TaS.
-        self.mainmenu.SetMenuState("OpenRPGTabStylesSlantedColorful", tabtheme == 'slanted&colorful')
+        #self.mainmenu.SetMenuState("OpenRPGTabStylesSlantedColorful", tabtheme == 'slanted&colorful')
         self.mainmenu.SetMenuState("OpenRPGTabStylesSlantedBlackandWhite", tabtheme == 'slanted&bw')
         self.mainmenu.SetMenuState("OpenRPGTabStylesSlantedAqua", tabtheme == 'slanted&aqua')
         self.mainmenu.SetMenuState("OpenRPGTabStylesFlatBlackandWhite", tabtheme == 'flat&bw')
@@ -336,7 +341,6 @@
         else:
             try: menu = args[0]
             except: logger.general('Invalid Syntax for orpgFrame->SetTabStyles(self, *args, **kwargs)'); return
-
         if kwargs.has_key('graidentTo'): graidentTo = kwargs['graidentTo']
         else: graidentTo = None
         if kwargs.has_key('graidentFrom'): graidentFrom = kwargs['graidentFrom']
@@ -360,7 +364,7 @@
         for wnd in tabbedwindows:
             style = wnd.GetWindowStyleFlag()
             # remove old tabs style
-            mirror = ~(FNB.FNB_VC71 | FNB.FNB_VC8 | FNB.FNB_FANCY_TABS | FNB.FNB_COLORFUL_TABS)
+            mirror = ~(FNB.FNB_VC71 | FNB.FNB_VC8 | FNB.FNB_FANCY_TABS )
             style &= mirror
             style |= newstyle
             wnd.SetWindowStyleFlag(style)
@@ -747,11 +751,11 @@
 
     def do_tab_window(self, xml_dom, parent_wnd):
         # if container window loop through childern and do a recursive call
-        temp_wnd = orpgTabberWnd(parent_wnd, style=FNB.FNB_ALLOW_FOREIGN_DND)
+        temp_wnd = orpgTabberWnd(parent_wnd)
 
         children = xml_dom.getchildren()
         for c in children:
-            wnd = self.build_window(c,temp_wnd)
+            wnd = self.build_window(c, temp_wnd)
             name = c.get("name")
             temp_wnd.AddPage(wnd, name, False)
         return temp_wnd
@@ -1124,7 +1128,7 @@
     
     def OnInit(self):
         component.add('log', logger)
-        component.add('xml', xml)
+        #component.add('xml', xml)
         component.add('settings', settings)
         component.add('validate', validate)
         component.add("tabbedWindows", [])
--- a/orpg/mapper/background.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/mapper/background.py	Sat Jun 12 04:38:29 2010 -0500
@@ -211,28 +211,31 @@
         else: return ''
 
     def layerTakeDOM(self, xml_dom):
-        type = BG_COLOR
-        color = xml_dom.getAttribute("color")
-        logger.debug("color=" + color)
-        path = urllib.unquote(xml_dom.getAttribute("path"))
-        logger.debug("path=" + path)
-        # Begin ted's map changes
-        if xml_dom.hasAttribute("color"):
-            r,g,b = self.r_h.rgb_tuple(xml_dom.getAttribute("color"))
+        bg_type = xml_dom.get("type")
+        urlpath = xml_dom.get('path')
+        color = xml_dom.get("color")
+
+        if urlpath != None:
+            path = urllib.unquote(xml_dom.get("path"))
+            logger.debug("path=" + path)
+
+        if color != None:
+            logger.debug("color=" + color)
+            r,g,b = self.r_h.rgb_tuple(color)
             self.set_color(cmpColour(r,g,b))
-        # End ted's map changes
-        if xml_dom.hasAttribute("type"):
-            type = int(xml_dom.getAttribute("type"))
-            logger.debug("type=" + str(type))
-        if type == BG_TEXTURE:
+
+        if bg_type != None:
+            logger.debug("type=" + bg_type)
+            bg_type = int(xml_dom.get("type"))
+        if bg_type == BG_TEXTURE:
             if path != "": self.set_texture(path)
-        elif type == BG_IMAGE:
+        elif bg_type == BG_IMAGE:
             if path != "": self.set_image(path, 1)
-        elif type == BG_NONE: self.clear()
-        if xml_dom.hasAttribute('local') and xml_dom.getAttribute('local') == 'True' and os.path.exists(urllib.unquote(xml_dom.getAttribute('localPath'))):
-            self.localPath = urllib.unquote(xml_dom.getAttribute('localPath'))
+        elif bg_type == BG_NONE: self.clear()
+        if xml_dom.get('local') == 'True' and os.path.exists(urllib.unquote(xml_dom.get('localPath'))):
+            self.localPath = urllib.unquote(xml_dom.get('localPath'))
             self.local = True
-            self.localTime = int(xml_dom.getAttribute('localTime'))
+            self.localTime = int(xml_dom.get('localTime'))
             if self.localTime-time.time() <= 144000:
                 file = open(self.localPath, "rb")
                 imgdata = file.read()
--- a/orpg/mapper/base_msg.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/mapper/base_msg.py	Sat Jun 12 04:38:29 2010 -0500
@@ -29,7 +29,7 @@
 
 from threading import RLock
 from orpg.networking.mplay_client import *
-from xml.etree.ElementTree import ElementTree, Element
+from xml.etree.ElementTree import ElementTree, Element, fromstring
 
 class map_element_msg_base:
 #  This is a base class
@@ -216,20 +216,24 @@
         self._from_dom(xml_dom,self.set_prop)
 
     def init_from_xml(self,xml):
-        xml_dom = parseXml(xml)
-        node_list = xml_dom.getElementsByTagName(self.tagname)
+        #xml_dom = parseXml(xml)
+        xml_dom = fromstring(xml)
+        #node_list = xml_dom.getElementsByTagName(self.tagname)
+        node_list = xml_dom.findall(self.tagname)
         if len(node_list) < 1: print "Warning: no <" + self.tagname + "/> elements found in DOM."
         else:
             while len(node_list): self.init_from_dom(node_list.pop())
-        if xml_dom: xml_dom.unlink()
+        #if xml_dom: xml_dom.unlink()
 
     def set_from_xml(self,xml):
-        xml_dom = parseXml(xml)
-        node_list = xml_dom.getElementsByTagName(self.tagname)
+        #xml_dom = parseXml(xml)
+        xml_dom = fromstring(xml)
+        #node_list = xml_dom.getElementsByTagName(self.tagname)
+        node_list = xml_dom.findall(self.tagname)
         if len(node_list) < 1: print "Warning: no <" + self.tagname + "/> elements found in DOM."
         else:
             while len(node_list): self.set_from_dom(node_list.pop())
-        if xml_dom: xml_dom.unlink()
+        #if xml_dom: xml_dom.unlink()
 
     # XML importers end
     #########################################
--- a/orpg/mapper/fog.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/mapper/fog.py	Sat Jun 12 04:38:29 2010 -0500
@@ -27,7 +27,7 @@
 from base import *
 from random import Random
 from region import *
-from orpg.minidom import Element
+from xml.etree.ElementTree import Element, tostring
 import traceback
 COURSE = 10
 
@@ -47,8 +47,8 @@
         for pairs in string.split( points, ';' ):
             pair = string.split( pairs, ',' )
             p = Element( "point" )
-            p.setAttribute( "x", pair[0] )
-            p.setAttribute( "y", pair[1] )
+            p.set( "x", pair[0] )
+            p.set( "y", pair[1] )
             result.append( p )
         return result
 
@@ -59,23 +59,20 @@
             localOutline = "points"
         elem = Element( "poly" )
         if action == "del":
-            elem.setAttribute( "action", action )
-            elem.setAttribute( "outline", localOutline )
+            elem.set( "action", action )
+            elem.set( "outline", localOutline )
             if localOutline == 'points':
-                list = self.points_to_elements( self.outline )
-                for p in list: elem.appendChild( p )
-            str = elem.toxml()
-            elem.unlink()
-            return str
-        elem.setAttribute( "action", action )
+                foglist = self.points_to_elements( self.outline )
+                for p in foglist: elem.append( p )
+            return tostring(elem)
+        elem.set( "action", action )
         if  localOutline != None:
-            elem.setAttribute( "outline", localOutline )
+            elem.set( "outline", localOutline )
             if localOutline == 'points':
-                list = self.points_to_elements( self.outline )
-                for p in list: elem.appendChild( p )
-        xml_str = elem.toxml()
-        elem.unlink()
-        return xml_str
+                foglist = self.points_to_elements( self.outline )
+                for p in foglist: elem.append( p )
+        #xml_str = elem.toxml()
+        return tostring(elem)
 
 class fog_layer(layer_base):
     def __init__(self, canvas):
@@ -223,11 +220,12 @@
             if not self.use_fog:
                 self.use_fog = True
                 self.recompute_fog()
-            if xml_dom.hasAttribute('serial'): self.serial_number = int(xml_dom.getAttribute('serial'))
-            children = xml_dom._get_childNodes()
+            serial = xml_dom.get('serial')
+            if serial != None: self.serial_number = int(serial)
+            children = xml_dom.getchildren()
             for l in children:
-                action = l.getAttribute("action")
-                outline = l.getAttribute("outline")
+                action = l.get("action")
+                outline = l.get("outline")
                 if (outline == "all"):
                     polyline = [IPoint().make(0,0), IPoint().make(self.width-1, 0),
                               IPoint().make(self.width-1, self.height-1),
@@ -240,10 +238,10 @@
                     polyline = []
                     lastx = None
                     lasty = None
-                    list = l._get_childNodes()
+                    list = l.getchildren()
                     for point in list:
-                        x = point.getAttribute( "x" )
-                        y = point.getAttribute( "y" )
+                        x = point.get( "x" )
+                        y = point.get( "y" )
                         if (x != lastx or y != lasty):
                             polyline.append(IPoint().make(int(x), int(y)))
                         lastx = x
--- a/orpg/mapper/fog_msg.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/mapper/fog_msg.py	Sat Jun 12 04:38:29 2010 -0500
@@ -27,7 +27,7 @@
 
 from base_msg import *
 from region import *
-from orpg.minidom import Element
+from xml.etree.ElementTree import Element, tostring
 import string
 
 class fog_msg(map_element_msg_base):
@@ -41,19 +41,17 @@
 
     def get_line(self,outline,action,output_act):
         elem = Element( "poly" )
-        if ( output_act ): elem.setAttribute( "action", action )
-        if ( outline == 'all' ) or ( outline == 'none' ): elem.setAttribute( "outline", outline )
+        if ( output_act ): elem.set( "action", action )
+        if ( outline == 'all' ) or ( outline == 'none' ): elem.set( "outline", outline )
         else:
-            elem.setAttribute( "outline", "points" )
+            elem.set( "outline", "points" )
             for pair in string.split( outline, ";" ):
                 p = string.split( pair, "," )
                 point = Element( "point" )
-                point.setAttribute( "x", p[ 0 ] )
-                point.setAttribute( "y", p[ 1 ] )
+                point.set( "x", p[ 0 ] )
+                point.set( "y", p[ 1 ] )
                 elem.appendChild( point )
-        str = elem.toxml()
-        elem.unlink()
-        return str
+        return tostring(elem)
 
     # convenience method to use if only this line is modified
     #   outputs a <map/> element containing only the changes to this line
@@ -83,23 +81,18 @@
                                          str(x2)+","+str(y1)+";"+
                                          str(x2)+","+str(y2)+";"+
                                          str(x1)+","+str(y2),action,output_action)
-        s = "<fog"
+        s = "<fog>"
         if fog_string:
-            s += ">"
             s += fog_string
-            s += "</fog>"
-        else: s+="/>"
+        s += "</fog>"
         return s
 
     def interpret_dom(self,xml_dom):
         self.use_fog=1
-        #print 'fog_msg.interpret_dom called'
-        children = xml_dom._get_childNodes()
-        #print "children",children
+        children = xml_dom.getchildren()
         for l in children:
-            action = l.getAttribute("action")
-            outline = l.getAttribute("outline")
-            #print "action/outline",action, outline
+            action = l.get("action")
+            outline = l.get("outline")
             if (outline=="all"):
                 polyline=[]
                 self.fogregion.Clear()
@@ -109,14 +102,13 @@
                 self.fogregion.Clear()
             else:
                 polyline=[]
-                list = l._get_childNodes()
+                list = l.getchildren()
                 for node in list:
-                    polyline.append( IPoint().make( int(node.getAttribute("x")), int(node.getAttribute("y")) ) )
+                    polyline.append( IPoint().make( int(node.get("x")), int(node.get("y")) ) )
                     # pointarray = outline.split(";")
                     # for m in range(len(pointarray)):
                     #     pt=pointarray[m].split(",")
                     #     polyline.append(IPoint().make(int(pt[0]),int(pt[1])))
-                    #print "length of polyline", len(polyline)
             if (len(polyline)>2):
                 if action=="del": self.fogregion.FromPolygon(polyline,0)
                 else: self.fogregion.FromPolygon(polyline,1)
--- a/orpg/mapper/grid.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/mapper/grid.py	Sat Jun 12 04:38:29 2010 -0500
@@ -406,19 +406,20 @@
         else: return ''
 
     def layerTakeDOM(self, xml_dom):
-        if xml_dom.hasAttribute("color"):
-            r,g,b = self.r_h.rgb_tuple(xml_dom.getAttribute("color"))
+        color = xml_dom.get('color')
+        if color != None:
+            r,g,b = self.r_h.rgb_tuple(color)
             self.set_color(cmpColour(r,g,b))
         #backwards compatible with non-isometric map formated clients
-        ratio = RATIO_DEFAULT
-        if xml_dom.hasAttribute("ratio"): ratio = xml_dom.getAttribute("ratio")
-        if xml_dom.hasAttribute("mode"):
-            self.SetMode(int(xml_dom.getAttribute("mode")))
-        if xml_dom.hasAttribute("size"):
-            self.unit_size = int(xml_dom.getAttribute("size"))
+        ratio = RATIO_DEFAULT if xml_dom.get("ratio") == None else xml_dom.get('ratio')
+        mode = xml_dom.get('mode')
+        if mode != None: self.SetMode(int(mode))
+        size = xml_dom.get('size')
+        if size != None:
+            self.unit_size = int(size)
             self.unit_size_y = self.unit_size
-        if xml_dom.hasAttribute("snap"):
-            if (xml_dom.getAttribute("snap") == 'True') or (xml_dom.getAttribute("snap") == "1"): self.snap = True
-            else: self.snap = False
-        if xml_dom.hasAttribute("line"):
-            self.SetLine(int(xml_dom.getAttribute("line")))
+        if (xml_dom.get("snap") == 'True') or (xml_dom.get("snap") == "1"): self.snap = True
+        else: self.snap = False
+        line = xml_dom.get('line')
+        if line != None: self.SetLine(int(line))
+
--- a/orpg/mapper/map.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/mapper/map.py	Sat Jun 12 04:38:29 2010 -0500
@@ -45,6 +45,8 @@
 from images import ImageHandler
 from orpg.orpgCore import component
 from orpg.tools.orpg_settings import settings
+from xml.etree.ElementTree import ElementTree, Element, parse
+from xml.etree.ElementTree import fromstring, tostring
 
 # Various marker modes for player tools on the map
 MARKER_MODE_NONE = 0
@@ -259,21 +261,26 @@
             dc.DrawRectangle(0,0,clientsize[0]+1,clientsize[1]+1)
             dc.SetDeviceOrigin(-topleft[0], -topleft[1])
             dc.SetUserScale(scale, scale)
+
+            layer_order = []
+            for i in xrange (0, len(self.parent.layer_handlers)-1):
+                if self.parent.layer_tabs.GetPageText(i) in ('Background', 'Fog', 'General'): pass
+                else: layer_order.append(self.parent.layer_tabs.GetPageText(i))
             self.layers['bg'].layerDraw(dc, scale, topleft, clientsize)
-            self.layers['grid'].layerDraw(dc, [topleft[0]/scale, topleft[1]/scale], 
-                [clientsize[0]/scale, clientsize[1]/scale])
-            self.layers['miniatures'].layerDraw(dc, [topleft[0]/scale, topleft[1]/scale], 
-                [clientsize[0]/scale, clientsize[1]/scale])
-            self.layers['whiteboard'].layerDraw(dc)
+
+            for layer in layer_order:
+                if layer == 'Grid': self.layers['grid'].layerDraw(dc, [topleft[0]/scale, topleft[1]/scale], 
+                    [clientsize[0]/scale, clientsize[1]/scale])
+                if layer == 'Miniatures': self.layers['miniatures'].layerDraw(dc, [topleft[0]/scale, topleft[1]/scale], 
+                    [clientsize[0]/scale, clientsize[1]/scale])
+                if layer == 'Whiteboard': self.layers['whiteboard'].layerDraw(dc)
+
             self.layers['fog'].layerDraw(dc, topleft, clientsize)
             dc.SetPen(wx.NullPen)
             dc.SetBrush(wx.NullBrush)
-
-            dc.SelectObject(wx.NullBitmap)
-            del dc
+            dc.SelectObject(wx.NullBitmap); del dc
             wdc = self.preppaint()
             wdc.DrawBitmap(bmp, topleft[0], topleft[1])
-
             if settings.get_setting("AlwaysShowMapScale") == "1":
                 self.showmapscale(wdc)
         try: evt.Skip()
@@ -622,15 +629,16 @@
            --Snowdog 5/27/03
         """
         try:
-            #parse the map DOM
-            xml_dom = parseXml(xml)
+            xml_dom = fromstring(xml)
             if xml_dom == None: return
-            node_list = xml_dom.getElementsByTagName("map")
+            node_list = xml_dom.findall("map")
+            if len(node_list) < 1: 
+                if xml_dom.tag == 'map': node_list = [xml_dom]
             if len(node_list) < 1: pass
             else:
                 # set map version to incoming data so layers can convert
-                self.map_version = node_list[0].getAttribute("version")
-                action = node_list[0].getAttribute("action")
+                self.map_version = node_list[0].get("version")
+                action = node_list[0].get("action")
                 if action == "new":
                     self.layers = {}
                     try: self.layers['bg'] = layer_back_ground(self)
@@ -643,33 +651,33 @@
                     except: pass
                     try: self.layers['fog'] = fog_layer(self)
                     except: pass
-                sizex = node_list[0].getAttribute("sizex")
+                sizex = node_list[0].get("sizex") or ''
                 if sizex != "":
                     sizex = int(float(sizex))
                     sizey = self.size[1]
                     self.set_size((sizex,sizey))
                     self.size_changed = 0
-                sizey = node_list[0].getAttribute("sizey")
+                sizey = node_list[0].get("sizey") or ''
                 if sizey != "":
                     sizey = int(float(sizey))
                     sizex = self.size[0]
                     self.set_size((sizex,sizey))
                     self.size_changed = 0
-                children = node_list[0]._get_childNodes()
+                children = node_list[0].getchildren()
                 #fog layer must be computed first, so that no data is inadvertently revealed
                 for c in children:
-                    name = c._get_nodeName()
+                    name = c.tag
                     if name == "fog": self.layers[name].layerTakeDOM(c)
                 for c in children:
-                    name = c._get_nodeName()
+                    name = c.tag
                     if name != "fog": self.layers[name].layerTakeDOM(c)
                 # all map data should be converted, set map version to current version
                 self.map_version = MAP_VERSION
-                self.Refresh(False)
-            xml_dom.unlink()  # eliminate circular refs
+                self.Refresh(True)
         except: pass
 
     def re_ids_in_xml(self, xml):
+        debug(('Developers note. Deprecated call to re_ids_in_xml!!'), parents=True)
         new_xml = ""
         tmp_map = map_msg()
         xml_dom = parseXml(str(xml))
@@ -714,20 +722,23 @@
         self.root_dir = os.getcwd()
         self.current_layer = 2
         self.layer_tabs = orpgTabberWnd(self, style=FNB.FNB_NO_X_BUTTON|FNB.FNB_BOTTOM|FNB.FNB_NO_NAV_BUTTONS)
+
         self.layer_handlers = []
-        self.layer_handlers.append(background_handler(self.layer_tabs,-1,self.canvas))
-        self.layer_tabs.AddPage(self.layer_handlers[0],"Background")
-        self.layer_handlers.append(grid_handler(self.layer_tabs,-1,self.canvas))
-        self.layer_tabs.AddPage(self.layer_handlers[1],"Grid")
-        self.layer_handlers.append(miniatures_handler(self.layer_tabs,-1,self.canvas))
-        self.layer_tabs.AddPage(self.layer_handlers[2],"Miniatures", True)
-        self.layer_handlers.append(whiteboard_handler(self.layer_tabs,-1,self.canvas))
-        self.layer_tabs.AddPage(self.layer_handlers[3],"Whiteboard")
-        self.layer_handlers.append(fog_handler(self.layer_tabs,-1,self.canvas))
-        self.layer_tabs.AddPage(self.layer_handlers[4],"Fog")
-        self.layer_handlers.append(map_handler(self.layer_tabs,-1,self.canvas))
-        self.layer_tabs.AddPage(self.layer_handlers[5],"General")
+        self.layer_handlers.append(background_handler(self.layer_tabs, -1, self.canvas))
+        self.layer_tabs.AddPage(self.layer_handlers[0], "Background")
+        self.layer_handlers.append(grid_handler(self.layer_tabs, -1, self.canvas))
+        self.layer_tabs.AddPage(self.layer_handlers[1], "Grid")
+        self.layer_handlers.append(miniatures_handler(self.layer_tabs, -1, self.canvas))
+        self.layer_tabs.AddPage(self.layer_handlers[2], "Miniatures", True)
+        self.layer_handlers.append(whiteboard_handler(self.layer_tabs, -1, self.canvas))
+        self.layer_tabs.AddPage(self.layer_handlers[3], "Whiteboard")
+        self.layer_handlers.append(fog_handler(self.layer_tabs, -1, self.canvas))
+        self.layer_tabs.AddPage(self.layer_handlers[4], "Fog")
+        self.layer_handlers.append(map_handler(self.layer_tabs, -1, self.canvas))
+        self.layer_tabs.AddPage(self.layer_handlers[5], "General")
         self.layer_tabs.SetSelection(2)
+
+        self.layer_order = {1: 'grid', 2: 'miniatures', 3: 'whiteboard'}
         self.sizer = wx.BoxSizer(wx.VERTICAL)
         self.sizer.Add(self.canvas, 1, wx.EXPAND)
         self.sizer.Add(self.layer_tabs, 0, wx.EXPAND)
--- a/orpg/mapper/map_msg.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/mapper/map_msg.py	Sat Jun 12 04:38:29 2010 -0500
@@ -53,17 +53,17 @@
 
     def init_from_dom(self,xml_dom):
         self.p_lock.acquire()
-        if xml_dom.tagName == self.tagname:
+        if xml_dom.tag == self.tagname:
             # If this is a map message, look for the "action=new"
             # Notice we only do this when the root is a map tag
-            if self.tagname == "map" and xml_dom.hasAttribute("action") and xml_dom.getAttribute("action") == "new":
+            if self.tagname == "map" and xml_dom.get("action") == "new":
                 self.clear()
             # Process all of the properties in each tag
-            if xml_dom.getAttributeKeys():
-                for k in xml_dom.getAttributeKeys():
-                    self.init_prop(k,xml_dom.getAttribute(k))
-            for c in xml_dom._get_childNodes():
-                name = c._get_nodeName()
+            if xml_dom.keys():
+                for k in xml_dom.keys():
+                    self.init_prop(k,xml_dom.get(k))
+            for c in xml_dom.getchildren():
+                name = c.tag
                 if not self.children.has_key(name):
                     if name == "miniatures": self.children[name] = minis_msg(self.p_lock)
                     elif name == "grid": self.children[name] = grid_msg(self.p_lock)
@@ -84,16 +84,16 @@
 
     def set_from_dom(self,xml_dom):
         self.p_lock.acquire()
-        if xml_dom.tagName == self.tagname:
+        if xml_dom.tag == self.tagname:
             # If this is a map message, look for the "action=new"
             # Notice we only do this when the root is a map tag
-            if self.tagname == "map" and xml_dom.hasAttribute("action") and xml_dom.getAttribute("action") == "new":
+            if self.tagname == "map" and xml_dom.get("action") == "new":
                 self.clear()
             # Process all of the properties in each tag
-            if xml_dom.getAttributeKeys():
-                for k in xml_dom.getAttributeKeys(): self.set_prop(k,xml_dom.getAttribute(k))
-            for c in xml_dom._get_childNodes():
-                name = c._get_nodeName()
+            if xml_dom.keys():
+                for k in xml_dom.keys(): self.set_prop(k,xml_dom.get(k))
+            for c in xml_dom.getchildren():
+                name = c.tag
                 if not self.children.has_key(name):
                     if name == "miniatures": self.children[name] = minis_msg(self.p_lock)
                     elif name == "grid": self.children[name] = grid_msg(self.p_lock)
--- a/orpg/mapper/miniatures.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/mapper/miniatures.py	Sat Jun 12 04:38:29 2010 -0500
@@ -344,27 +344,27 @@
         else: return ''
 
     def takedom(self, xml_dom):
-        self.id = xml_dom.getAttribute("id")
-        if xml_dom.hasAttribute("posx"): self.pos.x = int(xml_dom.getAttribute("posx"))
-        if xml_dom.hasAttribute("posy"): self.pos.y = int(xml_dom.getAttribute("posy"))
-        if xml_dom.hasAttribute("heading"): self.heading = int(xml_dom.getAttribute("heading"))
-        if xml_dom.hasAttribute("face"): self.face = int(xml_dom.getAttribute("face"))
-        if xml_dom.hasAttribute("path"):
-            self.path = urllib.unquote(xml_dom.getAttribute("path"))
+        self.id = xml_dom.get("id")
+        if xml_dom.get("posx") != None: self.pos.x = int(xml_dom.get("posx"))
+        if xml_dom.get("posy") != None: self.pos.y = int(xml_dom.get("posy"))
+        if xml_dom.get("heading") != None: self.heading = int(xml_dom.get("heading"))
+        if xml_dom.get("face") != None: self.face = int(xml_dom.get("face"))
+        if xml_dom.get("path") != None:
+            self.path = urllib.unquote(xml_dom.get("path"))
             self.set_bmp(ImageHandler.load(self.path, 'miniature', self.id))
-        if xml_dom.hasAttribute("locked"):
-            if xml_dom.getAttribute("locked") == '1' or xml_dom.getAttribute("locked") == 'True': self.locked = True
+        if xml_dom.get("locked") != None:
+            if xml_dom.get("locked") == '1' or xml_dom.get("locked") == 'True': self.locked = True
             else: self.locked = False
-        if xml_dom.hasAttribute("hide"):
-            if xml_dom.getAttribute("hide") == '1' or xml_dom.getAttribute("hide") == 'True': self.hide = True
+        if xml_dom.get("hide") != None:
+            if xml_dom.get("hide") == '1' or xml_dom.get("hide") == 'True': self.hide = True
             else: self.hide = False
-        if xml_dom.hasAttribute("label"): self.label = xml_dom.getAttribute("label")
-        if xml_dom.hasAttribute("zorder"): self.zorder = int(xml_dom.getAttribute("zorder"))
-        if xml_dom.hasAttribute("align"):
-            if xml_dom.getAttribute("align") == '1' or xml_dom.getAttribute("align") == 'True': self.snap_to_align = 1
+        if xml_dom.get("label") != None: self.label = xml_dom.get("label")
+        if xml_dom.get("zorder") != None: self.zorder = int(xml_dom.get("zorder"))
+        if xml_dom.get("align") != None:
+            if xml_dom.get("align") == '1' or xml_dom.get("align") == 'True': self.snap_to_align = 1
             else: self.snap_to_align = 0
-        if xml_dom.hasAttribute("width"): self.width = int(xml_dom.getAttribute("width"))
-        if xml_dom.hasAttribute("height"): self.height = int(xml_dom.getAttribute("height"))
+        if xml_dom.get("width") != None: self.width = int(xml_dom.get("width"))
+        if xml_dom.get("height") != None: self.height = int(xml_dom.get("height"))
 
 ##-----------------------------
 ## miniature layer
@@ -489,36 +489,36 @@
         else: return ""
 
     def layerTakeDOM(self, xml_dom):
-        if xml_dom.hasAttribute('serial'):
-            self.serial_number = int(xml_dom.getAttribute('serial'))
-        children = xml_dom._get_childNodes()
+        if xml_dom.get('serial') != None:
+            self.serial_number = int(xml_dom.get('serial'))
+        children = xml_dom.getchildren()
         for c in children:
-            action = c.getAttribute("action")
-            id = c.getAttribute('id')
+            action = c.get("action")
+            id = c.get('id')
             if action == "del": 
                 mini = self.get_miniature_by_id(id)
                 if mini: self.miniatures.remove(mini); del mini
             elif action == "new":
-                pos = cmpPoint(int(c.getAttribute('posx')),int(c.getAttribute('posy')))
-                path = urllib.unquote(c.getAttribute('path'))
-                label = c.getAttribute('label')
+                pos = cmpPoint(int(c.get('posx')),int(c.get('posy')))
+                path = urllib.unquote(c.get('path'))
+                label = c.get('label')
                 height = width = heading = face = snap_to_align = zorder = 0
                 locked = hide = False
-                if c.hasAttribute('height'): height = int(c.getAttribute('height'))
-                if c.hasAttribute('width'): width = int(c.getAttribute('width'))
-                if c.getAttribute('locked') == 'True' or c.getAttribute('locked') == '1': locked = True
-                if c.getAttribute('hide') == 'True' or c.getAttribute('hide') == '1': hide = True
-                if c.getAttribute('heading'): heading = int(c.getAttribute('heading'))
-                if c.hasAttribute('face'): face = int(c.getAttribute('face'))
-                if c.hasAttribute('align'): snap_to_align = int(c.getAttribute('align'))
-                if c.getAttribute('zorder'): zorder = int(c.getAttribute('zorder'))
+                if c.get('height') != None: height = int(c.get('height'))
+                if c.get('width') != None: width = int(c.get('width'))
+                if c.get('locked') == 'True' or c.get('locked') == '1': locked = True
+                if c.get('hide') == 'True' or c.get('hide') == '1': hide = True
+                if c.get('heading') != None: heading = int(c.get('heading'))
+                if c.get('face') != None: face = int(c.get('face'))
+                if c.get('align') != None: snap_to_align = int(c.get('align'))
+                if c.get('zorder') != None: zorder = int(c.get('zorder'))
                 min = BmpMiniature(id, path, ImageHandler.load(path, 'miniature', id), pos, heading, 
                     face, label, locked, hide, snap_to_align, zorder, width, height)
                 self.miniatures.append(min)
-                if c.hasAttribute('local') and c.getAttribute('local') == 'True' and os.path.exists(urllib.unquote(c.getAttribute('localPath'))):
-                    localPath = urllib.unquote(c.getAttribute('localPath'))
+                if c.get('local') == 'True' and os.path.exists(urllib.unquote(c.get('localPath'))):
+                    localPath = urllib.unquote(c.get('localPath'))
                     local = True
-                    localTime = float(c.getAttribute('localTime'))
+                    localTime = float(c.get('localTime'))
                     if localTime-time.time() <= 144000:
                         file = open(localPath, "rb")
                         imgdata = file.read()
--- a/orpg/mapper/miniatures_msg.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/mapper/miniatures_msg.py	Sat Jun 12 04:38:29 2010 -0500
@@ -79,11 +79,11 @@
 
     def init_from_dom(self,xml_dom):
         self.p_lock.acquire()
-        if xml_dom.tagName == self.tagname:
-            if xml_dom.getAttributeKeys():
-                for k in xml_dom.getAttributeKeys(): self.init_prop(k,xml_dom.getAttribute(k))
+        if xml_dom.tag == self.tagname:
+            if xml_dom.keys():
+                for k in xml_dom.keys(): self.init_prop(k,xml_dom.get(k))
 
-            for c in xml_dom._get_childNodes():
+            for c in xml_dom.getchildren():
                 mini = mini_msg(self.p_lock)
                 try: mini.init_from_dom(c)
                 except Exception, e: print e; continue
@@ -103,10 +103,10 @@
 
     def set_from_dom(self,xml_dom):
         self.p_lock.acquire()
-        if xml_dom.tagName == self.tagname:
-            if xml_dom.getAttributeKeys():
-                for k in xml_dom.getAttributeKeys(): self.set_prop(k,xml_dom.getAttribute(k))
-            for c in xml_dom._get_childNodes():
+        if xml_dom.tag == self.tagname:
+            if xml_dom.keys():
+                for k in xml_dom.keys(): self.set_prop(k,xml_dom.get(k))
+            for c in xml_dom.getchildren():
                 mini = mini_msg(self.p_lock)
                 try: mini.set_from_dom(c)
                 except Exception, e: print e; continue
--- a/orpg/mapper/whiteboard.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/mapper/whiteboard.py	Sat Jun 12 04:38:29 2010 -0500
@@ -119,21 +119,21 @@
         else: return ''
 
     def takedom(self, xml_dom):
-        self.text_string = xml_dom.getAttribute("text_string")
-        self.id = xml_dom.getAttribute("id")
-        if xml_dom.hasAttribute("posy"): self.posy = int(xml_dom.getAttribute("posy"))
-        if xml_dom.hasAttribute("posx"): self.posx = int(xml_dom.getAttribute("posx"))
-        if xml_dom.hasAttribute("weight"):
-            self.weight = int(xml_dom.getAttribute("weight"))
+        self.text_string = xml_dom.get("text_string")
+        self.id = xml_dom.get("id")
+        if xml_dom.get("posy") != None: self.posy = int(xml_dom.get("posy"))
+        if xml_dom.get("posx") != None: self.posx = int(xml_dom.get("posx"))
+        if xml_dom.get("weight"):
+            self.weight = int(xml_dom.get("weight"))
             self.font.SetWeight(self.weight)
-        if xml_dom.hasAttribute("style"):
-            self.style = int(xml_dom.getAttribute("style"))
+        if xml_dom.get("style") != None:
+            self.style = int(xml_dom.get("style"))
             self.font.SetStyle(self.style)
-        if xml_dom.hasAttribute("pointsize"):
-            self.pointsize = int(xml_dom.getAttribute("pointsize"))
+        if xml_dom.get("pointsize") != None:
+            self.pointsize = int(xml_dom.get("pointsize"))
             self.font.SetPointSize(self.pointsize)
-        if xml_dom.hasAttribute("color") and xml_dom.getAttribute("color") != '':
-            self.textcolor = xml_dom.getAttribute("color")
+        if xml_dom.get("color") != None and xml_dom.get("color") != '':
+            self.textcolor = xml_dom.get("color")
             if self.textcolor == '#0000000': self.textcolor = '#000000'
 
 class WhiteboardLine:
@@ -231,16 +231,16 @@
         return ''
 
     def takedom(self, xml_dom):
-        self.line_string = xml_dom.getAttribute("line_string")
-        self.id = xml_dom.getAttribute("id")
-        if xml_dom.hasAttribute("upperleftx"): self.upperleft.x = int(xml_dom.getAttribute("upperleftx"))
-        if xml_dom.hasAttribute("upperlefty"): self.upperleft.y = int(xml_dom.getAttribute("upperlefty"))
-        if xml_dom.hasAttribute("lowerrightx"): self.lowerright.x = int(xml_dom.getAttribute("lowerrightx"))
-        if xml_dom.hasAttribute("lowerrighty"): self.lowerright.y = int(xml_dom.getAttribute("lowerrighty"))
-        if xml_dom.hasAttribute("color") and xml_dom.getAttribute("color") != '':
-            self.linecolor = xml_dom.getAttribute("color")
+        self.line_string = xml_dom.get("line_string")
+        self.id = xml_dom.get("id")
+        if xml_dom.get("upperleftx") != None: self.upperleft.x = int(xml_dom.get("upperleftx"))
+        if xml_dom.get("upperlefty") != None: self.upperleft.y = int(xml_dom.get("upperlefty"))
+        if xml_dom.get("lowerrightx") != None: self.lowerright.x = int(xml_dom.get("lowerrightx"))
+        if xml_dom.get("lowerrighty") != None: self.lowerright.y = int(xml_dom.get("lowerrighty"))
+        if xml_dom.get("color") != None and xml_dom.get("color") != '':
+            self.linecolor = xml_dom.get("color")
             if self.linecolor == '#0000000': self.linecolor = '#000000'
-        if xml_dom.hasAttribute("width"): self.linewidth = int(xml_dom.getAttribute("width"))
+        if xml_dom.get("width") != None: self.linewidth = int(xml_dom.get("width"))
 
 ##-----------------------------
 ## whiteboard layer
@@ -416,13 +416,13 @@
         else: return ""
 
     def layerTakeDOM(self, xml_dom):
-        serial_number = xml_dom.getAttribute('serial')
-        if serial_number != "": self.serial_number = int(serial_number)
-        children = xml_dom._get_childNodes()
+        serial_number = xml_dom.get('serial')
+        if serial_number != None: self.serial_number = int(serial_number)
+        children = xml_dom.getchildren()
         for l in children:
-            nodename = l._get_nodeName()
-            action = l.getAttribute("action")
-            id = l.getAttribute('id')
+            nodename = l.tag
+            action = l.get("action")
+            id = l.get('id')
             try:
                 if self.serial_number < int(id.split('-')[2]): self.serial_number = int(id.split('-')[2])
             except: pass
@@ -436,17 +436,17 @@
             elif action == "new":
                 if nodename == "line":
                     try:
-                        line_string = l.getAttribute('line_string')
-                        upperleftx = l.getAttribute('upperleftx')
-                        upperlefty = l.getAttribute('upperlefty')
-                        lowerrightx = l.getAttribute('lowerrightx')
-                        lowerrighty = l.getAttribute('lowerrighty')
+                        line_string = l.get('line_string')
+                        upperleftx = l.get('upperleftx')
+                        upperlefty = l.get('upperlefty')
+                        lowerrightx = l.get('lowerrightx')
+                        lowerrighty = l.get('lowerrighty')
                         upperleft = wx.Point(int(upperleftx),int(upperlefty))
                         lowerright = wx.Point(int(lowerrightx),int(lowerrighty))
-                        color = l.getAttribute('color')
+                        color = l.get('color')
                         if color == '#0000000': color = '#000000'
-                        id = l.getAttribute('id')
-                        width = int(l.getAttribute('width'))
+                        id = l.get('id')
+                        width = int(l.get('width'))
                     except:
                         line_string = upperleftx = upperlefty = lowerrightx = lowerrighty = color = 0
                         continue
@@ -454,15 +454,15 @@
                     self.lines.append(line)
                 elif nodename == "text":
                     try:
-                        text_string = l.getAttribute('text_string')
-                        style = l.getAttribute('style')
-                        pointsize = l.getAttribute('pointsize')
-                        weight = l.getAttribute('weight')
-                        color = l.getAttribute('color')
+                        text_string = l.get('text_string')
+                        style = l.get('style')
+                        pointsize = l.get('pointsize')
+                        weight = l.get('weight')
+                        color = l.get('color')
                         if color == '#0000000': color = '#000000'
-                        id = l.getAttribute('id')
-                        posx = l.getAttribute('posx')
-                        posy = l.getAttribute('posy')
+                        id = l.get('id')
+                        posx = l.get('posx')
+                        posy = l.get('posy')
                         pos = wx.Point(0,0)
                         pos.x = int(posx)
                         pos.y = int(posy)
--- a/orpg/mapper/whiteboard_msg.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/mapper/whiteboard_msg.py	Sat Jun 12 04:38:29 2010 -0500
@@ -80,11 +80,11 @@
 
     def init_from_dom(self,xml_dom):
         self.p_lock.acquire()
-        if xml_dom.tagName == self.tagname:
-            if xml_dom.getAttributeKeys():
-                for k in xml_dom.getAttributeKeys(): self.init_prop(k,xml_dom.getAttribute(k))
-            for c in xml_dom._get_childNodes():
-                item = item_msg(self.p_lock,c._get_nodeName())
+        if xml_dom.tag == self.tagname:
+            if xml_dom.keys():
+                for k in xml_dom.keys(): self.init_prop(k,xml_dom.get(k))
+            for c in xml_dom.getchildren():
+                item = item_msg(self.p_lock,c.tag)
                 try: item.init_from_dom(c)
                 except Exception, e:
                     print e
@@ -105,11 +105,11 @@
 
     def set_from_dom(self,xml_dom):
         self.p_lock.acquire()
-        if xml_dom.tagName == self.tagname:
-            if xml_dom.getAttributeKeys():
-                for k in xml_dom.getAttributeKeys(): self.set_prop(k,xml_dom.getAttribute(k))
-            for c in xml_dom._get_childNodes():
-                item = item_msg(self.p_lock, c._get_nodeName())
+        if xml_dom.tag == self.tagname:
+            if xml_dom.keys():
+                for k in xml_dom.keys(): self.set_prop(k,xml_dom.get(k))
+            for c in xml_dom.getchildren():
+                item = item_msg(self.p_lock, c.tag)
                 try: item.set_from_dom(c)
                 except Exception, e:
                     print e
--- a/orpg/networking/meta_server_lib.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/networking/meta_server_lib.py	Sat Jun 12 04:38:29 2010 -0500
@@ -29,7 +29,7 @@
 
 
 #added debug flag for meta messages to cut console server spam --Snowdog
-META_DEBUG = 0
+META_DEBUG = False
 
 __version__ = "$Id: meta_server_lib.py,v 1.40 2007/04/04 01:18:42 digitalxero Exp $"
 
@@ -42,17 +42,15 @@
 
 from threading import *
 from random import uniform
+import urllib2
 from urllib import urlopen, urlencode
 from orpg.tools.orpg_log import debug
 
-from xml.etree.ElementTree import Element, fromstring
+from xml.etree.ElementTree import Element, fromstring, parse, tostring
 metacache_lock = RLock()
 
-def get_server_dom(data=None,path=None, string=False):
-    # post data at server and get the resulting DOM
-    if path == None:
-        # get meta server URI
-        path = getMetaServerBaseURL()
+def get_server_dom(data=None, path=None, string=False):
+    if path[len(path)-1] != "/": path += '/'
 
     # POST the data
     if META_DEBUG:
@@ -61,9 +59,9 @@
         print "=========================================="
         print data
         print
-    file = urlopen(path, data)
-    data = file.read()
-    file.close()
+    #recvdata = urllib2.Request(path, data)
+    response = urllib2.urlopen(path, data)
+    data = response.read()
 
     # Remove any leading or trailing data.  This can happen on some satellite connections
     p = re.compile('(<servers>.*?</servers>)',re.DOTALL|re.IGNORECASE)
@@ -77,9 +75,8 @@
         print data
         print
     # build dom
-    etreeEl = data
-    if not string: return fromstring(etreeEl)
-    else: return etreeEl
+    if string: return data
+    else: return fromstring(data)
 
 def post_server_data(name, realHostName=None):
     if realHostName: data = urlencode({"server_data[name]":name,
@@ -90,7 +87,7 @@
     else: data = urlencode({"server_data[name]":name,
                                   "server_data[version]":PROTOCOL_VERSION,
                                   "act":"new"})
-    path = component.get('settings').get('MetaServerBaseURL') #getMetaServerBaseURL()
+    path = component.get('settings').get('MetaServerBaseURL') #getMetaServerList()
     etreeEl = get_server_dom(data, path)
     return int(etreeEl.get('id'))
 
@@ -111,49 +108,38 @@
 def byStartAttribute(first, second):
     #  This function is used to easily sort a list of nodes by their start time
     # Ensure there is something to sort with for each
-
     first_start = int(first.get('start')) or 0
     second_start = int(second.get('start')) or 0
-
     # Return the result of the cmp function on the two strings
     return cmp(first_start, second_start)
 
 def byNameAttribute(first, second):
     #  This function is used to easily sort a list of nodes by their name attribute
     # Ensure there is something to sort with for each
-
     first_name = first.get('name') or ''
     second_name = second.get('name') or ''
-    
     # Return the result of the cmp function on the two strings
     return cmp(first_name,second_name)
 
 
-def get_server_list(versions = None, sort_by="start"):
+def get_server_list(versions=None, sort_by="start"):
     data = urlencode({"version":PROTOCOL_VERSION,"ports":"%"})
-    all_metas = getMetaServers(versions, 1)  # get the list of metas
-    base_meta = getMetaServerBaseURL()
-
+    #all_metas = getMetaServers(versions, False)  # get the list of metas
+    meta_list = getMetaServerList()
     #all_metas.reverse()  # The last one checked will take precedence, so reverse the order
                           #  so that the top one on the actual list is checked last
     return_hash = {}      # this will end up with an amalgamated list of servers
 
-    for meta in all_metas: # check all of the metas
+    for meta in meta_list: # check all of the metas
         #get the server's xml from the current meta
         bad_meta = 0
         #print "Getting server list from " + meta + "..."
-        try: xml_dom = get_server_dom(data=data, path=meta)
-        except: bad_meta = 1 #print "Trouble getting servers from " + meta + "..."
+        try: xml_dom = get_server_dom(data, meta.get('url'))
+        except: bad_meta = 1; print "Trouble getting servers from " + meta.get('url') + "..."
         if bad_meta: continue
-        if base_meta == meta: updateMetaCache(xml_dom) #print "This is our base meta: " + meta
         node_list = xml_dom.findall('server')
-        if len(node_list):  # if there are entries in the node list
-                            #  otherwise, just loop to next meta
-
-            #  for each node found, we're going to check the nodes from prior
-            #  metas in the list.  If a match is found, then use the new values.
+        if len(node_list): 
             for n in node_list:
-                # set them from current node
                 if not n.get('name'): n.set('name','NO_NAME_GIVEN')
                 name = n.get('name')
                 if not n.get('num_users'): n.set('num_users','N/A')
@@ -165,24 +151,15 @@
                 n.set('meta',meta)
                 end_point = str(address) + ":" + str(port)
                 if return_hash.has_key(end_point):
+                    print end_point
+                    print n
+                    
                     if META_DEBUG: print "Replacing duplicate server entry at " + end_point
                 return_hash[end_point] = n
-
-    #  At this point, we have an amalgamated list of servers
-    #  Now, we have to construct a new DOM to pass back.
-
-    #  Create a servers element
     server_list = Element('servers')
-
-    #  get the nodes stored in return_hash
     sort_list = return_hash.values()
-
-    #  sort them by their name attribute.  Uses byNameAttribute()
-    #  defined above as a comparison function
     if sort_by == "start": sort_list.sort(byStartAttribute)
     elif sort_by == "name": sort_list.sort(byNameAttribute)
-
-    #  Add each node to the DOM
     for n in sort_list: server_list.append(n)
     return server_list
 
@@ -216,122 +193,32 @@
         if META_DEBUG: traceback.print_exc()
         print "Meta Server Lib: UpdateMetaCache(): " + str(e)
 
-def getRawMetaList(path=None):
-    ### Alpha ### 
-    """This code will allow for a list of metas to be created.  Future developement  will more integrate the list of metas"""
-    if path != None: 
-        metas = []
-        data = urlencode({"version":PROTOCOL_VERSION,"ports":"%"})
-        xml_dom = get_server_dom(data, path)
-        node_list = fromstring(xml_dom).findall('meta_server')
-        if len(node_list):
-             for n in node_list:
-                 metas.append(n.get('path'))
-        return metas
+
+def getMetaServerList():
+    # get meta server URL
+    meta_list = fromstring("""
+        <metaservers>
+            <meta url="http://orpgmeta.appspot.com" versions="1 2" />
+            <meta url="http://traipsemeta.madmathlabs.info" versions="1 2" />
+        </metaservers>"""
+        )
     try:
-        try:
-            metacache_lock.acquire()
-            #  Read in the metas
-            validate.config_file("metaservers.cache","metaservers.cache")
-            ini = open(dir_struct["user"]+"metaservers.cache","r")
-            metas = ini.readlines()
-            ini.close()
-            return metas
-        finally:
-            metacache_lock.release()
-    except Exception, e:
-        if META_DEBUG: traceback.print_exc()
-        print "Meta Server Lib: getRawMetaList(): " + str(e)
-        return []
-
-def getMetaServers(versions = None, pick_random=0):
-    """
-     get meta server URLs as a list
-      versions is a list of acceptable version numbers.
-        A False truth value will use getMetaServerBaseURL()
-     set a default if we have weird reading problems
-     default_url = "http://www.openrpg.com/openrpg_servers.php"
-    """
-
-    ### Pre Alpha Design ###
-    """ Here is how to handle Multiple Meta servers, and probably the best way to do it.  Create an XML file that contains nodes with the various servers. Users will grab that meta data and have the option to connect to multiple meta servers which will allow them to find all the rooms.  A check box should be used so if one server faile the users can continue without much lag.  When creating a server hosts will need to select a meta to go too.  This should be in the final of Ornery Orc."""
-    meta_names = []
-    if(versions):  #  If versions are supplied, then look in metaservers.conf
-        try:
-            """
-              read in the metas from file
-              format of file is one meta entry per line
-              each entry will be the meta url, followed by one or more version numbers that it
-              handle.  Generally, this will be either a 1 for the original Meta format, or
-              2 for the new one.
-            """
-            #  Read in the metas
-            #Adding a path object will attempt to look for a meta_network.
-            metas = getRawMetaList()
-
-            # go through each one to check if it should be returned, based on the
-            #   version numbers allowed.
-            for meta in metas:
-                # split the line on whitespace
-                #   obviously, your meta servers urls shouldn't contain whitespace.  duh.
-                words = meta.split()
-                success = 0         #  init success flag for version check
-                for version in versions:    # run through each allowed version from caller
-                    if version in words[1:]:  #  if the allowed version token was found
-                        success += 1          #  then increment the success indicator
-                if success:          #  if the meta entry is acceptable to the caller
-                    meta_names.append(words[0])    #  add the entry
-                    if META_DEBUG: print "adding metaserver " + meta
-
-            #  at this point, we should have at least one name from the cache.  If not ...
-            if not meta_names:
-                default_meta = getMetaServerBaseURL()       # grab the meta from ini.xml
-                meta_names.append(default_meta)             # add it to the return list
-            # print "Warning!!\nNo valid metaservers cached."
-            # print "Using meta from MetaServerBaseURL: " + default_meta + "\n"
-            # if we have more than one and want a random one
-            elif pick_random:
-                if META_DEBUG: print "choosing random meta from: " + str(meta_names)
-                i = int(uniform(0,len(meta_names)))
-                #meta = meta_names[i]
-                meta_names = [meta_names[i]]
-                if META_DEBUG: print "using: " + str(meta_names)
-            else:
-                if META_DEBUG: print "using all metas: " + str(meta_names)
-            return meta_names
-        except Exception,e:
-            print e
-            #print "using default meta server URI: " + default_url
-            metas = []
-            #metas.append(default_url)
-            return metas   # return an empty list
-    else:        #  otherwise, use MetaServerBaseURL()
-        url = getMetaServerBaseURL()
-        meta_names.append(url)
-        return meta_names
-
-def getMetaServerBaseURL():
-    # get meta server URL
-    url = "http://orpgmeta.appspot.com/"
-    try:
+        component.get('validate').config_file("metaservers.xml","default_metaservers.xml")
         component.get('validate').config_file("settings.xml","default_settings.xml")
-        ini = open(dir_struct["user"]+"settings.xml","r")
-        txt = ini.read()
-        xml = component.get('xml')
-        tree = xml.parseXml(txt)._get_documentElement()
-        ini.close()
-        node_list = tree.getElementsByTagName("MetaServerBaseURL")
-        if node_list:
-            url = node_list[0].getAttribute("value")
-        print url
-        # allow tree to be collected
-        try: tree.unlink()
-        except: pass
-
-    except Exception,e:
-        print e
-    #print "using meta server URI: " + url
-    return url
+        setting = parse(dir_struct["user"]+"settings.xml")
+        tree = setting.getroot()
+        node_list = tree.getiterator("MetaServers")
+        if len(node_list) == 0:
+            component.get('frame').add_setting('Meta Servers')
+            setting = parse(dir_struct["user"]+"settings.xml")
+            metas = parse(dir_struct["user"]+'metaservers.xml').getroot()
+        else: 
+            meta = node_list[0].get("value")
+            metas = parse(dir_struct["user"]+meta).getroot()
+        meta_list = metas.findall('meta')
+        return meta_list
+    except Exception,e: print e
+    return meta_list
 
 """
   Beginning of Class registerThread
@@ -396,7 +283,7 @@
           it easier to have multiple registerThreads going to keep the server registered
           on multiple (compatible) Metas.
         """
-        if MetaPath == None: self.path = getMetaServerBaseURL()  #  Do this if no Meta specified
+        if MetaPath == None: self.path = getMetaServerList()  #  Do this if no Meta specified
         else: self.path = MetaPath
 
     def getIdAndCookie(self):
@@ -469,16 +356,18 @@
             if not self.isAlive():      #  check to see if this thread is dead
                 return 1                #  If so, return an error result
             #  Do the actual unregistering here
-            data = urlencode( {"server_data[id]":self.id,
+            data = urlencode( {         "server_data[id]":self.id,
                                         "server_data[cookie]":self.cookie,
                                         "server_data[version]":PROTOCOL_VERSION,
                                         "act":"unregister"} )
-            try: # this POSTS the request and returns the result
-                xml_dom = get_server_dom(data=data, path=self.path)  
-                if xml_dom.get("errmsg"):
-                    print "Error durring unregistration:  " + xml_dom.get("errmsg")
-            except:
-                if META_DEBUG: print "Problem talking to Meta.  Will go ahead and die, letting Meta remove us."
+            for path in getMetaServerList():
+                try: # this POSTS the request and returns the result
+                    etreeEl = get_server_dom(data, path.get('url'))
+                    if etreeEl.get("errmsg") != None:
+                        print "Error durring unregistration:  " + etreeEl.get("errmsg")
+                except Exception, e:
+                    if META_DEBUG: print "Problem talking to Meta.  Will go ahead and die, letting Meta remove us."
+                    if META_DEBUG: print e
             #  If there's an error, echo it to the console
 
             #  No special handling is required.  If the de-registration worked we're done.  If
@@ -509,11 +398,14 @@
 
             #  Set the server's attibutes, if specified.
             if name: self.name = name
-            if num_users != None: self.num_users = num_users
+            if num_users != None: 
+                try: self.num_users = len(num_users)
+                except: self.num_users = num_users; print num_users
+            else: self.num_users = 0
             if realHostName: self.realHostName = realHostName
             # build POST data
             if self.realHostName:
-                data = urlencode( {"server_data[id]":self.id,
+                data = urlencode( {     "server_data[id]":self.id,
                                         "server_data[cookie]":self.cookie,
                                         "server_data[name]":self.name,
                                         "server_data[port]":self.port,
@@ -523,38 +415,40 @@
                                         "server_data[address]": self.realHostName } )
             else:
                 if META_DEBUG:  print "Letting meta server decide the hostname to list..."
-                data = urlencode( {"server_data[id]":self.id,
+                data = urlencode( {     "server_data[id]":self.id,
                                         "server_data[cookie]":self.cookie,
                                         "server_data[name]":self.name,
                                         "server_data[port]":self.port,
                                         "server_data[version]":PROTOCOL_VERSION,
                                         "server_data[num_users]":self.num_users,
                                         "act":"register"} )
-            try: # this POSTS the request and returns the result
-                etreeEl = get_server_dom(data=data, path=self.path)
-            except:
-                if META_DEBUG: print "Problem talking to server.  Setting interval for retry ..."
-                if META_DEBUG: print data
-                if META_DEBUG: print
-                self.interval = 0
-                """
-                  If we are in the registerThread thread, then setting interval to 0
-                  will end up causing a retry in about 6 seconds (see self.run())
-                  If we are in the main thread, then setting interval to 0 will do one
-                  of two things:
-                  1)  Do the same as if we were in the registerThread
-                  2)  Cause the next, normally scheduled register() call to use the values
-                      provided in this call.
-                
-                  Which case occurs depends on where the registerThread thread is when
-                  the main thread calls register().
-                """
-                return 0  # indicates that it was okay to call, not that no errors occurred
+            for path in getMetaServerList():
+                try: # this POSTS the request and returns the result
+                    etreeEl = get_server_dom(data, path.get('url'))
+                except Exception, e:
+                    if META_DEBUG: print "Problem talking to server.  Setting interval for retry ..."
+                    if META_DEBUG: print data
+                    if META_DEBUG: print e
+                    self.interval = 0
+                    """
+                      If we are in the registerThread thread, then setting interval to 0
+                      will end up causing a retry in about 6 seconds (see self.run())
+                      If we are in the main thread, then setting interval to 0 will do one
+                      of two things:
+                      1)  Do the same as if we were in the registerThread
+                      2)  Cause the next, normally scheduled register() call to use the values
+                          provided in this call.
+                    
+                      Which case occurs depends on where the registerThread thread is when
+                      the main thread calls register().
+                    """
+                    return 0  # indicates that it was okay to call, not that no errors occurred
 
             #  If there is a DOM returned ....
-            if etreeEl:
+            if etreeEl != None:
                 #  If there's an error, echo it to the console
-                if etreeEl.get("errmsg"):
+                print tostring(etreeEl)
+                if etreeEl.get("errmsg") != None:
                     print "Error durring registration:  " + etreeEl.get("errmsg")
                     if META_DEBUG: print data
                     if META_DEBUG: print
@@ -580,11 +474,12 @@
                     self.interval = int(etreeEl.get("interval"))
                     self.id = etreeEl.get("id")
                     self.cookie = etreeEl.get("cookie")
-                    if not etreeEl.get("errmsg"): updateMetaCache(xml_dom)
-                except:
+                    #if etreeEl.get("errmsg") == None: updateMetaCache(xml_dom)
+                except Exception, e:
                     if META_DEBUG: print
                     if META_DEBUG: print "OOPS!  Is the Meta okay?  It should be returning an id, cookie, and interval."
                     if META_DEBUG: print "Check to see what it really returned.\n"
+                    if META_DEBUG: print e
                 #  Let xml_dom get garbage collected
                 try: xml_dom.unlink()
                 except: pass
--- a/orpg/networking/mplay_client.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/networking/mplay_client.py	Sat Jun 12 04:38:29 2010 -0500
@@ -38,7 +38,7 @@
 from orpg.orpg_version import CLIENT_STRING, PROTOCOL_VERSION, VERSION
 
 from orpg.orpgCore import component
-from orpg.orpg_xml import xml
+#from orpg.orpg_xml import xml
 from orpg.tools.orpg_log import debug
 from orpg.tools.settings import settings
 
@@ -81,6 +81,7 @@
 STATUS_SET_URL = 1
 
 def parseXml(data):
+    debug(('Developers note. Deprecated call to parseXml!!'), parents=True)
     "parse and return doc"
     doc = xml.parseXml(data)
     doc.normalize()
@@ -387,7 +388,6 @@
     def __init__(self,name,callbacks):
         client_base.__init__(self)
         component.add('mp_client', self)
-        self.xml = component.get('xml')
         self.set_name(name)
         self.on_receive = callbacks['on_receive']
         self.on_mplay_event = callbacks['on_mplay_event']
--- a/orpg/networking/mplay_server.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/networking/mplay_server.py	Sat Jun 12 04:38:29 2010 -0500
@@ -616,7 +616,7 @@
 
     def register_callback(instance, xml_dom = None, source=None):
         if xml_dom:    # if we get something
-            if source == getMetaServerBaseURL():    # if the source of this DOM is the authoritative meta
+            if source == getMetaServerList():    # if the source of this DOM is the authoritative meta
                 try:
                     metacache_lock.acquire()
                     curlist = getRawMetaList()      #  read the raw meta cache lines into a list
@@ -648,21 +648,22 @@
 
     def registerRooms(self, args=None):
         rooms = ''
-        id = '0'
-        time.sleep(500)
-        for rnum in self.groups.keys():
-            rooms += urllib.urlencode( {"room_data[rooms][" + str(rnum) + "][name]":self.groups[rnum].name,
-                                        "room_data[rooms][" + str(rnum) + "][pwd]":str(self.groups[rnum].pwd != "")})+'&'
-            for pid in self.groups[rnum].players:
-                rooms += urllib.urlencode( {"room_data[rooms][" + str(rnum) + "][players]["+str(pid)+"]":self.players[pid].name,})+'&'
+        serverId = '0'
+        x = 0
         for meta in self.metas.keys():
-            while id == '0':
-                id, cookie = self.metas[meta].getIdAndCookie()
-                data = urllib.urlencode( {"room_data[server_id]":id,
-                                        "act":'registerrooms'})
-            get_server_dom(data+'&'+rooms, self.metas[meta].path, string=True)
+            while serverId == '0':
+                serverId, cookie = self.metas[meta].getIdAndCookie()
+            if serverId != '0':
+                for rnum in self.groups.keys():
+                    rooms += urllib.urlencode({"room_data[rooms][" +str(rnum)+ "][name]":self.groups[rnum].name,
+                                            "room_data[rooms][" +str(rnum)+ "][pwd]":str(self.groups[rnum].pwd != ""),
+                                            "room_data[rooms][" +str(rnum)+ "][players]":str(len(self.groups[rnum].players))
+                                            })+'&'
+                data = urllib.urlencode({"room_data[server_id]":serverId,
+                                         "act":'registerrooms'})
+                get_server_dom(data+'&'+rooms, meta.get('url'), string=True)
 
-    def register(self,name_given=None):
+    def register(self, name_given=None):
         if name_given == None: name = self.name
         else: self.name = name = name_given
         name = self.clean_published_servername(name)
@@ -672,11 +673,10 @@
         else: num_players = 0
 
         #  request only Meta servers compatible with version 2
-        metalist = getMetaServers(versions=["2"])
+        metalist = getMetaServerList()
         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.get('url'))
         """
         #  Go through the list and see if there is already a running register
         #  thread for the meta.
@@ -686,7 +686,6 @@
         #  iterate through the currently running metas and prune any
         #  not currently listed in the Meta Server list.
         """
-
         if self.show_meta_messages != 0: self.log_msg( "Checking running register threads for outdated metas.")
         for meta in self.metas.keys():
             if self.show_meta_messages != 0: self.log_msg("meta:" + meta + ": ")
@@ -699,7 +698,7 @@
 
         #  Now call register() for alive metas or start one if we need one
         for meta in metalist:
-            if self.metas.has_key(meta) and self.metas[meta] and self.metas[meta].isAlive():
+            if (self.metas.has_key(meta) and self.metas[meta] and self.metas[meta].isAlive()):
                 self.metas[meta].register(name=name, 
                                         realHostName=self.server_address, 
                                         num_users=num_players)
@@ -1211,11 +1210,9 @@
                 self.log_msg(("update_group", (self.groups[LOBBY_ID].name, LOBBY_ID, len(self.groups[LOBBY_ID].players) ) ))
                 cmsg = ("connect", props) #################################################
                 self.log_msg(cmsg)
-
-                #  If already registered then re-register, thereby updating the Meta
-                #    on the number of players
-                if self.be_registered:
-                    self.register()
+                for meta in self.metas.keys():
+                    self.metas[meta].num_users = len(self.players)
+                thread.start_new_thread(self.registerRooms,(0,))
         except:
             traceback.print_exc()
 
@@ -1809,14 +1806,9 @@
             del self.players[id]
             self.log_msg(dmsg)
             self.log_msg(("disconnect",id))
-            """
-            #  If already registered then re-register, thereby updating the Meta
-            #    on the number of players
-            #  Note:  Upon server shutdown, the server is first unregistered, so
-            #           this code won't be repeated for each player being deleted.
-            """
-            if self.be_registered:
-                self.register()
+            for meta in self.metas.keys():
+                self.metas[meta].num_users = len(self.players)
+            thread.start_new_thread(self.registerRooms,(0,))
         except Exception, e: self.log_msg( ('exception', str(e)) )
         self.log_msg("Explicit garbage collection shows %s undeletable items." % str(gc.collect()))
 
--- a/orpg/networking/mplay_server_gui.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/networking/mplay_server_gui.py	Sat Jun 12 04:38:29 2010 -0500
@@ -658,19 +658,20 @@
                 wx.EndBusyCursor()
             else: self.show_error("Server is already running.", "Error Starting Server")
 
-    def OnStop(self, event = None):
+    def OnStop(self, event=None):
         """ Stop server. """
         if self.STATUS == SERVER_RUNNING:
-            self.OnUnregister()
+            self.OnUnregister(event)
             self.server.stop()
             self.STATUS = SERVER_STOPPED
-            self.sb.SetStatusText("Stopped", 3)
-            self.SetTitle(__appname__ + "- (stopped) - (unregistered)")
-            self.mainMenu.Enable(1, True)
-            self.mainMenu.Enable(2, False)
-            self.mainMenu.Enable(4, False)
-            self.mainMenu.Enable(5, False)
-            self.conns.DeleteAllItems()
+            if event != 'Quit':
+                self.sb.SetStatusText("Stopped", 3)
+                self.SetTitle(__appname__ + "- (stopped) - (unregistered)")
+                self.mainMenu.Enable(1, True)
+                self.mainMenu.Enable(2, False)
+                self.mainMenu.Enable(4, False)
+                self.mainMenu.Enable(5, False)
+                self.conns.DeleteAllItems()
 
     def OnRegister(self, event = None):
         """ Call into mplay_server's register() function.
@@ -695,11 +696,12 @@
         """
         wx.BeginBusyCursor()
         self.server.server.unregister()
-        self.sb.SetStatusText("Unregistered", 4)
-        self.mainMenu.Enable(5, False)
-        self.mainMenu.Enable(4, True)
-        #self.mainMenu.Enable( 2, True )
-        self.SetTitle(__appname__ + "- (running) - (unregistered)")
+        if event != 'Quit':
+            self.sb.SetStatusText("Unregistered", 4)
+            self.mainMenu.Enable(5, False)
+            self.mainMenu.Enable(4, True)
+            #self.mainMenu.Enable( 2, True )
+            self.SetTitle(__appname__ + "- (running) - (unregistered)")
         wx.EndBusyCursor()
 
     def ModifyBanList(self, event):
@@ -726,7 +728,7 @@
 
     def ExitConfirmed(self, event=None):
         """ Quit the program. """
-        self.OnStop()
+        self.OnStop('Quit')
         self.BanListDialog.Destroy()
         wx.CallAfter(self.Destroy)
 
--- a/orpg/orpg_version.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/orpg_version.py	Sat Jun 12 04:38:29 2010 -0500
@@ -2,9 +2,9 @@
 SERVER_MIN_CLIENT_VERSION = "1.7.1"
 
 #BUILD NUMBER FORMAT: "YYMMDD-##" where ## is the incremental daily build index (if needed)
-DISTRO = "Traipse Alpha"
+DISTRO = "Traipse"
 DIS_VER = "Ornery Orc"
-BUILD = "100503-01"
+BUILD = "100612-01"
 
 # This version is for network capability.
 PROTOCOL_VERSION = "1.2"
--- a/orpg/orpg_windows.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/orpg_windows.py	Sat Jun 12 04:38:29 2010 -0500
@@ -56,49 +56,54 @@
         pos = string.rfind(file_name,'.')
         ext = string.lower(file_name[pos+1:])
         img_type = 0
-	recycle_bin = {"gif": wx.BITMAP_TYPE_GIF, "jpg": wx.BITMAP_TYPE_JPEG, 
+        recycle_bin = {"gif": wx.BITMAP_TYPE_GIF, "jpg": wx.BITMAP_TYPE_JPEG, 
         "jpeg": wx.BITMAP_TYPE_JPEG, "bmp": wx.BITMAP_TYPE_BMP, "png": wx.BITMAP_TYPE_PNG}
-	if recycle_bin.has_key(ext): img_type = recycle_bin[ext]
-	else: img_type = None
-	del recycle_bin; return img_type
+        if recycle_bin.has_key(ext): img_type = recycle_bin[ext]
+        else: img_type = None
+        del recycle_bin; return img_type
 
 ################################
 ## Tabs
 ################################
 class orpgTabberWnd(FNB.FlatNotebook):
-    def __init__(self, parent, closeable=False, size=wx.DefaultSize, style = False):
+    def __init__(self, parent, closeable=False, size=wx.DefaultSize, style=False):
         nbstyle = FNB.FNB_HIDE_ON_SINGLE_TAB|FNB.FNB_BACKGROUND_GRADIENT
+        if style: nbstyle |= style
         FNB.FlatNotebook.__init__(self, parent, -1, size=size, style=nbstyle)
         rgbcovert = orpg.tools.rgbhex.RGBHex()
         self.log = component.get("log")
         self.log.log("Enter orpgTabberWnd", ORPG_DEBUG)
         self.settings = component.get("settings")
-        tabtheme = self.settings.get_setting('TabTheme')
-        tabtext = self.settings.get_setting('TabTextColor')
+        tabtheme = self.settings.get('TabTheme')
+        tabtext = self.settings.get('TabTextColor')
         (tred, tgreen, tblue) = rgbcovert.rgb_tuple(tabtext)
-        tabbedwindows = component.get("tabbedWindows")
-        tabbedwindows.append(self)
-        component.add("tabbedWindows", tabbedwindows)
+        component.get("tabbedWindows").append(self)
 
         theme_dict = {'slanted&aqua': FNB.FNB_VC8, 'slanted&bw': FNB.FNB_VC8, 'flat&aqua': FNB.FNB_FANCY_TABS, 
-            'flat&bw': FNB.FNB_FANCY_TABS, 'customflat': FNB.FNB_FANCY_TABS, 'customslant': FNB.FNB_VC8, 
-            'slanted&colorful': FNB.FNB_VC8|FNB.FNB_COLORFUL_TABS, 'slant&colorful': FNB.FNB_VC8|FNB.FNB_COLORFUL_TABS}
-        nbstyle |= theme_dict[tabtheme]
-        if style: nbstyle |= style
-        self.SetWindowStyleFlag(nbstyle)
+            'flat&bw': FNB.FNB_FANCY_TABS, 'customflat': FNB.FNB_FANCY_TABS, 'customslant': FNB.FNB_VC8}
+            #'slanted&colorful': FNB.FNB_VC8|FNB.FNB_COLORFUL_TABS, 'slant&colorful': FNB.FNB_VC8|FNB.FNB_COLORFUL_TABS}
+        if theme_dict.has_key(tabtheme): style |= theme_dict[tabtheme]
+        else: style |= theme_dict['customflat']; self.settings.change('TabTheme', 'customflat')
+        self.SetWindowStyleFlag(style)
+
+        tabbg = self.settings.get('TabBackgroundGradient')
+        (red, green, blue) = rgbcovert.rgb_tuple(tabbg)
+        self.SetTabAreaColour(wx.Color(red, green, blue))
 
         # Tas - sirebral.  Planned changes to the huge statement below.  
         if tabtheme == 'slanted&aqua':
             self.SetGradientColourTo(wx.Color(0, 128, 255))
             self.SetGradientColourFrom(wx.WHITE)
+            self.SetNonActiveTabTextColour(wx.BLACK)
 
         elif tabtheme == 'slanted&bw':
             self.SetGradientColourTo(wx.WHITE)
             self.SetGradientColourFrom(wx.WHITE)
+            self.SetNonActiveTabTextColour(wx.BLACK)
 
         elif tabtheme == 'flat&aqua':
-            self.SetGradientColourFrom(wx.Color(0, 128, 255))
-            self.SetGradientColourTo(wx.WHITE)
+            self.SetGradientColourTo(wx.Color(0, 128, 255))
+            self.SetGradientColourFrom(wx.WHITE)
             self.SetNonActiveTabTextColour(wx.BLACK)
 
         elif tabtheme == 'flat&bw':
@@ -107,28 +112,21 @@
             self.SetNonActiveTabTextColour(wx.BLACK)
 
         elif tabtheme == 'customflat':
-            gfrom = self.settings.get_setting('TabGradientFrom')
-            (red, green, blue) = rgbcovert.rgb_tuple(gfrom)
-            self.SetGradientColourFrom(wx.Color(red, green, blue))
+            (red, green, blue) = rgbcovert.rgb_tuple(self.settings.get_setting('TabGradientTo'))
+            self.SetGradientColourTo(wx.Color(red, green, blue))
 
-            gto = self.settings.get_setting('TabGradientTo')
-            (red, green, blue) = rgbcovert.rgb_tuple(gto)
-            self.SetGradientColourTo(wx.Color(red, green, blue))
+            (red, green, blue) = rgbcovert.rgb_tuple(self.settings.get_setting('TabGradientFrom'))
+            self.SetGradientColourFrom(wx.Color(red, green, blue))
             self.SetNonActiveTabTextColour(wx.Color(tred, tgreen, tblue))
 
         elif tabtheme == 'customslant':
-            gfrom = self.settings.get_setting('TabGradientFrom')
-            (red, green, blue) = rgbcovert.rgb_tuple(gfrom)
-            self.SetGradientColourFrom(wx.Color(red, green, blue))
+            (red, green, blue) = rgbcovert.rgb_tuple(self.settings.get_setting('TabGradientTo'))
+            self.SetGradientColourTo(wx.Color(red, green, blue))
 
-            gto = self.settings.get_setting('TabGradientTo')
-            (red, green, blue) = rgbcovert.rgb_tuple(gto)
-            self.SetGradientColourTo(wx.Color(red, green, blue))
+            (red, green, blue) = rgbcovert.rgb_tuple(self.settings.get_setting('TabGradientFrom'))
+            self.SetGradientColourFrom(wx.Color(red, green, blue))
             self.SetNonActiveTabTextColour(wx.Color(tred, tgreen, tblue))
 
-        tabbg = self.settings.get_setting('TabBackgroundGradient')
-        (red, green, blue) = rgbcovert.rgb_tuple(tabbg)
-        self.SetTabAreaColour(wx.Color(red, green, blue))
         self.Refresh()
         self.log.log("Exit orpgTabberWnd", ORPG_DEBUG)
 
--- a/orpg/orpg_xml.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/orpg_xml.py	Sat Jun 12 04:38:29 2010 -0500
@@ -31,7 +31,7 @@
 from orpg.tools.orpg_log import logger, debug
 
 class xml:
-    debug('Developers note. Deprecated call to orpg_xml!!')
+    debug(('Developers note. Deprecated call to orpg_xml!!'), parents=True)
     def __init__(self):
         pass
 
--- a/orpg/templates/default_settings.xml	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/templates/default_settings.xml	Sat Jun 12 04:38:29 2010 -0500
@@ -2,9 +2,9 @@
     <tab name="General" type="tab">
         <tab name="Networking" type="grid">
             <Heartbeat options="bool" value="1" help="This sends a message to the server to keep alive your connection when idle." />
-            <MetaServerBaseURL help="This is the URL that contains the server list." options="URL" value="http://orpgmeta.appspot.com/"/>
+            <MetaServers help="Contains a list of Meta Servers" options=".xml file" value="metaservers.xml"/>
             <ImageServerBaseURL help="This is the URL that contains the server list." options="URL" value="http://openrpg.digitalxero.net/imgupload/index.php"/>
-            <LocalorRemote help="Decide to load files locally or remotely. CherryPy must be running for local files." options="Local | Remote" value="Local"/>
+            <LocalorRemote help="Decide to load files locally or remotely. CherryPy must be running for local files." options="Local | Remote" value="Remote"/>
         </tab>
         <tab name="Sound" type="grid">
             <UnixSoundPlayer help="This is the path to the executable used by unix clients to play sounds." options="path to executable" value=""/>
--- a/orpg/templates/feature.xml	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/templates/feature.xml	Sat Jun 12 04:38:29 2010 -0500
@@ -65,40 +65,84 @@
         </nodehandler>
       </nodehandler>
       <nodehandler class="tabber_handler" frame="400,400,424,101" icon="gear" map="Traipse OpenRPG::User Manual" module="containers" name="Game Tree" version="1.0">
-        <nodehandler class="tabber_handler" frame="400,400,275,122" icon="labtop" map="Traipse OpenRPG::User Manual::Game Tree" module="containers" name="Namespace" version="1.0"><nodehandler class="textctrl_handler" frame="400,400,257,105" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Namespace" module="forms" name="Introduction" version="1.0">
-          <text hide_title="0" multiline="1" raw_mode="0" send_button="0">  Persistant users who wanted the stability of Traipse and the ease of Namespace have described to me how they envision Namespace should work. When I heard this I immediately realized that my method provided the aspects users wanted, but not simplicity in design this method would provide. The Traipse Namespace is a little different than Standard but it offers more stability in it's approach
+        <nodehandler class="tabber_handler" frame="400,400,472,75" icon="labtop" map="Traipse OpenRPG::User Manual::Game Tree" module="containers" name="Namespace 2.0" version="1.0"><nodehandler class="textctrl_handler" frame="400,400,393,95" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Namespace 2.0" module="forms" name="Introduction" version="1.0"><text hide_title="0" multiline="1" raw_mode="0" send_button="0">Namespace 2.0
 
-  There are two methods provided with the Traipse Namespace, and these two allow you to a great deal of control when you choose to use Namespace to reference your nodes.
+Internal Namespace: !=NodeName=! or !=GridName::Row,Colum=!
+External Namespace: !&amp;Container::NodeName&amp;! or !&amp;Container::GridName::Row,Colum&amp;!
+
+Namespace 2.0 now has two different ways of finding nodes in your gametree: Internal and 
+External. The new version will find nodes differently based on which method you use. With External you start looking from the gametree but can define a "container" to be more specific. With Internal you start looking from the "node" the reference is in and look through the tree backwards. You can now reference cells within a grid using either.
 
-There is only one difference in how these two methods work, so once you get the hang of Namespace, you will always know how it works. The difference is, External starts looking from the Game Tree and gets more narrow where as Internal starts from the node it is inside and searchs backwards getting more broad.
-</text>
-        </nodehandler><nodehandler class="textctrl_handler" frame="400,400,257,105" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Namespace" module="forms" name="Usage" version="1.0">
-          <text hide_title="0" multiline="1" raw_mode="0" send_button="1">Namespace Internal: 
-(Syntax) !=Node=!
+*An explanation of terms*
+Gametree: The list of objects on the left-hand side of the window that holds all your nodes.
+Node: Refers to any object in the gametree.
+Container: Refers only to those nodes that are capable of storing other nodes (Splitter, 
+Tabbers, Folder, Forms, etc.). Used here, it usually refers to the largest container, i.e. the 
+one that shows up in the gametree when fully collapsed. A Container can contain other 
+containers.
+</text></nodehandler><nodehandler class="textctrl_handler" frame="400,400,393,95" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Namespace 2.0" module="forms" name="Internal" version="1.0"><text hide_title="0" multiline="1" raw_mode="0" send_button="0">Internal Namespace: !=NodeName=!
+-Used from within a node to call another node in the same container, such as a list node 
+calling a text node or grid. *Note* Will not work if multiple nodes within the same container 
+have the same name. Multiple nodes within the entirety of the gametree can have the same names 
+though as long as they are in different containers.
+-Uses the !=NodeName=! syntax for normal nodes.
+-Uses !=GridName::Row,Colum=! to reference cells within a grid
+
+Examples: 
+!=Strength=! 
+(Will find the node named &#8220;Strength&#8221; in the same container and insert it in place of 
+!=Strength=!)
 
-Usage: When you use Namespace Internal the software finds the tree map of the node and searches for the top node. Once that node is found it will iterate through the node and look for the reference you have assigned. If it cannot find it in that node, then it will iterate through the map, finding all successive nodes and searching them
+!=Ability Scores::3,5=! 
+(Will find cell in Row number 3 and Colum number 5 and insert the information contained there 
+in place of !=Ability Scores::3,5=! )</text></nodehandler><nodehandler class="textctrl_handler" frame="400,400,393,95" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Namespace 2.0" module="forms" name="External" version="1.0"><text hide_title="0" multiline="1" raw_mode="0" send_button="0">External Namespace: !&amp;Container::NodeName&amp;!
+-Can only be used from chat (currently) to call a node from anywhere in the gametree. You must 
+specify the container the node is in. You only have to specify the &#8216;largest&#8217; container 
+(typically the one that shows in the gametree when fully collapsed). It doesn&#8217;t matter how 
+many smaller containers within the same container it&#8217;s in, you need only reference the 
+largest. *Note* Will not work if multiple nodes within the same container have the same name. 
+Multiple nodes within the entirety of the gametree can have the same names though as long as 
+they are in different containers.
+-Uses the !&amp;Container::NodeName&amp;! syntax for normal nodes.
+-Uses !&amp;Container::NodeName::Row,Colum&amp;! to reference cells within a grid.
 
-  Namespace Internal is completely context sensitive. You can assign a reference using the Namespace Internal method and it will always find the correct PC Sheet to search in.
-
-Namespace Internal must be used from within a node.
+Examples:
+!&amp;3.5 Character Sheet::Strength&amp;!
+(Will find the node named &#8220;Strength&#8221; within the larger container &#8220;3.5 Character Sheet&#8221; and 
+insert it in place of !&amp;3.5 Character Sheet::Strength&amp;!)
 
-Namespace External: 
-(Syntax) !&amp;Top Node::Node&amp;!
+!&amp;3.5 Character Sheet::Ability Scores::3,5&amp;!
+(Will find the cell in Row 3, Colum 5 in within the larger container &#8220;3.5 Character Sheet&#8221; and 
+insert its contents in place of !&amp;3.5 Character Sheet::Ability Scores::3,5&amp;!)</text></nodehandler><nodehandler class="textctrl_handler" frame="400,400,393,95" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Namespace 2.0" module="forms" name="Other Notes" version="1.0"><text hide_title="0" multiline="1" raw_mode="0" send_button="0">Other Notes:
+If you have similar nodes (i.e. have a lot of the same node names in them) located within the 
+same Larger container, Internal Namespace will still work as normal. With External Namespace, 
+you will have to specify which of the smaller containers you wish to call from.
 
-Usage: Namespace External is a different approach to Namespace. With Namespace External you can use the syntax in chat or in other nodes to cross reference nodes. Instead of External being context sensitive, External uses a broadscope that you can narrow down.
+For example, if you have a folder container that has two nodes in it, Internal will still work 
+fine from within either. However, if you are trying to use External, it you will have to 
+specify which of smaller containers you want like so: 
+!&amp;LargerContainer::SmallerContainer::NodeName&amp;!
 
-  It is really easy to narrow down External. External doesn't work like a string, it works like a lightning bolt. To get a good example open up the 4e PC Sheet node that comes with Traipse and try some different commands in chat.
+I.E.:
+The Largest container is called &#8220;Character Sheets.&#8221; It contains three other, Smaller 
+containers called &#8220;Luke,&#8221; &#8220;Leia,&#8221; and &#8220;Vader.&#8221; If you want to call the &#8220;Strength&#8221; node located 
+in &#8220;Leia&#8221; you will have to specify it like so: !&amp;Character Sheets::Leia::Strength&amp;!. </text></nodehandler><nodehandler class="textctrl_handler" frame="400,400,392,87" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Namespace 2.0" module="forms" name="Author Notes" version="1.0"><text hide_title="0" multiline="1" raw_mode="0" send_button="1">The Namespace 2.0 is so far my greatest gift to OpenRPG. Namespace 2.0 surpasses the other Namespaces styles because it has a lightning bolt effect.
+
+In 1.7.1 you could use a reference such as !@Name@! to get the name of the Behir (Example Node). The biggest problem with the Namespace was it would only look at the top most node.
+
+Traipse changes how Namespace works by allowing users to be more specific without needing to be too specific. Namespace 2.0 works in a similar fashion, by finding the top most node with a similar name and attempting to use it. Yet, if you want to be more specific you can add node names to the reference and Namespace will find them in order.
+
+Below are some examples uses of the new Namespace. To try them out, create a 4e PC Sheet node and press the Send button.
 
 &lt;b&gt;1:&lt;/b&gt; !&amp;4e PC Sheet::Slot 1&amp;!
-&lt;b&gt;2:&lt;/b&gt; !&amp;4e PC Sheet::Belt:: Slot 1&amp;!
+&lt;b&gt;2:&lt;/b&gt; !&amp;4e PC Sheet::Belt::Slot 1&amp;!
 &lt;b&gt;3:&lt;/b&gt; !&amp;4e PC Sheet::Inventory&amp;!
 &lt;b&gt;4:&lt;/b&gt; !&amp;4e PC Sheet::Inventory::Slot 1&amp;!
 
   Did you see what happened with the last two? Thankfully there is more than one way to get a node!
 
-(Create a 4e PC Sheet node from the Templates and press Send ---v to try it)</text>
-        </nodehandler>
-      </nodehandler><nodehandler class="textctrl_handler" frame="400,400,595,57" icon="note" map="Traipse OpenRPG::User Manual::Game Tree" module="forms" name="Grids" version="1.0">
+(Create a 4e PC Sheet node from the Templates and press Send ---v to try it)
+</text></nodehandler></nodehandler><nodehandler class="textctrl_handler" frame="400,400,595,57" icon="note" map="Traipse OpenRPG::User Manual::Game Tree" module="forms" name="Grids" version="1.0">
           <text hide_title="0" multiline="1" raw_mode="0" send_button="1">Grids can now be called from by adding a Row, Column to the end of the grid reference.
 
 Example: !&amp;Abilities::2,2&amp;!</text>
@@ -518,12 +562,14 @@
     </nodehandler>
     <nodehandler border="1" class="group_handler" cols="1" icon="grid" map="Traipse OpenRPG" module="containers" name="Templates" status="useful" version="1.0">
       <nodehandler border="1" class="group_handler" cols="1" icon="knight" map="Traipse OpenRPG::Templates" module="containers" name="PC Sheets" version="1.0">
-        <nodehandler class="file_loader" icon="d20" map="Traipse OpenRPG::Templates::PC Sheets" module="core" name="Create 4e PC Sheet" version="1.0">
-          <file name="4e_char_sheet.xml" />
-        </nodehandler>
         <nodehandler class="file_loader" icon="d20" map="Traipse OpenRPG::Templates::PC Sheets" module="core" name="3.5 Tool" version="1.0">
           <file name="dnd3.5.xml" />
         </nodehandler>
+        <nodehandler class="file_loader" icon="d20" map="Traipse OpenRPG::Templates::PC Sheets" module="core" name="Create WH PC Sheet" version="1.0">
+  <file name="Warhammerv2CS2-Traipse.xml" />
+</nodehandler><nodehandler class="file_loader" icon="d20" map="Traipse OpenRPG::Templates::PC Sheets" module="core" name="Create 4e PC Sheet" version="1.0">
+          <file name="4e_char_sheet.xml" />
+        </nodehandler>
         <nodehandler class="file_loader" icon="d20" map="Traipse OpenRPG::Templates::PC Sheets" module="core" name="3rd Edition Character Tool" version="1.0">
           <file name="dnd3e.xml" />
         </nodehandler>
--- a/orpg/templates/metaservers.cache	Mon May 03 03:28:29 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://orpgmeta.appspot.com 1 2
--- a/orpg/templates/nodes/4e_char_sheet.xml	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/templates/nodes/4e_char_sheet.xml	Sat Jun 12 04:38:29 2010 -0500
@@ -32,27 +32,27 @@
 This bears repeating:
 It comes with a Back Pack text node that you can clone to make bags and other containers.</text></nodehandler></nodehandler><nodehandler class="tabber_handler" frame="568,400,446,121" icon="tabber" map="4e PC Sheet" module="containers" name="Rollers" version="1.0"><nodehandler class="listbox_handler" frame="400,400,541,107" icon="gear" map="4e PC Sheet::Rollers" module="forms" name="Skills" version="1.0">
         <list raw_mode="1" send_button="1" type="2">
-          <option caption="Climb" selected="0" value="0">Climb [1d20+5+!=Abilities::(1,3)=!+(!=General::Level=!/2)]</option>
-          <option caption="Hide" selected="0" value="0">Hide [1d20+5+!=Abilities::(2,3)=!+(!=General::Level=!/2)]</option>
-          <option caption="Spot" selected="1" value="0">Spot [1d20+5+!=Abilities::(4,3)=!+(!=General::Level=!/2)]</option>
+          <option caption="Climb" selected="0" value="0">&lt;b&gt;Climb:&lt;/b&gt; [1d20+5+!=Abilities::(1,3)=!+(!=General::Level=!/2)]</option>
+          <option caption="Hide" selected="1" value="0">&lt;b&gt;Hide:&lt;/b&gt; [1d20+5+!=Abilities::(2,3)=!+(!=General::Level=!/2)]</option>
+          <option caption="Spot" selected="0" value="0">&lt;b&gt;Spot:&lt;/b&gt; [1d20+5+!=Abilities::(4,3)=!+(!=General::Level=!/2)]</option>
         </list>
       </nodehandler>
-      <nodehandler class="listbox_handler" frame="400,400,466,138" icon="gear" map="4e PC Sheet::Rollers" module="forms" name="Attacks" version="1.0">
+      <nodehandler class="listbox_handler" frame="400,400,450,100" icon="gear" map="4e PC Sheet::Rollers" module="forms" name="Attacks" version="1.0">
   <list raw_mode="1" send_button="1" type="1">
-    <option caption="Sword Attack" selected="0" value="">&lt;b&gt;Attack&lt;/b&gt; !=Combat::Weapons::2,1=! [1d20+!=Combat::To Hit::2,2=!] &lt;b&gt;Damage:&lt;/b&gt; [1!=Combat::Weapons::2,2=!+!=Abilities::1,3!]</option>
-    <option caption="Mace Attack" selected="1" value="">&lt;b&gt;Attack&lt;/b&gt; !=Combat::Weapons::3,1=! [1d20+!Combat::To Hit::2,2=!] &lt;b&gt;Damage:&lt;/b&gt; [1!=Combat::Weapons::3,2=!+!=Abilities::1,3=!]</option>
+    <option caption="Sword Attack" selected="0" value="">&lt;b&gt;Attack&lt;/b&gt; !=Combat::Weapons::2,1=! [1d20+!=Combat::To Hit::2,2=!] &lt;b&gt;Damage:&lt;/b&gt; [1!=Combat::Weapons::2,2=!+!=Abilities::1,3=!]</option>
+    <option caption="Mace Attack" selected="1" value="">&lt;b&gt;Attack&lt;/b&gt; !=Combat::Weapons::3,1=! [1d20+!=Combat::To Hit::2,2=!] &lt;b&gt;Damage:&lt;/b&gt; [1!=Combat::Weapons::3,2=!+!=Abilities::1,3=!]</option>
     <option caption="Uncreated" selected="0" value="">Option Text III</option>
   </list>
 </nodehandler><nodehandler class="splitter_handler" frame="764,400,9,91" horizontal="0" icon="divider" map="4e PC Sheet::Rollers" module="containers" name="Powers" version="1.0">
     <nodehandler class="listbox_handler" frame="400,400,236,66" icon="gear" map="4e PC Sheet::Rollers::Powers" module="forms" name="At Wills" version="1.0">
   <list raw_mode="1" send_button="1" type="3">
-    <option caption="At Will Power" selected="1" value="0">!=At Wills::At Will=!</option></list>
+    <option caption="At Will Power" selected="1" value="0">!=Utilities::At Wills::At Will=!</option></list>
 </nodehandler><nodehandler class="listbox_handler" frame="400,400,236,66" icon="gear" map="4e PC Sheet::Rollers::Powers" module="forms" name="Encounters" version="1.0">
   <list raw_mode="1" send_button="1" type="3">
-    <option caption="Encounter" selected="1" value="0">!=Encounters::Encounter=!</option></list>
+    <option caption="Encounter" selected="1" value="0">!=Utilities::Encounters::Encounter=!</option></list>
 </nodehandler><nodehandler class="listbox_handler" frame="400,400,470,62" icon="gear" map="4e PC Sheet::Rollers::Powers" module="forms" name="Dailys" version="1.0">
   <list raw_mode="1" send_button="1" type="3">
-    <option caption="Daily" selected="1" value="0">!=Dailys::Daily=!</option></list>
+    <option caption="Daily" selected="1" value="0">!=Utilities::Dailys::Daily=!</option></list>
 </nodehandler></nodehandler></nodehandler><nodehandler class="form_handler" frame="400,400,307,186" height="600" icon="form" map="4e PC Sheet" module="forms" name="General" version="1.0" width="400">
   <nodehandler class="textctrl_handler" icon="note" map="4e PC Sheet::General" module="forms" name="Name" version="1.0">
   <text multiline="0" raw_mode="1" send_button="0">text</text>
--- a/orpg/templates/nodes/Traipse_User_Guide.xml	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/templates/nodes/Traipse_User_Guide.xml	Sat Jun 12 04:38:29 2010 -0500
@@ -1,5 +1,6 @@
-<nodehandler class="tabber_handler" frame="636,449,368,80" icon="labtop" map="Traipse OpenRPG" module="containers" name="User Manual" version="1.0"><nodehandler class="textctrl_handler" frame="400,400,0,48" icon="note" map="Traipse OpenRPG::User Manual" module="forms" name="Introduction" version="1.0">
-  <text multiline="1" send_button="0">Welcome to Traipse OpenRPG.
+<nodehandler class="tabber_handler" frame="636,449,290,93" icon="labtop" map="Traipse OpenRPG" module="containers" name="User Manual" version="1.0">
+      <nodehandler class="textctrl_handler" frame="400,400,0,48" icon="note" map="Traipse OpenRPG::User Manual" module="forms" name="Introduction" version="1.0">
+        <text hide_title="0" multiline="1" raw_mode="0" send_button="0">Welcome to Traipse OpenRPG.
 
 This small user manual should help users learn about the details of OpenRPG that are often times obscure.  
 
@@ -16,14 +17,19 @@
 
 Adding to the Manual:
 Do you see something that could be explained eaiser?  Report the problem as a bug and it will be added to the manual.</text>
-</nodehandler><nodehandler class="tabber_handler" icon="player" map="Traipse OpenRPG::User Manual" module="containers" name="Chat" version="1.0"><nodehandler class="textctrl_handler" icon="note" map="Traipse OpenRPG::User Manual::Chat" module="forms" name="Using Chat" version="1.0">
-  <text multiline="1" send_button="0">The Chat window is a basic HTML Parser. It understands all basic HTML tags including table, td, tr, span, font, to name a few.
+      </nodehandler>
+      <nodehandler class="tabber_handler" icon="player" map="Traipse OpenRPG::User Manual" module="containers" name="Chat" version="1.0">
+        <nodehandler class="textctrl_handler" frame="400,400,0,47" icon="note" map="Traipse OpenRPG::User Manual::Chat" module="forms" name="Using Chat" version="1.0">
+          <text hide_title="0" multiline="1" raw_mode="0" send_button="0">The Chat window is a basic HTML Parser. It understands all basic HTML tags including table, td, tr, span, font, to name a few.
 
 The chat includes a set of commands. You can learn about the commands by entering /help
 
 The chat also has Settings in the Chat menu that allow you see a Chat Time Index, Images, or strip the HTML and see raw text.</text>
-</nodehandler></nodehandler><nodehandler class="tabber_handler" icon="ccmap" map="Traipse OpenRPG::User Manual" module="containers" name="Map" version="1.0"><nodehandler class="textctrl_handler" frame="400,400,310,82" icon="note" map="Traipse OpenRPG::User Manual::Map" module="forms" name="Using The Map" version="1.0">
-  <text multiline="1" raw_mode="0" send_button="0">The Tabs:
+        </nodehandler>
+      </nodehandler>
+      <nodehandler class="tabber_handler" icon="ccmap" map="Traipse OpenRPG::User Manual" module="containers" name="Map" version="1.0">
+        <nodehandler class="textctrl_handler" frame="400,400,310,82" icon="note" map="Traipse OpenRPG::User Manual::Map" module="forms" name="Using The Map" version="1.0">
+          <text hide_title="0" multiline="1" raw_mode="0" send_button="0">The Tabs:
 The Map is divided into 7 tabs. They are Background, Grid, Miniatures, Whiteboard, Fog, and General. There are 6 layers to the map, one tab for each layer except General.  
 
 When you select one of the tabs you may access that map layer and it's settings.  You may only select tabs based on your role.
@@ -55,8 +61,100 @@
 Fog: 
 The fog layer hides the entire map from the prying eyes of players.
 </text>
-</nodehandler></nodehandler><nodehandler class="tabber_handler" icon="gear" map="Traipse OpenRPG::User Manual" module="containers" name="Game Tree" version="1.0"><nodehandler class="tabber_handler" frame="410,490,334,45" icon="tabber" map="Traipse OpenRPG::User Manual::Game Tree" module="containers" name="Reference Examples" version="1.0"><nodehandler class="textctrl_handler" frame="400,400,484,144" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Reference Examples" module="forms" name="Quick Help" version="1.0">
-  <text multiline="1" raw_mode="1" send_button="1">Quick Help:
+        </nodehandler>
+      </nodehandler>
+      <nodehandler class="tabber_handler" frame="537,400,235,93" icon="gear" map="Traipse OpenRPG::User Manual" module="containers" name="Game Tree" version="1.0">
+        <nodehandler class="tabber_handler" frame="400,400,472,75" icon="tabber" map="Traipse OpenRPG::User Manual::Game Tree" module="containers" name="Namespace 2.0" version="1.0"><nodehandler class="textctrl_handler" frame="400,400,393,95" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Namespace 2.0" module="forms" name="Introduction" version="1.0"><text hide_title="0" multiline="1" raw_mode="0" send_button="0">Namespace 2.0
+
+Internal Namespace: !=NodeName=! or !=GridName::Row,Colum=!
+External Namespace: !&amp;Container::NodeName&amp;! or !&amp;Container::GridName::Row,Colum&amp;!
+
+Namespace 2.0 now has two different ways of finding nodes in your gametree: Internal and 
+External. The new version will find nodes differently based on which method you use. With External you start looking from the gametree but can define a "container" to be more specific. With Internal you start looking from the "node" the reference is in and look through the tree backwards. You can now reference cells within a grid using either.
+
+*An explanation of terms*
+Gametree: The list of objects on the left-hand side of the window that holds all your nodes.
+Node: Refers to any object in the gametree.
+Container: Refers only to those nodes that are capable of storing other nodes (Splitter, 
+Tabbers, Folder, Forms, etc.). Used here, it usually refers to the largest container, i.e. the 
+one that shows up in the gametree when fully collapsed. A Container can contain other 
+containers.
+</text></nodehandler><nodehandler class="textctrl_handler" frame="400,400,393,95" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Namespace 2.0" module="forms" name="Internal" version="1.0"><text hide_title="0" multiline="1" raw_mode="0" send_button="0">Internal Namespace: !=NodeName=!
+-Used from within a node to call another node in the same container, such as a list node 
+calling a text node or grid. *Note* Will not work if multiple nodes within the same container 
+have the same name. Multiple nodes within the entirety of the gametree can have the same names 
+though as long as they are in different containers.
+-Uses the !=NodeName=! syntax for normal nodes.
+-Uses !=GridName::Row,Colum=! to reference cells within a grid
+
+Examples: 
+!=Strength=! 
+(Will find the node named &#8220;Strength&#8221; in the same container and insert it in place of 
+!=Strength=!)
+
+!=Ability Scores::3,5=! 
+(Will find cell in Row number 3 and Colum number 5 and insert the information contained there 
+in place of !=Ability Scores::3,5=! )</text></nodehandler><nodehandler class="textctrl_handler" frame="400,400,393,95" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Namespace 2.0" module="forms" name="External" version="1.0"><text hide_title="0" multiline="1" raw_mode="0" send_button="0">External Namespace: !&amp;Container::NodeName&amp;!
+-Can only be used from chat (currently) to call a node from anywhere in the gametree. You must 
+specify the container the node is in. You only have to specify the &#8216;largest&#8217; container 
+(typically the one that shows in the gametree when fully collapsed). It doesn&#8217;t matter how 
+many smaller containers within the same container it&#8217;s in, you need only reference the 
+largest. *Note* Will not work if multiple nodes within the same container have the same name. 
+Multiple nodes within the entirety of the gametree can have the same names though as long as 
+they are in different containers.
+-Uses the !&amp;Container::NodeName&amp;! syntax for normal nodes.
+-Uses !&amp;Container::NodeName::Row,Colum&amp;! to reference cells within a grid.
+
+Examples:
+!&amp;3.5 Character Sheet::Strength&amp;!
+(Will find the node named &#8220;Strength&#8221; within the larger container &#8220;3.5 Character Sheet&#8221; and 
+insert it in place of !&amp;3.5 Character Sheet::Strength&amp;!)
+
+!&amp;3.5 Character Sheet::Ability Scores::3,5&amp;!
+(Will find the cell in Row 3, Colum 5 in within the larger container &#8220;3.5 Character Sheet&#8221; and 
+insert its contents in place of !&amp;3.5 Character Sheet::Ability Scores::3,5&amp;!)</text></nodehandler><nodehandler class="textctrl_handler" frame="400,400,393,95" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Namespace 2.0" module="forms" name="Other Notes" version="1.0"><text hide_title="0" multiline="1" raw_mode="0" send_button="0">Other Notes:
+If you have similar nodes (i.e. have a lot of the same node names in them) located within the 
+same Larger container, Internal Namespace will still work as normal. With External Namespace, 
+you will have to specify which of the smaller containers you wish to call from.
+
+For example, if you have a folder container that has two nodes in it, Internal will still work 
+fine from within either. However, if you are trying to use External, it you will have to 
+specify which of smaller containers you want like so: 
+!&amp;LargerContainer::SmallerContainer::NodeName&amp;!
+
+I.E.:
+The Largest container is called &#8220;Character Sheets.&#8221; It contains three other, Smaller 
+containers called &#8220;Luke,&#8221; &#8220;Leia,&#8221; and &#8220;Vader.&#8221; If you want to call the &#8220;Strength&#8221; node located 
+in &#8220;Leia&#8221; you will have to specify it like so: !&amp;Character Sheets::Leia::Strength&amp;!. </text></nodehandler><nodehandler class="textctrl_handler" frame="400,400,392,87" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Namespace 2.0" module="forms" name="Author Notes" version="1.0"><text hide_title="0" multiline="1" raw_mode="0" send_button="1">The Namespace 2.0 is so far my greatest gift to OpenRPG. Namespace 2.0 surpasses the other Namespaces styles because it has a lightning bolt effect.
+
+In 1.7.1 you could use a reference such as !@Name@! to get the name of the Behir (Example Node). The biggest problem with the Namespace was it would only look at the top most node.
+
+Traipse changes how Namespace works by allowing users to be more specific without needing to be too specific. Namespace 2.0 works in a similar fashion, by finding the top most node with a similar name and attempting to use it. Yet, if you want to be more specific you can add node names to the reference and Namespace will find them in order.
+
+I hope you enjoy the new Namespace very much. I tried to capture an OpenRPG users idea of how Namespace 'should' work and this time I think I set a new bar. I even created a plugin so Traipse users can use the Standard namespace references!
+
+Below are some examples uses of the new Namespace. To try them out, create a 4e PC Sheet node and press the Send button.
+
+&lt;b&gt;1:&lt;/b&gt; !&amp;4e PC Sheet::Slot 1&amp;!
+&lt;b&gt;2:&lt;/b&gt; !&amp;4e PC Sheet::Belt::Slot 1&amp;!
+&lt;b&gt;3:&lt;/b&gt; !&amp;4e PC Sheet::Inventory&amp;!
+&lt;b&gt;4:&lt;/b&gt; !&amp;4e PC Sheet::Inventory::Slot 1&amp;!
+
+ Did you see what happened with the last two? Thankfully there is more than one way to get a node!
+
+(Create a 4e PC Sheet node from the Templates and press Send ---v to try it)
+</text></nodehandler></nodehandler><nodehandler class="textctrl_handler" frame="400,400,595,57" icon="note" map="Traipse OpenRPG::User Manual::Game Tree" module="forms" name="Grids" version="1.0">
+          <text hide_title="0" multiline="1" raw_mode="0" send_button="1">Grids can now be called from by adding a Row, Column to the end of the grid reference.
+
+Example: !&amp;Abilities::2,2&amp;!</text>
+        </nodehandler><nodehandler class="tabber_handler" frame="527,400,259,85" icon="tabber" map="Traipse OpenRPG::User Manual::Game Tree" module="containers" name="Ornery (past)" version="1.0"><nodehandler class="tabber_handler" frame="410,490,334,45" icon="tabber" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)" module="containers" name="Reference Examples" version="1.0">
+          <nodehandler class="textctrl_handler" frame="400,400,484,144" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)::Reference Examples" module="forms" name="Quick Help" version="1.0">
+            <text hide_title="0" multiline="1" raw_mode="1" send_button="0">Quick Help:
+
+Designer Note:
+===
+For the life span of Ornery Orc the new Child, Parent, Root reference will exist, but in Pious the reference system will not transfer. This is because of the way the new Namespace works. Namespace will become the exclusive referencing system
+===
 
 The referencing system is an update to the Core of how the Game Tree works.  In it's current state I understand the syntax is difficult to pick up. Here are some tips to help you grasp the syntax further
 
@@ -113,86 +211,69 @@
 In the OpenRPG Core model your Game Tree has a lot more freedom, but only if you grant it, which I always felt was a design flaw. Comparably, with Traipse you can access any data on the Game Tree, no matter where the location.
 
 This freedom will help with future design and I feel it also frees up the hands of the GM who does not need to Index, un-Index, Namespace, un-Namspace the various creatures he or she may have in a Game Tree.</text>
-</nodehandler><nodehandler class="textctrl_handler" frame="400,400,540,67" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Reference Examples" module="forms" name="Root Reference" version="1.0">
-  <text multiline="1" raw_mode="1" send_button="1">&lt;b&gt;Root Reference&lt;/b&gt;
+          </nodehandler>
+          <nodehandler class="textctrl_handler" frame="400,400,540,67" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)::Reference Examples" module="forms" name="Root Reference" version="1.0">
+            <text hide_title="0" multiline="1" raw_mode="1" send_button="1">&lt;b&gt;Root Reference&lt;/b&gt;
 Works at the tree level. Must be exact.
 
 &lt;b&gt;Root Reference 1:&lt;/b&gt; !@Reference Examples::Group::Child@!
-&lt;b&gt;Root Reference 2:&lt;/b&gt; !@Reference Examples::Grid::(2,1)@!</text>
-</nodehandler><nodehandler class="textctrl_handler" frame="441,400,514,48" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Reference Examples" module="forms" name="Grid Reference" version="1.0">
-  <text multiline="1" raw_mode="1" send_button="1">&lt;b&gt;Grid Reference&lt;/b&gt;
+&lt;b&gt;Root Reference 2:&lt;/b&gt; !@Reference Examples::Grid::2,1@!</text>
+          </nodehandler>
+          <nodehandler class="textctrl_handler" frame="441,400,514,48" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)::Reference Examples" module="forms" name="Grid Reference" version="1.0">
+            <text hide_title="0" multiline="1" raw_mode="1" send_button="1">&lt;b&gt;Grid Reference&lt;/b&gt;
 Works by looking at the (Row, Column) of a Grid.
 
-&lt;b&gt;Grid Reference 1:&lt;/b&gt; !@Reference Examples::Grid::(1,1)@!
-&lt;b&gt;Grid Reference 2:&lt;/b&gt; !!Grid::(1,1)!!</text>
-</nodehandler><nodehandler class="textctrl_handler" frame="400,400,517,63" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Reference Examples" module="forms" name="Child Reference" version="1.0">
-  <text hide_title="1" multiline="1" raw_mode="1" send_button="1">&lt;b&gt;Child Reference&lt;/b&gt;
+&lt;b&gt;Grid Reference 1:&lt;/b&gt; !@Reference Examples::Grid::1,1@!
+&lt;b&gt;Grid Reference 2:&lt;/b&gt; !!Grid::1,1!!</text>
+          </nodehandler>
+          <nodehandler class="textctrl_handler" frame="400,400,517,63" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)::Reference Examples" module="forms" name="Child Reference" version="1.0">
+            <text hide_title="1" multiline="1" raw_mode="1" send_button="1">&lt;b&gt;Child Reference&lt;/b&gt;
 Works at the current tree location.
 
 &lt;b&gt;Child Reference 1:&lt;/b&gt; !!Group::Child!!
 &lt;b&gt;Child Reference 2:&lt;/b&gt; !!Group::Group_2::Child_2!!
 </text>
-</nodehandler><nodehandler class="textctrl_handler" frame="400,400,484,144" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Reference Examples" module="forms" name="Parent Reference" version="1.0">
-  <text multiline="1" raw_mode="1" send_button="1">&lt;b&gt;Parent Reference&lt;/b&gt;
+          </nodehandler>
+          <nodehandler class="textctrl_handler" frame="400,400,484,144" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)::Reference Examples" module="forms" name="Parent Reference" version="1.0">
+            <text hide_title="0" multiline="1" raw_mode="1" send_button="1">&lt;b&gt;Parent Reference&lt;/b&gt;
 Works by indexing the tree map of the node with the Reference. Allows you to start from a 'Parent'.
 
 &lt;b&gt;Parent Reference 1:&lt;/b&gt; !!Group::Group_2::Child_2!!
 &lt;b&gt;Parent Reference 2:&lt;/b&gt; !#Bonus Nodes::Deck::Draw#!</text>
-</nodehandler><nodehandler border="1" class="group_handler" cols="1" map="Traipse OpenRPG::User Manual::Game Tree::Reference Examples" module="containers" name="Group" version="1.0">
-  <nodehandler border="1" class="group_handler" cols="1" map="Traipse OpenRPG::User Manual::Game Tree::Reference Examples::Group" module="containers" name="Group_2" version="1.0">
-  <nodehandler class="textctrl_handler" frame="400,400,571,67" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Reference Examples::Group::Group_2" module="forms" name="Child_2" version="1.0">
-  <text multiline="1" raw_mode="1" send_button="0">!#Group::Child#!</text>
-</nodehandler><nodehandler border="1" class="group_handler" cols="1" map="Traipse OpenRPG::User Manual::Game Tree::Reference Examples::Group::Group_2" module="containers" name="Group_3" version="1.0">
-  <nodehandler class="textctrl_handler" frame="400,400,571,67" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Reference Examples::Group::Group_2::Group_3" module="forms" name="Child_3" version="1.0">
-  <text multiline="1" raw_mode="1" send_button="0">!#Group::Child#!</text>
-</nodehandler></nodehandler></nodehandler><nodehandler class="textctrl_handler" frame="400,400,0,48" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Reference Examples::Group" module="forms" name="Child" version="1.0">
-  <text multiline="0" raw_mode="1" send_button="0">Child Node Data</text>
-</nodehandler></nodehandler><nodehandler class="rpg_grid_handler" frame="400,400,547,51" icon="grid" map="Traipse OpenRPG::User Manual::Game Tree::Reference Examples" module="rpg_grid" name="Grid" version="1.0">
-  <grid autosize="1" border="1">
-    <row version="1.0">
-      <cell size="147">0</cell>
-      <cell>0</cell>
-    </row>
-    <row version="1.0">
-      <cell>!!Group::Child!!</cell>
-      <cell>0</cell>
-    </row>
-  </grid>
-  <macros>
-    <macro name="" />
-  </macros>
-</nodehandler></nodehandler><nodehandler class="textctrl_handler" frame="400,400,452,36" icon="note" map="Traipse OpenRPG::User Manual::Game Tree" module="forms" name="Additions &amp; Tips" version="1.0"><text hide_title="0" multiline="1" raw_mode="0" send_button="0">  With the new additions to the Game Tree  using nodes has never been easier nor has it ever been more fluid. Included here is a list of the additions to the Game Tree referencing model as well as some tips on how to make the Game Tree work the way it was intended.
-
-Grid Nodes:
-  Grid nodes are now reference-able with the coordinates of the grid. Example: !@Grid::(1,1)@!
-The example will return the top left most cell data. The grid understands coordinates like this (Row, Column)
-
-  Grid nodes can reference node data just like any other node can.  With a new added feature grids are even more useful. By using a new die rolling syntax you can draw just the number of the modified roll.  While this will not pass during game play, you can use it with the grid node to create a random chart. The new die roll syntax is [#XdY]. # works just like q, yet it returns only the modified die result. 
-
-  Here is an example with a 3 x 3 Grid
-Example: !@Grid::([#1d3], [#1d3])@!
-
-The result will be a random event from the grid.
-
-Bonus Node Included: A 52 Card Deck with 4 columns and 13 rows. (4 * 13 = 52)
-
-List Nodes:
-  List nodes now have a check box that allows users to send the content as a macro. List nodes are a prime reference holder because users can place a lot of references into one small node.
-
-  For the best results from a list node my tip to users would be to create a list node and place it next to the character sheet they are using, inside a the PC Sheet. The list will then use the Child Referencing syntax, but the PC Sheet can go anywhere in the tree and the player will have easy access to all the references.
-
-(List Nodes inside a Tool created PC sheet vanish when moved, or I would recommend the list be placed inside these sheets also.)
-
-  Here is an example of a Fortitude save inside the recommended list node: !!Fort::Check!!
-
-Text Nodes:
-  Text nodes remain little changed.  I agree with all the 1.7.1 users who tell me, if it's not broke don't fix it. With that in mind I have some good tips for text nodes.
-
-  Text nodes can be used in conjunction with the new grid features to create random encounters. A GM could place a list of text nodes into a folder and the grid could reference the nodes.
-
-  Text nodes also work great when you need to have story text at hand that you don't want to type out during play.  Create chapters with folder nodes and add the adventure text to different nodes.  You can then use a List Node or a Grid Node to reference the different chapters.
-
-Bonus Node Included: A small book node with 1 Chapter and 3 Parts.</text></nodehandler><nodehandler class="textctrl_handler" frame="400,400,393,95" icon="note" map="Traipse OpenRPG::User Manual::Game Tree" module="forms" name="Node Referencing" version="1.0"><text hide_title="0" multiline="1" raw_mode="0" send_button="0">  Traipse node referencing is unlike other distributions of OpenRPG.  The Game Tree mapping is a fluid map that changes with the location of your nodes.  This allows you to create a reference node that will stay with your character sheet, and if you change the location of your character sheet the reference will still work.
+          </nodehandler>
+          <nodehandler border="1" class="group_handler" cols="1" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)::Reference Examples" module="containers" name="Group" version="1.0">
+            <nodehandler border="1" class="group_handler" cols="1" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)::Reference Examples::Group" module="containers" name="Group_2" version="1.0">
+              <nodehandler class="textctrl_handler" frame="400,400,571,67" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)::Reference Examples::Group::Group_2" module="forms" name="Child_2" version="1.0">
+                <text hide_title="0" multiline="1" raw_mode="1" send_button="0">!#Group::Child#!</text>
+              </nodehandler>
+              <nodehandler border="1" class="group_handler" cols="1" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)::Reference Examples::Group::Group_2" module="containers" name="Group_3" version="1.0">
+                <nodehandler class="textctrl_handler" frame="400,400,571,67" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)::Reference Examples::Group::Group_2::Group_3" module="forms" name="Child_3" version="1.0">
+                  <text hide_title="0" multiline="1" raw_mode="1" send_button="0">!#Group::Child#!</text>
+                </nodehandler>
+                </nodehandler>
+              </nodehandler>
+            <nodehandler class="textctrl_handler" frame="400,134,382,175" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)::Reference Examples::Group" module="forms" name="Child" version="1.0">
+              <text hide_title="0" multiline="0" raw_mode="1" send_button="0">Child Node Data</text>
+            </nodehandler>
+            </nodehandler>
+          <nodehandler class="rpg_grid_handler" frame="400,400,547,51" icon="grid" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)::Reference Examples" module="rpg_grid" name="Grid" version="1.0">
+            <grid autosize="1" border="1">
+              <row version="1.0">
+                <cell size="147">0</cell>
+                <cell>0</cell>
+              </row>
+              <row version="1.0">
+                <cell>!!Group::Child!!</cell>
+                <cell>0</cell>
+              </row>
+            </grid>
+            <macros>
+              <macro name="" />
+            </macros>
+          </nodehandler>
+        </nodehandler>
+        <nodehandler class="textctrl_handler" frame="400,400,393,95" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)" module="forms" name="Node Referencing" version="1.0">
+          <text hide_title="0" multiline="1" raw_mode="0" send_button="0">  Traipse node referencing is unlike other distributions of OpenRPG.  The Game Tree mapping is a fluid map that changes with the location of your nodes.  This allows you to create a reference node that will stay with your character sheet, and if you change the location of your character sheet the reference will still work.
 
 (Note: Renaming your node causes problems with the tree mapping until you restart the software. You can just move the node and the software will reset the Game Tree map)
 
@@ -244,8 +325,46 @@
 
 Examples: 
 !@Kammen-Pai::Cast::Ray of Frost@!
-!@Kammen-Pai::Feat::Ability Focus@!</text></nodehandler></nodehandler><nodehandler class="tabber_handler" icon="labtop" map="Traipse OpenRPG::User Manual" module="containers" name="The Server" version="1.0"><nodehandler class="textctrl_handler" frame="400,400,310,82" icon="note" map="Traipse OpenRPG::User Manual::The Server" module="forms" name="Setting up a Server" version="1.0">
-  <text multiline="1" send_button="0">In Traipse starting a server has never been easier.  The setup is as easy as 1., 2., 3
+!@Kammen-Pai::Feat::Ability Focus@!</text>
+        </nodehandler>
+        <nodehandler class="textctrl_handler" frame="400,400,452,36" icon="note" map="Traipse OpenRPG::User Manual::Game Tree::Ornery (past)" module="forms" name="Additions &amp; Tips" version="1.0">
+          <text hide_title="0" multiline="1" raw_mode="0" send_button="0">  With the new additions to the Game Tree  using nodes has never been easier nor has it ever been more fluid. Included here is a list of the additions to the Game Tree referencing model as well as some tips on how to make the Game Tree work the way it was intended.
+
+Grid Nodes:
+  Grid nodes are now reference-able with the coordinates of the grid. Example: !@Grid::(1,1)@!
+The example will return the top left most cell data. The grid understands coordinates like this (Row, Column)
+
+  Grid nodes can reference node data just like any other node can.  With a new added feature grids are even more useful. By using a new die rolling syntax you can draw just the number of the modified roll.  While this will not pass during game play, you can use it with the grid node to create a random chart. The new die roll syntax is [#XdY]. # works just like q, yet it returns only the modified die result. 
+
+  Here is an example with a 3 x 3 Grid
+Example: !@Grid::([#1d3], [#1d3])@!
+
+The result will be a random event from the grid.
+
+Bonus Node Included: A 52 Card Deck with 4 columns and 13 rows. (4 * 13 = 52)
+
+List Nodes:
+  List nodes now have a check box that allows users to send the content as a macro. List nodes are a prime reference holder because users can place a lot of references into one small node.
+
+  For the best results from a list node my tip to users would be to create a list node and place it next to the character sheet they are using, inside a the PC Sheet. The list will then use the Child Referencing syntax, but the PC Sheet can go anywhere in the tree and the player will have easy access to all the references.
+
+(List Nodes inside a Tool created PC sheet vanish when moved, or I would recommend the list be placed inside these sheets also.)
+
+  Here is an example of a Fortitude save inside the recommended list node: !!Fort::Check!!
+
+Text Nodes:
+  Text nodes remain little changed.  I agree with all the 1.7.1 users who tell me, if it's not broke don't fix it. With that in mind I have some good tips for text nodes.
+
+  Text nodes can be used in conjunction with the new grid features to create random encounters. A GM could place a list of text nodes into a folder and the grid could reference the nodes.
+
+  Text nodes also work great when you need to have story text at hand that you don't want to type out during play.  Create chapters with folder nodes and add the adventure text to different nodes.  You can then use a List Node or a Grid Node to reference the different chapters.
+
+Bonus Node Included: A small book node with 1 Chapter and 3 Parts.</text>
+        </nodehandler>
+        </nodehandler></nodehandler>
+      <nodehandler class="tabber_handler" icon="labtop" map="Traipse OpenRPG::User Manual" module="containers" name="The Server" version="1.0">
+        <nodehandler class="textctrl_handler" frame="400,400,310,82" icon="note" map="Traipse OpenRPG::User Manual::The Server" module="forms" name="Setting up a Server" version="1.0">
+          <text hide_title="0" multiline="1" raw_mode="0" send_button="0">In Traipse starting a server has never been easier.  The setup is as easy as 1., 2., 3
 
 1. You will need to first start the Server GUI or the basic text based Server at least once so your software creates the server_ini.xml files in your myfiles directory. You can start it once and quit.
 
@@ -256,10 +375,15 @@
 3. This is the hardest step. You need to make sure your selected port is forwarded by your router and open to your firewall.
 
 That's it! You can now start the server and register it to the meta for all users to enjoy!</text>
-</nodehandler></nodehandler><nodehandler class="tabber_handler" frame="400,400,0,48" icon="browser" map="Traipse OpenRPG::User Manual" module="containers" name="Links" version="1.0"><nodehandler class="link_handler" icon="html" map="Traipse OpenRPG::User Manual::Links" module="forms" name="Release Notes" version="1.0">
-    <link href="http://www.assembla.com/wiki/show/traipse" />
-  </nodehandler>
-  <nodehandler class="link_handler" icon="html" map="Traipse OpenRPG::User Manual::Links" module="forms" name="Traipse User Guide" version="1.0">
-    <link href="http://www.assembla.com/wiki/show/traipse/User_Manual" />
-  </nodehandler>
-  </nodehandler></nodehandler>
\ No newline at end of file
+        </nodehandler>
+      </nodehandler>
+      <nodehandler class="tabber_handler" frame="400,400,0,48" icon="browser" map="Traipse OpenRPG::User Manual" module="containers" name="Links" version="1.0">
+        <nodehandler class="link_handler" icon="html" map="Traipse OpenRPG::User Manual::Links" module="forms" name="Release Notes" version="1.0">
+          <link href="http://www.assembla.com/wiki/show/traipse" />
+        </nodehandler>
+        <nodehandler class="link_handler" icon="html" map="Traipse OpenRPG::User Manual::Links" module="forms" name="Traipse User Guide" version="1.0">
+          <link href="http://www.assembla.com/wiki/show/traipse/User_Manual" />
+        </nodehandler>
+      </nodehandler>
+    </nodehandler>
+    
\ No newline at end of file
--- a/orpg/tools/FlatNotebook.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/tools/FlatNotebook.py	Sat Jun 12 04:38:29 2010 -0500
@@ -74,6 +74,7 @@
 # Beginning Of FLATNOTEBOOK wxPython Code
 #----------------------------------------------------------------------
 
+print 'Flatnotebook'
 import wx
 import random
 import math
--- a/orpg/tools/InterParse.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/tools/InterParse.py	Sat Jun 12 04:38:29 2010 -0500
@@ -49,7 +49,7 @@
         s = self.NameSpaceE(s)
         s = self.NameSpaceI(s, node)
         s = self.NodeMap(s, node)
-        s = self.NodeParent(s, node.get('map'))
+        s = self.NodeParent(s, node)
         return s
 
     def Normalize(self, s, tab):
@@ -159,7 +159,8 @@
         namespace -- TaS, Prof. Ebral"""
         reg2 = re.compile("(!=(.*?)=!)")
         matches = reg1.findall(s) + reg2.findall(s)
-        tree_map = node.get('map')
+        try: tree_map = node.get('map')
+        except: return node
         for i in xrange(0,len(matches)):
             ## Build the new tree_map
             new_map = tree_map.split('::')
@@ -168,7 +169,8 @@
             node = self.get_node(new_map)
             newstr = self.LocationCheck(node, tree_map, new_map, find)
             s = s.replace(matches[i][0], newstr, 1)
-            s = self.ParseLogic(s, node)
+            s = self.NodeMap(s, node)
+            s = self.NodeParent(s, node)
         return s
 
     def NameSpaceE(self, s):
@@ -231,8 +233,10 @@
             s = self.NodeParent(s, tree_map)
         return s
 
-    def NodeParent(self, s, tree_map):
+    def NodeParent(self, s, node):
         """Parses player input for embedded nodes rolls"""
+        if node == 'Invalid Reference!': return node
+        tree_map = node.get('map')
         cur_loc = 0
         reg = re.compile("(!#(.*?)#!)")
         matches = reg.findall(s)
--- a/orpg/tools/orpg_settings.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/tools/orpg_settings.py	Sat Jun 12 04:38:29 2010 -0500
@@ -33,7 +33,8 @@
 
 from orpg.tools.orpg_log import logger
 from orpg.tools.validate import validate
-from orpg.orpg_xml import xml
+from xml.etree.ElementTree import ElementTree, Element, parse
+from xml.etree.ElementTree import fromstring, tostring
 from orpg.tools.settings import settings
 
 class orpgSettingsWnd(wx.Dialog):
@@ -70,29 +71,28 @@
     def build_gui(self):
         validate.config_file("settings.xml","default_settings.xml")
         filename = dir_struct["user"] + "settings.xml"
-        temp_file = open(filename)
-        temp_file.close()
-        children = self.settings.xml_dom._get_childNodes()
-        for c in children: self.build_window(c,self.tabber)
+        temp_file = parse(filename)
+        children = self.settings.xml_dom.getchildren()
+        for c in children: self.build_window(c, self.tabber)
 
     def build_window(self, xml_dom, parent_wnd):
-        name = xml_dom._get_nodeName()
+        name = xml_dom.tag
         #container = 0
         if name=="tab": temp_wnd = self.do_tab_window(xml_dom,parent_wnd)
         return temp_wnd
 
     def do_tab_window(self, xml_dom, parent_wnd):
-        type = xml_dom.getAttribute("type")
-        name = xml_dom.getAttribute("name")
+        type = xml_dom.get("type")
+        name = xml_dom.get("name")
 
         if type == "grid":
             temp_wnd = self.do_grid_tab(xml_dom, parent_wnd)
             parent_wnd.AddPage(temp_wnd, name, False)
         elif type == "tab":
             temp_wnd = orpgTabberWnd(parent_wnd, style=FNB.FNB_NO_X_BUTTON)
-            children = xml_dom._get_childNodes()
+            children = xml_dom.getchildren()
             for c in children:
-                if c._get_nodeName() == "tab": self.do_tab_window(c, temp_wnd)
+                if c.tag == "tab": self.do_tab_window(c, temp_wnd)
             temp_wnd.SetSelection(0)
             parent_wnd.AddPage(temp_wnd, name, False)
         elif type == "text":
@@ -103,12 +103,12 @@
 
     def do_grid_tab(self, xml_dom, parent_wnd):
         settings = []
-        children = xml_dom._get_childNodes()
+        children = xml_dom.getchildren()
         for c in children:
-            name = c._get_nodeName()
-            value = c.getAttribute("value")
-            help = c.getAttribute("help")
-            options = c.getAttribute("options")
+            name = c.tag
+            value = c.get("value")
+            help = c.get("help")
+            options = c.get("options")
             settings.append([name, value, options, help])
         temp_wnd = settings_grid(parent_wnd, settings, self.changes)
         return temp_wnd
@@ -309,4 +309,3 @@
         for i in range(0,cols): self.SetColSize(i,col_w)
         self.Refresh()
 
-#settings = orpg.tools.settings.Settings()
--- a/orpg/tools/scriptkit.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/tools/scriptkit.py	Sat Jun 12 04:38:29 2010 -0500
@@ -30,7 +30,7 @@
 
 import time
 from orpg.orpg_windows import *
-from orpg.orpg_xml import *
+#from orpg.orpg_xml import *
 from orpg.orpg_wx import *
 import orpg.chat.chat_msg
 
@@ -45,7 +45,7 @@
         self.map = component.get( 'map' )
         self.settings = component.get( 'settings' )
         self.session = component.get('session')
-        self.xml = component.get('xml')
+        #self.xml = component.get('xml')
 
     def addMiniatureToMap( self, min_label, min_url, unique=0 ):
         """Adds a new miniature icon to the map.  Miniature <em>will</em> be labeled unless autolabel is
--- a/orpg/tools/settings.py	Mon May 03 03:28:29 2010 -0500
+++ b/orpg/tools/settings.py	Sat Jun 12 04:38:29 2010 -0500
@@ -2,41 +2,32 @@
 
 from orpg.tools.orpg_log import logger
 from orpg.tools.validate import validate
-from orpg.orpg_xml import xml
+from xml.etree.ElementTree import ElementTree, Element, parse
+from xml.etree.ElementTree import fromstring, tostring
 from orpg.orpgCore import component
 from orpg.dirpath import dir_struct
 
 class Settings:
     def __init__(self):
-        self.xml = component.get("xml")
         self.changes = []
         validate.config_file("settings.xml","default_settings.xml")
         self.filename = dir_struct["user"] + "settings.xml"
-        temp_file = open(self.filename)
-        txt = temp_file.read()
-        temp_file.close()
-
-        self.xml_dom = xml.parseXml(txt)
-
-        if self.xml_dom is None: self.rebuildSettings()
-        self.xml_dom = self.xml_dom._get_documentElement()
+        xml_dom = parse(dir_struct["user"] + "settings.xml")
+        if xml_dom == None: self.rebuildSettings()
+        else: self.xml_dom = xml_dom.getroot()
 
     def rebuildSettings(self):
         logger.info("Settings file has be corrupted, rebuilding settings.", True)
         try: os.remove(self.filename)
         except: pass
-
         validate.config_file("settings.xml","default_settings.xml")
-        temp_file = open(self.filename)
-        txt = temp_file.read()
-        temp_file.close()
-        self.xml_dom = xml.parseXml(txt)
+        self.xml_dom = parse(self.filename).getroot()
 
     def get_setting(self, name): ##Depricated
         return self.get(name)
 
     def get(self, name): 
-        try: return self.xml_dom.getElementsByTagName(name)[0].getAttribute("value")
+        try: return self.xml_dom.getiterator(name)[0].get("value")
         except: return 0
 
     def get_setting_keys(self): ##Depricated
@@ -44,30 +35,30 @@
 
     def get_keys(self):
         keys = []
-        tabs = self.xml_dom.getElementsByTagName("tab")
+        tabs = self.xml_dom.getiterator("tab")
         for i in xrange(0, len(tabs)):
-            if tabs[i].getAttribute("type") == 'grid':
-                children = tabs[i]._get_childNodes()
-                for c in children: keys.append(c._get_tagName())
+            if tabs[i].get("type") == 'grid':
+                children = tabs[i].getchildren()
+                for c in children: keys.append(c.tag)
         return keys
 
     def set_setting(self, name, value): ##Depricated
         self.change(name, value)
 
     def change(self, name, value):
-        self.xml_dom.getElementsByTagName(name)[0].setAttribute("value", value)
+        self.xml_dom.getiterator(name)[0].set("value", value)
 
     def add_setting(self, tab, setting, value, options, help): ##Depricated
         return self.add(tab, setting, value, options, help)
 
     def add(self, tab, setting, value, options, help):
-        if len(self.xml_dom.getElementsByTagName(setting)) > 0: return False
-        tabs = self.xml_dom.getElementsByTagName("tab")
-        newsetting = xml.parseXml('<' + setting + ' value="' + value + '" options="' + 
-                                        options + '" help="' + help + '" />')._get_documentElement()
+        if len(self.xml_dom.getiterator(setting)) > 0: return False
+        tabs = self.xml_dom.getiterator("tab")
+        newsetting = fromstring('<' + setting + ' value="' + value + '" options="' + 
+                                        options + '" help="' + help + '" />')
         for i in xrange(0, len(tabs)):
-            if tabs[i].getAttribute("name") == tab and tabs[i].getAttribute("type") == 'grid':
-                tabs[i].appendChild(newsetting)
+            if tabs[i].get("name") == tab and tabs[i].get("type") == 'grid':
+                tabs[i].append(newsetting)
                 return True
         return False
 
@@ -75,49 +66,44 @@
         tab_xml = '<tab '
         if tabtype == 'text': tab_xml += 'name="' + tabname + '" type="text" />'
         else: tab_xml += 'name="' + tabname + '" type="' + tabtype + '"></tab>'
-        newtab = xml.parseXml(tab_xml)._get_documentElement()
+        newtab = fromstring(tab_xml)
         if parent != None:
-            tabs = self.xml_dom.getElementsByTagName("tab")
+            tabs = self.xml_dom.getiterator("tab")
             for i in xrange(0, len(tabs)):
-                if tabs[i].getAttribute("name") == parent and tabs[i].getAttribute("type") == 'tab':
-                    children = tabs[i]._get_childNodes()
+                if tabs[i].get("name") == parent and tabs[i].get("type") == 'tab':
+                    children = tabs[i].getchildren()
                     for c in children:
-                        if c.getAttribute("name") == tabname: return False
-                    tabs[i].appendChild(newtab)
+                        if c.get("name") == tabname: return False
+                    tabs[i].append(newtab)
                     return True
         else:
-            children = self.xml_dom._get_childNodes()
+            children = self.xml_dom.getchildren()
             for c in children:
-                if c.getAttribute("name") == tabname: return False
-            self.xml_dom.appendChild(newtab)
+                if c.get("name") == tabname: return False
+            self.xml_dom.append(newtab)
             return True
         return False
 
     def updateIni(self):
         defaultFile = orpg.dirpath.dir_struct['template'] + 'default_settings.xml'
-        temp_file = open(defaultFile)
-        txt = temp_file.read()
-        temp_file.close()
-        default_dom = xml.parseXml(txt)._get_documentElement()
-        for child in default_dom.getChildren():
-            if child._get_tagName() == 'tab' and child.hasChildNodes(): self.proccessChildren(child)
-        default_dom.unlink()
+        default_dom = parse(defaultfile)
+        for child in default_dom.getchildren():
+            if child.tag == 'tab': self.proccessChildren(child)
 
     def proccessChildren(self, dom, parent=None):
-        if dom._get_tagName() == 'tab':
-            self.add_tab(parent, dom.getAttribute("name"), dom.getAttribute("type"))
+        if dom.tag == 'tab': self.add_tab(parent, dom.get("name"), dom.get("type"))
 
-        for child in dom.getChildren():
-            if child._get_tagName() == 'tab' and child.hasChildNodes():
-                self.proccessChildren(child, dom.getAttribute("name"))
+        for child in dom.getchildren():
+            if child.tag == 'tab': self.proccessChildren(child, dom.get("name"))
             else:
-                self.add_setting(dom.getAttribute("name"), child._get_tagName(), 
-                                child.getAttribute("value"), child.getAttribute("options"), 
-                                child.getAttribute("help"))
+                self.add_setting(dom.get("name"), child.tag, 
+                                child.get("value"), child.get("options"), 
+                                child.get("help"))
 
     def save(self):
+        #self.xml_dom.write(self.filename)
         temp_file = open(self.filename, "w")
-        temp_file.write(xml.toxml(self.xml_dom,1))
+        temp_file.write(tostring(self.xml_dom))
         temp_file.close()
 
 settings = Settings()
--- a/plugins/xxstdnamespace.py	Mon May 03 03:28:29 2010 -0500
+++ b/plugins/xxstdnamespace.py	Sat Jun 12 04:38:29 2010 -0500
@@ -21,11 +21,15 @@
         self.help += 'is not calculated when using the Standard syntax. References must '
         self.help += 'have a unique name.'
 
-        self.parseMethods = {'Traipse': Parse.NameSpaceE, 'Standard': self.NameSpaceS}
+        self.NameSpaceE = Parse.NameSpaceE
+        self.parseMethods = {'Traipse': self.NameSpaceE, 'Standard': self.NameSpaceS}
 
     def NameSpaceS(self, s): ## Re define NameSpace External
-        reg1 = re.compile("(!@(.*?)@!)") ## Inlcude 'Standard' method
+        reg1 = re.compile("(!@(.*?)@!)") ## Include 'Standard' method
         reg2 = re.compile("(!&(.*?)&!)")
+        ## Before anyone rags on me about how this is a useless plugin, or that two methods are confusing,
+        ## consider that this will be fully integrated later. Then consider that you can now create a reference
+        ## with a reference. !@ :: !& :: &! :: @!
         matches = reg1.findall(s) + reg2.findall(s)
         newstr = False
         nodeable = ['rpg_grid_handler', 'container_handler', 
@@ -36,7 +40,7 @@
             node = component.get('tree').xml_root
             if not iselement(node): 
                 s = s.replace(matches[i][0], 'Invalid Reference!', 1); 
-                s = Parse.NameSpaceE(s)
+                s = self.NameSpaceS(s)
                 return s
             for x in xrange(0, len(find)):
                 namespace = node.getiterator('nodehandler')
@@ -44,7 +48,7 @@
                     if find[x] == node.get('name'):
                         if node.get('class') not in nodeable: continue
                         if node.get('class') == 'rpg_grid_handler':
-                            try: newstr = self.NameSpaceGrid(find[x+1], node); break
+                            try: newstr = Parse.NameSpaceGrid(find[x+1], node); break
                             except: newstr = 'Invalid Grid Reference!'
                         try:
                             if Parse.FutureCheck(node, find[x+1]): break
@@ -69,10 +73,10 @@
 
     def plugin_toggle(self, evt):
         if self.toggle.IsChecked() == True: 
-            Parse.NameSpaceI = self.parseMethods['Standard']
+            Parse.NameSpaceE = self.parseMethods['Standard']
             self.plugindb.SetString('xxstdnamespace', 'Standard', 'True')
         if self.toggle.IsChecked() == False: 
-            Parse.NameSpaceI = self.parseMethods['Traipse']
+            Parse.NameSpaceE = self.parseMethods['Traipse']
             self.plugindb.SetString('xxstdnamespace', 'Standard', 'False')
         pass