105 lines
3.8 KiB
GDScript
105 lines
3.8 KiB
GDScript
extends RefCounted
|
|
## World loading delegate for DataLoader.
|
|
## Reads world manifests from engine/src/worlds/, loads biome/substrate collections,
|
|
## and registers runtime biomes into BiomeRegistry.
|
|
|
|
const WORLDS_BASE: String = "res://resources/worlds"
|
|
const BIOMES_BASE: String = "res://resources/biomes"
|
|
const EVENTS_BASE: String = "res://resources/events"
|
|
|
|
var manifest: Dictionary = {}
|
|
var active_world: String = ""
|
|
## Physics raw data loaded from world path (climate_params, climate_spec, hydrology_params).
|
|
## DataLoader merges these into _raw after calling load_world().
|
|
var physics: Dictionary = {}
|
|
## Capability flags from manifest.physics_features — explicit per-subsystem on/off.
|
|
var physics_features: Dictionary = {}
|
|
|
|
const PHYSICS_FILES: Array[String] = [
|
|
"climate_params", "climate_spec", "hydrology_params"
|
|
]
|
|
|
|
|
|
func load_world(world_id: String, ecology: Variant) -> void:
|
|
active_world = world_id
|
|
physics = {}
|
|
physics_features = {}
|
|
var world_path: String = "%s/%s" % [WORLDS_BASE, world_id]
|
|
|
|
# Load manifest
|
|
manifest = _load_json("%s/manifest.json" % world_path)
|
|
if manifest.is_empty():
|
|
push_error("DataLoader: Cannot load world manifest for '%s'" % world_id)
|
|
return
|
|
physics_features = manifest.get("physics_features", {})
|
|
|
|
# Load physics parameter files
|
|
for key: String in PHYSICS_FILES:
|
|
var data: Dictionary = _load_json("%s/%s.json" % [world_path, key])
|
|
if not data.is_empty():
|
|
physics[key] = data
|
|
|
|
# Load subscribed events
|
|
var events: Dictionary = {}
|
|
for event_id: Variant in manifest.get("subscribes_events", []):
|
|
var event_path: String = "%s/%s.json" % [EVENTS_BASE, str(event_id)]
|
|
var entry: Dictionary = _load_json(event_path)
|
|
if entry.is_empty():
|
|
push_warning("DataLoader: Missing event '%s'" % event_id)
|
|
continue
|
|
events[str(event_id)] = entry
|
|
if not events.is_empty():
|
|
physics["events"] = events
|
|
|
|
# Load subscribed biome collections
|
|
var biome_count: int = 0
|
|
for collection_id: Variant in manifest.get("subscribes_biomes", []):
|
|
var entries: Array = _load_collection_entries(str(collection_id), "biomes")
|
|
for entry: Dictionary in entries:
|
|
ecology.register_collection_biome(entry)
|
|
biome_count += 1
|
|
|
|
# Load subscribed substrate collections
|
|
var substrate_count: int = 0
|
|
for collection_id: Variant in manifest.get("subscribes_substrates", []):
|
|
var entries: Array = _load_collection_entries(str(collection_id), "substrates")
|
|
for entry: Dictionary in entries:
|
|
ecology.register_collection_substrate(entry)
|
|
substrate_count += 1
|
|
|
|
# Load runtime biomes
|
|
var runtime_data: Dictionary = _load_json("%s/runtime_biomes.json" % world_path)
|
|
for entry: Variant in runtime_data.get("runtime_biomes", []):
|
|
if entry is Dictionary and entry.has("id"):
|
|
var rt_tags: Array[String] = []
|
|
for tag: Variant in entry.get("tags", []):
|
|
rt_tags.append(str(tag))
|
|
BiomeRegistry.register_runtime_biome(str(entry["id"]), rt_tags)
|
|
|
|
BiomeRegistry.rebuild_from_data()
|
|
print("DataLoader: World '%s' — %d biomes, %d substrates, %d physics files" % [
|
|
world_id, biome_count, substrate_count, physics.size()])
|
|
|
|
|
|
func _load_collection_entries(collection_id: String, key: String) -> Array:
|
|
var path: String = "%s/%s/%s.json" % [BIOMES_BASE, collection_id, key]
|
|
var data: Dictionary = _load_json(path)
|
|
var entries: Array = data.get(key, [])
|
|
if entries.is_empty():
|
|
push_warning("DataLoader: Empty or missing collection %s/%s" % [collection_id, key])
|
|
return entries
|
|
|
|
|
|
func _load_json(path: String) -> Dictionary:
|
|
if not FileAccess.file_exists(path):
|
|
return {}
|
|
var file: FileAccess = FileAccess.open(path, FileAccess.READ)
|
|
if file == null:
|
|
return {}
|
|
var json: JSON = JSON.new()
|
|
if json.parse(file.get_as_text()) != OK:
|
|
push_warning("DataLoader: JSON error in %s: %s" % [path, json.get_error_message()])
|
|
return {}
|
|
if json.data is Dictionary:
|
|
return json.data
|
|
return {}
|