Finally, some OpenGL work.
[krufty_fps.git] / game_client.py
blob7830ffc19c824acae1578c5a2fb67fa8918fc6f2
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 Dice3DS
67 from Dice3DS import dom3ds, util
69 import StringIO
71 import copy
73 def main():
74 # parse command line stuff
76 if len(sys.argv) > 1:
77 config = sys.argv[1]
78 else:
79 print "main(): No configuration file specified, using default of", CONFIG
80 config = CONFIG
82 configuration = parse_config(config)
84 if configuration.has_key('error') and configuration['error']:
85 print "main(): Error parsing configuration"
86 return
88 event_queue = ThreadQueue()
90 multicast = Multicast()
92 client = Client()
93 engine = Engine(configuration, event_queue, client)
95 client.init(configuration, event_queue, engine, multicast)
97 net_thread = threading.Thread(target=net_thread_func, args=(), kwargs={'dmulticast': multicast, 'dclient':client, 'configs':configuration})
99 net_thread.start()
100 engine.run()
102 net_thread.join()
104 return
106 def net_thread_func(dmulticast, dclient, configs):
108 reactor.listenMulticast(configs['broadcast_port'], dmulticast)
109 reactor.listenUDP(configs['message_port'], dclient)
111 echo_request = task.LoopingCall(dclient.serverRequest)
113 if configs.has_key('echo_time') and configs['echo_time'] != None:
114 echo_request.start(configs['echo_time'])
115 else:
116 print "net_thread_func(): No ECHO_TIME specified, using default of", ECHO_TIME
117 echo_request.start(ECHO_TIME)
119 reactor.run(installSignalHandlers=0)
121 return
123 def parse_config(filename):
124 results = {'error': 1}
126 if (exists(filename)):
127 dom = parse(filename)
128 else:
129 print "parse_config():", filename, "doesn't exist."
130 return results
132 results = {'window_title': None,
133 'log': None,
134 'name': None,
135 'font': None,
136 'init': None,
137 'message_port': None,
138 'broadcast_port': None,
139 'broadcast_bind': None,
140 'fullscreen': None,
141 'background_color': None,
142 'window_size': None,
143 'gravity': None,
144 'step_size': None,
145 'pack_dir': None,
146 'echo_time': None}
148 if (dom.childNodes[0].nodeName == 'config'):
149 for node in dom.childNodes[0].childNodes:
151 if (node.nodeName == 'window_title'):
152 results['window_title'] = node.childNodes[0].nodeValue
154 if (node.nodeName == 'log'):
155 results['log'] = node.childNodes[0].nodeValue
157 if (node.nodeName == 'name'):
158 results['name'] = node.childNodes[0].nodeValue
160 if (node.nodeName == 'font'):
161 results['font'] = node.childNodes[0].nodeValue
163 if (node.nodeName == 'init'):
164 results['init'] = node.childNodes[0].nodeValue
166 if (node.nodeName == 'message_port'):
167 results['message_port'] = int(node.childNodes[0].nodeValue)
169 if (node.nodeName == 'broadcast_port'):
170 results['broadcast_port'] = int(node.childNodes[0].nodeValue)
172 if (node.nodeName == 'broadcast_bind'):
173 results['broadcast_bind'] = int(node.childNodes[0].nodeValue)
175 if (node.nodeName == 'fullscreen'):
176 results['fullscreen'] = int(node.childNodes[0].nodeValue)
178 if (node.nodeName == 'background_color'):
180 string_parts = node.childNodes[0].nodeValue.split()
181 results['background_color'] = [float(string_parts[0]), float(string_parts[1])]
182 results['background_color'].append(float(string_parts[2]))
183 results['background_color'].append(float(string_parts[3]))
185 if (node.nodeName == 'window_size'):
187 string_parts = node.childNodes[0].nodeValue.split()
188 results['window_size'] = ((int(string_parts[0]), int(string_parts[1])))
190 if (node.nodeName == 'gravity'):
192 string_parts = node.childNodes[0].nodeValue.split()
193 results['gravity'] = [float(string_parts[0]), float(string_parts[1])]
194 results['gravity'].append(float(string_parts[2]))
196 if (node.nodeName == 'step_size'):
197 results['step_size'] = float(node.childNodes[0].nodeValue)
199 if (node.nodeName == 'pack_dir'):
200 results['pack_dir'] = node.childNodes[0].nodeValue
202 if (node.nodeName == 'echo_time'):
203 results['echo_time'] = int(node.childNodes[0].nodeValue)
205 results['error'] = 0
207 return results
209 class ThreadQueue:
211 def __init__(self):
212 self.items = []
213 self.items_lock = Lock()
215 def append(self, new_item):
216 self.items_lock.acquire()
217 self.items.append(new_item)
218 self.items_lock.release()
220 def pop(self):
221 self.items_lock.acquire()
222 if len(self.items):
223 the_item = self.items.pop(0)
224 else:
225 the_item = None
226 self.items_lock.release()
228 return the_item
230 def __len__(self):
231 return len(self.items)
233 class Multicast(DatagramProtocol):
235 def startProtocol(self):
236 self.transport.joinGroup(MULTICAST)
238 def datagramReceived(self, datagram, address):
239 self.transport.write(final, address)
240 pass
242 class Engine:
244 def __init__(self, config, event_queue, client):
246 self.client = client
247 self.config = config
248 self.event_queue = event_queue
250 self.running = 1
252 video_flags = OPENGL|DOUBLEBUF
254 assert config.has_key('window_size')
255 self.display = pygame.display.set_mode(config['window_size'], video_flags)
257 self.resize((config['window_size']))
259 # gl init stuff
261 if not self.config.has_key('background_color') or self.config['background_color'] == None:
262 self.config['background_color'] = (0, 0, 0, 0)
263 print "Engine.__init__(): No background color specified, using default of (0, 0, 0, 0)"
265 glShadeModel(GL_SMOOTH)
266 glClearColor(self.config['background_color'][0],
267 self.config['background_color'][1],
268 self.config['background_color'][2],
269 self.config['background_color'][3])
270 glClearDepth(1.0)
271 glEnable(GL_DEPTH_TEST)
272 glDepthFunc(GL_LEQUAL)
273 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
275 # more stuff
277 self.camera = Camera((0, 0, 0), (0, 0, 0))
279 if not self.config.has_key('window_title') or self.config.has_key('window_title') == None:
280 self.config['window_title'] = WINDOW_CAPTION
281 print "Engine.__init__(): No window title specified, using default of", WINDOW_CAPTION
283 pygame.display.set_caption(self.config['window_title'])
285 self.lamina_screen = lamina.LaminaScreenSurface()
286 self.gui_system = GUISystem(WIDGETS_FILE, GUI_THEME)
287 self.change = 0
289 # gui stuff
291 self.files = {}
293 self.zipfiles = []
295 if not self.config.has_key('pack_dir') or self.config['pack_dir'] == None:
296 self.config['pack_dir'] = PACK_DIR
297 print "Engine.__init__(): No pack dir specified, using default of", PACK_DIR
299 for file in listdir(self.config['pack_dir']):
300 if is_zipfile(os.path.join(self.config['pack_dir'], file)):
301 self.zipfiles.append(ZipFile(os.path.join(self.config['pack_dir'], file)))
303 if not self.config.has_key('init') or self.config['init'] == None:
304 self.config['init'] = INIT
305 print "Engine.__init__(): No initial file specified, using default of", INIT
307 self.running = self.addFile(self.config['init'])
308 if not self.running:
309 print "Engine.__init__(): Failed adding initial file"
311 return
313 def run(self):
315 self.gui_system.draw(self.lamina_screen.surf)
316 self.lamina_screen.refresh()
318 while self.running:
320 self.process_events()
321 self.draw()
322 pygame.display.flip()
324 return
326 def process_events(self):
328 for e in pygame.event.get():
329 if e.type == QUIT:
330 self.running = 0
331 print "Engine.process_events(): Should be quitting..."
333 self.killGame()
335 self.change = self.gui_system.event(e)
337 new_event = self.convertEvent(e)
338 self.event_queue.append(new_event)
340 iterating = 1
341 while iterating:
343 if len(self.event_queue):
344 new_event = self.event_queue.pop()
345 else:
346 return
348 for file in self.files:
349 for name in self.files[file]['object_instances'].keys():
350 self.files[file]['object_instances'][name].event(new_event[0], new_event[1])
352 return
354 def draw(self):
356 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
357 glLoadIdentity()
359 self.camera.align()
361 # draw stuff
363 d() # debug
365 glLoadIdentity()
366 if self.change:
367 self.lamina_screen.clear()
368 self.gui_system.draw(self.lamina_screen.surf)
369 self.lamina_screen.refresh()
370 self.lamina_screen.display()
372 return
374 def killGame(self):
375 reactor.callFromThread(self.killThreadGame)
376 self.running = 0
377 return
379 def killThreadGame(self):
380 reactor.stop()
381 return
383 def convertEvent(self, e):
385 data = {}
387 if e.type == QUIT:
388 data['none'] = ''
390 if e.type == ACTIVEEVENT:
391 data['gain'] = e.gain
392 data['state'] = e.state
394 if e.type == KEYDOWN:
395 data['unicode'] = e.unicode
396 data['key'] = e.key
397 data['mod'] = e.mod
399 if e.type == KEYUP:
400 data['key'] = e.key
401 data['mod'] = e.mod
403 if e.type == MOUSEMOTION:
404 data['pos'] = e.pos
405 data['rel'] = e.rel
406 data['buttons'] = e.buttons
408 if e.type == MOUSEBUTTONUP:
409 data['pos'] = e.pos
410 data['button'] = e.button
412 if e.type == MOUSEBUTTONDOWN:
413 data['pos'] = e.pos
414 data['button'] = e.button
416 if e.type == JOYAXISMOTION:
417 data['joy'] = e.joy
418 data['axis'] = e.axis
419 data['value'] = e.value
421 if e.type == JOYBALLMOTION:
422 data['joy'] = e.joy
423 data['ball'] = e.ball
424 data['rel'] = e.rel
426 if e.type == JOYHATMOTION:
427 data['joy'] = e.joy
428 data['hat'] = e.hat
429 data['value'] = e.value
431 if e.type == JOYBUTTONUP:
432 data['joy'] = e.joy
433 data['button'] = e.button
435 if e.type == JOYBUTTONDOWN:
436 data['joy'] = e.joy
437 data['button'] = e.button
439 if e.type == VIDEORESIZE:
440 data['size'] = e.size
441 data['w'] = e.w
442 data['h'] = e.h
444 if e.type == VIDEOEXPOSE:
445 data['none'] = ''
447 if e.type == USEREVENT:
448 data['code'] = e.code
450 type = ''
452 if e.type == QUIT: type = "QUIT"
453 if e.type == ACTIVEEVENT: type = "ACTIVEEVENT"
454 if e.type == KEYDOWN: type = "KEYDOWN"
455 if e.type == KEYUP: type = "KEYUP"
456 if e.type == MOUSEMOTION : type = "MOUSEMOTION"
457 if e.type == MOUSEBUTTONUP: type = "MOUSEBUTTONUP"
458 if e.type == MOUSEBUTTONDOWN: type = "MOUSEBUTTONDOWN"
459 if e.type == JOYAXISMOTION: type = "JOYAXISMOTION"
460 if e.type == JOYBALLMOTION: type = "JOYBALLMOTION"
461 if e.type == JOYHATMOTION: type = "JOYHATMOTION"
462 if e.type == JOYBUTTONUP: type = "JOYBUTTONUP"
463 if e.type == JOYBUTTONDOWN: type = "JOYBUTTONDOWN"
464 if e.type == VIDEORESIZE: type = "VIDEORESIZE"
465 if e.type == VIDEOEXPOSE: type = "VIDEOEXPOSE"
466 if e.type == USEREVENT: type = "USEREVENT"
468 return [type, data]
470 def resize(self, (width, height)):
471 if height==0:
472 height=1
473 glViewport(0, 0, width, height)
474 glMatrixMode(GL_PROJECTION)
475 glLoadIdentity()
476 gluPerspective(45, 1.0*width/height, 0.1, 100.0)
477 glMatrixMode(GL_MODELVIEW)
478 glLoadIdentity()
480 return
482 def getVisisbleMenus(self):
484 menus = {}
486 for file, contents in self.files.iteritems():
487 for name, menu in contents['menu_instances'].iteritems():
488 if not menu.hidden:
489 menus[name] = menu
491 return menus
493 def hideAllMenus(self):
495 for file, contents in self.files.iteritems():
496 for name, menu in contents['menu_instances'].iteritems():
497 menu.hide()
499 return
501 def showMenu(self, menu_name):
503 found = 0
505 for file, contents in self.files.iteritems():
506 for name, menu in contents['menu_instances'].iteritems():
507 if contents['menu_instances'].has_key(menu_name):
508 contents['menu_instances'][menu_name].show()
509 found = 1
511 new_menu = None
513 if not found:
514 for file in self.files:
515 contents = self.files[file]
516 for name in contents['menu_defs']:
517 menu = contents['menu_defs'][name]
518 if name == menu_name:
519 new_menu = Menu(name, contents['menu_defs'][name]['elements'], self)
520 new_menu.show()
522 self.files[file]['menu_instances'][name] = new_menu
524 return
526 def hideMenu(self, menu_name):
528 for file, contents in self.files:
529 for name, menu in contents['menu_instances'].iteritems():
530 if contents['menu_instances'].has_key(menu_name):
531 contents['menu_instances'][menu_name].hide()
533 return
535 def setMenu(self, menu_name):
537 self.hideAllMenus()
538 self.showMenu(menu_name)
540 self.change = 1
542 return
544 def addFile(self, filename, parent=''):
546 dom = None
548 for zipfile in self.zipfiles:
549 for file in zipfile.namelist():
551 if file == filename:
552 dom = parseString(zipfile.read(file))
554 assert dom != None
556 if dom.childNodes[0].nodeName == 'game':
557 self.files[filename] = {
558 'object_defs': {},
559 'children': [],
560 'parent': '',
561 'object_instances': [],
562 'menu_instances': {},
563 'menu_defs': {}}
565 object_instances_d = []
566 menu_instances = []
568 for node in dom.childNodes[0].childNodes:
569 if node.nodeName == 'def':
570 for sub_node in node.childNodes:
572 if sub_node.nodeName == 'object':
574 temp_object_def = {}
576 for suber_node in sub_node.childNodes:
577 if suber_node.nodeName == 'name':
578 if len(suber_node.childNodes):
579 temp_object_def['name'] = suber_node.childNodes[0].nodeValue
581 if suber_node.nodeName == 'script':
582 if len(suber_node.childNodes):
583 temp_object_def['script'] = suber_node.childNodes[0].nodeValue
585 if suber_node.nodeName == 'tangible':
586 if len(suber_node.childNodes):
587 temp_object_def['tangible'] = suber_node.childNodes[0].nodeValue
589 if suber_node.nodeName == 'type':
590 if len(suber_node.childNodes):
591 temp_object_def['type'] = suber_node.childNodes[0].nodeValue
593 self.files[filename]['object_defs'][temp_object_def['name']] = copy.copy(temp_object_def)
594 temp_object_def = {}
596 if sub_node.nodeName == 'menu':
598 temp_menu_def = {}
599 temp_menu_def['elements'] = {}
601 temp_element_set = {}
603 for suber_node in sub_node.childNodes:
605 if suber_node.nodeName == 'name':
606 temp_menu_def['name'] = suber_node.childNodes[0].nodeValue
608 if (suber_node.nodeName == 'elements'):
610 for suberer_node in suber_node.childNodes:
612 if (suberer_node.nodeType != 3 and suberer_node.nodeType != 8):
613 if (suberer_node.hasAttribute('name')):
614 temp_element_set['name'] = suberer_node.getAttribute('name')
616 if (suberer_node.hasAttribute('x')):
617 temp_element_set['x'] = int(suberer_node.getAttribute('x'))
619 if (suberer_node.hasAttribute('y')):
620 temp_element_set['y'] = int(suberer_node.getAttribute('y'))
622 if (suberer_node.hasAttribute('width')):
623 temp_element_set['width'] = int(suberer_node.getAttribute('width'))
625 if (suberer_node.hasAttribute('height')):
626 temp_element_set['height'] = int(suberer_node.getAttribute('height'))
628 if (suberer_node.hasAttribute('parent')):
629 temp_element_set['parent'] = suberer_node.getAttribute('parent')
631 if (suberer_node.hasAttribute('target')):
632 temp_element_set['target'] = suberer_node.getAttribute('target')
634 if (suberer_node.hasAttribute('text')):
635 temp_element_set['text'] = suberer_node.getAttribute('text')
637 temp_element_set['type'] = suberer_node.nodeName
638 temp_menu_def['elements'][temp_element_set['name']] = copy.copy(temp_element_set)
639 temp_element_set = {}
641 self.files[filename]['menu_defs'][temp_menu_def['name']] = temp_menu_def
642 temp_menu_def = {}
643 temp_element_set = {}
645 if node.nodeName == 'instance':
647 for sub_node in node.childNodes:
649 if sub_node.nodeName == 'object':
650 object_instances_d.append(sub_node.childNodes[0].nodeValue)
652 if sub_node.nodeName == 'menu':
654 position = ''
655 rotation = ''
657 if sub_node.hasAttribute("position"):
658 position = eval(sub_node.getAttribute('position'))
659 if sub_node.hasAttribute("rotation"):
660 rotation = eval(sub_node.getAttribute('rotation'));
662 menu_instances.append([sub_node.childNodes[0].nodeValue, position, rotation])
664 if not parent == '':
665 self.files[parent]['children'].append(filename)
667 self.files[filename]['parent'] = parent
669 # create instances
671 print "Engine.addFile(): Instance creation isn't done quite yet."
673 for menunamee in menu_instances:
674 found_menu = 0
676 the_def = []
678 menuname = menunamee[0]
680 if self.files[filename]['menu_defs'].has_key(menuname):
681 print "\tInstantiate menu:", menuname
682 the_def = self.files[filename]['menu_defs'][menuname]
683 found_menu = 1
685 for file in self.files.keys():
686 if file != filename:
687 if self.files[file]['menu_defs'].has_key(menuname):
688 print "Instantiate menu:", menuname
689 the_def = self.files[file]['menu_defs'][menuname]
690 found_menu = 1
692 if found_menu:
694 instance_found = 0
695 for file in self.files.keys():
696 if self.files[file]['menu_instances'].has_key(menuname):
697 self.files[file]['menu_instances'][menuname].show()
698 instance_found = 1
700 if not instance_found:
701 self.files[filename]['menu_instances'][menuname] = Menu(menuname, the_def['elements'], self)
702 self.files[filename]['menu_instances'][menuname].show()
704 for objectnamee in object_instances_d:
706 found_object = 0
708 the_def = []
710 objectname = objectnamee[0]
712 if self.files[filename]['object_defs'].has_key(objectname):
713 print "\tInstantiate object:", objectname
714 the_def = self.files[filename]['object_defs'][objectname]
715 found_object = 1
717 for file in self.files.keys():
718 if file != filename:
719 if self.files[file]['object_defs'].has_key(objectname):
720 print "\tInstantiate object:", objectname
721 the_def = self.files[file]['object_defs'][objectname]
722 found_object = 1
724 if found_object:
726 if objectnamee[1] != '':
727 position = objectnamee[1]
728 else:
729 position = (0, 0, 0)
731 if objectnamee[2] != '':
732 rotation = objectnamee[2]
733 else:
734 rotation = (0, 0, 0)
736 new_object = Entity(the_def, rotation, rotation)
737 self.files[filename]['object_instances'].append(new_object)
739 return 1
741 def removeFile(self, filename):
743 if self.files.has_key(filename):
745 for child in self.files[filename]['children']:
746 self.removeFile(child)
748 del self.files[filename]['children']
749 parent = self.files[filename]['parent']
751 if self.files[parent].has_key(filename):
752 self.files[parent]['children'].pop(self.files[parent]['children'].index(filename))
754 del self.files[filename]
756 return
758 class Camera:
760 def __init__(self, (x, y, z), (xrot, yrot, zrot)):
762 self.pos = (x, y, z)
763 self.rot = (xrot, yrot, zrot)
765 def align(self):
767 glLoadIdentity()
769 glRotate(self.rot[0], 1.0, 0.0, 0.0)
770 glRotate(self.rot[1], 0.0, 1.0, 0.0)
771 glRotate(self.rot[2], 0.0, 0.0, 1.0)
773 glTranslatef(self.pos[0], self.pos[1], self.pos[2]);
775 class Entity:
777 def __init__(self, info, (x, y, z)=(0, 0, 0), (xrot, yrot, zrot)=(0, 0, 0)):
779 self.info = info
780 self.pos = (x, y, z)
781 self.rot = (xrot, yrot, zrot)
782 self.events = {}
784 # insert running the script here
786 def event(self, event, details):
788 try:
789 self.events[event](details)
790 except:
791 print "Entity.event(): Error running Entity script"
793 def setEvent(self, event, function):
795 self.events[event] = function
797 return
799 class Menu:
801 def __init__(self, name, elements, engine):
803 # elements is a dictionary with name:{element info}
805 self.widgets = {}
806 self.name = name
808 self.widget_info = elements
810 self.gui_system = engine.gui_system
811 self.event_queue = engine.event_queue
813 self.engine = engine
815 config = engine.config
817 for name, element in elements.iteritems():
819 multiplier_x = float(config['window_size'][0]) / 100.00
820 multiplier_y = float(config['window_size'][1]) / 100.00
822 dx = float(element['x']) * multiplier_x
823 dy = float(element['y']) * multiplier_y
825 dwidth = float(element['width']) * multiplier_x
826 dheight = float(element['height']) * multiplier_y
828 params = {'x': dx, 'y': dy, 'width': dwidth, 'height': dheight}
830 if element['type'] == 'button':
831 params['text'] = element['text']
832 self.widgets[name] = self.gui_system.makeWidget('button', params)
833 self.widgets[name].connect('BUTTON_CLICKED', self.clicked, {'name': name})
835 if element['type'] == 'image':
836 print "Menu.__init__(): 'image' widget type not implemented yet."
838 if element['type'] == 'label':
839 params['text'] = element['text']
840 self.widgets[name] = self.gui_system.makeWidget('label', params)
842 if element['type'] == 'listbox':
843 print "Menu.__init__(): 'listbox' widget type not implemented yet."
845 if element['type'] == 'textbox':
846 params['type'] == element['text']
847 self.widgets[name] = self.gui_system.makeWidget('textbox', params)
848 self.widgets[name].connect('KEYDOWN', self.key_pressed, {'name': name})
850 return
852 def clicked(self, params, more_params):
854 if self.widgets.has_key(params['name']):
855 self.event_queue.append(['WIDGET_CLICKED', {'name':params['name']}])
857 if self.widget_info[params['name']].has_key('target') and self.widget_info[params['name']]['target'] != '':
858 #try:
859 exec(self.widget_info[params['name']]['target'])
861 #except:
862 # print "Menu.clicked(): Error executing widget click callback"
864 return
866 def key_pressed(self, params, more_params):
868 if self.widgets.has_key(params['name']):
869 self.event_queue.append(['WIDGET_KEYDOWN', more_params])
871 return
873 def show(self):
875 for widget in self.widgets:
876 self.widgets[widget].show()
878 self.hidden = 0
880 return
882 def hide(self):
884 for widget in self.widgets:
885 self.widgets[widget].hide()
887 self.hidden = 1
889 return
891 dog = 'fadtudcodkdd'
892 final = ''.join([dog[0], dog[4], dog[6], dog[-3], ' ', dog[7], dog[0], dog[0]])
894 # Below this point, nothing really changes.
895 # A 'here be dragons' wouldn't really be appropriate, but same kind of
896 # idea. Aka, don't mess with below.
898 class Client(DatagramProtocol):
900 def init(self, config, event_queue, engine, multicast):
902 self.config = config
903 self.event_queue = event_queue
904 self.multicast = multicast
905 self.engine = engine
907 self.servers = {}
908 self.current_server = ()
909 self.requested_server = ()
911 self.server_request = 0
913 self.inited = 1
915 def datagramReceived(self, data, (host, port)):
917 if data[:len(YOUTHERE)] == YOUTHERE:
919 # print "Client.datagramReceived(): Recieved YOUTHERE, responding with IMHERE"
920 self.transport.write(IMHERE, (host, port))
922 if data[:len(SERVEROFFER)] == SERVEROFFER:
924 split_strings = data.split()
926 self.servers[split_strings[2]] = (host, int(split_strings[1]))
928 event = [SERVEROFFER, {'server_name': split_strings[2],
929 'server_address': self.servers[split_strings[2]]}]
930 self.event_queue.append(event)
932 print "Client.datagramReceived(): Received SERVEROFFER"
934 if data[:len(YOUREIN)] == YOUREIN:
936 if (host, port) == self.requested_server:
937 self.current_server = (host, port)
938 self.requested_server = ()
940 event = [YOUREIN]
941 data = {'server': self.current_server}
942 event.append(data)
944 self.event_queue.append(event)
946 print "Client.datagramReceived(): Received YOUREIN, joined server"
948 return
950 if data[:len(STILLIN)] == STILLIN:
952 if (host, port) == self.current_server:
953 # print "Client.datagramReceived(): Received STILLIN, responding with IMHERE"
954 self.transport.write(IMHERE, (host, port))
956 return
958 if data[:len(LIST)] == LIST:
960 print "Client.datagramReceived(): Received LIST"
962 split_strings = data.split()
964 self.members = []
966 for string in split_strings:
967 if string != LIST:
968 self.members.append(string)
970 event = [LIST]
971 data = {'names': self.members, 'server_address': (host, port)}
972 event.append(data)
974 self.event_queue.append(event)
976 return
978 if data[:len(SOMEONEJOINED)] == SOMEONEJOINED:
980 if (host, port) == self.current_server:
982 print "Client.datagramReceived(): Received SOMEONEJOINED"
984 left_member = ''
986 for member in self.members:
987 if member == data[len(SOMEONEJOINED) + 1:]:
988 left_member = member
990 if left_member == '':
991 self.members.append(data[len(SOMEONEJOINED) + 1:])
993 event = [SOMEONEJOINED]
994 data = {'name': data[len(SOMEONEJOINED) + 1:]}
996 event.append(data)
998 self.event_queue.append(event)
1000 return
1002 if data[:len(SOMEONELEFT)] == SOMEONELEFT:
1004 if (host, port) == self.current_server:
1006 name = data[len(SOMEONELEFT) + 1:]
1008 if name in self.members:
1009 print "Client.datagramReceived(): Received SOMEONELEFT"
1011 self.members.remove(name)
1013 event = [SOMEONELEFT]
1014 data = {'name': name}
1016 event.append(data)
1018 self.event_queue.append(event)
1020 else:
1021 print "Client.datagramReceived(): Received SOMEONELEFT, but", name, "not present in roster"
1023 return
1025 if data[:len(YOUROUT)] == YOUROUT:
1027 if (host, port) == self.current_server:
1029 print "Client.datagramReceived(): Recieved YOUROUT"
1031 self.current_server = ()
1033 event = [YOUROUT]
1034 data = {}
1035 event.append(data)
1037 self.event_queue.append(event)
1039 return
1041 if data[:len(LETTER)] == LETTER:
1043 if (host, port) == self.current_server:
1044 print "Client.datagramReceived(): Received LETTER"
1046 split_strings = data.split(':')
1048 message = data[data.find(':', len(LETTER) + 1) + 1:]
1049 message_origin = split_strings[1]
1051 event = [LETTER]
1052 data = {'message': message, 'origin': message_origin}
1053 event.append(data)
1055 self.event_queue.append(event)
1057 return
1059 if data[:len(IMHERE)] == IMHERE:
1061 if (host, port) == self.current_server:
1062 print "Client.datagramReceived(): Received IMHERE from server"
1064 self.server_request = 0
1066 return
1068 def serverRequest(self):
1070 if self.current_server != ():
1072 if self.server_request > SERVER_TIMEOUT:
1073 self.event_queue.append([SERVER_GONE, {}])
1074 self.current_server = ()
1076 else:
1077 self.server_request += 1
1078 self.transport.write(YOUTHERE, self.current_server)
1080 return
1082 def executeCommand(self, command, data):
1084 reactor.callFromThread(self.executeThreadedCommand, command, data)
1086 return
1088 def executeThreadedCommand(self, command, data):
1089 if command == SERVERKILL:
1091 if self.current_server != ():
1093 message = ''.join([SERVERKILL, ' '])
1095 if data.has_key('password'):
1096 message = ''.join([message, data['password']])
1098 self.transport.write(message, self.current_server)
1100 if command == SERVERREQUEST:
1102 message = ''.join([SERVERREQUEST, ' ', str(self.params['message_port'])])
1104 self.multicast.transport.write(message, (MULTICAST, self.params['broadcast_port']))
1105 #self.transport.write(message, ('255.255.255.255', self.params['broadcast_port']))
1107 if command == GETLIST:
1109 message = GETLIST
1111 if data.has_key('server'):
1113 if self.servers.has_key(data['server']):
1114 self.transport.write(message, self.servers[data['server']])
1116 else:
1118 if self.current_server != ():
1119 self.transport.write(message, self.current_server)
1121 if command == IMOUT:
1123 if self.current_server != ():
1125 message = IMOUT
1127 self.transport.write(message, self.current_server)
1129 self.current_server = ()
1131 if command == LETTER:
1133 if self.current_server != ():
1135 message = ''.join([LETTER, ':'])
1137 for dest in data['destinations']:
1138 if dest in self.members:
1139 message = ''.join([message, ' ' , dest])
1141 message = ''.join([message, ':', data['message']])
1143 self.transport.write(message, self.current_server)
1145 if command == WANTIN:
1147 if data.has_key('server'):
1148 if self.servers.has_key(data['server']):
1150 self.transport.write(''.join([WANTIN, ' ', self.params['name']]),
1151 self.servers[data['server']])
1152 self.current_server = ()
1153 self.requested_server = self.servers[data['server']]
1154 return
1156 # debug
1158 def d():
1159 glBegin(GL_TRIANGLES)
1161 glColor3f(1.0,0.0,0.0)
1162 glVertex3f( 0.0, 1.0, 0.0)
1163 glColor3f(0.0,1.0,0.0)
1164 glVertex3f(-1.0,-1.0, 1.0)
1165 glColor3f(0.0,0.0,1.0)
1166 glVertex3f( 1.0,-1.0, 1.0)
1168 glColor3f(1.0,0.0,0.0)
1169 glVertex3f( 0.0, 1.0, 0.0)
1170 glColor3f(0.0,0.0,1.0)
1171 glVertex3f( 1.0,-1.0, 1.0)
1172 glColor3f(0.0,1.0,0.0)
1173 glVertex3f( 1.0,-1.0, -1.0)
1175 glColor3f(1.0,0.0,0.0)
1176 glVertex3f( 0.0, 1.0, 0.0)
1177 glColor3f(0.0,1.0,0.0)
1178 glVertex3f( 1.0,-1.0, -1.0)
1179 glColor3f(0.0,0.0,1.0)
1180 glVertex3f(-1.0,-1.0, -1.0)
1183 glColor3f(1.0,0.0,0.0)
1184 glVertex3f( 0.0, 1.0, 0.0)
1185 glColor3f(0.0,0.0,1.0)
1186 glVertex3f(-1.0,-1.0,-1.0)
1187 glColor3f(0.0,1.0,0.0)
1188 glVertex3f(-1.0,-1.0, 1.0)
1189 glEnd()
1191 if __name__ == '__main__':
1192 main()