Add ready lobby and reconnect support

This commit is contained in:
Emporex committed 2026-10-04 04:31:52 +02:00
1 parent 19b1a67773
commit 32594c7f81
8 files changed
+215 -36

No files matched your search

+62 -7
View File
@@ -32,6 +32,9 @@ var current_host := ""
var current_match = null
var matchmaker_ticket := ""
var private_room_code := ""
var lobby_ready := false
var intentional_disconnect := false
var reconnect_in_progress := false
var account_manager: AccountManager
var auto_connect_enabled := true
@@ -83,21 +86,27 @@ func _authenticate_on(host: String, port: int, scheme: String) -> bool:
func _after_authentication() -> void:
socket = Nakama.create_socket_from(client)
socket.received_matchmaker_matched.connect(_on_matchmaker_matched)
socket.received_match_state.connect(_on_match_state)
socket.closed.connect(_on_socket_closed)
_bind_socket_signals()
var result = await socket.connect_async(session, true, 5)
if result == null or result.is_exception():
last_error = "Echtzeitverbindung konnte nicht aufgebaut werden"
socket = null
_set_connection_state("authenticated")
else:
intentional_disconnect = false
_set_connection_state("online")
authenticated.emit(session.user_id, session.username)
await flush_pending_scores()
func _bind_socket_signals() -> void:
socket.received_matchmaker_matched.connect(_on_matchmaker_matched)
socket.received_match_state.connect(_on_match_state)
socket.closed.connect(_on_socket_closed)
func disconnect_from_server() -> void:
intentional_disconnect = true
if socket:
socket.close()
socket = null
@@ -105,6 +114,7 @@ func disconnect_from_server() -> void:
current_match = null
matchmaker_ticket = ""
private_room_code = ""
lobby_ready = false
_set_connection_state("offline")
@@ -119,7 +129,7 @@ func submit_run(record: Dictionary) -> bool:
if not is_authenticated():
return false
var payload := record.duplicate(true)
payload["client_version"] = "0.20"
payload["client_version"] = "0.21"
var result = await client.rpc_async(session, "submit_run", JSON.stringify(payload))
var parsed := _parse_rpc_result(result)
if parsed.is_empty() or not bool(parsed.get("accepted", false)):
@@ -160,6 +170,7 @@ func load_leaderboard(map_index: int, difficulty_index: int, endless: bool, limi
func begin_matchmaking(mode := "quick", difficulty := 1) -> bool:
intentional_disconnect = false
if not is_online() or socket == null:
matchmaking_state_changed.emit("offline")
return false
@@ -178,6 +189,7 @@ func begin_matchmaking(mode := "quick", difficulty := 1) -> bool:
func cancel_matchmaking() -> void:
intentional_disconnect = true
if socket and not matchmaker_ticket.is_empty():
await socket.remove_matchmaker_async(matchmaker_ticket)
matchmaker_ticket = ""
@@ -189,6 +201,7 @@ func cancel_matchmaking() -> void:
func create_private_room(difficulty := 1) -> bool:
intentional_disconnect = false
if not is_online() or socket == null:
matchmaking_state_changed.emit("offline")
return false
@@ -209,11 +222,13 @@ func create_private_room(difficulty := 1) -> bool:
return false
private_room_created.emit(private_room_code)
matchmaking_state_changed.emit("hosting")
await send_match_command(OP_READY, {})
lobby_ready = false
await set_lobby_ready(false)
return true
func join_private_room(room_code: String) -> bool:
intentional_disconnect = false
if not is_online() or socket == null:
matchmaking_state_changed.emit("offline")
return false
@@ -233,11 +248,13 @@ func join_private_room(room_code: String) -> bool:
matchmaking_state_changed.emit("room_not_found")
return false
matchmaking_state_changed.emit("matched")
await send_match_command(OP_READY, {})
lobby_ready = false
await set_lobby_ready(false)
return true
func _on_matchmaker_matched(matched) -> void:
intentional_disconnect = false
matchmaker_ticket = ""
current_match = await socket.join_matched_async(matched)
if current_match == null or current_match.is_exception():
@@ -245,7 +262,14 @@ func _on_matchmaker_matched(matched) -> void:
return
matchmaking_state_changed.emit("matched")
match_found.emit(current_match)
await send_match_command(OP_READY, {})
lobby_ready = false
await set_lobby_ready(false)
func set_lobby_ready(value: bool) -> bool:
lobby_ready = value
var player_name := account_manager.display_name if account_manager else session.username
return await send_match_command(OP_READY, {"ready": value, "name": player_name})
func send_match_command(op_code: int, payload: Dictionary) -> bool:
@@ -276,6 +300,7 @@ func leave_current_match() -> void:
await socket.leave_match_async(current_match.match_id)
current_match = null
private_room_code = ""
lobby_ready = false
func _on_match_state(data) -> void:
@@ -291,8 +316,38 @@ func _on_match_state(data) -> void:
func _on_socket_closed() -> void:
var reconnect_match_id := ""
if not intentional_disconnect and current_match != null:
reconnect_match_id = String(current_match.match_id)
current_match = null
if connection_state != "offline":
_set_connection_state("authenticated")
if not reconnect_match_id.is_empty() and not reconnect_in_progress:
reconnect_in_progress = true
matchmaking_state_changed.emit("reconnecting")
_recover_match.call_deferred(reconnect_match_id)
func _recover_match(match_id: String) -> void:
for attempt in 5:
await get_tree().create_timer(1.5 + attempt).timeout
if intentional_disconnect or not is_authenticated():
break
socket = Nakama.create_socket_from(client)
_bind_socket_signals()
var connected = await socket.connect_async(session, true, 5)
if connected == null or connected.is_exception():
continue
var rejoined = await socket.join_match_async(match_id)
if rejoined != null and not rejoined.is_exception():
current_match = rejoined
intentional_disconnect = false
reconnect_in_progress = false
_set_connection_state("online")
matchmaking_state_changed.emit("reconnected")
return
reconnect_in_progress = false
matchmaking_state_changed.emit("connection_lost")
func _device_id() -> String: