Mercurial > traipse_dev
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 + "'" + e | 576 name = b + "'" + 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 |