fix: isolate controller settings side effects

This commit is contained in:
Alexander Sellite 2026-08-16 20:53:15 -04:00
parent a8be597d27
commit 7aaed6393b
6 changed files with 40 additions and 16 deletions

View file

@ -773,7 +773,6 @@ func _initialize_application(dedicated: bool) -> void:
_ui_pixelation.setup_controller_mapping(_controller_mapping_manager)
_game_ui.setup_keyboard_mouse_mapping(_keyboard_mouse_mapping_manager)
_data_root.conflict_detected.connect(_on_portable_conflict)
_data_root.status_changed.connect(_on_data_root_status)
if (
PortableFileGuard.has_syncthing_conflict(
_data_root.root_path.path_join("player")
@ -1103,11 +1102,7 @@ func _on_portable_conflict(message: String, _path: String) -> void:
dialog.dialog_text = (
message
+ "\n\nDo not play the same profile on two devices at the same time."
)
dialog.add_button("Open Data Folder", false, "open")
dialog.custom_action.connect(func(action: StringName) -> void:
if action == &"open":
_data_root.open_folder()
+ "\n\nThe data folder can be opened from Settings > Data."
)
dialog.confirmed.connect(dialog.queue_free)
_game_ui.add_child(dialog)
@ -1121,11 +1116,8 @@ func _on_data_root_status(message: String) -> void:
var dialog: AcceptDialog = AcceptDialog.new()
_interface_fonts.apply_utility_theme(dialog)
dialog.title = "Synced data needs review"
dialog.dialog_text = message
dialog.add_button("Open Data Folder", false, "open")
dialog.custom_action.connect(func(action: StringName) -> void:
if action == &"open":
_data_root.open_folder()
dialog.dialog_text = (
message + "\n\nThe data folder can be opened from Settings > Data."
)
dialog.confirmed.connect(dialog.queue_free)
_game_ui.add_child(dialog)

View file

@ -211,10 +211,6 @@ func storage_mode_text() -> String:
}.get(mode, "Unavailable")
func open_folder() -> bool:
return not root_path.is_empty() and OS.shell_open(root_path) == OK
func report_conflict(message: String, conflict_path: String) -> void:
error_message = message
conflict_detected.emit(message, conflict_path)

View file

@ -8,6 +8,8 @@ readonly GODOT_BIN="${GODOT_BIN:-godot}"
readonly TEST_TIMEOUT_SECONDS="${TEST_TIMEOUT_SECONDS:-120}"
readonly RUN_ROOT="$(mktemp -d -t netfishing-validations.XXXXXX)"
export NETFISHING_ISOLATED_VALIDATION_STORAGE=1
readonly -a QUICK_TESTS=(
"scripts/validate_animalese_samples.gd"
"tests/android_readiness_validation.gd"

View file

@ -6,6 +6,9 @@ const SETTINGS_PATH: String = "user://player_settings.json"
const TEMP_PATH: String = "user://player_settings.json.tmp"
const BACKUP_PATH: String = "user://player_settings.json.backup"
const SILENT_VOLUME_DB: float = -80.0
const HEADLESS_WRITE_ENVIRONMENT: String = (
"NETFISHING_ISOLATED_VALIDATION_STORAGE"
)
signal settings_changed(settings: PlayerSettings)
@ -197,6 +200,15 @@ func save_chat_preferences() -> bool:
func save_now() -> bool:
if (
OS.has_feature("editor")
and DisplayServer.get_name() == "headless"
and not OS.has_environment(HEADLESS_WRITE_ENVIRONMENT)
):
push_error(
"Refusing to write player settings from an unisolated headless editor run."
)
return false
if current_settings == null or not current_settings.is_valid():
return false
var data: Dictionary = {

View file

@ -210,6 +210,25 @@ func _validate_join_game_navigation() -> void:
func _validate_data_settings_navigation() -> void:
var main_source: String = FileAccess.get_file_as_string("res://main/main.gd")
var data_root_source: String = FileAccess.get_file_as_string(
"res://network/player_data_root.gd"
)
var settings_source: String = FileAccess.get_file_as_string(
"res://ui/settings_panel.gd"
)
_expect(
not main_source.contains("OS.shell_open")
and not main_source.contains(
"status_changed.connect(_on_data_root_status)"
)
and not data_root_source.contains("OS.shell_open")
and settings_source.count("OS.shell_open") == 1,
(
"Opening the data folder is not owned exclusively by the Settings "
+ "Data action."
),
)
var panel := SettingsPanelScene.instantiate() as SettingsPanel
root.add_child(panel)
await process_frame

View file

@ -623,7 +623,10 @@ func _open_data_folder() -> void:
if _data_root == null:
_feedback.text = "the data folder is unavailable."
return
if not _data_root.open_folder():
if (
_data_root.root_path.is_empty()
or OS.shell_open(_data_root.root_path) != OK
):
_feedback.text = "could not open the data folder."