def prepare_multiplayer(game, trader_enabled = True, pirate_enabled = True, natural_resource_multiplier = 1): """Starts a multiplayer game server TODO: acctual game data parameter passing """ global fife, preloading, db preload_game_join(preloading) # remove cursor while loading fife.cursor.set(fife_module.CURSOR_NONE) fife.engine.pump() fife.set_cursor_image('default') # hide whatever is displayed before the game starts _modules.gui.hide() # destruct old session (right now, without waiting for gc) if _modules.session is not None and _modules.session.is_alive: _modules.session.end() # start new session from mpsession import MPSession # get random seed for game uuid = game.get_uuid() random = sum([ int(uuid[i : i + 2], 16) for i in range(0, len(uuid), 2) ]) _modules.session = MPSession(_modules.gui, db, NetworkInterface(), rng_seed=random) # NOTE: this data passing is only temporary, maybe use a player class/struct if game.load: map_file = SavegameManager.get_multiplayersave_map( game.get_map_name() ) else: map_file = SavegameManager.get_map( game.get_map_name() ) _modules.session.load(map_file, game.get_player_list(), trader_enabled, pirate_enabled, natural_resource_multiplier)
def prepare_multiplayer(game, trader_enabled=True, pirate_enabled=True, natural_resource_multiplier=1): """Starts a multiplayer game server TODO: actual game data parameter passing """ _modules.gui.show_loading_screen() preloader.wait_for_finish() # remove cursor while loading horizons.globals.fife.cursor.set(fife_module.CURSOR_NONE) horizons.globals.fife.engine.pump() horizons.globals.fife.set_cursor_image('default') # destruct old session (right now, without waiting for gc) if _modules.session is not None and _modules.session.is_alive: _modules.session.end() # start new session from horizons.mpsession import MPSession # get random seed for game uuid = game.uuid random = sum([int(uuid[i : i + 2], 16) for i in range(0, len(uuid), 2)]) _modules.session = MPSession(horizons.globals.db, NetworkInterface(), rng_seed=random) # NOTE: this data passing is only temporary, maybe use a player class/struct if game.is_savegame: map_file = SavegameManager.get_multiplayersave_map(game.map_name) else: map_file = SavegameManager.get_map(game.map_name) options = StartGameOptions.create_start_multiplayer(map_file, game.get_player_list(), not game.is_savegame) _modules.session.load(options)
def prepare_multiplayer(game, trader_enabled=True, pirate_enabled=True, natural_resource_multiplier=1): """Starts a multiplayer game server TODO: actual game data parameter passing """ _modules.gui.show_loading_screen() global preloading preload_game_join(preloading) # remove cursor while loading horizons.globals.fife.cursor.set(fife_module.CURSOR_NONE) horizons.globals.fife.engine.pump() horizons.globals.fife.set_cursor_image('default') # destruct old session (right now, without waiting for gc) if _modules.session is not None and _modules.session.is_alive: _modules.session.end() # start new session from horizons.mpsession import MPSession # get random seed for game uuid = game.uuid random = sum([ int(uuid[i : i + 2], 16) for i in range(0, len(uuid), 2) ]) _modules.session = MPSession(horizons.globals.db, NetworkInterface(), rng_seed=random) # NOTE: this data passing is only temporary, maybe use a player class/struct if game.is_savegame: map_file = SavegameManager.get_multiplayersave_map(game.map_name) else: map_file = SavegameManager.get_map(game.map_name) options = StartGameOptions.create_start_multiplayer(map_file, game.get_player_list(), not game.is_savegame) _modules.session.load(options)
def __create_game(self, load=None, chosen_map=None): """ Actually create a game, join it, and display the lobby. @param load: game data tuple for creating loaded games @param chosen_map: the name of the map to start a new game on (overrides the gui) """ # create the game if load: mapname, gamename = load path = SavegameManager.get_multiplayersave_map(mapname) maxplayers = SavegameAccessor.get_players_num(path) load = SavegameAccessor.get_hash(path) else: mapindex = None if chosen_map is not None: for i, map in enumerate(self.maps_display): if map == chosen_map: mapindex = i break if mapindex is None: mapindex = self.current.collectData('maplist') mapname = self.maps_display[mapindex] maxplayers = self.current.collectData('playerlimit') + 2 # 1 is the first entry gamename = self.current.collectData('gamename') load = None game = NetworkInterface().creategame(mapname, maxplayers, gamename, load) if game is None: return self.__show_gamelobby()
def __join_game(self, game=None): """Joins a multiplayer game. Displays lobby for that specific game""" if game == None: game = self.__get_selected_game() if ( game.load is not None and SavegameAccessor.get_hash(SavegameManager.get_multiplayersave_map(game.mapname)) != game.load ): self.show_popup(_("Error"), self.current.findChild(name="save_missing_help_button").btn_text, size=1) return if game.get_uuid() == -1: # -1 signals no game AmbientSoundComponent.play_special("error") return if game.get_version() != NetworkInterface().get_clientversion(): self.show_popup( _("Wrong version"), # xgettext:python-format _( "The game's version differs from your version. Every player in a multiplayer game must use the same version. This can be fixed by every player updating to the latest version. Game version: {game_version} Your version: {own_version}" ).format(game_version=game.get_version(), own_version=NetworkInterface().get_clientversion()), ) return # actual join join_worked = NetworkInterface().joingame(game.get_uuid()) if not join_worked: return self.__apply_new_nickname() self.__show_gamelobby()
def __update_game_details(self, game=None): """Set map name and other misc data in a widget. Only possible in certain states""" if game == None: game = self.__get_selected_game() # xgettext:python-format self.current.findChild(name="game_map").text = _("Map: {map_name}").format(map_name=game.get_map_name()) self.current.findChild(name="game_name").text = _("Name: {game_name}").format(game_name=game.get_name()) # xgettext:python-format self.current.findChild(name="game_playersnum").text = _("Players: {player_amount}/{player_limit}").format( player_amount=game.get_player_count(), player_limit=game.get_player_limit() ) creator_text = self.current.findChild(name="game_creator") # xgettext:python-format creator_text.text = _("Creator: {player}").format(player=game.get_creator()) creator_text.adaptLayout() vbox_inner = self.current.findChild(name="game_info") if game.load is not None: # work around limitations of current systems via messages path = SavegameManager.get_multiplayersave_map(game.mapname) if SavegameAccessor.get_hash(path) != game.load: text = "" btn_name = "save_missing_help_button" btn = vbox_inner.findChild(name=btn_name) if btn is None: btn = pychan.widgets.Button(name=btn_name, text=_("This savegame is missing (click here)")) last_elem = vbox_inner.findChild(name="game_info_last") if last_elem is None: # no last elem -> we are last vbox_inner.addChild(btn) else: vbox_inner.insertChildBefore(btn, last_elem) btn_text = ( _( u"For multiplayer load, it is currently necessary for you to ensure you have the correct savegame file." ) + u"\n" ) btn_text += _(u"This is not nice and we hope to offer a more convenient solution very soon.") + u"\n" btn_text += _( u"Meanwhile, please request the file {path} from the game creator and put it in {map_directory} ." ).format(path=os.path.basename(path), map_directory=os.path.dirname(path)) btn.btn_text = btn_text def show(): self.show_popup(_("Help"), btn_text, size=1) btn.capture(show) else: text = _(u"This is a savegame.") if text: self.current.findChild(name="game_isloaded").text = text textplayers = self.current.findChild(name="game_players") if textplayers is not None: textplayers.text = u", ".join(game.get_players()) vbox_inner.adaptLayout() # inner vbox always exists vbox = self.current.findChild(name="gamedetailsbox") if vbox is not None: vbox.adaptLayout()
def __send_toggle_ready(self): game = NetworkInterface().get_game() if game.load is not None and \ SavegameAccessor.get_hash(SavegameManager.get_multiplayersave_map(game.mapname)) != game.load: self.__print_event_message("You are fetching savegame data. You must wait for it") return NetworkInterface().send_toggle_ready(NetworkInterface().get_client_name())
def __update_game_details(self, game=None): """Set map name and other misc data in a widget. Only possible in certain states""" if game is None: game = self.__get_selected_game() if game is None: return #xgettext:python-format self.current.findChild(name="game_map").text = _("Map: {map_name}").format(map_name=game.get_map_name()) self.current.findChild(name="game_name").text = _("Name: {game_name}").format(game_name=game.get_name()) self.current.findChild(name="game_creator").text = _("Creator: {game_creator}").format(game_creator=game.get_creator()) #xgettext:python-format self.current.findChild(name="game_playersnum").text = _("Players: {player_amount}/{player_limit}").format( player_amount=game.get_player_count(), player_limit=game.get_player_limit()) vbox_inner = self.current.findChild(name="game_info") if game.is_savegame(): # work around limitations of current systems via messages path = SavegameManager.get_multiplayersave_map(game.mapname) btn_name = "save_missing_help_button" btn = vbox_inner.findChild(name=btn_name) if SavegameAccessor.get_hash(path) != game.get_map_hash(): text = "" if btn is None: btn = Button(name=btn_name) btn.text = _("This savegame is missing (click here)") last_elem = vbox_inner.findChild(name="game_info_last") if last_elem is None: # no last elem -> we are last vbox_inner.addChild( btn ) else: vbox_inner.insertChildBefore( btn, last_elem ) btn_text = _(u"For multiplayer load, it is necessary for you to have the correct savegame file.") + u"\n" btn_text += _(u"The file will be downloaded when the game starts.") btn.btn_text = btn_text def show(): self.show_popup(_("Help"), btn_text, size=1) btn.capture(show) else: text = _(u"This is a savegame.") if btn is not None: btn.hide() if text: self.current.findChild(name="game_isloaded").text = text self.__update_players_box(game) vbox_inner.adaptLayout() # inner vbox always exists vbox = self.current.findChild(name="gamedetailsbox") if vbox is not None: vbox.adaptLayout()
def __actual_join(self, game=None, password=""): """Does the actual joining to the game. This method is called after everything is OK for joining.""" if game is None: return False self.__apply_new_nickname() self.__apply_new_color() fetch = False if game.is_savegame() and SavegameAccessor.get_hash(SavegameManager.get_multiplayersave_map(game.mapname)) != game.get_map_hash(): fetch = True if not NetworkInterface().joingame(game.get_uuid(), password, fetch): return False self.__show_gamelobby() return True
def __actual_join(self, game=None, password=""): """Does the actual joining to the game. This method is called after everything is OK for joining.""" if game is None: return False self.__apply_new_nickname() self.__apply_new_color() fetch = False if game.is_savegame() and SavegameAccessor.get_hash( SavegameManager.get_multiplayersave_map( game.mapname)) != game.get_map_hash(): fetch = True if not NetworkInterface().joingame(game.get_uuid(), password, fetch): return False self.__show_gamelobby() return True
def __create_game(self, load=None, chosen_map=None): """ Actually create a game, join it, and display the lobby. @param load: game data tuple for creating loaded games @param chosen_map: the name of the map to start a new game on (overrides the gui) """ # create the game if load: mapname, gamename, gamepassword = load path = SavegameManager.get_multiplayersave_map(mapname) maxplayers = SavegameAccessor.get_players_num(path) password = gamepassword maphash = SavegameAccessor.get_hash(path) else: mapindex = None if chosen_map is not None: for i, map in enumerate(self.maps_display): if map == chosen_map: mapindex = i break if mapindex is None: mapindex = self.current.collectData('maplist') mapname = self.maps_display[mapindex] maxplayers = self.current.collectData( 'playerlimit') + 2 # 1 is the first entry gamename = self.current.collectData('gamename') password = self.current.collectData('password') maphash = "" password = hashlib.sha1(password).hexdigest() if password != "" else "" game = NetworkInterface().creategame(mapname, maxplayers, gamename, maphash, password) if game is None: return self.__show_gamelobby()
def __join_game(self, game=None): """Joins a multiplayer game. Displays lobby for that specific game""" if game == None: game = self.__get_selected_game() if game.load is not None and SavegameAccessor.get_hash(SavegameManager.get_multiplayersave_map(game.mapname)) != game.load: NetworkInterface().send_fetch_game(NetworkInterface().get_clientversion(), game.get_uuid()) if game.get_uuid() == -1: # -1 signals no game AmbientSoundComponent.play_special('error') return if game.get_version() != NetworkInterface().get_clientversion(): self.show_popup(_("Wrong version"), #xgettext:python-format _("The game's version differs from your version. Every player in a multiplayer game must use the same version. This can be fixed by every player updating to the latest version. Game version: {game_version} Your version: {own_version}").format( game_version=game.get_version(), own_version=NetworkInterface().get_clientversion())) return # actual join if game.password: self.__enter_password_dialog(game) else: self.__actual_join(game)
def __update_game_details(self, game=None): """Set map name and other misc data in a widget. Only possible in certain states""" if game is None: game = self.__get_selected_game() if game is None: return #xgettext:python-format self.current.findChild( name="game_map").text = _("Map: {map_name}").format( map_name=game.get_map_name()) self.current.findChild( name="game_name").text = _("Name: {game_name}").format( game_name=game.get_name()) self.current.findChild( name="game_creator").text = _("Creator: {game_creator}").format( game_creator=game.get_creator()) #xgettext:python-format self.current.findChild(name="game_playersnum").text = _( "Players: {player_amount}/{player_limit}").format( player_amount=game.get_player_count(), player_limit=game.get_player_limit()) vbox_inner = self.current.findChild(name="game_info") if game.is_savegame( ): # work around limitations of current systems via messages path = SavegameManager.get_multiplayersave_map(game.mapname) btn_name = "save_missing_help_button" btn = vbox_inner.findChild(name=btn_name) if SavegameAccessor.get_hash(path) != game.get_map_hash(): text = "" if btn is None: btn = Button(name=btn_name) btn.text = _("This savegame is missing (click here)") last_elem = vbox_inner.findChild(name="game_info_last") if last_elem is None: # no last elem -> we are last vbox_inner.addChild(btn) else: vbox_inner.insertChildBefore(btn, last_elem) btn_text = _( u"For multiplayer load, it is necessary for you to have the correct savegame file." ) + u"\n" btn_text += _( u"The file will be downloaded when the game starts.") btn.btn_text = btn_text def show(): self.show_popup(_("Help"), btn_text, size=1) btn.capture(show) else: text = _(u"This is a savegame.") if btn is not None: btn.hide() if text: self.current.findChild(name="game_isloaded").text = text self.__update_players_box(game) vbox_inner.adaptLayout() # inner vbox always exists vbox = self.current.findChild(name="gamedetailsbox") if vbox is not None: vbox.adaptLayout()
def process_async_packet(self, packet): if packet is None: return True if isinstance(packet[1], packets.server.cmd_chatmsg): # ignore packet if we are not a game lobby if self.game is None: return True self.call_callbacks("lobbygame_chat", self.game, packet[1].playername, packet[1].chatmsg) elif isinstance(packet[1], packets.server.data_gamestate): # ignore packet if we are not a game lobby if self.game is None: return True self.call_callbacks("lobbygame_state", self.game, packet[1].game) #if there is more ready player then show it as chat message if len(self.game.ready_players) < len(packet[1].game.ready_players): self.game = packet[1].game self.call_callbacks("lobbygame_toggleready", self.game, packet[1].game.ready_players[-1]) return True #if there is less ready player then show it as chat message elif len(self.game.ready_players) > len(packet[1].game.ready_players): for nonready in self.game.ready_players: if nonready not in packet[1].game.ready_players: self.game = packet[1].game self.call_callbacks("lobbygame_toggleready", self.game, nonready) return True oldplayers = list(self.game.players) self.game = packet[1].game # calculate changeset for pnew in self.game.players: found = None for pold in oldplayers: if pnew.sid == pold.sid: found = pold myself = pnew.sid == self.sid if pnew.name != pold.name: self.call_callbacks("lobbygame_changename", self.game, pold, pnew, myself) if pnew.color != pold.color: self.call_callbacks("lobbygame_changecolor", self.game, pold, pnew, myself) break if found is None: self.call_callbacks("lobbygame_join", self.game, pnew) else: oldplayers.remove(found) for pold in oldplayers: self.call_callbacks("lobbygame_leave", self.game, pold) return True elif isinstance(packet[1], packets.server.cmd_preparegame): # ignore packet if we are not a game lobby if self.game is None: return True self.ongameprepare() elif isinstance(packet[1], packets.server.cmd_startgame): # ignore packet if we are not a game lobby if self.game is None: return True self.ongamestart() elif isinstance(packet[1], packets.client.game_data): self.log.debug("[GAMEDATA] from %s" % (packet[0].address)) self.call_callbacks("game_data", packet[1].data) elif isinstance(packet[1], packets.server.cmd_kick_player): self.call_callbacks("lobbygame_kickplayer", self.game, packet[1].player) elif isinstance(packet[1], packets.server.cmd_fetch_game): if self.game is None: return True path = SavegameManager.get_multiplayersave_map(self.game.mapname) compressed_data = bz2.compress(open(path).read()) self.send(packets.client.savegame_data(compressed_data, packet[1].psid)) elif isinstance(packet[1], packets.server.savegame_data): open(SavegameManager.get_multiplayersave_map(packet[1].mapname), "w").write(bz2.decompress(packet[1].data)) self.call_callbacks("savegame_data", self.game) return False