mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
129 lines
4.3 KiB
GDScript
129 lines
4.3 KiB
GDScript
extends Control
|
|
|
|
# Lobby (task 1.5): roster list split by team, team swap, ready toggle,
|
|
# leave. Reads/writes MatchNet.roster — this scene owns no state of its
|
|
# own, it's a view over the autoload. Reached via main_menu.gd's Host/Join
|
|
# flow (task 1.7) calling change_scene_to_file("res://scenes/lobby.tscn")
|
|
# after NetworkManager.host()/join() succeeds — this scene must always be
|
|
# loaded that way (as the real current_scene), not instantiated as a child
|
|
# of something else: change_scene_to_file() operates on
|
|
# get_tree().current_scene, and _on_disconnected_from_server()/_leave()
|
|
# below call it themselves, which hangs if this scene isn't actually the
|
|
# tree's current_scene when that happens (see multiplayer-next.md §9
|
|
# gotcha 27 — found the hard way while building tests/lobby_smoke.gd).
|
|
|
|
@onready var _status_label: Label = %StatusLabel
|
|
@onready var _team0_list: VBoxContainer = %Team0List
|
|
@onready var _team1_list: VBoxContainer = %Team1List
|
|
@onready var _controls_row: HBoxContainer = %ControlsRow
|
|
@onready var _switch_team_button: Button = %SwitchTeamButton
|
|
@onready var _ready_button: CheckButton = %ReadyButton
|
|
@onready var _leave_button: Button = %LeaveButton
|
|
var _planned_server_shutdown := false
|
|
|
|
|
|
func _ready() -> void:
|
|
MatchNet.welcomed.connect(_on_welcomed)
|
|
MatchNet.player_joined.connect(_on_roster_changed)
|
|
MatchNet.player_left.connect(_on_roster_changed)
|
|
MatchNet.player_state_changed.connect(_on_roster_changed)
|
|
MatchNet.rejected.connect(_on_rejected)
|
|
MatchNet.server_shutdown.connect(_on_server_shutdown)
|
|
NetworkManager.disconnected_from_server.connect(_on_disconnected_from_server)
|
|
|
|
# The server process is never a roster member (§1.1 decision 2) — it
|
|
# gets a read-only view, no team/ready controls to operate on itself.
|
|
_controls_row.visible = NetworkManager.is_client
|
|
|
|
_refresh()
|
|
if not MatchNet.last_server_shutdown_reason.is_empty():
|
|
_planned_server_shutdown = true
|
|
_status_label.text = "Server closed: %s" % MatchNet.last_server_shutdown_reason
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
NetworkManager.poll()
|
|
|
|
|
|
func _physics_process(_delta: float) -> void:
|
|
NetworkManager.poll()
|
|
|
|
|
|
func _unhandled_input(event: InputEvent) -> void:
|
|
if event.is_action_pressed("ui_cancel"):
|
|
_leave()
|
|
|
|
|
|
func _on_roster_changed(_a = null, _b = null, _c = null) -> void:
|
|
_refresh()
|
|
|
|
|
|
func _on_welcomed() -> void:
|
|
_refresh()
|
|
|
|
|
|
func _on_rejected(reason: String) -> void:
|
|
_status_label.text = "Connection rejected: %s" % reason
|
|
|
|
|
|
func _on_server_shutdown(reason: String) -> void:
|
|
_planned_server_shutdown = true
|
|
_status_label.text = "Server closed: %s" % reason
|
|
|
|
|
|
func _on_disconnected_from_server() -> void:
|
|
if _planned_server_shutdown:
|
|
return
|
|
get_tree().change_scene_to_file(ScenePaths.MAIN_MENU)
|
|
|
|
|
|
func _on_switch_team_pressed() -> void:
|
|
var my_id := multiplayer.get_unique_id()
|
|
var info: MatchNet.PlayerInfo = MatchNet.roster.get(my_id)
|
|
if info == null:
|
|
return
|
|
MatchNet.request_set_team((info.team + 1) % MatchNet.TEAM_COUNT)
|
|
|
|
|
|
func _on_ready_toggled(pressed: bool) -> void:
|
|
MatchNet.request_set_ready(pressed)
|
|
|
|
|
|
func _on_leave_pressed() -> void:
|
|
_leave()
|
|
|
|
|
|
func _leave() -> void:
|
|
NetworkManager.shutdown()
|
|
get_tree().change_scene_to_file(ScenePaths.MAIN_MENU)
|
|
|
|
|
|
func _refresh() -> void:
|
|
if NetworkManager.is_server:
|
|
_status_label.text = "Hosting — %d player(s) connected" % MatchNet.roster.size()
|
|
elif NetworkManager.is_client:
|
|
_status_label.text = "Connected" if not MatchNet.roster.is_empty() else "Connecting..."
|
|
else:
|
|
_status_label.text = "Not connected"
|
|
|
|
for child in _team0_list.get_children():
|
|
child.queue_free()
|
|
for child in _team1_list.get_children():
|
|
child.queue_free()
|
|
|
|
var my_id := multiplayer.get_unique_id()
|
|
var infos: Array = MatchNet.roster.values()
|
|
infos.sort_custom(func(a: MatchNet.PlayerInfo, b: MatchNet.PlayerInfo) -> bool: return a.peer_id < b.peer_id)
|
|
for info: MatchNet.PlayerInfo in infos:
|
|
var row := Label.new()
|
|
var marker := " (you)" if info.peer_id == my_id else ""
|
|
var ready_mark := "✓" if info.ready else "…"
|
|
row.text = "%s %s%s" % [ready_mark, info.player_name, marker]
|
|
var target_list := _team0_list if info.team == 0 else _team1_list
|
|
target_list.add_child(row)
|
|
|
|
if NetworkManager.is_client:
|
|
var my_info: MatchNet.PlayerInfo = MatchNet.roster.get(my_id)
|
|
if my_info != null:
|
|
_ready_button.set_pressed_no_signal(my_info.ready)
|