diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 029ef547..d7d547b7 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -73,7 +73,8 @@ body: The `state.json` file for the most recently completed turn, located at `/state.json`. This file is essential for - investigating any issues with end-of-turn results processing. + investigating any issues with end-of-turn results processing. **If you + include this file, also include `last_turn.liberation`.** You can attach files to the bug by dragging and dropping the file into diff --git a/changelog.md b/changelog.md index 263c5345..a0a34ccc 100644 --- a/changelog.md +++ b/changelog.md @@ -17,6 +17,7 @@ Saves from 6.0.0 are compatible with 6.1.0 * **[Factions]** Added Peru. * **[Flight Planning]** Refueling flights planned on aircraft carriers will act as a recovery tanker for the carrier. * **[Loadouts]** Adjusted F-15E loadouts. +* **[Mission Generation]** The previous turn will now be saved as last_turn.liberation when submitting mission results. This is often essential for debugging bug reports. **Include this file in the bug report whenever it is available.** * **[Modding]** Added support for the HMS Ariadne, Achilles, and Castle class. * **[Modding]** Added HMS Invincible to the game data as a helicopter carrier. diff --git a/game/game.py b/game/game.py index d2054682..e4885e2f 100644 --- a/game/game.py +++ b/game/game.py @@ -332,6 +332,8 @@ class Game: from .server import EventStream from .sim import GameUpdateEvents + persistency.save_last_turn_state(self) + events = GameUpdateEvents() logging.info("Pass turn") diff --git a/game/persistency.py b/game/persistency.py index 9b982407..383fc799 100644 --- a/game/persistency.py +++ b/game/persistency.py @@ -31,8 +31,8 @@ def save_dir() -> Path: return Path(base_path()) / "Liberation" / "Saves" -def _temporary_save_file() -> str: - return str(save_dir() / "tmpsave.liberation") +def _temporary_save_file() -> Path: + return save_dir() / "tmpsave.liberation" def _autosave_path() -> str: @@ -54,16 +54,18 @@ def load_game(path: str) -> Optional[Game]: return None -def save_game(game: Game) -> bool: +def save_game(game: Game, destination: Path | None = None) -> None: + if destination is None: + destination = Path(game.savepath) + + temp_save_file = _temporary_save_file() with logged_duration("Saving game"): try: - with open(_temporary_save_file(), "wb") as f: + with temp_save_file.open("wb") as f: pickle.dump(game, f) - shutil.copy(_temporary_save_file(), game.savepath) - return True + shutil.copy(temp_save_file, destination) except Exception: logging.exception("Could not save game") - return False def autosave(game: Game) -> bool: @@ -79,3 +81,7 @@ def autosave(game: Game) -> bool: except Exception: logging.exception("Could not save game") return False + + +def save_last_turn_state(game: Game) -> None: + save_game(game, save_dir() / "last_turn.liberation") diff --git a/game/sim/missionsimulation.py b/game/sim/missionsimulation.py index c96e7846..a0f2fffa 100644 --- a/game/sim/missionsimulation.py +++ b/game/sim/missionsimulation.py @@ -5,6 +5,7 @@ from datetime import timedelta from pathlib import Path from typing import Optional, TYPE_CHECKING +from game import persistency from game.debriefing import Debriefing from game.missiongenerator import MissionGenerator from game.unitmap import UnitMap @@ -73,6 +74,7 @@ class MissionSimulation: "was generated." ) + persistency.save_last_turn_state(self.game) MissionResultsProcessor(self.game).commit(debriefing, events) def finish(self) -> None: