extends Node # Standard Nakama Configuration const NAKAMA_SERVER_KEY = "defaultkey" const NAKAMA_HOST = "77.237.232.232" const NAKAMA_PORT = 7350 const NAKAMA_SCHEME = "http" # Core Nakama Variables var client: NakamaClient var session: NakamaSession var socket: NakamaSocket var bridge: NakamaMultiplayerBridge # Signals signal connected_to_nakama signal connection_failed(error_message) signal match_joined(match_id) signal match_join_error(error_message) # Current Match Info var current_match_id: String = "" func _ready(): # Initialize the Nakama Client client = Nakama.create_client(NAKAMA_SERVER_KEY, NAKAMA_HOST, NAKAMA_PORT, NAKAMA_SCHEME) # Ensure we process network events set_process(true) func _process(_delta): # If using the standard socket adapter, it needs polling in some versions if socket: pass func connect_to_nakama_async(email: String = "", password: String = "") -> void: # 1. Authenticate if email == "": var device_id = OS.get_unique_id() # For testing, append a random number to device ID to simulate unique users on one machine # device_id = device_id + str(randi()) session = await client.authenticate_device_async(device_id) else: session = await client.authenticate_email_async(email, password) if session.is_exception(): printerr("Auth Error: ", session.get_exception().message) emit_signal("connection_failed", session.get_exception().message) return # 2. Connect Socket socket = Nakama.create_socket_from(client) var socket_result = await socket.connect_async(session) if socket_result.is_exception(): printerr("Socket Error: ", socket_result.get_exception().message) emit_signal("connection_failed", socket_result.get_exception().message) return # 3. Initialize Multiplayer Bridge # This links Nakama's socket to Godot's High-Level Multiplayer API bridge = NakamaMultiplayerBridge.new(socket) # Connect bridge signals bridge.match_joined.connect(_on_bridge_match_joined) bridge.match_join_error.connect(_on_bridge_match_join_error) # CRITICAL: Set Godot's multiplayer peer to the Nakama bridge # This allows @rpc functions to work over Nakama multiplayer.set_multiplayer_peer(bridge.multiplayer_peer) print("Connected to Nakama and Bridge Initialized.") emit_signal("connected_to_nakama") # --- Match Management --- func host_game(): if not bridge: printerr("Cannot host: Bridge not initialized") return print("Hosting match via Nakama Bridge...") var result = await bridge.create_match() if result.is_exception(): emit_signal("match_join_error", result.get_exception().message) func join_game(match_id: String): if not bridge: printerr("Cannot join: Bridge not initialized") return print("Joining match: ", match_id) var result = await bridge.join_match(match_id) if result.is_exception(): emit_signal("match_join_error", result.get_exception().message) # --- Callbacks --- func _on_bridge_match_joined() -> void: current_match_id = bridge.match_id print("Successfully joined match: ", current_match_id) emit_signal("match_joined", current_match_id) func _on_bridge_match_join_error(error) -> void: printerr("Bridge failed to join match: ", error.message) emit_signal("match_join_error", error.message) func is_connected_to_nakama() -> bool: return socket != null and socket.is_connected_to_host() func _exit_tree(): if socket: socket.close()