68 lines
3.3 KiB
GDScript
68 lines
3.3 KiB
GDScript
extends SceneTree
|
|
|
|
var game: Node3D
|
|
var checks := 0
|
|
var failures := 0
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("run")
|
|
|
|
func check(value: bool, title: String) -> void:
|
|
checks += 1
|
|
if value:
|
|
print("PASS ", title)
|
|
else:
|
|
failures += 1
|
|
printerr("FAIL ", title)
|
|
|
|
func run() -> void:
|
|
create_timer(30).timeout.connect(func(): quit(1))
|
|
var good := ServerSettings.DEFAULTS.duplicate()
|
|
check(ServerSettings.validate(good).is_empty(), "Default dedicated configuration is valid")
|
|
for item in [["port", -1], ["port", 27841], ["max_players", 9], ["bots", "8"], ["mode", "CTF"],
|
|
["bind", "bad address"], ["difficulty", 8], ["round_delay", 0], ["discovery", "true"], ["typo", 1]]:
|
|
var bad := good.duplicate()
|
|
bad[item[0]] = item[1]
|
|
check(not ServerSettings.validate(bad).is_empty(), "Invalid server setting rejected: %s" % item[0])
|
|
var loaded := ServerSettings.read(PackedStringArray(["--dedicated", "--port=27989", "--bots=0", "--name=LAN Test", "--mode=FFA"]))
|
|
check(loaded.error.is_empty() and loaded.settings.port == 27989 and loaded.settings.bots == 0 and loaded.settings.server_name == "LAN Test", "CLI overrides config without changing the file")
|
|
check(not ServerSettings.read(PackedStringArray(["--port=oops"])).error.is_empty(), "Malformed CLI value is rejected")
|
|
check(not ServerSettings.read(PackedStringArray(["--config=res://missing-server.json"])).error.is_empty(), "Missing configuration fails clearly")
|
|
game = load("res://scenes/main.tscn").instantiate()
|
|
root.add_child(game)
|
|
await physics_frame
|
|
var server := DedicatedServer.new()
|
|
server.game = game
|
|
game.add_child(server)
|
|
server.start(PackedStringArray(["--dedicated", "--port=27989", "--bots=8", "--round-delay=3", "--discovery=false"]))
|
|
check(game.active and game.is_host and game.dedicated and game.local_id == 0, "Dedicated server owns authority without a local player")
|
|
check(not game.players.has(1) and game.players.size() == 8, "All eight slots can be bots; server consumes no slot")
|
|
game.set_physics_process(false)
|
|
server.set_physics_process(false)
|
|
for fighter: Fighter in game.players.values():
|
|
fighter.set_physics_process(false)
|
|
var player: Fighter = game.players[-1]
|
|
player.kills = 5
|
|
player.deaths = 2
|
|
player.hp = 0
|
|
player.killer_id = -2
|
|
game.scores = [9, 4]
|
|
game.time_left = 0
|
|
game.finish_match()
|
|
server._physics_process(0.1)
|
|
check(game.match_over and server.round_number == 1, "Round end preserves scoreboard during intermission")
|
|
server._physics_process(3.1)
|
|
check(not game.match_over and game.scores == [0, 0] and game.time_left == game.config.time_limit and server.round_number == 2, "Dedicated runtime automatically starts next round")
|
|
check(player.hp == 100 and player.kills == 0 and player.deaths == 0 and player.killer_id == 0, "New round resets fighters, scores and death-camera identity")
|
|
game.config.mode = "FFA"
|
|
game.finish_match()
|
|
check(game.match_over and not game.winner.is_empty(), "FFA can finish and restart as dedicated match")
|
|
game.remove_player(-1)
|
|
game.add_player(123, "Remote", false, 0).set_physics_process(false)
|
|
game._disconnected(123)
|
|
check(game.players.size() == 8 and not game.players.has(123), "Disconnected client slot is refilled by a bot")
|
|
game.leave()
|
|
await process_frame
|
|
print("DEDICATED ", checks, " checks, ", failures, " failures")
|
|
quit(0 if failures == 0 else 1)
|