def main(): logging_config.init_logging(VERSION) logging.debug("Python version %s", sys.version) game: Optional[Game] = None args = parse_args() # TODO: Flesh out data and then make unconditional. if args.warn_missing_weapon_data: lint_weapon_data() if args.subcommand == "new-game": with logged_duration("New game creation"): game = create_game( args.campaign, args.blue, args.red, args.supercarrier, args.auto_procurement, args.inverted, args.cheats, ) run_ui(game)
def process_debriefing(self): with logged_duration("Turn processing"): self.sim_controller.process_results(self.debriefing) self.game.pass_turn() GameUpdateSignal.get_instance().sendDebriefing(self.debriefing) GameUpdateSignal.get_instance().updateGame(self.game) self.close()
def process_debriefing(self): with logged_duration("Turn processing"): self.game.finish_event(event=self.gameEvent, debriefing=self.debriefing) self.game.pass_turn() GameUpdateSignal.get_instance().sendDebriefing(self.debriefing) GameUpdateSignal.get_instance().updateGame(self.game) self.close()
def save_game(game: Game) -> bool: with logged_duration("Saving game"): try: with open(_temporary_save_file(), "wb") as f: pickle.dump(game, f) shutil.copy(_temporary_save_file(), game.savepath) return True except Exception: logging.exception("Could not save game") return False
def plan_missions(self) -> None: """Identifies and plans mission for the turn.""" player = "Blue" if self.is_player else "Red" with logged_duration(f"{player} mission identification and fulfillment"): with MultiEventTracer() as tracer: for proposed_mission in self.propose_missions(): self.plan_mission(proposed_mission, tracer) with logged_duration(f"{player} reserve mission planning"): with MultiEventTracer() as tracer: for critical_mission in self.critical_missions(): self.plan_mission(critical_mission, tracer, reserves=True) with logged_duration(f"{player} mission scheduling"): self.stagger_missions() for cp in self.objective_finder.friendly_control_points(): inventory = self.game.aircraft_inventory.for_control_point(cp) for aircraft, available in inventory.all_aircraft: self.message("Unused aircraft", f"{available} {aircraft} from {cp}")
def initialize_turn(self) -> None: """Processes coalition-specific turn initialization. For more information on turn initialization in general, see the documentation for `Game.initialize_turn`. """ # Needs to happen *before* planning transfers so we don't cancel them. self.ato.clear() self.air_wing.reset() self.refund_outstanding_orders() self.procurement_requests.clear() with logged_duration("Transit network identification"): self.update_transit_network() with logged_duration("Procurement of airlift assets"): self.transfers.order_airlift_assets() with logged_duration("Transport planning"): self.transfers.plan_transports() self.plan_missions() self.plan_procurement()
def __init__(self, miz: Path, theater: ConflictTheater) -> None: self.theater = theater self.mission = Mission() with logged_duration("Loading miz"): self.mission.load_file(str(miz)) # If there are no red carriers there usually aren't red units. Make sure # both countries are initialized so we don't have to deal with None. if self.mission.country(self.BLUE_COUNTRY.name) is None: self.mission.coalition["blue"].add_country(self.BLUE_COUNTRY) if self.mission.country(self.RED_COUNTRY.name) is None: self.mission.coalition["red"].add_country(self.RED_COUNTRY)
def import_templates(self) -> None: """This will import all layouts from the template folder and dumps them to a pickle""" self._layouts = {} mappings: dict[str, list[LayoutMapping]] = defaultdict(list) with logged_duration("Parsing mapping yamls"): for file in Path(TEMPLATE_DIR).rglob("*.yaml"): if not file.is_file(): raise RuntimeError(f"{file.name} is not a file") with file.open("r", encoding="utf-8") as f: mapping_dict = yaml.safe_load(f) template_map = LayoutMapping.from_dict(mapping_dict, f.name) mappings[template_map.layout_file].append(template_map) with logged_duration(f"Parsing all layout miz multithreaded"): with ThreadPoolExecutor() as exe: exe.map(self._load_from_miz, mappings.keys(), mappings.values()) logging.info(f"Imported {len(self._layouts)} layouts") self._dump_templates()
def reset(self) -> None: if self.game_model.game is None: self.clear() return with logged_duration("Map reset"): self.reset_control_points() self.reset_ground_objects() self.reset_routes() self.reset_atos() self.reset_front_lines() self.reset_threat_zones() self.reset_navmeshes() self.reset_map_zones() self.reset_unculled_zones()
def main(): logging_config.init_logging(VERSION) logging.debug("Python version %s", sys.version) if not str(Path(__file__)).isascii(): logging.warning( "Installation path contains non-ASCII characters. This is known to cause problems." ) game: Optional[Game] = None args = parse_args() # TODO: Flesh out data and then make unconditional. if args.warn_missing_weapon_data: lint_all_weapon_data() load_mods() if args.subcommand == "new-game": with logged_duration("New game creation"): game = create_game( args.campaign, args.blue, args.red, args.supercarrier, args.auto_procurement, args.inverted, args.cheats, args.date, args.restrict_weapons_by_date, ) if args.subcommand == "lint-weapons": lint_weapon_data_for_aircraft(AircraftType.named(args.aircraft)) return with Server().run_in_thread(): run_ui(game, args.dev)
def launch_mission(self): """Finishes planning and waits for mission completion.""" if not self.ato_has_clients() and not self.confirm_no_client_launch(): return if self.check_no_missing_pilots(): return negative_starts = self.negative_start_packages() if negative_starts: if not self.confirm_negative_start_time(negative_starts): return if self.game.settings.fast_forward_to_first_contact: with logged_duration("Simulating to first contact"): self.sim_controller.run_to_first_contact() self.sim_controller.generate_miz( persistency.mission_path_for("liberation_nextturn.miz")) waiting = QWaitingForMissionResultWindow(self.game, self.sim_controller, self) waiting.exec_()
def load_theater(self) -> ConflictTheater: theaters = { "Caucasus": CaucasusTheater, "Nevada": NevadaTheater, "Persian Gulf": PersianGulfTheater, "Normandy": NormandyTheater, "The Channel": TheChannelTheater, "Syria": SyriaTheater, "MarianaIslands": MarianaIslandsTheater, } theater = theaters[self.data["theater"]] t = theater() try: miz = self.data["miz"] except KeyError as ex: raise RuntimeError( "Old format (non-miz) campaigns are no longer supported." ) from ex with logged_duration("Importing miz data"): MizCampaignLoader(self.path.parent / miz, t).populate_theater() return t
def passTurn(self): with logged_duration("Skipping turn"): self.game.pass_turn(no_action=True) GameUpdateSignal.get_instance().updateGame(self.game) self.proceedButton.setEnabled(True)
def initialize(self) -> None: if not self._layouts: with logged_duration("Loading layouts"): self.load_templates()
def _load_from_miz(self, miz: str, mappings: list[LayoutMapping]) -> None: template_position: dict[str, Point] = {} temp_mis = dcs.Mission() with logged_duration(f"Parsing {miz}"): # The load_file takes a lot of time to compute. That's why the layouts # are written to a pickle and can be reloaded from the ui # Example the whole routine: 0:00:00.934417, # the .load_file() method: 0:00:00.920409 temp_mis.load_file(miz) for mapping in mappings: # Find the group from the mapping in any coalition for country in itertools.chain( temp_mis.coalition["red"].countries.values(), temp_mis.coalition["blue"].countries.values(), ): for dcs_group in itertools.chain( temp_mis.country(country.name).vehicle_group, temp_mis.country(country.name).ship_group, temp_mis.country(country.name).static_group, ): try: g_id, group_name, group_mapping = mapping.group_for_name( dcs_group.name) except KeyError: continue if not isinstance(dcs_group, StaticGroup) and max( group_mapping.unit_count) > len(dcs_group.units): logging.error( f"Incorrect unit_count found in Layout {mapping.name}-{group_mapping.name}" ) layout = self._layouts.get(mapping.name, None) if layout is None: # Create a new template layout = TEMPLATE_TYPES[mapping.primary_role]( mapping.name, mapping.description) layout.generic = mapping.generic layout.tasks = mapping.tasks self._layouts[layout.name] = layout for i, unit in enumerate(dcs_group.units): group_layout = None for group in layout.all_groups: if group.name == group_mapping.name: # We already have a layoutgroup for this dcs_group group_layout = group if not group_layout: group_layout = TgoLayoutGroup( group_mapping.name, [], group_mapping.unit_count, group_mapping.unit_types, group_mapping.unit_classes, group_mapping.fallback_classes, ) group_layout.optional = group_mapping.optional group_layout.fill = group_mapping.fill # Add the group at the correct index layout.add_layout_group(group_name, group_layout, g_id) layout_unit = LayoutUnit.from_unit(unit) if i == 0 and layout.name not in template_position: template_position[layout.name] = unit.position layout_unit.position = (layout_unit.position - template_position[layout.name]) group_layout.layout_units.append(layout_unit)