完善客户端功能并同步差距文档

This commit is contained in:
shenlei
2026-09-03 18:40:01 +09:00
parent f93a172296
commit 13ccb8d02d
135 changed files with 21881 additions and 1259 deletions
+71
View File
@@ -0,0 +1,71 @@
# dungeon_state_test —— GC_DUNGEON 目的地状态回归。
# godot --headless --path project --script dungeon_state_test.gd
extends SceneTree
const DungeonState = preload("res://dungeon_state.gd")
class FakeClient extends Node:
signal dungeon_event(subheader: int, x: int, y: int, has_destination: bool)
signal world_reset
var _fail := 0
func _ck(condition: bool, message: String) -> void:
if not condition:
_fail += 1
printerr("FAIL: " + message)
func _init() -> void:
await _run()
if _fail == 0:
print("PASS: dungeon_state_test (GC_DUNGEON destination / arrival / reset)")
quit(0)
else:
printerr("%d check(s) failed" % _fail)
quit(1)
func _run() -> void:
MapCoord.set_base(Vector2.ZERO)
var client := FakeClient.new()
var player := Node3D.new()
get_root().add_child(client)
get_root().add_child(player)
var state := DungeonState.new()
get_root().add_child(state)
state.setup(client, func() -> Node3D: return player)
await process_frame
var changes: Array = []
var alarms: Array = []
state.destination_changed.connect(func(active: bool, pos: Vector3): changes.append([active, pos]))
state.alarm_requested.connect(func(pos: Vector3): alarms.append(pos))
client.dungeon_event.emit(state.TIME_ATTACK_START, 0, 0, false)
_ck(not state.active and state.last_subheader == state.TIME_ATTACK_START,
"TIME_ATTACK_START is consumed without inventing a timer")
client.dungeon_event.emit(state.DESTINATION_POSITION, 3210, 6540, true)
_ck(state.active, "destination packet activates route")
_ck(state.destination_cm == Vector2(3210, 6540), "destination keeps server cm")
_ck(state.destination_world.distance_to(Vector3(32.1, 0.0, 65.4)) < 0.01,
"destination converts global cm through MapCoord")
_ck(changes.size() == 1 and changes[0][0] == true, "destination_changed opens target")
_ck(alarms.size() == 1, "destination alarms immediately")
# Reference uses Manhattan < 10000 cm, so exactly 100m is not complete and
# 99m is complete. Keep the player in the same global coordinate frame.
player.global_position = Vector3(32.1, 0.0, 65.4 - 100.0)
state._process(0.0)
_ck(state.active, "Manhattan distance exactly 100m remains active")
player.global_position = Vector3(32.1, 0.0, 65.4 - 99.0)
state._process(0.0)
_ck(not state.active, "Manhattan distance below 100m completes route")
_ck(changes.size() == 2 and changes[1][0] == false, "arrival closes target")
client.dungeon_event.emit(state.DESTINATION_POSITION, 10000, 20000, true)
_ck(state.active, "second destination reopens route")
client.world_reset.emit()
_ck(not state.active and state.destination_cm == Vector2.ZERO and changes.size() == 4,
"world reset clears dungeon destination")
client.queue_free()
player.queue_free()
state.queue_free()