mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-11 00:14:00 +00:00
feat(server): complete phase 6 local verification
This commit is contained in:
@@ -306,12 +306,20 @@ var _spectator_target_index := 0
|
||||
# §6.3, server only. Peers that joined mid-match with no slot to reclaim, in
|
||||
# arrival order, waiting for the next kickoff to hand them a vacated slot.
|
||||
var _late_joiners: Array[Dictionary] = []
|
||||
# Task 6.5, server only. Set by ServerMatchLoop immediately before it switches
|
||||
# to this scene; static because the loop cannot hold a reference to a node that
|
||||
# does not exist yet, and consumed on read so it cannot leak into a later match.
|
||||
static var server_arena_override := ""
|
||||
# §6.3's "cap with --max-spectators". Server only; 0 disables spectating
|
||||
# entirely, negative means unlimited.
|
||||
var _max_spectators := -1
|
||||
var _last_emitted_countdown := -1
|
||||
var _in_overtime := false
|
||||
var _match_over := false
|
||||
# Dedicated-export smoke hook (task 6.2). It is parsed only by the authoritative
|
||||
# server, cannot be triggered by an RPC, and defaults to disabled.
|
||||
var _smoke_force_goal_tick := -1
|
||||
var _smoke_goal_forced := false
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
@@ -334,6 +342,9 @@ func _ready() -> void:
|
||||
# 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 smoke_after := float(config.get_value("smoke-force-goal-after"))
|
||||
if smoke_after >= 0.0:
|
||||
_smoke_force_goal_tick = -2 # arm when PLAYING begins; -1 remains disabled
|
||||
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
|
||||
@@ -418,7 +429,11 @@ func _exit_tree() -> void:
|
||||
# ============================================================
|
||||
|
||||
func _start_server() -> void:
|
||||
var arena_path := ArenaRegistry.random_path()
|
||||
# Task 6.5: the server match loop hands the arena down so rotation is a
|
||||
# rotation rather than a coincidence. Consumed once, so a match started any
|
||||
# other way (a test harness, a future lobby button) still picks at random.
|
||||
var arena_path := server_arena_override if not server_arena_override.is_empty() else ArenaRegistry.random_path()
|
||||
server_arena_override = ""
|
||||
_arena_path = arena_path
|
||||
arena = (load(arena_path) as PackedScene).instantiate()
|
||||
add_child(arena)
|
||||
@@ -1084,6 +1099,21 @@ func _on_goal_registered(conceding_team: int) -> void:
|
||||
_broadcast_clock_state()
|
||||
|
||||
|
||||
func _maybe_force_smoke_goal() -> void:
|
||||
if _smoke_goal_forced or _smoke_force_goal_tick == -1 or match_state != MatchState.State.PLAYING:
|
||||
return
|
||||
if _smoke_force_goal_tick == -2:
|
||||
var config := ServerConfig.parse(OS.get_cmdline_user_args(), false)
|
||||
_smoke_force_goal_tick = Engine.get_physics_frames() + int(maxf(0.0, float(config.get_value("smoke-force-goal-after"))) * SimConstants.TICK_HZ)
|
||||
ServerLog.info("smoke_goal_armed", {"tick": _smoke_force_goal_tick})
|
||||
return
|
||||
if Engine.get_physics_frames() < _smoke_force_goal_tick:
|
||||
return
|
||||
_smoke_goal_forced = true
|
||||
ServerLog.info("smoke_goal_forced", {"tick": Engine.get_physics_frames()})
|
||||
_on_goal_registered(0)
|
||||
|
||||
|
||||
# Task 5.9. Server-only by construction: _respawn_escaped_bodies() is gated on
|
||||
# _owns_world_simulation(). The bump uses Phase 2's deferred path because the
|
||||
# respawn only QUEUES a teleport — bumping now would broadcast the new
|
||||
@@ -2161,6 +2191,7 @@ func _physics_process(_delta: float) -> void:
|
||||
# Also before the broadcast, so a transition taken this tick ships in
|
||||
# this tick's own match_state byte rather than trailing it by one.
|
||||
_update_match_state()
|
||||
_maybe_force_smoke_goal()
|
||||
_expire_slot_reservations()
|
||||
# Countdown and clock are derived from absolute ticks on both peers, so
|
||||
# these run on the client too.
|
||||
|
||||
Reference in New Issue
Block a user