diff --git a/changelog.md b/changelog.md index 99991388..b1bbe612 100644 --- a/changelog.md +++ b/changelog.md @@ -15,7 +15,7 @@ Saves from 6.x are not compatible with 7.0. * **[Modding]** Custom factions can now be defined in YAML as well as JSON. JSON support may be removed in the future if having both formats causes confusion. * **[Modding]** Campaigns which require custom factions can now define those factions directly in the campaign YAML. See Operation Aliied Sword for an example. * **[Modding]** The `mission_types` field in squadron files has been removed. Squadron task capability is now determined by airframe, and the auto-assignable list has always been overridden by the campaign settings. -* **[New Game Wizard]** Some game settings are now saved to be reused for the next game. At present this is a small set (just supercarrier and auto-purchase), but it will be expanded later. +* **[New Game Wizard]** Choices for some options will be remembered for the next new game. Not all settings will be preserved, as many are campaign dependent. * **[New Game Wizard]** Lua plugins can now be set while creating a new game. * **[Squadrons]** Squadron-specific mission capability lists no longer restrict players from assigning missions outside the squadron's preferences. diff --git a/game/plugins/manager.py b/game/plugins/manager.py index 9ea225fa..70b42d33 100644 --- a/game/plugins/manager.py +++ b/game/plugins/manager.py @@ -4,7 +4,11 @@ import json import logging from collections.abc import Iterator from pathlib import Path +from typing import Any +import yaml + +from game.persistence.paths import liberation_user_dir from .luaplugin import LuaPlugin @@ -74,3 +78,51 @@ class LuaPluginManager: return self.by_id(plugin_id).is_option_enabled(option_id) except KeyError: return False + + def save_player_settings(self) -> None: + """Saves the player's global settings to the user directory.""" + settings: dict[str, dict[str, Any]] = {} + for plugin in self.iter_plugins(): + if not plugin.show_in_ui: + continue + + plugin_settings: dict[str, Any] = {"enabled": plugin.enabled} + if plugin.options: + plugin_settings["options"] = {} + settings[plugin.identifier] = plugin_settings + for option in plugin.options: + plugin_settings["options"][option.identifier] = option.enabled + + with self._player_settings_file.open("w", encoding="utf-8") as settings_file: + yaml.dump(settings, settings_file, sort_keys=False, explicit_start=True) + + def merge_player_settings(self) -> None: + """Updates with the player's global settings.""" + settings_path = self._player_settings_file + if not settings_path.exists(): + return + with settings_path.open(encoding="utf-8") as settings_file: + data = yaml.safe_load(settings_file) + + for plugin_id, plugin_data in data.items(): + try: + plugin = self.by_id(plugin_id) + except KeyError: + logging.warning( + "Unexpected plugin ID found in %s: %s. Ignoring.", + settings_path, + plugin_id, + ) + continue + + plugin.enabled = plugin_data["enabled"] + for option in plugin.options: + try: + option.enabled = plugin_data["options"][option.identifier] + except KeyError: + pass + + @property + def _player_settings_file(self) -> Path: + """Returns the path to the player's global settings file.""" + return liberation_user_dir() / "plugins.yaml" diff --git a/game/settings/settings.py b/game/settings/settings.py index bf849477..54b4195b 100644 --- a/game/settings/settings.py +++ b/game/settings/settings.py @@ -499,14 +499,6 @@ class Settings: if description.remember_player_choice: settings[name] = self.__dict__[name] - # Plugin settings are currently not handled. It looks like the PluginManager - # probably needs some changes to do so safely. When injecting plugin options - # into Settings with LuaPluginManager.load_settings, it sets a reference to the - # passed Settings object. The lifetime is unclear, but it might be the case that - # canceling the NGW would leave LuaPluginManager in a bad state (yes, we could - # reset it on cancel, but that's just one bug I've thought of and without better - # understanding of how that works it's hard to say where more could be lurking). - with self._player_settings_file.open("w", encoding="utf-8") as settings_file: yaml.dump(settings, settings_file, sort_keys=False, explicit_start=True) diff --git a/qt_ui/windows/newgame/QNewGameWizard.py b/qt_ui/windows/newgame/QNewGameWizard.py index 7d29dceb..a172ad74 100644 --- a/qt_ui/windows/newgame/QNewGameWizard.py +++ b/qt_ui/windows/newgame/QNewGameWizard.py @@ -97,6 +97,7 @@ class NewGameWizard(QtWidgets.QWizard): default_settings.merge_player_settings() self.lua_plugin_manager = LuaPluginManager.load() + self.lua_plugin_manager.merge_player_settings() factions = Factions.load() @@ -149,6 +150,8 @@ class NewGameWizard(QtWidgets.QWizard): else: start_date = self.theater_page.calendar.selectedDate().toPython() + self.lua_plugin_manager.save_player_settings() + logging.info("New campaign start date: %s", start_date.strftime("%m/%d/%Y")) settings = Settings( player_income_multiplier=self.field("player_income_multiplier") / 10,