## MapBrowserRPC — Client-Server RPC Bridge for Workshop Map Browser ## ## Autoload candidate (or child of NetworkManager) that provides ENet RPC ## methods for the workshop map browser system. ## ## ## Architecture ## ## ┌──────────────┐ request_map_list() ┌──────────────┐ ## │ Client │ ──────────────────────► │ Server │ ## │ │ ◄────────────────────── │ │ ## │ │ send_map_list() │ │ ## │ │ │ │ ## │ │ request_map_change() │ │ ## │ │ ──────────────────────► │ │ ## └──────────────┘ └──────────────┘ ## ## ## Signals ## ## map_list_received(map_list: Array) — emitted on client when map list arrives ## map_change_requested(map_id: String, peer_id: int) — emitted on server ## when a client requests a map change ## map_vote_started(map_id: String) — emitted on server when vote begins ## ## ## Integration ## ## Add as an autoload in project.godot: ## MapBrowserRPC="*res://scripts/network/map_browser_rpc.gd" ## ## Or add as a child of NetworkManager at runtime. ## ## ## RPC Visibility ## ## - Server → Client: send_map_list (authority, call_remote) ## - Client → Server: request_map_list (any_peer, call_remote) ## - Client → Server: request_map_change (any_peer, call_remote) ## ## ============================================================================= extends Node # --------------------------------------------------------------------------- # Signals # --------------------------------------------------------------------------- ## Emitted on the client when the server sends the map list. signal map_list_received(map_list: Array) ## Emitted on the server when a client requests a map change. signal map_change_requested(map_id: String, peer_id: int) ## Emitted on the server when a map vote is initiated by a client request. signal map_vote_started(map_id: String) ## Emitted on the client when the vote result is sent back. signal map_vote_result(map_id: String, passed: bool, yes_count: int, no_count: int) # --------------------------------------------------------------------------- # RPC: Server → Client # --------------------------------------------------------------------------- ## Server sends the serialized map list to a specific client. ## Called by server code after receiving request_map_list(). @rpc("authority", "call_remote", "reliable") func send_map_list(map_list: Array) -> void: if multiplayer.is_server(): return map_list_received.emit(map_list) print("[MapBrowserRPC] Received map list with %d maps" % map_list.size()) ## Server broadcasts the final vote result to all clients. @rpc("authority", "call_remote", "reliable") func broadcast_vote_result(map_id: String, passed: bool, yes_count: int, no_count: int) -> void: if multiplayer.is_server(): return map_vote_result.emit(map_id, passed, yes_count, no_count) print("[MapBrowserRPC] Vote result for %s: passed=%s (%d yes, %d no)" % [map_id, passed, yes_count, no_count]) # --------------------------------------------------------------------------- # RPC: Client → Server # --------------------------------------------------------------------------- ## Client requests the current map list from the server. ## The server should call send_map_list(peer_id, map_list) in response. @rpc("any_peer", "call_remote", "reliable") func request_map_list() -> void: if not multiplayer.is_server(): return var peer_id: int = multiplayer.get_remote_sender_id() print("[MapBrowserRPC] Map list requested by peer %d" % peer_id) # Delegate to WorkshopBrowser if available var list: Array = [] if WorkshopBrowser and WorkshopBrowser.has_method(&"get_map_list"): list = WorkshopBrowser.get_map_list() else: push_warning("[MapBrowserRPC] WorkshopBrowser singleton not available — returning empty list") # Send the map list back to the requesting client send_map_list.rpc_id(peer_id, list) ## Client requests a map change (initiates a vote or signals admin). ## Emits map_change_requested on the server for handling. @rpc("any_peer", "call_remote", "reliable") func request_map_change(map_id: String) -> void: if not multiplayer.is_server(): return var peer_id: int = multiplayer.get_remote_sender_id() print("[MapBrowserRPC] Map change requested by peer %d: %s" % [peer_id, map_id]) # Validate the map exists via WorkshopBrowser if WorkshopBrowser and WorkshopBrowser.has_method(&"has_map"): if not WorkshopBrowser.has_map(map_id): print("[MapBrowserRPC] Peer %d requested unknown map: %s" % [peer_id, map_id]) return map_change_requested.emit(map_id, peer_id) map_vote_started.emit(map_id)