fix: center ground under chunks and align player spawn with chunk grid
checkpoint / checkpoint (push) Successful in 5m56s

This commit is contained in:
2026-09-17 13:36:59 +00:00
parent bbd9ffc46f
commit 7c77c0b447
4 changed files with 253 additions and 3 deletions
+109
View File
@@ -0,0 +1,109 @@
extends SceneTree
## Regression test for world chunk alignment and ground positioning.
var _passed: int = 0
var _failed: int = 0
func _check(label: String, condition: bool) -> void:
if condition:
print(" PASS: %s" % label)
_passed += 1
else:
printerr(" FAIL: %s" % label)
_failed += 1
func _init() -> void:
call_deferred("_run_tests")
func _run_tests() -> void:
print("--- World Chunk & Ground Alignment Test ---")
await process_frame
var packed: PackedScene = load("res://scenes/game.tscn")
var result := change_scene_to_packed(packed)
if result != OK:
printerr("SMOKE: failed to change scene, error ", result)
quit(1)
return
await scene_changed
var game: Node3D = current_scene as Node3D
_check("game scene ready", game != null)
# Initially, ground is at default test level position (0, -0.5, 0)
var ground: StaticBody3D = game.get_node_or_null("Level/Ground") as StaticBody3D
_check("Ground initially exists", ground != null)
_check("Ground initially at (0, -0.5, 0)", ground.position.is_equal_approx(Vector3(0, -0.5, 0)))
# Create a ChunkScene for chunk (0, 0, 0) with corner objects
var chunk_scene := ChunkScene.new()
chunk_scene.coord = Vector3i(0, 0, 0)
chunk_scene.name = "chunk_0_0_0"
game.add_child(chunk_scene)
# Add lamp post at corner (0.5, 0.5) and corner (31.5, 31.5)
var obj_corner1 := WorldObject.new()
obj_corner1.id = "lamp1"
obj_corner1.type = "prop"
obj_corner1.position = Vector3(0.5, 0.5, 0.0)
obj_corner1.properties = {"catalog_id": "lamp_post_01"}
chunk_scene.add_object(obj_corner1)
var obj_corner2 := WorldObject.new()
obj_corner2.id = "lamp2"
obj_corner2.type = "prop"
obj_corner2.position = Vector3(31.5, 31.5, 0.0)
obj_corner2.properties = {"catalog_id": "lamp_post_01"}
chunk_scene.add_object(obj_corner2)
# Trigger _on_chunk_loaded
game.call("_on_chunk_loaded", Vector3i(0, 0, 0), chunk_scene)
# Verify Ground has moved to center of chunk: (16.0, -0.5, 16.0)
_check("Ground moved to chunk center (16, -0.5, 16)", ground.position.is_equal_approx(Vector3(16.0, -0.5, 16.0)))
var shape_node := ground.find_child("CollisionShape3D", true, false) as CollisionShape3D
_check("Ground CollisionShape3D size >= 40x40", shape_node != null and (shape_node.shape as BoxShape3D).size.x >= 40.0 and (shape_node.shape as BoxShape3D).size.z >= 40.0)
var mesh_node := ground.find_child("MeshInstance3D", true, false) as MeshInstance3D
_check("Ground MeshInstance3D size >= 40x40", mesh_node != null and (mesh_node.mesh as BoxMesh).size.x >= 40.0 and (mesh_node.mesh as BoxMesh).size.z >= 40.0)
# Verify corners are inside ground bounds
var half_x: float = (shape_node.shape as BoxShape3D).size.x * 0.5
var half_z: float = (shape_node.shape as BoxShape3D).size.z * 0.5
var min_gx: float = ground.position.x - half_x
var max_gx: float = ground.position.x + half_x
var min_gz: float = ground.position.z - half_z
var max_gz: float = ground.position.z + half_z
_check("Corner (0.5, 0.5) is on ground", 0.5 >= min_gx and 0.5 <= max_gx and 0.5 >= min_gz and 0.5 <= max_gz)
_check("Corner (31.5, 31.5) is on ground", 31.5 >= min_gx and 31.5 <= max_gx and 31.5 >= min_gz and 31.5 <= max_gz)
# Verify PlayerSpawn defaulted to chunk center (16, 1.5, 16)
var spawn_marker := game.get_node_or_null("Level/PlayerSpawn") as Node3D
_check("PlayerSpawn marker is at (16, 1.5, 16)", spawn_marker != null and spawn_marker.global_position.is_equal_approx(Vector3(16.0, 1.5, 16.0)))
# Now test placed spawn_point object
var chunk_scene2 := ChunkScene.new()
chunk_scene2.coord = Vector3i(0, 0, 0)
chunk_scene2.name = "chunk_with_spawn"
game.add_child(chunk_scene2)
var spawn_obj := WorldObject.new()
spawn_obj.id = "spawn1"
spawn_obj.type = "spawn_point"
spawn_obj.position = Vector3(8.5, 12.5, 0.0)
spawn_obj.properties = {"catalog_id": "spawn_point"}
chunk_scene2.add_object(spawn_obj)
game.call("_on_chunk_loaded", Vector3i(0, 0, 0), chunk_scene2)
_check("PlayerSpawn moved to placed spawn_point at (8.5, 1.5, 12.5)", spawn_marker != null and spawn_marker.global_position.is_equal_approx(Vector3(8.5, 1.5, 12.5)))
print("\n=== SMOKE RESULT: %d/%d passed ===" % [_passed, _passed + _failed])
if _failed > 0:
quit(1)
else:
quit(0)