refactor: clarify simulation ownership

This commit is contained in:
Rijad Zuzo
2026-07-10 11:02:11 +02:00
parent 0f7b12080e
commit ce8f71082b
29 changed files with 793 additions and 587 deletions
+223
View File
@@ -0,0 +1,223 @@
extends RefCounted
signal inventory_changed(npc: SimNPC, item_id: StringName, amount: float)
signal economic_event_requested(
event_type: StringName,
actor_id: int,
source_id: StringName,
destination_id: StringName,
item_id: StringName,
amount: float
)
signal narrative_event_requested(
event_type: StringName, actor_id: int, source_id: StringName, action_display: String
)
var village: SimVillage
var storage_states: Dictionary = {}
var debug_logs := false
func configure(village_state: SimVillage, should_debug: bool) -> void:
village = village_state
debug_logs = should_debug
func initialize_storage() -> void:
if village == null:
return
if not storage_states.has(SimulationIds.STORAGE_VILLAGE_PANTRY):
storage_states[SimulationIds.STORAGE_VILLAGE_PANTRY] = StorageStateRecord.create(
SimulationIds.STORAGE_VILLAGE_PANTRY,
{String(SimulationIds.RESOURCE_FOOD): village.food}
)
if not storage_states.has(SimulationIds.STORAGE_VILLAGE_WOODPILE):
storage_states[SimulationIds.STORAGE_VILLAGE_WOODPILE] = StorageStateRecord.create(
SimulationIds.STORAGE_VILLAGE_WOODPILE,
{String(SimulationIds.RESOURCE_WOOD): village.wood}
)
sync_all()
func restore_storage(records: Array[StorageStateRecord]) -> void:
storage_states.clear()
for storage_record in records:
storage_states[storage_record.get_storage_id()] = storage_record
# Older saves may not contain every authored storage. Preserve their village
# aggregates by creating only the missing records before synchronizing.
initialize_storage()
func get_storage(storage_id: StringName) -> StorageStateRecord:
return storage_states.get(storage_id) as StorageStateRecord
func get_pantry() -> StorageStateRecord:
return get_storage(SimulationIds.STORAGE_VILLAGE_PANTRY)
func get_woodpile() -> StorageStateRecord:
return get_storage(SimulationIds.STORAGE_VILLAGE_WOODPILE)
func get_storage_for_resource(resource_id: StringName) -> StorageStateRecord:
match resource_id:
SimulationIds.RESOURCE_FOOD:
return get_pantry()
SimulationIds.RESOURCE_WOOD:
return get_woodpile()
return null
func sync_all() -> void:
if village == null:
return
var pantry := get_pantry()
var woodpile := get_woodpile()
if pantry != null:
village.food = pantry.get_amount(SimulationIds.RESOURCE_FOOD)
if woodpile != null:
village.wood = woodpile.get_amount(SimulationIds.RESOURCE_WOOD)
_refresh_village_scores()
func sync_resource(resource_id: StringName) -> void:
if village == null:
return
var storage := get_storage_for_resource(resource_id)
if storage == null:
return
match resource_id:
SimulationIds.RESOURCE_FOOD:
village.food = storage.get_amount(resource_id)
SimulationIds.RESOURCE_WOOD:
village.wood = storage.get_amount(resource_id)
_refresh_village_scores()
func deposit_inventory(npc: SimNPC, item_id: StringName) -> float:
var storage := get_storage_for_resource(item_id)
if storage == null:
return 0.0
var deposited := storage.deposit(item_id, npc.get_inventory_amount(item_id))
npc.remove_inventory(item_id, deposited)
sync_resource(item_id)
if deposited > 0.0:
inventory_changed.emit(npc, item_id, npc.get_inventory_amount(item_id))
economic_event_requested.emit(
SimulationIds.EVENT_STORAGE_DEPOSITED,
npc.id,
SimulationIds.npc_inventory_id(npc.id),
storage.get_storage_id(),
item_id,
deposited
)
return deposited
func withdraw_to_inventory(npc: SimNPC, item_id: StringName, amount: float) -> float:
var storage := get_storage_for_resource(item_id)
if storage == null:
return 0.0
var withdrawn := storage.withdraw(item_id, amount)
npc.add_inventory(item_id, withdrawn)
sync_resource(item_id)
if withdrawn > 0.0:
inventory_changed.emit(npc, item_id, npc.get_inventory_amount(item_id))
economic_event_requested.emit(
SimulationIds.EVENT_STORAGE_WITHDRAWN,
npc.id,
storage.get_storage_id(),
SimulationIds.npc_inventory_id(npc.id),
item_id,
withdrawn
)
return withdrawn
func consume_npc_food(npc: SimNPC) -> bool:
if npc.remove_inventory(SimulationIds.RESOURCE_FOOD, 1.0) < 1.0:
npc.hunger = minf(npc.hunger + 5.0, 100.0)
npc.is_starving = npc.hunger >= 90.0
return false
npc.hunger = maxf(npc.hunger - 55.0, 0.0)
npc.starvation_ticks = 0
npc.is_starving = npc.hunger >= 90.0
inventory_changed.emit(
npc,
SimulationIds.RESOURCE_FOOD,
npc.get_inventory_amount(SimulationIds.RESOURCE_FOOD)
)
economic_event_requested.emit(
SimulationIds.EVENT_ITEM_CONSUMED,
npc.id,
SimulationIds.npc_inventory_id(npc.id),
&"consumed",
SimulationIds.RESOURCE_FOOD,
1.0
)
return true
func consume_completion_cost(npc: SimNPC, definition: ActionDefinition) -> bool:
if definition == null or not definition.has_completion_cost():
return true
var resource_id := definition.completion_cost_resource_id
var required_amount := definition.completion_cost_amount
var storage := get_storage_for_resource(resource_id)
var available := storage.get_amount(resource_id) if storage != null else 0.0
if storage == null or available < required_amount:
var reason := "%s: needs %.0f %s (%.1f available)" % [
definition.display_name,
required_amount,
String(resource_id).capitalize(),
available,
]
narrative_event_requested.emit(
SimulationIds.EVENT_TASK_BLOCKED,
npc.id,
storage.get_storage_id() if storage != null else &"",
reason
)
return false
var consumed := storage.withdraw(resource_id, required_amount)
sync_resource(resource_id)
if consumed < required_amount:
return false
economic_event_requested.emit(
SimulationIds.EVENT_ITEM_CONSUMED,
npc.id,
storage.get_storage_id(),
&"consumed",
resource_id,
consumed
)
if debug_logs:
print(
"[VillageEconomy] %s consumed %.1f %s for %s"
% [npc.npc_name, consumed, resource_id, definition.action_id]
)
return true
func deposit_resource(resource_id: StringName, amount: float) -> float:
var storage := get_storage_for_resource(resource_id)
if storage == null:
return 0.0
var deposited := storage.deposit(resource_id, amount)
sync_resource(resource_id)
return deposited
func withdraw_resource(resource_id: StringName, amount: float) -> float:
var storage := get_storage_for_resource(resource_id)
if storage == null:
return 0.0
var withdrawn := storage.withdraw(resource_id, amount)
sync_resource(resource_id)
return withdrawn
func _refresh_village_scores() -> void:
village.update_modifiers()
village.update_priorities()
+1
View File
@@ -0,0 +1 @@
uid://boecv7w7txoj0