# HG changeset patch # User sirebral # Date 1253361043 18000 # Node ID 68c7bd272f2712bdd1a257a9699c8b292b8fb99d # Parent 5c12918d6bb2413499fd8c554d56c944177148e5 Traipse Beta 'OpenRPG' {090919-00} Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on code without fear of sacrifice. '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: Adds menu changes to draw attention to important updates, errors, or other events. (image info coming soon) Traipse URL is not included in the repos tab and is set as default. Fixes Copy for Windows and Linux (finally!!) users. Fixes incomplete update to Grid and List nodes. Fixes incomplete update to Chat Commands. Fixes problems with Remote Image Upload. Fixes Drop and Drag of Minis to Map. CherryPy can now use any image in the webfiles/ folder and sub-folders. CherryPy can now Drop and Drag Minis to the Map. Minor changes to Update Manager's GUI. Expert recommendation warning added to Revision Update. Step down compatibility with open_rpg & component added to orpgCore. Using majority of 'Grumpy' network folder to correct server lag. diff -r 5c12918d6bb2 -r 68c7bd272f27 images/spotlight.png Binary file images/spotlight.png has changed diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/chat/chatwnd.py --- a/orpg/chat/chatwnd.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/chat/chatwnd.py Sat Sep 19 06:50:43 2009 -0500 @@ -72,7 +72,8 @@ from orpg.tools.orpg_settings import settings from orpg.orpgCore import component from orpg.tools.orpg_log import logger -from orpg.tools.decorators import debugging +from orpg.tools.decorators import debugging + NEWCHAT = False try: import wx.webview @@ -175,11 +176,11 @@ self.menu.AppendItem(item) @debugging - def OnM_EditCopy(self, evt): - wx.TheClipboard.Open() - wx.TheClipboard.Clear() - wx.TheClipboard.SetData(wx.TextDataObject(self.SelectionToText())) - wx.TheClipboard.Close() + def OnM_EditCopy(self, evt): + wx.TheClipboard.UsePrimarySelection(False) + wx.TheClipboard.Open() + wx.TheClipboard.SetData(wx.TextDataObject(self.SelectionToText())) + wx.TheClipboard.Close() @debugging def scroll_down(self): @@ -289,8 +290,11 @@ wx.CallAfter(self.parent.set_chat_text_focus, None) @debugging - def OnM_EditCopy(self, evt): - self.Copy() + def OnM_EditCopy(self, evt): + wx.TheClipboard.UsePrimarySelection(False) + wx.TheClipboard.Open() + wx.TheClipboard.SetData(wx.TextDataObject(self.SelectionToText())) + wx.TheClipboard.Close() #Cutom Methods @debugging @@ -874,15 +878,10 @@ self.Bind(wx.EVT_BUTTON, self.lock_scroll, self.scroll_lock) self.chattxt.Bind(wx.EVT_MOUSEWHEEL, self.chatwnd.mouse_wheel) self.chattxt.Bind(wx.EVT_CHAR, self.chattxt.OnChar) - self.chattxt.Bind(wx.EVT_TEXT_COPY, self.textCopy) + self.chattxt.Bind(wx.EVT_TEXT_COPY, self.chatwnd.OnM_EditCopy) # def build_ctrls - end @debugging - def textCopy(self, event): - if self.chattxt.GetStringSelection() == '': self.chatwnd.OnM_EditCopy(None) - else: self.chatwnd.Copy() - - @debugging def build_bar(self): self.toolbar_sizer = wx.BoxSizer(wx.HORIZONTAL) self.scroll_lock = None diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/chat/commands.py --- a/orpg/chat/commands.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/chat/commands.py Sat Sep 19 06:50:43 2009 -0500 @@ -14,6 +14,7 @@ import orpg.orpg_windows import traceback +from orpg.orpgCore import component from orpg.tools.orpg_log import logger from orpg.tools.decorators import debugging @@ -262,7 +263,7 @@ @debugging def on_dieroller(self, cmdargs): args = string.split(cmdargs,None,-1) - rm = self.chat.DiceManager + rm = component.get('DiceManager') try: rm.setRoller(args[0]) self.chat.SystemPost("You have changed your die roller to the \"" + args[0] + "\" roller.") diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/gametree/nodehandlers/forms.py --- a/orpg/gametree/nodehandlers/forms.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/gametree/nodehandlers/forms.py Sat Sep 19 06:50:43 2009 -0500 @@ -29,6 +29,7 @@ __version__ = "$Id: forms.py,v 1.53 2007/04/21 23:00:51 digitalxero Exp $" from containers import * +import orpg.minidom as minidom from orpg.orpg_xml import xml from wx.lib.scrolledpanel import ScrolledPanel @@ -66,7 +67,7 @@ else: self.tree.load_xml(c,self.mytree_node) if not self.atts: - elem = self.xml.minidom.Element('form') + elem = minidom.Element('form') elem.setAttribute("width","400") elem.setAttribute("height","600") self.atts = self.master_dom.appendChild(elem) diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/gametree/nodehandlers/rpg_grid.py --- a/orpg/gametree/nodehandlers/rpg_grid.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/gametree/nodehandlers/rpg_grid.py Sat Sep 19 06:50:43 2009 -0500 @@ -392,8 +392,7 @@ t_node = cell.appendChild(t_node) r.appendChild(cell) self.AppendCols(1) - self.fit_cols() - + #self.fit_cols()::Where did this go? TaS. def del_row(self,evt=None): num = self.GetNumberRows() @@ -409,7 +408,7 @@ cells = r.getElementsByTagName('cell') r.removeChild(cells[num-1]) self.DeleteCols(num-1,1) - self.fit_cols() + #self.fit_cols()::Where did this go? TaS. G_TITLE = wx.NewId() diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/main.py --- a/orpg/main.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/main.py Sat Sep 19 06:50:43 2009 -0500 @@ -268,9 +268,9 @@ self.Bind(wx.EVT_MENU, self.OnMB_UpdateManagerPanel, mana) self.traipseSuite.AppendItem(mana) - debugger = wx.MenuItem(self.traipseSuite, -1, "Debug Console", "Debug Console") - self.Bind(wx.EVT_MENU, self.OnMB_DebugConsole, debugger) - self.traipseSuite.AppendItem(debugger) + self.debugConsole = wx.MenuItem(self.traipseSuite, -1, "Debug Console", "Debug Console") + self.Bind(wx.EVT_MENU, self.OnMB_DebugConsole, self.debugConsole) + self.traipseSuite.AppendItem(self.debugConsole) ################################# @@ -474,6 +474,12 @@ @debugging def OnMB_DebugConsole(self, evt): + ## Alpha ## + self.traipseSuite.RemoveItem(self.debugConsole) + self.debugConsole.SetBitmap(wx.Bitmap(dir_struct["icon"] + 'clear.gif')) + self.traipseSuite.AppendItem(self.debugConsole) + self.mainmenu.Replace(8, self.traipseSuite, '&Traipse Suite') + ########### if self.debugger.IsShown() == True: self.debugger.Hide() else: self.debugger.Show() @@ -645,7 +651,7 @@ #Update Manager self.manifest = manifest.ManifestChanges() self.updateMana = upmana.updatemana.updaterFrame(self, - "OpenRPG Update Manager Beta 0.7.2", component, self.manifest, True) + "OpenRPG Update Manager Beta 0.8", component, self.manifest, True) logger.debug("Menu Created") h = int(xml_dom.getAttribute("height")) w = int(xml_dom.getAttribute("width")) @@ -732,6 +738,7 @@ wndinfo.Name("Browse Server Window") wndinfo.Caption("Game Server") wndinfo.Float() + wndinfo.FloatingPosition((50,50)) wndinfo.Dockable(False) wndinfo.MinSize(wx.Size(640,480)) wndinfo.Hide() diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/mapper/background.py --- a/orpg/mapper/background.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/mapper/background.py Sat Sep 19 06:50:43 2009 -0500 @@ -33,6 +33,7 @@ import urllib import os.path import time +import mimetypes from orpg.orpgCore import component from orpg.tools.orpg_log import logger diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/mapper/background_handler.py --- a/orpg/mapper/background_handler.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/mapper/background_handler.py Sat Sep 19 06:50:43 2009 -0500 @@ -90,8 +90,8 @@ else: try: min_url = component.get("cherrypy") + filename except: return - min_url = dlg.GetDirectory().replace(orpg.dirpath.dir_struct["user"]+'webfiles' + os.sep, - component.get("cherrypy")) + '/' + filename + min_url = dlg.GetDirectory().replace(orpg.dirpath.dir_struct["user"]+'webfiles', + component.get("cherrypy")).replace(os.sep, '/') + '/' + filename if self.bg_type.GetStringSelection() == 'Texture': self.canvas.layers['bg'].set_texture(min_url) elif self.bg_type.GetStringSelection() == 'Image': self.size = self.canvas.layers['bg'].set_image(min_url,1) diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/mapper/images.py --- a/orpg/mapper/images.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/mapper/images.py Sat Sep 19 06:50:43 2009 -0500 @@ -98,10 +98,11 @@ """This function will flush all images contained within the image cache.""" self.__lock.acquire() try: - keyList = self.__cache.keys() - for key in keyList: del self.__cache[key] - finally: self.__lock.release() - urllib.urlcleanup() + self.__cache = {} + self.__fetching = {} + finally: + self.__lock.release() + urllib.urlcleanup() """Private Methods""" def __loadThread(self, path, image_type, imageId): @@ -158,3 +159,4 @@ Queue = property(_getQueue) ImageHandler = singleton(ImageHandlerClass) +component.add('ImageHandler', ImageHandler) diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/mapper/miniatures.py --- a/orpg/mapper/miniatures.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/mapper/miniatures.py Sat Sep 19 06:50:43 2009 -0500 @@ -33,7 +33,9 @@ import time import urllib import os.path +import mimetypes +import xml.dom.minidom as minidom from orpg.tools.orpg_settings import settings MIN_STICKY_BACK = -0XFFFFFF @@ -610,8 +612,9 @@ except Exception, e: print e print recvdata - urllib.urlcleanup() - self.lock.release() + finally: + urllib.urlcleanup() + self.lock.release() #################################################################### ## helper function diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/mapper/miniatures_handler.py --- a/orpg/mapper/miniatures_handler.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/mapper/miniatures_handler.py Sat Sep 19 06:50:43 2009 -0500 @@ -33,7 +33,7 @@ import time import mimetypes import urllib -import xml.dom.minidom as minidom + import wx from grid import GRID_RECTANGLE from grid import GRID_HEXAGON @@ -167,38 +167,41 @@ thread.start_new_thread(self.canvas.layers['miniatures'].upload, (postdata, dlg.GetPath()), {'pos':cmpPoint(x,y)}) else: - try: min_url = component.get("cherrypy") + filename - except: return #chat.InfoPost('CherryPy is not started!') - min_url = dlg.GetDirectory().replace(dir_struct["user"]+'webfiles' + os.sep, - component.get("cherrypy")) + '/' + filename - # build url - if min_url == "" or min_url == "http://": return - if min_url[:7] != "http://": min_url = "http://" + min_url - # make label - if self.auto_label and min_url[-4:-3] == '.': - start = min_url.rfind("/") + 1 - min_label = min_url[start:len(min_url)-4] - if self.use_serial: min_label = '%s %d' % ( min_label, self.canvas.layers['miniatures'].next_serial() ) - else: min_label = "" - if self.min_url.FindString(min_url) == -1: self.min_url.Append(min_url) - try: - id = 'mini-' + self.canvas.frame.session.get_next_id() - # make the new mini appear in top left of current viewable map - dc = wx.ClientDC(self.canvas) - self.canvas.PrepareDC(dc) - dc.SetUserScale(self.canvas.layers['grid'].mapscale,self.canvas.layers['grid'].mapscale) - x = dc.DeviceToLogicalX(0) - y = dc.DeviceToLogicalY(0) - self.canvas.layers['miniatures'].add_miniature(id, min_url, pos=cmpPoint(x,y), label=min_label) - except: - # When there is an exception here, we should be decrementing the serial_number for reuse!! - unablemsg= "Unable to load/resolve URL: " + min_url + " on resource \"" + min_label + "\"!!!\n\n" - dlg = wx.MessageDialog(self,unablemsg, 'Url not found',wx.ICON_EXCLAMATION) - dlg.ShowModal() - dlg.Destroy() - self.canvas.layers['miniatures'].rollback_serial() - self.canvas.send_map_data() - self.canvas.Refresh(False) + self.CherryPy(dlg.GetDirectory(), filename) + + def CherryPit(self, path, filename): + try: min_url = component.get("cherrypy") + filename + except: return #chat.InfoPost('CherryPy is not started!') + min_url = path.replace(orpg.dirpath.dir_struct["user"]+'webfiles', + component.get("cherrypy")).replace(os.sep, '/') + '/' + filename + # build url + if min_url == "" or min_url == "http://": return + if min_url[:7] != "http://": min_url = "http://" + min_url + # make label + if self.auto_label and min_url[-4:-3] == '.': + start = min_url.rfind("/") + 1 + min_label = min_url[start:len(min_url)-4] + if self.use_serial: min_label = '%s %d' % ( min_label, self.canvas.layers['miniatures'].next_serial() ) + else: min_label = "" + if self.min_url.FindString(min_url) == -1: self.min_url.Append(min_url) + try: + id = 'mini-' + self.canvas.frame.session.get_next_id() + # make the new mini appear in top left of current viewable map + dc = wx.ClientDC(self.canvas) + self.canvas.PrepareDC(dc) + dc.SetUserScale(self.canvas.layers['grid'].mapscale,self.canvas.layers['grid'].mapscale) + x = dc.DeviceToLogicalX(0) + y = dc.DeviceToLogicalY(0) + self.canvas.layers['miniatures'].add_miniature(id, min_url, pos=cmpPoint(x,y), label=min_label) + except: + # When there is an exception here, we should be decrementing the serial_number for reuse!! + unablemsg= "Unable to load/resolve URL: " + min_url + " on resource \"" + min_label + "\"!!!\n\n" + dlg = wx.MessageDialog(self,unablemsg, 'Url not found',wx.ICON_EXCLAMATION) + dlg.ShowModal() + dlg.Destroy() + self.canvas.layers['miniatures'].rollback_serial() + self.canvas.send_map_data() + self.canvas.Refresh(False) def build_menu(self,label = "Miniature"): @@ -614,7 +617,10 @@ y = dc.DeviceToLogicalY(y) (imgtype,j) = mimetypes.guess_type(filename) postdata = urllib.urlencode({'filename':filename, 'imgdata':imgdata, 'imgtype':imgtype}) - thread.start_new_thread(self.canvas.layers['miniatures'].upload, (postdata, filepath), {'pos':cmpPoint(x,y)}) + if self.settings.get_setting('LocalorRemote') == 'Remote': + thread.start_new_thread(self.canvas.layers['miniatures'].upload, (postdata, filepath), {'pos':cmpPoint(x,y)}) + else: + self.CherryPit(filepath, '') def on_tooltip_timer(self, *args): pos = args[0] diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/networking/gsclient.py --- a/orpg/networking/gsclient.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/networking/gsclient.py Sat Sep 19 06:50:43 2009 -0500 @@ -28,14 +28,15 @@ __version__ = "$Id: gsclient.py,v 1.53 2007/10/25 21:49:34 digitalxero Exp $" -from orpg.dirpath import dir_struct +import orpg.dirpath from orpg.orpg_windows import * +from orpg.orpg_xml import * import meta_server_lib -import orpg.tools.orpg_settings from orpg.tools.orpg_settings import settings import orpg.tools.rgbhex -from orpg.orpgCore import component +from orpg.orpgCore import open_rpg, component import traceback +from orpg.tools.orpg_log import logger gs_host = 1 gs_join = 2 @@ -99,10 +100,10 @@ def __init__(self,parent): wx.Panel.__init__(self, parent, -1) self.parent = parent + logger.debug("Enter game_server_panel", False) self.password_manager = component.get('password_manager') # passtool --SD 8/03 self.frame = component.get('frame') self.session = component.get('session') - self.xml = component.get('xml') #Not used?? self.serverNameSet = 0 self.last_motd = "" self.buttons = {} @@ -111,11 +112,14 @@ self.build_ctrls() self.refresh_server_list() self.refresh_room_list() + logger.debug("Exit game_server_panel", False) #--------------------------------------------------------- # [START] Snowdog: Updated Game Server Window 12/02 #--------------------------------------------------------- def build_ctrls(self): + logger.debug("Enter game_server_panel->build_ctrls(self)", False) + ## Section Sizers (with frame edges and text captions) self.box_sizers = {} self.box_sizers["server"] = wx.StaticBox(self, -1, "Server") @@ -153,9 +157,9 @@ #Build Rooms Sizer self.room_list = wx.ListCtrl(self, LIST_ROOM, style=wx.LC_REPORT | wx.SUNKEN_BORDER) - self.room_list.InsertColumn(0,"Game", wx.LIST_FORMAT_LEFT,-1) - self.room_list.InsertColumn(1,"Players", wx.LIST_FORMAT_LEFT,-1) - self.room_list.InsertColumn(2,"PW", wx.LIST_FORMAT_LEFT,-1) + self.room_list.InsertColumn(0,"Game", wx.LIST_FORMAT_LEFT,0) + self.room_list.InsertColumn(1,"Players", wx.LIST_FORMAT_LEFT,0) + self.room_list.InsertColumn(2,"PW", wx.LIST_FORMAT_LEFT,0) self.buttons[GS_JOIN] = wx.Button(self, GS_JOIN, "Join Room") self.buttons[GS_JOINLOBBY] = wx.Button(self, GS_JOINLOBBY, "Lobby") self.sizers["roombtns"] = wx.BoxSizer(wx.HORIZONTAL) @@ -231,17 +235,21 @@ self.cur_room_index = -1 self.cur_server_index = -1 self.rmList = {} + logger.debug("Exit game_server_panel->build_ctrls(self)", False) #--------------------------------------------------------- # [END] Snowdog: Updated Game Server Window 12/02 #--------------------------------------------------------- + #----------------------------------------------------- # on_server_dbclick() # support for double click selection of server. # 5/16/05 -- Snowdog #----------------------------------------------------- def on_server_dbclick(self, evt=None): + logger.debug("Enter game_server_panel->on_server_dbclick(self, evt)", False) + #make sure address is updated just in case list select wasn't done try: self.on_select(evt) @@ -256,6 +264,7 @@ #address differs, disconnect. self.frame.kill_mplay_session() self.do_connect(address) + logger.debug("Exit game_server_panel->on_server_dbclick(self, evt)", False) #----------------------------------------------------- @@ -265,6 +274,8 @@ #----------------------------------------------------- def on_room_dbclick(self, evt=None): + logger.debug("Enter game_server_panel->on_room_dbclick(self, evt)", False) + #make sure address is updated just in case list select wasn't done try: self.on_select(evt) @@ -290,9 +301,11 @@ else: pwd = "" self.session.send_join_group(group_id, pwd) + logger.debug("Exit game_server_panel->on_room_dbclick(self, evt)", False) def on_select(self,evt): + logger.debug("Enter game_server_panel->on_select(self,evt)", False) id = evt.GetId() if id == LIST_ROOM: self.cur_room_index = evt.m_itemIndex @@ -303,15 +316,19 @@ port = self.svrList[self.cur_server_index].port self.texts["address"].SetValue(address+":"+str(port)) self.refresh_room_list() + logger.debug("Exit game_server_panel->on_select(self,evt)", False) def on_text(self,evt): + logger.debug("Enter game_server_panel->on_text(self,evt)", False) id = evt.GetId() if (id == ADDRESS) and (self.cur_server_index >= 0): #print "ADDRESS id = ", id, "index = ", self.cur_server_index self.cur_server_index = -1 evt.Skip() + logger.debug("Exit game_server_panel->on_text(self,evt)", False) def add_room(self,data): + logger.debug("Enter game_server_panel->add_room(self,data)", False) i = self.room_list.GetItemCount() if (data[2]=="1") or (data[2]=="True"): pwd="yes" else: pwd="no" @@ -320,17 +337,21 @@ self.room_list.SetStringItem(i,2,pwd) self.room_list.SetItemData(i,int(data[0])) self.refresh_room_list() + logger.debug("Exit game_server_panel->add_room(self,data)", False) def del_room(self, data): + logger.debug("Enter game_server_panel->del_room(self, data)", False) i = self.room_list.FindItemData(-1, int(data[0])) self.room_list.DeleteItem(i) self.refresh_room_list() + logger.debug("Exit game_server_panel->del_room(self, data)", False) #--------------------------------------------------------- # [START] Snowdog Password/Room Name altering code 12/02 #--------------------------------------------------------- def update_room(self,data): + logger.debug("Enter game_server_panel->update_room(self,data)", False) #------------------------------------------------------- # Udated 12/02 by Snowdog @@ -343,6 +364,7 @@ self.room_list.SetStringItem(i,1,data[3]) self.room_list.SetStringItem(i,2,pwd) self.refresh_room_list() + logger.debug("Exit game_server_panel->update_room(self,data)", False) #--------------------------------------------------------- # [END] Snowdog Password/Room Name altering code 12/02 @@ -354,9 +376,12 @@ #self.sizers["room"].Layout() def set_lobbybutton(self,allow): + logger.debug("Enter game_server_panel->set_lobbybutton(self,allow)", False) self.buttons[GS_JOINLOBBY].Enable(allow) + logger.debug("Exit game_server_panel->set_lobbybutton(self,allow)", False) def set_connected(self,connected): + logger.debug("Enter game_server_panel->set_connected(self,connected)", False) self.buttons[GS_CONNECT].Enable(not connected) self.buttons[GS_DISCONNECT].Enable(connected) self.buttons[GS_JOIN].Enable(connected) @@ -371,8 +396,10 @@ #data = self.session.get_my_group() self.frame.status.set_connect_status(self.name) self.set_cur_room_text("Lobby") + logger.debug("Exit game_server_panel->set_connected(self,connected)", False) def on_button(self,evt): + logger.debug("Enter game_server_panel->son_button(self,evt)", False) id = evt.GetId() if id == GS_CONNECT: address = self.texts["address"].GetValue() @@ -382,12 +409,18 @@ except: self.name = `address` self.do_connect(address) - elif id == GS_DISCONNECT: self.frame.kill_mplay_session() - elif id == GS_CREATE_ROOM: self.do_create_group() - elif id == GS_JOIN: self.do_join_group() - elif id == GS_JOINLOBBY: self.do_join_lobby() - elif id == GS_SERVER_REFRESH: self.refresh_server_list() - elif id == GS_PWD: self.texts["room_pwd"].Enable(evt.Checked()) + elif id == GS_DISCONNECT: + self.frame.kill_mplay_session() + elif id == GS_CREATE_ROOM: + self.do_create_group() + elif id == GS_JOIN: + self.do_join_group() + elif id == GS_JOINLOBBY: + self.do_join_lobby() + elif id == GS_SERVER_REFRESH: + self.refresh_server_list() + elif id == GS_PWD: + self.texts["room_pwd"].Enable(evt.Checked()) elif id == OR_CLOSE: dlg = wx.MessageDialog(self,"Quit OpenRPG?","OpenRPG",wx.YES_NO) if dlg.ShowModal() == wx.ID_YES: @@ -396,8 +429,10 @@ self.frame.closed_confirmed() elif id == GS_CLOSE: self.parent.OnMB_GameServerBrowseServers() + logger.debug("Exit game_server_panel->son_button(self,evt)", False) def refresh_room_list(self): + logger.debug("Enter game_server_panel->refresh_room_list(self)", False) self.room_list.DeleteAllItems() address = self.texts["address"].GetValue() try: @@ -422,14 +457,18 @@ self.colorize_group_list(groups) self.room_list.SortItems(roomCmp) wx.CallAfter(self.autosizeRooms) + logger.debug("Exit game_server_panel->refresh_room_list(self)", False) def autosizeRooms(self): + logger.debug("Enter game_server_panel->autosizeRooms(self)", False) self.room_list.SetColumnWidth(0, wx.LIST_AUTOSIZE) - if self.room_list.GetColumnWidth(0) < 70: self.room_list.SetColumnWidth(0, 70) - if self.room_list.GetColumnWidth(1) < 70: self.room_list.SetColumnWidth(1, 70) - if self.room_list.GetColumnWidth(2) < 50: self.room_list.SetColumnWidth(2, 50) + self.room_list.SetColumnWidth(1, wx.LIST_AUTOSIZE) + self.room_list.SetColumnWidth(2, wx.LIST_AUTOSIZE) + logger.debug("Exit game_server_panel->autosizeRooms(self)", False) def refresh_server_list(self): + logger.debug("Enter game_server_panel->refresh_server_list(self)", False) + try: self.svrList = [] self.server_list.DeleteAllItems() @@ -447,9 +486,7 @@ partLength = 1.0/length for n in node_list: if n.hasAttribute('id') and n.hasAttribute('name') and n.hasAttribute('num_users') and n.hasAttribute('address') and n.hasAttribute('port'): - self.svrList.append(server_instance(n.getAttribute('id'), n.getAttribute('name'), - n.getAttribute('num_users'), n.getAttribute('address'), - n.getAttribute('port'))) + self.svrList.append( server_instance(n.getAttribute('id'),n.getAttribute('name'), n.getAttribute('num_users'), n.getAttribute('address'),n.getAttribute('port'))) address = n.getAttribute('address') + ':' + n.getAttribute('port') self.rmList[address] = [] rooms = n.getElementsByTagName('room') @@ -488,7 +525,6 @@ # No server is currently selected!!! Versus the broken and random 0! self.cur_server_index = -1 self.server_list.SetColumnWidth(0, wx.LIST_AUTOSIZE) - if self.server_list.GetColumnWidth(0) < 70: self.server_list.SetColumnWidth(0, 70) self.server_list.SetColumnWidth(1, wx.LIST_AUTOSIZE) if self.serverNameSet == 0: @@ -512,8 +548,10 @@ except Exception, e: print "Server List not available." traceback.print_exc() + logger.debug("Exit game_server_panel->refresh_server_list(self)", False) def failed_connection(self): + logger.debug("Enter game_server_panel->failed_connection(self)", False) if(self.cur_server_index >= 0): id = self.servers[self.cur_server_index].getAttribute('id') meta = self.servers[self.cur_server_index].getAttribute('meta') @@ -523,8 +561,10 @@ # was removed. If it was, refresh the display if(meta_server_lib.post_failed_connection(id,meta=meta,address=address,port=port)): self.refresh_server_list() + logger.debug("Exit game_server_panel->failed_connection(self)", False) def do_connect(self, address): + logger.debug("Enter game_server_panel->do_connect(self, address)", False) chat = component.get('chat') chat.InfoPost("Locating server at " + address + "...") if self.session.connect(address): @@ -532,13 +572,17 @@ else: chat.SystemPost("Failed to connect to game server...") self.failed_connection() + logger.debug("Exit game_server_panel->do_connect(self, address)", False) def do_join_lobby(self): + logger.debug("Enter game_server_panel->do_join_lobby(self)", False) self.cur_room_index = 0 self.session.send_join_group("0","") self.set_lobbybutton(0); + logger.debug("Exit game_server_panel->do_join_lobby(self)", False) def do_join_group(self): + logger.debug("Enter game_server_panel->do_join_group(self)", False) if self.cur_room_index >= 0: if self.cur_room_index != 0: self.set_lobbybutton(1); @@ -557,8 +601,10 @@ pwd = "" if pwd != None: #pwd==None means the user clicked "Cancel" self.session.send_join_group(group_id,pwd) + logger.debug("Exit game_server_panel->do_join_group(self)", False) def do_create_group(self): + logger.debug("Enter game_server_panel->do_create_group(self)", False) name = self.texts["room_name"].GetValue() boot_pwd = self.texts["room_boot_pwd"].GetValue() minversion = self.texts["room_min_version"].GetValue() @@ -603,6 +649,7 @@ self.session.send( msg ) self.session.send_create_group(name,pwd,boot_pwd,minversion) self.set_lobbybutton(1); #enable the Lobby quickbutton + logger.debug("Exit game_server_panel->do_create_group(self)", False) #--------------------------------------------------------- @@ -624,31 +671,39 @@ def colorize_group_list(self, groups): + logger.debug("Enter game_server_panel->colorize_group_list(self, groups)", False) + try: hex = orpg.tools.rgbhex.RGBHex() +# activ = settings.get_setting("RoomColor_Active") +# lockt = settings.get_setting("RoomColor_Locked") +# empty = settings.get_setting("RoomColor_Empty") +# lobby = settings.get_setting("RoomColor_Lobby") +#renamed colors - TaS sirebral for gr in groups: item_list_location = self.room_list.FindItemData(-1,int(gr[0])) if item_list_location != -1: item = self.room_list.GetItem(item_list_location) if gr[0] == "0": - +# active_state = lobby r,g,b = hex.rgb_tuple(settings.get_setting("RoomColor_Lobby")) elif gr[3] <> "0": - +# active_state = activ if gr[2] == "True" or gr[2] == "1": - +# active_state = lockt r,g,b = hex.rgb_tuple(settings.get_setting("RoomColor_Locked")) else: - +# active_state = activ r,g,b = hex.rgb_tuple(settings.get_setting("RoomColor_Active")) else: - +# active_state = empty r,g,b = hex.rgb_tuple(settings.get_setting("RoomColor_Empty")) - +# r,g,b = hex.rgb_tuple(active_state) color = wx.Colour(red=r,green=g,blue=b) item.SetTextColour(color) self.room_list.SetItem(item) except: traceback.print_exc() + logger.debug("Exit game_server_panel->colorize_group_list(self, groups)", False) diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/networking/meta_server_lib.py --- a/orpg/networking/meta_server_lib.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/networking/meta_server_lib.py Sat Sep 19 06:50:43 2009 -0500 @@ -34,9 +34,9 @@ __version__ = "$Id: meta_server_lib.py,v 1.40 2007/04/04 01:18:42 digitalxero Exp $" from orpg.orpg_version import PROTOCOL_VERSION -from orpg.orpgCore import component -from orpg.tools.validate import validate -from orpg.dirpath import dir_struct +from orpg.orpg_xml import xml +import orpg.dirpath +import orpg.tools.validate import urllib import orpg.minidom from threading import * @@ -69,7 +69,8 @@ # Remove any leading or trailing data. This can happen on some satellite connections p = re.compile('(.*?)',re.DOTALL|re.IGNORECASE) mo = p.search(data) - if mo: data = mo.group(0) + if mo: + data = mo.group(0) if META_DEBUG: print @@ -78,12 +79,16 @@ print data print # build dom - xml = component.get('xml') xml_dom = xml.parseXml(data) xml_dom = xml_dom._get_documentElement() return xml_dom def post_server_data( name, realHostName=None): + # build POST data +## data = urllib.urlencode( {"server_data[name]":name, +## "server_data[version]":PROTOCOL_VERSION, +## "act":"new"} ) +## if realHostName: data = urllib.urlencode( {"server_data[name]":name, "server_data[version]":PROTOCOL_VERSION, @@ -96,9 +101,7 @@ "server_data[version]":PROTOCOL_VERSION, "act":"new"} ) - #xml_dom = get_server_dom( data , "http://openrpg.sf.net/openrpg_servers.php")#Sourceforge still? - path = component.get('settings').get_setting('MetaServerBaseURL') #getMetaServerBaseURL() - xml_dom = get_server_dom(data, path) + xml_dom = get_server_dom( data , "http://openrpg.sf.net/openrpg_servers.php") ret_val = int( xml_dom.getAttribute( "id" ) ) return ret_val @@ -106,10 +109,10 @@ # For now, turning this off. This needs to be re-vamped for # handling multiple Metas. return 0 - #data = urllib.urlencode({"id":id,"act":"failed"}); - #xml_dom = get_server_dom(data) - #ret_val = int(xml_dom.getAttribute("return")) - #return ret_val +# data = urllib.urlencode({"id":id,"act":"failed"}); +# xml_dom = get_server_dom(data) +# ret_val = int(xml_dom.getAttribute("return")) +# return ret_val def remove_server(id): data = urllib.urlencode({"id":id,"act":"del"}); @@ -122,11 +125,15 @@ # This function is used to easily sort a list of nodes # by their start time - if first.hasAttribute("start"): first_start = int(first.getAttribute("start")) - else: first_start = 0 + if first.hasAttribute("start"): + first_start = int(first.getAttribute("start")) + else: + first_start = 0 - if second.hasAttribute("start"): second_start = int(second.getAttribute("start")) - else: second_start = 0 + if second.hasAttribute("start"): + second_start = int(second.getAttribute("start")) + else: + second_start = 0 # Return the result of the cmp function on the two strings return cmp(first_start,second_start) @@ -137,13 +144,18 @@ # Ensure there is something to sort with for each - if first.hasAttribute("name"): first_name = str(first.getAttribute("name")).lower() - else: first_name = "" + if first.hasAttribute("name"): + first_name = str(first.getAttribute("name")).lower() + else: + first_name = "" - if second.hasAttribute("name"): second_name = str(second.getAttribute("name")).lower() - else: second_name = "" + if second.hasAttribute("name"): + second_name = str(second.getAttribute("name")).lower() + else: + second_name = "" # Return the result of the cmp function on the two strings + return cmp(first_name,second_name) @@ -159,10 +171,11 @@ for meta in all_metas: # check all of the metas - #get the server's xml from the current meta + # 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) + try: + xml_dom = get_server_dom(data=data,path=meta) except: #print "Trouble getting servers from " + meta + "..." bad_meta = 1 @@ -185,13 +198,17 @@ # set them from current node - if not n.hasAttribute('name'): n.setAttribute('name','NO_NAME_GIVEN') + if not n.hasAttribute('name'): + n.setAttribute('name','NO_NAME_GIVEN') name = n.getAttribute('name') - if not n.hasAttribute('num_users'): n.setAttribute('num_users','N/A') + if not n.hasAttribute('num_users'): + n.setAttribute('num_users','N/A') num_users = n.getAttribute('num_users') - if not n.hasAttribute('address'): n.setAttribute('address','NO_ADDRESS_GIVEN') + if not n.hasAttribute('address'): + n.setAttribute('address','NO_ADDRESS_GIVEN') address = n.getAttribute('address') - if not n.hasAttribute('port'): n.setAttribute('port','6774') + if not n.hasAttribute('port'): + n.setAttribute('port','6774') port = n.getAttribute('port') n.setAttribute('meta',meta) end_point = str(address) + ":" + str(port) @@ -211,11 +228,14 @@ # sort them by their name attribute. Uses byNameAttribute() # defined above as a comparison function - if sort_by == "start": return_list.sort(byStartAttribute) - elif sort_by == "name": return_list.sort(byNameAttribute) + if sort_by == "start": + return_list.sort(byStartAttribute) + elif sort_by == "name": + return_list.sort(byNameAttribute) # Add each node to the DOM - for n in return_list: return_dom.appendChild(n) + for n in return_list: + return_dom.appendChild(n) return return_dom ## List Format: @@ -237,7 +257,7 @@ if META_DEBUG: print " Meta List ("+str(len(metas))+" servers)" try: metacache_lock.acquire() - ini = open(dir_struct["user"]+"metaservers.cache","w") + ini = open(orpg.dirpath.dir_struct["user"]+"metaservers.cache","w") for meta in metas: if META_DEBUG: print " Writing: "+str(meta.getAttribute('path')) ini.write(str(meta.getAttribute('path')) + " " + str(meta.getAttribute('versions')) + "\n") @@ -253,8 +273,8 @@ try: metacache_lock.acquire() # Read in the metas - validate.config_file("metaservers.cache","metaservers.cache") - ini = open(dir_struct["user"]+"metaservers.cache","r") + orpg.tools.validate.Validate().config_file("metaservers.cache","metaservers.cache") + ini = open(orpg.dirpath.dir_struct["user"]+"metaservers.cache","r") metas = ini.readlines() ini.close() return metas @@ -266,27 +286,23 @@ return [] def getMetaServers(versions = None, pick_random=0): - """ - get meta server URLs as a list + # get meta server URLs as a list - versions is a list of acceptable version numbers. - A False truth value will use getMetaServerBaseURL() + # 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" - """ + # set a default if we have weird reading problems + # default_url = "http://www.openrpg.com/openrpg_servers.php" 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 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 metas = getRawMetaList() @@ -299,10 +315,13 @@ # 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 @@ -311,8 +330,8 @@ 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" +# 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) @@ -338,10 +357,9 @@ # get meta server URL url = "http://www.openrpg.com/openrpg_servers.php" try: - component.get('validate').config_file("settings.xml","default_settings.xml") - ini = open(dir_struct["user"]+"settings.xml","r") + orpg.tools.validate.Validate().config_file("settings.xml","default_settings.xml") + ini = open(orpg.dirpath.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") @@ -349,47 +367,47 @@ url = node_list[0].getAttribute("value") # allow tree to be collected - try: tree.unlink() - except: pass + try: + tree.unlink() + except: + pass except Exception,e: print e - #print "using meta server URI: " + url +# print "using meta server URI: " + url return url -""" - Beginning of Class registerThread - - A Class to Manage Registration with the Meta2 - Create an instance and call it's start() method - if you want to be (and stay) registered. This class - will take care of registering and re-registering as - often as necessary to stay in the Meta list. +####################################################################################### +# Beginning of Class registerThread +# +# A Class to Manage Registration with the Meta2 +# Create an instance and call it's start() method +# if you want to be (and stay) registered. This class +# will take care of registering and re-registering as +# often as necessary to stay in the Meta list. +# +# You may call register() yourself if you wish to change your +# server's name. It will immediately update the Meta. There +# is no need to unregister first. +# +# Call unregister() when you no longer want to be registered. +# This will result in the registerThread dying after +# attempting to immediately remove itself from the Meta. +# +# If you need to become registered again after that, you +# must create a new instance of class registerThread. Don't +# just try to call register() on the old, dead thread class. - You may call register() yourself if you wish to change your - server's name. It will immediately update the Meta. There - is no need to unregister first. - - Call unregister() when you no longer want to be registered. - This will result in the registerThread dying after - attempting to immediately remove itself from the Meta. - - If you need to become registered again after that, you - must create a new instance of class registerThread. Don't - just try to call register() on the old, dead thread class. -""" class registerThread(Thread): - """ - Originally, I wrote this as a sub-class of wxThread, but - A) I couldn't get it to import right - B) I realized that I want this to be used in a server, - which I don't want needing wxWindows to run! - - Because of this fact, there are some methods from wxThread - that I implemented to minimize changes to the code I had - just written, i.e. TestDeleteStatus() and Delete() - """ +# Originally, I wrote this as a sub-class of wxThread, but +# A) I couldn't get it to import right +# B) I realized that I want this to be used in a server, +# which I don't want needing wxWindows to run! +# +# Because of this fact, there are some methods from wxThread +# that I implemented to minimize changes to the code I had +# just written, i.e. TestDeleteStatus() and Delete() def __init__(self,name=None,realHostName=None,num_users = "Hmmm",MetaPath=None,port=6774,register_callback=None): @@ -411,17 +429,15 @@ # re-register, in minutes. self.destroy = 0 # Used to flag that this thread should die self.port = str(port) - self.register_callback = register_callback # set a method to call to report result of register - """ - This thread will communicate with one and only one - Meta. If the Meta in ini.xml is changed after - instantiation, then this instance must be - unregistered and a new instance instantiated. - - Also, if MetaPath is specified, then use that. Makes - it easier to have multiple registerThreads going to keep the server registered - on multiple (compatible) Metas. - """ + self.register_callback = register_callback # set a method to call to report result of register + # This thread will communicate with one and only one + # Meta. If the Meta in ini.xml is changed after + # instantiation, then this instance must be + # unregistered and a new instance instantiated. + # + # Also, if MetaPath is specified, then use that. Makes + # 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 @@ -446,19 +462,18 @@ self.rlock.release() def run(self): - """ - This method gets called by Thread implementation - when self.start() is called to begin the thread's - execution - - We will basically enter a loop that continually - re-registers this server and sleeps Interval - minutes until the thread is ordered to die in place - """ + # This method gets called by Thread implementation + # when self.start() is called to begin the thread's + # execution + # + # We will basically enter a loop that continually + # re-registers this server and sleeps Interval + # minutes until the thread is ordered to die in place while(not self.TestDeleteStatus()): # Loop while until told to die # Otherwise, call thread safe register(). self.register(self.name, self.realHostName, self.num_users) if META_DEBUG: print "Sent Registration Data" + # register() will end up setting the state variables # for us, including self.interval. try: @@ -481,21 +496,19 @@ # calls to Thread.isAlive() return False. def unregister(self): - """ - This method can (I hope) be called from both within the thread - and from other threads. It will attempt to unregister this - server from the Meta database - When this is either accomplished or has been tried hard enough - (after which it just makes sense to let the Meta remove the - entry itself when we don't re-register using this id), - this method will either cause the thread to immediately die - (if called from this thread's context) or set the Destroy flag - (if called from the main thread), a positive test for which will cause - the code in Entry() to exit() when the thread wakes up and - checks TestDeleteStatus(). - lock the critical section. The unlock will - automatically occur at the end of the function in the finally clause - """ + # This method can (I hope) be called from both within the thread + # and from other threads. It will attempt to unregister this + # server from the Meta database + # When this is either accomplished or has been tried hard enough + # (after which it just makes sense to let the Meta remove the + # entry itself when we don't re-register using this id), + # this method will either cause the thread to immediately die + # (if called from this thread's context) or set the Destroy flag + # (if called from the main thread), a positive test for which will cause + # the code in Entry() to exit() when the thread wakes up and + # checks TestDeleteStatus(). + # lock the critical section. The unlock will + # automatically occur at the end of the function in the finally clause try: self.rlock.acquire() if not self.isAlive(): # check to see if this thread is dead @@ -518,31 +531,35 @@ # way, we can't do anything else, so die. self.Delete() # This will cause the registerThread to die in register() # prep xml_dom for garbage collection - try: xml_dom.unlink() - except: pass + try: + xml_dom.unlink() + except: + pass return 0 - finally: self.rlock.release() + finally: + self.rlock.release() def register(self, name=None, realHostName=None, num_users=None): - """ - Designed to handle the registration, both new and - repeated. - - It is intended to be called once every interval - (or interval - delta) minutes. + # Designed to handle the registration, both new and + # repeated. + # + # It is intended to be called once every interval + # (or interval - delta) minutes. - lock the critical section. The unlock will - automatically occur at the end of the function in the finally clause - """ + # lock the critical section. The unlock will + # automatically occur at the end of the function in the finally clause try: self.rlock.acquire() if not self.isAlive(): # check to see if this thread is dead return 1 # If so, return an error result # Set the server's attibutes, if specified. - if name: self.name = name - if num_users != None: self.num_users = num_users - if realHostName: self.realHostName = realHostName + if name: + self.name = name + if num_users != None: + self.num_users = num_users + if realHostName: + self.realHostName = realHostName # build POST data if self.realHostName: data = urllib.urlencode( {"server_data[id]":self.id, @@ -569,20 +586,17 @@ 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(). - """ + # 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 xml_dom: # If there's an error, echo it to the console @@ -590,24 +604,22 @@ print "Error durring registration: " + xml_dom.getAttribute("errmsg") if META_DEBUG: print data if META_DEBUG: print - """ - No special handling is required. If the registration worked, id, cookie, and interval - can be stored and used for the next time. - If an error occurred, then the Meta will delete us and we need to re-register as - a new server. The way to indicate this is with a "0" id and "0" cookie sent to - the server during the next registration. Since that's what the server returns to - us on an error anyway, we just store them and the next registration will - automatically be set up as a new one. - - Unless the server calls register() itself in the meantime. Of course, that's okay - too, because a success on THAT register() call will set up the next one to use - the issued id and cookie. - - The interval is stored unconditionally for similar reasons. If there's an error, - the interval will be less than 1, and the main thread's while loop will reset it - to 6 seconds for the next retry. - Is it wrong to have a method where there's more comments than code? :) - """ + # No special handling is required. If the registration worked, id, cookie, and interval + # can be stored and used for the next time. + # If an error occurred, then the Meta will delete us and we need to re-register as + # a new server. The way to indicate this is with a "0" id and "0" cookie sent to + # the server during the next registration. Since that's what the server returns to + # us on an error anyway, we just store them and the next registration will + # automatically be set up as a new one. + # + # Unless the server calls register() itself in the meantime. Of course, that's okay + # too, because a success on THAT register() call will set up the next one to use + # the issued id and cookie. + # + # The interval is stored unconditionally for similar reasons. If there's an error, + # the interval will be less than 1, and the main thread's while loop will reset it + # to 6 seconds for the next retry. + # Is it wrong to have a method where there's more comments than code? :) try: self.interval = int(xml_dom.getAttribute("interval")) self.id = xml_dom.getAttribute("id") diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/networking/mplay_client.py --- a/orpg/networking/mplay_client.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/networking/mplay_client.py Sat Sep 19 06:50:43 2009 -0500 @@ -29,7 +29,7 @@ __version__ = "$Id: mplay_client.py,v 1.71 2007/05/12 20:41:54 digitalxero Exp $" -#import orpg.minidom +import orpg.minidom import socket import Queue import thread @@ -38,22 +38,24 @@ from xml.sax.saxutils import escape from struct import pack, unpack, calcsize from string import * -from orpg.orpg_version import CLIENT_STRING, PROTOCOL_VERSION, VERSION +from orpg.orpg_version import * import errno import os import time -from orpg.orpgCore import component from orpg.orpg_xml import xml +import orpg.minidom as minidom try: import bz2 cmpBZ2 = True -except: cmpBZ2 = False +except: + cmpBZ2 = False try: import zlib cmpZLIB = True -except: cmpZLIB = False +except: + cmpZLIB = False # This should be configurable @@ -83,7 +85,7 @@ def parseXml(data): "parse and return doc" #print data - doc = xml.parseXml(data) + doc = minidom.parseString(data) doc.normalize() return doc @@ -117,11 +119,9 @@ self.group_id = "0" self.name = "" self.role = "GM" - ## Soon to be removed self.ROLE_GM = "GM" self.ROLE_PLAYER = "Player" self.ROLE_LURKER = "Lurker" - ## --TaS self.ip = socket.gethostbyname(socket.gethostname()) self.remote_ip = None self.version = VERSION @@ -135,6 +135,9 @@ self.text_status = "Idle" self.statLock = Lock() self.useroles = 0 + self.ROLE_GM = "GM" + self.ROLE_PLAYER = "Player" + self.ROLE_LURKER = "Lurker" self.lastmessagetime = time.time() self.connecttime = time.time() @@ -146,7 +149,8 @@ # Loop as long as we have a connection while( self.get_status() == MPLAY_CONNECTED ): - try: readMsg = self.outbox.get( block=1 ) + try: + readMsg = self.outbox.get( block=1 ) except Exception, text: self.log_msg( ("outbox.get() got an exception: ", text) ) @@ -174,13 +178,15 @@ try: if self.useCompression and self.compressionType != None: readMsg = self.compressionType.decompress(readMsg) - except: pass + except: + pass # Check the length of the message bytes = len( readMsg ) # Make sure we are still connected - if bytes == 0: break + if bytes == 0: + break else: # Pass along the message so it can be processed self.inbox.put( readMsg ) @@ -219,9 +225,12 @@ # Now, send the message the the length was describing sentm = sock.send( msg ) - if self.isServer(): self.log_msg(("data_sent", sentl+sentm)) - except socket.error, e: self.log_msg( e ) - except Exception, e: self.log_msg( e ) + if self.isServer(): + self.log_msg(("data_sent", sentl+sentm)) + except socket.error, e: + self.log_msg( e ) + except Exception, e: + self.log_msg( e ) return sentm def recvData( self, sock, readSize ): @@ -269,8 +278,10 @@ # Make the peer IP address available for reference later if self.remote_ip is None: self.remote_ip = self.sock.getpeername() - except IOError, e: self.log_msg( e ) - except Exception, e: self.log_msg( e ) + except IOError, e: + self.log_msg( e ) + except Exception, e: + self.log_msg( e ) return msgData def initialize_threads(self): @@ -286,7 +297,8 @@ self.set_status(MPLAY_DISCONNECTING) self.log_msg("client stub " + self.ip +" disconnecting...") self.log_msg("closing sockets...") - try: self.sock.shutdown( 2 ) + try: + self.sock.shutdown( 2 ) except Exception, e: print "Caught exception: " + str(e) print @@ -308,15 +320,13 @@ else: return 0 def update_self_from_player(self, player): - try: (self.name, self.ip, self.id, - self.text_status, self.version, - self.protocol_version, self.client_string, role) = player + try: + (self.name, self.ip, self.id, self.text_status, self.version, self.protocol_version, self.client_string,role) = player except Exception, e: print e - """ - The IP field should really be deprecated as too many systems are NAT'd and/or behind firewalls for a - client provided IP address to have much value. As such, we now label it as deprecated. - """ + +# The IP field should really be deprecated as too many systems are NAT'd and/or behind firewalls for a +# client provided IP address to have much value. As such, we now label it as deprecated. def toxml(self,action): xml_data = '" - self.outbox.put(recycle_bin); del recycle_bin #makes line easier to read. --TaS + self.outbox.put("") self.update() def set_room_name(self,name,pwd=""): @@ -587,10 +600,7 @@ e = name[loc+1:] name = b + "'" + e oldloc = loc+1 - recycle_bin = "" - self.outbox.put(recycle_bin); del recycle_bin #makes line easier to read. --TaS + self.outbox.put("") self.update() #--------------------------------------------------------- @@ -604,9 +614,7 @@ self.outbox.put("") def set_role(self,player,role,pwd=""): - recycle_bin = "" - self.outbox.put(recycle_bin); del recycle_bin #makes line easer to read. --TaS + self.outbox.put("") self.update() def send(self,msg,player="all"): @@ -620,13 +628,12 @@ self.check_my_status() def send_create_group(self,name,pwd,boot_pwd,minversion): - recycle_bin = "" - self.outbox.put(recycle_bin); del recycle_bin #makes line easier to read. --TaS + self.outbox.put("") def send_join_group(self,group_id,pwd): - if (group_id != 0): self.update_role("Lurker") + if (group_id != 0): + self.update_role("Lurker") self.outbox.put("") def poll(self, evt=None): @@ -636,7 +643,8 @@ if self.get_status() != MPLAY_CONNECTED: self.check_my_status() else: - try: self.pretranslate(msg) + try: + self.pretranslate(msg) except Exception, e: print "The following message: " + str(msg) print "created the following exception: " @@ -645,13 +653,16 @@ def add_msg_handler(self, tag, function, core=False): if not self.msg_handlers.has_key(tag): self.msg_handlers[tag] = function - if core: self.core_msg_handlers.append(tag) - else: print 'XML Messages ' + tag + ' already has a handler' + if core: + self.core_msg_handlers.append(tag) + else: + print 'XML Messages ' + tag + ' already has a handler' def remove_msg_handler(self, tag): if self.msg_handlers.has_key(tag) and not tag in self.core_msg_handlers: del self.msg_handlers[tag] - else: print 'XML Messages ' + tag + ' already deleted' + else: + print 'XML Messages ' + tag + ' already deleted' def load_core_msg_handlers(self): self.add_msg_handler('msg', self.on_msg, True) @@ -665,16 +676,19 @@ def pretranslate(self,data): # Pre-qualify our data. If we don't have atleast 5-bytes, then there is # no way we even have a valid message! - if len(data) < 5: return + if len(data) < 5: + return end = data.find(">") head = data[:end+1] msg = data[end+1:] - xml_dom = self.xml.parseXml(head) + xml_dom = xml.parseXml(head) xml_dom = xml_dom._get_documentElement() tag_name = xml_dom._get_tagName() id = xml_dom.getAttribute("from") - if id == '': id = xml_dom.getAttribute("id") - if self.msg_handlers.has_key(tag_name): self.msg_handlers[tag_name](id, data, xml_dom) + if id == '': + id = xml_dom.getAttribute("id") + if self.msg_handlers.has_key(tag_name): + self.msg_handlers[tag_name](id, data, xml_dom) else: #Unknown messages recived ignoring #using pass insted or printing an error message @@ -682,7 +696,8 @@ #if someone is using a plugin to send messages and this user does not #have the plugin they would be getting errors pass - if xml_dom: xml_dom.unlink() + if xml_dom: + xml_dom.unlink() def on_sound(self, id, data, xml_dom): (ignore_id,ignore_name) = self.get_ignore_list() @@ -704,8 +719,10 @@ self.on_receive(msg,None) # None get's interpreted in on_receive as the sys admin. # Doing it this way makes it harder to impersonate the admin else: - if self.is_valid_id(id): self.on_receive(msg,self.players[id]) - if xml_dom: xml_dom.unlink() + if self.is_valid_id(id): + self.on_receive(msg,self.players[id]) + if xml_dom: + xml_dom.unlink() def on_ping(self, id, msg, xml_dom): #a REAL ping time implementation by Snowdog 8/03 @@ -720,7 +737,8 @@ latency = float( latency) / 10.0 ping_msg = "Ping Results: " + str(latency) + " ms (parsed message, round trip)" self.on_receive(ping_msg,None) - if xml_dom: xml_dom.unlink() + if xml_dom: + xml_dom.unlink() def on_group(self, id, msg, xml_dom): name = xml_dom.getAttribute("name") @@ -738,7 +756,8 @@ elif act == 'update': self.groups[id] = group_data self.on_group_event(mplay_event(GROUP_UPDATE, group_data)) - if xml_dom: xml_dom.unlink() + if xml_dom: + xml_dom.unlink() def on_role(self, id, msg, xml_dom): act = xml_dom.getAttribute("action") @@ -749,10 +768,13 @@ if id == self.id: self.players[id] = (a,b,c,d,e,f,g,role) self.update_role(role) - else: self.players[id] = (a,b,c,d,e,f,g,role) + else: + self.players[id] = (a,b,c,d,e,f,g,role) self.on_player_event(mplay_event(PLAYER_UPDATE,self.players[id])) - except: pass - if xml_dom: xml_dom.unlink() + except: + pass + if xml_dom: + xml_dom.unlink() def on_player(self, id, msg, xml_dom): act = xml_dom.getAttribute("action") @@ -762,39 +784,42 @@ version = xml_dom.getAttribute("version") protocol_version = xml_dom.getAttribute("protocol_version") client_string = xml_dom.getAttribute("client_string") - try: player = (name, ip, id, status, - version, protocol_version, - client_string, self.players[id][7]) + try: + player = (name,ip,id,status,version,protocol_version,client_string,self.players[id][7]) except Exception, e: - player = (name, ip, id, status, - version, protocol_version, - client_string, "Player") + player = (name,ip,id,status,version,protocol_version,client_string,"Player") if act == "new": self.players[id] = player - self.on_player_event(mplay_event(PLAYER_NEW, self.players[id])) + self.on_player_event(mplay_event(PLAYER_NEW,self.players[id])) elif act == "group": self.group_id = xml_dom.getAttribute("group_id") self.clear_players() - self.on_mplay_event(mplay_event(MPLAY_GROUP_CHANGE, self.groups[self.group_id])) + self.on_mplay_event(mplay_event(MPLAY_GROUP_CHANGE,self.groups[self.group_id])) self.players[self.id] = self.get_my_info() #(self.name,self.ip,self.id,self.text_status) - self.on_player_event(mplay_event(PLAYER_NEW, self.players[self.id])) + self.on_player_event(mplay_event(PLAYER_NEW,self.players[self.id])) elif act == "failed": self.on_mplay_event(mplay_event(MPLAY_GROUP_CHANGE_F)) elif act == "del": self.on_player_event(mplay_event(PLAYER_DEL,self.players[id])) - if self.players.has_key(id): del self.players[id] - if id == self.id: self.do_disconnect() + if self.players.has_key(id): + del self.players[id] + if id == self.id: + self.do_disconnect() # the next two cases handle the events that are used to let you know when others are typing elif act == "update": if id == self.id: self.players[id] = player self.update_self_from_player(player) - else: self.players[id] = player + else: + self.players[id] = player dont_send = 0 for m in self.ignore_id: - if m == id: dont_send=1 - if dont_send != 1: self.on_player_event(mplay_event(PLAYER_UPDATE,self.players[id])) - if xml_dom: xml_dom.unlink() + if m == id: + dont_send=1 + if dont_send != 1: + self.on_player_event(mplay_event(PLAYER_UPDATE,self.players[id])) + if xml_dom: + xml_dom.unlink() def on_password(self, id, msg, xml_dom): signal = type = id = data = None @@ -808,7 +833,8 @@ def check_my_status(self): status = self.get_status() - if status == MPLAY_DISCONNECTING: self.do_disconnect() + if status == MPLAY_DISCONNECTING: + self.do_disconnect() def connect(self, addressport): """Establish a connection to a server while still using sendThread & recvThread for its @@ -834,7 +860,7 @@ self.sendMsg( self.sock, self.toxml("new") ) data = self.recvMsg( self.sock ) # get new id and group_id - xml_dom = self.xml.parseXml(data) + xml_dom = xml.parseXml(data) xml_dom = xml_dom._get_documentElement() self.id = xml_dom.getAttribute("id") self.group_id = xml_dom.getAttribute("group_id") @@ -845,29 +871,31 @@ self.compressionType = bz2 elif cmpZLIB and xml_dom.getAttribute('cmpType') == 'zlib': self.compressionType = zlib - else: self.compressionType = None - else: self.compressionType = bz2 + else: + self.compressionType = None + else: + self.compressionType = bz2 #send confirmation self.sendMsg( self.sock, self.toxml("new") ) except Exception, e: self.log_msg(e) - if xml_dom: xml_dom.unlink() + if xml_dom: + xml_dom.unlink() return 0 # Start things rollings along self.initialize_threads() self.on_mplay_event(mplay_event(MPLAY_CONNECTED)) - self.players[self.id] = (self.name, self.ip, self.id, - self.text_status, self.version, - self.protocol_version, self.client_string, self.role) + self.players[self.id] = (self.name,self.ip,self.id,self.text_status,self.version,self.protocol_version,self.client_string,self.role) self.on_player_event(mplay_event(PLAYER_NEW,self.players[self.id])) - if xml_dom: xml_dom.unlink() + if xml_dom: + xml_dom.unlink() return 1 def start_disconnect(self): self.on_mplay_event(mplay_event(MPLAY_DISCONNECTING)) self.outbox.put( self.toxml("del") ) - ## Client Side Disconect Forced -- Snowdog 10-09-2003 + ## Client Side Disconect Forced -- Snowdog 10-09-2003 #pause to allow GUI events time to sync. time.sleep(1) self.do_disconnect() diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/networking/mplay_groups.py --- a/orpg/networking/mplay_groups.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/networking/mplay_groups.py Sat Sep 19 06:50:43 2009 -0500 @@ -1,9 +1,7 @@ from orpg.mapper.map_msg import * class game_group: - def __init__( self, id, name, pwd, desc="", - boot_pwd="", minVersion="", - mapFile=None, messageFile=None, persist=0 ): + def __init__( self, id, name, pwd, desc="", boot_pwd="", minVersion="", mapFile=None, messageFile=None, persist =0 ): self.id = id self.name = name self.desc = desc @@ -35,7 +33,8 @@ self.players.append(id) def remove_player(self,id): - if self.voice.has_key(id): del self.voice[id] + if self.voice.has_key(id): + del self.voice[id] self.players.remove(id) def get_num_players(self): @@ -46,6 +45,7 @@ tmp = self.players return tmp + def check_pwd(self,pwd): return (pwd==self.pwd) @@ -61,10 +61,13 @@ w=max(len(minVersion[i]),len(version[i])) v1=minVersion[i].rjust(w); v2=version[i].rjust(w); - if v1v2: return 0 + if v1v2: + return 0 - if len(minVersion)>len(version): return 0 + if len(minVersion)>len(version): + return 0 return 1 #depreciated - see send_group_list() diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/networking/mplay_messaging.py --- a/orpg/networking/mplay_messaging.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/networking/mplay_messaging.py Sat Sep 19 06:50:43 2009 -0500 @@ -36,22 +36,22 @@ from xml.sax.saxutils import escape from struct import pack, unpack, calcsize from string import * -from orpg.orpg_version import VERSION, PROTOCOL_VERSION, CLIENT_STRING, SERVER_MIN_CLIENT_VERSION +from orpg.orpg_version import * import os import time -from orpg.tools.orpg_log import logger -from orpg.orpgCore import component +from orpg.orpgCore import * def myescape(data): return escape(data,{"\"":""}) class messenger: def __init__(self, *args, **kwargs): - #self.xml = component.get("xml") used once, no need for the object. - self.dir_struct = component.get("dir_struct") #used? - self.validate = component.get("validate") #used?? - #self.settings = component.get("settings") ## used once, no need for the object. + self.log = open_rpg.get_component("log") + self.xml = open_rpg.get_component("xml") + self.dir_struct = open_rpg.get_component("dir_struct") + self.validate = open_rpg.get_component("validate") + self.settings = open_rpg.get_component("settings") if kwargs.has_key('isServer'): self.isServer = kwargs['isServer'] else: @@ -64,7 +64,7 @@ self.exitEvent = Event() self.sendThreadExitEvent = Event() self.recvThreadExitEvent = Event() - self.port = int(component.get("settings").get_setting("port")) ##used even? + self.port = int(self.settings.get_setting("port")) self.ip = socket.gethostbyname(socket.gethostname()) self.lensize = calcsize('i') self.mplay_type = ('disconnected', 'connected', 'disconnecting', 'group change', 'group change failed') @@ -137,12 +137,12 @@ def disconnect(self): self.set_status(2) - logger.debug("client stub " + self.ip +" disconnecting...") - logger.debug("closing sockets...") + self.log.log("client stub " + self.ip +" disconnecting...", ORPG_DEBUG) + self.log.log("closing sockets...", ORPG_DEBUG) try: self.sock.shutdown( 2 ) except: - logger.general("Caught exception:\n" + traceback.format_exc()) + self.log.log("Caught exception:\n" + traceback.format_exc(), ORPG_GENERAL) self.set_status(0) def reset(self, sock): @@ -161,10 +161,10 @@ try: (self.name, self.ip, self.id, self.text_status, self.version, self.protocol_version, self.client_string,role) = player except: - logger.general("Exception: messenger->update_self_from_player():\n" + traceback.format_exc()) + self.log.log("Exception: messenger->update_self_from_player():\n" + traceback.format_exc(), ORPG_GENERAL) def toxml(self, act): - logger.exception("DEPRECIATED! messenger->toxml()") + self.log.log("DEPRECIATED! messenger->toxml()", ORPG_CRITICAL) xml_data = self.build_message('player', name=myescape(self.name), action=act, @@ -290,7 +290,7 @@ #Message Handaling def message_handler(self, arg): xml_dom = None - logger.note("message handler thread running...", ORPG_NOTE) + self.log.log("message handler thread running...", ORPG_NOTE) while self.alive or self.status == 'connected': data = None try: @@ -308,24 +308,24 @@ del data data = None except Exception, e: - logger.general(traceback.format_exc()) + self.log.log(traceback.format_exc(), ORPG_GENERAL) if xml_dom: xml_dom.unlink() if xml_dom: xml_dom.unlink() - logger.note("message handler thread exiting...") + self.log.log("message handler thread exiting...", ORPG_NOTE) self.inbox_event.set() def parse_incoming_dom(self, data): #print data xml_dom = None try: - xml_dom = component.get("xml").parseXml(data) + xml_dom = self.xml.parseXml(data) xml_dom = xml_dom._get_documentElement() self.message_action(xml_dom, data) except Exception, e: - logger.general("Error in parse of inbound message. Ignoring message.") - logger.general("\tOffending data(" + str(len(data)) + "bytes)=" + data) - logger.general("Exception=" + traceback.format_exc()) + self.log.log("Error in parse of inbound message. Ignoring message.", ORPG_GENERAL) + self.log.log("\tOffending data(" + str(len(data)) + "bytes)=" + data, ORPG_GENERAL) + self.log.log("Exception=" + traceback.format_exc(), ORPG_GENERAL) if xml_dom: xml_dom.unlink() def message_action(self, xml_dom, data): @@ -333,8 +333,8 @@ if self.msg_handlers.has_key(tag_name): self.msg_handlers[tag_name](xml_dom, data) else: - logger.general("Unknown Message Type") - logger.general(data) + self.log.log("Unknown Message Type", ORPG_GENERAL) + self.log.log(data, ORPG_GENERAL) #Message Action thread expires and closes here. return @@ -350,7 +350,7 @@ readMsg = self.outbox.get( block=1 ) except Exception, text: - logger.exception("Exception: messenger->sendThread(): " + str(text) + self.log.log("Exception: messenger->sendThread(): " + str(text), ORPG_CRITICAL) # If we are here, it's because we have data to send, no doubt! if self.status == 'connected': @@ -358,12 +358,12 @@ # Send the entire message, properly formated/encoded sent = self.sendMsg( self.sock, readMsg ) except: - logger.exception("Exception: messenger->sendThread():\n" + traceback.format_exc() + self.log.log("Exception: messenger->sendThread():\n" + traceback.format_exc(), ORPG_CRITICAL) else: # If we are not connected, purge the data queue - logger.note("Data queued without a connection, purging data from queue...") + self.log.log("Data queued without a connection, purging data from queue...", ORPG_NOTE) self.sendThreadExitEvent.set() - logger.note( "sendThread has terminated...") + self.log.log( "sendThread has terminated...", ORPG_NOTE) def sendMsg( self, sock, msg ): """Very simple function that will properly encode and send a message to te @@ -382,12 +382,12 @@ # Now, send the message the the length was describing sentm = sock.send( msg ) if self.isServer: - logger.debug("('data_sent', " + str(sentl+sentm) + ")") + self.log.log("('data_sent', " + str(sentl+sentm) + ")", ORPG_DEBUG) return sentm except socket.error, e: - logger.exception("Socket Error: messenger->sendMsg(): " + traceback.format_exc()) + self.log.log("Socket Error: messenger->sendMsg(): " + traceback.format_exc(), ORPG_CRITICAL) except: - logger.exception("Exception: messenger->sendMsg(): " + traceback.format_exc()) + self.log.log("Exception: messenger->sendMsg(): " + traceback.format_exc(), ORPG_CRITICAL) def recvThread( self, arg ): "Receiving thread. This thread reads from the socket and writes to the data queue." @@ -413,11 +413,11 @@ self.inbox.put( readMsg ) self.update_idle_time() #update the last message time if bytes == 0: - logger.note("Remote has disconnected!") + self.log.log("Remote has disconnected!", ORPG_NOTE) self.set_status(2) self.outbox.put( "" ) # Make sure the other thread is woken up! self.sendThreadExitEvent.set() - logger.note("messenger->recvThread() has terminated...") + self.log.log("messenger->recvThread() has terminated...", ORPG_NOTE) def recvData( self, sock, readSize ): """Simple socket receive method. This method will only return when the exact @@ -439,7 +439,7 @@ offset += rs data += frag except socket.error, e: - logger.exception("Socket Error: messenger->recvData(): " + str(e)) + self.log.log("Socket Error: messenger->recvData(): " + str(e), ORPG_CRITICAL) data = "" return data @@ -465,9 +465,9 @@ msgData = self.recvData( sock, length ) if self.isServer: - logger.debug("('data_recv', " + str(length+4) + ")") + self.log.log("('data_recv', " + str(length+4) + ")", ORPG_DEBUG) except: - logger.exception("Exception: messenger->recvMsg():\n" + traceback.format_exc()) + self.log.log("Exception: messenger->recvMsg():\n" + traceback.format_exc(), ORPG_CRITICAL) return msgData if __name__ == "__main__": diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/networking/mplay_server.py --- a/orpg/networking/mplay_server.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/networking/mplay_server.py Sat Sep 19 06:50:43 2009 -0500 @@ -43,30 +43,28 @@ """ -import re +from mplay_client import * +from mplay_client import MPLAY_LENSIZE +from orpg.dirpath import dir_struct +from orpg.tools.validate import validate import gc import cgi import sys import string import time import urllib -import traceback - -from mplay_client import * -from mplay_client import MPLAY_LENSIZE -from orpg.dirpath import dir_struct -import orpg.tools.validate - from orpg.mapper.map_msg import * from threading import Lock, RLock from struct import pack, unpack, calcsize from meta_server_lib import * +import traceback +import re # Import the minidom XML module from xml.dom import minidom # Snag the version number -from orpg.orpg_version import VERSION, PROTOCOL_VERSION, CLIENT_STRING, SERVER_MIN_CLIENT_VERSION +from orpg.orpg_version import * #Plugins from server_plugins import ServerPlugins @@ -112,6 +110,7 @@ f.write(self.game_map.get_all_xml()) f.close() + def add_player(self,id): self.players.append(id) @@ -128,6 +127,7 @@ tmp = self.players return tmp + def check_pwd(self,pwd): return (pwd==self.pwd) @@ -135,15 +135,19 @@ return (pwd==self.boot_pwd) def check_version(self,ver): - if (self.minVersion == ""): return 1 + if (self.minVersion == ""): + return 1 minVersion=self.minVersion.split('.') version=ver.split('.') for i in xrange(min(len(minVersion),len(version))): w=max(len(minVersion[i]),len(version[i])) v1=minVersion[i].rjust(w); v2=version[i].rjust(w); - if v1v2: return 0 + if v1v2: + return 0 + if len(minVersion)>len(version): return 0 return 1 @@ -159,6 +163,7 @@ return xml_data + class client_stub(client_base): def __init__(self,inbox,sock,props,log): client_base.__init__(self) @@ -184,11 +189,14 @@ self.timeout_time = None def check_time_out(self): - if self.timeout_time==None: self.timeout_time = time.time() + if self.timeout_time==None: + self.timeout_time = time.time() curtime = time.time() diff = curtime - self.timeout_time - if diff > 1800: return 1 - else: return 0 + if diff > 1800: + return 1 + else: + return 0 def send(self,msg,player,group): if self.get_status() == MPLAY_CONNECTED: @@ -211,7 +219,7 @@ self.name = xml_dom.getAttribute("name") self.text_status = xml_dom.getAttribute("status") -""" + ###################################################################### ###################################################################### ## @@ -221,7 +229,6 @@ ## ###################################################################### ###################################################################### -""" class mplay_server: def __init__(self, log_console=None, name=None): @@ -257,19 +264,18 @@ self.allowRemoteKill = False self.allowRemoteAdmin = True self.sendLobbySound = False - self.lobbySound = 'http://www.digitalxero.net/music/mus_tavern1.bmu' ##used? + self.lobbySound = 'http://www.digitalxero.net/music/mus_tavern1.bmu' def initServer(self, **kwargs): - for atter, value in kwargs.iteritems(): setattr(self, atter, value) + for atter, value in kwargs.iteritems(): + setattr(self, atter, value) validate.config_file( self.lobbyMapFile, "default_Lobby_map.xml" ) validate.config_file( self.lobbyMessageFile, "default_LobbyMessage.html" ) self.server_start_time = time.time() # Since the server is just starting here, we read in the XML configuration # file. Notice the lobby is still created here by default. - self.groups = { '0': game_group('0','Lobby','', - 'The game lobby', '', '', self.userPath + self.lobbyMapFile, - self.userPath + self.lobbyMessageFile, 1)} + self.groups = { '0': game_group('0','Lobby','','The game lobby', '', '', self.userPath + self.lobbyMapFile, self.userPath + self.lobbyMessageFile, 1)} # Make sure the server's name gets set, in case we are being started from # elsewhere. Basically, if it's passed in, we'll over ride what we were # prompted for. This should never really happen at any rate. @@ -307,6 +313,7 @@ self.addsvrcmd('plugin', self.plugin_msg_handler) self.addsvrcmd('sound', self.sound_msg_handler) + # This method reads in the server's ban list added by Darren def initBanList( self ): self.log_msg("Processing Ban List File...") @@ -375,7 +382,6 @@ if len(opt) and (opt[0].upper() == 'Y'): self.reg = 'Y' else: self.reg = 'N' LobbyName = 'Lobby' - if self.configDoc.hasAttribute("lobbyname"): LobbyName = self.configDoc.getAttribute("lobbyname") map_node = service_node = self.configDoc.getElementsByTagName("map")[0] msg_node = service_node = self.configDoc.getElementsByTagName("message")[0] @@ -384,7 +390,6 @@ if mapFile == '': mapFile = 'Lobby_map.xml' if msgFile == '': msgFile = 'LobbyMessage.html' # Update the lobby with the passwords if they've been specified - if len(self.boot_pwd): self.groups = {'0': game_group( '0', LobbyName, "", 'The game lobby', self.boot_pwd, "", self.userPath + mapFile.replace("myfiles/", ""), @@ -405,14 +410,12 @@ if self.reg[0].upper() == "Y": if self.name == None: self.name = raw_input("Server Name? ") self.register() - """ + # Get the minimum openrpg version from config if available # if it isn't set min version to internal default. # # server_ini.xml entry for version tag... # - """ - try: mver = self.configDoc.getElementsByTagName("version")[0] self.minClientVersion = mver.getAttribute("min") @@ -421,14 +424,13 @@ # This try/except bit is to allow older versions of python to continue without a list error. - """ + #------------------------[ START TAG PROCESSING ]-------------- # Auto-kick option defaults for silent booting and # setting the default zombie-client delay time --Snowdog 9/05 # # server_ini.xml entry for autikick tag... # - """ try: ak = self.configDoc.getElementsByTagName("autokick")[0] @@ -452,10 +454,10 @@ alk = "" if (self.silent_auto_kick == 1): alk = "(Silent Mode)" self.log_msg("Auto Kick: Delay="+str(self.zombie_time) + " " + alk) - """------------------------[ END TAG PROCESSING ]--------------""" - - - """ + #------------------------[ END TAG PROCESSING ]-------------- + + + #-------------------------------[ START TAG PROCESSING ]-------------------- # # New room_defaults configuration option used to set various defaults @@ -464,7 +466,6 @@ # # option syntax # - """ #default settings for tag options... roomdefault_msg = str(self.defaultMessageFile) #no message is the default @@ -491,7 +492,8 @@ if map != "": roomdefault_map = self.userPath + map.replace("myfiles/", "") self.log_msg("Room Defaults: Using " + str(map) + " for room map") - except: self.log_msg("Room Defaults: [Warning] Using Default Map") + except: + self.log_msg("Room Defaults: [Warning] Using Default Map") try: setting = roomdefaults.getElementsByTagName('message')[0] @@ -505,10 +507,12 @@ traceback.print_exc() self.log_msg("**WARNING** Error loading default room settings from configuration file. Using internal defaults.") + #set the defaults if roomdefault_msg != "" or roomdefault_msg != None: self.defaultMessageFile = roomdefault_msg # tag superceeds older tag else: self.defaultMessageFile = None + if roomdefault_map != "" or roomdefault_map != None: self.defaultMapFile = roomdefault_map # tag superceeds older tag else: self.defaultMapFile = None @@ -516,7 +520,9 @@ ##### room default map not handled yet. SETTING IGNORED if roomdefault_pass == 0: self.allow_room_passwords = 0 else: self.allow_room_passwords = 1 - """-------------------------------[ END TAG PROCESSING ]--------------------""" + + #-------------------------------[ END TAG PROCESSING ]-------------------- + ###Server Cheat message try: @@ -526,19 +532,27 @@ self.cheat_msg = "**FAKE ROLL**" self.log_msg("**WARNING** tag missing from server configuration file. Using empty string.") + + # should validate protocal validate_protocol_node = self.configDom.getElementsByTagName("validate_protocol ") + self.validate_protocol = 1 + if(validate_protocol_node): self.validate_protocol = (validate_protocol_node[0].getAttribute("value") == "True") if(self.validate_protocol != 1): self.log_msg("Protocol Validation: OFF") self.makePersistentRooms() + self.log_msg("Server Configuration File: Processing Completed.") + except Exception, e: traceback.print_exc() self.log_msg("Exception in initServerConfig() " + str(e)) + def makePersistentRooms(self): 'Creates rooms on the server as defined in the server config file.' + for element in self.configDom.getElementsByTagName('room'): roomName = element.getAttribute('name') roomPassword = element.getAttribute('password') @@ -552,28 +566,31 @@ # we only care about the first map element found -- others are ignored mapElement = element.getElementsByTagName('map')[0] mapFile = self.userPath + mapElement.getAttribute('file').replace("myfiles/", "") + messageElement = element.getElementsByTagName('message')[0] messageFile = messageElement.getAttribute('file') + if messageFile[:4] != 'http': messageFile = self.userPath + messageFile.replace("myfiles/", "") # Make sure we have a message to even mess with if(len(messageFile) == 0): messageFile = self.defaultMessageFile + if(len(mapFile) == 0): mapFile = self.defaultMapFile + moderated = 0 if element.hasAttribute('moderated') and element.getAttribute('moderated').lower() == "true": moderated = 1 #create the new persistant group - self.new_group(roomName, roomPassword, - bootPassword, minVersion, mapFile, - messageFile, persist = 1, moderated=moderated) + self.new_group(roomName, roomPassword, bootPassword, minVersion, mapFile, messageFile, persist = 1, moderated=moderated) + + def isPersistentRoom(self, id): 'Returns True if the id is a persistent room (other than the lobby), otherwise, False.' - """ + # altered persistance tracking from simple room id based to per-group setting # allows arbitrary rooms to be marked as persistant without needing the self.persistRoomThreshold # -- Snowdog 4/04 - """ try: id = str(id) #just in case someone sends an int instead of a str into the function if id not in self.groups: return 0 #invalid room, can't be persistant @@ -583,6 +600,8 @@ self.log_msg("Exception occured in isPersistentRoom(self,id)") return 0 + + #----------------------------------------------------- # Toggle Meta Logging -- Added by Snowdog 4/03 #----------------------------------------------------- @@ -613,13 +632,15 @@ for n in self.players: try: self.players[n].EnableMessageLogging = mode except: self.log_msg("Error changing Message Logging Mode for client #" + str(self.players[n].id)) - def NetworkLoggingStatus(self): if self.log_network_messages == 0: return "Network Traffic Log: Off" elif self.log_network_messages == 1: return "Network Traffic Log: Logging (composite file)" elif self.log_network_messages == 2: return "Network Traffic Log: Logging (inbound/outbound files)" else: self.log_msg("Network Traffic Log: [Unknown]") + + + 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 @@ -633,19 +654,17 @@ if newlist != curlist: # If the two lists aren't identical # then something has changed. - instance.register() # Call self.register() + instance.register() # Call self.register() # which will force a re-read of the meta cache and # redo the registerThreads else: instance.register() - # Eventually, reset the MetaServerBaseURL here - - """ + # Eventually, reset the MetaServerBaseURL here + ## Added to help clean up parser errors in the XML on clients ## due to characters that break welformedness of the XML from ## the meta server. ## NOTE: this is a stopgap measure -SD - """ def clean_published_servername(self, name): #clean name of all apostrophes and quotes badchars = "\"\\`><" @@ -659,8 +678,11 @@ 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,})+'&' + + for meta in self.metas.keys(): while id == '0': id, cookie = self.metas[meta].getIdAndCookie() @@ -668,9 +690,11 @@ "act":'registerrooms'}) get_server_dom(data+'&'+rooms, self.metas[meta].path) + 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) # Set up the value for num_users @@ -683,16 +707,14 @@ self.log_msg("Found these valid metas:") for meta in metalist: self.log_msg("Meta:" + meta) - """ # Go through the list and see if there is already a running register # thread for the meta. # If so, call it's register() method # If not, start one, implicitly calling the new thread's register() method + # 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 + ": ") @@ -706,43 +728,39 @@ # 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(): - self.metas[meta].register(name=name, - realHostName=self.server_address, - num_users=num_players) + self.metas[meta].register(name=name, realHostName=self.server_address, num_users=num_players) else: - self.metas[meta] = registerThread(name=name, realHostName=self.server_address, - num_users=num_players, MetaPath=meta, port=self.server_port, - register_callback=self.register_callback) + self.metas[meta] = registerThread(name=name, realHostName=self.server_address, num_users=num_players, MetaPath=meta, port=self.server_port,register_callback=self.register_callback) self.metas[meta].start() #The register Rooms thread + self.be_registered = 1 thread.start_new_thread(self.registerRooms,(0,)) + + def unregister(self): - """ # loop through all existing meta entries # Don't rely on getMetaServers(), as a server may have been # removed since it was started. In that case, then the meta # would never get unregistered. # # Instead, loop through all existing meta threads and unregister them - """ for meta in self.metas.values(): if meta and meta.isAlive(): meta.unregister() self.be_registered = 0 - """ # This method runs as it's own thread and does the group_member_check every # sixty seconds. This should eliminate zombies that linger when no one is # around to spook them. GC: Frequency has been reduced as I question how valid # the implementation is as it will only catch a very small segment of lingering # connections. - """ def player_reaper_thread_func(self,arg): while self.alive: time.sleep(60) + self.p_lock.acquire() for group in self.groups.keys(): self.check_group_members(group) self.p_lock.release() @@ -752,6 +770,7 @@ while self.alive: self.p_lock.acquire() players = ServerPlugins.getPlayer() + for player in players: if player is not None: pass #Do something here so they can show up in the chat room for non web users' data = ServerPlugins.preParseOutgoing() @@ -759,22 +778,28 @@ try: xml_dom = parseXml(msg) xml_dom = xml_dom._get_documentElement() + if xml_dom.hasAttribute('from') and int(xml_dom.getAttribute('from')) > -1: xml_dom.setAttribute('from', '-1') + xml_dom.setAttribute('to', 'all') self.incoming_msg_handler(xml_dom, msg) xml_dom.unlink() except: pass + self.p_lock.release() time.sleep(0.250) + def sendMsg( self, sock, msg, useCompression=False, cmpType=None): """Very simple function that will properly encode and send a message to te remote on the specified socket.""" + if useCompression and cmpType != None: mpacket = cmpType.compress(msg) lpacket = pack('!i', len(mpacket)) sock.send(lpacket) + offset = 0 while offset < len(mpacket): slice = buffer(mpacket, offset, len(mpacket)-offset) @@ -795,6 +820,7 @@ """Simple socket receive method. This method will only return when the exact byte count has been read from the connection, if remote terminates our connection or we get some other socket exception.""" + data = "" offset = 0 try: @@ -807,6 +833,7 @@ else: # Continue to build complete message offset += rs data += frag + except socket.error, e: self.log_msg("Socket Error: recvData(): " + e ) data = "" @@ -825,14 +852,18 @@ msgData = "" try: lenData = self.recvData( sock, MPLAY_LENSIZE ) - (length,) = unpack('!i', lenData) # Now, convert to a usable form - msgData = self.recvData( sock, length ) # Read exactly the remaining amount of data + # Now, convert to a usable form + (length,) = unpack('!i', lenData) + # Read exactly the remaining amount of data + msgData = self.recvData( sock, length ) try: if useCompression and cmpType != None: msgData = cmpType.decompress(msgData) except: traceback.print_exc() + except Exception, e: self.log_msg( "Exception: recvMsg(): " + str(e) ) return msgData + def kill_server(self): self.alive = 0 self.log_msg("Server stopping...") @@ -840,8 +871,10 @@ for p in self.players.itervalues(): p.disconnect() self.incoming.put("") + for g in self.groups.itervalues(): g.save_map() + try: ip = socket.gethostbyname(socket.gethostname()) kill = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -858,10 +891,15 @@ self.incoming_event.wait(10) self.log_msg("Server stopped!") + + def log_msg(self,msg): if self.log_to_console: - if self.log_console: self.log_console(msg) - else: print str(msg) + if self.log_console: + self.log_console(msg) + else: + print str(msg) + def print_help(self): print @@ -898,9 +936,11 @@ print "'help' or '?' or 'h' - for this help message" print + def broadcast(self,msg): self.send_to_all("0","" + msg + "") + def console_log(self): if self.log_to_console == 1: print "console logging now off" @@ -909,6 +949,7 @@ print "console logging now on" self.log_to_console = 1 + def groups_list(self): self.p_lock.acquire() try: @@ -916,23 +957,26 @@ for k in keys: pw = "-" pr = " -" - if self.groups[k].pwd != "": pw = "P" - if self.isPersistentRoom( k ): pr = " S" #using S for static (P for persistant conflicts with password) + if self.groups[k].pwd != "": + pw = "P" + if self.isPersistentRoom( k ): + pr = " S" #using S for static (P for persistant conflicts with password) print "Group: " + k + pr + pw + ' Name: ' + self.groups[k].name print + except Exception, e: self.log_msg(str(e)) + self.p_lock.release() - """ - #---------------------------------------------------------------- - # Monitor Function -- Added by snowdog 2/05 - #---------------------------------------------------------------- - """ +#---------------------------------------------------------------- +# Monitor Function -- Added by snowdog 2/05 +#---------------------------------------------------------------- def monitor(self, pid, mode=1 ): "allows monitoring of a specific user(s) network i/o" #if mode is not set to 1 then monitor adds toggles the state #of monitoring on the given user + if (mode == 1): for p in self.players: try: p.monitor("off") @@ -944,29 +988,44 @@ self.log_msg("Monitor: Invalid Player ID") traceback.print_exc() + def search(self,patern): keys = self.groups.keys() print "Search results:" for k in keys: ids = self.groups[k].get_player_ids() for id in ids: - if self.players[id].id.find(patern)>-1: self.print_player_info(self.players[id]) - elif self.players[id].name.find(patern)>-1: self.print_player_info(self.players[id]) - elif self.players[id].ip.find(patern)>-1: self.print_player_info(self.players[id]) - elif self.players[id].group_id.find(patern)>-1: self.print_player_info(self.players[id]) - elif self.players[id].role.find(patern)>-1: self.print_player_info(self.players[id]) - elif self.players[id].version.find(patern)>-1: self.print_player_info(self.players[id]) - elif self.players[id].protocol_version.find(patern)>-1: self.print_player_info(self.players[id]) - elif self.players[id].client_string.find(patern)>-1: self.print_player_info(self.players[id]) + if self.players[id].id.find(patern)>-1: + self.print_player_info(self.players[id]) + + elif self.players[id].name.find(patern)>-1: + self.print_player_info(self.players[id]) + + elif self.players[id].ip.find(patern)>-1: + self.print_player_info(self.players[id]) + + elif self.players[id].group_id.find(patern)>-1: + self.print_player_info(self.players[id]) + + elif self.players[id].role.find(patern)>-1: + self.print_player_info(self.players[id]) + + elif self.players[id].version.find(patern)>-1: + self.print_player_info(self.players[id]) + + elif self.players[id].protocol_version.find(patern)>-1: + self.print_player_info(self.players[id]) + + elif self.players[id].client_string.find(patern)>-1: + self.print_player_info(self.players[id]) + def print_player_info(self,player): - print player.id, player.name, player.ip, player.group_id, player.role, player.version, player.protocol_version, player.client_string - - """ + print player.id,player.name,player.ip,player.group_id, player.role,player.version,player.protocol_version,player.client_string + #---------------------------------------------------------------- # Uptime Function -- Added by snowdog 4/03 #---------------------------------------------------------------- - """ def uptime(self , mode = 0): "returns string containing how long server has been in operation" ut = time.time() - self.server_start_time @@ -978,11 +1037,9 @@ if mode == 0: print uts else: return uts - """ #----------------------------------------------------- # Toggle Room Password Allow -- Added by Snowdog 11/03 #----------------------------------------------------- - """ def RoomPasswords(self): if self.allow_room_passwords != 0: self.allow_room_passwords = 0 @@ -991,6 +1048,7 @@ self.allow_room_passwords = 1 return "Client Created Room Passwords: Allowed" + def group_dump(self,k): self.p_lock.acquire() try: @@ -1006,11 +1064,9 @@ self.log_msg(str(e)) self.p_lock.release() - """ #---------------------------------------------------------------- # Player List -- Added by snowdog 4/03 #---------------------------------------------------------------- - """ def player_list(self): "display a condensed list of players on the server" self.p_lock.acquire() @@ -1045,46 +1101,56 @@ keys = self.groups.keys() for k in keys: print "Group: %s %s (pass: \"%s\")" % (str(k),self.groups[k].name, self.groups[k].pwd) + ids = self.groups[k].get_player_ids() for id in ids: - if self.players.has_key(id): print str(self.players[id]) + if self.players.has_key(id): + print str(self.players[id]) else: self.groups[k].remove_player(id) print "Bad Player Ref (#" + id + ") in group" except Exception, e: self.log_msg(str(e)) + self.p_lock.release() + def update_request(self,newsock,xml_dom): # handle reconnects + self.log_msg( "update_request() has been called." ) # get player id id = xml_dom.getAttribute("id") group_id = xml_dom.getAttribute("group_id") + self.p_lock.acquire() if self.players.has_key(id): - self.sendMsg(newsock, self.players[id].toxml("update"), - self.players[id].useCompression, - self.players[id].compressionType ) + self.sendMsg( newsock, self.players[id].toxml("update"), self.players[id].useCompression, self.players[id].compressionType ) self.players[id].reset(newsock) self.players[id].clear_timeout() need_new = 0 - else: need_new = 1 + else: + need_new = 1 self.p_lock.release() - if need_new: self.new_request(newsock,xml_dom) + + if need_new: + self.new_request(newsock,xml_dom) else: msg = self.groups[group_id].game_map.get_all_xml() self.send(msg,id,group_id) + def new_request(self,newsock,xml_dom,LOBBY_ID='0'): #build client stub props = {} # Don't trust what the client tells us...trust what they connected as! props['ip'] = socket.gethostbyname( newsock.getpeername()[0] ) - try: props['role'] = xml_dom.getAttribute("role") - except: props['role'] = "GM" + try: + props['role'] = xml_dom.getAttribute("role") + except: + props['role'] = "GM" props['name'] = xml_dom.getAttribute("name") props['group_id'] = LOBBY_ID @@ -1092,21 +1158,28 @@ props['version'] = xml_dom.getAttribute("version") props['protocol_version'] = xml_dom.getAttribute("protocol_version") props['client_string'] = xml_dom.getAttribute("client_string") - self.next_player_id += 1 new_stub = client_stub(self.incoming,newsock,props,self.log_console) if xml_dom.hasAttribute('useCompression'): new_stub.useCompression = True + if xml_dom.hasAttribute('cmpType'): cmpType = xml_dom.getAttribute('cmpType') - if cmpBZ2 and cmpType == 'bz2': new_stub.compressionType = bz2 - elif cmpZLIB and cmpType == 'zlib': new_stub.compressionType = zlib - else: new_stub.compressionType = None - else: new_stub.compressionType = bz2 - else: new_stub.useCompression = False + if cmpBZ2 and cmpType == 'bz2': + new_stub.compressionType = bz2 + elif cmpZLIB and cmpType == 'zlib': + new_stub.compressionType = zlib + else: + new_stub.compressionType = None + else: + new_stub.compressionType = bz2 + + else: + new_stub.useCompression = False #update newly create client stub with network logging state new_stub.EnableMessageLogging = self.log_network_messages + self.sendMsg(newsock, new_stub.toxml("new"), False, None) # try to remove circular refs @@ -1132,10 +1205,13 @@ print "Error in parse found from " + str(remote_host) + ". Disconnected." print " Offending data(" + str(len(data)) + "bytes)=" + data print "Exception=" + str(e) - if xml_dom: xml_dom.unlink() + + if xml_dom: + xml_dom.unlink() return #start threads and store player + allowed = 1 version_string = "" @@ -1145,16 +1221,12 @@ if not self.checkClientVersion(props['version']): version_string = "Sorry, your client is out of date.
" - version_string += "This server requires your client be version " - version_string += "" + self.minClientVersion + " or higher to connect.
" + version_string += "This server requires your client be version " + self.minClientVersion + " or higher to connect.
" allowed = 0 if not allowed: - version_string += " Please go to " - version_string += "http://www.assembla.com/traipse to find a compatible client.
" - version_string += "If you can't find a compatible client on the website, " - version_string += "chances are that the server is running an unreleased development " - version_string += "version for testing purposes.
" + version_string += ' Please go to http://openrpg.digitalxero.net to find a compatible client.
' + version_string += "If you can't find a compatible client on the website, chances are that the server is running an unreleased development version for testing purposes.
" self.sendMsg( newsock, "" + version_string, new_stub.useCompression, new_stub.compressionType) # Give messages time to flow @@ -1171,6 +1243,7 @@ cmsg = "Banned Client: (" + str(props['id']) + ") " + str(props['name']) + " [" + str(props['ip']) + "]" self.log_msg(cmsg) allowed = 0 + self.sendMsg( newsock, "" + banmsg, new_stub.useCompression, new_stub.compressionType) # Give messages time to flow time.sleep(1) @@ -1179,7 +1252,6 @@ xml_dom.unlink() return None - """ #---- Connection order changed by Snowdog 1/05 #---- Attempt to register player and send group data #---- before displaying lobby message @@ -1191,7 +1263,6 @@ #---- to clients. Not sure why the group messages were being sent to the #---- incomming message queue, when they should be sent directly to user #---- Does not solve the black hole bug totally -SD - """ try: if xml_dom.getAttribute("id") == props['id']: @@ -1202,6 +1273,7 @@ self.send_group_list(props['id']) self.send_player_list(props['id'],LOBBY_ID) self.p_lock.release() + msg = self.groups[LOBBY_ID].game_map.get_all_xml() self.send(msg,props['id'],LOBBY_ID) self.send_to_group(props['id'],LOBBY_ID,self.players[props['id']].toxml('new')) @@ -1209,6 +1281,7 @@ # Re-initialize the role for this player incase they came from a different server self.handle_role("set",props['id'], "GM",self.groups[LOBBY_ID].boot_pwd, LOBBY_ID) + cmsg = "Client Connect: (" + str(props['id']) + ") " + str(props['name']) + " [" + str(props['ip']) + "]" self.log_msg(cmsg) cmsg = ("connect", props) ################################################# @@ -1231,11 +1304,14 @@ time.sleep(2) newsock.close() + # Display the lobby message self.SendLobbyMessage(newsock,props['id']) + if xml_dom: xml_dom.unlink() + def checkClientVersion(self, clientversion): minv = self.minClientVersion.split('.') cver = clientversion.split('.') @@ -1243,47 +1319,53 @@ w=max(len(minv[i]),len(cver[i])) v1=minv[i].rjust(w); v2=cver[i].rjust(w); - if v1v2: return 0 - if len(minv)>len(cver): return 0 + if v1v2: + return 0 + + if len(minv)>len(cver): + return 0 return 1 + + def SendLobbyMessage(self, socket, player_id): - """ + ####################################################################### # Display the lobby message # prepend this server's version string to the the lobby message - """ try: - lobbyMsg = "You have connected to an OpenRPG " - lobbyMsg += "server, version '" + VERSION + "'" + lobbyMsg = "You have connected to an OpenRPG server, version '" + VERSION + "'" # See if we have a server name to report! + if len(self.serverName): lobbyMsg += ", named '" + self.serverName + "'." + else: lobbyMsg += "." # Add extra line spacing lobbyMsg += "\n\n" - try: validate.config_file("LobbyMessage.html","default_LobbyMessage.html") - except: pass + try: + validate.config_file("LobbyMessage.html","default_LobbyMessage.html") + except: + pass else: open_msg = open( self.userPath + "LobbyMessage.html", "r" ) lobbyMsg += open_msg.read() open_msg.close() # Send the server's lobby message to the client no matter what - self.sendMsg(socket, "" + lobbyMsg, - self.players[player_id].useCompression, self.players[player_id].compressionType) + self.sendMsg(socket, "" + lobbyMsg, self.players[player_id].useCompression, self.players[player_id].compressionType) if self.sendLobbySound: - self.sendMsg(socket, '', - self.players[player_id].useCompression, self.players[player_id].compressionType) + self.sendMsg(socket, '', self.players[player_id].useCompression, self.players[player_id].compressionType) return - except: traceback.print_exc() - """ + except: + traceback.print_exc() # End of lobby message code - """ + ####################################################################### def listenAcceptThread(self,arg): @@ -1291,7 +1373,8 @@ try: self.log_msg("\nlisten thread running...") adder = "" - if self.server_address is not None: adder = self.server_address + if self.server_address is not None: + adder = self.server_address self.listen_sock.bind(('', self.server_port)) self.listen_sock.listen(5) @@ -1299,18 +1382,18 @@ self.log_msg(("Error binding request socket!", e)) self.alive = 0 + while self.alive: + # Block on the socket waiting for a new connection try: (newsock, addr) = self.listen_sock.accept() - """ ## self.log_msg("New connection from " + str(addr)+ ". Interfacing with server...") # Now that we've accepted a new connection, we must immediately spawn a new # thread to handle it...otherwise we run the risk of having a DoS shoved into # our face! :O After words, this thread is dead ready for another connection # accept to come in. - """ thread.start_new_thread(self.acceptedNewConnectionThread, ( newsock, addr )) except: @@ -1321,8 +1404,11 @@ self.log_msg("server socket listening thread exiting...") self.listen_event.set() + + def acceptedNewConnectionThread( self, newsock, addr ): """Once a new connection comes in and is accepted, this thread starts up to handle it.""" + # Initialize xml_dom xml_dom = None data = None @@ -1330,36 +1416,51 @@ # get client info and send othe client info # If this receive fails, this thread should exit without even attempting to process it self.log_msg("Connection from " + str(addr) + " has been accepted. Waiting for data...") + data = self.recvMsg( newsock ) + if data=="" or data == None: self.log_msg("Connection from " + str(addr) + " failed. Closing connection.") - try: newsock.close() + try: + newsock.close() except Exception, e: self.log_msg( str(e) ) print str(e) return #returning causes connection thread instance to terminate + + if data == "": - try: newsock.close() - except: pass + try: + newsock.close() + except: + pass return #returning causes connection thread instance to terminate + # Clear out the xml_dom in preparation for new stuff, if necessary try: - if xml_dom: xml_dom.unlink() + if xml_dom: + xml_dom.unlink() except: self.log_msg( "The following exception caught unlinking xml_dom:") self.log_msg("Continuing") - try: newsock.close() - except: pass + + try: + newsock.close() + except: + pass return #returning causes connection thread instance to terminate + # Parse the XML received from the connecting client try: xml_dom = parseXml(data) xml_dom = xml_dom._get_documentElement() except: - try: newsock.close() - except: pass + try: + newsock.close() + except: + pass self.log_msg( "Error in parse found from " + str(addr) + ". Disconnected.") self.log_msg(" Offending data(" + str(len(data)) + "bytes)=" + data) self.log_msg( "Exception:") @@ -1372,9 +1473,14 @@ action = xml_dom.getAttribute("action") # Figure out what type of connection we have going on now - if action == "new": self.new_request(newsock,xml_dom) - elif action == "update": self.update_request(newsock,xml_dom) - else: self.log_msg("Unknown Join Request!") + if action == "new": + self.new_request(newsock,xml_dom) + + elif action == "update": + self.update_request(newsock,xml_dom) + + else: + self.log_msg("Unknown Join Request!") except Exception, e: print "The following message: " + str(data) @@ -1384,13 +1490,15 @@ # Again attempt to clean out DOM stuff try: - if xml_dom: xml_dom.unlink() + if xml_dom: + xml_dom.unlink() except: print "The following exception caught unlinking xml_dom:" traceback.print_exc() return #returning causes connection thread instance to terminate - """ + + #======================================================== # # Message_handler @@ -1400,20 +1508,21 @@ # Changed thread organization from one continuous parsing/handling thread # to multiple expiring parsing/handling threads to improve server performance # and player load capacity -- Snowdog 3/04 - """ def message_handler(self,arg): xml_dom = None self.log_msg( "message handler thread running..." ) while self.alive: data = None - try: data=self.incoming.get(0) + try: + data=self.incoming.get(0) except Queue.Empty: time.sleep(0.5) #sleep 1/2 second continue bytes = len(data) - if bytes <= 0: continue + if bytes <= 0: + continue try: thread.start_new_thread(self.parse_incoming_dom,(str(data),)) #data has been passed... unlink from the variable references @@ -1441,15 +1550,20 @@ print "Error in parse of inbound message. Ignoring message." print " Offending data(" + str(len(data)) + "bytes)=" + data print "Exception=" + str(e) + if xml_dom: xml_dom.unlink() + def message_action(self, xml_dom, data): tag_name = xml_dom._get_tagName() - if self.svrcmds.has_key(tag_name): self.svrcmds[tag_name]['function'](xml_dom,data) - else: raise Exception, "Not a valid header!" + if self.svrcmds.has_key(tag_name): + self.svrcmds[tag_name]['function'](xml_dom,data) + else: + raise Exception, "Not a valid header!" #Message Action thread expires and closes here. return + def do_alter(self, xml_dom, data): target = xml_dom.getAttribute("key") value = xml_dom.getAttribute("val") @@ -1459,15 +1573,14 @@ actual_boot_pwd = self.groups[group_id].boot_pwd if self.allow_room_passwords == 0: - msg =" " - msg += "Room passwords have been disabled by the server administrator." + msg =" Room passwords have been disabled by the server administrator." self.players[player].outbox.put(msg) return elif boot_pwd == actual_boot_pwd: if target == "pwd": - lmessage = "Room password changed to from " + self.groups[group_id].pwd + " to " + value + " by " + player + lmessage = "Room password changed to from \"" + self.groups[group_id].pwd + "\" to \"" + value + "\" by " + player self.groups[group_id].pwd = value - msg =" Room password changed to " + value + "." + msg =" Room password changed to \"" + value + "\"." self.players[player].outbox.put(msg) self.log_msg(lmessage) self.send_to_all('0',self.groups[group_id].toxml('update')) @@ -1481,6 +1594,7 @@ msg ="Invalid Administrator Password." self.players[player].outbox.put(msg) + def do_role(self, xml_dom, data): role = "" boot_pwd = "" @@ -1500,12 +1614,17 @@ group_id = xml_dom.getAttribute("group_id") sent_time = "" msg = "" - try: sent_time = xml_dom.getAttribute("time") - except: pass - if sent_time != "": msg ="" #because a time was sent return a ping response + try: + sent_time = xml_dom.getAttribute("time") + except: + pass + + if sent_time != "": + #because a time was sent return a ping response + msg ="" else: - msg ="" - msg += "PONG!?!" + msg ="PONG!?!" + self.players[player].outbox.put(msg) xml_dom.unlink() @@ -1516,43 +1635,65 @@ try: action = xml_dom.getAttribute("action") from_id = xml_dom.getAttribute("from") - if xml_dom.hasAttribute("pwd"): pwd=xml_dom.getAttribute("pwd") - else: pwd="" + if xml_dom.hasAttribute("pwd"): + pwd=xml_dom.getAttribute("pwd") + else: + pwd="" group_id=self.players[from_id].group_id + if action == "list": if (self.groups[group_id].moderated): msg = "" for i in self.groups[group_id].voice.keys(): - if msg != "": msg +=", " - if self.players.has_key(i): msg += '('+i+') '+self.players[i].name - else: del self.groups[group_id].voice[i] - if (msg != ""): msg = "The following users may speak in this room: " + msg - else: msg = "No people are currently in this room with the ability to chat" + if msg != "": + msg +=", " + if self.players.has_key(i): + msg += '('+i+') '+self.players[i].name + else: + del self.groups[group_id].voice[i] + if (msg != ""): + msg = "The following users may speak in this room: " + msg + else: + msg = "No people are currently in this room with the ability to chat" self.players[from_id].self_message(msg) - else: self.players[from_id].self_message("This room is currently unmoderated") - elif action == 'enable' or 'disable' or 'addvoice' or 'delvoice': - #condenses password check --TaS 2009 + else: + self.players[from_id].self_message("This room is currently unmoderated") + elif action == "enable": + if not self.groups[group_id].check_boot_pwd(pwd): + self.players[from_id].self_message("Failed - incorrect admin password") + return + self.groups[group_id].moderated = 1 + self.players[from_id].self_message("This channel is now moderated") + elif action == "disable": if not self.groups[group_id].check_boot_pwd(pwd): self.players[from_id].self_message("Failed - incorrect admin password") return - if action == 'enable': - self.groups[group_id].moderated = 1 - self.players[from_id].self_message("This channel is now moderated") - if action == 'disable': - self.groups[group_id].moderated = 0 - self.players[from_id].self_message("This channel is now unmoderated") - if action == 'addvoice': - users = xml_dom.getAttribute("users").split(',') - for i in users: self.groups[group_id].voice[i.strip()]=1 - if action == 'delvoice': - users = xml_dom.getAttribute("users").split(',') - for i in users: - if self.groups[group_id].voice.has_key(i.strip()): del self.groups[group_id].voice[i.strip()] + self.groups[group_id].moderated = 0 + self.players[from_id].self_message("This channel is now unmoderated") + elif action == "addvoice": + if not self.groups[group_id].check_boot_pwd(pwd): + self.players[from_id].self_message("Failed - incorrect admin password") + return + users = xml_dom.getAttribute("users").split(',') + for i in users: + self.groups[group_id].voice[i.strip()]=1 + elif action == "delvoice": + if not self.groups[group_id].check_boot_pwd(pwd): + self.players[from_id].self_message("Failed - incorrect admin password") + return + users = xml_dom.getAttribute("users").split(',') + for i in users: + if self.groups[group_id].voice.has_key(i.strip()): + del self.groups[group_id].voice[i.strip()] else: print "Bad input: " + data + except Exception,e: self.log_msg(str(e)) + + + def join_group(self,xml_dom,data): try: from_id = xml_dom.getAttribute("from") @@ -1571,6 +1712,7 @@ #tell the clients password manager the password failed -- SD 8/03 pm = "" self.players[from_id].outbox.put(pm) + msg = 'failed - incorrect room password' if not allowed: @@ -1584,16 +1726,19 @@ #move the player into their new group. self.move_player(from_id, group_id) + except Exception, e: self.log_msg(str(e)) - """ + + + + #---------------------------------------------------------------------------- # move_player function -- added by Snowdog 4/03 # # Split join_group function in half. separating the player validation checks # from the actual group changing code. Done primarily to impliment # boot-from-room-to-lobby behavior in the server. - """ def move_player(self, from_id, group_id ): "move a player from one group to another" @@ -1612,20 +1757,19 @@ self.send_to_group(from_id,group_id,self.players[from_id].toxml('new')) self.check_group(from_id, old_group_id) - """ # Here, if we have a group specific lobby message to send, push it on # out the door! Make it put the message then announce the player...just # like in the lobby during a new connection. # -- only do this check if the room id is within range of known persistent id thresholds #also goes ahead if there is a defaultRoomMessage --akoman - """ if self.isPersistentRoom(group_id) or self.defaultMessageFile != None: try: if self.groups[group_id].messageFile[:4] == 'http': data = urllib.urlretrieve(self.groups[group_id].messageFile) roomMsgFile = open(data[0]) - else: roomMsgFile = open(self.groups[group_id].messageFile, "r") + else: + roomMsgFile = open(self.groups[group_id].messageFile, "r") roomMsg = roomMsgFile.read() roomMsgFile.close() urllib.urlcleanup() @@ -1636,18 +1780,24 @@ # Spit that darn message out now! self.players[from_id].outbox.put("" + roomMsg) + if self.sendLobbySound and group_id == '0': self.players[from_id].outbox.put('') + # Now, tell everyone that we've arrived self.send_to_all('0', self.groups[group_id].toxml('update')) + # this line sends a handle role message to change the players role self.send_player_list(from_id,group_id) + #notify user about others in the room self.return_room_roles(from_id,group_id) self.log_msg(("join_group", (self.groups[group_id].name, group_id, from_id))) self.handle_role("set", from_id, self.players[from_id].role, self.groups[group_id].boot_pwd, group_id) + except Exception, e: self.log_msg(str(e)) + thread.start_new_thread(self.registerRooms,(0,)) def return_room_roles(self,from_id,group_id): @@ -1656,13 +1806,12 @@ msg = "" self.players[from_id].outbox.put(msg) - """ + # This is pretty much the same thing as the create_group method, however, # it's much more generic whereas the create_group method is tied to a specific # xml message. Ack! This version simply creates the groups, it does not # send them to players. Also note, both these methods have race # conditions written all over them. Ack! Ack! - """ def new_group( self, name, pwd, boot, minVersion, mapFile, messageFile, persist = 0, moderated=0 ): group_id = str( self.next_group_id ) self.next_group_id += 1 @@ -1674,6 +1823,7 @@ self.log_msg( lmsg ) self.log_msg(("create_group", (str(name), int(group_id), 0) )) ##-99 works, could be better. + def change_group_name(self,gid,name,pid): "Change the name of a group" # Check for & in name. We want to allow this because of its common @@ -1688,6 +1838,7 @@ e = name[loc+1:] value = b + "&" + e oldloc = loc+1 + loc = name.find("'") oldloc = 0 while loc > -1: @@ -1697,6 +1848,7 @@ e = name[loc+1:] name = b + "'" + e oldloc = loc+1 + loc = name.find('"') oldloc = 0 while loc > -1: @@ -1706,15 +1858,20 @@ e = name[loc+1:] name = b + """ + e oldloc = loc+1 + oldroomname = self.groups[gid].name self.groups[gid].name = str(name) lmessage = "Room name changed to from \"" + oldroomname + "\" to \"" + name + "\"" self.log_msg(lmessage + " by " + str(pid) ) self.send_to_all('0',self.groups[gid].toxml('update')) return lmessage - except: return "An error occured during rename of room!" + except: + return "An error occured during rename of room!" + thread.start_new_thread(self.registerRooms,(0,)) + + def create_group(self,xml_dom,data): try: from_id = xml_dom.getAttribute("from") @@ -1728,6 +1885,8 @@ # see if passwords are allowed on this server and null password if not if self.allow_room_passwords != 1: pwd = "" + + # # Check for & in name. We want to allow this because of its common # use in d&d games. @@ -1740,6 +1899,7 @@ e = name[loc+1:] name = b + "&" + e oldloc = loc+1 + loc = name.find("'") oldloc = 0 while loc > -1: @@ -1749,6 +1909,7 @@ e = name[loc+1:] name = b + "'" + e oldloc = loc+1 + loc = name.find('"') oldloc = 0 while loc > -1: @@ -1758,6 +1919,8 @@ e = name[loc+1:] name = b + """ + e oldloc = loc+1 + + group_id = str(self.next_group_id) self.next_group_id += 1 self.groups[group_id] = game_group(group_id,name,pwd,"",boot_pwd, minVersion, None, messageFile ) @@ -1781,14 +1944,20 @@ data = urllib.urlretrieve(self.defaultMessageFile) open_msg = open(data[0]) urllib.urlcleanup() - else: open_msg = open( self.defaultMessageFile, "r" ) + else: + open_msg = open( self.defaultMessageFile, "r" ) + roomMsg = open_msg.read() open_msg.close() # Send the rooms message to the client no matter what self.players[from_id].outbox.put( "" + roomMsg ) - except Exception, e: self.log_msg( "Exception: create_group(): " + str(e)) + + except Exception, e: + self.log_msg( "Exception: create_group(): " + str(e)) + thread.start_new_thread(self.registerRooms,(0,)) + def check_group(self, from_id, group_id): try: if group_id not in self.groups: return @@ -1799,12 +1968,15 @@ self.send_to_all("0",self.groups[group_id].toxml('del')) del self.groups[group_id] self.log_msg(("delete_group", (group_id, from_id))) - else: self.send_to_all("0",self.groups[group_id].toxml('update')) + + else: + self.send_to_all("0",self.groups[group_id].toxml('update')) #The register Rooms thread thread.start_new_thread(self.registerRooms,(0,)) - except Exception, e: self.log_msg(str(e)) + except Exception, e: + self.log_msg(str(e)) def del_player(self,id,group_id): try: @@ -1814,17 +1986,23 @@ 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() - except Exception, e: self.log_msg(str(e)) + + + except Exception, e: + self.log_msg(str(e)) + self.log_msg("Explicit garbage collection shows %s undeletable items." % str(gc.collect())) + + def incoming_player_handler(self,xml_dom,data): id = xml_dom.getAttribute("id") act = xml_dom.getAttribute("action") @@ -1832,13 +2010,16 @@ group_id = self.players[id].group_id ip = self.players[id].ip self.log_msg("Player with IP: " + str(ip) + " joined.") + ServerPlugins.setPlayer(self.players[id]) + self.send_to_group(id,group_id,data) if act=="new": try: self.send_player_list(id,group_id) self.send_group_list(id) - except Exception, e: traceback.print_exc() + except Exception, e: + traceback.print_exc() elif act=="del": #print "del player" self.del_player(id,group_id) @@ -1857,26 +2038,31 @@ "ping": xml_dom.getAttribute("time") \ })) + def strip_cheat_roll(self, string): try: cheat_regex = re.compile('&#91;(.*?)&#93;') string = cheat_regex.sub( r'[ ' + self.cheat_msg + " \\1 " + self.cheat_msg + ' ]', string) - except: pass + except: + pass return string def strip_body_tags(self, string): try: bodytag_regex = re.compile('<\/?body(.*?)>') string = bodytag_regex.sub('', string) - except: pass + except: + pass return string def msgTooLong(self, length): - if length > self.maxSendSize and not self.maxSendSize == 0: return True + if length > self.maxSendSize and not self.maxSendSize == 0: + return True return False def incoming_msg_handler(self,xml_dom,data): xml_dom, data = ServerPlugins.preParseIncoming(xml_dom, data) + to_id = xml_dom.getAttribute("to") from_id = xml_dom.getAttribute("from") group_id = xml_dom.getAttribute("group_id") @@ -1887,10 +2073,15 @@ print "WARNING!! Message received with an invalid from_id. Message dropped." return None - """ check for < body to prevent someone from changing the background""" + # + # check for < body to prevent someone from changing the background + # + data = self.strip_body_tags(data) - """check for [ and ] codes which are often used to cheat with dice.""" + # + # check for [ and ] codes which are often used to cheat with dice. + # if self.players[from_id].role != "GM": data = self.strip_cheat_roll(data) @@ -1918,15 +2109,19 @@ if to_id == 'all': if self.groups[group_id].moderated and not self.groups[group_id].voice.has_key(from_id): self.players[from_id].self_message('This room is moderated - message not sent to others') - else: self.send_to_group(from_id,group_id,data) - else: self.players[to_id].outbox.put(data) + else: + self.send_to_group(from_id,group_id,data) + else: + self.players[to_id].outbox.put(data) + self.check_group_members(group_id) return def sound_msg_handler(self, xml_dom, data): from_id = xml_dom.getAttribute("from") group_id = xml_dom.getAttribute("group_id") - if group_id != 0: self.send_to_group(from_id, group_id, data) + if group_id != 0: + self.send_to_group(from_id, group_id, data) def plugin_msg_handler(self,xml_dom,data): to_id = xml_dom.getAttribute("to") @@ -1938,11 +2133,16 @@ if from_id == "0" or len(from_id) == 0: print "WARNING!! Message received with an invalid from_id. Message dropped." return None + + if to_id == 'all': if self.groups[group_id].moderated and not self.groups[group_id].voice.has_key(from_id): self.players[from_id].self_message('This room is moderated - message not sent to others') - else: self.send_to_group(from_id, group_id, msg) - else: self.players[to_id].outbox.put(msg) + else: + self.send_to_group(from_id, group_id, msg) + else: + self.players[to_id].outbox.put(msg) + self.check_group_members(group_id) return @@ -1952,7 +2152,8 @@ msg += "Displaying Roles

