Addresses blocker comments from PR review: - Delete star_map.gd and star_map.tscn — dead implant/map/starchart HudGroups registration that should have landed with the atlas unification (D-191 criterion 1) - Remove test_star_map_is_accessible_from_insert_ui and test_star_map_scene_exists from test_sprint30.gd — D-191 supersedes the insert-UI accessibility pattern - ImplantRegistry._scan() now detects default_key collisions (first-wins with push_warning) and validates default_mode against HudGroups.Mode enum (skip + warn on invalid) star_map_data.json remains — still used by atlas_app and economics_app for system index lookups. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
64 lines
2.0 KiB
GDScript
64 lines
2.0 KiB
GDScript
extends Node
|
|
## Lazy registry of installed implant apps (#844, D-191).
|
|
## Autoload — scans apps/*/app.tres on first get_manifests() call.
|
|
## Does NOT reference ImplantAppManifest class_name at load time (autoload
|
|
## parse-order rule; see CLAUDE.md).
|
|
|
|
var _manifests: Array = [] # Array[ImplantAppManifest]
|
|
var _scanned: bool = false
|
|
|
|
|
|
func get_manifests() -> Array:
|
|
if not _scanned:
|
|
_scan()
|
|
return _manifests
|
|
|
|
|
|
func _scan() -> void:
|
|
_scanned = true
|
|
_manifests.clear()
|
|
var key_owners: Dictionary = {} # default_key -> app_path (collision detection)
|
|
var valid_modes: Array = HudGroups.Mode.values()
|
|
var dir := DirAccess.open("res://ui/implant/apps")
|
|
if dir == null:
|
|
push_warning("ImplantRegistry: could not open res://ui/implant/apps")
|
|
return
|
|
dir.list_dir_begin()
|
|
var entry := dir.get_next()
|
|
while not entry.is_empty():
|
|
if dir.current_is_dir() and not entry.begins_with("."):
|
|
var tres_path: String = "res://ui/implant/apps/%s/app.tres" % entry
|
|
if ResourceLoader.exists(tres_path):
|
|
var m = load(tres_path)
|
|
if not _is_valid_manifest(m):
|
|
push_warning("ImplantRegistry: invalid or missing app_path in %s" % tres_path)
|
|
else:
|
|
var app_path: String = m.get("app_path")
|
|
var default_mode: int = m.get("default_mode", 2)
|
|
var default_key: int = m.get("default_key", -1)
|
|
if not valid_modes.has(default_mode):
|
|
push_warning(
|
|
"ImplantRegistry: invalid default_mode %d in %s — skipping" % [
|
|
default_mode, tres_path
|
|
]
|
|
)
|
|
elif default_key >= 0 and key_owners.has(default_key):
|
|
push_warning(
|
|
"ImplantRegistry: key binding collision — key %d already bound to %s, skipping %s" % [
|
|
default_key, key_owners[default_key], app_path
|
|
]
|
|
)
|
|
else:
|
|
if default_key >= 0:
|
|
key_owners[default_key] = app_path
|
|
_manifests.append(m)
|
|
entry = dir.get_next()
|
|
dir.list_dir_end()
|
|
|
|
|
|
func _is_valid_manifest(m: Variant) -> bool:
|
|
if m == null:
|
|
return false
|
|
var app_path = m.get("app_path")
|
|
return app_path != null and not (app_path as String).is_empty()
|