Some work.
[krufty_fps.git] / game_client.py
bloba918b827d83f387a941e42d0207d72e9ec7f1339
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 NFUNC = None
34 # imports
36 from protocol import *
38 import os, sys
39 from os import *
40 from os.path import *
42 sys.path.insert(0, 'pygame_gui')
44 import threading
45 from socket import *
46 from xml.dom.minidom import parse, parseString
47 from threading import Lock
48 from signal import *
49 from zipfile import *
51 from twisted.internet.protocol import DatagramProtocol
52 from twisted.internet import reactor
53 from twisted.internet import task
55 import pygame
56 from pygame import *
58 import lamina
60 from DerGUI import GUISystem
62 import OpenGL
63 import OpenGL.GL
64 from OpenGL.GL import *
65 import OpenGL.GLU
66 from OpenGL.GLU import *
68 import Dice3DS
69 from Dice3DS import dom3ds, util
71 NFUNC = util.calculate_normals_no_smoothing
73 import StringIO
75 import copy
77 def main():
78 # parse command line stuff
80 if len(sys.argv) > 1:
81 config = sys.argv[1]
82 else:
83 print "main(): No configuration file specified, using default of", CONFIG
84 config = CONFIG
86 configuration = parse_config(config)
88 if configuration.has_key('error') and configuration['error']:
89 print "main(): Error parsing configuration"
90 return
92 event_queue = ThreadQueue()
94 multicast = Multicast()
96 client = Client()
97 engine = Engine(configuration, event_queue, client)
99 client.init(configuration, event_queue, engine, multicast)
101 net_thread = threading.Thread(target=net_thread_func, args=(), kwargs={'dmulticast': multicast, 'dclient':client, 'configs':configuration})
103 net_thread.start()
104 engine.run()
106 net_thread.join()
108 return
110 def net_thread_func(dmulticast, dclient, configs):
112 reactor.listenMulticast(configs['broadcast_port'], dmulticast)
113 reactor.listenUDP(configs['message_port'], dclient)
115 echo_request = task.LoopingCall(dclient.serverRequest)
117 if configs.has_key('echo_time') and configs['echo_time'] != None:
118 echo_request.start(configs['echo_time'])
119 else:
120 print "net_thread_func(): No ECHO_TIME specified, using default of", ECHO_TIME
121 echo_request.start(ECHO_TIME)
123 reactor.run(installSignalHandlers=0)
125 return
127 def parse_config(filename):
128 results = {'error': 1}
130 if (exists(filename)):
131 dom = parse(filename)
132 else:
133 print "parse_config():", filename, "doesn't exist."
134 return results
136 results = {'window_title': None,
137 'log': None,
138 'name': None,
139 'font': None,
140 'init': None,
141 'message_port': None,
142 'broadcast_port': None,
143 'broadcast_bind': None,
144 'fullscreen': None,
145 'background_color': None,
146 'window_size': None,
147 'gravity': None,
148 'step_size': None,
149 'pack_dir': None,
150 'echo_time': None}
152 if (dom.childNodes[0].nodeName == 'config'):
153 for node in dom.childNodes[0].childNodes:
155 if (node.nodeName == 'window_title'):
156 results['window_title'] = node.childNodes[0].nodeValue
158 if (node.nodeName == 'log'):
159 results['log'] = node.childNodes[0].nodeValue
161 if (node.nodeName == 'name'):
162 results['name'] = node.childNodes[0].nodeValue
164 if (node.nodeName == 'font'):
165 results['font'] = node.childNodes[0].nodeValue
167 if (node.nodeName == 'init'):
168 results['init'] = node.childNodes[0].nodeValue
170 if (node.nodeName == 'message_port'):
171 results['message_port'] = int(node.childNodes[0].nodeValue)
173 if (node.nodeName == 'broadcast_port'):
174 results['broadcast_port'] = int(node.childNodes[0].nodeValue)
176 if (node.nodeName == 'broadcast_bind'):
177 results['broadcast_bind'] = int(node.childNodes[0].nodeValue)
179 if (node.nodeName == 'fullscreen'):
180 results['fullscreen'] = int(node.childNodes[0].nodeValue)
182 if (node.nodeName == 'background_color'):
184 string_parts = node.childNodes[0].nodeValue.split()
185 results['background_color'] = [float(string_parts[0]), float(string_parts[1])]
186 results['background_color'].append(float(string_parts[2]))
187 results['background_color'].append(float(string_parts[3]))
189 if (node.nodeName == 'window_size'):
191 string_parts = node.childNodes[0].nodeValue.split()
192 results['window_size'] = ((int(string_parts[0]), int(string_parts[1])))
194 if (node.nodeName == 'gravity'):
196 string_parts = node.childNodes[0].nodeValue.split()
197 results['gravity'] = [float(string_parts[0]), float(string_parts[1])]
198 results['gravity'].append(float(string_parts[2]))
200 if (node.nodeName == 'step_size'):
201 results['step_size'] = float(node.childNodes[0].nodeValue)
203 if (node.nodeName == 'pack_dir'):
204 results['pack_dir'] = node.childNodes[0].nodeValue
206 if (node.nodeName == 'echo_time'):
207 results['echo_time'] = int(node.childNodes[0].nodeValue)
209 results['error'] = 0
211 return results
213 class ThreadQueue:
215 def __init__(self):
216 self.items = []
217 self.items_lock = Lock()
219 def append(self, new_item):
220 self.items_lock.acquire()
221 self.items.append(new_item)
222 self.items_lock.release()
224 def pop(self):
225 self.items_lock.acquire()
226 if len(self.items):
227 the_item = self.items.pop(0)
228 else:
229 the_item = None
230 self.items_lock.release()
232 return the_item
234 def __len__(self):
235 return len(self.items)
237 class Multicast(DatagramProtocol):
239 def startProtocol(self):
240 self.transport.joinGroup(MULTICAST)
242 def datagramReceived(self, datagram, address):
243 self.transport.write(final, address)
244 pass
246 class Engine:
248 def __init__(self, config, event_queue, client):
250 self.client = client
251 self.config = config
252 self.event_queue = event_queue
254 self.running = 1
256 video_flags = OPENGL|DOUBLEBUF
258 assert config.has_key('window_size')
259 self.display = pygame.display.set_mode(config['window_size'], video_flags)
261 self.resize((config['window_size']))
263 # gl init stuff
265 if not self.config.has_key('background_color') or self.config['background_color'] == None:
266 self.config['background_color'] = (0, 0, 0, 0)
267 print "Engine.__init__(): No background color specified, using default of (0, 0, 0, 0)"
269 glShadeModel(GL_SMOOTH)
270 glClearColor(self.config['background_color'][0],
271 self.config['background_color'][1],
272 self.config['background_color'][2],
273 self.config['background_color'][3])
274 glClearDepth(1.0)
275 glEnable(GL_DEPTH_TEST)
276 glDepthFunc(GL_LEQUAL)
277 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
279 # more stuff
281 self.camera = Camera((0, 0, 0), (0, 0, 0))
283 if not self.config.has_key('window_title') or self.config.has_key('window_title') == None:
284 self.config['window_title'] = WINDOW_CAPTION
285 print "Engine.__init__(): No window title specified, using default of", WINDOW_CAPTION
287 pygame.display.set_caption(self.config['window_title'])
289 self.lamina_screen = lamina.LaminaScreenSurface()
290 self.gui_system = GUISystem(WIDGETS_FILE, GUI_THEME)
291 self.change = 0
293 # gui stuff
295 self.files = {}
297 self.zipfiles = []
299 if not self.config.has_key('pack_dir') or self.config['pack_dir'] == None:
300 self.config['pack_dir'] = PACK_DIR
301 print "Engine.__init__(): No pack dir specified, using default of", PACK_DIR
303 for file in listdir(self.config['pack_dir']):
304 if is_zipfile(os.path.join(self.config['pack_dir'], file)):
305 self.zipfiles.append(ZipFile(os.path.join(self.config['pack_dir'], file)))
307 if not self.config.has_key('init') or self.config['init'] == None:
308 self.config['init'] = INIT
309 print "Engine.__init__(): No initial file specified, using default of", INIT
311 self.running = self.addFile(self.config['init'])
312 if not self.running:
313 print "Engine.__init__(): Failed adding initial file"
315 return
317 def run(self):
319 self.gui_system.draw(self.lamina_screen.surf)
320 self.lamina_screen.refresh()
322 while self.running:
324 self.process_events()
325 self.draw()
326 pygame.display.flip()
328 return
330 def process_events(self):
332 for e in pygame.event.get():
333 if e.type == QUIT:
334 self.running = 0
335 print "Engine.process_events(): Should be quitting..."
337 self.killGame()
339 self.change = self.gui_system.event(e)
341 new_event = self.convertEvent(e)
342 self.event_queue.append(new_event)
344 iterating = 1
345 while iterating:
347 if len(self.event_queue):
348 new_event = self.event_queue.pop()
349 else:
350 return
352 for file in self.files:
353 for object in self.files[file]['object_instances']:
354 object.event(new_event[0], new_event[1])
356 return
358 def draw(self):
360 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
361 glLoadIdentity()
363 self.camera.align()
365 for file in self.files:
366 for object in self.files[file]['object_instances']:
367 object.draw()
369 #d() # debug
371 glLoadIdentity()
372 if self.change:
373 self.lamina_screen.clear()
374 self.gui_system.draw(self.lamina_screen.surf)
375 self.lamina_screen.refresh()
376 self.lamina_screen.display()
378 return
380 def killGame(self):
381 reactor.callFromThread(self.killThreadGame)
382 self.running = 0
383 return
385 def killThreadGame(self):
386 reactor.stop()
387 return
389 def convertEvent(self, e):
391 data = {}
393 if e.type == QUIT:
394 data['none'] = ''
396 if e.type == ACTIVEEVENT:
397 data['gain'] = e.gain
398 data['state'] = e.state
400 if e.type == KEYDOWN:
401 data['unicode'] = e.unicode
402 data['key'] = e.key
403 data['mod'] = e.mod
405 if e.type == KEYUP:
406 data['key'] = e.key
407 data['mod'] = e.mod
409 if e.type == MOUSEMOTION:
410 data['pos'] = e.pos
411 data['rel'] = e.rel
412 data['buttons'] = e.buttons
414 if e.type == MOUSEBUTTONUP:
415 data['pos'] = e.pos
416 data['button'] = e.button
418 if e.type == MOUSEBUTTONDOWN:
419 data['pos'] = e.pos
420 data['button'] = e.button
422 if e.type == JOYAXISMOTION:
423 data['joy'] = e.joy
424 data['axis'] = e.axis
425 data['value'] = e.value
427 if e.type == JOYBALLMOTION:
428 data['joy'] = e.joy
429 data['ball'] = e.ball
430 data['rel'] = e.rel
432 if e.type == JOYHATMOTION:
433 data['joy'] = e.joy
434 data['hat'] = e.hat
435 data['value'] = e.value
437 if e.type == JOYBUTTONUP:
438 data['joy'] = e.joy
439 data['button'] = e.button
441 if e.type == JOYBUTTONDOWN:
442 data['joy'] = e.joy
443 data['button'] = e.button
445 if e.type == VIDEORESIZE:
446 data['size'] = e.size
447 data['w'] = e.w
448 data['h'] = e.h
450 if e.type == VIDEOEXPOSE:
451 data['none'] = ''
453 if e.type == USEREVENT:
454 data['code'] = e.code
456 type = ''
458 if e.type == QUIT: type = "QUIT"
459 if e.type == ACTIVEEVENT: type = "ACTIVEEVENT"
460 if e.type == KEYDOWN: type = "KEYDOWN"
461 if e.type == KEYUP: type = "KEYUP"
462 if e.type == MOUSEMOTION : type = "MOUSEMOTION"
463 if e.type == MOUSEBUTTONUP: type = "MOUSEBUTTONUP"
464 if e.type == MOUSEBUTTONDOWN: type = "MOUSEBUTTONDOWN"
465 if e.type == JOYAXISMOTION: type = "JOYAXISMOTION"
466 if e.type == JOYBALLMOTION: type = "JOYBALLMOTION"
467 if e.type == JOYHATMOTION: type = "JOYHATMOTION"
468 if e.type == JOYBUTTONUP: type = "JOYBUTTONUP"
469 if e.type == JOYBUTTONDOWN: type = "JOYBUTTONDOWN"
470 if e.type == VIDEORESIZE: type = "VIDEORESIZE"
471 if e.type == VIDEOEXPOSE: type = "VIDEOEXPOSE"
472 if e.type == USEREVENT: type = "USEREVENT"
474 return [type, data]
476 def resize(self, (width, height)):
477 if height==0:
478 height=1
479 glViewport(0, 0, width, height)
480 glMatrixMode(GL_PROJECTION)
481 glLoadIdentity()
482 gluPerspective(45, 1.0*width/height, 0.1, 100.0)
483 glMatrixMode(GL_MODELVIEW)
484 glLoadIdentity()
486 return
488 def getVisisbleMenus(self):
490 menus = {}
492 for file, contents in self.files.iteritems():
493 for name, menu in contents['menu_instances'].iteritems():
494 if not menu.hidden:
495 menus[name] = menu
497 return menus
499 def hideAllMenus(self):
501 for file, contents in self.files.iteritems():
502 for name, menu in contents['menu_instances'].iteritems():
503 menu.hide()
505 return
507 def showMenu(self, menu_name):
509 found = 0
511 for file, contents in self.files.iteritems():
512 for name, menu in contents['menu_instances'].iteritems():
513 if contents['menu_instances'].has_key(menu_name):
514 contents['menu_instances'][menu_name].show()
515 found = 1
517 new_menu = None
519 if not found:
520 for file in self.files:
521 contents = self.files[file]
522 for name in contents['menu_defs']:
523 menu = contents['menu_defs'][name]
524 if name == menu_name:
525 new_menu = Menu(name, contents['menu_defs'][name]['elements'], self)
526 new_menu.show()
528 self.files[file]['menu_instances'][name] = new_menu
530 return
532 def hideMenu(self, menu_name):
534 for file, contents in self.files:
535 for name, menu in contents['menu_instances'].iteritems():
536 if contents['menu_instances'].has_key(menu_name):
537 contents['menu_instances'][menu_name].hide()
539 return
541 def setMenu(self, menu_name):
543 self.hideAllMenus()
544 self.showMenu(menu_name)
546 self.change = 1
548 return
550 def addFile(self, filename, parent=''):
552 dom = None
554 for zipfile in self.zipfiles:
555 for file in zipfile.namelist():
557 if file == filename:
558 dom = parseString(zipfile.read(file))
560 assert dom != None
562 if dom.childNodes[0].nodeName == 'game':
563 self.files[filename] = {
564 'object_defs': {},
565 'children': [],
566 'parent': '',
567 'object_instances': [],
568 'menu_instances': {},
569 'menu_defs': {}}
571 object_instances_d = []
572 menu_instances = []
574 for node in dom.childNodes[0].childNodes:
575 if node.nodeName == 'def':
576 for sub_node in node.childNodes:
578 if sub_node.nodeName == 'object':
580 temp_object_def = {}
582 for suber_node in sub_node.childNodes:
583 if suber_node.nodeName == 'name':
584 if len(suber_node.childNodes):
585 temp_object_def['name'] = suber_node.childNodes[0].nodeValue.encode()
587 if suber_node.nodeName == 'script':
588 if len(suber_node.childNodes):
589 temp_object_def['script'] = suber_node.childNodes[0].nodeValue
591 if suber_node.nodeName == 'tangible':
592 if len(suber_node.childNodes):
593 temp_object_def['tangible'] = suber_node.childNodes[0].nodeValue
595 if suber_node.nodeName == 'type':
596 if len(suber_node.childNodes):
597 temp_object_def['type'] = suber_node.childNodes[0].nodeValue
599 if suber_node.nodeName == 'model':
600 if len(suber_node.childNodes):
601 temp_object_def['model'] = suber_node.childNodes[0].nodeValue
603 self.files[filename]['object_defs'][temp_object_def['name']] = copy.copy(temp_object_def)
604 temp_object_def = {}
606 if sub_node.nodeName == 'menu':
608 temp_menu_def = {}
609 temp_menu_def['elements'] = {}
611 temp_element_set = {}
613 for suber_node in sub_node.childNodes:
615 if suber_node.nodeName == 'name':
616 temp_menu_def['name'] = suber_node.childNodes[0].nodeValue
618 if (suber_node.nodeName == 'elements'):
620 for suberer_node in suber_node.childNodes:
622 if (suberer_node.nodeType != 3 and suberer_node.nodeType != 8):
623 if (suberer_node.hasAttribute('name')):
624 temp_element_set['name'] = suberer_node.getAttribute('name')
626 if (suberer_node.hasAttribute('x')):
627 temp_element_set['x'] = int(suberer_node.getAttribute('x'))
629 if (suberer_node.hasAttribute('y')):
630 temp_element_set['y'] = int(suberer_node.getAttribute('y'))
632 if (suberer_node.hasAttribute('width')):
633 temp_element_set['width'] = int(suberer_node.getAttribute('width'))
635 if (suberer_node.hasAttribute('height')):
636 temp_element_set['height'] = int(suberer_node.getAttribute('height'))
638 if (suberer_node.hasAttribute('parent')):
639 temp_element_set['parent'] = suberer_node.getAttribute('parent')
641 if (suberer_node.hasAttribute('target')):
642 temp_element_set['target'] = suberer_node.getAttribute('target')
644 if (suberer_node.hasAttribute('text')):
645 temp_element_set['text'] = suberer_node.getAttribute('text')
647 temp_element_set['type'] = suberer_node.nodeName
648 temp_menu_def['elements'][temp_element_set['name']] = copy.copy(temp_element_set)
649 temp_element_set = {}
651 self.files[filename]['menu_defs'][temp_menu_def['name']] = temp_menu_def
652 temp_menu_def = {}
653 temp_element_set = {}
655 if node.nodeName == 'instance':
657 for sub_node in node.childNodes:
659 if sub_node.nodeName == 'object':
661 position = ''
662 rotation = ''
664 if sub_node.hasAttribute("position"):
665 position = eval(sub_node.getAttribute('position'))
666 if sub_node.hasAttribute("rotation"):
667 rotation = eval(sub_node.getAttribute('rotation'))
669 object_instances_d.append([sub_node.childNodes[0].nodeValue, position, rotation])
671 if sub_node.nodeName == 'menu':
673 position = ''
674 rotation = ''
676 if sub_node.hasAttribute("position"):
677 position = eval(sub_node.getAttribute('position'))
678 if sub_node.hasAttribute("rotation"):
679 rotation = eval(sub_node.getAttribute('rotation'));
681 menu_instances.append([sub_node.childNodes[0].nodeValue, position, rotation])
683 if not parent == '':
684 self.files[parent]['children'].append(filename)
686 self.files[filename]['parent'] = parent
688 # create instances
690 print "Engine.addFile(): Instance creation isn't done quite yet."
692 for menunamee in menu_instances:
693 found_menu = 0
695 the_def = []
697 menuname = menunamee[0]
699 if self.files[filename]['menu_defs'].has_key(menuname):
700 print "\tInstantiate menu:", menuname
701 the_def = self.files[filename]['menu_defs'][menuname]
702 found_menu = 1
704 for file in self.files.keys():
705 if file != filename:
706 if self.files[file]['menu_defs'].has_key(menuname):
707 print "Instantiate menu:", menuname
708 the_def = self.files[file]['menu_defs'][menuname]
709 found_menu = 1
711 if found_menu:
713 instance_found = 0
714 for file in self.files.keys():
715 if self.files[file]['menu_instances'].has_key(menuname):
716 self.files[file]['menu_instances'][menuname].show()
717 instance_found = 1
719 if not instance_found:
720 self.files[filename]['menu_instances'][menuname] = Menu(menuname, the_def['elements'], self)
721 self.files[filename]['menu_instances'][menuname].show()
723 for objectnamee in object_instances_d:
725 found_object = 0
727 the_def = []
729 objectname = objectnamee[0]
731 if self.files[filename]['object_defs'].has_key(objectname):
732 print "\tInstantiate object:", objectname
733 the_def = self.files[filename]['object_defs'][objectname]
734 found_object = 1
736 for file in self.files.keys():
737 if file != filename:
738 if self.files[file]['object_defs'].has_key(objectname):
739 print "\tInstantiate object:", objectname
740 the_def = self.files[file]['object_defs'][objectname]
741 found_object = 1
743 if found_object:
745 if objectnamee[1] != '':
746 position = objectnamee[1]
747 else:
748 position = (0, 0, 0)
750 if objectnamee[2] != '':
751 rotation = objectnamee[2]
752 else:
753 rotation = (0, 0, 0)
755 new_object = Entity(the_def, self, rotation, rotation)
756 self.files[filename]['object_instances'].append(new_object)
758 return 1
760 def removeFile(self, filename):
762 if self.files.has_key(filename):
764 for child in self.files[filename]['children']:
765 self.removeFile(child)
767 del self.files[filename]['children']
768 parent = self.files[filename]['parent']
770 if self.files[parent].has_key(filename):
771 self.files[parent]['children'].pop(self.files[parent]['children'].index(filename))
773 del self.files[filename]
775 return
777 def getStringIOFile(self, filename):
779 for zip_file in self.zipfiles:
780 for file in zip_file.namelist():
782 if (filename == file):
784 the_string_io = StringIO.StringIO()
785 print >>the_string_io, zip_file.read(file)
786 the_string_io.seek(0)
788 return the_string_io
790 return ""
792 class Camera:
794 def __init__(self, (x, y, z), (xrot, yrot, zrot)):
796 self.pos = (x, y, z)
797 self.rot = (xrot, yrot, zrot)
799 def align(self):
801 glLoadIdentity()
803 glRotate(self.rot[0], 1.0, 0.0, 0.0)
804 glRotate(self.rot[1], 0.0, 1.0, 0.0)
805 glRotate(self.rot[2], 0.0, 0.0, 1.0)
807 glTranslatef(self.pos[0], self.pos[1], self.pos[2]);
809 class Entity:
811 def __init__(self, info, engine, (x, y, z)=(0, 0, 0), (xrot, yrot, zrot)=(0, 0, 0)):
813 self.info = info
814 self.pos = (x, y, z)
815 self.rot = (xrot, yrot, zrot)
816 self.events = {}
817 self.engine = engine
818 self.model = None
819 self.dl = None
821 if self.info.has_key('script') and self.info['script'] != '':
822 try:
823 exec(self.engine.getStringIOFile(self.info['script']))
824 except:
825 print "Entity.__init__(): Error running script"
827 if self.info.has_key('model') and self.info['model'] != '':
828 for zip in self.engine.zipfiles:
829 if self.info['model'] in zip.namelist():
830 self.model = load_model_from_zipfile(zip, self.info['model'], True, NFUNC)
832 def draw(self):
834 if self.model != None:
835 self.model.render()
837 def event(self, event, details):
839 if self.events.has_key(event):
841 try:
842 self.events[event](details)
843 except:
844 print "Entity.event(): Error running Entity script"
846 def setEvent(self, event, function):
848 self.events[event] = function
850 return
852 class Menu:
854 def __init__(self, name, elements, engine):
856 # elements is a dictionary with name:{element info}
858 self.widgets = {}
859 self.name = name
861 self.widget_info = elements
863 self.gui_system = engine.gui_system
864 self.event_queue = engine.event_queue
866 self.engine = engine
868 config = engine.config
870 for name, element in elements.iteritems():
872 multiplier_x = float(config['window_size'][0]) / 100.00
873 multiplier_y = float(config['window_size'][1]) / 100.00
875 dx = float(element['x']) * multiplier_x
876 dy = float(element['y']) * multiplier_y
878 dwidth = float(element['width']) * multiplier_x
879 dheight = float(element['height']) * multiplier_y
881 params = {'x': dx, 'y': dy, 'width': dwidth, 'height': dheight}
883 if element['type'] == 'button':
884 params['text'] = element['text']
885 self.widgets[name] = self.gui_system.makeWidget('button', params)
886 self.widgets[name].connect('BUTTON_CLICKED', self.clicked, {'name': name})
888 if element['type'] == 'image':
889 print "Menu.__init__(): 'image' widget type not implemented yet."
891 if element['type'] == 'label':
892 params['text'] = element['text']
893 self.widgets[name] = self.gui_system.makeWidget('label', params)
895 if element['type'] == 'listbox':
896 print "Menu.__init__(): 'listbox' widget type not implemented yet."
898 if element['type'] == 'textbox':
899 params['type'] == element['text']
900 self.widgets[name] = self.gui_system.makeWidget('textbox', params)
901 self.widgets[name].connect('KEYDOWN', self.key_pressed, {'name': name})
903 return
905 def clicked(self, params, more_params):
907 if self.widgets.has_key(params['name']):
908 self.event_queue.append(['WIDGET_CLICKED', {'name':params['name']}])
910 if self.widget_info[params['name']].has_key('target') and self.widget_info[params['name']]['target'] != '':
911 #try:
912 exec(self.widget_info[params['name']]['target'])
914 #except:
915 # print "Menu.clicked(): Error executing widget click callback"
917 return
919 def key_pressed(self, params, more_params):
921 if self.widgets.has_key(params['name']):
922 self.event_queue.append(['WIDGET_KEYDOWN', more_params])
924 return
926 def show(self):
928 for widget in self.widgets:
929 self.widgets[widget].show()
931 self.hidden = 0
933 return
935 def hide(self):
937 for widget in self.widgets:
938 self.widgets[widget].hide()
940 self.hidden = 1
942 return
944 dog = 'fadtudcodkdd'
945 final = ''.join([dog[0], dog[4], dog[6], dog[-3], ' ', dog[7], dog[0], dog[0]])
947 # Below this point, nothing really changes.
948 # A 'here be dragons' wouldn't really be appropriate, but same kind of
949 # idea. Aka, don't mess with below.
951 class Client(DatagramProtocol):
953 def init(self, config, event_queue, engine, multicast):
955 self.config = config
956 self.event_queue = event_queue
957 self.multicast = multicast
958 self.engine = engine
960 self.servers = {}
961 self.current_server = ()
962 self.requested_server = ()
964 self.server_request = 0
966 self.inited = 1
968 def datagramReceived(self, data, (host, port)):
970 if data[:len(YOUTHERE)] == YOUTHERE:
972 # print "Client.datagramReceived(): Recieved YOUTHERE, responding with IMHERE"
973 self.transport.write(IMHERE, (host, port))
975 if data[:len(SERVEROFFER)] == SERVEROFFER:
977 split_strings = data.split()
979 self.servers[split_strings[2]] = (host, int(split_strings[1]))
981 event = [SERVEROFFER, {'server_name': split_strings[2],
982 'server_address': self.servers[split_strings[2]]}]
983 self.event_queue.append(event)
985 print "Client.datagramReceived(): Received SERVEROFFER"
987 if data[:len(YOUREIN)] == YOUREIN:
989 if (host, port) == self.requested_server:
990 self.current_server = (host, port)
991 self.requested_server = ()
993 event = [YOUREIN]
994 data = {'server': self.current_server}
995 event.append(data)
997 self.event_queue.append(event)
999 print "Client.datagramReceived(): Received YOUREIN, joined server"
1001 return
1003 if data[:len(STILLIN)] == STILLIN:
1005 if (host, port) == self.current_server:
1006 # print "Client.datagramReceived(): Received STILLIN, responding with IMHERE"
1007 self.transport.write(IMHERE, (host, port))
1009 return
1011 if data[:len(LIST)] == LIST:
1013 print "Client.datagramReceived(): Received LIST"
1015 split_strings = data.split()
1017 self.members = []
1019 for string in split_strings:
1020 if string != LIST:
1021 self.members.append(string)
1023 event = [LIST]
1024 data = {'names': self.members, 'server_address': (host, port)}
1025 event.append(data)
1027 self.event_queue.append(event)
1029 return
1031 if data[:len(SOMEONEJOINED)] == SOMEONEJOINED:
1033 if (host, port) == self.current_server:
1035 print "Client.datagramReceived(): Received SOMEONEJOINED"
1037 left_member = ''
1039 for member in self.members:
1040 if member == data[len(SOMEONEJOINED) + 1:]:
1041 left_member = member
1043 if left_member == '':
1044 self.members.append(data[len(SOMEONEJOINED) + 1:])
1046 event = [SOMEONEJOINED]
1047 data = {'name': data[len(SOMEONEJOINED) + 1:]}
1049 event.append(data)
1051 self.event_queue.append(event)
1053 return
1055 if data[:len(SOMEONELEFT)] == SOMEONELEFT:
1057 if (host, port) == self.current_server:
1059 name = data[len(SOMEONELEFT) + 1:]
1061 if name in self.members:
1062 print "Client.datagramReceived(): Received SOMEONELEFT"
1064 self.members.remove(name)
1066 event = [SOMEONELEFT]
1067 data = {'name': name}
1069 event.append(data)
1071 self.event_queue.append(event)
1073 else:
1074 print "Client.datagramReceived(): Received SOMEONELEFT, but", name, "not present in roster"
1076 return
1078 if data[:len(YOUROUT)] == YOUROUT:
1080 if (host, port) == self.current_server:
1082 print "Client.datagramReceived(): Recieved YOUROUT"
1084 self.current_server = ()
1086 event = [YOUROUT]
1087 data = {}
1088 event.append(data)
1090 self.event_queue.append(event)
1092 return
1094 if data[:len(LETTER)] == LETTER:
1096 if (host, port) == self.current_server:
1097 print "Client.datagramReceived(): Received LETTER"
1099 split_strings = data.split(':')
1101 message = data[data.find(':', len(LETTER) + 1) + 1:]
1102 message_origin = split_strings[1]
1104 event = [LETTER]
1105 data = {'message': message, 'origin': message_origin}
1106 event.append(data)
1108 self.event_queue.append(event)
1110 return
1112 if data[:len(IMHERE)] == IMHERE:
1114 if (host, port) == self.current_server:
1115 print "Client.datagramReceived(): Received IMHERE from server"
1117 self.server_request = 0
1119 return
1121 def serverRequest(self):
1123 if self.current_server != ():
1125 if self.server_request > SERVER_TIMEOUT:
1126 self.event_queue.append([SERVER_GONE, {}])
1127 self.current_server = ()
1129 else:
1130 self.server_request += 1
1131 self.transport.write(YOUTHERE, self.current_server)
1133 return
1135 def executeCommand(self, command, data):
1137 reactor.callFromThread(self.executeThreadedCommand, command, data)
1139 return
1141 def executeThreadedCommand(self, command, data):
1142 if command == SERVERKILL:
1144 if self.current_server != ():
1146 message = ''.join([SERVERKILL, ' '])
1148 if data.has_key('password'):
1149 message = ''.join([message, data['password']])
1151 self.transport.write(message, self.current_server)
1153 if command == SERVERREQUEST:
1155 message = ''.join([SERVERREQUEST, ' ', str(self.params['message_port'])])
1157 self.multicast.transport.write(message, (MULTICAST, self.params['broadcast_port']))
1158 #self.transport.write(message, ('255.255.255.255', self.params['broadcast_port']))
1160 if command == GETLIST:
1162 message = GETLIST
1164 if data.has_key('server'):
1166 if self.servers.has_key(data['server']):
1167 self.transport.write(message, self.servers[data['server']])
1169 else:
1171 if self.current_server != ():
1172 self.transport.write(message, self.current_server)
1174 if command == IMOUT:
1176 if self.current_server != ():
1178 message = IMOUT
1180 self.transport.write(message, self.current_server)
1182 self.current_server = ()
1184 if command == LETTER:
1186 if self.current_server != ():
1188 message = ''.join([LETTER, ':'])
1190 for dest in data['destinations']:
1191 if dest in self.members:
1192 message = ''.join([message, ' ' , dest])
1194 message = ''.join([message, ':', data['message']])
1196 self.transport.write(message, self.current_server)
1198 if command == WANTIN:
1200 if data.has_key('server'):
1201 if self.servers.has_key(data['server']):
1203 self.transport.write(''.join([WANTIN, ' ', self.params['name']]),
1204 self.servers[data['server']])
1205 self.current_server = ()
1206 self.requested_server = self.servers[data['server']]
1207 return
1209 # debug
1211 def d():
1212 glBegin(GL_TRIANGLES)
1214 glColor3f(1.0,0.0,0.0)
1215 glVertex3f( 0.0, 1.0, 0.0)
1216 glColor3f(0.0,1.0,0.0)
1217 glVertex3f(-1.0,-1.0, 1.0)
1218 glColor3f(0.0,0.0,1.0)
1219 glVertex3f( 1.0,-1.0, 1.0)
1221 glColor3f(1.0,0.0,0.0)
1222 glVertex3f( 0.0, 1.0, 0.0)
1223 glColor3f(0.0,0.0,1.0)
1224 glVertex3f( 1.0,-1.0, 1.0)
1225 glColor3f(0.0,1.0,0.0)
1226 glVertex3f( 1.0,-1.0, -1.0)
1228 glColor3f(1.0,0.0,0.0)
1229 glVertex3f( 0.0, 1.0, 0.0)
1230 glColor3f(0.0,1.0,0.0)
1231 glVertex3f( 1.0,-1.0, -1.0)
1232 glColor3f(0.0,0.0,1.0)
1233 glVertex3f(-1.0,-1.0, -1.0)
1236 glColor3f(1.0,0.0,0.0)
1237 glVertex3f( 0.0, 1.0, 0.0)
1238 glColor3f(0.0,0.0,1.0)
1239 glVertex3f(-1.0,-1.0,-1.0)
1240 glColor3f(0.0,1.0,0.0)
1241 glVertex3f(-1.0,-1.0, 1.0)
1242 glEnd()
1244 if __name__ == '__main__':
1245 main()