2026-10-09 12:49:07 +02:00

67 lines
3.0 KiB
GDScript

@tool
extends RefCounted
## Monitors the ProjectSettings that shift the user:// base path.
##
## Godot derives the user:// directory from THREE settings — config/name,
## use_custom_user_dir, and custom_user_dir_name (OS::get_user_data_dir reads
## all three live on every call). Renaming the project, toggling the custom
## user dir, or changing its name at runtime makes every user:// path silently
## resolve to a new OS directory. Files written before the shift (sidecar, auth
## token, audit log, onboarding flags) become orphaned under the old path.
##
## This monitor listens to ProjectSettings.settings_changed (available 4.2+),
## detects a change to any of the three user://-deriving settings, ensures the
## addon directories exist at the new user:// path, then emits user_path_changed
## so that all consumers can react knowing the directory structure is already in
## place. The signal carries no payload: the shift can come from any of the
## three settings (a custom-dir toggle leaves the name unchanged), so a "user
## path changed, re-resolve" notification is the only meaningful contract.
##
## Usage:
## var monitor := UserPathMonitor.new()
## monitor.start()
## monitor.user_path_changed.connect(_on_user_path_changed)
const ProjectPaths := preload("res://addons/godot_mcp_toolkit/paths/project_paths.gd")
signal user_path_changed
var _cached_name: String = ""
var _cached_use_custom_dir: bool = false
var _cached_custom_dir_name: String = ""
## Begin monitoring. Call once after plugin initialization.
func start() -> void:
_cache_settings()
if not ProjectSettings.settings_changed.is_connected(_on_settings_changed):
ProjectSettings.settings_changed.connect(_on_settings_changed)
## Stop monitoring. Call from _exit_tree() cleanup.
func stop() -> void:
if ProjectSettings.settings_changed.is_connected(_on_settings_changed):
ProjectSettings.settings_changed.disconnect(_on_settings_changed)
func _on_settings_changed() -> void:
var name := ProjectSettings.get_setting("application/config/name", "")
var use_custom := bool(ProjectSettings.get_setting("application/config/use_custom_user_dir", false))
var custom_name := ProjectSettings.get_setting("application/config/custom_user_dir_name", "")
if name == _cached_name and use_custom == _cached_use_custom_dir and custom_name == _cached_custom_dir_name:
return
_cached_name = name
_cached_use_custom_dir = use_custom
_cached_custom_dir_name = custom_name
push_warning("[MCP] user:// path-deriving setting changed - user:// path shifted. Re-creating addon state.")
# Ensure addon dirs exist at the new user:// path before notifying
# consumers — they can write immediately without calling ensure_dirs().
ProjectPaths.ensure_dirs()
user_path_changed.emit()
func _cache_settings() -> void:
_cached_name = ProjectSettings.get_setting("application/config/name", "")
_cached_use_custom_dir = bool(ProjectSettings.get_setting("application/config/use_custom_user_dir", false))
_cached_custom_dir_name = ProjectSettings.get_setting("application/config/custom_user_dir_name", "")