comparison orpg/networking/mplay_client.py @ 92:68c7bd272f27 beta

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.
author sirebral
date Sat, 19 Sep 2009 06:50:43 -0500
parents 449a8900f9ac
children 7ed4979cc1cf
comparison
equal deleted inserted replaced
84:5c12918d6bb2 92:68c7bd272f27
27 # features in the orpg project. 27 # features in the orpg project.
28 # 28 #
29 29
30 __version__ = "$Id: mplay_client.py,v 1.71 2007/05/12 20:41:54 digitalxero Exp $" 30 __version__ = "$Id: mplay_client.py,v 1.71 2007/05/12 20:41:54 digitalxero Exp $"
31 31
32 #import orpg.minidom 32 import orpg.minidom
33 import socket 33 import socket
34 import Queue 34 import Queue
35 import thread 35 import thread
36 import traceback 36 import traceback
37 from threading import Event, Lock 37 from threading import Event, Lock
38 from xml.sax.saxutils import escape 38 from xml.sax.saxutils import escape
39 from struct import pack, unpack, calcsize 39 from struct import pack, unpack, calcsize
40 from string import * 40 from string import *
41 from orpg.orpg_version import CLIENT_STRING, PROTOCOL_VERSION, VERSION 41 from orpg.orpg_version import *
42 import errno 42 import errno
43 import os 43 import os
44 import time 44 import time
45 from orpg.orpgCore import component
46 from orpg.orpg_xml import xml 45 from orpg.orpg_xml import xml
46 import orpg.minidom as minidom
47 47
48 try: 48 try:
49 import bz2 49 import bz2
50 cmpBZ2 = True 50 cmpBZ2 = True
51 except: cmpBZ2 = False 51 except:
52 cmpBZ2 = False
52 53
53 try: 54 try:
54 import zlib 55 import zlib
55 cmpZLIB = True 56 cmpZLIB = True
56 except: cmpZLIB = False 57 except:
58 cmpZLIB = False
57 59
58 60
59 # This should be configurable 61 # This should be configurable
60 OPENRPG_PORT = 9557 62 OPENRPG_PORT = 9557
61 63
81 STATUS_SET_URL = 1 83 STATUS_SET_URL = 1
82 84
83 def parseXml(data): 85 def parseXml(data):
84 "parse and return doc" 86 "parse and return doc"
85 #print data 87 #print data
86 doc = xml.parseXml(data) 88 doc = minidom.parseString(data)
87 doc.normalize() 89 doc.normalize()
88 return doc 90 return doc
89 91
90 def myescape(data): 92 def myescape(data):
91 return escape(data,{"\"":""}) 93 return escape(data,{"\"":""})
115 self.recvThreadExitEvent = Event() 117 self.recvThreadExitEvent = Event()
116 self.id = "0" 118 self.id = "0"
117 self.group_id = "0" 119 self.group_id = "0"
118 self.name = "" 120 self.name = ""
119 self.role = "GM" 121 self.role = "GM"
120 ## Soon to be removed
121 self.ROLE_GM = "GM" 122 self.ROLE_GM = "GM"
122 self.ROLE_PLAYER = "Player" 123 self.ROLE_PLAYER = "Player"
123 self.ROLE_LURKER = "Lurker" 124 self.ROLE_LURKER = "Lurker"
124 ## --TaS
125 self.ip = socket.gethostbyname(socket.gethostname()) 125 self.ip = socket.gethostbyname(socket.gethostname())
126 self.remote_ip = None 126 self.remote_ip = None
127 self.version = VERSION 127 self.version = VERSION
128 self.protocol_version = PROTOCOL_VERSION 128 self.protocol_version = PROTOCOL_VERSION
129 self.client_string = CLIENT_STRING 129 self.client_string = CLIENT_STRING
133 self.log_console = None 133 self.log_console = None
134 self.sock = None 134 self.sock = None
135 self.text_status = "Idle" 135 self.text_status = "Idle"
136 self.statLock = Lock() 136 self.statLock = Lock()
137 self.useroles = 0 137 self.useroles = 0
138 self.ROLE_GM = "GM"
139 self.ROLE_PLAYER = "Player"
140 self.ROLE_LURKER = "Lurker"
138 self.lastmessagetime = time.time() 141 self.lastmessagetime = time.time()
139 self.connecttime = time.time() 142 self.connecttime = time.time()
140 143
141 def sendThread( self, arg ): 144 def sendThread( self, arg ):
142 "Sending thread. This thread reads from the data queue and writes to the socket." 145 "Sending thread. This thread reads from the data queue and writes to the socket."
144 # Wait to be told it's okay to start running 147 # Wait to be told it's okay to start running
145 self.startedEvent.wait() 148 self.startedEvent.wait()
146 149
147 # Loop as long as we have a connection 150 # Loop as long as we have a connection
148 while( self.get_status() == MPLAY_CONNECTED ): 151 while( self.get_status() == MPLAY_CONNECTED ):
149 try: readMsg = self.outbox.get( block=1 ) 152 try:
153 readMsg = self.outbox.get( block=1 )
150 except Exception, text: 154 except Exception, text:
151 self.log_msg( ("outbox.get() got an exception: ", text) ) 155 self.log_msg( ("outbox.get() got an exception: ", text) )
152 156
153 # If we are here, it's because we have data to send, no doubt! 157 # If we are here, it's because we have data to send, no doubt!
154 if self.status == MPLAY_CONNECTED: 158 if self.status == MPLAY_CONNECTED:
172 while( self.get_status() == MPLAY_CONNECTED ): 176 while( self.get_status() == MPLAY_CONNECTED ):
173 readMsg = self.recvMsg( self.sock ) 177 readMsg = self.recvMsg( self.sock )
174 try: 178 try:
175 if self.useCompression and self.compressionType != None: 179 if self.useCompression and self.compressionType != None:
176 readMsg = self.compressionType.decompress(readMsg) 180 readMsg = self.compressionType.decompress(readMsg)
177 except: pass 181 except:
182 pass
178 183
179 # Check the length of the message 184 # Check the length of the message
180 bytes = len( readMsg ) 185 bytes = len( readMsg )
181 186
182 # Make sure we are still connected 187 # Make sure we are still connected
183 if bytes == 0: break 188 if bytes == 0:
189 break
184 else: 190 else:
185 # Pass along the message so it can be processed 191 # Pass along the message so it can be processed
186 self.inbox.put( readMsg ) 192 self.inbox.put( readMsg )
187 self.update_idle_time() #update the last message time 193 self.update_idle_time() #update the last message time
188 if bytes == 0: 194 if bytes == 0:
217 # Send the encoded length 223 # Send the encoded length
218 sentl = sock.send( lp ) 224 sentl = sock.send( lp )
219 225
220 # Now, send the message the the length was describing 226 # Now, send the message the the length was describing
221 sentm = sock.send( msg ) 227 sentm = sock.send( msg )
222 if self.isServer(): self.log_msg(("data_sent", sentl+sentm)) 228 if self.isServer():
223 except socket.error, e: self.log_msg( e ) 229 self.log_msg(("data_sent", sentl+sentm))
224 except Exception, e: self.log_msg( e ) 230 except socket.error, e:
231 self.log_msg( e )
232 except Exception, e:
233 self.log_msg( e )
225 return sentm 234 return sentm
226 235
227 def recvData( self, sock, readSize ): 236 def recvData( self, sock, readSize ):
228 """Simple socket receive method. This method will only return when the exact 237 """Simple socket receive method. This method will only return when the exact
229 byte count has been read from the connection, if remote terminates our 238 byte count has been read from the connection, if remote terminates our
267 if self.isServer(): 276 if self.isServer():
268 self.log_msg(("data_recv", length+4)) 277 self.log_msg(("data_recv", length+4))
269 # Make the peer IP address available for reference later 278 # Make the peer IP address available for reference later
270 if self.remote_ip is None: 279 if self.remote_ip is None:
271 self.remote_ip = self.sock.getpeername() 280 self.remote_ip = self.sock.getpeername()
272 except IOError, e: self.log_msg( e ) 281 except IOError, e:
273 except Exception, e: self.log_msg( e ) 282 self.log_msg( e )
283 except Exception, e:
284 self.log_msg( e )
274 return msgData 285 return msgData
275 286
276 def initialize_threads(self): 287 def initialize_threads(self):
277 "Starts up our threads (2) and waits for them to make sure they are running!" 288 "Starts up our threads (2) and waits for them to make sure they are running!"
278 self.status = MPLAY_CONNECTED 289 self.status = MPLAY_CONNECTED
284 295
285 def disconnect(self): 296 def disconnect(self):
286 self.set_status(MPLAY_DISCONNECTING) 297 self.set_status(MPLAY_DISCONNECTING)
287 self.log_msg("client stub " + self.ip +" disconnecting...") 298 self.log_msg("client stub " + self.ip +" disconnecting...")
288 self.log_msg("closing sockets...") 299 self.log_msg("closing sockets...")
289 try: self.sock.shutdown( 2 ) 300 try:
301 self.sock.shutdown( 2 )
290 except Exception, e: 302 except Exception, e:
291 print "Caught exception: " + str(e) 303 print "Caught exception: " + str(e)
292 print 304 print
293 print "Continuing" 305 print "Continuing"
294 self.set_status(MPLAY_DISCONNECTED) 306 self.set_status(MPLAY_DISCONNECTED)
306 if self.useroles: 318 if self.useroles:
307 return 1 319 return 1
308 else: 320 else:
309 return 0 321 return 0
310 def update_self_from_player(self, player): 322 def update_self_from_player(self, player):
311 try: (self.name, self.ip, self.id, 323 try:
312 self.text_status, self.version, 324 (self.name, self.ip, self.id, self.text_status, self.version, self.protocol_version, self.client_string,role) = player
313 self.protocol_version, self.client_string, role) = player
314 except Exception, e: 325 except Exception, e:
315 print e 326 print e
316 """ 327
317 The IP field should really be deprecated as too many systems are NAT'd and/or behind firewalls for a 328 # The IP field should really be deprecated as too many systems are NAT'd and/or behind firewalls for a
318 client provided IP address to have much value. As such, we now label it as deprecated. 329 # client provided IP address to have much value. As such, we now label it as deprecated.
319 """
320 def toxml(self,action): 330 def toxml(self,action):
321 xml_data = '<player name="' + myescape(self.name) + '"' 331 xml_data = '<player name="' + myescape(self.name) + '"'
322 xml_data += ' action="' + action + '" id="' + self.id + '"' 332 xml_data += ' action="' + action + '" id="' + self.id + '"'
323 xml_data += ' group_id="' + self.group_id + '" ip="' + self.ip + '"' 333 xml_data += ' group_id="' + self.group_id + '" ip="' + self.ip + '"'
324 xml_data += ' status="' + self.text_status + '"' 334 xml_data += ' status="' + self.text_status + '"'
328 xml_data += ' useCompression="' + str(self.useCompression) + '"' 338 xml_data += ' useCompression="' + str(self.useCompression) + '"'
329 if cmpBZ2 and (self.compressionType == 'Undefined' or self.compressionType == bz2): 339 if cmpBZ2 and (self.compressionType == 'Undefined' or self.compressionType == bz2):
330 xml_data += ' cmpType="bz2"' 340 xml_data += ' cmpType="bz2"'
331 elif cmpZLIB and (self.compressionType == 'Undefined' or self.compressionType == zlib): 341 elif cmpZLIB and (self.compressionType == 'Undefined' or self.compressionType == zlib):
332 xml_data += ' cmpType="zlib"' 342 xml_data += ' cmpType="zlib"'
333 else: xml_data += ' cmpType="None"' 343 else:
344 xml_data += ' cmpType="None"'
334 xml_data += ' />' 345 xml_data += ' />'
335 return xml_data 346 return xml_data
336 347
337 def log_msg(self,msg): 348 def log_msg(self,msg):
338 if self.log_console: 349 if self.log_console:
339 self.log_console(msg) 350 self.log_console(msg)
351 # else:
352 # print "message", msg
340 353
341 def get_status(self): 354 def get_status(self):
342 self.statLock.acquire() 355 self.statLock.acquire()
343 status = self.status 356 status = self.status
344 self.statLock.release() 357 self.statLock.release()
345 return status 358 return status
346 359
347 def my_role(self): 360 def my_role(self):
348 #Leaving this for testing. 361 #Why create the three different objects? Why not just assign a value to self.role and use that? Prof_Ebral ponders.
349 return self.role
350 """
351 if self.role == "GM": 362 if self.role == "GM":
352 return self.ROLE_GM 363 return self.ROLE_GM
353 elif self.role == "Player": 364 elif self.role == "Player":
354 return self.ROLE_PLAYER 365 return self.ROLE_PLAYER
355 elif self.role == "Lurker": 366 elif self.role == "Lurker":
356 return self.ROLE_LURKER 367 return self.ROLE_LURKER
357 return -1 368 return -1
358 """
359 369
360 def set_status(self,status): 370 def set_status(self,status):
361 self.statLock.acquire() 371 self.statLock.acquire()
362 self.status = status 372 self.status = status
363 self.statLock.release() 373 self.statLock.release()
381 391
382 def idle_status(self): 392 def idle_status(self):
383 idletime = self.idle_time() 393 idletime = self.idle_time()
384 idlemins = idletime / 60 394 idlemins = idletime / 60
385 status = "Unknown" 395 status = "Unknown"
386 if idlemins < 3: status = "Active" 396 if idlemins < 3:
387 elif idlemins < 10: status = "Idle ("+str(int(idlemins))+" mins)" 397 status = "Active"
388 else: status = "Inactive ("+str(int(idlemins))+" mins)" 398 elif idlemins < 10:
399 status = "Idle ("+str(int(idlemins))+" mins)"
400 else:
401 status = "Inactive ("+str(int(idlemins))+" mins)"
389 return status 402 return status
390 403
391 def connected_time(self): 404 def connected_time(self):
392 curtime = time.time() 405 curtime = time.time()
393 timeoffset = curtime - self.connecttime 406 timeoffset = curtime - self.connecttime
412 #======================================================================== 425 #========================================================================
413 class mplay_client(client_base): 426 class mplay_client(client_base):
414 "mplay client" 427 "mplay client"
415 def __init__(self,name,callbacks): 428 def __init__(self,name,callbacks):
416 client_base.__init__(self) 429 client_base.__init__(self)
417 component.add('mp_client', self)
418 self.xml = component.get('xml')
419 self.set_name(name) 430 self.set_name(name)
420 self.on_receive = callbacks['on_receive'] 431 self.on_receive = callbacks['on_receive']
421 self.on_mplay_event = callbacks['on_mplay_event'] 432 self.on_mplay_event = callbacks['on_mplay_event']
422 self.on_group_event = callbacks['on_group_event'] 433 self.on_group_event = callbacks['on_group_event']
423 self.on_player_event = callbacks['on_player_event'] 434 self.on_player_event = callbacks['on_player_event']
426 # I know this is a bad thing to do but it has to be 437 # I know this is a bad thing to do but it has to be
427 # be done to use the unified password manager. 438 # be done to use the unified password manager.
428 # Should really find a better solution. -- SD 8/03 439 # Should really find a better solution. -- SD 8/03
429 self.orpgFrame_callback = callbacks['orpgFrame'] 440 self.orpgFrame_callback = callbacks['orpgFrame']
430 self.settings = self.orpgFrame_callback.settings 441 self.settings = self.orpgFrame_callback.settings
442 #self.version = VERSION
443 #self.protocol_version = PROTOCOL_VERSION
444 #self.client_string = CLIENT_STRING
431 self.ignore_id = [] 445 self.ignore_id = []
432 self.ignore_name = [] 446 self.ignore_name = []
433 self.players = {} 447 self.players = {}
434 self.groups = {} 448 self.groups = {}
435 self.unique_cookie = 0 449 self.unique_cookie = 0
493 507
494 def get_player_by_player_id(self,player): 508 def get_player_by_player_id(self,player):
495 players = self.get_players() 509 players = self.get_players()
496 if self.players.has_key(player): 510 if self.players.has_key(player):
497 for m in players: 511 for m in players:
498 if player == m[2]: return m 512 if player == m[2]:
513 return m
499 return -1 514 return -1
500 515
501 def get_id(self): 516 def get_id(self):
502 return self.id 517 return self.id
503 518
504 def get_my_info(self): 519 def get_my_info(self):
505 return (self.name, self.ip, self.id, 520 return (self.name, self.ip, self.id, self.text_status, self.version, self.protocol_version, self.client_string, self.role)
506 self.text_status, self.version,
507 self.protocol_version, self.client_string,
508 self.role)
509 521
510 def is_valid_id(self,id): 522 def is_valid_id(self,id):
511 self.statLock.acquire() 523 self.statLock.acquire()
512 value = self.players.has_key( id ) 524 value = self.players.has_key( id )
513 self.statLock.release() 525 self.statLock.release()
514 return value 526 return value
515 527
516 def clear_players(self,save_self=0): 528 def clear_players(self,save_self=0):
517 self.statLock.acquire() 529 self.statLock.acquire()
518 keys = self.players.keys() 530 keys = self.players.keys()
519 for k in keys: del self.players[k] 531 for k in keys:
532 del self.players[k]
520 self.statLock.release() 533 self.statLock.release()
521 534
522 def clear_groups(self): 535 def clear_groups(self):
523 self.statLock.acquire() 536 self.statLock.acquire()
524 keys = self.groups.keys() 537 keys = self.groups.keys()
525 for k in keys: del self.groups[k] 538 for k in keys:
539 del self.groups[k]
526 self.statLock.release() 540 self.statLock.release()
527 541
528 def find_role(self,id): 542 def find_role(self,id):
529 return self.players[id].role 543 return self.players[id].role
530 544
531 def get_ignore_list(self): 545 def get_ignore_list(self):
532 try: return (self.ignore_id, self.ignore_name) 546 try:
533 except: return (None, None) 547 return (self.ignore_id, self.ignore_name)
548 except:
549 return (None, None)
534 550
535 def toggle_ignore(self, id): 551 def toggle_ignore(self, id):
536 for m in self.ignore_id: 552 for m in self.ignore_id:
537 if `self.ignore_id[self.ignore_id.index(m)]` == `id`: 553 if `self.ignore_id[self.ignore_id.index(m)]` == `id`:
538 name = self.ignore_name[self.ignore_id.index(m)] 554 name = self.ignore_name[self.ignore_id.index(m)]
551 #--------------------------------------------------------- 567 #---------------------------------------------------------
552 # [START] Snowdog Password/Room Name altering code 12/02 568 # [START] Snowdog Password/Room Name altering code 12/02
553 #--------------------------------------------------------- 569 #---------------------------------------------------------
554 570
555 def set_room_pass(self,npwd,pwd=""): 571 def set_room_pass(self,npwd,pwd=""):
556 recycle_bin = "<alter key=\"pwd\" " 572 self.outbox.put("<alter key=\"pwd\" val=\"" +npwd+ "\" bpw=\"" + pwd + "\" plr=\"" + self.id +"\" gid=\"" + self.group_id + "\" />")
557 recycle_bin += "val=\"" +npwd+ "\" bpw=\"" + pwd + "\" "
558 recycle_bin += "plr=\"" + self.id +"\" gid=\"" + self.group_id + "\" />"
559 self.outbox.put(recycle_bin); del recycle_bin #makes line easier to read. --TaS
560 self.update() 573 self.update()
561 574
562 def set_room_name(self,name,pwd=""): 575 def set_room_name(self,name,pwd=""):
563 loc = name.find("&") 576 loc = name.find("&")
564 oldloc=0 577 oldloc=0
585 if loc > -1: 598 if loc > -1:
586 b = name[:loc] 599 b = name[:loc]
587 e = name[loc+1:] 600 e = name[loc+1:]
588 name = b + "&#39;" + e 601 name = b + "&#39;" + e
589 oldloc = loc+1 602 oldloc = loc+1
590 recycle_bin = "<alter key=\"name\" " 603 self.outbox.put("<alter key=\"name\" val=\"" + name + "\" bpw=\"" + pwd + "\" plr=\"" + self.id +"\" gid=\"" + self.group_id + "\" />")
591 recycle_bin += "val=\"" + name + "\" bpw=\"" + pwd + "\" "
592 recycle_bin += "plr=\"" + self.id +"\" gid=\"" + self.group_id + "\" />"
593 self.outbox.put(recycle_bin); del recycle_bin #makes line easier to read. --TaS
594 self.update() 604 self.update()
595 605
596 #--------------------------------------------------------- 606 #---------------------------------------------------------
597 # [END] Snowdog Password/Room Name altering code 12/02 607 # [END] Snowdog Password/Room Name altering code 12/02
598 #--------------------------------------------------------- 608 #---------------------------------------------------------
602 612
603 def get_role(self): 613 def get_role(self):
604 self.outbox.put("<role action=\"get\" player=\"" + self.id +"\" group_id=\""+self.group_id + "\" />") 614 self.outbox.put("<role action=\"get\" player=\"" + self.id +"\" group_id=\""+self.group_id + "\" />")
605 615
606 def set_role(self,player,role,pwd=""): 616 def set_role(self,player,role,pwd=""):
607 recycle_bin = "<role action=\"set\" player=\"" + player + "\" " 617 self.outbox.put("<role action=\"set\" player=\"" + player + "\" role=\"" +role+ "\" boot_pwd=\"" + pwd + "\" group_id=\"" + self.group_id + "\" />")
608 recycle_bin += "role=\"" +role+ "\" boot_pwd=\"" + pwd + "\" group_id=\"" + self.group_id + "\" />"
609 self.outbox.put(recycle_bin); del recycle_bin #makes line easer to read. --TaS
610 self.update() 618 self.update()
611 619
612 def send(self,msg,player="all"): 620 def send(self,msg,player="all"):
613 if self.status == MPLAY_CONNECTED and player != self.id: 621 if self.status == MPLAY_CONNECTED and player != self.id:
614 self.outbox.put("<msg to='"+player+"' from='"+self.id+"' group_id='"+self.group_id+"' />"+msg) 622 self.outbox.put("<msg to='"+player+"' from='"+self.id+"' group_id='"+self.group_id+"' />"+msg)
618 if self.status == MPLAY_CONNECTED: 626 if self.status == MPLAY_CONNECTED:
619 self.outbox.put(snd_xml) 627 self.outbox.put(snd_xml)
620 self.check_my_status() 628 self.check_my_status()
621 629
622 def send_create_group(self,name,pwd,boot_pwd,minversion): 630 def send_create_group(self,name,pwd,boot_pwd,minversion):
623 recycle_bin = "<create_group from=\""+self.id+"\" " 631 self.outbox.put("<create_group from=\""+self.id+"\" pwd=\""+pwd+"\" name=\""+
624 recycle_bin += "pwd=\""+pwd+"\" name=\""+ name+"\" boot_pwd=\""+boot_pwd+"\" " 632 name+"\" boot_pwd=\""+boot_pwd+"\" min_version=\"" + minversion +"\" />")
625 recycle_bin += "min_version=\"" + minversion +"\" />"
626 self.outbox.put(recycle_bin); del recycle_bin #makes line easier to read. --TaS
627 633
628 def send_join_group(self,group_id,pwd): 634 def send_join_group(self,group_id,pwd):
629 if (group_id != 0): self.update_role("Lurker") 635 if (group_id != 0):
636 self.update_role("Lurker")
630 self.outbox.put("<join_group from=\""+self.id+"\" pwd=\""+pwd+"\" group_id=\""+str(group_id)+"\" />") 637 self.outbox.put("<join_group from=\""+self.id+"\" pwd=\""+pwd+"\" group_id=\""+str(group_id)+"\" />")
631 638
632 def poll(self, evt=None): 639 def poll(self, evt=None):
633 try: 640 try:
634 msg = self.inbox.get_nowait() 641 msg = self.inbox.get_nowait()
635 except: 642 except:
636 if self.get_status() != MPLAY_CONNECTED: 643 if self.get_status() != MPLAY_CONNECTED:
637 self.check_my_status() 644 self.check_my_status()
638 else: 645 else:
639 try: self.pretranslate(msg) 646 try:
647 self.pretranslate(msg)
640 except Exception, e: 648 except Exception, e:
641 print "The following message: " + str(msg) 649 print "The following message: " + str(msg)
642 print "created the following exception: " 650 print "created the following exception: "
643 traceback.print_exc() 651 traceback.print_exc()
644 652
645 def add_msg_handler(self, tag, function, core=False): 653 def add_msg_handler(self, tag, function, core=False):
646 if not self.msg_handlers.has_key(tag): 654 if not self.msg_handlers.has_key(tag):
647 self.msg_handlers[tag] = function 655 self.msg_handlers[tag] = function
648 if core: self.core_msg_handlers.append(tag) 656 if core:
649 else: print 'XML Messages ' + tag + ' already has a handler' 657 self.core_msg_handlers.append(tag)
658 else:
659 print 'XML Messages ' + tag + ' already has a handler'
650 660
651 def remove_msg_handler(self, tag): 661 def remove_msg_handler(self, tag):
652 if self.msg_handlers.has_key(tag) and not tag in self.core_msg_handlers: 662 if self.msg_handlers.has_key(tag) and not tag in self.core_msg_handlers:
653 del self.msg_handlers[tag] 663 del self.msg_handlers[tag]
654 else: print 'XML Messages ' + tag + ' already deleted' 664 else:
665 print 'XML Messages ' + tag + ' already deleted'
655 666
656 def load_core_msg_handlers(self): 667 def load_core_msg_handlers(self):
657 self.add_msg_handler('msg', self.on_msg, True) 668 self.add_msg_handler('msg', self.on_msg, True)
658 self.add_msg_handler('ping', self.on_ping, True) 669 self.add_msg_handler('ping', self.on_ping, True)
659 self.add_msg_handler('group', self.on_group, True) 670 self.add_msg_handler('group', self.on_group, True)
663 self.add_msg_handler('sound', self.on_sound, True) 674 self.add_msg_handler('sound', self.on_sound, True)
664 675
665 def pretranslate(self,data): 676 def pretranslate(self,data):
666 # Pre-qualify our data. If we don't have atleast 5-bytes, then there is 677 # Pre-qualify our data. If we don't have atleast 5-bytes, then there is
667 # no way we even have a valid message! 678 # no way we even have a valid message!
668 if len(data) < 5: return 679 if len(data) < 5:
680 return
669 end = data.find(">") 681 end = data.find(">")
670 head = data[:end+1] 682 head = data[:end+1]
671 msg = data[end+1:] 683 msg = data[end+1:]
672 xml_dom = self.xml.parseXml(head) 684 xml_dom = xml.parseXml(head)
673 xml_dom = xml_dom._get_documentElement() 685 xml_dom = xml_dom._get_documentElement()
674 tag_name = xml_dom._get_tagName() 686 tag_name = xml_dom._get_tagName()
675 id = xml_dom.getAttribute("from") 687 id = xml_dom.getAttribute("from")
676 if id == '': id = xml_dom.getAttribute("id") 688 if id == '':
677 if self.msg_handlers.has_key(tag_name): self.msg_handlers[tag_name](id, data, xml_dom) 689 id = xml_dom.getAttribute("id")
690 if self.msg_handlers.has_key(tag_name):
691 self.msg_handlers[tag_name](id, data, xml_dom)
678 else: 692 else:
679 #Unknown messages recived ignoring 693 #Unknown messages recived ignoring
680 #using pass insted or printing an error message 694 #using pass insted or printing an error message
681 #because plugins should now be able to send and proccess messages 695 #because plugins should now be able to send and proccess messages
682 #if someone is using a plugin to send messages and this user does not 696 #if someone is using a plugin to send messages and this user does not
683 #have the plugin they would be getting errors 697 #have the plugin they would be getting errors
684 pass 698 pass
685 if xml_dom: xml_dom.unlink() 699 if xml_dom:
700 xml_dom.unlink()
686 701
687 def on_sound(self, id, data, xml_dom): 702 def on_sound(self, id, data, xml_dom):
688 (ignore_id,ignore_name) = self.get_ignore_list() 703 (ignore_id,ignore_name) = self.get_ignore_list()
689 for m in ignore_id: 704 for m in ignore_id:
690 if m == id: 705 if m == id:
702 msg = data[end+1:] 717 msg = data[end+1:]
703 if id == "0": 718 if id == "0":
704 self.on_receive(msg,None) # None get's interpreted in on_receive as the sys admin. 719 self.on_receive(msg,None) # None get's interpreted in on_receive as the sys admin.
705 # Doing it this way makes it harder to impersonate the admin 720 # Doing it this way makes it harder to impersonate the admin
706 else: 721 else:
707 if self.is_valid_id(id): self.on_receive(msg,self.players[id]) 722 if self.is_valid_id(id):
708 if xml_dom: xml_dom.unlink() 723 self.on_receive(msg,self.players[id])
724 if xml_dom:
725 xml_dom.unlink()
709 726
710 def on_ping(self, id, msg, xml_dom): 727 def on_ping(self, id, msg, xml_dom):
711 #a REAL ping time implementation by Snowdog 8/03 728 #a REAL ping time implementation by Snowdog 8/03
712 # recieves special server <ping time="###" /> command 729 # recieves special server <ping time="###" /> command
713 # where ### is a returning time from the clients ping command 730 # where ### is a returning time from the clients ping command
718 latency = float(float(ct) - float(ot)) 735 latency = float(float(ct) - float(ot))
719 latency = int( latency * 10000.0 ) 736 latency = int( latency * 10000.0 )
720 latency = float( latency) / 10.0 737 latency = float( latency) / 10.0
721 ping_msg = "Ping Results: " + str(latency) + " ms (parsed message, round trip)" 738 ping_msg = "Ping Results: " + str(latency) + " ms (parsed message, round trip)"
722 self.on_receive(ping_msg,None) 739 self.on_receive(ping_msg,None)
723 if xml_dom: xml_dom.unlink() 740 if xml_dom:
741 xml_dom.unlink()
724 742
725 def on_group(self, id, msg, xml_dom): 743 def on_group(self, id, msg, xml_dom):
726 name = xml_dom.getAttribute("name") 744 name = xml_dom.getAttribute("name")
727 players = xml_dom.getAttribute("players") 745 players = xml_dom.getAttribute("players")
728 act = xml_dom.getAttribute("action") 746 act = xml_dom.getAttribute("action")
736 del self.groups[id] 754 del self.groups[id]
737 self.on_group_event(mplay_event(GROUP_DEL, group_data)) 755 self.on_group_event(mplay_event(GROUP_DEL, group_data))
738 elif act == 'update': 756 elif act == 'update':
739 self.groups[id] = group_data 757 self.groups[id] = group_data
740 self.on_group_event(mplay_event(GROUP_UPDATE, group_data)) 758 self.on_group_event(mplay_event(GROUP_UPDATE, group_data))
741 if xml_dom: xml_dom.unlink() 759 if xml_dom:
760 xml_dom.unlink()
742 761
743 def on_role(self, id, msg, xml_dom): 762 def on_role(self, id, msg, xml_dom):
744 act = xml_dom.getAttribute("action") 763 act = xml_dom.getAttribute("action")
745 role = xml_dom.getAttribute("role") 764 role = xml_dom.getAttribute("role")
746 if (act == "set") or (act == "update"): 765 if (act == "set") or (act == "update"):
747 try: 766 try:
748 (a,b,c,d,e,f,g,h) = self.players[id] 767 (a,b,c,d,e,f,g,h) = self.players[id]
749 if id == self.id: 768 if id == self.id:
750 self.players[id] = (a,b,c,d,e,f,g,role) 769 self.players[id] = (a,b,c,d,e,f,g,role)
751 self.update_role(role) 770 self.update_role(role)
752 else: self.players[id] = (a,b,c,d,e,f,g,role) 771 else:
772 self.players[id] = (a,b,c,d,e,f,g,role)
753 self.on_player_event(mplay_event(PLAYER_UPDATE,self.players[id])) 773 self.on_player_event(mplay_event(PLAYER_UPDATE,self.players[id]))
754 except: pass 774 except:
755 if xml_dom: xml_dom.unlink() 775 pass
776 if xml_dom:
777 xml_dom.unlink()
756 778
757 def on_player(self, id, msg, xml_dom): 779 def on_player(self, id, msg, xml_dom):
758 act = xml_dom.getAttribute("action") 780 act = xml_dom.getAttribute("action")
759 ip = xml_dom.getAttribute("ip") 781 ip = xml_dom.getAttribute("ip")
760 name = xml_dom.getAttribute("name") 782 name = xml_dom.getAttribute("name")
761 status = xml_dom.getAttribute("status") 783 status = xml_dom.getAttribute("status")
762 version = xml_dom.getAttribute("version") 784 version = xml_dom.getAttribute("version")
763 protocol_version = xml_dom.getAttribute("protocol_version") 785 protocol_version = xml_dom.getAttribute("protocol_version")
764 client_string = xml_dom.getAttribute("client_string") 786 client_string = xml_dom.getAttribute("client_string")
765 try: player = (name, ip, id, status, 787 try:
766 version, protocol_version, 788 player = (name,ip,id,status,version,protocol_version,client_string,self.players[id][7])
767 client_string, self.players[id][7])
768 except Exception, e: 789 except Exception, e:
769 player = (name, ip, id, status, 790 player = (name,ip,id,status,version,protocol_version,client_string,"Player")
770 version, protocol_version,
771 client_string, "Player")
772 if act == "new": 791 if act == "new":
773 self.players[id] = player 792 self.players[id] = player
774 self.on_player_event(mplay_event(PLAYER_NEW, self.players[id])) 793 self.on_player_event(mplay_event(PLAYER_NEW,self.players[id]))
775 elif act == "group": 794 elif act == "group":
776 self.group_id = xml_dom.getAttribute("group_id") 795 self.group_id = xml_dom.getAttribute("group_id")
777 self.clear_players() 796 self.clear_players()
778 self.on_mplay_event(mplay_event(MPLAY_GROUP_CHANGE, self.groups[self.group_id])) 797 self.on_mplay_event(mplay_event(MPLAY_GROUP_CHANGE,self.groups[self.group_id]))
779 self.players[self.id] = self.get_my_info() #(self.name,self.ip,self.id,self.text_status) 798 self.players[self.id] = self.get_my_info() #(self.name,self.ip,self.id,self.text_status)
780 self.on_player_event(mplay_event(PLAYER_NEW, self.players[self.id])) 799 self.on_player_event(mplay_event(PLAYER_NEW,self.players[self.id]))
781 elif act == "failed": 800 elif act == "failed":
782 self.on_mplay_event(mplay_event(MPLAY_GROUP_CHANGE_F)) 801 self.on_mplay_event(mplay_event(MPLAY_GROUP_CHANGE_F))
783 elif act == "del": 802 elif act == "del":
784 self.on_player_event(mplay_event(PLAYER_DEL,self.players[id])) 803 self.on_player_event(mplay_event(PLAYER_DEL,self.players[id]))
785 if self.players.has_key(id): del self.players[id] 804 if self.players.has_key(id):
786 if id == self.id: self.do_disconnect() 805 del self.players[id]
806 if id == self.id:
807 self.do_disconnect()
787 # the next two cases handle the events that are used to let you know when others are typing 808 # the next two cases handle the events that are used to let you know when others are typing
788 elif act == "update": 809 elif act == "update":
789 if id == self.id: 810 if id == self.id:
790 self.players[id] = player 811 self.players[id] = player
791 self.update_self_from_player(player) 812 self.update_self_from_player(player)
792 else: self.players[id] = player 813 else:
814 self.players[id] = player
793 dont_send = 0 815 dont_send = 0
794 for m in self.ignore_id: 816 for m in self.ignore_id:
795 if m == id: dont_send=1 817 if m == id:
796 if dont_send != 1: self.on_player_event(mplay_event(PLAYER_UPDATE,self.players[id])) 818 dont_send=1
797 if xml_dom: xml_dom.unlink() 819 if dont_send != 1:
820 self.on_player_event(mplay_event(PLAYER_UPDATE,self.players[id]))
821 if xml_dom:
822 xml_dom.unlink()
798 823
799 def on_password(self, id, msg, xml_dom): 824 def on_password(self, id, msg, xml_dom):
800 signal = type = id = data = None 825 signal = type = id = data = None
801 id = xml_dom.getAttribute("id") 826 id = xml_dom.getAttribute("id")
802 type = xml_dom.getAttribute("type") 827 type = xml_dom.getAttribute("type")
806 if xml_dom: 831 if xml_dom:
807 xml_dom.unlink() 832 xml_dom.unlink()
808 833
809 def check_my_status(self): 834 def check_my_status(self):
810 status = self.get_status() 835 status = self.get_status()
811 if status == MPLAY_DISCONNECTING: self.do_disconnect() 836 if status == MPLAY_DISCONNECTING:
837 self.do_disconnect()
812 838
813 def connect(self, addressport): 839 def connect(self, addressport):
814 """Establish a connection to a server while still using sendThread & recvThread for its 840 """Establish a connection to a server while still using sendThread & recvThread for its
815 communication.""" 841 communication."""
816 if self.is_connected(): 842 if self.is_connected():
832 self.sock.connect((address,port)) 858 self.sock.connect((address,port))
833 # send client into with id=0 859 # send client into with id=0
834 self.sendMsg( self.sock, self.toxml("new") ) 860 self.sendMsg( self.sock, self.toxml("new") )
835 data = self.recvMsg( self.sock ) 861 data = self.recvMsg( self.sock )
836 # get new id and group_id 862 # get new id and group_id
837 xml_dom = self.xml.parseXml(data) 863 xml_dom = xml.parseXml(data)
838 xml_dom = xml_dom._get_documentElement() 864 xml_dom = xml_dom._get_documentElement()
839 self.id = xml_dom.getAttribute("id") 865 self.id = xml_dom.getAttribute("id")
840 self.group_id = xml_dom.getAttribute("group_id") 866 self.group_id = xml_dom.getAttribute("group_id")
841 if xml_dom.hasAttribute('useCompression') and xml_dom.getAttribute('useCompression') == 'True': 867 if xml_dom.hasAttribute('useCompression') and xml_dom.getAttribute('useCompression') == 'True':
842 self.useCompression = True 868 self.useCompression = True
843 if xml_dom.hasAttribute('cmpType'): 869 if xml_dom.hasAttribute('cmpType'):
844 if cmpBZ2 and xml_dom.getAttribute('cmpType') == 'bz2': 870 if cmpBZ2 and xml_dom.getAttribute('cmpType') == 'bz2':
845 self.compressionType = bz2 871 self.compressionType = bz2
846 elif cmpZLIB and xml_dom.getAttribute('cmpType') == 'zlib': 872 elif cmpZLIB and xml_dom.getAttribute('cmpType') == 'zlib':
847 self.compressionType = zlib 873 self.compressionType = zlib
848 else: self.compressionType = None 874 else:
849 else: self.compressionType = bz2 875 self.compressionType = None
876 else:
877 self.compressionType = bz2
850 #send confirmation 878 #send confirmation
851 self.sendMsg( self.sock, self.toxml("new") ) 879 self.sendMsg( self.sock, self.toxml("new") )
852 except Exception, e: 880 except Exception, e:
853 self.log_msg(e) 881 self.log_msg(e)
854 if xml_dom: xml_dom.unlink() 882 if xml_dom:
883 xml_dom.unlink()
855 return 0 884 return 0
856 885
857 # Start things rollings along 886 # Start things rollings along
858 self.initialize_threads() 887 self.initialize_threads()
859 self.on_mplay_event(mplay_event(MPLAY_CONNECTED)) 888 self.on_mplay_event(mplay_event(MPLAY_CONNECTED))
860 self.players[self.id] = (self.name, self.ip, self.id, 889 self.players[self.id] = (self.name,self.ip,self.id,self.text_status,self.version,self.protocol_version,self.client_string,self.role)
861 self.text_status, self.version,
862 self.protocol_version, self.client_string, self.role)
863 self.on_player_event(mplay_event(PLAYER_NEW,self.players[self.id])) 890 self.on_player_event(mplay_event(PLAYER_NEW,self.players[self.id]))
864 if xml_dom: xml_dom.unlink() 891 if xml_dom:
892 xml_dom.unlink()
865 return 1 893 return 1
866 894
867 def start_disconnect(self): 895 def start_disconnect(self):
868 self.on_mplay_event(mplay_event(MPLAY_DISCONNECTING)) 896 self.on_mplay_event(mplay_event(MPLAY_DISCONNECTING))
869 self.outbox.put( self.toxml("del") ) 897 self.outbox.put( self.toxml("del") )
870 ## Client Side Disconect Forced -- Snowdog 10-09-2003 898 ## Client Side Disconect Forced -- Snowdog 10-09-2003
871 #pause to allow GUI events time to sync. 899 #pause to allow GUI events time to sync.
872 time.sleep(1) 900 time.sleep(1)
873 self.do_disconnect() 901 self.do_disconnect()
874 902
875 def do_disconnect(self): 903 def do_disconnect(self):