diff --git a/globals/message_bus.gd b/globals/message_bus.gd new file mode 100644 index 0000000..3ea9186 --- /dev/null +++ b/globals/message_bus.gd @@ -0,0 +1,57 @@ +extends Node + + +var message_types: Dictionary[String, Array] = {} + + +func subscribe(id: String, callback: Callable) -> void: + if not message_types.has(id): + message_types.set(id, Array()) + + message_types.get(id).append(callback) + + +func emit(id: String, data: Variant) -> void: + emit_propagation(id, data) + + +# TODO: Need to actually validate client request. Also, message bus is more +# about server talking to clients than clients to server. I.E, reducing +# the number of needed @rpc method decorator bindings. +@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]) + 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]) + return + + for callback: Callable in listeners: + if not expand: + callback.call(data) + else: + callback.callv(data) + + +@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]) + return + + for callback: Callable in listeners: + if not expand: + callback.call(data) + else: + callback.callv(data) diff --git a/globals/message_bus.gd.uid b/globals/message_bus.gd.uid new file mode 100644 index 0000000..c5ca5ff --- /dev/null +++ b/globals/message_bus.gd.uid @@ -0,0 +1 @@ +uid://oatwf3crdtpt diff --git a/project.godot b/project.godot index 09069b9..6416332 100644 --- a/project.godot +++ b/project.godot @@ -19,6 +19,7 @@ config/icon="res://icon.svg" Globals="*res://globals/globals.gd" InstanceLauncher="*res://globals/instance_launcher.gd" +MessageBus="*res://globals/message_bus.gd" [display] diff --git a/scenes/data_bridge/lobby_data.gd b/scenes/data_bridge/lobby_data.gd index df5dbb2..0b17b12 100644 --- a/scenes/data_bridge/lobby_data.gd +++ b/scenes/data_bridge/lobby_data.gd @@ -30,25 +30,17 @@ func _init() -> void: func _delete_from_match_pool(match_id: String) -> Dictionary: - if not match_pool.get(match_id): - return {} + if not match_pool.has(match_id): return {} var to_delete: Dictionary = match_pool[match_id].data match_pool.erase(match_id) return to_delete -func _signal_match_list_remove_entry(match_id: String) -> void: - lobby_ui.rpc_signals.rpc_id(1, "match_list_remove_entry", match_id) - - for client in client_pool.values(): - if client.in_match: continue - - lobby_ui.rpc_signals.rpc_id(client.id, "match_list_remove_entry", match_id) - func _launch_game_server( match_entry: Dictionary, - client1: Dictionary, client2: Dictionary + client1: Dictionary, + client2: Dictionary ) -> void: var port: String = InstanceLauncher.launch_game_server(match_entry.data.type) if port == "-1": @@ -60,10 +52,10 @@ func _launch_game_server( Globals.game_data.rpc_id(client2.id, "set_game_address", "127.0.0.1") Globals.game_data.rpc_id(client1.id, "set_game_port", port) Globals.game_data.rpc_id(client2.id, "set_game_port", port) + rpc_id(client1.id, "connect_to_game") rpc_id(client2.id, "connect_to_game") -@rpc("any_peer", "reliable") func match_list_add_entry(match_entry: Dictionary) -> void: var client1 = client_pool.get( multiplayer.get_remote_sender_id() ) if not client1: return @@ -79,25 +71,15 @@ func match_list_add_entry(match_entry: Dictionary) -> void: match_pool[match_entry.match_id].data = match_entry client1.match_id = match_entry.match_id - lobby_ui.rpc_signals.rpc_id(1, "match_list_add_entry", match_entry) - for client in client_pool.values(): - if client.in_match: continue - lobby_ui.rpc_signals.rpc_id(client.id, "match_list_add_entry", match_entry) - - lobby_ui.rpc_signals.rpc_id(client1.id, "match_list_activate_entry", match_entry.match_id) - - -@rpc("any_peer", "reliable") func match_list_remove_entry(match_id: String) -> void: var client1 = client_pool.get( multiplayer.get_remote_sender_id() ) if not client1: return if not client1.match_id == match_id: return client1.match_id = "" - _delete_from_match_pool(match_id) - _signal_match_list_remove_entry(match_id) -@rpc("any_peer", "reliable") + _delete_from_match_pool(match_id) + func match_list_join_entry(match_id: String) -> void: var match_entry = match_pool.get(match_id) if not match_entry: return @@ -119,11 +101,9 @@ func match_list_join_entry(match_id: String) -> void: active_match_pool[match_id] = match_entry - match_pool.erase(match_id) client_pool.erase(client1.id) client_pool.erase(client2.id) - _signal_match_list_remove_entry(match_id) _launch_game_server(match_entry, client1, client2) # NOTE: Needed for hash check to pass between client and server but isn't used by server... @@ -131,10 +111,6 @@ func match_list_join_entry(match_id: String) -> void: func connect_to_game() -> void: pass -@rpc("authority", "call_local", "reliable") -func load_game_scene(_match_entry: Dictionary, _is_player_1: bool) -> void: - pass - @rpc("authority", "reliable") func go_back_to_match_screen() -> void: pass @@ -150,7 +126,9 @@ func server_client_connected(id: int) -> void: for match_entry in match_pool.values(): matches.append(match_entry.data) - lobby_ui.rpc_signals.rpc_id(id, "receive_match_list", matches) + MessageBus.emit_propagation_clients_only.rpc_id( + id, "receive_match_list", matches + ) func server_client_disconnected(id: int) -> void: push_warning("Client Disconnected... ID: ", id) @@ -162,13 +140,17 @@ func server_client_disconnected(id: int) -> void: var match_entry = _delete_from_match_pool(client1.match_id) if not client1.match_id.is_empty() and not match_entry.is_empty(): - lobby_ui.rpc_signals.rpc_id(1, "match_list_remove_entry", match_entry.match_id) + MessageBus.emit_propagation( + "match_list_remove_entry", match_entry.match_id + ) for client in client_pool.values(): if client.in_match: continue if client.id == id: continue - lobby_ui.rpc_signals.rpc_id(client.id, "match_list_remove_entry", match_entry.match_id) + MessageBus.emit_propagation_clients_only.rpc_id( + client.id, "match_list_remove_entry", match_entry.match_id + ) match_pool.erase(client1.match_id) diff --git a/scenes/screens/lobby_screen/lobby.gd b/scenes/screens/lobby_screen/lobby.gd index a2c363c..1362b44 100644 --- a/scenes/screens/lobby_screen/lobby.gd +++ b/scenes/screens/lobby_screen/lobby.gd @@ -13,26 +13,56 @@ func _exit_tree() -> void: server.close_connection() func setup_signals() -> void: - rpc_signals.server_host_started.connect(_server_host_started) - rpc_signals.match_list_entry_added.connect(_on_match_list_entry_added) - rpc_signals.match_list_entry_removed.connect(_on_match_list_entry_removed) + MessageBus.subscribe("match_list_add_entry", _on_match_list_entry_added) + MessageBus.subscribe("match_list_remove_entry", _on_match_list_entry_removed) + MessageBus.subscribe("match_list_join_entry", _on_match_list_join_entry) + func _server_host_started() -> void: host_start_bttn.visible = false host_stop_bttn.visible = true func _on_match_list_entry_added(match_entry: Dictionary) -> void: - push_warning("Client: Added Match List Entry... ", match_entry) + Globals.lobby_data.match_list_add_entry(match_entry) + if not match_entry.has("match_id"): return + + push_warning("Client Added Match List Entry... ", match_entry) _create_match_entry(match_entry) + MessageBus.emit_propagation_clients_only.rpc( + "match_list_add_entry", match_entry + ) + + MessageBus.emit_propagation_clients_only.rpc_id( + multiplayer.get_remote_sender_id(), + "match_list_activate_entry", + match_entry.match_id + ) + func _on_match_list_entry_removed(match_id: String) -> void: - push_warning("Client: Removed Match List Entry... ", match_id) + Globals.lobby_data.match_list_remove_entry(match_id) + if Globals.lobby_data.match_pool.has(match_id): return + + push_warning("Removed Match List Entry... ", match_id) + + MessageBus.emit_propagation_clients_only.rpc( + "match_list_remove_entry", + match_id + ) for match_entry in match_list.get_children(): if not match_id == match_entry.match_id: continue match_entry.queue_free() +func _on_match_list_join_entry(match_id: String) -> void: + Globals.lobby_data.match_list_join_entry(match_id) + push_warning("Client Joining Match List Entry... ", match_id) + + if Globals.lobby_data.match_pool.has(match_id): return + + _on_match_list_entry_removed(match_id) + func _create_match_entry(match_entry: Dictionary) -> void: var container = MATCH_ENTRY.instantiate() match_list.add_child(container) diff --git a/scenes/screens/lobby_screen/lobby_rpc.gd b/scenes/screens/lobby_screen/lobby_rpc.gd index 0424a31..61510e1 100644 --- a/scenes/screens/lobby_screen/lobby_rpc.gd +++ b/scenes/screens/lobby_screen/lobby_rpc.gd @@ -1,29 +1 @@ extends Node - - -@warning_ignore_start("unused_signal") -signal server_host_started() -signal match_list_entry_added(match_entry: Dictionary) -signal match_list_entry_removed(match_id: String) -@warning_ignore_restore("unused_signal") - - -@rpc("authority", "call_local", "reliable") -func match_list_add_entry(match_entry: Dictionary) -> void: - push_warning("Received new match entry...") - - emit_signal("match_list_entry_added", match_entry) - -@rpc("authority", "call_local", "reliable") -func match_list_remove_entry(match_id: String) -> void: - push_warning("Received delete match entry...") - - emit_signal("match_list_entry_removed", match_id) - -@rpc("authority", "reliable") -func receive_match_list(_match_list: Array) -> void: - pass - -@rpc("authority", "reliable") -func match_list_activate_entry(_match_id: String) -> void: - pass