extends SceneTree ## Headless M02 contract, interpolation, cache and player-injection regression. const TERRAIN_QUERY_PATH := "res://src/gameplay/terrain/terrain_query.gd" const ADT_TERRAIN_QUERY_PATH := "res://src/gameplay/terrain/adt_terrain_query.gd" const PLAYER_CONTROLLER_PATH := "res://src/scenes/player/third_person_wow_controller.gd" const REGRESSION_SCENE_PATH := "res://src/tests/scenes/player_input_regression.tscn" var _synthetic_adt_tile_data: Dictionary = {} var _synthetic_loader_call_count := 0 class FlatTerrainQuery extends TerrainQuery: var _height_units: float func _init(height_units: float) -> void: _height_units = height_units func sample_ground_height(_godot_world_position: GodotWorldPosition) -> TerrainGroundSample: return TerrainGroundSample.available(_height_units) func _initialize() -> void: _run_verification.call_deferred() func _run_verification() -> void: var failures: Array[String] = [] _verify_typed_result_contract(failures) _verify_synthetic_adt_interpolation_and_cache(failures) _verify_unavailable_tile(failures) _verify_player_injection(failures) _verify_source_boundaries(failures) if not failures.is_empty(): for failure in failures: push_error("TERRAIN_QUERY: %s" % failure) quit(1) return print("TERRAIN_QUERY PASS contract=4 interpolation=1 cache=1 failures=2 player_injection=1") quit(0) func _verify_typed_result_contract(failures: Array[String]) -> void: var available_sample := TerrainGroundSample.available(123.5) _expect_true(available_sample.is_available, "available sample state", failures) _expect_near(available_sample.height_units, 123.5, "available sample height", failures) _expect_true(available_sample.failure_code.is_empty(), "available sample has no failure", failures) var unavailable_sample := TerrainGroundSample.unavailable(&"synthetic_failure") _expect_true(not unavailable_sample.is_available, "unavailable sample state", failures) _expect_equal(unavailable_sample.failure_code, &"synthetic_failure", "unavailable failure code", failures) var base_sample := TerrainQuery.new().sample_ground_height(GodotWorldPosition.new(0.0, 0.0, 0.0)) _expect_equal(base_sample.failure_code, &"terrain_query_not_implemented", "base query failure", failures) var non_finite_sample := TerrainGroundSample.available(NAN) _expect_true(not non_finite_sample.is_available, "non-finite sample unavailable", failures) _expect_equal(non_finite_sample.failure_code, &"terrain_height_not_finite", "non-finite failure code", failures) func _verify_synthetic_adt_interpolation_and_cache(failures: Array[String]) -> void: var query_position := GodotWorldPosition.new(17000.0, 999.0, 26525.0) _synthetic_adt_tile_data = _build_synthetic_adt_tile(query_position) _synthetic_loader_call_count = 0 var terrain_query := AdtTerrainQuery.new("res://synthetic", "Azeroth", _load_synthetic_adt_tile) var first_sample := terrain_query.sample_ground_height(query_position) _expect_true(first_sample.is_available, "synthetic ADT sample available", failures) _expect_near_with_tolerance(first_sample.height_units, 137.0, 0.002, "synthetic bilinear height", failures) var second_sample := terrain_query.sample_ground_height(query_position) _expect_near_with_tolerance(second_sample.height_units, 137.0, 0.002, "cached synthetic height", failures) _expect_equal(_synthetic_loader_call_count, 1, "ADT tile loaded once", failures) func _verify_unavailable_tile(failures: Array[String]) -> void: var query_position := GodotWorldPosition.new(17000.0, 0.0, 26525.0) var empty_query := AdtTerrainQuery.new("res://synthetic", "Azeroth", func(_path: String) -> Dictionary: return {}) var empty_sample := empty_query.sample_ground_height(query_position) _expect_true(not empty_sample.is_available, "empty ADT unavailable", failures) _expect_equal(empty_sample.failure_code, &"adt_tile_unavailable", "empty ADT failure", failures) var invalid_heights_data := _build_synthetic_adt_tile(query_position) var invalid_chunks: Array = invalid_heights_data.get("chunks", []) (invalid_chunks[invalid_chunks.size() - 1] as Dictionary)["heights"] = PackedFloat32Array() var invalid_query := AdtTerrainQuery.new( "res://synthetic", "Azeroth", func(_path: String) -> Dictionary: return invalid_heights_data ) var invalid_sample := invalid_query.sample_ground_height(query_position) _expect_equal(invalid_sample.failure_code, &"adt_chunk_heights_invalid", "invalid heights failure", failures) func _verify_player_injection(failures: Array[String]) -> void: var packed_scene := load(REGRESSION_SCENE_PATH) as PackedScene _expect_true(packed_scene != null, "regression scene loads", failures) if packed_scene == null: return var player := packed_scene.instantiate() as CharacterBody3D player.set_terrain_query(FlatTerrainQuery.new(20.0)) root.add_child(player) player.set_physics_process(false) _expect_near(player.position.y, 20.05, "injected spawn ground height", failures) player.position.y = 30.0 player.call("_physics_process", 1.0) _expect_near(player.position.y, 20.05, "injected physics ground snap", failures) player.free() func _verify_source_boundaries(failures: Array[String]) -> void: var terrain_contract_source := _read_text(TERRAIN_QUERY_PATH, failures) _expect_true(not terrain_contract_source.contains("extends Node"), "TerrainQuery omits Node", failures) _expect_true(not terrain_contract_source.contains("Vector3"), "TerrainQuery omits untyped Vector3 position", failures) var adt_query_source := _read_text(ADT_TERRAIN_QUERY_PATH, failures) _expect_true(adt_query_source.contains("ADTLoader"), "ADT adapter owns native loader", failures) _expect_true(adt_query_source.contains("_adt_tile_cache"), "ADT adapter owns tile cache", failures) var player_source := _read_text(PLAYER_CONTROLLER_PATH, failures) for forbidden_text in ["ADTLoader", "load_adt", "_adt_cache", "_find_chunk", "_outer_height_index"]: _expect_true(not player_source.contains(forbidden_text), "player omits %s" % forbidden_text, failures) _expect_true(player_source.contains("set_terrain_query"), "player exposes terrain query injection", failures) _expect_true(player_source.contains("_terrain_query.sample_ground_height"), "player delegates ground sampling", failures) func _build_synthetic_adt_tile(query_position: GodotWorldPosition) -> Dictionary: var tile_coordinate := CoordinateMapper.godot_to_adt_tile(query_position) var tile_local_position := CoordinateMapper.godot_to_adt_tile_local(query_position) var chunk_coordinate := CoordinateMapper.adt_tile_local_to_chunk(tile_coordinate, tile_local_position) var chunk_size := CoordinateMapper.ADT_CHUNK_SIZE_YARDS var outer_grid_unit_size := chunk_size / 8.0 var target_chunk_origin := Vector3( query_position.x_units - outer_grid_unit_size * 4.5, 100.0, query_position.z_units - outer_grid_unit_size * 3.25 ) var tile_origin := target_chunk_origin - Vector3( chunk_coordinate.chunk_x * chunk_size, 0.0, chunk_coordinate.chunk_y * chunk_size ) var heights := PackedFloat32Array() heights.resize(145) for row in range(9): for column in range(9): heights[row * 17 + column] = float(row * 10 + column) var target_chunk := {"origin": target_chunk_origin, "heights": heights} if chunk_coordinate.chunk_x == 0 and chunk_coordinate.chunk_y == 0: return {"chunks": [target_chunk]} return { "chunks": [ {"origin": tile_origin, "heights": PackedFloat32Array()}, target_chunk, ] } func _load_synthetic_adt_tile(_absolute_path: String) -> Dictionary: _synthetic_loader_call_count += 1 return _synthetic_adt_tile_data func _read_text(path: String, failures: Array[String]) -> String: var file := FileAccess.open(path, FileAccess.READ) if file == null: failures.append("cannot open %s" % path) return "" return file.get_as_text() func _expect_near(actual_value: float, expected_value: float, label: String, failures: Array[String]) -> void: if absf(actual_value - expected_value) > 0.000001: failures.append("%s expected %.6f, got %.6f" % [label, expected_value, actual_value]) func _expect_near_with_tolerance( actual_value: float, expected_value: float, tolerance: float, label: String, failures: Array[String] ) -> void: if absf(actual_value - expected_value) > tolerance: failures.append("%s expected %.6f ± %.6f, got %.6f" % [label, expected_value, tolerance, actual_value]) func _expect_equal(actual_value: Variant, expected_value: Variant, label: String, failures: Array[String]) -> void: if actual_value != expected_value: failures.append("%s expected %s, got %s" % [label, expected_value, actual_value]) func _expect_true(actual_value: bool, label: String, failures: Array[String]) -> void: if not actual_value: failures.append("%s expected true" % label)