extends SceneTree var failures: Array[String] = [] func _initialize() -> void: call_deferred("_run") func _run() -> void: var manager := _create_manager(961) var bush := ResourceNode.new() bush.name = "RegrowBush" bush.node_id = &"regrow_bush" bush.action_id = SimulationIds.ACTION_GATHER_FOOD bush.resource_id = SimulationIds.RESOURCE_FOOD bush.initial_amount = 2.0 bush.max_amount = 5.0 bush.regrow_rate = 0.1 bush.debug_label_enabled = false var interaction_point := Marker3D.new() interaction_point.name = "InteractionPoint" interaction_point.position = Vector3.ZERO bush.add_child(interaction_point) root.add_child(bush) await process_frame _check( manager.register_resource_node(bush), "Regrowth test should bind a real finite ResourceNode" ) var state: ResourceStateRecord = manager.get_resource_state(bush.node_id) _check( ( is_equal_approx(state.get_amount_remaining(), 2.0) and is_equal_approx(state.get_max_amount(), 5.0) and is_equal_approx(state.get_regrow_rate(), 0.1) ), "Regrowth metadata should bind from the authored node" ) _check( is_equal_approx(manager.harvest_resource_node(bush), 2.0), "Harvesting should deplete the regrowing bush into carried inventory" ) _check( is_equal_approx(state.get_amount_remaining(), 0.0), "The regrowing bush should reach zero after harvesting" ) manager.simulate_tick() manager.simulate_tick() _check( is_equal_approx(state.get_amount_remaining(), 0.2), "Regrowing resources should recover exactly their rate per simulation tick" ) for _tick in 50: manager.simulate_tick() _check( ( is_equal_approx(state.get_amount_remaining(), 5.0) and state.get_amount_remaining() <= state.get_max_amount() ), "Regrowth should stop at the authored maximum without creating extra food" ) manager.simulate_tick() var saved_json: String = manager.serialize_state() var restored := _create_manager(962) _check( restored.restore_state_from_json(saved_json), "Regrowing resource state should survive save and restore" ) _check( ( restored.get_state_checksum() == manager.get_state_checksum() and is_equal_approx( restored.get_resource_state(bush.node_id).get_amount_remaining(), 5.0 ) and is_equal_approx(restored.get_resource_state(bush.node_id).get_regrow_rate(), 0.1) ), "Restore should preserve the regrow amount, cap, and checksum" ) restored.free() var v3_data: Dictionary = state.to_dictionary() v3_data["schema_version"] = ResourceStateRecord.REGROW_LEGACY_SCHEMA_VERSION v3_data.erase("max_amount") v3_data.erase("regrow_rate") var migrated := ResourceStateRecord.from_dictionary(v3_data) _check( ( migrated != null and is_equal_approx(migrated.get_max_amount(), 5.0) and is_equal_approx(migrated.get_regrow_rate(), 0.0) ), "Resource v3 should migrate with its current amount as cap and no regrowth" ) bush.queue_free() manager.free() _finish() func _create_manager(seed_value: int = 961) -> Node: var manager: Node = load("res://simulation/SimulationManager.gd").new() manager.simulation_seed = seed_value manager.debug_logs = false var home_positions: Array[Vector3] = [ Vector3(0.0, 0.0, 0.0), Vector3(2.0, 0.0, 0.0), Vector3(10.0, 0.0, 0.0), Vector3(12.0, 0.0, 0.0), Vector3(30.0, 0.0, 30.0), Vector3(40.0, 0.0, 40.0), ] manager.home_positions = home_positions root.add_child(manager) manager.set_process(false) return manager func _finish() -> void: if failures.is_empty(): print("[TEST] Resource regrowth passed: bounded recovery -> cap -> restore") quit(0) return for failure in failures: push_error("[TEST] " + failure) quit(1) func _check(condition: bool, message: String) -> void: if not condition: failures.append(message)