Skip to content

Instantly share code, notes, and snippets.

@nisovin
Last active March 7, 2021 02:41
Show Gist options
  • Save nisovin/83881d8e95dd5fdc145936ac4b11ccef to your computer and use it in GitHub Desktop.
Save nisovin/83881d8e95dd5fdc145936ac4b11ccef to your computer and use it in GitHub Desktop.
Use Godot's UDP multicast feature to find host games on the LAN. Largely untested.
extends Node
class_name LANFinder
const MULTICAST_ADDRESS = "239.10.10.10"
const MULTICAST_PORT = 33221
signal host_found(ip, info)
signal stopped()
var udp := PacketPeerUDP.new()
var thread := Thread.new()
var mutex := Mutex.new()
var stop_request := false
var host := false
var host_info := {}
var client := false
func set_as_host(info: Dictionary) -> void:
if host or client: return
host = true
host_info = info
_init_udp()
func update_host_info(info: Dictionary) -> void:
mutex.lock()
host_info = info
mutex.unlock()
func search_for_hosts(timeout: float = 10) -> void:
if host or client: return
client = true
_init_udp()
udp.put_var({"msg": "ping"})
if timeout > 0:
yield(Engine.get_main_loop().create_timer(timeout), "timeout")
if client:
stop()
func stop() -> void:
mutex.lock()
stop_request = true
mutex.unlock()
udp.close()
func _received_host_info(ip: String, info: Dictionary) -> void:
emit_signal("host_found", ip, info)
func _init_udp() -> void:
udp.listen(MULTICAST_PORT)
udp.set_dest_address(MULTICAST_ADDRESS, MULTICAST_PORT)
for i in IP.get_local_interfaces():
udp.join_multicast_group(MULTICAST_ADDRESS, i.name)
thread.start(self, "_listen_thread")
func _end_thread() -> void:
thread.wait_to_finish()
stop_request = false
emit_signal("stopped")
host = false
client = false
func _listen_thread(x) -> void:
var loop = true
while loop:
udp.wait()
if udp.get_available_packet_count() > 0:
var data := udp.get_var() as Dictionary
if data and data.has("msg"):
var ip := udp.get_packet_ip()
if data.msg == "ping" and host:
mutex.lock()
udp.put_var({"msg": "pong", "info": host_info})
mutex.unlock()
elif data.msg == "pong" and client:
call_deferred("_received_host_info", ip, data.info)
mutex.lock()
if stop_request:
loop = false
mutex.unlock()
call_deferred("_end_thread")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment