mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-11 08:23:45 +00:00
feat(server): task 6.1/6.3 — dedicated server export preset and a real CLI surface
6.1: "Linux Dedicated Server" preset (dedicated_server=true, custom_features="dedicated_server") mirroring the existing training preset, plus run/main_scene.dedicated_server so the server binary reaches its own entry point with no flag. Builds: an 85MB Linux x86_64 binary, gitignored like the training one. 6.3: scripts/server_config.gd declares every server flag once - name, type, default, section, help - and one parser turns that into parsing, type checking, range validation, config-file backing and --help. The flags had grown to ~30 across server_boot.gd and networked_match.gd, each parsed inline with begins_with, none documented, and an unrecognised flag was SILENTLY IGNORED: --max-clientss=8 ran a server on the default cap and said nothing. Unknown flags, missing values, wrong types, duplicates and out-of-range values are now hard errors, reported all at once. Precedence is command line > config file > default. server_boot.gd parses strictly because it owns the whole command line; networked_match.gd reads the same declaration leniently because it is one consumer of an argv the smoke harnesses also fill with --role= and --drive-seconds=. Nothing is lost - every server flag is declared, so the strict pass already caught any typo before the match scene re-reads its own. 13 unit tests covering the precedence order, the typo rejection that motivated this, --no-<bool> not double-listing in --help, and --help documenting every flag asserted against the declaration rather than a hand-kept list. Verified end to end: --help prints, a typo'd flag refuses to start, and the plain/replay-log/late-joiner smoke scenarios still pass.
This commit is contained in:
@@ -320,31 +320,31 @@ func _ready() -> void:
|
||||
if kickoff_rng_seed == 0:
|
||||
_kickoff_rng.randomize()
|
||||
if multiplayer.is_server():
|
||||
for arg: String in OS.get_cmdline_user_args():
|
||||
if arg == "--fill-bots":
|
||||
_fill_bots = true
|
||||
elif arg == "--no-fill-bots":
|
||||
_fill_bots = false
|
||||
elif arg.begins_with("--max-spectators="):
|
||||
_max_spectators = maxi(0, arg.get_slice("=", 1).to_int())
|
||||
elif arg.begins_with("--replay-log="):
|
||||
# Task 5.10. Diagnostic only: a log that cannot be opened must
|
||||
# never stop the server serving the match.
|
||||
var replay_path := arg.get_slice("=", 1)
|
||||
_replay_log = ReplayLog.new()
|
||||
var replay_err := _replay_log.open_for_write(replay_path)
|
||||
if replay_err != OK:
|
||||
push_warning("NetworkedMatch: could not open replay log %s (%s)" % [replay_path, error_string(replay_err)])
|
||||
_replay_log = null
|
||||
else:
|
||||
print("NetworkedMatch: recording replay log to %s" % replay_path)
|
||||
elif arg.begins_with("--slot-reservation-seconds="):
|
||||
_slot_reservation_seconds = maxf(0.0, arg.get_slice("=", 1).to_float())
|
||||
elif arg.begins_with("--match-length="):
|
||||
# Regulation is 150s; a smoke test cannot wait that long to see
|
||||
# FULL_TIME/OVERTIME/RESULTS, so allow an override. Server-side
|
||||
# only — a client cannot shorten anyone's match.
|
||||
match_length_seconds = maxf(1.0, arg.get_slice("=", 1).to_float())
|
||||
# Task 6.3: the same declaration server_boot.gd validated, re-read here
|
||||
# LENIENTLY — this scene is one consumer of an argv the smoke harnesses
|
||||
# also fill with --role=, --drive-seconds= and client-side flags. The
|
||||
# strict pass at the process entry point already rejected any typo in a
|
||||
# server flag, so nothing is lost by ignoring what is not ours.
|
||||
var config := ServerConfig.parse(OS.get_cmdline_user_args(), false)
|
||||
_fill_bots = bool(config.get_value("fill-bots"))
|
||||
var spectator_cap := int(config.get_value("max-spectators"))
|
||||
_max_spectators = spectator_cap if spectator_cap < 0 else maxi(0, spectator_cap)
|
||||
_slot_reservation_seconds = maxf(0.0, float(config.get_value("slot-reservation-seconds")))
|
||||
# Regulation is 150s; a smoke test cannot wait that long to see
|
||||
# FULL_TIME/OVERTIME/RESULTS, so allow an override. Server-side only —
|
||||
# a client cannot shorten anyone's match.
|
||||
match_length_seconds = maxf(1.0, float(config.get_value("match-length")))
|
||||
var replay_path := String(config.get_value("replay-log"))
|
||||
if not replay_path.is_empty():
|
||||
# Task 5.10. Diagnostic only: a log that cannot be opened must
|
||||
# never stop the server serving the match.
|
||||
_replay_log = ReplayLog.new()
|
||||
var replay_err := _replay_log.open_for_write(replay_path)
|
||||
if replay_err != OK:
|
||||
push_warning("NetworkedMatch: could not open replay log %s (%s)" % [replay_path, error_string(replay_err)])
|
||||
_replay_log = null
|
||||
else:
|
||||
print("NetworkedMatch: recording replay log to %s" % replay_path)
|
||||
_start_server()
|
||||
else:
|
||||
for arg: String in OS.get_cmdline_user_args():
|
||||
|
||||
Reference in New Issue
Block a user