Help With Local Hosting / Multiplayer

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By scrubswithnosleeves

Hey All,

Preface: I don’t know what I am doing lol. I am trying to connect two+ devices on a local network via Godot high-level multiplayer without requiring the clients to manually input the server’s IP address. (I already have it working if they manually enter in the server/host IP).

u/nicemike40 told me that using UDP broadcasts would be a good solution for this, and I saw that Godot has UDPServer and PacketPeer built-in. I basically want the server to broadcast, and if it finds a client trying to connect, send them a UDP packet so that they can get_packet_ip() from the host, and then use that IP to connect via the high-level multiplayer

I can get this working when I run both the client and server on the same machine, but not on different devices, so I think I am missing something here. Again, my knowledge of networking is shallow at best, so please feel free to school me lol:

Here is the code I am trying to use for the UDP Server / Broadcast:

ServerSide

extends Node


const SERVER_PORT = 31416

var server := UDPServer.new()


func _ready():
	server.listen(SERVER_PORT, "0.0.0.0")

func _process(_delta):
	server.poll() # Important!
	if server.is_connection_available():
		var peer : PacketPeerUDP = server.take_connection()
		var pkt = peer.get_packet()
		print("Accepted peer: %s:%s" % [peer.get_packet_ip(), peer.get_packet_port()])
		print("Received data: %s" % [pkt.get_string_from_utf8()])
		# Reply so it knows we received the message.
		peer.put_packet(pkt)

ClientSide

extends Node


const SERVER_PORT = 31416

var udp := PacketPeerUDP.new()
var udp_connected = false
var ip_address = "x.x.x.x"


func _ready():
	udp.connect_to_host("0.0.0.0", SERVER_PORT)


func _process(delta):
	if !udp_connected:
		# Try to contact server
		udp.put_packet("Recieved Test Packet".to_utf8())
	if udp.get_available_packet_count() > 0:
		print("Connected: %s" % udp.get_packet().get_string_from_utf8())
		ip_address = udp.get_packet_ip()
		print(ip_address)
		udp_connected = true
:bust_in_silhouette: Reply From: scrubswithnosleeves

Just posting for anyone having this problem in the future:

Server Side

const UDP_PORT = 4242
var server := UDPServer.new()


func _ready():
	set_process(false)


func _process(_delta):
# warning-ignore:return_value_discarded
	server.poll()
	if server.is_connection_available():
		var peer : PacketPeerUDP = server.take_connection()
		var pkt = peer.get_packet()
		print("Accepted peer: %s:%s" % [peer.get_packet_ip(),                    peer.get_packet_port()])
		print("Received data: %s" % [pkt.get_string_from_utf8()])
		# Reply so it knows we received the message.
# warning-ignore:return_value_discarded
		peer.put_packet(pkt)


func start_broadcast():
# warning-ignore:return_value_discarded
	server.listen(UDP_PORT)
	set_process(true)
	print('UDP Broadcast Started')


func stop_broadcast():
	server.stop()
	set_process(false)
	print('UDP Broadcast Stopped')

Client-Side

const UDP_PORT = 4242
var udp := PacketPeerUDP.new()
var udp_connected = false


func _ready():
	set_process(false)
# warning-ignore:return_value_discarded
	udp.set_dest_address("255.255.255.255", UDP_PORT)
	udp.set_broadcast_enabled(true)


func get_server_ip():
	if !Client.host_ip_address:
		set_process(true)
	else:
		Client.join_server()


func _process(_delta):
	if !udp_connected:
		# Try to contact server
# warning-ignore:return_value_discarded
		udp.put_packet("Contacted Host".to_utf8())
	
	if udp.get_available_packet_count() > 0:
		print(udp.get_packet().get_string_from_utf8())
		Client.host_ip_address = udp.get_packet_ip()
		Client.join_server()
		
		# Stop Broadcasting
		udp_connected = true
		set_process(false)

The issue was really just two things:

  1. You need to do udp.set_broadcast_enabled(true) (false by default)

  2. You need to use udp.set_dest_address(“255.255.255.255”, UDP_PORT) instead of connect_to_host()