I have succesfully implement the netfox-noray, but can't connect on itch.io

help me

After succesfully testing the game locally on my network I decided to upload it to Itch.io and attempt to host/join a p2p server. However I always endup with a timeout error (noray error 26)

This is the NetworkManager script that I built by following this documentation.

# NetworkManager.gd - Autoload singleton with netfox-noray support

extends Node

signal peer_connected(id: int)

signal peer_disconnected(id: int)

signal connection_failed()

signal server_disconnected()

var peer: ENetMultiplayerPeer

var is_multiplayer_mode := false

var connected_players := {} # {peer_id: player_data}

# Game synchronization signals

signal game_state_synced(state_data: Dictionary)

signal card_played_remote(player_id: int, card_data: Dictionary, slot_index: int)

signal truco_called_remote(player_id: int, truco_level: int)

signal truco_response_remote(player_id: int, accepted: bool)

# Netfox-noray specific variables

const NORAY_ADDRESS = "tomfol.io"

const NORAY_PORT = 8890

var open_id: String = "" # Public ID that others use to connect

var lobby_code: String = "" # Alias for open_id for compatibility with LobbyMenu

var _is_host: bool = false

var is_connecting: bool = false

func _ready():

`# Connect multiplayer events`

`multiplayer.peer_connected.connect(_on_peer_connected)`

`multiplayer.peer_disconnected.connect(_on_peer_disconnected)`

`multiplayer.connection_failed.connect(_on_connection_failed)`

`multiplayer.server_disconnected.connect(_on_server_disconnected)`



`# Connect noray signals`

`Noray.on_oid.connect(_on_open_id_received)`

`Noray.on_connect_nat.connect(_handle_connect_nat)`

`Noray.on_connect_relay.connect(_handle_connect_relay)`

# --- Host/Join Functions ---

func host_game():

`if is_connecting:`

	`print("Already connecting...")`

	`return false`



`is_connecting = true`

`_is_host = true`



`# Connect to noray server`

`print("Connecting to noray server at %s:%d" % [NORAY_ADDRESS, NORAY_PORT])`

`var err = await Noray.connect_to_host(NORAY_ADDRESS, NORAY_PORT)`

`if err != OK:`

	`print("Failed to connect to noray server: %s" % err)`

	`is_connecting = false`

	`return false`



`# Register as host`

`print("Registering as host...")`

`Noray.register_host()`

`await Noray.on_pid  # Wait for private ID`



`# Register remote address`

`err = await Noray.register_remote()`

`if err != OK:`

	`print("Failed to register remote address: %s" % err)`

	`is_connecting = false`

	`return false`



`# Create server on noray's local port`

`peer = ENetMultiplayerPeer.new()`

`err = peer.create_server(Noray.local_port, 1)  # Max 1 client`

`if err != OK:`

	`print("Failed to create server on port %d: %s" % [Noray.local_port, err])`

	`is_connecting = false`

	`return false`



`multiplayer.multiplayer_peer = peer`

`is_multiplayer_mode = true`

`is_connecting = false`



`# Add host as player 0`

`connected_players[1] = {`

	`"player_id": 0,`

	`"peer_id": 1,`

	`"name": "Host",`

	`"is_human": true`

`}`



`print("Hosting on port %d" % Noray.local_port)`

`print("Waiting for Open ID...")`

`return true`

func join_game(host_open_id: String, use_relay: bool = true):

`if is_connecting:`

	`print("Already connecting...")`

	`return false`

	

`if host_open_id.is_empty():`

	`print("Host Open ID cannot be empty")`

	`return false`



`is_connecting = true`

`_is_host = false`



`# Connect to noray server`

`print("Connecting to noray server at %s:%d" % [NORAY_ADDRESS, NORAY_PORT])`

`var err = await Noray.connect_to_host(NORAY_ADDRESS, NORAY_PORT)`

`if err != OK:`

	`print("Failed to connect to noray server: %s" % err)`

	`is_connecting = false`

	`return false`



`# Register host (clients also need to register)`

`print("Registering with noray...")`

`Noray.register_host()`

`await Noray.on_pid  # Wait for private ID`



`# Register remote address`

`err = await Noray.register_remote()`

`if err != OK:`

	`print("Failed to register remote address: %s" % err)`

	`is_connecting = false`

	`return false`



`# Request connection to host`

`print("Requesting connection to host: %s" % host_open_id)`

`if use_relay:`

	`Noray.connect_relay(host_open_id)`

`else:`

	`Noray.connect_nat(host_open_id)`



`print("Connection request sent, waiting for response...")`

`return true`

func disconnect_from_game():

`if peer:`

	`peer.close()`

	`peer = null`

`multiplayer.multiplayer_peer = null`

`is_multiplayer_mode = false`

`_is_host = false`

`is_connecting = false`

`connected_players.clear()`

`open_id = ""`

`lobby_code = ""  # Clear lobby_code as well`

`print("Disconnected from multiplayer game")`

func is_server() -> bool:

`return _is_host`

# Legacy method for compatibility with old code

func is_host() -> bool:

`return _is_host`

func get_open_id() -> String:

`return open_id`

func get_local_player_id() -> int:

`if not is_multiplayer_mode:`

	`return 0`



`for peer_id in connected_players:`

	`if peer_id == multiplayer.get_unique_id():`

		`return connected_players[peer_id].player_id`

