diff --git a/src/game/engine/src/autoloads/data_loader.gd b/src/game/engine/src/autoloads/data_loader.gd index 70837355..1fbd40f1 100644 --- a/src/game/engine/src/autoloads/data_loader.gd +++ b/src/game/engine/src/autoloads/data_loader.gd @@ -1,4 +1,3 @@ -# gdlint: disable=max-public-methods extends Node ## Loads all JSON data files from the active theme pack. ## Supports both single files (terrain.json) and split directories (units/). @@ -425,67 +424,29 @@ func get_ley_line_params() -> Dictionary: func get_social_policies() -> Dictionary: return _raw.get("social_policies", {}) -# -- Ecology: typed accessors (delegated to _ecology) -- - -func get_biome(id: String) -> Variant: - return _ecology.get_biome(id) - -func get_all_biomes() -> Array: - return _ecology.get_all_biomes() - -func get_flora_profile(biome_id: String) -> Variant: - return _ecology.get_flora_profile(biome_id) - -func get_substrate(id: String) -> Variant: - return _ecology.get_substrate(id) - -func get_all_substrates() -> Array: - return _ecology.get_all_substrates() - -func get_marine_fauna_params() -> Variant: - return _ecology.get_marine_fauna_params() - -func get_land_fauna_params() -> Variant: - return _ecology.get_land_fauna_params() - -func get_air_fauna_params() -> Variant: - return _ecology.get_air_fauna_params() - -func get_trait_definitions() -> Dictionary: - return _ecology.get_trait_definitions() - -func get_trait_constraints() -> Array: - return _ecology.get_trait_constraints() - +# -- Ecology: delegated to _ecology (data_loader_ecology.gd) -- +func get_biome(id: String) -> Variant: return _ecology.get_biome(id) +func get_all_biomes() -> Array: return _ecology.get_all_biomes() +func get_flora_profile(biome_id: String) -> Variant: return _ecology.get_flora_profile(biome_id) +func get_substrate(id: String) -> Variant: return _ecology.get_substrate(id) +func get_all_substrates() -> Array: return _ecology.get_all_substrates() +func get_marine_fauna_params() -> Variant: return _ecology.get_marine_fauna_params() +func get_land_fauna_params() -> Variant: return _ecology.get_land_fauna_params() +func get_air_fauna_params() -> Variant: return _ecology.get_air_fauna_params() +func get_trait_definitions() -> Dictionary: return _ecology.get_trait_definitions() +func get_trait_constraints() -> Array: return _ecology.get_trait_constraints() func get_biome_trait_weights(biome_id: String) -> Dictionary: return _ecology.get_biome_trait_weights(biome_id) - -func get_food_web_rules() -> Dictionary: - return _ecology.get_food_web_rules() - -func get_spawn_rules() -> Array: - return _ecology.get_spawn_rules() - -func get_flavor_tables() -> Dictionary: - return _ecology.get_flavor_tables() - -func get_ecosystem_health_params() -> Dictionary: - return _ecology.get_ecosystem_health_params() - -func get_food_yield_params() -> Dictionary: - return _ecology.get_food_yield_params() - +func get_food_web_rules() -> Dictionary: return _ecology.get_food_web_rules() +func get_spawn_rules() -> Array: return _ecology.get_spawn_rules() +func get_flavor_tables() -> Dictionary: return _ecology.get_flavor_tables() +func get_ecosystem_health_params() -> Dictionary: return _ecology.get_ecosystem_health_params() +func get_food_yield_params() -> Dictionary: return _ecology.get_food_yield_params() func get_ecosystem_stability_params() -> Dictionary: return _ecology.get_ecosystem_stability_params() - -func get_vegetation_params() -> Dictionary: - return _ecology.get_vegetation_params() - -func get_succession_params() -> Dictionary: - return _ecology.get_succession_params() - -func get_desertification_params() -> Dictionary: - return _ecology.get_desertification_params() +func get_vegetation_params() -> Dictionary: return _ecology.get_vegetation_params() +func get_succession_params() -> Dictionary: return _ecology.get_succession_params() +func get_desertification_params() -> Dictionary: return _ecology.get_desertification_params() # -- Internal helpers -- diff --git a/src/game/engine/src/map/tile.gd b/src/game/engine/src/map/tile.gd index 50819d4a..39595491 100644 --- a/src/game/engine/src/map/tile.gd +++ b/src/game/engine/src/map/tile.gd @@ -4,6 +4,7 @@ extends Resource ## Resource class (not Node) — lightweight, serializable, no scene tree dependency. const ImprovementScript: GDScript = preload("res://engine/src/entities/improvement.gd") +const TileSerializerScript: GDScript = preload("res://engine/src/map/tile_serializer.gd") var biome_id: String = "" # biome classification result var substrate_id: String = "" # geological substrate from elevation @@ -362,193 +363,10 @@ func set_visibility(player_index: int, state: int) -> void: func to_dict() -> Dictionary: - ## Serialize tile state for save files. - var data: Dictionary = { - "position": [position.x, position.y], - "biome_id": biome_id, - } - if substrate_id != "": - data["substrate_id"] = substrate_id - if water_body_id != -1: - data["water_body_id"] = water_body_id - if water_body_type != "": - data["water_body_type"] = water_body_type - if depth_from_coast != -1: - data["depth_from_coast"] = depth_from_coast - if soil_type != "": - data["soil_type"] = soil_type - if is_river_mouth: - data["is_river_mouth"] = true - if has_cave: - data["has_cave"] = true - if resource_id != "": - data["resource_id"] = resource_id - if improvement != "": - data["improvement"] = improvement - if owner != -1: - data["owner"] = owner - if lair_type != "": - data["lair_type"] = lair_type - if not visibility.is_empty(): - data["visibility"] = visibility - if variation_index != 0: - data["variation_index"] = variation_index - if elevation != 0.0: - data["elevation"] = elevation - if moisture != 0.0: - data["moisture"] = moisture - if temperature != 0.0: - data["temperature"] = temperature - if not river_edges.is_empty(): - data["river_edges"] = river_edges - if not river_flow.is_empty(): - data["river_flow"] = river_flow - if flow_accumulation != 0.0: - data["flow_accumulation"] = flow_accumulation - if lake_id != -1: - data["lake_id"] = lake_id - if river_source_type != "": - data["river_source_type"] = river_source_type - if is_coastal: - data["is_coastal"] = true - if quality != 2: - data["quality"] = quality - if quality_progress != 0: - data["quality_progress"] = quality_progress - if wind_speed != 0.5: - data["wind_speed"] = wind_speed - if culture_pressure != 0.0: - data["culture_pressure"] = culture_pressure - # magic_heat_delta and magic_moisture_delta are per-turn transients — not saved - # relative_humidity, dew_point, cape are recalculated each turn — not saved - # ley fields - if mana_density != 0.0: - data["mana_density"] = mana_density - if ley_line_count != 0: - data["ley_line_count"] = ley_line_count - if ley_school != "": - data["ley_school"] = ley_school - if ley_corrupted: - data["ley_corrupted"] = true - if ley_residue_school != "": - data["ley_residue_school"] = ley_residue_school - if ley_residue_strength != 0.0: - data["ley_residue_strength"] = ley_residue_strength - if ley_residue_turns != 0: - data["ley_residue_turns"] = ley_residue_turns - if humidity != 0.5: - data["humidity"] = humidity - if pressure_anomaly != 0.0: - data["pressure_anomaly"] = pressure_anomaly - if fish_stock != -1: - data["fish_stock"] = fish_stock - if reef_health != 1.0: - data["reef_health"] = reef_health - # marine_bloom_turns is transient (spell effect) — not saved - if marine_creature != "": - data["marine_creature"] = marine_creature - # Flora fields - if canopy_cover != 0.0: - data["canopy_cover"] = canopy_cover - if undergrowth != 0.0: - data["undergrowth"] = undergrowth - if fungi_network != 0.0: - data["fungi_network"] = fungi_network - if drought_counter != 0: - data["drought_counter"] = drought_counter - if succession_progress != 0: - data["succession_progress"] = succession_progress - if regrowth_stage != -1: - data["regrowth_stage"] = regrowth_stage - if regrowth_turns != 0: - data["regrowth_turns"] = regrowth_turns - # Fauna tracking (habitat_suitability is NOT serialized — recalculated per turn) - if habitat_low_turns != 0: - data["habitat_low_turns"] = habitat_low_turns - if landmark_name != "": - data["landmark_name"] = landmark_name - if not ground_items.is_empty(): - data["ground_items"] = ground_items.duplicate(true) - if wonder_anchor_strength != 0.0: - data["wonder_anchor_strength"] = wonder_anchor_strength - if wonder_anchor_school != "": - data["wonder_anchor_school"] = wonder_anchor_school - if not wonder_anchor_schools.is_empty(): - data["wonder_anchor_schools"] = wonder_anchor_schools.duplicate() - if wonder_tier != 0: - data["wonder_tier"] = wonder_tier - if sulfate_aerosol != 0.0: - data["sulfate_aerosol"] = sulfate_aerosol - if solar_forcing != 0.0: - data["solar_forcing"] = solar_forcing - if glacial_forcing != 0.0: - data["glacial_forcing"] = glacial_forcing - return data + ## Serialize tile state for save files. Layout lives in TileSerializer. + return TileSerializerScript.to_dict(self) static func from_dict(data: Dictionary) -> Resource: # Tile - ## Deserialize tile state from save files. - var pos_arr: Array = data.get("position", [0, 0]) - var pos: Vector2i = Vector2i(pos_arr[0], pos_arr[1]) - var SelfScript: GDScript = load("res://engine/src/map/tile.gd") - var tile: Resource = SelfScript.new(pos, data.get("biome_id", "")) - tile.substrate_id = data.get("substrate_id", "") - tile.water_body_id = data.get("water_body_id", -1) - tile.water_body_type = data.get("water_body_type", "") - tile.depth_from_coast = data.get("depth_from_coast", -1) - tile.soil_type = data.get("soil_type", "") - tile.is_river_mouth = data.get("is_river_mouth", false) - tile.has_cave = data.get("has_cave", false) - tile.resource_id = data.get("resource_id", "") - tile.improvement = data.get("improvement", "") - tile.owner = data.get("owner", -1) - tile.lair_type = data.get("lair_type", "") - tile.visibility = data.get("visibility", {}) - tile.variation_index = data.get("variation_index", 0) - tile.elevation = data.get("elevation", 0.0) - tile.moisture = data.get("moisture", 0.0) - tile.temperature = data.get("temperature", 0.0) - var edges: Array = data.get("river_edges", []) - for edge: Variant in edges: - tile.river_edges.append(int(edge)) - tile.river_flow = data.get("river_flow", {}) - tile.flow_accumulation = data.get("flow_accumulation", 0.0) - tile.lake_id = data.get("lake_id", -1) - tile.river_source_type = data.get("river_source_type", "") - tile.is_coastal = data.get("is_coastal", false) - tile.quality = data.get("quality", 2) - tile.quality_progress = data.get("quality_progress", 0) - tile.wind_speed = data.get("wind_speed", 0.5) - tile.culture_pressure = data.get("culture_pressure", 0.0) - tile.mana_density = data.get("mana_density", 0.0) - tile.ley_line_count = data.get("ley_line_count", 0) - tile.ley_school = data.get("ley_school", "") - tile.ley_corrupted = data.get("ley_corrupted", false) - tile.ley_residue_school = data.get("ley_residue_school", "") - tile.ley_residue_strength = data.get("ley_residue_strength", 0.0) - tile.ley_residue_turns = data.get("ley_residue_turns", 0) - tile.humidity = data.get("humidity", 0.5) - tile.pressure_anomaly = data.get("pressure_anomaly", 0.0) - tile.fish_stock = data.get("fish_stock", -1) - tile.reef_health = data.get("reef_health", 1.0) - tile.marine_creature = data.get("marine_creature", "") - tile.canopy_cover = data.get("canopy_cover", 0.0) - tile.undergrowth = data.get("undergrowth", 0.0) - tile.fungi_network = data.get("fungi_network", 0.0) - tile.drought_counter = data.get("drought_counter", 0) - tile.succession_progress = data.get("succession_progress", 0) - tile.regrowth_stage = data.get("regrowth_stage", -1) - tile.regrowth_turns = data.get("regrowth_turns", 0) - tile.habitat_low_turns = data.get("habitat_low_turns", 0) - tile.landmark_name = data.get("landmark_name", "") - tile.ground_items = data.get("ground_items", []) - tile.wonder_anchor_strength = data.get("wonder_anchor_strength", 0.0) - tile.wonder_anchor_school = data.get("wonder_anchor_school", "") - var schools_raw: Array = data.get("wonder_anchor_schools", []) - for s: Variant in schools_raw: - tile.wonder_anchor_schools.append(str(s)) - tile.wonder_tier = data.get("wonder_tier", 0) - tile.sulfate_aerosol = data.get("sulfate_aerosol", 0.0) - tile.solar_forcing = data.get("solar_forcing", 0.0) - tile.glacial_forcing = data.get("glacial_forcing", 0.0) - return tile + ## Deserialize tile state from save files. Layout lives in TileSerializer. + return TileSerializerScript.from_dict(data) diff --git a/src/game/engine/src/map/tile_serializer.gd b/src/game/engine/src/map/tile_serializer.gd new file mode 100644 index 00000000..3773ebeb --- /dev/null +++ b/src/game/engine/src/map/tile_serializer.gd @@ -0,0 +1,193 @@ +class_name TileSerializer +extends RefCounted +## Serialisation helpers for Tile. Extracted from tile.gd to keep that file +## under the 500-line limit. All save/load field mapping lives here. + +const TILE_SCRIPT_PATH: String = "res://engine/src/map/tile.gd" + + +static func to_dict(tile: Resource) -> Dictionary: + ## Serialize tile state for save files. + var data: Dictionary = { + "position": [tile.position.x, tile.position.y], + "biome_id": tile.biome_id, + } + if tile.substrate_id != "": + data["substrate_id"] = tile.substrate_id + if tile.water_body_id != -1: + data["water_body_id"] = tile.water_body_id + if tile.water_body_type != "": + data["water_body_type"] = tile.water_body_type + if tile.depth_from_coast != -1: + data["depth_from_coast"] = tile.depth_from_coast + if tile.soil_type != "": + data["soil_type"] = tile.soil_type + if tile.is_river_mouth: + data["is_river_mouth"] = true + if tile.has_cave: + data["has_cave"] = true + if tile.resource_id != "": + data["resource_id"] = tile.resource_id + if tile.improvement != "": + data["improvement"] = tile.improvement + if tile.owner != -1: + data["owner"] = tile.owner + if tile.lair_type != "": + data["lair_type"] = tile.lair_type + if not tile.visibility.is_empty(): + data["visibility"] = tile.visibility + if tile.variation_index != 0: + data["variation_index"] = tile.variation_index + if tile.elevation != 0.0: + data["elevation"] = tile.elevation + if tile.moisture != 0.0: + data["moisture"] = tile.moisture + if tile.temperature != 0.0: + data["temperature"] = tile.temperature + if not tile.river_edges.is_empty(): + data["river_edges"] = tile.river_edges + if not tile.river_flow.is_empty(): + data["river_flow"] = tile.river_flow + if tile.flow_accumulation != 0.0: + data["flow_accumulation"] = tile.flow_accumulation + if tile.lake_id != -1: + data["lake_id"] = tile.lake_id + if tile.river_source_type != "": + data["river_source_type"] = tile.river_source_type + if tile.is_coastal: + data["is_coastal"] = true + if tile.quality != 2: + data["quality"] = tile.quality + if tile.quality_progress != 0: + data["quality_progress"] = tile.quality_progress + if tile.wind_speed != 0.5: + data["wind_speed"] = tile.wind_speed + if tile.culture_pressure != 0.0: + data["culture_pressure"] = tile.culture_pressure + if tile.mana_density != 0.0: + data["mana_density"] = tile.mana_density + if tile.ley_line_count != 0: + data["ley_line_count"] = tile.ley_line_count + if tile.ley_school != "": + data["ley_school"] = tile.ley_school + if tile.ley_corrupted: + data["ley_corrupted"] = true + if tile.ley_residue_school != "": + data["ley_residue_school"] = tile.ley_residue_school + if tile.ley_residue_strength != 0.0: + data["ley_residue_strength"] = tile.ley_residue_strength + if tile.ley_residue_turns != 0: + data["ley_residue_turns"] = tile.ley_residue_turns + if tile.humidity != 0.5: + data["humidity"] = tile.humidity + if tile.pressure_anomaly != 0.0: + data["pressure_anomaly"] = tile.pressure_anomaly + if tile.fish_stock != -1: + data["fish_stock"] = tile.fish_stock + if tile.reef_health != 1.0: + data["reef_health"] = tile.reef_health + if tile.marine_creature != "": + data["marine_creature"] = tile.marine_creature + if tile.canopy_cover != 0.0: + data["canopy_cover"] = tile.canopy_cover + if tile.undergrowth != 0.0: + data["undergrowth"] = tile.undergrowth + if tile.fungi_network != 0.0: + data["fungi_network"] = tile.fungi_network + if tile.drought_counter != 0: + data["drought_counter"] = tile.drought_counter + if tile.succession_progress != 0: + data["succession_progress"] = tile.succession_progress + if tile.regrowth_stage != -1: + data["regrowth_stage"] = tile.regrowth_stage + if tile.regrowth_turns != 0: + data["regrowth_turns"] = tile.regrowth_turns + if tile.habitat_low_turns != 0: + data["habitat_low_turns"] = tile.habitat_low_turns + if tile.landmark_name != "": + data["landmark_name"] = tile.landmark_name + if not tile.ground_items.is_empty(): + data["ground_items"] = tile.ground_items.duplicate(true) + if tile.wonder_anchor_strength != 0.0: + data["wonder_anchor_strength"] = tile.wonder_anchor_strength + if tile.wonder_anchor_school != "": + data["wonder_anchor_school"] = tile.wonder_anchor_school + if not tile.wonder_anchor_schools.is_empty(): + data["wonder_anchor_schools"] = tile.wonder_anchor_schools.duplicate() + if tile.wonder_tier != 0: + data["wonder_tier"] = tile.wonder_tier + if tile.sulfate_aerosol != 0.0: + data["sulfate_aerosol"] = tile.sulfate_aerosol + if tile.solar_forcing != 0.0: + data["solar_forcing"] = tile.solar_forcing + if tile.glacial_forcing != 0.0: + data["glacial_forcing"] = tile.glacial_forcing + return data + + +static func from_dict(data: Dictionary) -> Resource: # Tile + ## Deserialize tile state from save files. + var pos_arr: Array = data.get("position", [0, 0]) + var pos: Vector2i = Vector2i(pos_arr[0], pos_arr[1]) + var TileScript: GDScript = load(TILE_SCRIPT_PATH) + var tile: Resource = TileScript.new(pos, data.get("biome_id", "")) + tile.substrate_id = data.get("substrate_id", "") + tile.water_body_id = data.get("water_body_id", -1) + tile.water_body_type = data.get("water_body_type", "") + tile.depth_from_coast = data.get("depth_from_coast", -1) + tile.soil_type = data.get("soil_type", "") + tile.is_river_mouth = data.get("is_river_mouth", false) + tile.has_cave = data.get("has_cave", false) + tile.resource_id = data.get("resource_id", "") + tile.improvement = data.get("improvement", "") + tile.owner = data.get("owner", -1) + tile.lair_type = data.get("lair_type", "") + tile.visibility = data.get("visibility", {}) + tile.variation_index = data.get("variation_index", 0) + tile.elevation = data.get("elevation", 0.0) + tile.moisture = data.get("moisture", 0.0) + tile.temperature = data.get("temperature", 0.0) + var edges: Array = data.get("river_edges", []) + for edge: Variant in edges: + tile.river_edges.append(int(edge)) + tile.river_flow = data.get("river_flow", {}) + tile.flow_accumulation = data.get("flow_accumulation", 0.0) + tile.lake_id = data.get("lake_id", -1) + tile.river_source_type = data.get("river_source_type", "") + tile.is_coastal = data.get("is_coastal", false) + tile.quality = data.get("quality", 2) + tile.quality_progress = data.get("quality_progress", 0) + tile.wind_speed = data.get("wind_speed", 0.5) + tile.culture_pressure = data.get("culture_pressure", 0.0) + tile.mana_density = data.get("mana_density", 0.0) + tile.ley_line_count = data.get("ley_line_count", 0) + tile.ley_school = data.get("ley_school", "") + tile.ley_corrupted = data.get("ley_corrupted", false) + tile.ley_residue_school = data.get("ley_residue_school", "") + tile.ley_residue_strength = data.get("ley_residue_strength", 0.0) + tile.ley_residue_turns = data.get("ley_residue_turns", 0) + tile.humidity = data.get("humidity", 0.5) + tile.pressure_anomaly = data.get("pressure_anomaly", 0.0) + tile.fish_stock = data.get("fish_stock", -1) + tile.reef_health = data.get("reef_health", 1.0) + tile.marine_creature = data.get("marine_creature", "") + tile.canopy_cover = data.get("canopy_cover", 0.0) + tile.undergrowth = data.get("undergrowth", 0.0) + tile.fungi_network = data.get("fungi_network", 0.0) + tile.drought_counter = data.get("drought_counter", 0) + tile.succession_progress = data.get("succession_progress", 0) + tile.regrowth_stage = data.get("regrowth_stage", -1) + tile.regrowth_turns = data.get("regrowth_turns", 0) + tile.habitat_low_turns = data.get("habitat_low_turns", 0) + tile.landmark_name = data.get("landmark_name", "") + tile.ground_items = data.get("ground_items", []) + tile.wonder_anchor_strength = data.get("wonder_anchor_strength", 0.0) + tile.wonder_anchor_school = data.get("wonder_anchor_school", "") + var schools_raw: Array = data.get("wonder_anchor_schools", []) + for s: Variant in schools_raw: + tile.wonder_anchor_schools.append(str(s)) + tile.wonder_tier = data.get("wonder_tier", 0) + tile.sulfate_aerosol = data.get("sulfate_aerosol", 0.0) + tile.solar_forcing = data.get("solar_forcing", 0.0) + tile.glacial_forcing = data.get("glacial_forcing", 0.0) + return tile