From 93a2be399cb68f8055fd902365967a6f285df6a9 Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Sun, 9 Aug 2026 18:41:18 -0500 Subject: [PATCH] refactor: decouple game networking from lobby client * Replace direct client/server networking references with GameClient/GameServer scenes * Refactor message bus to support local emission and argument expansion * Move lobby connection lifecycle handling to message bus events * Remove multiplayer connection wait helpers and direct lobby client coupling * Rename Server to ServerNetworking and update lobby client references * Update scene resources and export configuration --- billiards.gd | 24 ++++++------- billiards.tscn | 10 +++--- export_presets.cfg | 2 +- game_client.gd | 35 +++++++++++++++++++ game_client.gd.uid | 1 + game_client.tscn | 6 ++++ game_server.gd | 11 ++++++ game_server.gd.uid | 1 + game_server.tscn | 6 ++++ globals/message_bus.gd | 32 +++++++++-------- project.godot | 4 --- scenes/data_bridge/lobby_data.gd | 18 +++++----- scenes/data_bridge/multiplayer_data.gd | 11 ------ scenes/screens/lobby_screen/lobby.gd | 13 ++++--- scenes/screens/lobby_screen/lobby.tscn | 2 +- scenes/screens/lobby_screen/lobby_base.gd | 5 +-- scenes/screens/lobby_screen/lobby_client.gd | 35 +++++++++++++++++++ .../screens/lobby_screen/lobby_client.gd.uid | 1 + scripts/client_networking.gd | 32 ++++++++++++----- scripts/server_networking.gd | 2 +- 20 files changed, 174 insertions(+), 77 deletions(-) create mode 100644 game_client.gd create mode 100644 game_client.gd.uid create mode 100644 game_client.tscn create mode 100644 game_server.gd create mode 100644 game_server.gd.uid create mode 100644 game_server.tscn create mode 100644 scenes/screens/lobby_screen/lobby_client.gd create mode 100644 scenes/screens/lobby_screen/lobby_client.gd.uid diff --git a/billiards.gd b/billiards.gd index aa60c1a..97cfb7b 100644 --- a/billiards.gd +++ b/billiards.gd @@ -1,8 +1,8 @@ class_name Billiards extends Node -@onready var server_net: Node = $server_net -@onready var client_net: ClientNetworking = $client_net +@onready var game_server: GameServer = $game_server +@onready var game_client: GameClient = $game_client # @@ -76,18 +76,17 @@ func _set_game_mode(mode: String) -> void: Globals.game_data.GameModeType.SNOOKER - - func server_(arg: String) -> void: var server_port = arg.split("_")[1] - server_net.start_server("0.0.0.0", int(server_port)) + game_server.start_server("0.0.0.0", int(server_port)) func host_(arg: String) -> void: var game_mode = arg.split("_")[1] var match_name = OS.get_cmdline_user_args()[-1] - Globals.multiplayer_data.wait_for_connection() + while not $scene/lobby_screen.client.lobby_fully_connected: + await get_tree().process_frame $scene/lobby_screen.find_child(game_mode, true, false).emit_signal("pressed") $scene/lobby_screen.find_child("new_match_name_input", true, false).text = match_name @@ -99,13 +98,14 @@ func join_server(_arg: String) -> void: Globals.multiplayer_data.set_multiplayer_active() + # TODO: Need to check if true still... # NOTE: Need to load lobby in order for signals to get bound - # which then game server calls on its load to do handoff + # which then game server calls on its load to do handoff Globals.game_state.set_game_scene( "res://scenes/screens/lobby_screen/lobby.tscn" ) - client_net.start_client(server_address, int(server_port)) + game_client.start_client(server_address, int(server_port)) func client(_arg: String) -> void: Globals.game_state.set_game_scene( @@ -118,17 +118,13 @@ func game(_arg: String) -> void: var game_mode = OS.get_cmdline_user_args()[-1] _set_game_mode(game_mode) - Globals.multiplayer_data.set_multiplayer_active() - Globals.game_state.set_game_scene( - "res://scenes/game.tscn" - ) + Globals.multiplayer_data.set_multiplayer_active() + Globals.game_state.set_game_scene( "res://scenes/game.tscn" ) func join(_arg: String) -> void: var _match_id = OS.get_cmdline_user_args()[-1] - Globals.multiplayer_data.wait_for_connection() - var button = $scene/lobby_screen.find_child("join_bttn", true, false) while not button: await get_tree().process_frame diff --git a/billiards.tscn b/billiards.tscn index c55016c..c5d037d 100644 --- a/billiards.tscn +++ b/billiards.tscn @@ -2,18 +2,16 @@ [ext_resource type="Script" uid="uid://dbca7qndk7coq" path="res://billiards.gd" id="1_bhs8v"] [ext_resource type="PackedScene" uid="uid://dy51wny4x53f4" path="res://scenes/data_bridge/bridge.tscn" id="1_xa5nf"] -[ext_resource type="Script" uid="uid://ci57tiuqsx1jp" path="res://scripts/client_networking.gd" id="3_hkpkv"] -[ext_resource type="Script" uid="uid://bgnr36m8qvbx3" path="res://scripts/server_networking.gd" id="4_cni66"] +[ext_resource type="PackedScene" uid="uid://cbvv2msu13vr2" path="res://game_client.tscn" id="3_hkpkv"] +[ext_resource type="PackedScene" uid="uid://bss61m8hfvab3" path="res://game_server.tscn" id="4_cni66"] [node name="billiards" type="Node"] script = ExtResource("1_bhs8v") [node name="bridge" parent="." instance=ExtResource("1_xa5nf")] -[node name="client_net" type="Node" parent="."] -script = ExtResource("3_hkpkv") +[node name="game_client" parent="." instance=ExtResource("3_hkpkv")] -[node name="server_net" type="Node" parent="."] -script = ExtResource("4_cni66") +[node name="game_server" parent="." instance=ExtResource("4_cni66")] [node name="scene" type="Node" parent="."] diff --git a/export_presets.cfg b/export_presets.cfg index 85cc4a1..887f4ca 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -54,7 +54,7 @@ dedicated_server=false custom_features="" export_filter="all_resources" include_filter="" -exclude_filter="s" +exclude_filter=".godot/*" export_path="../../builds/desktop/billiards/billiards.x86_64" patches=PackedStringArray() encryption_include_filters="" diff --git a/game_client.gd b/game_client.gd new file mode 100644 index 0000000..ba781ec --- /dev/null +++ b/game_client.gd @@ -0,0 +1,35 @@ +class_name GameClient extends ClientNetworking + + +func _ready() -> void: + setup_signals() + + +func setup_signals() -> void: + MessageBus.subscribe("game_start_client", _start_client) + + MessageBus.subscribe("game_wait_for_connection", _wait_for_connection) + MessageBus.subscribe("game_close_connection", _wait_close_connection) + +func _start_client(address: String = "127.0.0.1", port: int = 8080) -> void: + if peer: return + start_client(address, port) + + +func client_connected_to_server() -> void: + push_warning("Connected to server!") + +func close_connection() -> void: + if not peer: return + + push_warning("Disconnected from, server...") + + unset_client() + +func client_disconnected_from_server() -> void: + push_warning("Disconnected from, server...") + +func client_connection_failed_to_server() -> void: + push_warning("Connection failed!") + + unset_client() diff --git a/game_client.gd.uid b/game_client.gd.uid new file mode 100644 index 0000000..b8987a2 --- /dev/null +++ b/game_client.gd.uid @@ -0,0 +1 @@ +uid://cjtu1d1j35r32 diff --git a/game_client.tscn b/game_client.tscn new file mode 100644 index 0000000..788bc4d --- /dev/null +++ b/game_client.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://cbvv2msu13vr2"] + +[ext_resource type="Script" uid="uid://cjtu1d1j35r32" path="res://game_client.gd" id="1_tea1p"] + +[node name="client_net" type="Node"] +script = ExtResource("1_tea1p") diff --git a/game_server.gd b/game_server.gd new file mode 100644 index 0000000..3ba4aee --- /dev/null +++ b/game_server.gd @@ -0,0 +1,11 @@ +class_name GameServer extends ServerNetworking + + +func _ready() -> void: + setup_signals() + + +func setup_signals() -> void: + #MessageBus.subscribe("game_wait_for_connection", _wait_for_connection) + #MessageBus.subscribe("game_close_connection", _wait_close_connection) + pass diff --git a/game_server.gd.uid b/game_server.gd.uid new file mode 100644 index 0000000..8a59b5a --- /dev/null +++ b/game_server.gd.uid @@ -0,0 +1 @@ +uid://bndylf4rwtlkn diff --git a/game_server.tscn b/game_server.tscn new file mode 100644 index 0000000..b610315 --- /dev/null +++ b/game_server.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bss61m8hfvab3"] + +[ext_resource type="Script" uid="uid://bndylf4rwtlkn" path="res://game_server.gd" id="1_3xapr"] + +[node name="server_net" type="Node"] +script = ExtResource("1_3xapr") diff --git a/globals/message_bus.gd b/globals/message_bus.gd index f716f05..5518fae 100644 --- a/globals/message_bus.gd +++ b/globals/message_bus.gd @@ -11,8 +11,8 @@ func subscribe(id: String, callback: Callable) -> void: message_types.get(id).append(callback) -func emit(id: String, data: Variant) -> void: - emit_propagation(id, data) +func emit_local(id: String, data: Variant, expand: bool = false) -> void: + emit_propagation(id, data, expand) # TODO: Need to actually validate client request. Also, message bus is more @@ -21,22 +21,23 @@ func emit(id: String, data: Variant) -> void: @rpc("any_peer", "call_remote", "reliable") func emit_request(id: String, data: Variant, expand: bool = false) -> void: if not multiplayer.is_server(): return - - var listeners: Array = message_types.get(id) - if not listeners: - push_error("'%s' not an existing message type to send...", [id]) + if not message_types.has(id): + push_error("'%s' not an existing message type to handle...", [id]) return emit_propagation(id, data, expand) @rpc("authority", "call_local", "reliable") func emit_propagation(id: String, data: Variant, expand: bool = false) -> void: - var listeners: Array = message_types.get(id) - if not listeners: - push_error("'%s' not an existing message type to send...", [id]) + if not message_types.has(id): + push_error("'%s' not an existing message type to handle...", [id]) return - for callback: Callable in listeners: + for callback: Callable in message_types.get(id): + if data == null: + callback.call() + continue + if not expand: callback.call(data) else: @@ -44,12 +45,15 @@ func emit_propagation(id: String, data: Variant, expand: bool = false) -> void: @rpc("authority", "call_remote", "reliable") func emit_propagation_clients_only(id: String, data: Variant, expand: bool = false) -> void: - var listeners: Array = message_types.get(id) - if not listeners: - push_error("'%s' not an existing message type to send...", [id]) + if not message_types.has(id): + push_error("'%s' not an existing message type to handle...", [id]) return - for callback: Callable in listeners: + for callback: Callable in message_types.get(id): + if data == null: + callback.call() + continue + if not expand: callback.call(data) else: diff --git a/project.godot b/project.godot index 6fc39a3..ed669bf 100644 --- a/project.godot +++ b/project.godot @@ -72,7 +72,3 @@ jolt_physics_3d/simulation/velocity_steps=20 jolt_physics_3d/simulation/position_steps=20 3d/simulation/position_steps=10 3d/simulation/velocity_steps=10 - -[rendering] - -textures/vram_compression/import_etc2_astc=true diff --git a/scenes/data_bridge/lobby_data.gd b/scenes/data_bridge/lobby_data.gd index d63d7cf..0a2ea7e 100644 --- a/scenes/data_bridge/lobby_data.gd +++ b/scenes/data_bridge/lobby_data.gd @@ -1,9 +1,6 @@ class_name LobbyData extends Node -@onready var lobby_ui: Node - - func _init() -> void: Globals.lobby_data = self @@ -11,15 +8,16 @@ func _init() -> void: @rpc("authority", "reliable") func connect_to_game() -> void: # NOTE: Leave the lobby - lobby_ui.client.close_connection() - - Globals.multiplayer_data.wait_for_connection_close() + MessageBus.emit_local("lobby_close_connection", null) # NOTE: Join target game server - # TODO: Don't use libby client... Use a created game client. - lobby_ui.client.start_client( - Globals.game_data.game_address, - Globals.game_data.game_port + MessageBus.emit_local( + "game_start_client", + [ + Globals.game_data.game_address, + Globals.game_data.game_port + ], + true ) @rpc("authority", "reliable") diff --git a/scenes/data_bridge/multiplayer_data.gd b/scenes/data_bridge/multiplayer_data.gd index ff7c67b..15bd02e 100644 --- a/scenes/data_bridge/multiplayer_data.gd +++ b/scenes/data_bridge/multiplayer_data.gd @@ -44,17 +44,6 @@ func init_match(): true ) -func wait_for_connection() -> void: - while not Globals.lobby_data.lobby_ui.client.peer: - await get_tree().process_frame - - while Globals.lobby_data.lobby_ui.client.peer.get_connection_status() != 2: - await get_tree().process_frame - -func wait_for_connection_close() -> void: - while Globals.lobby_data.lobby_ui.client.peer: - await get_tree().process_frame - func set_multiplayer_inactive() -> void: is_multiplayer_active = false diff --git a/scenes/screens/lobby_screen/lobby.gd b/scenes/screens/lobby_screen/lobby.gd index 926c88f..c729ab5 100644 --- a/scenes/screens/lobby_screen/lobby.gd +++ b/scenes/screens/lobby_screen/lobby.gd @@ -2,17 +2,18 @@ class_name Lobby extends LobbyBase func _ready() -> void: - Globals.lobby_data.lobby_ui = self - setup_signals() func _exit_tree() -> void: + # TODO: Maybe no longer needed... if Globals.multiplayer_data.is_multiplayer_active: return + client._do_wait_close_connection() - if client.peer: - client.close_connection() func setup_signals() -> void: + MessageBus.subscribe("lobby_wait_for_connection", client._do_wait_for_connection) + MessageBus.subscribe("lobby_close_connection", client._do_wait_close_connection) + MessageBus.subscribe("receive_match_list", _on_receive_match_list) MessageBus.subscribe("match_list_activate_entry", _on_match_list_entry_activated) MessageBus.subscribe("match_list_add_entry", _on_match_list_entry_added) @@ -23,7 +24,7 @@ func setup_signals() -> void: func _server_host_started() -> void: host_connect_bttn.visible = false -# NOTE: 'matches_list' can be empty but so long as we get the call from the +# NOTE: 'matches_list' can be empty; so long as we get the call from the # server we know we are connected and thus hide respective UI elements. func _on_receive_match_list(matches_list: Array) -> void: push_warning("Client Joined Host: Full Match List Recieved...\n", matches_list) @@ -36,6 +37,8 @@ func _on_receive_match_list(matches_list: Array) -> void: for match_entry in matches_list: _create_match_entry(match_entry) + client.lobby_fully_connected = true + func _on_match_list_entry_activated(match_id: String) -> void: for match_entry in match_list.get_children(): match_entry.join_bttn.visible = false diff --git a/scenes/screens/lobby_screen/lobby.tscn b/scenes/screens/lobby_screen/lobby.tscn index 1805fc2..c58311b 100644 --- a/scenes/screens/lobby_screen/lobby.tscn +++ b/scenes/screens/lobby_screen/lobby.tscn @@ -3,7 +3,7 @@ [ext_resource type="Script" uid="uid://dk7afnf7ol7dy" path="res://scenes/screens/lobby_screen/lobby.gd" id="1_hhiik"] [ext_resource type="PackedScene" uid="uid://dg7pgj6i5pk8p" path="res://scenes/ui_controls/lobby_screen/lobby_ui.tscn" id="2_lqt48"] [ext_resource type="Script" uid="uid://sihv0kwbcr33" path="res://scenes/screens/lobby_screen/lobby_rpc.gd" id="3_rurl6"] -[ext_resource type="Script" uid="uid://ci57tiuqsx1jp" path="res://scripts/client_networking.gd" id="4_glu7g"] +[ext_resource type="Script" uid="uid://dv7j35h2ngiq7" path="res://scenes/screens/lobby_screen/lobby_client.gd" id="4_glu7g"] [node name="lobby" type="Node"] script = ExtResource("1_hhiik") diff --git a/scenes/screens/lobby_screen/lobby_base.gd b/scenes/screens/lobby_screen/lobby_base.gd index 47b7184..5c8381c 100644 --- a/scenes/screens/lobby_screen/lobby_base.gd +++ b/scenes/screens/lobby_screen/lobby_base.gd @@ -16,7 +16,7 @@ const MATCH_ENTRY = preload("res://scenes/screens/lobb @onready var new_match_name_input: LineEdit = $ui/body/right_body/create_match_hbox/new_match_name_input @onready var rpc_signals: Node = $rpc_signals -@onready var client: Node = $client +@onready var client: LobbyClient = $client var active_mode: String = "snooker" var active_match: HBoxContainer = null @@ -52,7 +52,8 @@ func _on_match_create_bttn_pressed() -> void: "type": active_mode } - MessageBus.emit_request.rpc_id(1, "match_list_add_entry", match_entry) + #MessageBus.emit_request.rpc_id(1, "match_list_add_entry", match_entry) + MessageBus.emit_request.rpc("match_list_add_entry", match_entry) func _on_mode_bttn_pressed(button: Button) -> void: active_mode = button.text.remove_chars("-").to_lower() diff --git a/scenes/screens/lobby_screen/lobby_client.gd b/scenes/screens/lobby_screen/lobby_client.gd new file mode 100644 index 0000000..9c2c783 --- /dev/null +++ b/scenes/screens/lobby_screen/lobby_client.gd @@ -0,0 +1,35 @@ +class_name LobbyClient extends ClientNetworking + + +var lobby_fully_connected: bool = false + + +func _ready() -> void: + pass + +func _process(_delta: float) -> void: + pass + +func _do_wait_for_connection() -> void: + _wait_for_connection() + + while not lobby_fully_connected: + await get_tree().process_frame + +func _do_wait_close_connection(): + _wait_close_connection() + + lobby_fully_connected = false + + +func client_connected_to_server() -> void: + push_warning("Connected to server!") + + +func client_disconnected_from_server() -> void: + push_warning("Disconnected from, server...") + +func client_connection_failed_to_server() -> void: + push_warning("Connection failed!") + + unset_client() diff --git a/scenes/screens/lobby_screen/lobby_client.gd.uid b/scenes/screens/lobby_screen/lobby_client.gd.uid new file mode 100644 index 0000000..8f15cec --- /dev/null +++ b/scenes/screens/lobby_screen/lobby_client.gd.uid @@ -0,0 +1 @@ +uid://dv7j35h2ngiq7 diff --git a/scripts/client_networking.gd b/scripts/client_networking.gd index 822ac2c..9717dfe 100644 --- a/scripts/client_networking.gd +++ b/scripts/client_networking.gd @@ -17,8 +17,31 @@ func start_client(address: String = "127.0.0.1", port: int = 8080) -> void: multiplayer.server_disconnected.connect(client_disconnected_from_server) multiplayer.connection_failed.connect(client_connection_failed_to_server) + +func _wait_for_connection() -> void: + while not peer: + await get_tree().process_frame + + while peer.get_connection_status() != 2: + await get_tree().process_frame + +func _wait_close_connection(): + close_connection() + + while peer: + await get_tree().process_frame + + func client_connected_to_server() -> void: - push_warning("Connected to server!") + assert(false, "This method needs to be overridden...") + +func client_disconnected_from_server() -> void: + assert(false, "This method needs to be overridden...") + + +func client_connection_failed_to_server() -> void: + assert(false, "This method needs to be overridden...") + func close_connection() -> void: if not peer: return @@ -27,13 +50,6 @@ func close_connection() -> void: unset_client() -func client_disconnected_from_server() -> void: - push_warning("Disconnected from, server...") - -func client_connection_failed_to_server() -> void: - push_warning("Connection failed!") - - unset_client() func unset_client() -> void: if not peer: return diff --git a/scripts/server_networking.gd b/scripts/server_networking.gd index c4f8b7e..a7beb31 100644 --- a/scripts/server_networking.gd +++ b/scripts/server_networking.gd @@ -1,4 +1,4 @@ -class_name Server extends Node +class_name ServerNetworking extends Node var peer: ENetMultiplayerPeer