feat(@projects/@magic-civilization): 🦌 p3-27 — FFI + harness to boot the headless biosphere
Runtime wiring so the ecology phase actually ticks in a real headless game (was a no-op until the species library was supplied): - GdPlayerApi::set_ecology_species_json (api-gdext) — loads the fauna species library (JSON array of per-species file contents) onto GameState. Mirrors set_events_config_json; call after load_state_json (the field is #[serde(skip)]). - player_api_main._apply_ecology_species — reads public/resources/ecology/fauna/species/*.json into an array + stamps it via the FFI at boot (right after _apply_events_config), emitting ecology_species_api_loaded. Mirrors the live EcologyState species load. gdext compiles clean. Dylib rebuild in progress. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b984143e60
commit
2a0777e183
2 changed files with 43 additions and 0 deletions
|
|
@ -234,6 +234,11 @@ func _hydrate_player_api(num_players: int) -> void:
|
|||
# `load_state_json`. Without this `events_config` is empty and no events fire.
|
||||
_apply_events_config()
|
||||
|
||||
# p3-27 biosphere: stamp the fauna species library so the headless ecology phase
|
||||
# can seed + emerge a living world. Same `#[serde(skip)]` re-stamp pattern — load
|
||||
# AFTER `load_state_json`. Without this the ecology phase is a no-op (barren world).
|
||||
_apply_ecology_species()
|
||||
|
||||
|
||||
## p3-26 gap 2: stamp the natural-event category configs (DataLoader's merged
|
||||
## `{category: {base_frequency, severity_weights, tiers, …}}`) onto `GdPlayerApi` via
|
||||
|
|
@ -247,6 +252,33 @@ func _apply_events_config() -> void:
|
|||
_emit_event("events_config_api_loaded", {"categories": n})
|
||||
|
||||
|
||||
## p3-27 biosphere: read every fauna species JSON file and stamp the array onto
|
||||
## `GdPlayerApi` via `set_ecology_species_json`. Consumed by `mc-player-api`'s
|
||||
## `process_ecology_phase` (apply_end_turn) to build the EcologyEngine species
|
||||
## library. Mirrors the live `EcologyState` species load.
|
||||
func _apply_ecology_species() -> void:
|
||||
const SPECIES_DIR: String = "res://public/resources/ecology/fauna/species"
|
||||
var dir: DirAccess = DirAccess.open(SPECIES_DIR)
|
||||
if dir == null:
|
||||
_emit_protocol_error("ecology species dir not found — headless ecology will not tick")
|
||||
return
|
||||
var species_jsons: Array = []
|
||||
dir.list_dir_begin()
|
||||
var name: String = dir.get_next()
|
||||
while name != "":
|
||||
if not dir.current_is_dir() and name.ends_with(".json"):
|
||||
var raw: String = FileAccess.get_file_as_string("%s/%s" % [SPECIES_DIR, name])
|
||||
if raw != "":
|
||||
species_jsons.append(raw)
|
||||
name = dir.get_next()
|
||||
dir.list_dir_end()
|
||||
if species_jsons.is_empty():
|
||||
_emit_protocol_error("ecology species dir empty — headless ecology will not tick")
|
||||
return
|
||||
var n: int = int(_api.set_ecology_species_json(JSON.stringify(species_jsons)))
|
||||
_emit_event("ecology_species_api_loaded", {"species": n})
|
||||
|
||||
|
||||
## p3-25: build the resource id→category map ("luxury" | "strategic" | "bonus")
|
||||
## from DataLoader and stamp it onto `GdPlayerApi` via
|
||||
## `set_resource_categories_json`. Consumed by `mc-turn::process_trade_phase`.
|
||||
|
|
|
|||
|
|
@ -168,6 +168,17 @@ impl GdPlayerApi {
|
|||
.load_events_config_json(json.to_string().as_str()) as i64
|
||||
}
|
||||
|
||||
/// p3-27: load the fauna species library (a JSON array of per-species file
|
||||
/// contents, e.g. `["{…grey_wolf…}","{…rabbit…}"]`) so the headless ecology
|
||||
/// phase can build the `EcologyEngine` species library and emerge a living
|
||||
/// biosphere. Returns the count loaded, or 0 on parse failure. Call AFTER
|
||||
/// `load_state_json` (the field is `#[serde(skip)]`, not restored by a load).
|
||||
#[func]
|
||||
pub fn set_ecology_species_json(&mut self, json: GString) -> i64 {
|
||||
self.state
|
||||
.load_ecology_species_json(json.to_string().as_str()) as i64
|
||||
}
|
||||
|
||||
/// Stamp the runtime `UnitsCatalog` (id → `UnitStats`) onto the held
|
||||
/// `GameState`. Distinct from `set_units_catalog_json` (which loads the
|
||||
/// tactical `ai_unit_catalog`): this is the same `mc_units::UnitsCatalog`
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue