refactor(@projects/@magic-civilization): 🔥 cull 3 orphaned helpers (~266 LOC)

All three statically unreachable + clean headless boot. Verified the scan is
sound (a known-live helper correctly resolves its callers):
- game_state_serialization_helpers.gd — docstring "Called by game_state.gd" is
  stale; the caller was removed by the npc_buildings refactor
- turn_processor_signals.gd — no longer referenced by the turn_processor module
- achievement_tracker.gd — orphaned by the legacy-save-manager removal

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Natalie 2026-06-19 18:23:52 -05:00
parent 7dd049df13
commit 507e782fa1
3 changed files with 0 additions and 266 deletions

View file

@ -1,26 +0,0 @@
extends RefCounted
## Stateless serialization helpers for GameState.
## Called by game_state.gd; not instanced — all methods are static.
const GameMapScript: GDScript = preload("res://engine/src/map/game_map.gd")
static func serialize_layer(layer: Dictionary) -> Dictionary:
var serialized: Dictionary = {"id": layer.get("id", "")}
var map_ref: RefCounted = layer.get("map")
if map_ref is GameMapScript:
serialized["map"] = map_ref.to_dict()
return serialized
static func deserialize_layer(layer_data: Dictionary) -> Dictionary:
var layer: Dictionary = {
"id": layer_data.get("id", ""),
"map": null,
"fog": null,
"units": [],
"settlements": [],
}
if layer_data.has("map") and layer_data["map"] is Dictionary:
layer["map"] = GameMapScript.from_dict(layer_data["map"])
return layer

View file

@ -1,97 +0,0 @@
class_name AchievementTracker
extends RefCounted
signal achievement_unlocked(achievement_id: String, data: Dictionary)
const DATA_PATH: String = "res://public/games/age-of-dwarves/data/achievements.json"
var _achievements: Array[Dictionary] = []
var _unlocked: Dictionary = {}
var _counts: Dictionary = {}
func load_data() -> void:
if not FileAccess.file_exists(DATA_PATH):
push_warning("AchievementTracker: missing %s" % DATA_PATH)
return
var file: FileAccess = FileAccess.open(DATA_PATH, FileAccess.READ)
if file == null:
return
var text: String = file.get_as_text()
file.close()
var json: JSON = JSON.new()
if json.parse(text) != OK or not (json.data is Dictionary):
return
var root: Dictionary = json.data as Dictionary
var entries: Array = root.get("achievements", []) as Array
for entry: Dictionary in entries:
_achievements.append(entry)
func connect_bus(bus: Node) -> void:
if bus == null:
return
bus.connect("combat_resolved", _on_combat_resolved)
bus.connect("city_founded", _on_city_founded)
bus.connect("city_captured", _on_city_captured)
bus.connect("tech_researched", _on_tech_researched)
bus.connect("wonder_built", _on_wonder_built)
bus.connect("victory_achieved", _on_victory)
func is_unlocked(id: String) -> bool:
return _unlocked.has(id)
func unlocked_ids() -> Array:
return _unlocked.keys()
func _increment(signal_name: String, match_fn: Callable = Callable()) -> void:
for entry: Dictionary in _achievements:
var trigger: Dictionary = entry.get("trigger", {}) as Dictionary
if String(trigger.get("signal", "")) != signal_name:
continue
if match_fn.is_valid() and not bool(match_fn.call(trigger)):
continue
var id: String = String(entry.get("id", ""))
if _unlocked.has(id):
continue
var new_count: int = int(_counts.get(id, 0)) + 1
_counts[id] = new_count
if new_count >= int(trigger.get("count", 1)):
_unlock(entry)
func _unlock(entry: Dictionary) -> void:
var id: String = String(entry.get("id", ""))
_unlocked[id] = true
achievement_unlocked.emit(id, entry)
func _on_combat_resolved(_attacker: Variant, _defender: Variant, result: Dictionary) -> void:
var winner: String = String(result.get("winner", ""))
_increment("combat_resolved", func(t: Dictionary) -> bool:
var cond: String = String(t.get("condition", ""))
return cond == "" or (cond == "attacker_wins" and winner == "attacker")
)
func _on_city_founded(_city: Variant, _player_index: int) -> void:
_increment("city_founded")
func _on_city_captured(_city: Variant, _old_owner: int, _new_owner: int) -> void:
_increment("city_captured")
func _on_tech_researched(_tech_id: String, _player_index: int) -> void:
_increment("tech_researched")
func _on_wonder_built(_wonder_id: String, _player_index: int) -> void:
_increment("wonder_built")
func _on_victory(_player_index: int, _victory_type: String) -> void:
_increment("victory_achieved")

View file

