Dan Albert 0f34946127 Restructure save games into a zipped bundle.
This is the first step toward bundling all assets related to a save game
into a single item. That makes it easier to avoid clobbering "temporary"
assets from other games like the state.json, but also makes it easier
for players to file bug reports, since there's only a single asset to
upload.

This is only the first step because so far it only includes the various
save files: start of turn, end of last turn before results processing,
and "latest" (the game saved explicitly by the player).
2023-01-16 13:59:16 -08:00

81 lines
2.6 KiB
Python

from __future__ import annotations
from collections.abc import Iterator
from contextlib import contextmanager
from pathlib import Path
from typing import TYPE_CHECKING
from qt_ui import liberation_install
from .paths import save_dir
from .savegamebundle import SaveGameBundle
if TYPE_CHECKING:
from game.game import Game
class SaveManager:
def __init__(self, game: Game) -> None:
self.game = game
self.player_save_location: Path | None = None
self.autosave_path = self.default_save_directory() / "autosave.liberation.zip"
self.last_saved_bundle: SaveGameBundle | None = None
@property
def default_save_location(self) -> Path:
if self.player_save_location is not None:
return self.player_save_location
return self.autosave_path
@property
def default_save_bundle(self) -> SaveGameBundle:
return SaveGameBundle(self.default_save_location)
def save_player(self, override_destination: Path | None = None) -> None:
copy_from = self.last_saved_bundle
with self._save_bundle_context(override_destination) as bundle:
self.player_save_location = bundle.bundle_path
bundle.save_player(self.game, copy_from)
liberation_install.setup_last_save_file(str(bundle.bundle_path))
liberation_install.save_config()
def save_last_turn(self) -> None:
with self._save_bundle_context() as bundle:
bundle.save_last_turn(self.game)
def save_start_of_turn(self) -> None:
with self._save_bundle_context() as bundle:
bundle.save_start_of_turn(self.game)
@contextmanager
def _save_bundle_context(
self, override_destination: Path | None = None
) -> Iterator[SaveGameBundle]:
if override_destination is not None:
bundle = SaveGameBundle(override_destination)
else:
bundle = self.default_save_bundle
previous_saved_bundle = self.last_saved_bundle
try:
self.last_saved_bundle = bundle
yield bundle
except Exception:
self.last_saved_bundle = previous_saved_bundle
raise
@staticmethod
def load_last_turn(bundle_path: Path) -> Game:
return SaveGameBundle(bundle_path).load_last_turn()
@staticmethod
def load_start_of_turn(bundle_path: Path) -> Game:
return SaveGameBundle(bundle_path).load_start_of_turn()
@staticmethod
def load_player_save(bundle_path: Path) -> Game:
return SaveGameBundle(bundle_path).load_player()
@staticmethod
def default_save_directory() -> Path:
return save_dir()