Files
Void-Bastion/tests/online_snapshot_test.gd

109 lines
6.1 KiB
GDScript

extends Node
func _ready() -> void:
call_deferred("_run")
func _run() -> void:
var game = load("res://main.tscn").instantiate()
get_tree().root.add_child(game)
await get_tree().process_frame
game.ui_language = "en"
assert(game._ui("FREUNDESLISTE") == "FRIENDS")
assert(game._ui("WELLE") == "WAVE")
game.ui_language = "de"
assert(game._ui("FREUNDESLISTE") == "FREUNDESLISTE")
game._on_match_invite_received({"room_code": "ABC123", "from": "Testpilot"})
assert(game.pending_match_invite.room_code == "ABC123")
game.pending_match_invite.clear()
game.friend_return_mode = "matchmaking"
game.multiplayer_manager.matchmaking_mode = "private_host"
game.multiplayer_manager.matchmaking_state = "hosting"
game.multiplayer_manager.private_room_code = "ABC123"
assert(game._can_invite_friends())
game.multiplayer_manager.matchmaking_state = "lobby"
assert(game._can_invite_friends(), "Im privaten Warteraum muss EINLADEN sichtbar bleiben.")
game.multiplayer_manager.matchmaking_state = "offline"
assert(not game._can_invite_friends(), "Ein alter Raumcode darf keine Einladung mehr ermöglichen.")
game.coop_online_mode = true
var base_snapshot := {
"difficulty": 1, "reactor_lives": 30, "wave": 1, "wave_active": true,
"enemies_to_spawn": 0, "wave_types_remaining": [], "towers": [],
"enemies": [{"id": 4, "type": 0, "x": 100.0, "y": 200.0, "hp": 40.0,
"max_hp": 40.0, "shield": false, "boss": false}], "shots": []
}
game._apply_online_snapshot(base_snapshot)
assert(game.enemies.size() == 1)
assert(game.enemies[0].pos == Vector2(100, 200))
var first_enemy: Dictionary = game.enemies[0]
var next_snapshot: Dictionary = base_snapshot.duplicate(true)
next_snapshot["enemies"][0]["x"] = 200.0
next_snapshot["enemies"][0]["hp"] = 25.0
game._apply_online_snapshot(next_snapshot)
assert(is_same(first_enemy, game.enemies[0]), "Gegnerdaten sollen zwischen Paketen wiederverwendet werden.")
game._update_online_interpolation(0.05)
assert(game.enemies[0].pos.x > 100.0 and game.enemies[0].pos.x < 200.0,
"Die Position soll zwischen zwei Serverständen gleichmäßig übergehen.")
game._update_online_interpolation(0.1)
assert(is_equal_approx(game.enemies[0].pos.x, 200.0))
game.online_projectiles.append({"pos": Vector2.ZERO, "target": Vector2(30, 0), "speed": 920.0, "color": Color.WHITE})
game._update_online_projectiles(0.1)
assert(game.online_projectiles.is_empty(), "Geschosse dürfen bei einem langen Frame nicht am Ziel vorbeipendeln.")
var online_manager: OnlineManager = game.get_node("OnlineManager")
var received: Array = []
online_manager.match_snapshot_received.connect(func(snapshot: Dictionary) -> void: received.append(snapshot))
online_manager.pending_snapshot_payloads.append(JSON.stringify({"tick": 1, "shots": [{"id": 1}]}))
online_manager.pending_snapshot_payloads.append(JSON.stringify({"tick": 2, "shots": [{"id": 2}]}))
online_manager._flush_pending_snapshots()
assert(received.size() == 1 and received[0].tick == 2, "Nur der neueste Spielstand darf angewendet werden.")
assert(received[0].shots.size() == 2, "Schusseffekte aus zusammengefassten Spielständen müssen erhalten bleiben.")
received.clear()
online_manager.current_match = {"match_id": "test-match"}
for tick in 8:
online_manager._on_match_state({"match_id": "test-match", "op_code": online_manager.OP_SNAPSHOT,
"data": JSON.stringify({"tick": tick, "shots": [{"id": tick}]})})
assert(online_manager.pending_snapshot_payloads.size() == online_manager.MAX_PENDING_SNAPSHOTS,
"Die Warteschlange muss auch nach einem längeren Rückstau begrenzt bleiben.")
online_manager._flush_pending_snapshots()
assert(received.size() == 1 and received[0].tick == 7)
assert(received[0].shots.size() == online_manager.MAX_PENDING_SNAPSHOTS)
var diagnostic_bundle: String = online_manager.get_diagnostic_bundle()
assert(diagnostic_bundle.contains("\"event\":\"window\""), "Die Online-Diagnose muss einen kopierbaren Messbericht erzeugen.")
assert(diagnostic_bundle.contains("\"queue_dropped\":3"), "Verworfene Zustände im Rückstau müssen erfasst werden.")
online_manager._finish_match_diagnostics("test_finished")
assert(online_manager.diagnostic_match_key.is_empty())
assert(online_manager.diagnostic_finished_match_key == "test-match".sha256_text().substr(0, 12))
online_manager._on_match_state({"match_id": "test-match", "op_code": online_manager.OP_SNAPSHOT,
"data": JSON.stringify({"tick": 8, "shots": []})})
assert(online_manager.diagnostic_file == null, "Nach dem Rundenende darf kein zweiter Diagnosebericht geöffnet werden.")
game._select_map(0)
game._prepare_draw_geometry()
assert(not game.draw_geometry_dirty and not game.road_tile_cache.is_empty())
assert(not game.build_cell_cache.is_empty())
game._select_map(1)
assert(game.draw_geometry_dirty, "Ein Kartenwechsel muss die Weggeometrie erneuern.")
game._prepare_draw_geometry()
assert(not game.draw_geometry_dirty)
game.coop_mode = true
game._configure_coop_arena()
game._prepare_draw_geometry()
var partner_cells: Array = game.build_cell_cache.filter(func(cell: Dictionary) -> bool: return cell.partner)
assert(not partner_cells.is_empty(), "Die gespiegelte Koop-Seite braucht eigene Baufelder.")
assert(partner_cells.all(func(cell: Dictionary) -> bool: return cell.rect.get_center().x > game.COOP_MIRROR_X),
"Für Spieler 1 muss nur die rechte Seite als Partnerseite markiert sein.")
game.coop_online_mode = true
game.local_player_slot = 1
game.draw_geometry_dirty = true
game._prepare_draw_geometry()
partner_cells = game.build_cell_cache.filter(func(cell: Dictionary) -> bool: return cell.partner)
assert(not partner_cells.is_empty() and partner_cells.all(func(cell: Dictionary) -> bool: return cell.rect.get_center().x < game.COOP_MIRROR_X),
"Für Spieler 2 muss nur die linke Seite als Partnerseite markiert sein.")
game.camera_offset.x = game.COOP_WORLD_WIDTH - game.SCREEN.x
game._toggle_coop_side()
assert(game.status_text == "PARTNER-SEITE", "Der Seitenwechsel muss Spieler 2 links als Partnerseite benennen.")
game._toggle_coop_side()
assert(game.status_text == "DEINE SEITE", "Der Seitenwechsel muss Spieler 2 rechts als eigene Seite benennen.")
print("VOID_BASTION_ONLINE_SNAPSHOT_OK")
get_tree().quit()