109 lines
6.1 KiB
GDScript
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()
|