69 lines
2.2 KiB
GDScript3
69 lines
2.2 KiB
GDScript3
|
|
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()]
|