diff orpg/mapper/base_msg.py @ 0:4385a7d0efd1 grumpy-goblin

Deleted and repushed it with the 'grumpy-goblin' branch. I forgot a y
author sirebral
date Tue, 14 Jul 2009 16:41:58 -0500
parents
children 78407d627cba
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/orpg/mapper/base_msg.py	Tue Jul 14 16:41:58 2009 -0500
@@ -0,0 +1,259 @@
+# Copyright (C) 2000-2001 The OpenRPG Project
+#
+#    openrpg-dev@lists.sourceforge.net
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+# --
+#
+# File: mapper/base_msg.py
+# Author: Chris Davis
+# Maintainer:
+# Version:
+#   $Id: base_msg.py,v 1.9 2007/03/09 14:11:55 digitalxero Exp $
+#
+# Description:
+#
+__version__ = "$Id: base_msg.py,v 1.9 2007/03/09 14:11:55 digitalxero Exp $"
+
+from threading import RLock
+from orpg.networking.mplay_client import *
+
+class map_element_msg_base:
+#  This is a base class
+
+    def __init__(self,reentrant_lock_object = None):
+
+        if not hasattr(self,"tagname"):
+            raise Exception, "This is a virtual class that cannot be directly instantiated.  Set self.tagname in derived class."
+
+        self._props = {}
+        #  This is a dictionary that holds (value,changed) 2-tuples, indexed by attribute
+        #  Avoid manipulating these values directly.  Instead, use the provided accessor methods.
+        #  If there is not one that suits your needs, please add one to this class and
+        #  use it instead.
+
+        self.children = {}
+        # This next clause will set self.p_lock to a passed-in RLock object, if present.
+        #    Otherwise, it will create it's very own for this instance.
+        #    Using a passed in object is useful to protect an entire <map/> element from
+        #    being changed by another thread when any part of it is being change by another
+        #    thread.  Just pass the map_msg's p_lock object in to it's descendents.
+        if reentrant_lock_object:
+            self.p_lock = reentrant_lock_object
+        else:
+            self.p_lock = RLock()
+
+    def clear(self):
+        self.p_lock.acquire()
+
+        for child in self.children.keys():
+            self.children[child].clear()
+            self.children[child] = None
+            del self.children[child]
+
+        for p in self._props.keys():
+            self._props[p] = None
+
+        self.p_lock.release()
+
+
+    #########################################
+    #  Accessor functions begin
+
+    #  Access single property
+
+    def init_prop(self,prop,value):  # set's the changed flag to False and assigns
+        self.p_lock.acquire()
+        self._props[prop] = (value, 0)
+        self.p_lock.release()
+
+    def set_prop(self,prop,value):  # set's the changed flag to True and assigns
+        self.p_lock.acquire()
+        self._props[prop] = (value, 1)
+        self.p_lock.release()
+
+    def get_prop(self,prop):  # returns None if prop not found
+        self.p_lock.acquire()
+        if prop in self._props.keys():
+            (p,c) = self._props[prop]
+            self.p_lock.release()
+            return p
+        else:
+            self.p_lock.release()
+            return None
+
+    def is_prop_changed(self,prop):  # returns None if prop not found
+        self.p_lock_acquire()
+        if prop in self._props.keys():
+            (p,c) = self._props[prop]
+            self.p_lock.release()
+            return c
+        else:
+            self.p_lock.release()
+            return None
+
+    def get_child(self,key):         # returns None if key not found in children list
+        self.p_lock_acquire()
+        if self.children.has_key(key):
+            self.p_lock.release()
+            return self.children[key]
+        else:
+            self.p_lock.release()
+            return None
+
+    #  Access multiple properties
+
+    def init_props(self,props):               # same as init_prop(), but takes dictionary of props
+        self.p_lock.acquire()
+        for k in props.keys():
+            self._props[k] = (props[k],0)
+        self.p_lock.release()
+
+    def set_props(self,props):                # same as set_prop(), but takes dictionary of props
+        self.p_lock.acquire()
+        for k in props.keys():
+            self._props[k] = (props[k],1)
+        self.p_lock.release()
+
+    def get_all_props(self):                  # returns dictionary of all properties, regardless of change
+        self.p_lock.acquire()
+
+        result = {}
+        for k in self._props.keys():
+            (p,c) = self._props[k]
+            result[k] = p
+
+        self.p_lock.release()
+        return result
+
+    def get_changed_props(self):              # returns dictionary of all properties that have been changed
+        self.p_lock.acquire()
+        result = {}
+        for k in self._props.keys():
+            (p,c) = self._props[k]
+            if c:
+                result[k] = p
+        self.p_lock.release()
+        return result
+
+    def get_children(self):                 # returns dictionary of children
+        return self.children
+
+
+    #  Accessor functions end
+    #########################################
+
+    #########################################
+    #  XML emitters begin
+    def get_all_xml(self,action="new",output_action = 0):    # outputs a tag with all attributes it contains
+        self.p_lock.acquire()
+        xml_str = "<" + self.tagname
+        if action and output_action:
+            xml_str += " action='" + action + "'"
+        for k in self._props.keys():
+            (p,c) = self._props[k]
+            if k != "action" or not action:
+                xml_str += " " + k + "='" + p + "'"
+        if self.children:
+            xml_str += ">"
+            for child in self.children.keys():
+                xml_str += self.children[child].get_all_xml(action)
+            xml_str += "</" + self.tagname + ">"
+        else:
+            xml_str += "/>"
+        self.p_lock.release()
+        return xml_str
+
+    def get_changed_xml(self,action="update",output_action = 0):    # outputs a tag with all changed attributes
+        self.p_lock.acquire()
+        xml_str = "<" + self.tagname
+        if action and output_action:
+            xml_str += " action='" + action + "'"
+
+        # if present, always send the id, even if it didn't change
+        if self._props.has_key("id"):
+            (p,c) = self._props["id"]
+            xml_str += " id='" + p + "'"
+        for k in self._props.keys():
+            (p,c) = self._props[k]
+            if (k != "id" or k != "action") and c == 1:  # don't duplicate the id attribute
+                xml_str += " " + k + "='" + p + "'"
+        if self.children:
+            xml_str += ">"
+            for child in self.children.keys():
+                xml_str += self.children[child].get_changed_xml(action)
+            xml_str += "</" + self.tagname + ">"
+        else:
+            xml_str += "/>"
+        self.p_lock.release()
+        return xml_str
+
+    # convenience method to use if only this tag is modified
+    #   outputs a <map/> element containing only the changes to this tag
+    def standalone_update_text(self,update_id_string):
+        buffer = "<map id='" + update_id_string + "'>"
+        buffer += self.get_changed_xml("update")
+        buffer += "<map/>"
+        return buffer
+
+    # XML emitters end
+    #########################################
+
+    #########################################
+    #  XML importers begin
+
+    def _from_dom(self,xml_dom,prop_func):
+        self.p_lock.acquire()
+        if xml_dom.tagName == self.tagname:
+            if xml_dom.getAttributeKeys():
+                for k in xml_dom.getAttributeKeys():
+                    prop_func(k,xml_dom.getAttribute(k))
+        else:
+            self.p_lock.release()
+            raise Exception, "Error attempting to modify a " + self.tagname + " from a non-<" + self.tagname + "/> element"
+        self.p_lock.release()
+
+    def init_from_dom(self,xml_dom):
+    #  xml_dom must be pointing to an empty tag.  Override in a derived class for <map/> and other similar tags.
+        self._from_dom(xml_dom,self.init_prop)
+
+    def set_from_dom(self,xml_dom):
+    #  xml_dom must be pointing to an empty tag.  Override in a derived class for <map/> and other similar tags
+        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)
+        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()
+
+    def set_from_xml(self,xml):
+        xml_dom = parseXml(xml)
+        node_list = xml_dom.getElementsByTagName(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()
+
+    # XML importers end
+    #########################################