style: apply gdformat formatting across the entire project
Auto-format all GDScript files using gdformat from gdtoolkit. This is a baseline formatting pass to ensure consistent style: - Normalizes indentation and spacing - Wraps long lines to 100 characters - Removes trailing whitespace - Standardizes blank lines between functions 68 files reformatted, 8 files left unchanged (3rd-party addon files with parse errors excluded).
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
extends SceneTree
|
||||
|
||||
|
||||
class FakeActiveWorld:
|
||||
extends Node
|
||||
|
||||
@@ -12,12 +13,15 @@ class FakeActiveWorld:
|
||||
func get_activity_target(_action_id: StringName) -> Dictionary:
|
||||
return {"target_id": "", "position": activity_position}
|
||||
|
||||
|
||||
var failures: Array[String] = []
|
||||
var travel_requests: Array[Vector3] = []
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
|
||||
func _run() -> void:
|
||||
_test_selection_and_execution_are_separate()
|
||||
_test_target_resolution_and_travel_are_separate()
|
||||
@@ -31,16 +35,11 @@ func _run() -> void:
|
||||
push_error("[TEST] " + failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _test_selection_and_execution_are_separate() -> void:
|
||||
var village := SimVillage.new()
|
||||
village.debug_logs = false
|
||||
var npc := SimNPC.new(
|
||||
700,
|
||||
"BoundaryWorker",
|
||||
SimulationIds.PROFESSION_FARMER,
|
||||
5.0,
|
||||
5.0
|
||||
)
|
||||
var npc := SimNPC.new(700, "BoundaryWorker", SimulationIds.PROFESSION_FARMER, 5.0, 5.0)
|
||||
npc.hunger = 80.0
|
||||
var executor := ActionExecutionSystem.new()
|
||||
executor.advance_npc(npc, village)
|
||||
@@ -55,12 +54,12 @@ func _test_selection_and_execution_are_separate() -> void:
|
||||
"Selection should independently choose food retrieval"
|
||||
)
|
||||
|
||||
|
||||
func _test_target_resolution_and_travel_are_separate() -> void:
|
||||
var adapter := FakeActiveWorld.new()
|
||||
adapter.resource_candidates = [{
|
||||
"target_id": "boundary_bush",
|
||||
"position": Vector3(3.0, 0.0, 2.0)
|
||||
}]
|
||||
adapter.resource_candidates = [
|
||||
{"target_id": "boundary_bush", "position": Vector3(3.0, 0.0, 2.0)}
|
||||
]
|
||||
root.add_child(adapter)
|
||||
|
||||
var manager: Node = load("res://simulation/SimulationManager.gd").new()
|
||||
@@ -70,18 +69,20 @@ func _test_target_resolution_and_travel_are_separate() -> void:
|
||||
manager.set_process(false)
|
||||
manager.npc_travel_requested.connect(_on_travel_requested)
|
||||
|
||||
var resource_state := ResourceStateRecord.from_dictionary({
|
||||
"schema_version": ResourceStateRecord.SCHEMA_VERSION,
|
||||
"node_id": "boundary_bush",
|
||||
"action_id": String(SimulationIds.ACTION_GATHER_FOOD),
|
||||
"resource_id": String(SimulationIds.RESOURCE_FOOD),
|
||||
"amount_remaining": 5.0,
|
||||
"yield_per_action": 1.0,
|
||||
"reserved_by": -1,
|
||||
"enabled": true,
|
||||
"can_npcs_use": true,
|
||||
"can_player_use": true
|
||||
})
|
||||
var resource_state := ResourceStateRecord.from_dictionary(
|
||||
{
|
||||
"schema_version": ResourceStateRecord.SCHEMA_VERSION,
|
||||
"node_id": "boundary_bush",
|
||||
"action_id": String(SimulationIds.ACTION_GATHER_FOOD),
|
||||
"resource_id": String(SimulationIds.RESOURCE_FOOD),
|
||||
"amount_remaining": 5.0,
|
||||
"yield_per_action": 1.0,
|
||||
"reserved_by": -1,
|
||||
"enabled": true,
|
||||
"can_npcs_use": true,
|
||||
"can_player_use": true
|
||||
}
|
||||
)
|
||||
manager.resource_states[resource_state.get_node_id()] = resource_state
|
||||
|
||||
var npc: SimNPC = manager.npcs[0]
|
||||
@@ -91,8 +92,7 @@ func _test_target_resolution_and_travel_are_separate() -> void:
|
||||
"Target resolver should resolve a resource from adapter facts"
|
||||
)
|
||||
_check(
|
||||
npc.target_id == &"boundary_bush"
|
||||
and resource_state.get_reserved_by() == npc.id,
|
||||
npc.target_id == &"boundary_bush" and resource_state.get_reserved_by() == npc.id,
|
||||
"Target resolver should authoritatively assign and reserve the target"
|
||||
)
|
||||
_check(
|
||||
@@ -113,12 +113,11 @@ func _test_target_resolution_and_travel_are_separate() -> void:
|
||||
manager.free()
|
||||
adapter.free()
|
||||
|
||||
func _on_travel_requested(
|
||||
_npc: SimNPC,
|
||||
target_position: Vector3
|
||||
) -> void:
|
||||
|
||||
func _on_travel_requested(_npc: SimNPC, target_position: Vector3) -> void:
|
||||
travel_requests.append(target_position)
|
||||
|
||||
|
||||
func _check(condition: bool, message: String) -> void:
|
||||
if not condition:
|
||||
failures.append(message)
|
||||
|
||||
@@ -2,9 +2,11 @@ extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
|
||||
func _run() -> void:
|
||||
var clock := SimulationClock.new(1.0)
|
||||
_check(clock.advance(0.4) == 0, "Clock should not tick before its interval")
|
||||
@@ -28,6 +30,7 @@ func _run() -> void:
|
||||
push_error("[TEST] " + failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _run_scenario(seed_value: int) -> String:
|
||||
var manager: Node = load("res://simulation/SimulationManager.gd").new()
|
||||
manager.simulation_seed = seed_value
|
||||
@@ -47,6 +50,7 @@ func _run_scenario(seed_value: int) -> String:
|
||||
manager.free()
|
||||
return checksum
|
||||
|
||||
|
||||
func _check(condition: bool, message: String) -> void:
|
||||
if not condition:
|
||||
failures.append(message)
|
||||
|
||||
@@ -2,9 +2,11 @@ extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
|
||||
func _run() -> void:
|
||||
var manager: Node = load("res://simulation/SimulationManager.gd").new()
|
||||
manager.debug_logs = false
|
||||
@@ -14,18 +16,20 @@ func _run() -> void:
|
||||
var pantry: StorageStateRecord = manager.get_pantry()
|
||||
pantry.withdraw(SimulationIds.RESOURCE_FOOD, 1000.0)
|
||||
manager._sync_village_food()
|
||||
var resource := ResourceStateRecord.from_dictionary({
|
||||
"schema_version": ResourceStateRecord.SCHEMA_VERSION,
|
||||
"node_id": "food_loop_bush",
|
||||
"action_id": String(SimulationIds.ACTION_GATHER_FOOD),
|
||||
"resource_id": String(SimulationIds.RESOURCE_FOOD),
|
||||
"amount_remaining": 10.0,
|
||||
"yield_per_action": 2.0,
|
||||
"reserved_by": -1,
|
||||
"enabled": true,
|
||||
"can_npcs_use": true,
|
||||
"can_player_use": true
|
||||
})
|
||||
var resource := ResourceStateRecord.from_dictionary(
|
||||
{
|
||||
"schema_version": ResourceStateRecord.SCHEMA_VERSION,
|
||||
"node_id": "food_loop_bush",
|
||||
"action_id": String(SimulationIds.ACTION_GATHER_FOOD),
|
||||
"resource_id": String(SimulationIds.RESOURCE_FOOD),
|
||||
"amount_remaining": 10.0,
|
||||
"yield_per_action": 2.0,
|
||||
"reserved_by": -1,
|
||||
"enabled": true,
|
||||
"can_npcs_use": true,
|
||||
"can_player_use": true
|
||||
}
|
||||
)
|
||||
manager.resource_states[resource.get_node_id()] = resource
|
||||
|
||||
var npc: SimNPC = manager.npcs[0]
|
||||
@@ -38,10 +42,9 @@ func _run() -> void:
|
||||
manager.simulate_tick()
|
||||
|
||||
_check(
|
||||
is_equal_approx(resource.get_amount_remaining(), 8.0)
|
||||
and is_equal_approx(
|
||||
npc.get_inventory_amount(SimulationIds.RESOURCE_FOOD),
|
||||
2.0
|
||||
(
|
||||
is_equal_approx(resource.get_amount_remaining(), 8.0)
|
||||
and is_equal_approx(npc.get_inventory_amount(SimulationIds.RESOURCE_FOOD), 2.0)
|
||||
),
|
||||
"Gathering should move food from the source into NPC inventory"
|
||||
)
|
||||
@@ -58,10 +61,9 @@ func _run() -> void:
|
||||
manager.notify_npc_arrived(npc.id)
|
||||
manager.simulate_tick()
|
||||
_check(
|
||||
is_equal_approx(pantry.get_amount(SimulationIds.RESOURCE_FOOD), 2.0)
|
||||
and is_equal_approx(
|
||||
npc.get_inventory_amount(SimulationIds.RESOURCE_FOOD),
|
||||
0.0
|
||||
(
|
||||
is_equal_approx(pantry.get_amount(SimulationIds.RESOURCE_FOOD), 2.0)
|
||||
and is_equal_approx(npc.get_inventory_amount(SimulationIds.RESOURCE_FOOD), 0.0)
|
||||
),
|
||||
"Deposit should transfer carried food into the pantry"
|
||||
)
|
||||
@@ -75,28 +77,23 @@ func _run() -> void:
|
||||
manager.notify_npc_arrived(npc.id)
|
||||
manager.simulate_tick()
|
||||
_check(
|
||||
is_equal_approx(pantry.get_amount(SimulationIds.RESOURCE_FOOD), 1.0)
|
||||
and is_equal_approx(
|
||||
npc.get_inventory_amount(SimulationIds.RESOURCE_FOOD),
|
||||
1.0
|
||||
(
|
||||
is_equal_approx(pantry.get_amount(SimulationIds.RESOURCE_FOOD), 1.0)
|
||||
and is_equal_approx(npc.get_inventory_amount(SimulationIds.RESOURCE_FOOD), 1.0)
|
||||
),
|
||||
"Withdraw should transfer pantry food into NPC inventory"
|
||||
)
|
||||
|
||||
manager.simulate_tick()
|
||||
_check(
|
||||
npc.current_task == SimulationIds.ACTION_EAT,
|
||||
"NPC carrying food should select eat"
|
||||
)
|
||||
_check(npc.current_task == SimulationIds.ACTION_EAT, "NPC carrying food should select eat")
|
||||
manager.notify_npc_arrived(npc.id)
|
||||
var hunger_before_eating := npc.hunger
|
||||
manager.simulate_tick()
|
||||
manager.simulate_tick()
|
||||
_check(
|
||||
npc.hunger < hunger_before_eating
|
||||
and is_equal_approx(
|
||||
npc.get_inventory_amount(SimulationIds.RESOURCE_FOOD),
|
||||
0.0
|
||||
(
|
||||
npc.hunger < hunger_before_eating
|
||||
and is_equal_approx(npc.get_inventory_amount(SimulationIds.RESOURCE_FOOD), 0.0)
|
||||
),
|
||||
"Eating should consume carried food and reduce hunger"
|
||||
)
|
||||
@@ -121,8 +118,10 @@ func _run() -> void:
|
||||
"Economic events should restore with the simulation"
|
||||
)
|
||||
_check(
|
||||
restored.economic_events.size() == manager.economic_events.size()
|
||||
and restored.next_event_id == manager.next_event_id,
|
||||
(
|
||||
restored.economic_events.size() == manager.economic_events.size()
|
||||
and restored.next_event_id == manager.next_event_id
|
||||
),
|
||||
"Economic event history and its next ID should round-trip"
|
||||
)
|
||||
|
||||
@@ -134,10 +133,12 @@ func _run() -> void:
|
||||
push_error("[TEST] " + failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _check(condition: bool, message: String) -> void:
|
||||
if not condition:
|
||||
failures.append(message)
|
||||
|
||||
|
||||
func _check_economic_event_chain(manager: Node) -> void:
|
||||
var expected_types: Array[StringName] = [
|
||||
SimulationIds.EVENT_RESOURCE_EXTRACTED,
|
||||
@@ -154,28 +155,19 @@ func _check_economic_event_chain(manager: Node) -> void:
|
||||
for index in expected_types.size():
|
||||
var event: EconomicEventRecord = manager.economic_events[index]
|
||||
_check(
|
||||
int(event.data["event_id"]) == index
|
||||
and StringName(event.data["event_type"]) == expected_types[index]
|
||||
and StringName(event.data["item_id"])
|
||||
== SimulationIds.RESOURCE_FOOD,
|
||||
(
|
||||
int(event.data["event_id"]) == index
|
||||
and StringName(event.data["event_type"]) == expected_types[index]
|
||||
and StringName(event.data["item_id"]) == SimulationIds.RESOURCE_FOOD
|
||||
),
|
||||
"Economic event order, identity, and item should be deterministic"
|
||||
)
|
||||
_check(
|
||||
is_equal_approx(
|
||||
float(manager.economic_events[0].data["amount"]),
|
||||
2.0
|
||||
)
|
||||
and is_equal_approx(
|
||||
float(manager.economic_events[1].data["amount"]),
|
||||
2.0
|
||||
)
|
||||
and is_equal_approx(
|
||||
float(manager.economic_events[2].data["amount"]),
|
||||
1.0
|
||||
)
|
||||
and is_equal_approx(
|
||||
float(manager.economic_events[3].data["amount"]),
|
||||
1.0
|
||||
(
|
||||
is_equal_approx(float(manager.economic_events[0].data["amount"]), 2.0)
|
||||
and is_equal_approx(float(manager.economic_events[1].data["amount"]), 2.0)
|
||||
and is_equal_approx(float(manager.economic_events[2].data["amount"]), 1.0)
|
||||
and is_equal_approx(float(manager.economic_events[3].data["amount"]), 1.0)
|
||||
),
|
||||
"Economic events should record exact transferred quantities"
|
||||
)
|
||||
|
||||
@@ -2,9 +2,11 @@ extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
|
||||
func _run() -> void:
|
||||
var main_scene: Node = load("res://main.tscn").instantiate()
|
||||
root.add_child(main_scene)
|
||||
@@ -19,26 +21,21 @@ func _run() -> void:
|
||||
main_scene.has_node("JajceWorld/TerrainRoot/Terrain3D"),
|
||||
"Playable runtime should instance the Jajce Terrain3D world"
|
||||
)
|
||||
var terrain: Terrain3D = main_scene.get_node(
|
||||
"JajceWorld/TerrainRoot/Terrain3D"
|
||||
)
|
||||
var terrain: Terrain3D = main_scene.get_node("JajceWorld/TerrainRoot/Terrain3D")
|
||||
_check(
|
||||
terrain.get_camera() == main_scene.get_node("CameraRig/Camera3D"),
|
||||
"Runtime Terrain3D should bind to the gameplay camera"
|
||||
)
|
||||
_check(
|
||||
not main_scene.has_node("World")
|
||||
and not main_scene.has_node("ResourceNodes")
|
||||
and not main_scene.has_node("ActivityMarkers"),
|
||||
(
|
||||
not main_scene.has_node("World")
|
||||
and not main_scene.has_node("ResourceNodes")
|
||||
and not main_scene.has_node("ActivityMarkers")
|
||||
),
|
||||
"Runtime should not retain duplicate flat-world objects"
|
||||
)
|
||||
var resource_root := main_scene.get_node(
|
||||
"JajceWorld/WorldObjects/ResourceNodes"
|
||||
)
|
||||
_check(
|
||||
resource_root.get_child_count() == 4,
|
||||
"Runtime should contain four Jajce ResourceNodes"
|
||||
)
|
||||
var resource_root := main_scene.get_node("JajceWorld/WorldObjects/ResourceNodes")
|
||||
_check(resource_root.get_child_count() == 4, "Runtime should contain four Jajce ResourceNodes")
|
||||
_check(
|
||||
simulation_manager.resource_states.size() == 4,
|
||||
"Simulation authority should bind all four Jajce resources"
|
||||
@@ -48,11 +45,7 @@ func _run() -> void:
|
||||
await _wait_for_navigation_map(navigation_map)
|
||||
NavigationServer3D.map_force_update(navigation_map)
|
||||
|
||||
var fixed_origins := [
|
||||
Vector3(-6.0, 0.0, -4.0),
|
||||
Vector3(0.0, 0.0, 0.0),
|
||||
Vector3(6.0, 0.0, 4.0)
|
||||
]
|
||||
var fixed_origins := [Vector3(-6.0, 0.0, -4.0), Vector3(0.0, 0.0, 0.0), Vector3(6.0, 0.0, 4.0)]
|
||||
var destinations: Array[Vector3] = []
|
||||
for marker_path in [
|
||||
"JajceWorld/LegacyActivityMarkers/PantryMarker",
|
||||
@@ -67,25 +60,14 @@ func _run() -> void:
|
||||
|
||||
for origin in fixed_origins:
|
||||
for destination in destinations:
|
||||
var path := NavigationServer3D.map_get_path(
|
||||
navigation_map,
|
||||
origin,
|
||||
destination,
|
||||
true
|
||||
)
|
||||
var path := NavigationServer3D.map_get_path(navigation_map, origin, destination, true)
|
||||
_check(
|
||||
not path.is_empty(),
|
||||
"Navigation path should exist from %s to %s" % [origin, destination]
|
||||
)
|
||||
|
||||
var village := SimVillage.new()
|
||||
var worker := SimNPC.new(
|
||||
100,
|
||||
"BaselineWorker",
|
||||
SimulationIds.PROFESSION_SCHOLAR,
|
||||
5.0,
|
||||
5.0
|
||||
)
|
||||
var worker := SimNPC.new(100, "BaselineWorker", SimulationIds.PROFESSION_SCHOLAR, 5.0, 5.0)
|
||||
worker.set_task(SimulationIds.ACTION_STUDY, 2.0)
|
||||
worker.start_working()
|
||||
var executor := ActionExecutionSystem.new()
|
||||
@@ -93,13 +75,7 @@ func _run() -> void:
|
||||
executor.advance_npc(worker, village)
|
||||
_check(worker.task_complete, "A two-tick working task should complete")
|
||||
|
||||
var starving := SimNPC.new(
|
||||
101,
|
||||
"BaselineStarving",
|
||||
SimulationIds.PROFESSION_WANDERER,
|
||||
5.0,
|
||||
5.0
|
||||
)
|
||||
var starving := SimNPC.new(101, "BaselineStarving", SimulationIds.PROFESSION_WANDERER, 5.0, 5.0)
|
||||
starving.hunger = 100.0
|
||||
starving.starvation_death_threshold = 1
|
||||
executor.advance_npc(starving, village)
|
||||
@@ -114,6 +90,7 @@ func _run() -> void:
|
||||
push_error("[TEST] " + failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _wait_for_navigation_map(navigation_map: RID) -> void:
|
||||
for attempt in 30:
|
||||
if (
|
||||
@@ -125,6 +102,7 @@ func _wait_for_navigation_map(navigation_map: RID) -> void:
|
||||
await physics_frame
|
||||
_check(false, "Navigation map did not synchronize within 30 physics frames")
|
||||
|
||||
|
||||
func _check(condition: bool, message: String) -> void:
|
||||
if not condition:
|
||||
failures.append(message)
|
||||
|
||||
@@ -2,9 +2,11 @@ extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
|
||||
func _run() -> void:
|
||||
var camera := Camera3D.new()
|
||||
camera.current = true
|
||||
@@ -24,8 +26,10 @@ func _run() -> void:
|
||||
)
|
||||
_check(
|
||||
terrain.assets.get_texture_count() >= 3,
|
||||
"Jajce terrain should expose at least three materials (found %s)"
|
||||
% terrain.assets.get_texture_count()
|
||||
(
|
||||
"Jajce terrain should expose at least three materials (found %s)"
|
||||
% terrain.assets.get_texture_count()
|
||||
)
|
||||
)
|
||||
_check(
|
||||
absf(terrain.data.get_height(Vector3.ZERO)) < 0.1,
|
||||
@@ -42,32 +46,22 @@ func _run() -> void:
|
||||
world.get_node("FoliageRoot").get_child_count() >= 10,
|
||||
"JajceWorld should include restrained authored foliage clusters"
|
||||
)
|
||||
_check(
|
||||
world.has_node("FortressBlockout"),
|
||||
"JajceWorld should include the fortress landmark"
|
||||
)
|
||||
_check(
|
||||
world.has_node("WaterRoot/WaterfallBody"),
|
||||
"WaterRoot should include a waterfall drop"
|
||||
)
|
||||
_check(world.has_node("FortressBlockout"), "JajceWorld should include the fortress landmark")
|
||||
_check(world.has_node("WaterRoot/WaterfallBody"), "WaterRoot should include a waterfall drop")
|
||||
_check(
|
||||
world.has_node("WaterRoot/WaterfallMist"),
|
||||
"WaterRoot should include waterfall mist particles"
|
||||
)
|
||||
_check(
|
||||
world.has_node("WaterRoot/RiverSurface"),
|
||||
"WaterRoot should include a river surface"
|
||||
)
|
||||
_check(world.has_node("WaterRoot/RiverSurface"), "WaterRoot should include a river surface")
|
||||
var environment: Environment = (
|
||||
world.get_node("WorldEnvironment") as WorldEnvironment
|
||||
).environment
|
||||
(world.get_node("WorldEnvironment") as WorldEnvironment).environment
|
||||
)
|
||||
_check(
|
||||
environment.fog_enabled and environment.sky != null,
|
||||
"Jajce environment should provide sky and restrained valley fog"
|
||||
)
|
||||
_check(
|
||||
world.has_node("VillageRoot/Mill")
|
||||
and world.has_node("VillageRoot/Bridge"),
|
||||
world.has_node("VillageRoot/Mill") and world.has_node("VillageRoot/Bridge"),
|
||||
"VillageRoot should include the mill and bridge blockouts"
|
||||
)
|
||||
var smoke_count := 0
|
||||
@@ -103,11 +97,7 @@ func _run() -> void:
|
||||
await _wait_for_navigation_map(navigation_map)
|
||||
NavigationServer3D.map_force_update(navigation_map)
|
||||
|
||||
var origins := [
|
||||
Vector3(-6, 0, -4),
|
||||
Vector3(0, 0, 0),
|
||||
Vector3(6, 0, 4)
|
||||
]
|
||||
var origins := [Vector3(-6, 0, -4), Vector3(0, 0, 0), Vector3(6, 0, 4)]
|
||||
var destinations: Array[Vector3] = []
|
||||
for resource in resources:
|
||||
destinations.append((resource as ResourceNode).interaction_point.global_position)
|
||||
@@ -116,12 +106,7 @@ func _run() -> void:
|
||||
|
||||
for origin in origins:
|
||||
for destination in destinations:
|
||||
var path := NavigationServer3D.map_get_path(
|
||||
navigation_map,
|
||||
origin,
|
||||
destination,
|
||||
true
|
||||
)
|
||||
var path := NavigationServer3D.map_get_path(navigation_map, origin, destination, true)
|
||||
_check(
|
||||
not path.is_empty(),
|
||||
"Jajce navigation path should exist from %s to %s" % [origin, destination]
|
||||
@@ -143,9 +128,7 @@ func _run() -> void:
|
||||
)
|
||||
var selected := ResourceNode.get_by_id(npc.target_id)
|
||||
if selected != null:
|
||||
var selected_state: ResourceStateRecord = manager.get_resource_state(
|
||||
selected.node_id
|
||||
)
|
||||
var selected_state: ResourceStateRecord = manager.get_resource_state(selected.node_id)
|
||||
_check(
|
||||
selected_state.get_reserved_by() == npc.id,
|
||||
"Selected Jajce resource should be authoritatively reserved"
|
||||
@@ -153,7 +136,9 @@ func _run() -> void:
|
||||
manager.release_resource(selected.node_id, npc.id)
|
||||
|
||||
if failures.is_empty():
|
||||
print("[TEST] Jajce scaffold passed: Terrain3D, 6 textures, shader water, building blockouts, chimney smoke")
|
||||
print(
|
||||
"[TEST] Jajce scaffold passed: Terrain3D, 6 textures, shader water, building blockouts, chimney smoke"
|
||||
)
|
||||
quit(0)
|
||||
return
|
||||
|
||||
@@ -161,6 +146,7 @@ func _run() -> void:
|
||||
push_error("[TEST] " + failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _wait_for_navigation_map(navigation_map: RID) -> void:
|
||||
for attempt in 30:
|
||||
if (
|
||||
@@ -172,6 +158,7 @@ func _wait_for_navigation_map(navigation_map: RID) -> void:
|
||||
await physics_frame
|
||||
_check(false, "Jajce navigation map did not synchronize within 30 physics frames")
|
||||
|
||||
|
||||
func _check(condition: bool, message: String) -> void:
|
||||
if not condition:
|
||||
failures.append(message)
|
||||
|
||||
@@ -2,9 +2,11 @@ extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
|
||||
func _run() -> void:
|
||||
var main_scene: Node = load("res://main.tscn").instantiate()
|
||||
root.add_child(main_scene)
|
||||
@@ -21,25 +23,13 @@ func _run() -> void:
|
||||
var carried_food: MeshInstance3D = visual.get_node("CarriedFood")
|
||||
_check(not carried_food.visible, "NPC should begin without a carried-food prop")
|
||||
npc.add_inventory(SimulationIds.RESOURCE_FOOD, 1.0)
|
||||
manager.emit_signal(
|
||||
"npc_inventory_changed",
|
||||
npc,
|
||||
SimulationIds.RESOURCE_FOOD,
|
||||
1.0
|
||||
)
|
||||
manager.emit_signal("npc_inventory_changed", npc, SimulationIds.RESOURCE_FOOD, 1.0)
|
||||
_check(carried_food.visible, "Carried food should be visible on the NPC")
|
||||
npc.remove_inventory(SimulationIds.RESOURCE_FOOD, 1.0)
|
||||
manager.emit_signal(
|
||||
"npc_inventory_changed",
|
||||
npc,
|
||||
SimulationIds.RESOURCE_FOOD,
|
||||
0.0
|
||||
)
|
||||
manager.emit_signal("npc_inventory_changed", npc, SimulationIds.RESOURCE_FOOD, 0.0)
|
||||
_check(not carried_food.visible, "Deposited or eaten food should be hidden")
|
||||
|
||||
var resource_state: ResourceStateRecord = manager.get_resource_state(
|
||||
&"berry_bush_01"
|
||||
)
|
||||
var resource_state: ResourceStateRecord = manager.get_resource_state(&"berry_bush_01")
|
||||
npc.set_task(SimulationIds.ACTION_GATHER_FOOD)
|
||||
npc.target_id = resource_state.get_node_id()
|
||||
npc.travel_target_position = Vector3(-6.0, 0.0, -8.0)
|
||||
@@ -60,9 +50,11 @@ func _run() -> void:
|
||||
"Unload should synchronize the last active position"
|
||||
)
|
||||
_check(
|
||||
npc.current_task == saved_action
|
||||
and npc.target_id == saved_target_id
|
||||
and npc.travel_target_position.is_equal_approx(saved_target_position),
|
||||
(
|
||||
npc.current_task == saved_action
|
||||
and npc.target_id == saved_target_id
|
||||
and npc.travel_target_position.is_equal_approx(saved_target_position)
|
||||
),
|
||||
"Unload should preserve action and target state"
|
||||
)
|
||||
_check(
|
||||
@@ -87,10 +79,7 @@ func _run() -> void:
|
||||
manager.get_state_checksum() == unloaded_checksum,
|
||||
"Loading a visual must not mutate simulation state"
|
||||
)
|
||||
_check(
|
||||
resource_state.get_reserved_by() == npc.id,
|
||||
"Reload should preserve the reservation"
|
||||
)
|
||||
_check(resource_state.get_reserved_by() == npc.id, "Reload should preserve the reservation")
|
||||
|
||||
var moved_position := authoritative_position + Vector3(0.5, 0.0, 0.25)
|
||||
reloaded.emit_signal("position_changed", npc.id, moved_position)
|
||||
@@ -124,6 +113,7 @@ func _run() -> void:
|
||||
push_error("[TEST] " + failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _check(condition: bool, message: String) -> void:
|
||||
if not condition:
|
||||
failures.append(message)
|
||||
|
||||
@@ -3,9 +3,11 @@ extends SceneTree
|
||||
var main_scene: Node
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
|
||||
func _run() -> void:
|
||||
main_scene = load("res://main.tscn").instantiate()
|
||||
root.add_child(main_scene)
|
||||
@@ -14,20 +16,14 @@ func _run() -> void:
|
||||
|
||||
var simulation_manager := main_scene.get_node("SimulationManager")
|
||||
var player := main_scene.get_node("Player")
|
||||
var bush := main_scene.get_node(
|
||||
"JajceWorld/WorldObjects/ResourceNodes/BerryBush_01"
|
||||
) as ResourceNode
|
||||
var tree := main_scene.get_node(
|
||||
"JajceWorld/WorldObjects/ResourceNodes/Tree_01"
|
||||
) as ResourceNode
|
||||
var bush := (
|
||||
main_scene.get_node("JajceWorld/WorldObjects/ResourceNodes/BerryBush_01") as ResourceNode
|
||||
)
|
||||
var tree := main_scene.get_node("JajceWorld/WorldObjects/ResourceNodes/Tree_01") as ResourceNode
|
||||
simulation_manager.set_process(false)
|
||||
|
||||
var bush_state: ResourceStateRecord = simulation_manager.get_resource_state(
|
||||
bush.node_id
|
||||
)
|
||||
var tree_state: ResourceStateRecord = simulation_manager.get_resource_state(
|
||||
tree.node_id
|
||||
)
|
||||
var bush_state: ResourceStateRecord = simulation_manager.get_resource_state(bush.node_id)
|
||||
var tree_state: ResourceStateRecord = simulation_manager.get_resource_state(tree.node_id)
|
||||
bush_state.set_amount_remaining(1.0)
|
||||
_check(
|
||||
simulation_manager.reserve_resource(bush.node_id, 999),
|
||||
@@ -41,11 +37,11 @@ func _run() -> void:
|
||||
is_equal_approx(bush_state.get_amount_remaining(), 0.0),
|
||||
"Player should deplete the nearby bush"
|
||||
)
|
||||
_check(is_equal_approx(simulation_manager.village.food, food_before + 1.0), "Village should receive exactly the bush's remaining food")
|
||||
_check(
|
||||
bush_state.get_reserved_by() == -1,
|
||||
"Depletion should release the NPC reservation"
|
||||
is_equal_approx(simulation_manager.village.food, food_before + 1.0),
|
||||
"Village should receive exactly the bush's remaining food"
|
||||
)
|
||||
_check(bush_state.get_reserved_by() == -1, "Depletion should release the NPC reservation")
|
||||
|
||||
player.global_position = tree.interaction_point.global_position
|
||||
var wood_before: float = simulation_manager.village.wood
|
||||
@@ -53,13 +49,13 @@ func _run() -> void:
|
||||
player.try_interact()
|
||||
|
||||
_check(
|
||||
is_equal_approx(
|
||||
tree_state.get_amount_remaining(),
|
||||
tree_before - tree.yield_per_action
|
||||
),
|
||||
is_equal_approx(tree_state.get_amount_remaining(), tree_before - tree.yield_per_action),
|
||||
"Player should extract the tree's configured yield"
|
||||
)
|
||||
_check(is_equal_approx(simulation_manager.village.wood, wood_before + tree.yield_per_action), "Village should receive exactly the extracted wood")
|
||||
_check(
|
||||
is_equal_approx(simulation_manager.village.wood, wood_before + tree.yield_per_action),
|
||||
"Village should receive exactly the extracted wood"
|
||||
)
|
||||
|
||||
if failures.is_empty():
|
||||
print("[TEST] ResourceNode player parity passed")
|
||||
@@ -70,6 +66,7 @@ func _run() -> void:
|
||||
push_error("[TEST] " + failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _check(condition: bool, message: String) -> void:
|
||||
if not condition:
|
||||
failures.append(message)
|
||||
|
||||
@@ -2,9 +2,11 @@ extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
|
||||
func _run() -> void:
|
||||
var test_directory := "user://save_slot_test_%s" % Time.get_ticks_usec()
|
||||
var store := SaveSlotStore.new(test_directory)
|
||||
@@ -48,17 +50,14 @@ func _run() -> void:
|
||||
|
||||
var unchanged_checksum: String = manager.get_state_checksum()
|
||||
var file := FileAccess.open(final_path, FileAccess.WRITE)
|
||||
file.store_string("{\"schema\":\"broken\"}")
|
||||
file.store_string('{"schema":"broken"}')
|
||||
file.close()
|
||||
_check(not store.load_into(manager), "Invalid save data should be rejected")
|
||||
_check(
|
||||
manager.get_state_checksum() == unchanged_checksum,
|
||||
"A rejected save must not partially mutate the simulation"
|
||||
)
|
||||
_check(
|
||||
not store.save(manager, "../escape"),
|
||||
"Slot names must not escape the save directory"
|
||||
)
|
||||
_check(not store.save(manager, "../escape"), "Slot names must not escape the save directory")
|
||||
|
||||
store.delete_slot()
|
||||
DirAccess.remove_absolute(ProjectSettings.globalize_path(test_directory))
|
||||
@@ -70,6 +69,7 @@ func _run() -> void:
|
||||
push_error("[TEST] " + failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _check(condition: bool, message: String) -> void:
|
||||
if not condition:
|
||||
failures.append(message)
|
||||
|
||||
@@ -2,9 +2,11 @@ extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
|
||||
func _run() -> void:
|
||||
_test_registry_integrity()
|
||||
_test_definition_backed_behavior()
|
||||
@@ -20,12 +22,10 @@ func _run() -> void:
|
||||
push_error("[TEST] " + failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _test_registry_integrity() -> void:
|
||||
var errors := SimulationDefinitions.validate()
|
||||
_check(
|
||||
errors.is_empty(),
|
||||
"Definition registry should validate: %s" % [errors]
|
||||
)
|
||||
_check(errors.is_empty(), "Definition registry should validate: %s" % [errors])
|
||||
|
||||
var action_ids: Array[StringName] = []
|
||||
for definition in SimulationDefinitions.get_actions():
|
||||
@@ -34,30 +34,19 @@ func _test_registry_integrity() -> void:
|
||||
SimulationDefinitions.get_action(definition.action_id) == definition,
|
||||
"Action lookup should return '%s'" % definition.action_id
|
||||
)
|
||||
_check(
|
||||
action_ids.size() == 9,
|
||||
"Registry should contain all nine executable prototype actions"
|
||||
)
|
||||
_check(action_ids.size() == 9, "Registry should contain all nine executable prototype actions")
|
||||
|
||||
var profession_ids := SimulationDefinitions.get_profession_ids()
|
||||
_check(
|
||||
profession_ids.size() == 5,
|
||||
"Registry should contain all five prototype professions"
|
||||
)
|
||||
_check(profession_ids.size() == 5, "Registry should contain all five prototype professions")
|
||||
for profession_id in profession_ids:
|
||||
_check(
|
||||
SimulationDefinitions.get_profession(profession_id) != null,
|
||||
"Profession lookup should return '%s'" % profession_id
|
||||
)
|
||||
|
||||
|
||||
func _test_definition_backed_behavior() -> void:
|
||||
var npc := SimNPC.new(
|
||||
500,
|
||||
"DefinitionWorker",
|
||||
SimulationIds.PROFESSION_SCHOLAR,
|
||||
5.0,
|
||||
5.0
|
||||
)
|
||||
var npc := SimNPC.new(500, "DefinitionWorker", SimulationIds.PROFESSION_SCHOLAR, 5.0, 5.0)
|
||||
npc.set_task(SimulationIds.ACTION_STUDY)
|
||||
var study := SimulationDefinitions.get_action(SimulationIds.ACTION_STUDY)
|
||||
_check(
|
||||
@@ -68,23 +57,18 @@ func _test_definition_backed_behavior() -> void:
|
||||
study.preferred_profession_id == SimulationIds.PROFESSION_SCHOLAR,
|
||||
"Study should reference the stable scholar profession ID"
|
||||
)
|
||||
var gather := SimulationDefinitions.get_action(
|
||||
SimulationIds.ACTION_GATHER_FOOD
|
||||
)
|
||||
var gather := SimulationDefinitions.get_action(SimulationIds.ACTION_GATHER_FOOD)
|
||||
_check(
|
||||
gather.target_type == SimulationIds.TARGET_RESOURCE
|
||||
and gather.resource_action_id == SimulationIds.ACTION_GATHER_FOOD,
|
||||
(
|
||||
gather.target_type == SimulationIds.TARGET_RESOURCE
|
||||
and gather.resource_action_id == SimulationIds.ACTION_GATHER_FOOD
|
||||
),
|
||||
"Gather-food target metadata should come from its definition"
|
||||
)
|
||||
|
||||
|
||||
func _test_state_reference_validation() -> void:
|
||||
var npc := SimNPC.new(
|
||||
501,
|
||||
"ValidationWorker",
|
||||
SimulationIds.PROFESSION_FARMER,
|
||||
5.0,
|
||||
5.0
|
||||
)
|
||||
var npc := SimNPC.new(501, "ValidationWorker", SimulationIds.PROFESSION_FARMER, 5.0, 5.0)
|
||||
var valid_data := NPCStateRecord.capture(npc).to_dictionary()
|
||||
var invalid_profession := valid_data.duplicate(true)
|
||||
invalid_profession["profession"] = "missing_profession"
|
||||
@@ -99,6 +83,7 @@ func _test_state_reference_validation() -> void:
|
||||
"NPC state should reject an unknown action ID"
|
||||
)
|
||||
|
||||
|
||||
func _test_id_round_trip() -> void:
|
||||
var manager: Node = load("res://simulation/SimulationManager.gd").new()
|
||||
manager.debug_logs = false
|
||||
@@ -116,8 +101,7 @@ func _test_id_round_trip() -> void:
|
||||
)
|
||||
for npc in restored.npcs:
|
||||
_check(
|
||||
typeof(npc.profession) == TYPE_STRING_NAME,
|
||||
"Profession should restore as StringName"
|
||||
typeof(npc.profession) == TYPE_STRING_NAME, "Profession should restore as StringName"
|
||||
)
|
||||
_check(
|
||||
typeof(npc.current_task) == TYPE_STRING_NAME,
|
||||
@@ -131,6 +115,7 @@ func _test_id_round_trip() -> void:
|
||||
manager.free()
|
||||
restored.free()
|
||||
|
||||
|
||||
func _check(condition: bool, message: String) -> void:
|
||||
if not condition:
|
||||
failures.append(message)
|
||||
|
||||
@@ -2,9 +2,11 @@ extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
|
||||
func _run() -> void:
|
||||
await _test_deterministic_continuation()
|
||||
await _test_resource_state_round_trip()
|
||||
@@ -23,6 +25,7 @@ func _run() -> void:
|
||||
push_error("[TEST] " + failure)
|
||||
quit(1)
|
||||
|
||||
|
||||
func _test_deterministic_continuation() -> void:
|
||||
var uninterrupted := _create_manager(91234)
|
||||
_advance_scenario(uninterrupted, 24)
|
||||
@@ -63,10 +66,9 @@ func _test_deterministic_continuation() -> void:
|
||||
before_save.free()
|
||||
restored.free()
|
||||
|
||||
|
||||
func _test_resource_state_round_trip() -> void:
|
||||
var resource: ResourceNode = load(
|
||||
"res://world/resource_nodes/ResourceNode.tscn"
|
||||
).instantiate()
|
||||
var resource: ResourceNode = load("res://world/resource_nodes/ResourceNode.tscn").instantiate()
|
||||
resource.node_id = &"SerializationTestBerry"
|
||||
resource.initial_amount = 9.0
|
||||
resource.yield_per_action = 2.0
|
||||
@@ -78,9 +80,7 @@ func _test_resource_state_round_trip() -> void:
|
||||
manager.register_resource_node(resource),
|
||||
"Resource presentation should bind to simulation authority"
|
||||
)
|
||||
var resource_state: ResourceStateRecord = manager.get_resource_state(
|
||||
resource.node_id
|
||||
)
|
||||
var resource_state: ResourceStateRecord = manager.get_resource_state(resource.node_id)
|
||||
_check(resource_state.reserve(42), "Resource should accept the test reservation")
|
||||
resource_state.extract()
|
||||
var saved_json: String = manager.serialize_state()
|
||||
@@ -103,15 +103,10 @@ func _test_resource_state_round_trip() -> void:
|
||||
is_equal_approx(resource_state.get_amount_remaining(), 7.0),
|
||||
"Resource amount should round-trip"
|
||||
)
|
||||
_check(
|
||||
resource_state.get_reserved_by() == 42,
|
||||
"Resource reservation should round-trip"
|
||||
)
|
||||
_check(resource_state.get_reserved_by() == 42, "Resource reservation should round-trip")
|
||||
_check(resource_state.is_enabled(), "Resource enabled state should round-trip")
|
||||
|
||||
var rebound: ResourceNode = load(
|
||||
"res://world/resource_nodes/ResourceNode.tscn"
|
||||
).instantiate()
|
||||
var rebound: ResourceNode = load("res://world/resource_nodes/ResourceNode.tscn").instantiate()
|
||||
rebound.node_id = &"SerializationTestBerry"
|
||||
rebound.initial_amount = 999.0
|
||||
root.add_child(rebound)
|
||||
@@ -128,28 +123,28 @@ func _test_resource_state_round_trip() -> void:
|
||||
manager.free()
|
||||
rebound.free()
|
||||
|
||||
|
||||
func _test_schema_rejection() -> void:
|
||||
var unsupported := JSON.stringify({
|
||||
"schema": SimulationStateRecord.SCHEMA_NAME,
|
||||
"schema_version": 999
|
||||
})
|
||||
var unsupported := JSON.stringify(
|
||||
{"schema": SimulationStateRecord.SCHEMA_NAME, "schema_version": 999}
|
||||
)
|
||||
_check(
|
||||
SimulationStateRecord.from_json(unsupported) == null,
|
||||
"Unsupported schema versions should be rejected"
|
||||
)
|
||||
_check(
|
||||
SimulationStateRecord.from_json("[]") == null,
|
||||
"Non-record JSON should be rejected"
|
||||
)
|
||||
_check(SimulationStateRecord.from_json("[]") == null, "Non-record JSON should be rejected")
|
||||
|
||||
|
||||
func _test_legacy_resource_migration() -> void:
|
||||
var migrated := ResourceStateRecord.from_dictionary({
|
||||
"schema_version": 1,
|
||||
"node_id": "legacy_tree",
|
||||
"amount_remaining": 6.0,
|
||||
"reserved_by": 12,
|
||||
"enabled": true
|
||||
})
|
||||
var migrated := ResourceStateRecord.from_dictionary(
|
||||
{
|
||||
"schema_version": 1,
|
||||
"node_id": "legacy_tree",
|
||||
"amount_remaining": 6.0,
|
||||
"reserved_by": 12,
|
||||
"enabled": true
|
||||
}
|
||||
)
|
||||
_check(migrated != null, "ResourceStateRecord v1 should migrate explicitly")
|
||||
if migrated == null:
|
||||
return
|
||||
@@ -158,19 +153,13 @@ func _test_legacy_resource_migration() -> void:
|
||||
"Migrated resource state should use the current nested schema"
|
||||
)
|
||||
_check(
|
||||
is_equal_approx(migrated.get_amount_remaining(), 6.0)
|
||||
and migrated.get_reserved_by() == 12,
|
||||
is_equal_approx(migrated.get_amount_remaining(), 6.0) and migrated.get_reserved_by() == 12,
|
||||
"Resource migration should preserve mutable authority"
|
||||
)
|
||||
|
||||
|
||||
func _test_legacy_npc_migration() -> void:
|
||||
var npc := SimNPC.new(
|
||||
88,
|
||||
"LegacyNPC",
|
||||
SimulationIds.PROFESSION_FARMER,
|
||||
5.0,
|
||||
5.0
|
||||
)
|
||||
var npc := SimNPC.new(88, "LegacyNPC", SimulationIds.PROFESSION_FARMER, 5.0, 5.0)
|
||||
var legacy_data := NPCStateRecord.capture(npc).to_dictionary()
|
||||
legacy_data["schema_version"] = NPCStateRecord.LEGACY_SCHEMA_VERSION
|
||||
legacy_data.erase("travel_target_position")
|
||||
@@ -184,6 +173,7 @@ func _test_legacy_npc_migration() -> void:
|
||||
"Legacy NPC migration should not invent an active travel target"
|
||||
)
|
||||
|
||||
|
||||
func _test_legacy_world_storage_migration() -> void:
|
||||
var manager := _create_manager(55)
|
||||
var legacy_data: Dictionary = manager.create_state_record().to_dictionary()
|
||||
@@ -193,35 +183,34 @@ func _test_legacy_world_storage_migration() -> void:
|
||||
_check(migrated != null, "World schema v1 should migrate pantry storage")
|
||||
if migrated != null:
|
||||
_check(
|
||||
migrated.storages.size() == 1
|
||||
and is_equal_approx(
|
||||
migrated.storages[0].get_amount(
|
||||
SimulationIds.RESOURCE_FOOD
|
||||
),
|
||||
manager.village.food
|
||||
(
|
||||
migrated.storages.size() == 1
|
||||
and is_equal_approx(
|
||||
migrated.storages[0].get_amount(SimulationIds.RESOURCE_FOOD),
|
||||
manager.village.food
|
||||
)
|
||||
),
|
||||
"World migration should preserve legacy village food in pantry"
|
||||
)
|
||||
manager.free()
|
||||
|
||||
|
||||
func _test_previous_world_event_migration() -> void:
|
||||
var manager := _create_manager(56)
|
||||
var previous_data: Dictionary = manager.create_state_record().to_dictionary()
|
||||
previous_data["schema_version"] = (
|
||||
SimulationStateRecord.PREVIOUS_SCHEMA_VERSION
|
||||
)
|
||||
previous_data["schema_version"] = (SimulationStateRecord.PREVIOUS_SCHEMA_VERSION)
|
||||
previous_data.erase("economic_events")
|
||||
previous_data["simulation"].erase("next_event_id")
|
||||
var migrated := SimulationStateRecord.from_dictionary(previous_data)
|
||||
_check(migrated != null, "World schema v2 should add an empty event stream")
|
||||
if migrated != null:
|
||||
_check(
|
||||
migrated.economic_events.is_empty()
|
||||
and int(migrated.simulation["next_event_id"]) == 0,
|
||||
migrated.economic_events.is_empty() and int(migrated.simulation["next_event_id"]) == 0,
|
||||
"World v2 migration should initialize deterministic event identity"
|
||||
)
|
||||
manager.free()
|
||||
|
||||
|
||||
func _create_manager(seed_value: int) -> Node:
|
||||
var manager: Node = load("res://simulation/SimulationManager.gd").new()
|
||||
manager.simulation_seed = seed_value
|
||||
@@ -230,6 +219,7 @@ func _create_manager(seed_value: int) -> Node:
|
||||
manager.set_process(false)
|
||||
return manager
|
||||
|
||||
|
||||
func _advance_scenario(manager: Node, steps: int) -> void:
|
||||
for step in steps:
|
||||
manager.simulate_tick()
|
||||
@@ -238,6 +228,7 @@ func _advance_scenario(manager: Node, steps: int) -> void:
|
||||
if npc.task_state == SimNPC.TASK_STATE_TRAVELING:
|
||||
manager.notify_npc_arrived(npc.id)
|
||||
|
||||
|
||||
func _check(condition: bool, message: String) -> void:
|
||||
if not condition:
|
||||
failures.append(message)
|
||||
|
||||
Reference in New Issue
Block a user