Remember player preferences for plugins.

This commit is contained in:
Dan Albert 2023-04-26 00:13:03 -07:00
parent 081c97583b
commit cf47dd82d7
4 changed files with 56 additions and 9 deletions

View File

@ -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]** 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]** 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. * **[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. * **[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. * **[Squadrons]** Squadron-specific mission capability lists no longer restrict players from assigning missions outside the squadron's preferences.

View File

@ -4,7 +4,11 @@ import json
import logging import logging
from collections.abc import Iterator from collections.abc import Iterator
from pathlib import Path from pathlib import Path
from typing import Any
import yaml
from game.persistence.paths import liberation_user_dir
from .luaplugin import LuaPlugin from .luaplugin import LuaPlugin
@ -74,3 +78,51 @@ class LuaPluginManager:
return self.by_id(plugin_id).is_option_enabled(option_id) return self.by_id(plugin_id).is_option_enabled(option_id)
except KeyError: except KeyError:
return False 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"

View File

@ -499,14 +499,6 @@ class Settings:
if description.remember_player_choice: if description.remember_player_choice:
settings[name] = self.__dict__[name] 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: with self._player_settings_file.open("w", encoding="utf-8") as settings_file:
yaml.dump(settings, settings_file, sort_keys=False, explicit_start=True) yaml.dump(settings, settings_file, sort_keys=False, explicit_start=True)

View File

@ -97,6 +97,7 @@ class NewGameWizard(QtWidgets.QWizard):
default_settings.merge_player_settings() default_settings.merge_player_settings()
self.lua_plugin_manager = LuaPluginManager.load() self.lua_plugin_manager = LuaPluginManager.load()
self.lua_plugin_manager.merge_player_settings()
factions = Factions.load() factions = Factions.load()
@ -149,6 +150,8 @@ class NewGameWizard(QtWidgets.QWizard):
else: else:
start_date = self.theater_page.calendar.selectedDate().toPython() 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")) logging.info("New campaign start date: %s", start_date.strftime("%m/%d/%Y"))
settings = Settings( settings = Settings(
player_income_multiplier=self.field("player_income_multiplier") / 10, player_income_multiplier=self.field("player_income_multiplier") / 10,