diff options
Diffstat (limited to 'plugins/multi_player.py')
-rwxr-xr-x | plugins/multi_player.py | 552 |
1 files changed, 552 insertions, 0 deletions
diff --git a/plugins/multi_player.py b/plugins/multi_player.py new file mode 100755 index 0000000..68acc63 --- /dev/null +++ b/plugins/multi_player.py @@ -0,0 +1,552 @@ +import pygame +from pygame import * +from layout import * +from frontend import hex2rgb +import threading +import time +import traceback + +__PLUGIN_NAME__ = 'multi player' +#import single_player + +class Status: + """ edited by the hosts """ + + game_state = '0' # 0=open_before_game, 1=..? + + status_line = 'statusline' + clients = [] + + class Client: + def __init__(self, name, status=''): + self.name = name + self.status = status + + def set_status_line(self, s1, s2): + return True + + def get_status_line(self): + self.status_line = "%s;;%s" % (self.game_state, self.get_user_names(";")) + return self.status_line + + def get_user_names(self, split_str=';;'): + usernames = [] + for c in self.clients: + usernames.append(c.name) + return split_str.join(usernames) + + def add_user(self, user_name): + for c in self.clients: + if c.name.upper() == user_name.upper(): return False + + new_client = self.Client(user_name) + self.clients.append(new_client) + return True + + def del_user(self, user_name): + print "deleting user %s" % user_name + new_clients = [] + for c in self.clients: + if c.name.upper() != user_name.upper(): + new_clients.append(c) + + self.clients = new_clients + return True + + +def show_answer(): + A.display_answer() + +def finished(): + sf.refresh() + sf.add_text_item("You have finished this category!", (180, 80)) + sf.add_text_item("Won: %i" % Q.count_won, (220, 120)) + sf.add_text_item("Lost: %i" % Q.count_lost, (220, 160)) + pygame.display.update() + ask_category(130) + + +def startgame(db_cat_id): + print "* Starting Game, Category:", db_cat_id + print "** Loading Questions" + + Q.count_won = 0 + Q.count_won = 0 + A.reset_points() + + Q.load_questions(db_cat_id) + display_points() + + sf.clear_text_items() + next_question(0) + + +def ask_category(offset_y = 0, offset_x = 0, cat_id=0): + Q.load(__SERVICES__.locale.lang_id, __SERVICES__.locale.lang_name) + +# sf.clear_text_items() + + i = 1 + y = 110 + offset_y + x = 340 + offset_x + + sf.add_text_item("Category:", (x,y)) + y += 50 + x += 50 + sf.add_text_item('All', (x,y), game_host.set_category, 0, True) +# global game_host + for q in Q.categories: + y += 50 + sf.add_text_item("%s (%s)" % (q[1], q[2]), (x,y), game_host.set_category, q[0], True) + i += 1 + + display_points() + +def display_points(): + format = TextFormat(None, 30) + max_q = len(Q.questions) + +# sf.display_tooltip("%i" % (Q.count_won), (480, 14), format) +# sf.display_tooltip("%i" % Q.count_lost, (480, 42), format) + + if max_q == 0: + sf.display_line(0, True) + sf.display_line(0, False) + else: + sf.display_line(100 * Q.count_won / max_q, True) + sf.display_line(100 * Q.count_lost / max_q, False) + +def click_on_next_question(): + next_question(0) + +def next_question(params): + print "* Next Question" + + # Select Category + if Q._cat_id == -1: + ask_category() + return 1 + + + # Pick only locale language's categories + if Q.question_pick(): + __SERVICES__.frontend.question_display(Q.question) + Q.in_question = True + + pass + else: + # game / cat finished! + in_question = False + print "finished" + Q._cat_id = -1 + finished() + pass + +def spot_found(params): + if Q.in_question: + print "found" + A.display_icon("found") + A.play_sound(1) + Q.in_question = False + Q.count_won += 1 + display_points() + show_answer() + +def spot_not_found(params): + print params + if Q.in_question: + print "not found" + A.display_icon("not-found") + A.play_sound(0) + Q.in_question = False + Q.count_lost += 1 + display_points() + show_answer() + return "ok" + + + + +class getStatus(threading.Thread): + running = True + + def set(self, client_talk, status_call_function, abort_function=None): + self.talk = client_talk + self.status_call_function = status_call_function + self.abort_function = abort_function + self.running = True + + def run(self): + while self.running: + time.sleep(2) + try: + self.status = self.talk('get:status') + self.status_call_function(self.status) + except: + traceback.print_exc() + print "getstatus aborted" + self.running = False + if self.abort_function != None: self.abort_function() + + +class waitForUsersToJoin(threading.Thread): + running = True + last_users = '' + + def set(self, talk, waittext_id, textid_connectedto=None): + self.talk = talk + self.waittext_id = waittext_id + self.textid_connectedto = textid_connectedto + + def display_server_quit(self): + self.running = False + + def run(self): + format = TextFormat() + font = pygame.font.Font(None, format.size) + bg = pygame.Surface((560, 30)) + + while self.running: + time.sleep(2) + + users = self.talk("get:userlist") + if users == False: return + + self.users = users.split(";;") + users = users.replace(";;", ", ") + + print self.users + print users + + text = font.render("> %s" % users, 1, hex2rgb(format.color)) + textpos = text.get_rect() + + bg.fill(hex2rgb(Layout().background)) + bg.blit(text, (0,0)) + sf.display_surface(bg, (48, 610)) + + pygame.display.update((48, 610, 560, 30)) + +class DrawTimer: + def __init__(self): + self.bg = pygame.Surface((100, 60)) + + def draw(self, time): + self.bg.fill(hex2rgb(Layout().Question.background)) + + format = TextFormat(None, 46, None) + font = pygame.font.Font(None, format.size) + text = font.render("%i sec" % time, 1, hex2rgb(format.color)) + + self.bg.blit(text, (0,0)) + sf.display_surface(self.bg, (150, 440)) + pygame.display.update() + +class MultiPlayerHost: + category = 0 + game_time = 0 + textid_timer = -1 + status = Status() + + def __init__(self, host, port): + self.host = host + self.port = port + self.socket = __import__("plugins/_quizsocket") + + print "starting server" + self.server = self.socket.Server('', port, self.status) + self.server.start() + + def close(self): + self.client.running = False + self.waituser.running = False + self.server.quit() + + def update_status(self, params): + print params + + def load(self): + print "Creating a new game" + sf.clear_question_frame(True) + + # Display some text + format = TextFormat(None, 40) + sf.add_text_item("New Multiplayer Game", (340, 45), None, None, False, format) + waittext_id = sf.add_text_item("Waiting for users to join...", (40, 570)) + + # let's spawn our own client now + self.client = self.socket.Client(self.host, self.port, Layout().user_name) + self.client.start() + + # Display "Waiting for users to join..." + self.waituser = waitForUsersToJoin() + self.waituser.set(self.client.talk, waittext_id, None) + self.waituser.start() + + # Constantly Get Status Updates from the Host +# self.getstatus = getStatus() +# self.getstatus.set(self.Spawner.client_talk, self.update_status, self.abort_net) +# self.getstatus.start() + + # Display Start Button + format = TextFormat(None, None, Colors().green) + sf.add_text_item("Start", (Layout().Question.x + Layout().Question.width - 150, 570), None, None, True, format) + + # Display Categories + ask_category() + self.set_category(0) + pygame.display.update() + + self.hookid_click = sf.add_event_hook("onclick", self.click) + + + # Draw Timer Option + img, rect = sf.image_load("images/xclock.png") + sf.display_surface(img, (40, 400)) + self.draw_timer = DrawTimer() + self.click_timer() + + + def click(self, params): + x, y = list(params) + if x > 40 and x < (40 + 96) and y > 400 and y < (400 + 96): + # Click on Clock + self.click_timer() + + def click_timer(self): + if self.game_time == 30: + self.game_time = 10 + elif self.game_time == 20: + self.game_time = 30 + elif self.game_time == 10: + self.game_time = 20 + elif self.game_time == 0: + self.game_time = 10 + +# self.Spawner.master_set_status("time:%i" % self.game_time) + self.draw_timer.draw(self.game_time) + + def set_category(self, param): + cat_id = int(param) + self.category = cat_id + + cat_name = 'All' + if cat_id > 0: + q = "SELECT text FROM categories WHERE cat_id=%i AND lang_id=%s" % (cat_id, __SERVICES__.locale.lang_id) + res = __SERVICES__.db.query(q) + print res + cat_name = res[0][0] + +# self.Spawner.master_set_status(u"cat:%s" % cat_name) + + bg = pygame.Surface((360, 30)) + bg.fill(hex2rgb(Layout().background)) + + format = TextFormat() + font = pygame.font.Font(None, format.size) + + text = font.render("%s" % cat_name, 1, hex2rgb(format.color)) + bg.blit(text, (0,0)) + sf.display_surface(bg, (480, 115)) + pygame.display.update() + +class MultiPlayerClient: + connected = False + game_time = 0 + cat_name = u'' + + socket = None + waittext_id = None + + format = TextFormat() + font = pygame.font.Font(None, format.size) + bg = pygame.Surface((560, 30)) + + def __init__(self, host, port): + self.host = host + self.port = port + self.connected = False + if self.socket == None: self.socket = __import__("plugins/_quizsocket") + + def close(self): + self.getstatus.running = False + self.client.close() + self.connected = False + + def load(self): + print "Joining a multiplayer game" + + sf.clear_question_frame(True) + + format = TextFormat(None, 40) + sf.add_text_item("Joining a Multiplayer Game", (340, 45), None, None, False, format) + pygame.display.update() + +# print self.connected + if self.connected == False: + host = sf.ask("host") + sf.refresh() + print "host: ", host + self.host = host + + if len(host) == 0: + return False + +# if host == "l": host = "localhost" + print "starting client" + textid_connectedto = sf.add_text_item("[connecting to %s]" % host, (340, 80)) + self.textid_connectedto = textid_connectedto + + self.client = self.socket.Client(self.host, self.port, Layout().user_name, self.nonet_function) + self.client.start() + + self.getstatus = getStatus() + self.getstatus.set(self.client.talk, self.update_status, self.nonet_function) + self.getstatus.start() + + def display_catname(self): + bg = pygame.Surface((300, 60)) + bg.fill(hex2rgb(Layout().Question.background)) + + format = TextFormat(None, 40) + font = pygame.font.Font(None, format.size) + text = font.render("Category: %s" % self.cat_name, 1, hex2rgb(format.color)) + + bg.blit(text, (0,0)) + sf.display_surface(bg, (350, 190)) + pygame.display.update() + + def update_status(self, params): + self.status = params + print "STATUS UPDATE:",params + + if params == False or len(params) == 0 or params == None or params == "None": + self.close() + return + + if self.connected == False: + self.connection_ok() + + n = params.split(";;") + + users = n[1].replace(";", ", ") + + text = self.font.render("> %s" % users, 1, hex2rgb(self.format.color)) + textpos = text.get_rect() + + self.bg.fill(hex2rgb(Layout().background)) + self.bg.blit(text, (0,0)) + sf.display_surface(self.bg, (48, 610)) + + pygame.display.update((48, 610, 560, 30)) + print params + +# for n in params: +# m = n.split(":") +# if m[0] == "time": +# if int(m[1]) != self.game_time: +# self.game_time = int(m[1]) +# self.draw_timer.draw(self.game_time) +# +# if m[0] == "cat": +# if m[1] != self.cat_name: +# self.cat_name = m[1] +# self.display_catname() + + + def connection_ok(self): + self.connected = True + sf.del_text_item(self.textid_connectedto) + + self.textid_connectedto = sf.add_text_item("[connected to %s]" % self.host, (340, 80)) + self.waittext_id = sf.add_text_item("Waiting for users to join...", (40, 570)) + + pygame.display.update() + + # Draw Timer Option + img, rect = sf.image_load("images/xclock.png") + sf.display_surface(img, (40, 400)) + self.draw_timer = DrawTimer() + + def nonet_function(self): + print "client net aborted, quitting MultiPlayer-Client" + + self.running = False + + if self.waittext_id != None: sf.del_text_item(self.waittext_id) + if self.textid_connectedto != None: sf.del_text_item(self.textid_connectedto) + + sf.add_text_item("Server quit the game", (340, 84)) + + # clear player + bg = pygame.Surface((560, 30)) + bg.fill(hex2rgb(Layout().background)) + sf.display_surface(bg, (48, 610)) + pygame.display.update() + + self.close() + + global game_client + game_client = None + + + + +def click_create(): + global game_client + global game_host + + if game_client == None and game_host == None: + game_host = MultiPlayerHost("", Layout().port) + sf.clear_text_items(False) + game_host.load() + + +def click_join(): + global game_client + global game_host + + if game_client == None and game_host == None: + game_client = '' + game_client = MultiPlayerClient("localhost", Layout().port) + + sf.clear_text_items() + + res = game_client.load() + if res == False: + game_client = None + +def load(): + global sf + sf = __SERVICES__.frontend; + + sp = __import__("plugins/single_player") + sp.sf = sf + + global Q + Q = sp.Questions() + + global A + A = sp.Answer() + + global game_host + game_host = None + + global game_client + game_client = None + + sf.add_menu_dir('/multi-player', 'Multiplayer', 1) + sf.add_menu_item('/multi-player', 'Create Game', click_create, 1) + sf.add_menu_item('/multi-player', 'Join Game', click_join, 2) + + __SERVICES__.add_service("next_question", next_question) + __SERVICES__.add_service("spot_found", spot_found) + __SERVICES__.add_service("spot_not_found", spot_not_found) + +def close(): + global game_host + global game_client + + if game_host != None: game_host.close() + if game_client != None: game_client.close() + |