Add supply auto-purchase and preserve save recovery state
This commit is contained in:
@@ -19,7 +19,10 @@ const CONSTRUCTION_EXPENSE_ACCOUNT := &"CONSTRUCTION_EXPENSE"
|
||||
const OPERATING_EXPENSE_ACCOUNT := &"OPERATING_EXPENSE"
|
||||
const AUTHORITY_FINE_ACCOUNT := &"AUTHORITY_FINE_EXPENSE"
|
||||
const WAGE_EXPENSE_ACCOUNT := &"WAGE_EXPENSE"
|
||||
const RUNTIME_SNAPSHOT_VERSION := 13
|
||||
const RUNTIME_SNAPSHOT_VERSION := 14
|
||||
const AUTO_PURCHASE_RUNTIME_SNAPSHOT_VERSION := 14
|
||||
const EVENT_THREAT_RUNTIME_SNAPSHOT_VERSION := 13
|
||||
const AutoPurchasePlansType := preload("res://scripts/supply/supply_auto_purchase_plans.gd")
|
||||
const CLEANING_RUNTIME_SNAPSHOT_VERSION := 12
|
||||
const WEATHER_RUNTIME_SNAPSHOT_VERSION := 11
|
||||
const FacilityCleanliness = preload("res://scripts/environment/facility_cleanliness_service.gd")
|
||||
@@ -110,6 +113,7 @@ var logistics_dispatcher := LogisticsDispatcher.new()
|
||||
var logistics_requests: Dictionary = {}
|
||||
var kitchen_production := KitchenProductionService.new()
|
||||
var supply_management := SupplyManagementService.new()
|
||||
var auto_purchase_plans := AutoPurchasePlansType.new()
|
||||
var supply_logistics := SupplyLogisticsBridge.new()
|
||||
var elevators := ElevatorService.new()
|
||||
var legacy_stairs := LegacyStairService.new()
|
||||
@@ -300,6 +304,7 @@ func initialize(clock: SimulationKernel, state: Variant, seed := DEFAULT_WORLD_S
|
||||
register_command_executor(&"complete_progression_quest", Callable(self, "_execute_complete_progression_quest"))
|
||||
register_command_executor(&"acknowledge_operations_pause", Callable(self, "_execute_acknowledge_operations_pause"))
|
||||
register_command_executor(&"purchase_supplies", Callable(self, "_execute_purchase_supplies"))
|
||||
register_command_executor(&"set_supply_auto_purchase", Callable(self, "_execute_set_supply_auto_purchase"))
|
||||
register_command_executor(&"set_kitchen_production", Callable(self, "_execute_set_kitchen_production"))
|
||||
register_command_executor(&"add_inventory_stack", Callable(self, "_execute_add_inventory_stack"))
|
||||
register_command_executor(&"create_logistics_request", Callable(self, "_execute_create_logistics_request"))
|
||||
@@ -502,9 +507,7 @@ func get_rng_stream(stream_id: StringName) -> DeterministicRng:
|
||||
|
||||
func create_snapshot() -> Dictionary:
|
||||
var rng_data := {}
|
||||
var stream_ids: Array = _rng_streams.keys()
|
||||
stream_ids.sort()
|
||||
for stream_id: Variant in stream_ids:
|
||||
for stream_id: StringName in _sorted_name_keys(_rng_streams):
|
||||
var stream: DeterministicRng = _rng_streams[stream_id]
|
||||
rng_data[String(stream_id)] = stream.snapshot()
|
||||
var owned_systems := {
|
||||
@@ -531,6 +534,7 @@ func create_snapshot() -> Dictionary:
|
||||
&"upkeep_settlement": upkeep_settlement.create_snapshot(),
|
||||
&"inventory": inventory_service.create_snapshot(),
|
||||
&"kitchen_production": kitchen_production.create_snapshot(),
|
||||
&"auto_purchase_plans": auto_purchase_plans.create_snapshot(),
|
||||
&"elevators": elevators.create_snapshot(),
|
||||
&"legacy_stairs": legacy_stairs.create_snapshot(),
|
||||
&"logistics_dispatcher": logistics_dispatcher.create_snapshot(),
|
||||
@@ -610,6 +614,7 @@ func _restore_snapshot_internal(snapshot: Dictionary, recovery_mode: bool) -> bo
|
||||
UPKEEP_RUNTIME_SNAPSHOT_VERSION,
|
||||
WEATHER_RUNTIME_SNAPSHOT_VERSION,
|
||||
CLEANING_RUNTIME_SNAPSHOT_VERSION,
|
||||
EVENT_THREAT_RUNTIME_SNAPSHOT_VERSION,
|
||||
RUNTIME_SNAPSHOT_VERSION,
|
||||
]:
|
||||
return false
|
||||
@@ -649,6 +654,8 @@ func _restore_snapshot_internal(snapshot: Dictionary, recovery_mode: bool) -> bo
|
||||
runtime_current_keys.append(&"weather")
|
||||
if runtime_schema_version >= CLEANING_RUNTIME_SNAPSHOT_VERSION:
|
||||
runtime_current_keys.append(&"facility_cleanliness")
|
||||
if runtime_schema_version >= AUTO_PURCHASE_RUNTIME_SNAPSHOT_VERSION:
|
||||
runtime_current_keys.append(&"auto_purchase_plans")
|
||||
if not _dictionary_has_exact_canonical_keys(runtime_data, runtime_current_keys) \
|
||||
or typeof(runtime_data.get(&"runtime_schema_version", null)) != TYPE_INT \
|
||||
or typeof(runtime_data.get(&"world_seed", null)) != TYPE_INT \
|
||||
@@ -688,6 +695,10 @@ func _restore_snapshot_internal(snapshot: Dictionary, recovery_mode: bool) -> bo
|
||||
return false
|
||||
if runtime_schema_version >= STAIRS_RUNTIME_SNAPSHOT_VERSION and not runtime_data.get(&"legacy_stairs", null) is Dictionary:
|
||||
return false
|
||||
if runtime_schema_version < AUTO_PURCHASE_RUNTIME_SNAPSHOT_VERSION and runtime_data.has(&"auto_purchase_plans"):
|
||||
return false
|
||||
if runtime_schema_version >= AUTO_PURCHASE_RUNTIME_SNAPSHOT_VERSION and not runtime_data.get(&"auto_purchase_plans", null) is Dictionary:
|
||||
return false
|
||||
var restored_catalog := MvpContentCatalog.new()
|
||||
var restored_catalog_report := restored_catalog.rebuild()
|
||||
if not bool(restored_catalog_report.get(&"valid", false)):
|
||||
@@ -738,6 +749,13 @@ func _restore_snapshot_internal(snapshot: Dictionary, recovery_mode: bool) -> bo
|
||||
var restored_queue := CommandQueue.new()
|
||||
if not restored_queue.restore_snapshot(runtime_data[&"command_queue"]):
|
||||
return false
|
||||
if runtime_schema_version < AUTO_PURCHASE_RUNTIME_SNAPSHOT_VERSION:
|
||||
# Old saves must not reinterpret an unsupported queued action as a new
|
||||
# paid feature when loading into this release. Failed historical actions
|
||||
# remain ordinary recorded history; only resumable pending work is gated.
|
||||
for row: Dictionary in restored_queue.create_snapshot()["pending"]:
|
||||
if row["command_type"] == "set_supply_auto_purchase":
|
||||
return false
|
||||
var restored_id_generator := StableIdGenerator.new()
|
||||
if not restored_id_generator.restore_snapshot(runtime_data[&"id_generator"]):
|
||||
return false
|
||||
@@ -1203,6 +1221,10 @@ func _restore_snapshot_internal(snapshot: Dictionary, recovery_mode: bool) -> bo
|
||||
return false
|
||||
if restored_kitchen.current_minute != restored_runtime_domain_minute or not restored_kitchen.validate_crosslinks():
|
||||
return false
|
||||
var restored_auto_purchase := AutoPurchasePlansType.new()
|
||||
if runtime_schema_version >= AUTO_PURCHASE_RUNTIME_SNAPSHOT_VERSION:
|
||||
if not restored_auto_purchase.restore_snapshot(runtime_data[&"auto_purchase_plans"], restored_facilities, restored_economy, restored_runtime_domain_minute):
|
||||
return false
|
||||
if not SupplyLogisticsBridge.validate_crosslinks(restored_logistics, restored_staff, restored_inventory, restored_facilities):
|
||||
return false
|
||||
var restored_weather := WeatherTimeline.new()
|
||||
@@ -1271,6 +1293,7 @@ func _restore_snapshot_internal(snapshot: Dictionary, recovery_mode: bool) -> bo
|
||||
economy_service = restored_economy
|
||||
inventory_service = restored_inventory
|
||||
kitchen_production = restored_kitchen
|
||||
auto_purchase_plans = restored_auto_purchase
|
||||
logistics_dispatcher = restored_dispatcher
|
||||
logistics_requests = restored_logistics
|
||||
facility_service = restored_facilities
|
||||
@@ -1966,6 +1989,7 @@ func _build_operations_external_state() -> Dictionary:
|
||||
&"upkeep_settlement": upkeep_settlement.create_snapshot(),
|
||||
&"inventory": inventory_service.create_snapshot(),
|
||||
&"kitchen_production": kitchen_production.create_snapshot(),
|
||||
&"auto_purchase_plans": auto_purchase_plans.create_snapshot(),
|
||||
&"facilities": facility_service.create_snapshot(),
|
||||
&"facility_cleanliness": facility_cleanliness.create_snapshot(),
|
||||
&"guests": guest_service.create_snapshot(),
|
||||
@@ -2023,7 +2047,7 @@ func _restore_operations_external_state(token: Variant) -> bool:
|
||||
var saved: Dictionary = token
|
||||
var required_dictionary_keys: Array[StringName] = [
|
||||
&"facility_upkeep", &"upkeep_settlement", &"facility_cleanliness",
|
||||
&"game_state", &"command_queue", &"economy", &"inventory", &"kitchen_production", &"facilities", &"guests",
|
||||
&"game_state", &"command_queue", &"economy", &"inventory", &"kitchen_production", &"auto_purchase_plans", &"facilities", &"guests",
|
||||
&"staff", &"relationships", &"events", &"authority", &"world", &"path", &"elevators", &"legacy_stairs",
|
||||
&"excavation", &"spatial_subslots", &"route_projection",
|
||||
&"facility_infrastructure",
|
||||
@@ -2066,6 +2090,7 @@ func _restore_operations_external_state(token: Variant) -> bool:
|
||||
var facilities_ok := facility_service.restore_snapshot(saved[&"facilities"])
|
||||
facilities_ok = facility_cleanliness.restore_snapshot(saved.get(&"facility_cleanliness", {})) and facilities_ok
|
||||
var kitchen_ok := kitchen_production.restore_snapshot(saved[&"kitchen_production"])
|
||||
var auto_purchase_ok := auto_purchase_plans.restore_snapshot(saved[&"auto_purchase_plans"], facility_service, economy_service, int(saved[&"captured_minute"]))
|
||||
var guests_ok := guest_service.restore_snapshot(saved[&"guests"])
|
||||
var staff_ok := staff_service.restore_snapshot(saved[&"staff"])
|
||||
var relationships_ok := relationship_service.restore_snapshot(saved[&"relationships"])
|
||||
@@ -2116,7 +2141,7 @@ func _restore_operations_external_state(token: Variant) -> bool:
|
||||
rng_ok = false
|
||||
|
||||
_discard_operations_domain_events()
|
||||
var participants_ok := upkeep_ok and state_ok and command_queue_ok and economy_ok and inventory_ok and kitchen_ok \
|
||||
var participants_ok := upkeep_ok and state_ok and command_queue_ok and economy_ok and inventory_ok and kitchen_ok and auto_purchase_ok \
|
||||
and facilities_ok and guests_ok and staff_ok and relationships_ok \
|
||||
and events_ok and authority_ok and world_ok and spatial_ok and path_ok \
|
||||
and route_ok and infrastructure_ok and excavation_ok \
|
||||
@@ -2173,6 +2198,7 @@ func _operations_external_state_matches(saved: Dictionary) -> bool:
|
||||
or not _strict_variants_equal(economy_service.create_snapshot(), saved[&"economy"]) \
|
||||
or not _strict_variants_equal(inventory_service.create_snapshot(), saved[&"inventory"]) \
|
||||
or not _strict_variants_equal(kitchen_production.create_snapshot(), saved[&"kitchen_production"]) \
|
||||
or not _strict_variants_equal(auto_purchase_plans.create_snapshot(), saved[&"auto_purchase_plans"]) \
|
||||
or not _strict_variants_equal(facility_service.create_snapshot(), saved[&"facilities"]) \
|
||||
or not _strict_variants_equal(facility_cleanliness.create_snapshot(), saved.get(&"facility_cleanliness", {})) \
|
||||
or not _strict_variants_equal(guest_service.create_snapshot(), saved[&"guests"]) \
|
||||
@@ -5081,6 +5107,7 @@ func _initialize_s2_operations() -> void:
|
||||
facility_service.current_minute = _clock.absolute_minute
|
||||
_configure_facility_boundaries()
|
||||
_connect_facility_signals()
|
||||
auto_purchase_plans = AutoPurchasePlansType.new()
|
||||
kitchen_production = KitchenProductionService.new()
|
||||
kitchen_production.configure(inventory_service, facility_service, definition_registry, _clock.absolute_minute)
|
||||
|
||||
@@ -7541,6 +7568,7 @@ func _execute_demolish_facility(command: SimulationCommand) -> CommandResult:
|
||||
result.command_id = command.command_id
|
||||
if result.is_success():
|
||||
kitchen_production.remove_plan(instance_id)
|
||||
auto_purchase_plans.remove_warehouse(instance_id)
|
||||
return result
|
||||
|
||||
|
||||
@@ -8184,6 +8212,7 @@ func _advance_inventory_and_logistics(absolute_minute: int) -> void:
|
||||
inventory_service.current_minute = absolute_minute
|
||||
inventory_service.process_expired(absolute_minute, &"inventory.waste")
|
||||
if int(_state.get_resource(&"mana")) > 0:
|
||||
supply_management.advance_auto_purchases(self, absolute_minute)
|
||||
supply_management.ensure_deliveries(self, absolute_minute)
|
||||
supply_logistics.tick(absolute_minute)
|
||||
|
||||
@@ -12138,6 +12167,10 @@ func _execute_purchase_supplies(command: SimulationCommand) -> CommandResult:
|
||||
return supply_management.purchase(self, command)
|
||||
|
||||
|
||||
func _execute_set_supply_auto_purchase(command: SimulationCommand) -> CommandResult:
|
||||
return supply_management.set_auto_purchase(self, command)
|
||||
|
||||
|
||||
func _execute_set_kitchen_production(command: SimulationCommand) -> CommandResult:
|
||||
return supply_management.set_production(self, command)
|
||||
|
||||
@@ -12965,7 +12998,7 @@ func _prepare_construction_dimension_snapshot(job_id: StringName) -> Dictionary:
|
||||
|
||||
## Read-only saved-game preflight used by the load menu before confirmation.
|
||||
func preview_facility_dimensions_at_path(save_path: String) -> Dictionary:
|
||||
var loaded := SaveService.load_snapshot(save_path)
|
||||
var loaded := SaveService.inspect_snapshot(save_path)
|
||||
if not loaded[&"ok"]: return loaded
|
||||
var isolated: Variant = get_script().new()
|
||||
var preview_clock: Variant = load("res://autoload/game_clock.gd").new()
|
||||
|
||||
Reference in New Issue
Block a user