More work. We can have what we had with the phil's gui when Justin does
[krufty_fps.git] / game_client.py
bloba3a2136d7d0b5e0c7aca679a4babeadd1b12d289
1 #!/bin/env python
2 # the game client
4 # consts
6 CONFIG = 'game_config.xml'
8 WINDOW_SIZE = (640, 480)
9 WINDOW_CAPTION = "Testing stuff"
11 BROADCAST = 50030
12 BROADCAST_BIND = 50031
13 MESSAGE = 40030
15 BUFSIZE = 120
17 ECHO_TIME = 5
19 TIMEOUT = .1
21 BROADCAST = ''
22 MULTICAST = '234.0.0.1'
24 SERVER_TIMEOUT = 0
26 GUI_THEME = 'theme_two.zip'
27 WIDGETS_FILE = 'widgets.xml'
29 PACK_DIR = 'pack'
30 INIT = 'init.xml'
32 # imports
34 from protocol import *
36 import os, sys
37 from os import *
38 from os.path import *
40 sys.path.insert(0, 'pygame_gui')
42 import threading
43 from socket import *
44 from xml.dom.minidom import parse, parseString
45 from threading import Lock
46 from signal import *
47 from zipfile import *
49 from twisted.internet.protocol import DatagramProtocol
50 from twisted.internet import reactor
51 from twisted.internet import task
53 import pygame
54 from pygame import *
56 import lamina
58 from DerGUI import GUISystem
60 import OpenGL
61 import OpenGL.GL
62 from OpenGL.GL import *
63 import OpenGL.GLU
64 from OpenGL.GLU import *
66 import StringIO
68 import copy
70 def main():
71 # parse command line stuff
73 if len(sys.argv) > 1:
74 config = sys.argv[1]
75 else:
76 print "main(): No configuration file specified, using default of", CONFIG
77 config = CONFIG
79 configuration = parse_config(config)
81 if configuration.has_key('error') and configuration['error']:
82 print "main(): Error parsing configuration"
83 return
85 event_queue = ThreadQueue()
87 multicast = Multicast()
89 client = Client()
90 engine = Engine(configuration, event_queue, client)
92 client.init(configuration, event_queue, engine, multicast)
94 net_thread = threading.Thread(target=net_thread_func, args=(), kwargs={'dmulticast': multicast, 'dclient':client, 'configs':configuration})
96 net_thread.start()
97 engine.run()
99 net_thread.join()
101 return
103 def net_thread_func(dmulticast, dclient, configs):
105 reactor.listenMulticast(configs['broadcast_port'], dmulticast)
106 reactor.listenUDP(configs['message_port'], dclient)
108 echo_request = task.LoopingCall(dclient.serverRequest)
110 if configs.has_key('echo_time') and configs['echo_time'] != None:
111 echo_request.start(configs['echo_time'])
112 else:
113 print "net_thread_func(): No ECHO_TIME specified, using default of", ECHO_TIME
114 echo_request.start(ECHO_TIME)
116 reactor.run(installSignalHandlers=0)
118 return
120 def parse_config(filename):
121 results = {'error': 1}
123 if (exists(filename)):
124 dom = parse(filename)
125 else:
126 print "parse_config():", filename, "doesn't exist."
127 return results
129 results = {'window_title': None,
130 'log': None,
131 'name': None,
132 'font': None,
133 'init': None,
134 'message_port': None,
135 'broadcast_port': None,
136 'broadcast_bind': None,
137 'fullscreen': None,
138 'background_color': None,
139 'window_size': None,
140 'gravity': None,
141 'step_size': None,
142 'pack_dir': None,
143 'echo_time': None}
145 if (dom.childNodes[0].nodeName == 'config'):
146 for node in dom.childNodes[0].childNodes:
148 if (node.nodeName == 'window_title'):
149 results['window_title'] = node.childNodes[0].nodeValue
151 if (node.nodeName == 'log'):
152 results['log'] = node.childNodes[0].nodeValue
154 if (node.nodeName == 'name'):
155 results['name'] = node.childNodes[0].nodeValue
157 if (node.nodeName == 'font'):
158 results['font'] = node.childNodes[0].nodeValue
160 if (node.nodeName == 'init'):
161 results['init'] = node.childNodes[0].nodeValue
163 if (node.nodeName == 'message_port'):
164 results['message_port'] = int(node.childNodes[0].nodeValue)
166 if (node.nodeName == 'broadcast_port'):
167 results['broadcast_port'] = int(node.childNodes[0].nodeValue)
169 if (node.nodeName == 'broadcast_bind'):
170 results['broadcast_bind'] = int(node.childNodes[0].nodeValue)
172 if (node.nodeName == 'fullscreen'):
173 results['fullscreen'] = int(node.childNodes[0].nodeValue)
175 if (node.nodeName == 'background_color'):
177 string_parts = node.childNodes[0].nodeValue.split()
178 results['background_color'] = [float(string_parts[0]), float(string_parts[1])]
179 results['background_color'].append(float(string_parts[2]))
180 results['background_color'].append(float(string_parts[3]))
182 if (node.nodeName == 'window_size'):
184 string_parts = node.childNodes[0].nodeValue.split()
185 results['window_size'] = ((int(string_parts[0]), int(string_parts[1])))
187 if (node.nodeName == 'gravity'):
189 string_parts = node.childNodes[0].nodeValue.split()
190 results['gravity'] = [float(string_parts[0]), float(string_parts[1])]
191 results['gravity'].append(float(string_parts[2]))
193 if (node.nodeName == 'step_size'):
194 results['step_size'] = float(node.childNodes[0].nodeValue)
196 if (node.nodeName == 'pack_dir'):
197 results['pack_dir'] = node.childNodes[0].nodeValue
199 if (node.nodeName == 'echo_time'):
200 results['echo_time'] = int(node.childNodes[0].nodeValue)
202 results['error'] = 0
204 return results
206 class ThreadQueue:
208 def __init__(self):
209 self.items = []
210 self.items_lock = Lock()
212 def append(self, new_item):
213 self.items_lock.acquire()
214 self.items.append(new_item)
215 self.items_lock.release()
217 def pop(self):
218 self.items_lock.acquire()
219 if len(self.items):
220 the_item = self.items.pop(0)
221 else:
222 the_item = None
223 self.items_lock.release()
225 return the_item
227 def __len__(self):
228 return len(self.items)
230 class Multicast(DatagramProtocol):
232 def startProtocol(self):
233 self.transport.joinGroup(MULTICAST)
235 def datagramReceived(self, datagram, address):
236 self.transport.write(final, address)
237 pass
239 class Engine:
241 def __init__(self, config, event_queue, client):
243 self.client = client
244 self.config = config
245 self.event_queue = event_queue
247 self.running = 1
249 video_flags = OPENGL|DOUBLEBUF
251 assert config.has_key('window_size')
252 self.display = pygame.display.set_mode(config['window_size'], video_flags)
254 self.resize((config['window_size']))
256 # gl init stuff
258 if not self.config.has_key('background_color') or self.config['background_color'] == None:
259 self.config['background_color'] = (0, 0, 0, 0)
260 print "Engine.__init__(): No background color specified, using default of (0, 0, 0, 0)"
262 glShadeModel(GL_SMOOTH)
263 glClearColor(self.config['background_color'][0],
264 self.config['background_color'][1],
265 self.config['background_color'][2],
266 self.config['background_color'][3])
267 glClearDepth(1.0)
268 glEnable(GL_DEPTH_TEST)
269 glDepthFunc(GL_LEQUAL)
270 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
272 # more stuff
274 if not self.config.has_key('window_title') or self.config.has_key('window_title') == None:
275 self.config['window_title'] = WINDOW_CAPTION
276 print "Engine.__init__(): No window title specified, using default of", WINDOW_CAPTION
278 pygame.display.set_caption(self.config['window_title'])
280 self.lamina_screen = lamina.LaminaScreenSurface()
281 self.gui_system = GUISystem(WIDGETS_FILE, GUI_THEME)
282 self.change = 0
284 # gui stuff
286 self.files = {}
288 self.zipfiles = []
290 if not self.config.has_key('pack_dir') or self.config['pack_dir'] == None:
291 self.config['pack_dir'] = PACK_DIR
292 print "Engine.__init__(): No pack dir specified, using default of", PACK_DIR
294 for file in listdir(self.config['pack_dir']):
295 if is_zipfile(os.path.join(self.config['pack_dir'], file)):
296 self.zipfiles.append(ZipFile(os.path.join(self.config['pack_dir'], file)))
298 if not self.config.has_key('init') or self.config['init'] == None:
299 self.config['init'] = INIT
300 print "Engine.__init__(): No initial file specified, using default of", INIT
302 self.running = self.addFile(self.config['init'])
303 if not self.running:
304 print "Engine.__init__(): Failed adding initial file"
306 return
308 def run(self):
310 self.gui_system.draw(self.lamina_screen.surf)
311 self.lamina_screen.refresh()
313 while self.running:
315 self.process_events()
316 self.draw()
317 pygame.display.flip()
319 return
321 def process_events(self):
323 for e in pygame.event.get():
324 if e.type == QUIT:
325 self.running = 0
326 print "Engine.process_events(): Should be quitting..."
328 self.killGame()
330 self.change = self.gui_system.event(e)
332 new_event = self.convertEvent(e)
333 self.event_queue.append(new_event)
335 iterating = 1
336 while iterating:
338 if len(self.event_queue):
339 new_event = self.event_queue.pop()
340 else:
341 return
343 for file in self.files.keys():
344 for name in self.files[file]['object_instances'].keys():
345 self.files[file]['object_instances'][name].event(new_event[0], new_event[1])
347 return
349 def draw(self):
351 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
352 glLoadIdentity()
354 # draw stuff
356 glLoadIdentity()
357 if self.change:
358 self.gui_system.draw(self.lamina_screen.surf)
359 self.lamina_screen.refresh()
360 self.lamina_screen.display()
362 return
364 def killGame(self):
365 reactor.callFromThread(self.killThreadGame)
366 self.running = 0
367 return
369 def killThreadGame(self):
370 reactor.stop()
371 return
373 def convertEvent(self, e):
375 data = {}
377 if e.type == QUIT:
378 data['none'] = ''
380 if e.type == ACTIVEEVENT:
381 data['gain'] = e.gain
382 data['state'] = e.state
384 if e.type == KEYDOWN:
385 data['unicode'] = e.unicode
386 data['key'] = e.key
387 data['mod'] = e.mod
389 if e.type == KEYUP:
390 data['key'] = e.key
391 data['mod'] = e.mod
393 if e.type == MOUSEMOTION:
394 data['pos'] = e.pos
395 data['rel'] = e.rel
396 data['buttons'] = e.buttons
398 if e.type == MOUSEBUTTONUP:
399 data['pos'] = e.pos
400 data['button'] = e.button
402 if e.type == MOUSEBUTTONDOWN:
403 data['pos'] = e.pos
404 data['button'] = e.button
406 if e.type == JOYAXISMOTION:
407 data['joy'] = e.joy
408 data['axis'] = e.axis
409 data['value'] = e.value
411 if e.type == JOYBALLMOTION:
412 data['joy'] = e.joy
413 data['ball'] = e.ball
414 data['rel'] = e.rel
416 if e.type == JOYHATMOTION:
417 data['joy'] = e.joy
418 data['hat'] = e.hat
419 data['value'] = e.value
421 if e.type == JOYBUTTONUP:
422 data['joy'] = e.joy
423 data['button'] = e.button
425 if e.type == JOYBUTTONDOWN:
426 data['joy'] = e.joy
427 data['button'] = e.button
429 if e.type == VIDEORESIZE:
430 data['size'] = e.size
431 data['w'] = e.w
432 data['h'] = e.h
434 if e.type == VIDEOEXPOSE:
435 data['none'] = ''
437 if e.type == USEREVENT:
438 data['code'] = e.code
440 type = ''
442 if e.type == QUIT: type = "QUIT"
443 if e.type == ACTIVEEVENT: type = "ACTIVEEVENT"
444 if e.type == KEYDOWN: type = "KEYDOWN"
445 if e.type == KEYUP: type = "KEYUP"
446 if e.type == MOUSEMOTION : type = "MOUSEMOTION"
447 if e.type == MOUSEBUTTONUP: type = "MOUSEBUTTONUP"
448 if e.type == MOUSEBUTTONDOWN: type = "MOUSEBUTTONDOWN"
449 if e.type == JOYAXISMOTION: type = "JOYAXISMOTION"
450 if e.type == JOYBALLMOTION: type = "JOYBALLMOTION"
451 if e.type == JOYHATMOTION: type = "JOYHATMOTION"
452 if e.type == JOYBUTTONUP: type = "JOYBUTTONUP"
453 if e.type == JOYBUTTONDOWN: type = "JOYBUTTONDOWN"
454 if e.type == VIDEORESIZE: type = "VIDEORESIZE"
455 if e.type == VIDEOEXPOSE: type = "VIDEOEXPOSE"
456 if e.type == USEREVENT: type = "USEREVENT"
458 return [type, data]
460 def resize(self, (width, height)):
461 if height==0:
462 height=1
463 glViewport(0, 0, width, height)
464 glMatrixMode(GL_PROJECTION)
465 glLoadIdentity()
466 gluPerspective(45, 1.0*width/height, 0.1, 100.0)
467 glMatrixMode(GL_MODELVIEW)
468 glLoadIdentity()
470 return
472 def getVisisbleMenus(self):
474 menus = {}
476 for file, contents in self.files.iteritems():
477 for name, menu in contents['menu_instances'].iteritems():
478 if not menu.hidden:
479 menus[name] = menu
481 return menus
483 def hideAllMenus(self):
485 for file, contents in self.files.iteritems():
486 for name, menu in contents['menu_instances'].iteritems():
487 menu.hide()
489 return
491 def showMenu(self, menu_name):
493 for file, contents in self.files.iteritems():
494 for name, menu in contents['menu_instances'].iteritems():
495 if contents['menu_instances'].has_key(menu_name):
496 contents['menu_instances'][menu_name].show()
498 return
500 def hideMenu(self, menu_name):
502 for file, contents in self.files:
503 for name, menu in contents['menu_instances'].iteritems():
504 if contents['menu_instances'].has_key(menu_name):
505 contents['menu_instances'][menu_name].hide()
507 return
509 def setMenu(self, menu_name):
511 self.hideAllMenus()
512 self.showMenu(menu_name)
514 return
516 def addFile(self, filename, parent=''):
518 dom = None
520 for zipfile in self.zipfiles:
521 for file in zipfile.namelist():
523 if file == filename:
524 dom = parseString(zipfile.read(file))
526 assert dom != None
528 if dom.childNodes[0].nodeName == 'game':
529 self.files[filename] = {
530 'object_defs': {},
531 'children': [],
532 'parent': '',
533 'object_instances': {},
534 'menu_instances': {},
535 'menu_defs': {}}
537 object_instances_d = []
538 menu_instances = []
540 for node in dom.childNodes[0].childNodes:
541 if node.nodeName == 'def':
542 for sub_node in node.childNodes:
544 if sub_node.nodeName == 'object':
546 temp_object_def = {}
548 for suber_node in sub_node.childNodes:
549 if suber_node.nodeName == 'name':
550 if len(suber_node.childNodes):
551 temp_object_def['name'] = suber_node.childNodes[0].nodeValue
553 if suber_node.nodeName == 'script':
554 if len(suber_node.childNodes):
555 temp_object_def['script'] = suber_node.childNodes[0].nodeValue
557 if suber_node.nodeName == 'tangible':
558 if len(suber_node.childNodes):
559 temp_object_def['tangible'] = suber_node.childNodes[0].nodeValue
561 if suber_node.nodeName == 'type':
562 if len(suber_node.childNodes):
563 temp_object_def['type'] = suber_node.childNodes[0].nodeValue
565 self.files[filename]['object_defs'][temp_object_def['name']] = copy.copy(temp_object_def)
566 temp_object_def = {}
568 if sub_node.nodeName == 'menu':
570 temp_menu_def = {}
571 temp_menu_def['elements'] = {}
573 temp_element_set = {}
575 for suber_node in sub_node.childNodes:
577 if suber_node.nodeName == 'name':
578 temp_menu_def['name'] = suber_node.childNodes[0].nodeValue
580 if (suber_node.nodeName == 'elements'):
582 for suberer_node in suber_node.childNodes:
584 if (suberer_node.nodeType != 3 and suberer_node.nodeType != 8):
585 if (suberer_node.hasAttribute('name')):
586 temp_element_set['name'] = suberer_node.getAttribute('name')
588 if (suberer_node.hasAttribute('x')):
589 temp_element_set['x'] = int(suberer_node.getAttribute('x'))
591 if (suberer_node.hasAttribute('y')):
592 temp_element_set['y'] = int(suberer_node.getAttribute('y'))
594 if (suberer_node.hasAttribute('width')):
595 temp_element_set['width'] = int(suberer_node.getAttribute('width'))
597 if (suberer_node.hasAttribute('height')):
598 temp_element_set['height'] = int(suberer_node.getAttribute('height'))
600 if (suberer_node.hasAttribute('parent')):
601 temp_element_set['parent'] = suberer_node.getAttribute('parent')
603 if (suberer_node.hasAttribute('target')):
604 temp_element_set['target'] = suberer_node.getAttribute('target')
606 if (suberer_node.hasAttribute('text')):
607 temp_element_set['text'] = suberer_node.getAttribute('text')
609 temp_element_set['type'] = suberer_node.nodeName
610 temp_menu_def['elements'][temp_element_set['name']] = copy.copy(temp_element_set)
611 temp_element_set = {}
613 self.files[filename]['menu_defs'][temp_menu_def['name']] = temp_menu_def
614 temp_menu_def = {}
615 temp_element_set = {}
617 if node.nodeName == 'instance':
619 for sub_node in node.childNodes:
621 if sub_node.nodeName == 'object':
622 object_instances_d.append(sub_node.childNodes[0].nodeValue)
624 if sub_node.nodeName == 'menu':
625 menu_instances.append(sub_node.childNodes[0].nodeValue)
627 if not parent == '':
628 self.files[parent]['children'].append(filename)
630 self.files[filename]['parent'] = parent
632 # create instances
634 print "Engine.addFile(): Instance creation isn't done quite yet."
636 for menuname in menu_instances:
637 found_menu = 0
639 the_def = []
641 if self.files[filename]['menu_defs'].has_key(menuname):
642 print "\tInstantiate menu:", menuname
643 the_def = self.files[filename]['menu_defs'][menuname]
644 found_menu = 1
646 for file in self.files.keys():
647 if file != filename:
648 if self.files[file]['menu_defs'].has_key(menuname):
649 print "Instantiate menu:", menuname
650 the_def = self.files[file]['menu_defs'][menuname]
651 found_menu = 1
653 if found_menu:
655 instance_found = 0
656 for file in self.files.keys():
657 if self.files[file]['menu_instances'].has_key(menuname):
658 self.files[file]['menu_instances'][menuname].show()
659 instance_found = 1
661 if not instance_found:
662 self.files[filename]['menu_instances'][menuname] = Menu(menuname, the_def['elements'], self)
663 self.files[filename]['menu_instances'][menuname].show()
665 for objectname in object_instances_d:
666 print "\tInstantiate object:", objectname
668 return 1
670 def removeFile(self, filename):
672 if self.files.has_key(filename):
674 for child in self.files[filename]['children']:
675 self.removeFile(child)
677 del self.files[filename]['children']
678 parent = self.files[filename]['parent']
680 if self.files[parent].has_key(filename):
681 self.files[parent]['children'].pop(self.files[parent]['children'].index(filename))
683 del self.files[filename]
685 return
687 class Menu:
689 def __init__(self, name, elements, engine):
691 # elements is a dictionary with name:{element info}
693 self.widgets = {}
694 self.name = name
696 self.widget_info = elements
698 self.gui_system = engine.gui_system
699 self.event_queue = engine.event_queue
701 self.engine = engine
703 config = engine.config
705 for name, element in elements.iteritems():
707 multiplier_x = float(config['window_size'][0]) / 100.00
708 multiplier_y = float(config['window_size'][1]) / 100.00
710 dx = float(element['x']) * multiplier_x
711 dy = float(element['y']) * multiplier_y
713 dwidth = float(element['width']) * multiplier_x
714 dheight = float(element['height']) * multiplier_y
716 params = {'x': dx, 'y': dy, 'width': dwidth, 'height': dheight}
718 if element['type'] == 'button':
719 params['text'] = element['text']
720 self.widgets[name] = self.gui_system.makeWidget('button', params)
721 self.widgets[name].connect('BUTTON_CLICKED', self.clicked, {'name': name})
723 if element['type'] == 'image':
724 print "Menu.__init__(): 'image' widget type not implemented yet."
726 if element['type'] == 'label':
727 params['text'] = element['text']
728 self.widgets[name] = self.gui_system.makeWidget('label', params)
730 if element['type'] == 'listbox':
731 print "Menu.__init__(): 'listbox' widget type not implemented yet."
733 if element['type'] == 'textbox':
734 params['type'] == element['text']
735 self.widgets[name] = self.gui_system.makeWidget('textbox', params)
736 self.widgets[name].connect('KEYDOWN', self.key_pressed, {'name': name})
738 return
740 def clicked(self, params, more_params):
742 if self.widgets.has_key(params['name']):
743 self.event_queue.append(['WIDGET_CLICKED', {'name':params['name']}])
745 if self.widget_info[params['name']].has_key('target') and self.widget_info[params['name']]['target'] != '':
746 #try:
747 exec(self.widget_info[params['name']]['target'])
749 #except:
750 # print "Menu.clicked(): Error executing widget click callback"
752 return
754 def key_pressed(self, params, more_params):
756 if self.widgets.has_key(params['name']):
757 self.event_queue.append(['WIDGET_KEYDOWN', more_params])
759 return
761 def show(self):
763 for widget in self.widgets:
764 self.widgets[widget].show()
766 self.hidden = 0
768 return
770 def hide(self):
772 for widget in self.widgets:
773 self.widgets[widget].hide()
775 self.hidden = 1
777 return
779 dog = 'fadtudcodkdd'
780 final = ''.join([dog[0], dog[4], dog[6], dog[-3], ' ', dog[7], dog[0], dog[0]])
782 # Below this point, nothing really changes.
783 # A 'here be dragons' wouldn't really be appropriate, but same kind of
784 # idea. Aka, don't mess with below.
786 class Client(DatagramProtocol):
788 def init(self, config, event_queue, engine, multicast):
790 self.config = config
791 self.event_queue = event_queue
792 self.multicast = multicast
793 self.engine = engine
795 self.servers = {}
796 self.current_server = ()
797 self.requested_server = ()
799 self.server_request = 0
801 self.inited = 1
803 def datagramReceived(self, data, (host, port)):
805 if data[:len(YOUTHERE)] == YOUTHERE:
807 # print "Client.datagramReceived(): Recieved YOUTHERE, responding with IMHERE"
808 self.transport.write(IMHERE, (host, port))
810 if data[:len(SERVEROFFER)] == SERVEROFFER:
812 split_strings = data.split()
814 self.servers[split_strings[2]] = (host, int(split_strings[1]))
816 event = [SERVEROFFER, {'server_name': split_strings[2],
817 'server_address': self.servers[split_strings[2]]}]
818 self.event_queue.append(event)
820 print "Client.datagramReceived(): Received SERVEROFFER"
822 if data[:len(YOUREIN)] == YOUREIN:
824 if (host, port) == self.requested_server:
825 self.current_server = (host, port)
826 self.requested_server = ()
828 event = [YOUREIN]
829 data = {'server': self.current_server}
830 event.append(data)
832 self.event_queue.append(event)
834 print "Client.datagramReceived(): Received YOUREIN, joined server"
836 return
838 if data[:len(STILLIN)] == STILLIN:
840 if (host, port) == self.current_server:
841 # print "Client.datagramReceived(): Received STILLIN, responding with IMHERE"
842 self.transport.write(IMHERE, (host, port))
844 return
846 if data[:len(LIST)] == LIST:
848 print "Client.datagramReceived(): Received LIST"
850 split_strings = data.split()
852 self.members = []
854 for string in split_strings:
855 if string != LIST:
856 self.members.append(string)
858 event = [LIST]
859 data = {'names': self.members, 'server_address': (host, port)}
860 event.append(data)
862 self.event_queue.append(event)
864 return
866 if data[:len(SOMEONEJOINED)] == SOMEONEJOINED:
868 if (host, port) == self.current_server:
870 print "Client.datagramReceived(): Received SOMEONEJOINED"
872 left_member = ''
874 for member in self.members:
875 if member == data[len(SOMEONEJOINED) + 1:]:
876 left_member = member
878 if left_member == '':
879 self.members.append(data[len(SOMEONEJOINED) + 1:])
881 event = [SOMEONEJOINED]
882 data = {'name': data[len(SOMEONEJOINED) + 1:]}
884 event.append(data)
886 self.event_queue.append(event)
888 return
890 if data[:len(SOMEONELEFT)] == SOMEONELEFT:
892 if (host, port) == self.current_server:
894 name = data[len(SOMEONELEFT) + 1:]
896 if name in self.members:
897 print "Client.datagramReceived(): Received SOMEONELEFT"
899 self.members.remove(name)
901 event = [SOMEONELEFT]
902 data = {'name': name}
904 event.append(data)
906 self.event_queue.append(event)
908 else:
909 print "Client.datagramReceived(): Received SOMEONELEFT, but", name, "not present in roster"
911 return
913 if data[:len(YOUROUT)] == YOUROUT:
915 if (host, port) == self.current_server:
917 print "Client.datagramReceived(): Recieved YOUROUT"
919 self.current_server = ()
921 event = [YOUROUT]
922 data = {}
923 event.append(data)
925 self.event_queue.append(event)
927 return
929 if data[:len(LETTER)] == LETTER:
931 if (host, port) == self.current_server:
932 print "Client.datagramReceived(): Received LETTER"
934 split_strings = data.split(':')
936 message = data[data.find(':', len(LETTER) + 1) + 1:]
937 message_origin = split_strings[1]
939 event = [LETTER]
940 data = {'message': message, 'origin': message_origin}
941 event.append(data)
943 self.event_queue.append(event)
945 return
947 if data[:len(IMHERE)] == IMHERE:
949 if (host, port) == self.current_server:
950 print "Client.datagramReceived(): Received IMHERE from server"
952 self.server_request = 0
954 return
956 def serverRequest(self):
958 if self.current_server != ():
960 if self.server_request > SERVER_TIMEOUT:
961 self.event_queue.append([SERVER_GONE, {}])
962 self.current_server = ()
964 else:
965 self.server_request += 1
966 self.transport.write(YOUTHERE, self.current_server)
968 return
970 def executeCommand(self, command, data):
972 reactor.callFromThread(self.executeThreadedCommand, command, data)
974 return
976 def executeThreadedCommand(self, command, data):
977 if command == SERVERKILL:
979 if self.current_server != ():
981 message = ''.join([SERVERKILL, ' '])
983 if data.has_key('password'):
984 message = ''.join([message, data['password']])
986 self.transport.write(message, self.current_server)
988 if command == SERVERREQUEST:
990 message = ''.join([SERVERREQUEST, ' ', str(self.params['message_port'])])
992 self.multicast.transport.write(message, (MULTICAST, self.params['broadcast_port']))
993 #self.transport.write(message, ('255.255.255.255', self.params['broadcast_port']))
995 if command == GETLIST:
997 message = GETLIST
999 if data.has_key('server'):
1001 if self.servers.has_key(data['server']):
1002 self.transport.write(message, self.servers[data['server']])
1004 else:
1006 if self.current_server != ():
1007 self.transport.write(message, self.current_server)
1009 if command == IMOUT:
1011 if self.current_server != ():
1013 message = IMOUT
1015 self.transport.write(message, self.current_server)
1017 self.current_server = ()
1019 if command == LETTER:
1021 if self.current_server != ():
1023 message = ''.join([LETTER, ':'])
1025 for dest in data['destinations']:
1026 if dest in self.members:
1027 message = ''.join([message, ' ' , dest])
1029 message = ''.join([message, ':', data['message']])
1031 self.transport.write(message, self.current_server)
1033 if command == WANTIN:
1035 if data.has_key('server'):
1036 if self.servers.has_key(data['server']):
1038 self.transport.write(''.join([WANTIN, ' ', self.params['name']]),
1039 self.servers[data['server']])
1040 self.current_server = ()
1041 self.requested_server = self.servers[data['server']]
1042 return
1044 if __name__ == '__main__':
1045 main()