`return 0`

# --- Noray Signal Handlers ---

func _on_open_id_received(oid: String):

`open_id = oid`

`lobby_code = oid  # Set lobby_code for compatibility with LobbyMenu`

`print("Received Open ID: %s" % open_id)`

func _handle_connect_nat(address: String, port: int) -> Error:

`print("Handling NAT connection to %s:%d" % [address, port])`

`return await _handle_connect(address, port)`

func _handle_connect_relay(address: String, port: int) -> Error:

`print("Handling relay connection to %s:%d" % [address, port])`

`return await _handle_connect(address, port)`

func _handle_connect(address: String, port: int) -> Error:

`if _is_host:`

	`# Host handshake`

	`var enet_peer = multiplayer.multiplayer_peer as ENetMultiplayerPeer`

	`var err = await PacketHandshake.over_enet(enet_peer.host, address, port)`

	`if err != OK:`

		`print("Host handshake failed: %s" % err)`

		`return err`

	`print("Host handshake successful")`

`else:`

	`# Client handshake and connection`

	`var udp = PacketPeerUDP.new()`

	`udp.bind(Noray.local_port)`

	`udp.set_dest_address(address, port)`

	`var err = await PacketHandshake.over_packet_peer(udp)`

	`udp.close()`

	

	`if err != OK:`

		`print("Client handshake failed: %s" % err)`

		`is_connecting = false`

		`return err`

	

	`print("Client handshake successful, connecting...")`

	

	`# Connect to host`

	`peer = ENetMultiplayerPeer.new()`

	`err = peer.create_client(address, port, 0, 0, 0, Noray.local_port)`

	`if err != OK:`

		`print("Failed to create client: %s" % err)`

		`is_connecting = false`

		`return err`

	

	`multiplayer.multiplayer_peer = peer`

	`is_multiplayer_mode = true`

	`is_connecting = false`

	

	`print("Connected to host successfully!")`



`return OK`

# --- Multiplayer Events ---

func _on_peer_connected(id: int):

`print("Peer %s connected" % id)`



`if is_server():`

	`# Assign player ID 1 to the joining client`

	`connected_players[id] = {`

		`"player_id": 1,`

		`"peer_id": id,`

		`"name": "Client",`

		`"is_human": true`

	`}`

	

	`# Send welcome message and player assignment`

	`rpc_id(id, "_receive_player_assignment", 1)`

	`rpc_id(id, "_client_greet", "Welcome to the game!")`

	

	`# Notify about successful connection`

	`peer_connected.emit(id)`

func _on_peer_disconnected(id: int):

`print("Peer %s disconnected" % id)`

`if connected_players.has(id):`

	`connected_players.erase(id)`

`peer_disconnected.emit(id)`

func _on_connection_failed():

`print("Failed to connect to server")`

`is_connecting = false`

`connection_failed.emit()`

func _on_server_disconnected():

`print("Server disconnected")`

`server_disconnected.emit()`

# --- RPC Functions ---

@rpc("authority", "reliable")

func _client_greet(message: String):

`print("[GREETING] %s" % message)`

@rpc("authority", "reliable")

func _receive_player_assignment(player_id: int):

`# Store our player assignment`

`connected_players[multiplayer.get_unique_id()] = {`

	`"player_id": player_id,`

	`"peer_id": multiplayer.get_unique_id(),`

	`"name": "Player %d" % player_id,`

	`"is_human": true`

`}`

`print("Assigned as Player %d" % player_id)`

# --- Game Synchronization RPCs ---

@rpc("any_peer", "reliable")

func sync_game_state(state_data: Dictionary):

`print("Game state synced from peer %d" % multiplayer.get_remote_sender_id())`

`game_state_synced.emit(state_data)`

@rpc("any_peer", "reliable")

func play_card_remote(player_id: int, card_name: String, card_value: int, slot_index: int):

`var card_data = {"name": card_name, "value": card_value}`

`print("Card played remotely by player %d" % player_id)`

`card_played_remote.emit(player_id, card_data, slot_index)`

@rpc("any_peer", "reliable")

func call_truco_remote(player_id: int, truco_level: int):

`print("Truco called remotely by player %d (level %d)" % [player_id, truco_level])`

`truco_called_remote.emit(player_id, truco_level)`

@rpc("any_peer", "reliable")

func respond_truco_remote(player_id: int, accepted: bool):

`print("Truco response from player %d: %s" % [player_id, "accepted" if accepted else "rejected"])`

`truco_response_remote.emit(player_id, accepted)`

# --- Utility Functions ---

func get_opponent_peer_id() -> int:

`var local_id = multiplayer.get_unique_id()`

`for peer_id in connected_players:`

	`if peer_id != local_id:`

		`return peer_id`

`return -1`

func get_player_count() -> int:

`return connected_players.size()`

func is_all_players_connected() -> bool:

`return connected_players.size() >= 2`

# --- Connection Status ---

func get_connection_status() -> String:

`if is_connecting:`

	`return "Connecting..."`

`elif not is_multiplayer_mode:`

	`return "Not connected"`

`elif is_server():`

	`return "Hosting (Open ID: %s)" % open_id`

`else:`

	`return "Connected as client"`

I would like to know if I am missing something with my current configuration.

Posted Sep 2, 2025, 3:21 PM UTC

25
Loading comments…