Role   Player
" keys = self.players.keys() for m in keys: - if self.players[m].group_id == group_id: msg += self.players[m].role + " " + self.players[m].name + "
" + if self.players[m].group_id == group_id: + msg += self.players[m].role + " " + self.players[m].name + "
" self.send(msg,player,group_id) elif act == "set": try: @@ -1965,7 +2166,8 @@ msg = "" self.send_to_group("0", group_id, msg) self.players[player].role = role - if (role.lower() == "gm" or role.lower() == "player"): self.groups[group_id].voice[player]=1 + if (role.lower() == "gm" or role.lower() == "player"): + self.groups[group_id].voice[player]=1 else: #tell the clients password manager the password failed -- SD 8/03 pm = "" @@ -1995,22 +2197,25 @@ try: actual_boot_pwd = self.groups[group_id].boot_pwd server_admin_pwd = self.groups["0"].boot_pwd + self.log_msg("Actual boot pwd = " + actual_boot_pwd) self.log_msg("Given boot pwd = " + given_boot_pwd) if self.players[to_id].group_id == group_id: - """ + ### ---CHANGES BY SNOWDOG 4/03 --- ### added boot to lobby code. ### if boot comes from lobby dump player from the server ### any user in-room boot will dump to lobby instead - """ if given_boot_pwd == server_admin_pwd: # Send a message to everyone in the room, letting them know someone has been booted boot_msg = "Booting '(%s) %s' from server..." % (from_id, group_id, to_id, self.players[to_id].name) + self.log_msg("boot_msg:" + boot_msg) + self.send_to_group( "0", group_id, boot_msg ) time.sleep( 1 ) + self.log_msg("Booting player " + str(to_id) + " from server.") # Send delete player event to all @@ -2025,7 +2230,9 @@ elif actual_boot_pwd == given_boot_pwd: # Send a message to everyone in the room, letting them know someone has been booted boot_msg = "Booting '(%s) %s' from room..." % (from_id, group_id, to_id, self.players[to_id].name) + self.log_msg("boot_msg:" + boot_msg) + self.send_to_group( "0", group_id, boot_msg ) time.sleep( 1 ) @@ -2046,15 +2253,17 @@ finally: try: - if xml_dom: xml_dom.unlink() + if xml_dom: + xml_dom.unlink() except Exception, e: traceback.print_exc() self.log_msg('Exception in xml_dom.unlink() ' + str(e)) - """ + + #--------------------------------------------------------------- # admin_kick function -- by Snowdog 4/03 # 9/17/05 updated to allow stealth boots (no client chat announce) -SD - """ + #--------------------------------------------------------------- def admin_kick(self, id, message="", silent = 0 ): "Kick a player from a server from the console" @@ -2063,7 +2272,8 @@ # Send a message to everyone in the victim's room, letting them know someone has been booted boot_msg = "Kicking '(%s) %s' from server... %s" % ( group_id, id, self.players[id].name, str(message)) self.log_msg("boot_msg:" + boot_msg) - if (silent == 0): self.send_to_group( "0", group_id, boot_msg ) + if (silent == 0): + self.send_to_group( "0", group_id, boot_msg ) time.sleep( 1 ) self.log_msg("kicking player " + str(id) + " from server.") @@ -2080,6 +2290,7 @@ traceback.print_exc() self.log_msg('Exception in admin_kick() ' + str(e)) + def admin_banip(self, ip, name="", silent = 0): "Ban a player from a server from the console" try: @@ -2126,7 +2337,9 @@ def admin_unban(self, ip): try: - if self.ban_list.has_key(ip): del self.ban_list[ip] + if self.ban_list.has_key(ip): + del self.ban_list[ip] + self.saveBanList() except Exception, e: @@ -2143,11 +2356,15 @@ msg.append(self.ban_list[ip]['ip']) msg.append("") msg.append("") + return "".join(msg) def admin_toggleSound(self): - if self.sendLobbySound: self.sendLobbySound = False - else: self.sendLobbySound = True + if self.sendLobbySound: + self.sendLobbySound = False + else: + self.sendLobbySound = True + return self.sendLobbySound def admin_soundFile(self, file): @@ -2166,13 +2383,16 @@ self.groups[group].persistant = 0 try: keys = self.groups[group].get_player_ids() - for k in keys: self.del_player(k, str(group)) + for k in keys: + self.del_player(k, str(group)) self.check_group("0", str(group)) - except: pass + except: + pass def send(self,msg,player,group): self.players[player].send(msg,player,group) + def send_to_all(self,from_id,data): try: print data @@ -2180,7 +2400,8 @@ keys = self.players.keys() self.p_lock.release() for k in keys: - if k != from_id: self.players[k].outbox.put(data) + if k != from_id: + self.players[k].outbox.put(data) except Exception, e: traceback.print_exc() self.log_msg("Exception: send_to_all(): " + str(e)) @@ -2193,7 +2414,8 @@ keys = self.groups[group_id].get_player_ids() self.p_lock.release() for k in keys: - if k != from_id: self.players[k].outbox.put(data) + if k != from_id: + self.players[k].outbox.put(data) except Exception, e: traceback.print_exc() self.log_msg("Exception: send_to_group(): " + str(e)) @@ -2218,24 +2440,24 @@ self.log_msg("Exception: send_group_list(): (client #"+to_id+") : " + str(e)) traceback.print_exc() - """ + #-------------------------------------------------------------------------- # KICK_ALL_CLIENTS() # # Convience method for booting all clients off the server at once. # used while troubleshooting mysterious "black hole" server bug # Added by Snowdog 11-19-04 - """ def kick_all_clients(self): try: keys = self.groups.keys() for k in keys: pl = self.groups[k].get_player_ids() - for p in pl: self.admin_kick(p,"Purged from server") + for p in pl: + self.admin_kick(p,"Purged from server") except Exception, e: traceback.print_exc() self.log_msg("Exception: kick_all_clients(): " + str(e)) - """ + # This really has little value as it will only catch people that are hung # on a disconnect which didn't complete. Other idle connections which are # really dead go undeterred. @@ -2243,7 +2465,6 @@ # UPDATED 11-29-04: Changed remove XML send to forced admin_kick for 'dead clients' # Dead clients now removed more effeciently as soon as they are detected # --Snowdog - """ def check_group_members(self, group_id): try: keys = self.groups[group_id].get_player_ids() @@ -2252,7 +2473,8 @@ #as these are likely dead clients idlemins = self.players[k].idle_time() idlemins = idlemins/60 - if (idlemins > self.zombie_time): self.admin_kick(k,"Removing zombie client", self.silent_auto_kick) + if (idlemins > self.zombie_time): + self.admin_kick(k,"Removing zombie client", self.silent_auto_kick) elif self.players[k].get_status() != MPLAY_CONNECTED: if self.players[k].check_time_out(): self.log_msg("Player #" + k + " Lost connection!") @@ -2262,12 +2484,13 @@ def remote_admin_handler(self,xml_dom,data): - """ # handle incoming remove server admin messages # (allows basic administration of server from a remote client) # base message format: - """ - if not self.allowRemoteAdmin: return + + if not self.allowRemoteAdmin: + return + try: pid = xml_dom.getAttribute("id") gid = "" @@ -2278,6 +2501,7 @@ p_name= "" p_ip = "" + #verify that the message came from the proper ID/Socket and get IP address for logging if self.players.has_key(pid): p_name=(self.players[pid]).name @@ -2299,40 +2523,44 @@ #tell the clients password manager the password failed -- SD 8/03 pm = "" self.players[pid].outbox.put(pm) - m = "Invalid Remote Server Control Message (bad password) from " - m += "#" + str(pid) + " (" + str(p_name) + ") " + str(p_ip) + m = "Invalid Remote Server Control Message (bad password) from #" + str(pid) + " (" + str(p_name) + ") " + str(p_ip) self.log_msg( m ) return #message now deemed 'authentic' #determine action to take based on command (cmd) + if cmd == "list": #return player list to this user. msg ="" + self.player_list_remote() self.players[pid].outbox.put(msg) + elif cmd == "banip": ip = xml_dom.getAttribute("bip") name = xml_dom.getAttribute("bname") msg = " Banned: " + str(ip) self.admin_banip(ip, name) + elif cmd == "ban": id = xml_dom.getAttribute("bid") msg = " Banned!" self.players[pid].outbox.put(msg) self.admin_ban(id, "") + elif cmd == "unban": ip = xml_dom.getAttribute("ip") self.admin_unban(ip) msg = " Unbaned: " + str(ip) self.players[pid].outbox.put(msg) + elif cmd == "banlist": msg = "" + self.admin_banlist() self.players[pid].outbox.put(msg) + elif cmd == "killgroup": ugid = xml_dom.getAttribute("gid") if ugid == "0": - m = "" - m += "Cannot Remove Lobby! Remote administrator request denied!" + m = "Cannot Remove Lobby! Remote administrator request denied!" self.players[pid].outbox.put(m) else: result = self.prune_room(ugid) @@ -2347,24 +2575,30 @@ except: msg = "" + self.uptime(1) self.players[pid].outbox.put(msg) + elif cmd == "help": msg = "" msg += self.AdminHelpMessage() self.players[pid].outbox.put( msg) + elif cmd == "roompasswords": # Toggle if room passwords are allowed on this server msg = "" msg += self.RoomPasswords() self.players[pid].outbox.put( msg) + elif cmd == "createroom": rm_name = xml_dom.getAttribute("name") rm_pass = xml_dom.getAttribute("pass") @@ -2372,18 +2606,19 @@ result = self.create_temporary_persistant_room(rm_name, rm_boot, rm_pass) msg = "" + result self.players[pid].outbox.put(msg) + elif cmd == "nameroom": rm_id = xml_dom.getAttribute("rmid") rm_name = xml_dom.getAttribute("name") result = self.change_group_name(rm_id,rm_name,pid) msg ="" + result self.players[pid].outbox.put(msg) + elif cmd == "passwd": tgid = xml_dom.getAttribute("gid") npwd = xml_dom.getAttribute("pass") if tgid == "0": - msg ="" - msg += "Server password may not be changed remotely!" + msg ="Server password may not be changed remotely!" self.players[pid].outbox.put(msg) else: try: @@ -2391,72 +2626,81 @@ msg ="Password changed for room " + tgid self.players[pid].outbox.put(msg) except: pass + elif cmd == "savemaps": for g in self.groups.itervalues(): g.save_map() + msg ="Persistent room maps saved" self.players[pid].outbox.put(msg) + + else: msg ="[Unknown Remote Administration Command]" self.players[pid].outbox.put(msg) + + except Exception, e: self.log_msg("Exception: Remote Admin Handler Error: " + str(e)) traceback.print_exc() + def toggleRemoteKill(self): - if self.allowRemoteKill: self.allowRemoteKill = False - else: self.allowRemoteKill = True + if self.allowRemoteKill: + self.allowRemoteKill = False + else: + self.allowRemoteKill = True + return self.allowRemoteKill def toggleRemoteAdmin(self): - if self.allowRemoteAdmin: self.allowRemoteAdmin = False - else: self.allowRemoteAdmin = True + if self.allowRemoteAdmin: + self.allowRemoteAdmin = False + else: + self.allowRemoteAdmin = True + return self.allowRemoteAdmin - """ - # Remote Administrator Help (returns from server not client) - """ +#----------------------------------------------------------------- +# Remote Administrator Help (returns from server not client) +#----------------------------------------------------------------- def AdminHelpMessage(self): "returns a string to be sent as a message to a remote admin" + #define the help command list information info = [] info.append( ['list', '/admin list', 'Displays information about rooms and players on the server'] ) info.append( ['uptime', '/admin uptime', 'Information on how long server has been running'] ) info.append( ['help', '/admin help', 'This help message']) - info.append( ['passwd', '/admin passwd <group id> <new password>', - 'Changes a rooms bootpassword. Server(lobby) password may not be changed']) + info.append( ['passwd', '/admin passwd <group id> <new password>', 'Changes a rooms bootpassword. Server(lobby) password may not be changed']) info.append( ['roompasswords', '/admin roompasswords', 'Allow/Disallow Room Passwords on the server (toggles)']) - info.append( ['message', '/admin message <user id> <message>', - 'Send a message to a specific user on the server']) + info.append( ['message', '/admin message <user id> <message>', 'Send a message to a specific user on the server']) info.append( ['broadcast', '/admin broadcast <message>', 'Broadcast message to all players on server']) - info.append( ['createroom', '/admin createroom <room name> <boot password> [password]', - 'Creates a temporary persistant room if possible.Rooms created this way are lost on server restarts']) + info.append( ['createroom', '/admin createroom <room name> <boot password> [password]', 'Creates a temporary persistant room if possible.Rooms created this way are lost on server restarts']) info.append( ['nameroom', '/admin nameroom <group id> <new name>', 'Rename a room']) - info.append( ['killgroup', '/admin killgroup <room id>', - 'Remove a room from the server and kick everyone in it.']) + info.append( ['killgroup', '/admin killgroup <room id>', 'Remove a room from the server and kick everyone in it.']) if self.allowRemoteKill: - info.append( ['killserver', '/admin killserver', - 'Shuts down the server. WARNING: Server cannot be restarted remotely via OpenRPG']) + info.append( ['killserver', '/admin killserver', 'Shuts down the server. WARNING: Server cannot be restarted remotely via OpenRPG']) info.append( ['ban', '/admin ban {playerId}', 'Ban a player from the server.']) info.append( ['unban', '/admin unban {bannedIP}', 'UnBan a player from the server.']) info.append( ['banlist', '/admin banlist', 'List Banned IPs and the Names associated with them']) - info.append( ['savemaps', '/admin savemaps', - 'Save all persistent room maps that are not using the default map file.']) + info.append( ['savemaps', '/admin savemaps', 'Save all persistent room maps that are not using the default map file.']) + #define the HTML for the help display FS = "" FE = "" + help = "
REMOTE ADMINISTRATOR COMMANDS SUPPORTED

