class_name PlanetSetups extends RefCounted # Registry of authored PlanetSetup resources. Deliberately scans # res://PlanetSetups/ at first use instead of a hardcoded preload # dictionary (contrast PlanetDefinitions.gd), so dropping a new .tres in # that folder is the only step needed to add a setup - the map editor # (#48) writes there directly. const SETUPS_DIR: String = "res://PlanetSetups" # Compared against get_script() rather than an `is PlanetSetup` check - the # same load-order hazard as PlanetSurfaceController's setup_host: a global # class_name identifier can be looked up before an import pass has # registered it, while a direct script preload never depends on that cache. const PLANET_SETUP_SCRIPT: Script = preload("res://PlanetSetup.gd") static var _all: Array = [] static var _scanned: bool = false static func _ensure_scanned() -> void: if _scanned: return _scanned = true var dir: DirAccess = DirAccess.open(SETUPS_DIR) if dir == null: return dir.list_dir_begin() var file_name: String = dir.get_next() while file_name != "": if not dir.current_is_dir() and file_name.ends_with(".tres"): var res: Resource = load(SETUPS_DIR + "/" + file_name) if res != null and res.get_script() == PLANET_SETUP_SCRIPT: _all.append(res) file_name = dir.get_next() dir.list_dir_end() static func rescan() -> void: # The map editor calls this after saving so a freshly written setup is # visible without restarting the process. _all = [] _scanned = false _ensure_scanned() static func all() -> Array: _ensure_scanned() return _all static func setups_for_profile(profile_id: String) -> Array: var result: Array = [] for setup in all(): if setup.surface_profile_id == profile_id: result.append(setup) return result static func setup_for_planet(planet_id: String, profile_id: String) -> Resource: # Same pattern as WorldGen.planet_data_at_chunk: seeded purely from the # planet's own stable id, so the same planet always resolves to the # same setup from anywhere, with nothing stored. var candidates: Array = setups_for_profile(profile_id) if candidates.is_empty(): return null var rng: RandomNumberGenerator = RandomNumberGenerator.new() rng.seed = hash(planet_id) return candidates[rng.randi() % candidates.size()]