@ -1,143 +0,0 @@
extends RefCounted
## Signal replay helpers for TurnProcessor. Parses the event arrays returned
## by GdTurnProcessor.advance_turn() and emits the corresponding EventBus
## signals so the UI stays in sync with Rust state mutations.
const PlayerScript: GDScript = preload("res://engine/src/entities/player.gd")
const CityScript: GDScript = preload("res://engine/src/entities/city.gd")
const UnitScript: GDScript = preload("res://engine/src/entities/unit.gd")
const UnitManagerScript: GDScript = preload(
"res://engine/src/modules/management/unit_manager.gd"
)
## Assigned by TurnProcessor after construction
var unit_manager: RefCounted # UnitManager
func replay_growth_events(player: PlayerScript, result: Dictionary) -> void:
var growth_events: Array = result.get("growth_events", []) as Array
for ev: Dictionary in growth_events:
var city_id: String = ev.get("city_id", "") as String
var event_type: String = ev.get("type", "") as String
var new_pop: int = int(ev.get("population", 0))
for city_raw: RefCounted in player.cities:
var city: CityScript = city_raw as CityScript
if city == null or city.id != city_id:
continue
if event_type == "grew":
EventBus.city_grew.emit(city, new_pop)
elif event_type == "starved":
EventBus.city_starved.emit(city, new_pop)
break
func replay_production_events(player: PlayerScript, result: Dictionary) -> void:
var prod_events: Array = result.get("production_events", []) as Array
for ev: Dictionary in prod_events:
var city_id: String = ev.get("city_id", "") as String
var item_type: String = ev.get("item_type", "") as String
var item_id: String = ev.get("item_id", "") as String
var city_ref: CityScript = null
for city_raw: RefCounted in player.cities:
var city: CityScript = city_raw as CityScript
if city != null and city.id == city_id:
city_ref = city
break
if city_ref == null:
continue
if item_type == "unit":
var unit: RefCounted = (unit_manager as UnitManagerScript).create_unit(
item_id, player.index, city_ref.position, player
)
if unit != null:
EventBus.city_unit_completed.emit(city_ref, unit)
elif item_type == "building":
EventBus.city_building_completed.emit(city_ref, item_id)
if DataLoader.get_building(item_id).get("is_wonder", false):
EventBus.wonder_built.emit(item_id, player.index)
func replay_research_events(player: PlayerScript, result: Dictionary) -> void:
var research_events: Array = result.get("research_events", []) as Array
for ev: Dictionary in research_events:
var event_type: String = ev.get("type", "") as String
var completed_id: String = ev.get("id", "") as String
if completed_id.is_empty():
continue
if event_type == "tech":
EventBus.tech_researched.emit(completed_id, player.index)
func replay_improvement_events(player: PlayerScript, result: Dictionary) -> void:
var imp_events: Array = result.get("improvement_events", []) as Array
for ev: Dictionary in imp_events:
if ev.get("type", "") != "completed":
continue
var tile_x: int = int(ev.get("x", 0))
var tile_y: int = int(ev.get("y", 0))
var imp_type: String = ev.get("improvement_type", "") as String
EventBus.improvement_completed.emit(Vector2i(tile_x, tile_y), imp_type)
for i: int in range(player.pending_improvements.size() - 1, -1, -1):
var imp: Dictionary = player.pending_improvements[i] as Dictionary
if imp != null \
and imp.get("x", -9999) == tile_x \
and imp.get("y", -9999) == tile_y:
player.pending_improvements.remove_at(i)
break
func replay_fauna_events(result: Dictionary) -> void:
## Emit EventBus signals for wild creature activity from the turn result.
var units_lost: Array = result.get("units_lost_to_fauna", []) as Array
for entry: Dictionary in units_lost:
var unit_id: String = entry.get("unit_id", "") as String
if unit_id.is_empty():
continue
var primary: Dictionary = GameState.get_primary_layer()
for u: RefCounted in primary.get("units", []) as Array:
var unit: UnitScript = u as UnitScript
if unit != null and unit.id == unit_id:
EventBus.unit_destroyed.emit(unit, null)
break
var fauna_events: Array = result.get("fauna_events", []) as Array
for ev: Dictionary in fauna_events:
if ev.get("type", "") == "spawned":
var lair_x: int = int(ev.get("lair_x", 0))
var lair_y: int = int(ev.get("lair_y", 0))
EventBus.wild_creature_spawned.emit(null, Vector2i(lair_x, lair_y))
func replay_climate_events(result: Dictionary) -> void:
var climate_events: Array = result.get("climate_events", []) as Array
for ev: Dictionary in climate_events:
var event_type: String = ev.get("type", "") as String
match event_type:
"terrain_transformed":
var pos: Vector2i = Vector2i(int(ev.get("x", 0)), int(ev.get("y", 0)))
var gmap: RefCounted = GameState.get_game_map()
var tile: RefCounted = gmap.get_tile(pos) if gmap != null else null
EventBus.terrain_transformed.emit(
tile,
ev.get("old_type", "") as String,
ev.get("new_type", "") as String,
)
"quality_changed":
var pos: Vector2i = Vector2i(int(ev.get("x", 0)), int(ev.get("y", 0)))
var gmap: RefCounted = GameState.get_game_map()
var tile: RefCounted = gmap.get_tile(pos) if gmap != null else null
EventBus.quality_changed.emit(
tile,
int(ev.get("old_quality", 0)),
int(ev.get("new_quality", 0)),
)
"flood":
var pos: Vector2i = Vector2i(int(ev.get("x", 0)), int(ev.get("y", 0)))
EventBus.tile_flooded.emit(pos, ev.get("old_terrain", "") as String)
"biome_changed":
var pos: Vector2i = Vector2i(int(ev.get("x", 0)), int(ev.get("y", 0)))
EventBus.biome_changed.emit(
pos,
ev.get("old_biome", "") as String,
ev.get("new_biome", "") as String,
)