mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
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).
This commit is contained in:
@@ -6,7 +6,7 @@ from shutil import copyfile
|
||||
|
||||
import dcs
|
||||
|
||||
from game import persistency
|
||||
from game import persistence
|
||||
|
||||
global __dcs_saved_game_directory
|
||||
global __dcs_installation_directory
|
||||
@@ -61,7 +61,7 @@ def init():
|
||||
__dcs_installation_directory = ""
|
||||
|
||||
is_first_start = True
|
||||
persistency.setup(__dcs_saved_game_directory)
|
||||
persistence.set_dcs_save_game_directory(Path(__dcs_saved_game_directory))
|
||||
return is_first_start
|
||||
|
||||
|
||||
@@ -70,10 +70,10 @@ def setup(saved_game_dir, install_dir):
|
||||
global __dcs_installation_directory
|
||||
__dcs_saved_game_directory = saved_game_dir
|
||||
__dcs_installation_directory = install_dir
|
||||
persistency.setup(__dcs_saved_game_directory)
|
||||
persistence.set_dcs_save_game_directory(Path(__dcs_saved_game_directory))
|
||||
|
||||
|
||||
def setup_last_save_file(last_save_file):
|
||||
def setup_last_save_file(last_save_file: str) -> None:
|
||||
global __last_save_file
|
||||
__last_save_file = last_save_file
|
||||
|
||||
@@ -114,11 +114,10 @@ def set_ignore_empty_install_directory(value: bool):
|
||||
__ignore_empty_install_directory = value
|
||||
|
||||
|
||||
def get_last_save_file():
|
||||
def get_last_save_file() -> Path | None:
|
||||
global __last_save_file
|
||||
print(__last_save_file)
|
||||
if os.path.exists(__last_save_file):
|
||||
return __last_save_file
|
||||
return Path(__last_save_file)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ from PySide6.QtGui import QPixmap
|
||||
from PySide6.QtWidgets import QApplication, QCheckBox, QSplashScreen
|
||||
from dcs.payloads import PayloadDirectories
|
||||
|
||||
from game import Game, VERSION, logging_config, persistency
|
||||
from game import Game, VERSION, logging_config, persistence
|
||||
from game.campaignloader.campaign import Campaign, DEFAULT_BUDGET
|
||||
from game.data.weapons import Pylon, Weapon, WeaponGroup
|
||||
from game.dcs.aircrafttype import AircraftType
|
||||
@@ -85,14 +85,14 @@ def run_ui(game: Game | None, ui_flags: UiFlags) -> None:
|
||||
window = QLiberationFirstStartWindow()
|
||||
window.exec_()
|
||||
|
||||
logging.info("Using {} as 'Saved Game Folder'".format(persistency.base_path()))
|
||||
logging.info("Using {} as 'Saved Game Folder'".format(persistence.base_path()))
|
||||
logging.info(
|
||||
"Using {} as 'DCS installation folder'".format(
|
||||
liberation_install.get_dcs_install_directory()
|
||||
)
|
||||
)
|
||||
|
||||
inject_custom_payloads(Path(persistency.base_path()))
|
||||
inject_custom_payloads(Path(persistence.base_path()))
|
||||
|
||||
# Splash screen setup
|
||||
pixmap = QPixmap("./resources/ui/splash_screen.png")
|
||||
@@ -271,7 +271,7 @@ def create_game(
|
||||
# Without this, it is not possible to use next turn (or anything that needs to check
|
||||
# for loadouts) without saving the generated campaign and reloading it the normal
|
||||
# way.
|
||||
inject_custom_payloads(Path(persistency.base_path()))
|
||||
inject_custom_payloads(Path(persistence.base_path()))
|
||||
campaign = Campaign.from_file(campaign_path)
|
||||
theater = campaign.load_theater(advanced_iads)
|
||||
generator = GameGenerator(
|
||||
|
||||
@@ -11,7 +11,7 @@ from PySide6.QtWidgets import (
|
||||
)
|
||||
|
||||
import qt_ui.uiconstants as CONST
|
||||
from game import Game, persistency
|
||||
from game import Game, persistence
|
||||
from game.ato.package import Package
|
||||
from game.ato.traveltime import TotEstimator
|
||||
from game.profiling import logged_duration
|
||||
@@ -290,7 +290,7 @@ class QTopPanel(QFrame):
|
||||
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")
|
||||
persistence.mission_path_for("liberation_nextturn.miz")
|
||||
)
|
||||
|
||||
waiting = QWaitingForMissionResultWindow(self.game, self.sim_controller, self)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import logging
|
||||
import traceback
|
||||
import webbrowser
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from PySide6.QtCore import QSettings, Qt, Signal
|
||||
@@ -16,9 +17,10 @@ from PySide6.QtWidgets import (
|
||||
)
|
||||
|
||||
import qt_ui.uiconstants as CONST
|
||||
from game import Game, VERSION, persistency
|
||||
from game import Game, VERSION
|
||||
from game.debriefing import Debriefing
|
||||
from game.layout import LAYOUTS
|
||||
from game.persistence import SaveManager
|
||||
from game.server import EventStream, GameContext
|
||||
from game.server.dependencies import QtCallbacks, QtContext
|
||||
from game.theater import ControlPoint, MissionTarget, TheaterGroundObject
|
||||
@@ -106,11 +108,11 @@ class QLiberationWindow(QMainWindow):
|
||||
if last_save_file:
|
||||
try:
|
||||
logging.info("Loading last saved game : " + str(last_save_file))
|
||||
game = persistency.load_game(last_save_file)
|
||||
game = SaveManager.load_player_save(last_save_file)
|
||||
self.onGameGenerated(game)
|
||||
self.updateWindowTitle(last_save_file if game else None)
|
||||
except:
|
||||
logging.info("Error loading latest save game")
|
||||
logging.exception("Error loading latest save game")
|
||||
else:
|
||||
logging.info("No existing save game")
|
||||
else:
|
||||
@@ -316,58 +318,61 @@ class QLiberationWindow(QMainWindow):
|
||||
wizard.accepted.connect(lambda: self.onGameGenerated(wizard.generatedGame))
|
||||
|
||||
def openFile(self):
|
||||
if self.game is not None and self.game.savepath:
|
||||
save_dir = self.game.savepath
|
||||
if (
|
||||
self.game is not None
|
||||
and self.game.save_manager.player_save_location is not None
|
||||
):
|
||||
save_dir = str(self.game.save_manager.player_save_location)
|
||||
else:
|
||||
save_dir = str(persistency.save_dir())
|
||||
save_dir = str(SaveManager.default_save_directory())
|
||||
file = QFileDialog.getOpenFileName(
|
||||
self,
|
||||
"Select game file to open",
|
||||
dir=save_dir,
|
||||
filter="*.liberation",
|
||||
filter="*.liberation.zip",
|
||||
)
|
||||
if file is not None and file[0] != "":
|
||||
game = persistency.load_game(file[0])
|
||||
GameUpdateSignal.get_instance().game_loaded.emit(game)
|
||||
try:
|
||||
game = SaveManager.load_player_save(Path(file[0]))
|
||||
GameUpdateSignal.get_instance().game_loaded.emit(game)
|
||||
|
||||
self.updateWindowTitle(file[0])
|
||||
self.updateWindowTitle(Path(file[0]))
|
||||
except Exception:
|
||||
logging.exception("Error loading save game %s", file[0])
|
||||
|
||||
def saveGame(self):
|
||||
logging.info("Saving game")
|
||||
|
||||
if self.game.savepath:
|
||||
persistency.save_game(self.game)
|
||||
liberation_install.setup_last_save_file(self.game.savepath)
|
||||
liberation_install.save_config()
|
||||
if self.game.save_manager.player_save_location is not None:
|
||||
self.game.save_manager.save_player()
|
||||
else:
|
||||
self.saveGameAs()
|
||||
|
||||
def saveGameAs(self):
|
||||
if self.game is not None and self.game.savepath:
|
||||
save_dir = self.game.savepath
|
||||
if (
|
||||
self.game is not None
|
||||
and self.game.save_manager.player_save_location is not None
|
||||
):
|
||||
save_dir = str(self.game.save_manager.player_save_location)
|
||||
else:
|
||||
save_dir = str(persistency.save_dir())
|
||||
save_dir = str(SaveManager.default_save_directory())
|
||||
file = QFileDialog.getSaveFileName(
|
||||
self,
|
||||
"Save As",
|
||||
dir=save_dir,
|
||||
filter="*.liberation",
|
||||
filter="*.liberation.zip",
|
||||
)
|
||||
if file is not None:
|
||||
self.game.savepath = file[0]
|
||||
persistency.save_game(self.game)
|
||||
liberation_install.setup_last_save_file(self.game.savepath)
|
||||
liberation_install.save_config()
|
||||
if file is not None and file[0]:
|
||||
self.game.save_manager.save_player(override_destination=Path(file[0]))
|
||||
self.updateWindowTitle(Path(file[0]))
|
||||
|
||||
self.updateWindowTitle(file[0])
|
||||
|
||||
def updateWindowTitle(self, save_path: Optional[str] = None) -> None:
|
||||
def updateWindowTitle(self, save_path: Path | None = None) -> None:
|
||||
"""
|
||||
to DCS Liberation - vX.X.X - file_name
|
||||
"""
|
||||
window_title = f"DCS Liberation - v{VERSION}"
|
||||
if save_path: # appending the file name to title as it is updated
|
||||
file_name = save_path.split("/")[-1].split(".liberation")[0]
|
||||
file_name = save_path.name.split(".liberation.zip")[0]
|
||||
window_title = f"{window_title} - {file_name}"
|
||||
self.setWindowTitle(window_title)
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
@@ -23,7 +22,6 @@ from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||
|
||||
from game import Game
|
||||
from game.debriefing import Debriefing
|
||||
from game.persistency import base_path
|
||||
from game.profiling import logged_duration
|
||||
from qt_ui.simcontroller import SimController
|
||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||
@@ -221,9 +219,6 @@ class QWaitingForMissionResultWindow(QDialog):
|
||||
GameUpdateSignal.get_instance().updateGame(self.game)
|
||||
self.close()
|
||||
|
||||
def debriefing_directory_location(self) -> str:
|
||||
return os.path.join(base_path(), "liberation_debriefings")
|
||||
|
||||
def closeEvent(self, evt):
|
||||
super(QWaitingForMissionResultWindow, self).closeEvent(evt)
|
||||
if self.wait_thread is not None:
|
||||
|
||||
Reference in New Issue
Block a user