Create client that fails gracefully when server is disconnected

Godot Version

4.2 stable

Question

When the server is shutdown/disconnect, I want the clients to exit gracefully. Currently if I quit the server, the clients all get a grey screens. Somehow it worked for a little bit, but then reverted back even though it was the exact same code and I’m so lost lol

Here’s all my network code.

extends Node3D

const PlayerScene = preload("res://scenes/player.tscn")
const PORT = 4200
var ip = "localhost"
var enet_peer = ENetMultiplayerPeer.new()

func start_host(upnp:bool):
	Global.singleplayer = false
	
	var err = enet_peer.create_server(PORT)
	if err == 0:
		multiplayer.multiplayer_peer = enet_peer
		multiplayer.peer_connected.connect(add_player)
		multiplayer.peer_disconnected.connect(remove_player)
		multiplayer.server_disconnected.connect(return_to_singleplayer)
		#Remove already existing character
		get_tree().root.get_node("World/Player").queue_free()
		add_player(multiplayer.get_unique_id())
	else:
		Global.singleplayer = true
	
	#add as checkbox to enable manually
	if upnp == true:
		upnp_setup()

func add_player(peer_id):
	var player = PlayerScene.instantiate()
	player.name = str(peer_id)
	get_tree().root.get_node("World").add_child(player)
	print("Player %s joined the game!" % player.name)

func remove_player(peer_id):
	var player = get_tree().root.get_node_or_null(str("World/",peer_id))
	if player:
		player.queue_free()

func join_server(address:String):
	Global.singleplayer = false
	var err = enet_peer.create_client(address, PORT)
	if err == 0:
		ip = address
		get_tree().root.get_node("World/Player").queue_free()
		multiplayer.multiplayer_peer = enet_peer

func close_connection():
	#Disable connection on the signals if it's the server
	if multiplayer.is_server():
		multiplayer.peer_connected.disconnect(add_player)
		multiplayer.peer_disconnected.disconnect(remove_player)
		multiplayer.server_disconnected.disconnect(return_to_singleplayer)
	
	multiplayer.multiplayer_peer.close()
	return_to_singleplayer()

func return_to_singleplayer():
	Global.singleplayer = true
	multiplayer.multiplayer_peer = OfflineMultiplayerPeer.new()
	get_tree().change_scene_to_file("res://scenes/Frolf course.tscn")

#TODO: Fail gracefully
func upnp_setup():
	var upnp = UPNP.new()
	var discover_result = upnp.discover()
	
	assert(discover_result == UPNP.UPNP_RESULT_SUCCESS, \
		"UPNP Discover Failed! Error %s" % discover_result)
		
	assert(upnp.get_gateway() and upnp.get_gateway().is_valid_gateway(), \
		"UPNP Invalid Gateway!")
		
	var map_result = upnp.add_port_mapping(PORT)
	assert(map_result == UPNP.UPNP_RESULT_SUCCESS, \
		"UPNP Port Mapping Failed! Error %s" % map_result)

	print("Success! Join Address: %s" % upnp.query_external_address())

Seems like you need to connect server_disconnected to the joined clients, also the server will never see a server_disconnected signal.

2 Likes

OMG duh that makes so much sense lol. Thanks, I’ll give that a shot when I get a chance! Can’t believe I missed that lol

EDIT: this worked! Thanks so much

1 Like