feat: integrate regional caravan persistence
This commit is contained in:
@@ -12,6 +12,9 @@ const NpcTickDebugLog := preload("res://simulation/debug/npc_tick_debug_log.gd")
|
||||
const RelationshipSystemScript := preload("res://simulation/relationships/RelationshipSystem.gd")
|
||||
const EventKnowledgeSystemScript := preload("res://simulation/knowledge/EventKnowledgeSystem.gd")
|
||||
const ConflictSystemScript := preload("res://simulation/conflict/ConflictSystem.gd")
|
||||
const RegionalSimulationFacadeScript := preload(
|
||||
"res://simulation/regional/RegionalSimulationFacade.gd"
|
||||
)
|
||||
|
||||
signal npc_task_changed(npc: SimNPC, old_task: StringName, new_task: StringName)
|
||||
signal village_changed(village: SimVillage)
|
||||
@@ -84,6 +87,8 @@ var conflict_system := ConflictSystemScript.new()
|
||||
var player_quest_system := PlayerQuestSystem.new()
|
||||
var player_needs := PlayerNeedsSystem.new()
|
||||
var player_negotiation := PlayerNegotiationSystem.new()
|
||||
var _regional_simulation: RegionalSimulationFacade
|
||||
var _restoring_save_manifest := false
|
||||
var _last_player_tier := PlayerStandingRecord.TIER_STRANGER
|
||||
var storage_states: Dictionary:
|
||||
get:
|
||||
@@ -165,6 +170,9 @@ func _ready() -> void:
|
||||
clock = SimulationClock.new(tick_interval)
|
||||
clock.cycle_duration_seconds = cycle_duration_seconds
|
||||
clock.elapsed_ticks = int(0.25 * cycle_duration_seconds / tick_interval)
|
||||
if not _initialize_regional_simulation(tick_count):
|
||||
set_process(false)
|
||||
return
|
||||
village.debug_logs = debug_logs
|
||||
economy.configure(village, debug_logs)
|
||||
animal_care.configure(economy, active_world_adapter)
|
||||
@@ -248,7 +256,17 @@ func get_wander_offset(npc_id: int) -> Vector3:
|
||||
|
||||
|
||||
func simulate_tick() -> void:
|
||||
tick_count += 1
|
||||
var next_tick := tick_count + 1
|
||||
if _regional_simulation == null or not _regional_simulation.advance_to_tick(next_tick):
|
||||
var regional_error := (
|
||||
_regional_simulation.get_last_error()
|
||||
if _regional_simulation != null
|
||||
else "regional facade is missing"
|
||||
)
|
||||
push_error("SimulationManager: regional tick failed: " + regional_error)
|
||||
set_process(false)
|
||||
return
|
||||
tick_count = next_tick
|
||||
if debug_logs:
|
||||
print("--- Tick ", tick_count, " ---")
|
||||
animal_care.advance(tick_count)
|
||||
@@ -2408,6 +2426,34 @@ func get_state_checksum() -> String:
|
||||
return create_state_record().to_json().sha256_text()
|
||||
|
||||
|
||||
func get_regional_state_checksum() -> String:
|
||||
return _regional_simulation.checksum() if _regional_simulation != null else ""
|
||||
|
||||
|
||||
func get_world_state_checksum() -> String:
|
||||
var manifest := create_save_manifest()
|
||||
return manifest.checksum() if manifest != null else ""
|
||||
|
||||
|
||||
func get_regional_snapshot() -> Dictionary:
|
||||
return (
|
||||
_regional_simulation.to_dictionary().duplicate(true) if _regional_simulation != null else {}
|
||||
)
|
||||
|
||||
|
||||
func request_regional_jajce_delivery(
|
||||
amount: float = 1.0, presentation_mode: StringName = &"never"
|
||||
) -> bool:
|
||||
if (
|
||||
not uses_combined_save_manifest()
|
||||
or _regional_simulation == null
|
||||
or not is_finite(amount)
|
||||
or amount <= 0.0
|
||||
):
|
||||
return false
|
||||
return _regional_simulation.depart_jajce_delivery(amount, presentation_mode)
|
||||
|
||||
|
||||
func get_latest_decision(npc_id: int) -> ActionSelectionResult:
|
||||
return latest_decisions.get(npc_id)
|
||||
|
||||
@@ -2484,6 +2530,59 @@ func serialize_state() -> String:
|
||||
return create_state_record().to_json()
|
||||
|
||||
|
||||
func uses_combined_save_manifest() -> bool:
|
||||
var scope := event_log.get_scope()
|
||||
return (
|
||||
StringName(scope.get("world_id", &"")) == SimulationIds.REGIONAL_WORLD_BOSNIA
|
||||
and (StringName(scope.get("location_id", &"")) == SimulationIds.REGIONAL_LOCATION_JAJCE)
|
||||
)
|
||||
|
||||
|
||||
func can_serialize_local_state_only() -> bool:
|
||||
if uses_combined_save_manifest() or _regional_simulation == null:
|
||||
return false
|
||||
var idle_facade := RegionalSimulationFacadeScript.create_jajce_route(
|
||||
simulation_seed, tick_count
|
||||
)
|
||||
return idle_facade != null and idle_facade.checksum() == _regional_simulation.checksum()
|
||||
|
||||
|
||||
func create_save_manifest() -> SimulationSaveManifest:
|
||||
if _regional_simulation == null:
|
||||
return null
|
||||
return SimulationSaveManifest.create(create_state_record(), _regional_simulation)
|
||||
|
||||
|
||||
func serialize_save_manifest() -> String:
|
||||
var manifest := create_save_manifest()
|
||||
return manifest.to_json() if manifest != null else ""
|
||||
|
||||
|
||||
func restore_save_manifest(manifest: SimulationSaveManifest) -> bool:
|
||||
if manifest == null:
|
||||
return false
|
||||
var local_candidate := manifest.get_local_state()
|
||||
var regional_candidate := manifest.get_regional_facade()
|
||||
if local_candidate == null or regional_candidate == null:
|
||||
return false
|
||||
var previous_local := create_state_record()
|
||||
var previous_regional := _regional_simulation
|
||||
_regional_simulation = regional_candidate
|
||||
_restoring_save_manifest = true
|
||||
var restored := restore_state(local_candidate)
|
||||
_restoring_save_manifest = false
|
||||
if restored:
|
||||
_publish_restored_state()
|
||||
return true
|
||||
_regional_simulation = previous_regional
|
||||
_restoring_save_manifest = true
|
||||
var rolled_back := restore_state(previous_local)
|
||||
_restoring_save_manifest = false
|
||||
if not rolled_back:
|
||||
push_error("SimulationManager: failed to roll back rejected save manifest")
|
||||
return false
|
||||
|
||||
|
||||
func restore_state_from_json(json_text: String) -> bool:
|
||||
var record := SimulationStateRecord.from_json(json_text)
|
||||
if record == null:
|
||||
@@ -2578,8 +2677,24 @@ func restore_state(record: SimulationStateRecord) -> bool:
|
||||
conflict_system.register_npc_combatants(npcs)
|
||||
conflict_system.configure(economy, tick_interval)
|
||||
_sync_player_combatant()
|
||||
if not _restoring_save_manifest and not _initialize_regional_simulation(tick_count):
|
||||
return false
|
||||
if not _restoring_save_manifest:
|
||||
_publish_restored_state()
|
||||
return true
|
||||
|
||||
|
||||
func _publish_restored_state() -> void:
|
||||
village_changed.emit(village)
|
||||
state_restored.emit()
|
||||
|
||||
|
||||
func _initialize_regional_simulation(current_tick: int) -> bool:
|
||||
var facade := RegionalSimulationFacadeScript.create_jajce_route(simulation_seed, current_tick)
|
||||
if facade == null:
|
||||
push_error("SimulationManager: could not initialize the Jajce regional facade")
|
||||
return false
|
||||
_regional_simulation = facade
|
||||
return true
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user