" help += "" - help += "" + help += "" for n in info: - help += "" + help += "" help += "
CommandFormat" - help += "Description
CommandFormatDescription
" + FS + n[0] + FE + "" + FS + n[1] + FE + "" - help += "" + FS + n[2] + FE + "
" + FS + n[0] + FE + "" + FS + n[1] + FE + "" + FS + n[2] + FE + "
" return help - """ + + #---------------------------------------------------------------- # Create Persistant Group -- Added by Snowdog 6/03 # # Allows persistant groups to be created on the fly. @@ -2465,11 +2709,11 @@ # # Updated function code to use per-group based persistance and # removed references to outdated persistRoomIdThreshold - """ + #---------------------------------------------------------------- def create_temporary_persistant_room(self, roomname, bootpass, password=""): # if the room id just above the persistant room limit is available (not in use) - # then it will be assigned as a persistant room on the server + # then it will be assigned as a persistant room on the server "create a temporary persistant room" group_id = str(self.next_group_id) @@ -2481,7 +2725,7 @@ self.send_to_all('0',self.groups[group_id].toxml('update')) return str("Persistant room created (group " + group_id + ").") - """ + #---------------------------------------------------------------- # Prune Room -- Added by Snowdog 6/03 # # similar to remove_room() except rooms are removed regardless @@ -2489,34 +2733,39 @@ # # Added some error checking and updated room removal for per-room # based persistance -- Snowdog 4/04 - """ + #---------------------------------------------------------------- def prune_room(self,group): #don't allow lobby to be removed if group == '0': return "Lobby is required to exist and cannot be removed." #check that group id exists - if group not in self.groups: return "Invalid Room Id. Ignoring remove request." + if group not in self.groups: + return "Invalid Room Id. Ignoring remove request." try: keys = self.groups[group].get_player_ids() - for k in keys: self.move_player(k,'0') + for k in keys: + self.move_player(k,'0') + ins = "Room" if self.isPersistentRoom(group) : ins="Persistant room" self.send_to_all("0",self.groups[group].toxml('del')) del self.groups[group] self.log_msg(("delete_group", ('0',group))) return ins + " removed." + except: traceback.print_exc() return "An Error occured on the server during room removal!" - """ - # Remote Player List -- Added by snowdog 6/03 - # - # Similar to console listing except formated for web display - # in chat window on remote client - """ + +#---------------------------------------------------------------- +# Remote Player List -- Added by snowdog 6/03 +# +# Similar to console listing except formated for web display +# in chat window on remote client +#---------------------------------------------------------------- def player_list_remote(self): COLOR1 = "\"#004080\"" #header/footer background color COLOR2 = "\"#DDDDDD\"" #group line background color @@ -2528,19 +2777,18 @@ SIZE = "size=\"-1\"" #player info text size FG = PCOLOR + "display a condensed list of players on the server" self.p_lock.acquire() pl = "
" - pl += "" + pl += "" try: + keys = self.groups.keys() keys.sort(id_compare) for k in keys: - groupstring = "" - groupstring += "" + groupstring = "" pl += groupstring ids = self.groups[k].get_player_ids() ids.sort(id_compare) @@ -2554,20 +2802,18 @@ pl += "" - pl += "
" - pl += "GROUP & PLAYER LIST
GROUP & PLAYER LIST
" - groutstring += "Group " + str(k) + ": " + self.groups[k].name + "" - groupstring += " Password: \"" + self.groups[k].pwd + "\" Boot: \"" + self.groups[k].boot_pwd + "\"
Group " + str(k) + ": " + self.groups[k].name + "" + groupstring += " Password: \"" + self.groups[k].pwd + "\" Boot: \"" + self.groups[k].boot_pwd + "\"
" pl += "  (" + (self.players[id]).id + ") " pl += (self.players[id]).name - pl += "" - pl += "[IP: " + (self.players[id]).ip + "]" - pl += " " + pl += "[IP: " + (self.players[id]).ip + "] " pl += (self.players[id]).idle_status() pl += "" pl += (self.players[id]).connected_time_string() pl += "" + else: self.groups[k].remove_player(id) pl +="
Bad Player Ref (#" + id + ") in group" pl+="
" - pl += "Statistics: groups: " + str(len(self.groups)) + " " - pl += "players: " + str(len(self.players)) + "
" - except Exception, e: self.log_msg(str(e)) + pl += "Statistics: groups: " + str(len(self.groups)) + " players: " + str(len(self.players)) + "" + except Exception, e: + self.log_msg(str(e)) self.p_lock.release() return pl diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/networking/mplay_server_gui.py --- a/orpg/networking/mplay_server_gui.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/networking/mplay_server_gui.py Sat Sep 19 06:50:43 2009 -0500 @@ -13,9 +13,8 @@ import sys import time import types -from orpg.dirpath import dir_struct -#import orpg.systempath looks old -from orpg.tools.validate import Validate +import orpg.dirpath +import orpg.systempath from orpg.orpg_wx import * import webbrowser from threading import Thread @@ -58,8 +57,10 @@ f = ['b', 'Kb', 'Mb', 'Gb'] i = 0 while i < 3: - if b < 1024: return str(b) + f[i] - else: b = b/1024 + if b < 1024: + return str(b) + f[i] + else: + b = b/1024 i += 1 return str(b) + f[3] @@ -88,8 +89,10 @@ def __init__(self, owner ): """ Loads default configuration settings.""" - Validate(dir_struct["user"]).config_file("server_ini.xml", "default_server_ini.xml" ) - configDom = minidom.parse(dir_struct["user"] + 'server_ini.xml') + userPath = orpg.dirpath.dir_struct["user"] + validate = orpg.tools.validate.Validate(userPath) + validate.config_file( "server_ini.xml", "default_server_ini.xml" ) + configDom = minidom.parse(userPath + 'server_ini.xml') port = configDom.childNodes[0].childNodes[1].getAttribute('port') OPENRPG_PORT = 6774 if port == '' else int(port) #Pretty ugly, but I couldn't find the tag any other way. self.owner = owner @@ -143,14 +146,13 @@ # Main = GUI class Connections(wx.ListCtrl): def __init__( self, parent, main ): - wx.ListCtrl.__init__( self, parent, -1, wx.DefaultPosition, - wx.DefaultSize, wx.LC_REPORT|wx.SUNKEN_BORDER|wx.EXPAND|wx.LC_HRULES ) + wx.ListCtrl.__init__( self, parent, -1, wx.DefaultPosition, wx.DefaultSize, wx.LC_REPORT|wx.SUNKEN_BORDER|wx.EXPAND|wx.LC_HRULES ) self.main = main self.roomList = { 0 : "Lobby" } self._imageList = wx.ImageList( 16, 16, False ) - img = wx.Image(dir_struct["icon"]+"player.gif", wx.BITMAP_TYPE_GIF).ConvertToBitmap() + img = wx.Image(orpg.dirpath.dir_struct["icon"]+"player.gif", wx.BITMAP_TYPE_GIF).ConvertToBitmap() self._imageList.Add( img ) - img = wx.Image(dir_struct["icon"]+"player-whisper.gif", wx.BITMAP_TYPE_GIF).ConvertToBitmap() + img = wx.Image(orpg.dirpath.dir_struct["icon"]+"player-whisper.gif", wx.BITMAP_TYPE_GIF).ConvertToBitmap() self._imageList.Add( img ) self.SetImageList( self._imageList, wx.IMAGE_LIST_SMALL ) @@ -274,11 +276,13 @@ print "Send message to room..." msg = self.GetMessageInput( "Send message to room of this player") if len(msg): self.main.server.server.send_to_group('0', str(groupID), msg ) + elif menuItem == MENU_PLAYER_SEND_SERVER_MESSAGE: print "broadcast a message..." msg = self.GetMessageInput( "Broadcast Server Message" ) # If we got a message back, send it - if len(msg): self.main.server.server.broadcast( msg ) + if len(msg): + self.main.server.server.broadcast( msg ) def GetMessageInput( self, title ): prompt = "Please enter the message you wish to send:" @@ -289,10 +293,11 @@ class ServerGUI(wx.Frame): STATUS = SERVER_STOPPED + def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, id, title, size = (760, 560) ) - if wx.Platform == '__WXMSW__': icon = wx.Icon( dir_struct["icon"]+'WAmisc9.ico', wx.BITMAP_TYPE_ICO ) - else: icon = wx.Icon( dir_struct["icon"]+'connect.gif', wx.BITMAP_TYPE_GIF ) + if wx.Platform == '__WXMSW__': icon = wx.Icon( orpg.dirpath.dir_struct["icon"]+'WAmisc9.ico', wx.BITMAP_TYPE_ICO ) + else: icon = wx.Icon( orpg.dirpath.dir_struct["icon"]+'connect.gif', wx.BITMAP_TYPE_GIF ) self.SetIcon(icon) self.serverName = "Server Name" self.bootPwd = "" @@ -328,47 +333,52 @@ self.total_messages_sent = 0 self.total_data_sent = 0 - """ Build GUI """ + ### Build GUI ############################################ def build_menu(self): """ Build the GUI menu. """ self.mainMenu = wx.MenuBar() - # File Menu menu = wx.Menu() + # Start menu.Append( MENU_START_SERVER, 'Start', 'Start server.') self.Bind(wx.EVT_MENU, self.OnStart, id=MENU_START_SERVER) + # Stop menu.Append( MENU_STOP_SERVER, 'Stop', 'Shutdown server.') self.Bind(wx.EVT_MENU, self.OnStop, id=MENU_STOP_SERVER) + # Exit menu.AppendSeparator() menu.Append( MENU_EXIT, 'E&xit', 'Exit application.') self.Bind(wx.EVT_MENU, self.OnExit, id=MENU_EXIT) self.mainMenu.Append(menu, '&Server') - # Registration Menu menu = wx.Menu() + # Register menu.Append( MENU_REGISTER_SERVER, 'Register', 'Register with OpenRPG server directory.') self.Bind(wx.EVT_MENU, self.OnRegister, id=MENU_REGISTER_SERVER) + # Unregister menu.Append( MENU_UNREGISTER_SERVER, 'Unregister', 'Unregister from OpenRPG server directory.') self.Bind(wx.EVT_MENU, self.OnUnregister, id=MENU_UNREGISTER_SERVER) + # Add the registration menu self.mainMenu.Append( menu, '&Registration' ) - # Server Configuration Menu menu = wx.Menu() + # Ping Connected Players menu.Append( MENU_START_PING_PLAYERS, 'Start Ping', 'Ping players to validate remote connection.' ) self.Bind(wx.EVT_MENU, self.PingPlayers, id=MENU_START_PING_PLAYERS) + # Stop Pinging Connected Players menu.Append( MENU_STOP_PING_PLAYERS, 'Stop Ping', 'Stop validating player connections.' ) self.Bind(wx.EVT_MENU, self.StopPingPlayers, id=MENU_STOP_PING_PLAYERS) + # Set Ping Interval menu.Append( MENU_PING_INTERVAL, 'Ping Interval', 'Change the ping interval.' ) self.Bind(wx.EVT_MENU, self.ConfigPingInterval, id=MENU_PING_INTERVAL) self.mainMenu.Append( menu, '&Configuration' ) - + # Add the menus to the main menu bar self.SetMenuBar( self.mainMenu ) - + # Disable register, unregister & stop server by default self.mainMenu.Enable( MENU_STOP_SERVER, False ) self.mainMenu.Enable( MENU_REGISTER_SERVER, False ) self.mainMenu.Enable( MENU_UNREGISTER_SERVER, False ) - # Disable the ping menu items self.mainMenu.Enable( MENU_START_PING_PLAYERS, False ) self.mainMenu.Enable( MENU_STOP_PING_PLAYERS, False ) @@ -470,8 +480,10 @@ if self.STATUS == SERVER_STOPPED: # see if we already have name specified try: - Validate(dir_struct["user"]).config_file( "server_ini.xml", "default_server_ini.xml" ) - configDom = minidom.parse(dir_struct["user"] + 'server_ini.xml') + userPath = orpg.dirpath.dir_struct["user"] + validate = orpg.tools.validate.Validate(userPath) + validate.config_file( "server_ini.xml", "default_server_ini.xml" ) + configDom = minidom.parse(userPath + 'server_ini.xml') configDom.normalize() configDoc = configDom.documentElement if configDoc.hasAttribute("name"): self.serverName = configDoc.getAttribute("name") @@ -482,18 +494,19 @@ if serverNameEntry.ShowModal() == wx.ID_OK: self.serverName = serverNameEntry.GetValue() # see if we already have password specified try: - Validate(dir_struct["user"]).config_file( "server_ini.xml", "default_server_ini.xml" ) - configDom = minidom.parse(dir_struct["user"] + 'server_ini.xml') + userPath = orpg.dirpath.dir_struct["user"] + validate = orpg.tools.validate.Validate(userPath) + validate.config_file( "server_ini.xml", "default_server_ini.xml" ) + configDom = minidom.parse(userPath + 'server_ini.xml') configDom.normalize() configDoc = configDom.documentElement if configDoc.hasAttribute("admin"): self.bootPwd = configDoc.getAttribute("admin") elif configDoc.hasAttribute("boot"): self.bootPwd = configDoc.getAttribute("boot") except: pass if self.bootPwd == '': - serverPasswordEntry = wx.TextEntryDialog(self, - "Please Enter The Server Admin Password:", "Server's Password", - self.bootPwd, wx.OK|wx.CANCEL|wx.CENTRE) + serverPasswordEntry = wx.TextEntryDialog(self, "Please Enter The Server Admin Password:", "Server's Password", self.bootPwd, wx.OK|wx.CANCEL|wx.CENTRE) if serverPasswordEntry.ShowModal() == wx.ID_OK: self.bootPwd = serverPasswordEntry.GetValue() + if len(self.serverName): wx.BeginBusyCursor() self.server = ServerMonitor(self.callbacks, self.conf, self.serverName, self.bootPwd) @@ -519,6 +532,7 @@ self.mainMenu.Enable( MENU_START_SERVER, True ) self.mainMenu.Enable( MENU_REGISTER_SERVER, False ) self.mainMenu.Enable( MENU_UNREGISTER_SERVER, False ) + # Delete any items that are still in the player list self.conns.DeleteAllItems() def OnRegister(self, event = None): @@ -572,7 +586,7 @@ def OnInit(self): # Make sure our image handlers are loaded before we try to display anything wx.InitAllImageHandlers() - self.splash = wx.SplashScreen(wx.Bitmap(dir_struct["icon"]+'splash.gif'), + self.splash = wx.SplashScreen(wx.Bitmap(orpg.dirpath.dir_struct["icon"]+'splash.gif'), wx.SPLASH_CENTRE_ON_SCREEN|wx.SPLASH_TIMEOUT, 2000, None) @@ -590,6 +604,7 @@ class HTMLMessageWindow(wx.html.HtmlWindow): "Widget used to present user to admin messages, in HTML format, to the server administrator" + # Init using the derived from class def __init__( self, parent ): wx.html.HtmlWindow.__init__( self, parent ) diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/networking/server_plugins.py --- a/orpg/networking/server_plugins.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/networking/server_plugins.py Sat Sep 19 06:50:43 2009 -0500 @@ -25,6 +25,7 @@ def initBase(self): self._startPlugins() + #Methods def _startPlugins(self): autoload = [] @@ -59,6 +60,7 @@ self._load(pluginData) #Write to the autoload file for this plugin + self.__plugins[pluginName].Activated = True self.__plugins[pluginName].start() @@ -66,12 +68,13 @@ if not self.__plugins.has_key(pluginName): #Print some error about invalid plugin return + pluginData = self.__plugins[pluginName] - pluginData = self.__plugins[pluginName] self.__plugins[pluginName].stop() #Unload it self._unload(pluginData) + #Remove this plugin from the autoload file #Private Methods @@ -81,10 +84,7 @@ return ('plugins.' + self.__ptype + '.' + s2[0], s2[0]) def _unload(self, pluginData): - self.__plugins[pluginData.Name] = PluginData(pluginData.Name, - pluginData.File, - pluginData.Author, - pluginData.Help) + self.__plugins[pluginData.Name] = PluginData(pluginData.Name, pluginData.File, pluginData.Author, pluginData.Help) unload = [] mod = self._findModule(pluginData.File)[0] for key, module in sys.modules.iteritems(): @@ -115,6 +115,8 @@ def _getType(self): return self.__ptype + + #Properties Plugins = property(_getPlugins, None) Type = property(_getType, None) @@ -130,15 +132,18 @@ def preParseIncoming(self, xml_dom, data): sent = True errmsg = "" + for pluginName, pluginData in self.Plugins.iteritems(): if pluginData.Activated: xml_dom, data = pluginData.preParseIncoming(xml_dom, data) + return xml_dom, data def postParseIncoming(self, data): for pluginName, pluginData in self.Plugins.iteritems(): if pluginData.Activated: data = pluginData.postParseIncoming(data) + return data def getPlayer(self): @@ -147,6 +152,7 @@ if pluginData.Activated: playerName = pluginData.addPlayer(data) players.append(playerName) + return players def setPlayer(self, playerData): @@ -155,6 +161,7 @@ if pluginData.Activated: playerName = pluginData.addPlayer(data) players.append(playerName) + return def preParseOutgoing(self): @@ -164,6 +171,7 @@ xml = pluginData.preParseOutgoing() for msg in xml: data.append(msg) + return data def postParseOutgoing(self): @@ -173,6 +181,7 @@ xml = pluginData.postParseOutgoing() for msg in xml: data.append(msg) + return data __key = _SingletonKey() diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/orpgCore.py --- a/orpg/orpgCore.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/orpgCore.py Sat Sep 19 06:50:43 2009 -0500 @@ -71,6 +71,13 @@ if self.__components.has_key(key): del self.__components[key] else: return + ###Grumpy to Ornery### + def add_component(self, key, com): + return self.add(key, com) + + def get_component(self, key): + return self.get(key) + def singleton(cls): instances = {} def getinstance(): @@ -81,3 +88,6 @@ ORPGStorage = singleton(ORPGStorage) component = ORPGStorage() + +###Grumpy to Ornery### +open_rpg = ORPGStorage() diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/orpg_version.py --- a/orpg/orpg_version.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/orpg_version.py Sat Sep 19 06:50:43 2009 -0500 @@ -4,7 +4,7 @@ #BUILD NUMBER FORMAT: "YYMMDD-##" where ## is the incremental daily build index (if needed) DISTRO = "Traipse Beta" DIS_VER = "Ornery Orc" -BUILD = "090909-00" +BUILD = "090919-00" # This version is for network capability. PROTOCOL_VERSION = "1.2" diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/tools/orpg_log.py --- a/orpg/tools/orpg_log.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/tools/orpg_log.py Sat Sep 19 06:50:43 2009 -0500 @@ -54,7 +54,12 @@ crash_report.close() logger.exception("Crash Report Created!!") logger.info("Printed out crash-report.txt in your System folder", True) - wx.MessageBox('Crash Report Created!', 'System Failure') + #component.get('frame').traipseSuite.SetTitle('&Traipse!!') + component.get('frame').mainmenu.Replace(8, component.get('frame').traipseSuite, '&Traipse Suite!') + component.get('frame').debugConsole.SetBitmap(wx.Bitmap(dir_struct["icon"] + 'spotlight.png')) + component.get('frame').traipseSuite.RemoveItem(component.get('frame').debugConsole) + component.get('frame').traipseSuite.AppendItem(component.get('frame').debugConsole) + #wx.MessageBox('Crash Report Created!', 'System Failure') class DebugConsole(wx.Frame): def __init__(self, parent): diff -r 5c12918d6bb2 -r 68c7bd272f27 orpg/tools/orpg_settings.py --- a/orpg/tools/orpg_settings.py Wed Sep 09 17:12:59 2009 -0500 +++ b/orpg/tools/orpg_settings.py Sat Sep 19 06:50:43 2009 -0500 @@ -33,41 +33,47 @@ import sys import os from orpg.orpg_xml import xml +from orpg.tools.orpg_log import logger +from orpg.tools.validate import validate +from orpg.orpg_xml import xml class orpgSettings: def __init__(self): - self.validate = component.get("validate") - component.add('xml', xml) self.xml = component.get("xml") - self.orpgLog = component.get("log") self.changes = [] - self.validate.config_file("settings.xml","default_settings.xml") + 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 = self.xml.parseXml(txt) + self.xml_dom = xml.parseXml(txt) if self.xml_dom is None: self.rebuildSettings() self.xml_dom = self.xml_dom._get_documentElement() def rebuildSettings(self): - self.orpgLog.log("Settings file has be corrupted, rebuilding settings.", ORPG_INFO, True) + logger.info("Settings file has be corrupted, rebuilding settings.", True) try: os.remove(self.filename) except: pass - self.validate.config_file("settings.xml","default_settings.xml") + validate.config_file("settings.xml","default_settings.xml") temp_file = open(self.filename) txt = temp_file.read() temp_file.close() - self.xml_dom = self.xml.parseXml(txt) + self.xml_dom = xml.parseXml(txt) - def get_setting(self, name): + def get_setting(self, name): ##Depricated + return self.get(name) + + def get(self, name): try: return self.xml_dom.getElementsByTagName(name)[0].getAttribute("value") except: return 0 - def get_setting_keys(self): + def get_setting_keys(self): ##Depricated + return self.get_keys() + + def get_keys(self): keys = [] tabs = self.xml_dom.getElementsByTagName("tab") for i in xrange(0, len(tabs)): @@ -76,13 +82,19 @@ for c in children: keys.append(c._get_tagName()) return keys - def set_setting(self, name, value): + 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) - def add_setting(self, tab, setting, value, options, help): + 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 = self.xml.parseXml('<' + setting + ' value="' + value + '" options="' + + newsetting = xml.parseXml('<' + setting + ' value="' + value + '" options="' + options + '" help="' + help + '" />')._get_documentElement() for i in xrange(0, len(tabs)): if tabs[i].getAttribute("name") == tab and tabs[i].getAttribute("type") == 'grid': @@ -94,7 +106,7 @@ tab_xml = '' else: tab_xml += 'name="' + tabname + '" type="' + tabtype + '">' - newtab = self.xml.parseXml(tab_xml)._get_documentElement() + newtab = xml.parseXml(tab_xml)._get_documentElement() if parent != None: tabs = self.xml_dom.getElementsByTagName("tab") for i in xrange(0, len(tabs)): @@ -117,7 +129,7 @@ temp_file = open(defaultFile) txt = temp_file.read() temp_file.close() - default_dom = self.xml.parseXml(txt)._get_documentElement() + 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() @@ -136,7 +148,7 @@ def save(self): temp_file = open(self.filename, "w") - temp_file.write(self.xml.toxml(self.xml_dom,1)) + temp_file.write(xml.toxml(self.xml_dom,1)) temp_file.close() class orpgSettingsWnd(wx.Dialog): @@ -145,7 +157,6 @@ wx.DefaultPosition,size = wx.Size(-1,-1), style=wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION) self.Freeze() - self.validate = component.get("validate") self.settings = component.get("settings") self.chat = component.get("chat") self.changes = [] @@ -172,7 +183,7 @@ self.winsizer.SetDimension(0,0,w,h-25) def build_gui(self): - self.validate.config_file("settings.xml","default_settings.xml") + validate.config_file("settings.xml","default_settings.xml") filename = dir_struct["user"] + "settings.xml" temp_file = open(filename) temp_file.close() diff -r 5c12918d6bb2 -r 68c7bd272f27 upmana/default_manifest.xml --- a/upmana/default_manifest.xml Wed Sep 09 17:12:59 2009 -0500 +++ b/upmana/default_manifest.xml Sat Sep 19 06:50:43 2009 -0500 @@ -1,1 +1,13 @@ - + + + http://hg.assembla.com/traipse + http://hg.assembla.com/traipse + + + + + repo-Traipse + + + + diff -r 5c12918d6bb2 -r 68c7bd272f27 upmana/updatemana.py --- a/upmana/updatemana.py Wed Sep 09 17:12:59 2009 -0500 +++ b/upmana/updatemana.py Sat Sep 19 06:50:43 2009 -0500 @@ -26,7 +26,7 @@ self.parent = parent self.SetBackgroundColour(wx.WHITE) self.sizer = wx.GridBagSizer(hgap=1, vgap=1) - self.changelog = wx.TextCtrl(self, wx.ID_ANY, size=(325, -1), style=wx.TE_MULTILINE | wx.TE_READONLY) + self.changelog = wx.TextCtrl(self, wx.ID_ANY, size=(300, -1), style=wx.TE_MULTILINE | wx.TE_READONLY) self.filelist = wx.TextCtrl(self, wx.ID_ANY, size=(275, 300), style=wx.TE_MULTILINE | wx.TE_READONLY) self.buttons = {} self.buttons['progress_bar'] = wx.Gauge(self, wx.ID_ANY, 100) @@ -436,8 +436,10 @@ ## Branches / Revisions branchcp = wx.Panel(self) + self.current = self.repo.dirstate.branch() self.branchcp = wx.GridBagSizer(hgap=1, vgap=1) self.branches = wx.Choice(branchcp, wx.ID_ANY, choices=self.package_list) + self.branches.SetSelection(self.package_list.index(self.current)) self.branch_txt = wx.StaticText(branchcp, wx.ID_ANY, "Branches") self.branchcp.Add(self.branches, (0,0)) self.branchcp.Add(self.branch_txt, (0,1), flag=wx.ALIGN_CENTER_VERTICAL) @@ -482,7 +484,6 @@ self.SetSizer(self.sizer) self.SetAutoLayout(True) - self.current = self.repo.dirstate.branch() self.currev = self.repo.changelog.rev(self.repo.branchtags()[self.current]) self.RevInfo(self.currev) self.revlist.Select(self.revlist.FindItem(0, str(self.currev), 1)) @@ -541,18 +542,22 @@ pass def RevUpdate(self, event): - filename = 'ignorelist.txt' - self.filename = dir_struct["home"] + 'upmana' + os.sep + filename - component.get('validate').config_file(filename, "default_ignorelist.txt") - self.mana = self.LoadDoc() - temp = dir_struct["home"] + 'upmana' + os.sep + 'tmp' + os.sep - for ignore in self.ignorelist: - shutil.copy(ignore, temp + ignore.split('/')[len(ignore.split('/')) - 1]) - hg.clean(self.repo, self.currev) - for ignore in self.ignorelist: - shutil.copyfile(temp + ignore.split('/')[len(ignore.split('/')) - 1], ignore) - os.remove(temp + ignore.split('/')[len(ignore.split('/')) - 1]) - pass + dlg = wx.MessageDialog(None, 'Revision Updates are recommended for Developers only.\n\nAre you sure to preform a Revision Update?\n\nNewer builds tend to have less bugs while older revisions may no longer function properly.', 'Expert Feature', wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) + if dlg.ShowModal() == wx.ID_YES: + dlg.Destroy() + filename = 'ignorelist.txt' + self.filename = dir_struct["home"] + 'upmana' + os.sep + filename + component.get('validate').config_file(filename, "default_ignorelist.txt") + self.mana = self.LoadDoc() + temp = dir_struct["home"] + 'upmana' + os.sep + 'tmp' + os.sep + for ignore in self.ignorelist: + shutil.copy(ignore, temp + ignore.split('/')[len(ignore.split('/')) - 1]) + hg.clean(self.repo, self.currev) + for ignore in self.ignorelist: + shutil.copyfile(temp + ignore.split('/')[len(ignore.split('/')) - 1], ignore) + os.remove(temp + ignore.split('/')[len(ignore.split('/')) - 1]) + else: + dlg.Destroy(); pass def LoadDoc(self): ignore = open(self.filename)