comparison orpg/networking/mplay_client.py @ 119:9314d63c0941 alpha

Traipse Alpha 'OpenRPG' {091029-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 Bookmarks (Alpha) with cool Smiley Star and Plus Symbol images! Changes made to the map for increased portability. SnowDog has changes planned in Core, though. Added an initial push to the BCG. Not much to see, just shows off how it is re-writing Main code. Fix to remote admin commands Minor fix to texted based server, works in /System/ folder Some Core changes to gametree to correctly disply Pretty Print, thanks David! Fix to Splitter Nodes not being created. Added images to Plugin Control panel for Autostart feature Fix to massive amounts of images loading; from Core fix to gsclient so with_statement imports Added 'boot' command to remote admin Prep work in Pass tool for remote admin rankings and different passwords, ei, Server, Admin, Moderator, etc. Remote Admin Commands more organized, more prep work. Added Confirmation window for sent nodes. Minor changes to allow for portability to an OpenSUSE linux OS (hopefully without breaking) {091028} 00: Made changes to gametree to start working with Element Tree, mostly from Core Minor changes to Map to start working with Element Tree, from Core Preliminary changes to map efficiency, from FlexiRPG Miniatures Layer pop up box allows users to turn off Mini labels, from FlexiRPG Changes to main.py to start working with Element Tree {091029} 00: Changes made to server to start working with Element Tree. Changes made to Meta Server Lib. Prepping test work for a multi meta network page. Minor bug fixed with mini to gametree Zoom Mouse plugin added. Known Issue: Disconnecting causes an server side error. XML data is not being passed correctly.
author sirebral
date Thu, 29 Oct 2009 20:35:28 -0500
parents 217fb049bd00
children 36919b8a3ef9
comparison
equal deleted inserted replaced
118:217fb049bd00 119:9314d63c0941
44 import os 44 import os
45 import time 45 import time
46 from orpg.orpgCore import component 46 from orpg.orpgCore import component
47 from orpg.orpg_xml import xml 47 from orpg.orpg_xml import xml
48 48
49 from xml.etree.ElementTree import ElementTree, Element 49 from xml.etree.ElementTree import ElementTree, Element, iselement
50 from xml.etree.ElementTree import fromstring, tostring 50 from xml.etree.ElementTree import fromstring, tostring
51 from xml.parsers.expat import ExpatError
52
51 53
52 try: 54 try:
53 import bz2 55 import bz2
54 cmpBZ2 = True 56 cmpBZ2 = True
55 except: cmpBZ2 = False 57 except: cmpBZ2 = False
148 # Wait to be told it's okay to start running 150 # Wait to be told it's okay to start running
149 self.startedEvent.wait() 151 self.startedEvent.wait()
150 152
151 # Loop as long as we have a connection 153 # Loop as long as we have a connection
152 while( self.get_status() == MPLAY_CONNECTED ): 154 while( self.get_status() == MPLAY_CONNECTED ):
153 try: readMsg = self.outbox.get( block=1 ) 155 try: readMsg = self.outbox.get(block=1)
154 except Exception, text: 156 except Exception, text:
155 self.log_msg( ("outbox.get() got an exception: ", text) ) 157 self.log_msg( ("outbox.get() got an exception: ", text) )
156 158
157 # If we are here, it's because we have data to send, no doubt! 159 # If we are here, it's because we have data to send, no doubt!
158 if self.status == MPLAY_CONNECTED: 160 if self.status == MPLAY_CONNECTED:
190 self.inbox.put( readMsg ) 192 self.inbox.put( readMsg )
191 self.update_idle_time() #update the last message time 193 self.update_idle_time() #update the last message time
192 if bytes == 0: 194 if bytes == 0:
193 self.log_msg( "Remote has disconnected!" ) 195 self.log_msg( "Remote has disconnected!" )
194 self.set_status( MPLAY_DISCONNECTING ) 196 self.set_status( MPLAY_DISCONNECTING )
195 self.outbox.put( "" ) # Make sure the other thread is woken up! 197 self.outbox.put("") # Make sure the other thread is woken up!
196 self.sendThreadExitEvent.set() 198 self.sendThreadExitEvent.set()
197 self.log_msg( "recvThread has terminated..." ) 199 self.log_msg( "recvThread has terminated..." )
198 200
199 def sendMsg( self, sock, msg ): 201 def sendMsg( self, sock, msg ):
200 """Very simple function that will properly encode and send a message to te 202 """Very simple function that will properly encode and send a message to te
209 slice = buffer(mpacket, offset, len(mpacket)-offset) 211 slice = buffer(mpacket, offset, len(mpacket)-offset)
210 sent = sock.send(slice) 212 sent = sock.send(slice)
211 offset += sent 213 offset += sent
212 sentm = offset 214 sentm = offset
213 else: 215 else:
214 # Calculate our message length 216 length = len(msg) # Calculate our message length
215 length = len(msg) 217 lp = pack('!i', length) # Encode the message length into network byte order
216
217 # Encode the message length into network byte order
218 lp = pack('!i', length)
219
220 try: 218 try:
221 # Send the encoded length 219 sentl = sock.send( lp ) # Send the encoded length
222 sentl = sock.send( lp )
223
224 # Now, send the message the the length was describing 220 # Now, send the message the the length was describing
225 sentm = sock.send( msg ) 221 sentm = sock.send( msg )
226 if self.isServer(): self.log_msg(("data_sent", sentl+sentm)) 222 if self.isServer(): self.log_msg(("data_sent", sentl+sentm))
227 except socket.error, e: self.log_msg( e ) 223 except socket.error, e: self.log_msg( e )
228 except Exception, e: self.log_msg( e ) 224 except Exception, e: self.log_msg( e )
249 except socket.error, e: 245 except socket.error, e:
250 self.log_msg( e ) 246 self.log_msg( e )
251 data = "" 247 data = ""
252 return data 248 return data
253 249
254 def recvMsg( self, sock ): 250 def recvMsg(self, sock):
255 """This method now expects to receive a message having a 4-byte prefix length. It will ONLY read 251 """This method now expects to receive a message having a 4-byte prefix length. It will ONLY read completed messages. In the event that the remote's connection is terminated, it will throw an exception which should allow for the caller to more gracefully handle this exception event.
256 completed messages. In the event that the remote's connection is terminated, it will throw an 252
257 exception which should allow for the caller to more gracefully handle this exception event. 253 Because we use strictly reading ONLY based on the length that is told to use, we no longer have to worry about partially adjusting for fragmented buffers starting somewhere within a buffer that we've read. Rather, it will get ONLY a whole message and nothing more. Everything else will remain buffered with the OS until we attempt to read the next complete message."""
258
259 Because we use strictly reading ONLY based on the length that is told to use, we no longer have to
260 worry about partially adjusting for fragmented buffers starting somewhere within a buffer that we've
261 read. Rather, it will get ONLY a whole message and nothing more. Everything else will remain buffered
262 with the OS until we attempt to read the next complete message."""
263
264 msgData = "" 254 msgData = ""
265 try: 255 try:
266 lenData = self.recvData( sock, MPLAY_LENSIZE ) 256 lenData = self.recvData( sock, MPLAY_LENSIZE )
267 # Now, convert to a usable form 257 (length,) = unpack('!i', lenData) # Now, convert to a usable form
268 (length,) = unpack('!i', lenData) 258 msgData = self.recvData( sock, length ) # Read exactly the remaining amount of data
269 # Read exactly the remaining amount of data
270 msgData = self.recvData( sock, length )
271 if self.isServer(): 259 if self.isServer():
272 self.log_msg(("data_recv", length+4)) 260 self.log_msg(("data_recv", length+4))
273 # Make the peer IP address available for reference later 261 if self.remote_ip is None: # Make the peer IP address available for reference later
274 if self.remote_ip is None:
275 self.remote_ip = self.sock.getpeername() 262 self.remote_ip = self.sock.getpeername()
276 except IOError, e: self.log_msg( e ) 263 except IOError, e: self.log_msg( e )
277 except Exception, e: self.log_msg( e ) 264 except Exception, e: self.log_msg( e )
278 return msgData 265 return msgData
279 266
280 def initialize_threads(self): 267 def initialize_threads(self):
281 "Starts up our threads (2) and waits for them to make sure they are running!" 268 "Starts up our threads (2) and waits for them to make sure they are running!"
282 self.status = MPLAY_CONNECTED 269 self.status = MPLAY_CONNECTED
283 self.sock.setblocking(1) 270 self.sock.setblocking(1)
284 # Confirm that our threads have started 271 # Confirm that our threads have started
285 thread.start_new_thread( self.sendThread,(0,) ) 272 thread.start_new_thread( self.sendThread,(0,))
286 thread.start_new_thread( self.recvThread,(0,) ) 273 thread.start_new_thread( self.recvThread,(0,))
287 self.startedEvent.set() 274 self.startedEvent.set()
288 275
289 def disconnect(self): 276 def disconnect(self):
290 self.set_status(MPLAY_DISCONNECTING) 277 self.set_status(MPLAY_DISCONNECTING)
291 self.log_msg("client stub " + self.ip +" disconnecting...") 278 self.log_msg("client stub " + self.ip +" disconnecting...")
292 self.log_msg("closing sockets...") 279 self.log_msg("closing sockets...")
293 try: self.sock.shutdown( 2 ) 280 try: self.sock.shutdown(2)
294 except Exception, e: 281 except Exception, e:
295 print "Caught exception: " + str(e) 282 print "Caught exception: " + str(e)
296 print 283 print
297 print "Continuing" 284 print "Continuing"
298 self.set_status(MPLAY_DISCONNECTED) 285 self.set_status(MPLAY_DISCONNECTED)
319 print e 306 print e
320 """ 307 """
321 The IP field should really be deprecated as too many systems are NAT'd and/or behind firewalls for a 308 The IP field should really be deprecated as too many systems are NAT'd and/or behind firewalls for a
322 client provided IP address to have much value. As such, we now label it as deprecated. 309 client provided IP address to have much value. As such, we now label it as deprecated.
323 """ 310 """
324 def toxml(self,action): 311 def toxml(self, action):
325 """
326 el = Element('player') 312 el = Element('player')
327 el.set('name', myescape(self.name)) 313 el.set('name', myescape(self.name))
328 el.set('action', action) 314 el.set('action', action)
329 el.set('id', self.id) 315 el.set('id', self.id)
330 el.set('group_id', self.group_id) 316 el.set('group_id', self.group_id)
332 el.set('status', self.text_status) 318 el.set('status', self.text_status)
333 el.set('version', self.version) 319 el.set('version', self.version)
334 el.set('protocol_version', self.protocol_version) 320 el.set('protocol_version', self.protocol_version)
335 el.set('client_string', self.client_string) 321 el.set('client_string', self.client_string)
336 el.set('useCompression', str(self.useCompression)) 322 el.set('useCompression', str(self.useCompression))
337
338 cmpType = 'None' 323 cmpType = 'None'
339 if cmpBZ2 and (self.compressionType == 'Undefined' or self.compressionType == bz2): 324 if cmpBZ2 and (self.compressionType == 'Undefined' or self.compressionType == bz2):
340 cmpType = 'bz2' 325 cmpType = 'bz2'
341 elif cmpZLIB and (self.compressionType == 'Undefined' or self.compressionType == zlib): 326 elif cmpZLIB and (self.compressionType == 'Undefined' or self.compressionType == zlib):
342 cmpType = 'zlib' 327 cmpType = 'zlib'
343
344 el.set('cmpType', cmpType) 328 el.set('cmpType', cmpType)
345 return el 329 return tostring(el)
346 """
347
348 xml_data = '<player name="' + myescape(self.name) + '"'
349 xml_data += ' action="' + action + '" id="' + self.id + '"'
350 xml_data += ' group_id="' + self.group_id + '" ip="' + self.ip + '"'
351 xml_data += ' status="' + self.text_status + '"'
352 xml_data += ' version="' + self.version + '"'
353 xml_data += ' protocol_version="' + self.protocol_version + '"'
354 xml_data += ' client_string="' + self.client_string + '"'
355 xml_data += ' useCompression="' + str(self.useCompression) + '"'
356 if cmpBZ2 and (self.compressionType == 'Undefined' or self.compressionType == bz2):
357 xml_data += ' cmpType="bz2"'
358 elif cmpZLIB and (self.compressionType == 'Undefined' or self.compressionType == zlib):
359 xml_data += ' cmpType="zlib"'
360 else: xml_data += ' cmpType="None"'
361 xml_data += ' />'
362 return xml_data
363 330
364 def log_msg(self,msg): 331 def log_msg(self,msg):
365 if self.log_console: 332 if self.log_console:
366 self.log_console(msg) 333 self.log_console(msg)
367 334
372 return status 339 return status
373 340
374 def my_role(self): 341 def my_role(self):
375 #Leaving this for testing. 342 #Leaving this for testing.
376 return self.role 343 return self.role
377 """
378 if self.role == "GM":
379 return self.ROLE_GM
380 elif self.role == "Player":
381 return self.ROLE_PLAYER
382 elif self.role == "Lurker":
383 return self.ROLE_LURKER
384 return -1
385 """
386 344
387 def set_status(self,status): 345 def set_status(self,status):
388 self.statLock.acquire() 346 self.statLock.acquire()
389 self.status = status 347 self.status = status
390 self.statLock.release() 348 self.statLock.release()
566 self.ignore_id.remove(m) 524 self.ignore_id.remove(m)
567 self.ignore_name.remove(name) 525 self.ignore_name.remove(name)
568 return (0,id,name) 526 return (0,id,name)
569 self.ignore_name.append(self.players[id][0]) 527 self.ignore_name.append(self.players[id][0])
570 self.ignore_id.append(self.players[id][2]) 528 self.ignore_id.append(self.players[id][2])
571 return (1,self.players[id][2],self.players[id][0]) 529 return (1, self.players[id][2], self.players[id][0])
572 530
573 def boot_player(self,id,boot_pwd = ""): 531 def boot_player(self,id,boot_pwd = ""):
574 #self.send(BOOT_MSG,id) 532 el = Element('boot')
575 msg = '<boot boot_pwd="' + boot_pwd + '"/>' 533 el.set('boot_pwd', boot_pwd)
576 self.send(msg,id) 534 self.send(tostring(el), id)
577 535
578 #--------------------------------------------------------- 536 #---------------------------------------------------------
579 # [START] Snowdog Password/Room Name altering code 12/02 537 # [START] Snowdog Password/Room Name altering code 12/02
580 #--------------------------------------------------------- 538 #---------------------------------------------------------
581 539
582 def set_room_pass(self,npwd,pwd=""): 540 def set_room_pass(self, npwd, pwd=""):
583 recycle_bin = "<alter key=\"pwd\" " 541 el = Element('alter')
584 recycle_bin += "val=\"" +npwd+ "\" bpw=\"" + pwd + "\" " 542 el.set('key', 'pwd')
585 recycle_bin += "plr=\"" + self.id +"\" gid=\"" + self.group_id + "\" />" 543 el.set('val', npwd)
586 self.outbox.put(recycle_bin); del recycle_bin #makes line easier to read. --TaS 544 el.set('bpw', pwd)
545 el.set('plr', self.id)
546 el.set('gid', self.group_id)
547 self.outbox.put(tostring(el))
587 self.update() 548 self.update()
588 549
589 def set_room_name(self,name,pwd=""): 550 def set_room_name(self, name, pwd=""):
590 loc = name.find("&") 551 loc = name.find("&")
591 oldloc=0 552 oldloc=0
592 while loc > -1: 553 while loc > -1:
593 loc = name.find("&",oldloc) 554 loc = name.find("&",oldloc)
594 if loc > -1: 555 if loc > -1:
612 if loc > -1: 573 if loc > -1:
613 b = name[:loc] 574 b = name[:loc]
614 e = name[loc+1:] 575 e = name[loc+1:]
615 name = b + "&#39;" + e 576 name = b + "&#39;" + e
616 oldloc = loc+1 577 oldloc = loc+1
617 recycle_bin = "<alter key=\"name\" " 578 el = Element('alter')
618 recycle_bin += "val=\"" + name + "\" bpw=\"" + pwd + "\" " 579 el.set('key', 'pwd')
619 recycle_bin += "plr=\"" + self.id +"\" gid=\"" + self.group_id + "\" />" 580 el.set('val', npwd)
620 self.outbox.put(recycle_bin); del recycle_bin #makes line easier to read. --TaS 581 el.set('bpw', pwd)
582 el.set('plr', self.id)
583 el.set('gid', self.group_id)
584 self.outbox.put(tostring(el))
621 self.update() 585 self.update()
622 586
623 #--------------------------------------------------------- 587 #---------------------------------------------------------
624 # [END] Snowdog Password/Room Name altering code 12/02 588 # [END] Snowdog Password/Room Name altering code 12/02
625 #--------------------------------------------------------- 589 #---------------------------------------------------------
626 590
627 def display_roles(self): 591 def display_roles(self):
628 self.outbox.put("<role action=\"display\" player=\"" + self.id +"\" group_id=\""+self.group_id + "\" />") 592 el = Element('role')
593 el.set('action', 'display')
594 el.set('player', self.id)
595 el.set('group_id', self.group_id)
596 self.outbox.put(tostring(el))
629 597
630 def get_role(self): 598 def get_role(self):
631 self.outbox.put("<role action=\"get\" player=\"" + self.id +"\" group_id=\""+self.group_id + "\" />") 599 el = Element('role')
632 600 el.set('action', 'get')
633 def set_role(self,player,role,pwd=""): 601 el.set('player', self.id)
634 recycle_bin = "<role action=\"set\" player=\"" + player + "\" " 602 el.set('group_id', self.group_id)
635 recycle_bin += "role=\"" +role+ "\" boot_pwd=\"" + pwd + "\" group_id=\"" + self.group_id + "\" />" 603 self.outbox.put(tostring(el))
636 self.outbox.put(recycle_bin); del recycle_bin #makes line easer to read. --TaS 604
605 def set_role(self, player, role, pwd=""):
606 el = Element('role')
607 el.set('action', 'set')
608 el.set('player', player)
609 el.set('role', role)
610 el.set('boot_pwd', pwd)
611 el.set('group_id', self.group_id)
612 self.outbox.put(tostring(el))
637 self.update() 613 self.update()
638 614
639 def send(self,msg,player="all"): 615 def send(self, msg, player="all"):
640 if self.status == MPLAY_CONNECTED and player != self.id: 616 if self.status == MPLAY_CONNECTED and player != self.id:
617 ### Pre Alpha ###
618 #el = Element('msg')
619 #el.set('to', player)
620 #el.set('from', self.id)
621 #el.set('group_id', self.group_id)
622 #el.append(fromstring(msg))
623 #self.outbox.put(tostring(el))
624 ### Current chat is not ready for Element Tree ###
641 self.outbox.put("<msg to='"+player+"' from='"+self.id+"' group_id='"+self.group_id+"' />"+msg) 625 self.outbox.put("<msg to='"+player+"' from='"+self.id+"' group_id='"+self.group_id+"' />"+msg)
642 self.check_my_status() 626 self.check_my_status()
643 627
644 def send_sound(self, snd_xml): 628 def send_sound(self, snd_xml):
645 if self.status == MPLAY_CONNECTED: 629 if self.status == MPLAY_CONNECTED:
646 self.outbox.put(snd_xml) 630 self.outbox.put(snd_xml)
647 self.check_my_status() 631 self.check_my_status()
648 632
649 def send_create_group(self,name,pwd,boot_pwd,minversion): 633 def send_create_group(self, name, pwd, boot_pwd, min_version):
650 recycle_bin = "<create_group from=\""+self.id+"\" " 634 el = Element('create_group')
651 recycle_bin += "pwd=\""+pwd+"\" name=\""+ name+"\" boot_pwd=\""+boot_pwd+"\" " 635 el.set('from', self.id)
652 recycle_bin += "min_version=\"" + minversion +"\" />" 636 el.set('pwd', pwd)
653 self.outbox.put(recycle_bin); del recycle_bin #makes line easier to read. --TaS 637 el.set('name', name)
654 638 el.set('boot_pwd', boot_pwd)
655 def send_join_group(self,group_id,pwd): 639 el.set('min_version', min_version)
640 self.outbox.put(tostring(el))
641
642 def send_join_group(self, group_id, pwd):
656 if (group_id != 0): self.update_role("Lurker") 643 if (group_id != 0): self.update_role("Lurker")
657 self.outbox.put("<join_group from=\""+self.id+"\" pwd=\""+pwd+"\" group_id=\""+str(group_id)+"\" />") 644 el = Element('join_group')
645 el.set('from', self.id)
646 el.set('pwd', pwd)
647 el.set('group_id', str(group_id))
648 print 'send join group ', str(group_id)
649 self.outbox.put(tostring(el))
658 650
659 def poll(self, evt=None): 651 def poll(self, evt=None):
660 try: 652 try: msg = self.inbox.get_nowait()
661 msg = self.inbox.get_nowait()
662 except: 653 except:
663 if self.get_status() != MPLAY_CONNECTED: 654 if self.get_status() != MPLAY_CONNECTED:
664 self.check_my_status() 655 self.check_my_status()
665 else: 656 else:
666 try: self.pretranslate(msg) 657 try: self.pretranslate(msg)
687 self.add_msg_handler('role', self.on_role, True) 678 self.add_msg_handler('role', self.on_role, True)
688 self.add_msg_handler('player', self.on_player, True) 679 self.add_msg_handler('player', self.on_player, True)
689 self.add_msg_handler('password', self.on_password, True) 680 self.add_msg_handler('password', self.on_password, True)
690 self.add_msg_handler('sound', self.on_sound, True) 681 self.add_msg_handler('sound', self.on_sound, True)
691 682
692 def pretranslate(self,data): 683 def pretranslate(self, data):
693 # Pre-qualify our data. If we don't have atleast 5-bytes, then there is 684 # Pre-qualify our data. If we don't have atleast 5-bytes, then there is
694 # no way we even have a valid message! 685 # no way we even have a valid message!
695 if len(data) < 5: return 686 if len(data) < 5: return
696 end = data.find(">") 687 try: el = fromstring(data)
697 head = data[:end+1] 688 except ExpatError:
698 msg = data[end+1:] 689 end = data.find(">")
699 xml_dom = self.xml.parseXml(head) 690 head = data[:end+1]
700 xml_dom = xml_dom._get_documentElement() 691 msg = data[end+1:]
701 tag_name = xml_dom._get_tagName() 692 el = fromstring(head)
702 id = xml_dom.getAttribute("from") 693 try:
703 if id == '': id = xml_dom.getAttribute("id") 694 el1 = fromstring(msg)
704 if self.msg_handlers.has_key(tag_name): self.msg_handlers[tag_name](id, data, xml_dom) 695 el.append(el1)
705 else: 696 except ExpatError:
706 #Unknown messages recived ignoring 697 el.text = msg
707 #using pass insted or printing an error message 698 #logger.general("Bad Message: \n" + data)
708 #because plugins should now be able to send and proccess messages 699 id = el.get('from') or el.get('id')
709 #if someone is using a plugin to send messages and this user does not 700 if el.tag in self.msg_handlers: self.msg_handlers[el.tag](id, data, el)
710 #have the plugin they would be getting errors 701
711 pass 702 def on_sound(self, id, data, etreeEl):
712 if xml_dom: xml_dom.unlink()
713
714 def on_sound(self, id, data, xml_dom):
715 (ignore_id,ignore_name) = self.get_ignore_list() 703 (ignore_id,ignore_name) = self.get_ignore_list()
716 for m in ignore_id: 704 for m in ignore_id:
717 if m == id: 705 if m == id:
718 # yes we are 706 # yes we are
719 print "ignoring sound from player:" 707 print "ignoring sound from player:"
720 return 708 return
721 chat = self.get_chat() 709 chat = self.get_chat()
722 snd = xml_dom.getAttribute("url") 710 chat.sound_player.play(etreeEl.get('url'), 'remote', etreeEl.get('loop'))
723 loop_sound = xml_dom.getAttribute("loop") 711
724 chat.sound_player.play(snd, "remote", loop_sound) 712 def on_msg(self, id, data, etreeEl):
725
726 def on_msg(self, id, data, xml_dom):
727 end = data.find(">") 713 end = data.find(">")
728 head = data[:end+1] 714 head = data[:end+1]
729 msg = data[end+1:] 715 msg = data[end+1:]
730 if id == "0": 716 if msg[-6:] == '</msg>': msg = msg[:-6]
731 self.on_receive(msg,None) # None get's interpreted in on_receive as the sys admin. 717 if id == "0": self.on_receive(msg, None)
732 # Doing it this way makes it harder to impersonate the admin 718 # None get's interpreted in on_receive as the sys admin.
733 else: 719 # Doing it this way makes it harder to impersonate the admin
734 if self.is_valid_id(id): self.on_receive(msg,self.players[id]) 720 elif self.is_valid_id(id): self.on_receive(msg, self.players[id])
735 if xml_dom: xml_dom.unlink() 721
736 722 def on_ping(self, id, msg, etreeEl):
737 def on_ping(self, id, msg, xml_dom):
738 #a REAL ping time implementation by Snowdog 8/03 723 #a REAL ping time implementation by Snowdog 8/03
739 # recieves special server <ping time="###" /> command 724 # recieves special server <ping time="###" /> command
740 # where ### is a returning time from the clients ping command 725 # where ### is a returning time from the clients ping command
741 #get current time, pull old time from object and compare them 726 #get current time, pull old time from object and compare them
742 # the difference is the latency between server and client * 2 727 # the difference is the latency between server and client * 2
743 ct = time.clock() 728 ct = time.clock()
744 ot = xml_dom.getAttribute("time") 729 ot = etreeEl.get("time")
745 latency = float(float(ct) - float(ot)) 730 latency = float(float(ct) - float(ot))
746 latency = int( latency * 10000.0 ) 731 latency = int(latency * 10000.0)
747 latency = float( latency) / 10.0 732 latency = float(latency) / 10.0
748 ping_msg = "Ping Results: " + str(latency) + " ms (parsed message, round trip)" 733 ping_msg = "Ping Results: " + str(latency) + " ms (parsed message, round trip)"
749 self.on_receive(ping_msg,None) 734 self.on_receive(ping_msg, None)
750 if xml_dom: xml_dom.unlink() 735
751 736 def on_group(self, id, msg, etreeEl):
752 def on_group(self, id, msg, xml_dom): 737 act = etreeEl.get("action")
753 name = xml_dom.getAttribute("name") 738 group_data = (id, etreeEl.get("name"), etreeEl.get("pwd"), etreeEl.get("players"))
754 players = xml_dom.getAttribute("players") 739 if act == 'new' or 'update':
755 act = xml_dom.getAttribute("action")
756 pwd = xml_dom.getAttribute("pwd")
757 group_data = (id, name, pwd, players)
758
759 if act == 'new':
760 self.groups[id] = group_data 740 self.groups[id] = group_data
761 self.on_group_event(mplay_event(GROUP_NEW, group_data)) 741 if act == 'update': self.on_group_event(mplay_event(GROUP_UPDATE, group_data))
742 elif act == 'new': self.on_group_event(mplay_event(GROUP_NEW, group_data))
762 elif act == 'del': 743 elif act == 'del':
763 del self.groups[id] 744 del self.groups[id]
764 self.on_group_event(mplay_event(GROUP_DEL, group_data)) 745 self.on_group_event(mplay_event(GROUP_DEL, group_data))
765 elif act == 'update': 746
766 self.groups[id] = group_data 747 def on_role(self, id, msg, etreeEl):
767 self.on_group_event(mplay_event(GROUP_UPDATE, group_data)) 748 act = etreeEl.get("action")
768 if xml_dom: xml_dom.unlink()
769
770 def on_role(self, id, msg, xml_dom):
771 act = xml_dom.getAttribute("action")
772 role = xml_dom.getAttribute("role")
773 if (act == "set") or (act == "update"): 749 if (act == "set") or (act == "update"):
774 try: 750 try:
775 (a,b,c,d,e,f,g,h) = self.players[id] 751 (a,b,c,d,e,f,g,h) = self.players[id]
776 if id == self.id: 752 if id == self.id:
777 self.players[id] = (a,b,c,d,e,f,g,role) 753 self.players[id] = (a,b,c,d,e,f,g,etreeEl.get("role"))
778 self.update_role(role) 754 self.update_role(etreeEl.get("role"))
779 else: self.players[id] = (a,b,c,d,e,f,g,role) 755 else: self.players[id] = (a,b,c,d,e,f,g,etreeEl.get("role"))
780 self.on_player_event(mplay_event(PLAYER_UPDATE,self.players[id])) 756 self.on_player_event(mplay_event(PLAYER_UPDATE, self.players[id]))
781 except: pass 757 except: pass
782 if xml_dom: xml_dom.unlink() 758
783 759 def on_player(self, id, msg, etreeEl):
784 def on_player(self, id, msg, xml_dom): 760 act = etreeEl.get("action")
785 act = xml_dom.getAttribute("action") 761 try: player = (etreeEl.get("name"), etreeEl.get("ip"), id, etreeEl.get("status"),
786 ip = xml_dom.getAttribute("ip") 762 etreeEl.get("version"), etreeEl.get("protocol_version"),
787 name = xml_dom.getAttribute("name") 763 etreeEl.get("client_string"), self.players[id][7])
788 status = xml_dom.getAttribute("status")
789 version = xml_dom.getAttribute("version")
790 protocol_version = xml_dom.getAttribute("protocol_version")
791 client_string = xml_dom.getAttribute("client_string")
792 try: player = (name, ip, id, status,
793 version, protocol_version,
794 client_string, self.players[id][7])
795 except Exception, e: 764 except Exception, e:
796 player = (name, ip, id, status, 765 player = (etreeEl.get("name"), etreeEl.get("ip"), id, etreeEl.get("status"),
797 version, protocol_version, 766 etreeEl.get("version"), etreeEl.get("protocol_version"),
798 client_string, "Player") 767 etreeEl.get("client_string"), "Player")
768 print e
799 if act == "new": 769 if act == "new":
800 self.players[id] = player 770 self.players[id] = player
801 self.on_player_event(mplay_event(PLAYER_NEW, self.players[id])) 771 self.on_player_event(mplay_event(PLAYER_NEW, self.players[id]))
802 elif act == "group": 772 elif act == "group":
803 self.group_id = xml_dom.getAttribute("group_id") 773 self.group_id = etreeEl.get('group_id')
804 self.clear_players() 774 self.clear_players()
805 self.on_mplay_event(mplay_event(MPLAY_GROUP_CHANGE, self.groups[self.group_id])) 775 self.on_mplay_event(mplay_event(MPLAY_GROUP_CHANGE, self.groups[self.group_id]))
806 self.players[self.id] = self.get_my_info() #(self.name,self.ip,self.id,self.text_status) 776 self.players[self.id] = self.get_my_info()
777 #(self.name,self.ip,self.id,self.text_status)
807 self.on_player_event(mplay_event(PLAYER_NEW, self.players[self.id])) 778 self.on_player_event(mplay_event(PLAYER_NEW, self.players[self.id]))
808 elif act == "failed": 779 elif act == "failed":
809 self.on_mplay_event(mplay_event(MPLAY_GROUP_CHANGE_F)) 780 self.on_mplay_event(mplay_event(MPLAY_GROUP_CHANGE_F))
810 elif act == "del": 781 elif act == "del":
811 self.on_player_event(mplay_event(PLAYER_DEL,self.players[id])) 782 self.on_player_event(mplay_event(PLAYER_DEL, self.players[id]))
812 if self.players.has_key(id): del self.players[id] 783 if self.players.has_key(id): del self.players[id]
813 if id == self.id: self.do_disconnect() 784 if id == self.id: self.do_disconnect()
814 # the next two cases handle the events that are used to let you know when others are typing 785 # the next two cases handle the events that are used to let you know when others are typing
815 elif act == "update": 786 elif act == "update":
816 if id == self.id: 787 if id == self.id:
817 self.players[id] = player 788 self.players[id] = player
818 self.update_self_from_player(player) 789 self.update_self_from_player(player)
819 else: self.players[id] = player 790 else: self.players[id] = player
820 dont_send = 0 791 dont_send = 0
821 for m in self.ignore_id: 792 for m in self.ignore_id:
822 if m == id: dont_send=1 793 if m == id: dont_send=1
823 if dont_send != 1: self.on_player_event(mplay_event(PLAYER_UPDATE,self.players[id])) 794 if dont_send != 1: self.on_player_event(mplay_event(PLAYER_UPDATE, self.players[id]))
824 if xml_dom: xml_dom.unlink() 795
825 796 def on_password(self, id, msg, etreeEl):
826 def on_password(self, id, msg, xml_dom): 797 self.on_password_signal(etreeEl.get("signal"), etreeEl.get("type"),
827 signal = type = id = data = None 798 etreeEl.get("id"), etreeEl.get("data"))
828 id = xml_dom.getAttribute("id")
829 type = xml_dom.getAttribute("type")
830 signal = xml_dom.getAttribute("signal")
831 data = xml_dom.getAttribute("data")
832 self.on_password_signal( signal,type,id,data )
833 if xml_dom:
834 xml_dom.unlink()
835 799
836 def check_my_status(self): 800 def check_my_status(self):
837 status = self.get_status() 801 status = self.get_status()
838 if status == MPLAY_DISCONNECTING: self.do_disconnect() 802 if status == MPLAY_DISCONNECTING: self.do_disconnect()
839 803
841 """Establish a connection to a server while still using sendThread & recvThread for its 805 """Establish a connection to a server while still using sendThread & recvThread for its
842 communication.""" 806 communication."""
843 if self.is_connected(): 807 if self.is_connected():
844 self.log_msg( "Client is already connected to a server?!? Need to disconnect first." ) 808 self.log_msg( "Client is already connected to a server?!? Need to disconnect first." )
845 return 0 809 return 0
846 xml_dom = None
847 self.inbox = Queue.Queue(0) 810 self.inbox = Queue.Queue(0)
848 self.outbox = Queue.Queue(0) 811 self.outbox = Queue.Queue(0)
849 addressport_ar = addressport.split(":") 812 addressport_ar = addressport.split(":")
850 if len(addressport_ar) == 1: 813 if len(addressport_ar) == 1:
851 address = addressport_ar[0] 814 address = addressport_ar[0]
856 self.host_server = addressport 819 self.host_server = addressport
857 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 820 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
858 try: 821 try:
859 self.sock.connect((address,port)) 822 self.sock.connect((address,port))
860 # send client into with id=0 823 # send client into with id=0
861 self.sendMsg( self.sock, self.toxml("new") ) 824 outgoing = self.toxml('new')
862 data = self.recvMsg( self.sock ) 825 if iselement(outgoing): outgoing = tostring(outgoing)
826 self.sendMsg(self.sock, outgoing)
827 data = self.recvMsg(self.sock)
863 # get new id and group_id 828 # get new id and group_id
864 xml_dom = self.xml.parseXml(data) 829 el = fromstring(data)
865 xml_dom = xml_dom._get_documentElement() 830 self.id = el.get('id')
866 self.id = xml_dom.getAttribute("id") 831 self.group_id = el.get('group_id')
867 self.group_id = xml_dom.getAttribute("group_id") 832 if el.get('useCompression') == 'True':
868 if xml_dom.hasAttribute('useCompression') and xml_dom.getAttribute('useCompression') == 'True':
869 self.useCompression = True 833 self.useCompression = True
870 if xml_dom.hasAttribute('cmpType'): 834 if cmpBZ2 and el.get('cmpType') == 'bz2':
871 if cmpBZ2 and xml_dom.getAttribute('cmpType') == 'bz2': 835 self.compressionType = bz2
872 self.compressionType = bz2 836 elif cmpZLIB and el.get('cmpType') == 'zlib':
873 elif cmpZLIB and xml_dom.getAttribute('cmpType') == 'zlib': 837 self.compressionType = zlib
874 self.compressionType = zlib 838 else: self.compressionType = None
875 else: self.compressionType = None
876 else: self.compressionType = bz2
877 #send confirmation 839 #send confirmation
878 self.sendMsg( self.sock, self.toxml("new") ) 840 outgoing = self.toxml('new')
841 if iselement(outgoing): outgoing = tostring(outgoing)
842 self.sendMsg(self.sock, outgoing)
879 except Exception, e: 843 except Exception, e:
844 print e
880 self.log_msg(e) 845 self.log_msg(e)
881 if xml_dom: xml_dom.unlink()
882 return 0 846 return 0
883
884 # Start things rollings along 847 # Start things rollings along
885 self.initialize_threads() 848 self.initialize_threads()
886 self.on_mplay_event(mplay_event(MPLAY_CONNECTED)) 849 self.on_mplay_event(mplay_event(MPLAY_CONNECTED))
887 self.players[self.id] = (self.name, self.ip, self.id, 850 self.players[self.id] = (self.name, self.ip, self.id,
888 self.text_status, self.version, 851 self.text_status, self.version,
889 self.protocol_version, self.client_string, self.role) 852 self.protocol_version, self.client_string, self.role)
890 self.on_player_event(mplay_event(PLAYER_NEW,self.players[self.id])) 853 self.on_player_event(mplay_event(PLAYER_NEW,self.players[self.id]))
891 if xml_dom: xml_dom.unlink()
892 return 1 854 return 1
893 855
894 def start_disconnect(self): 856 def start_disconnect(self):
895 self.on_mplay_event(mplay_event(MPLAY_DISCONNECTING)) 857 self.on_mplay_event(mplay_event(MPLAY_DISCONNECTING))
896 self.outbox.put( self.toxml("del") ) 858 outgoing = self.toxml('del')
859 if iselement(outgoing): outgoing = tostring(outgoing)
860 self.outbox.put(outgoing)
897 ## Client Side Disconect Forced -- Snowdog 10-09-2003 861 ## Client Side Disconect Forced -- Snowdog 10-09-2003
898 #pause to allow GUI events time to sync. 862 #pause to allow GUI events time to sync.
899 time.sleep(1) 863 time.sleep(1)
900 self.do_disconnect() 864 self.do_disconnect()
901 865