Files
lobby-server/scenes/data_bridge/lobby_data.gd
itdominator 7897462309 feat: support configurable game server address and port
* Launch game servers in headless mode
* Add configurable game address and port to GameData
* Pass dynamically assigned server ports to clients
* Update lobby defaults for `0.0.0.0:8080`
* Refactor server command-line argument handling
2026-08-10 00:28:23 -05:00

167 lines
5.0 KiB
GDScript

class_name LobbyData extends Node
var uuid = null
var lobby_ui: Node = null
var IS_VALID_CHARS_REGEX: RegEx = RegEx.create_from_string("^[a-zA-Z0-9]+$")
const MATCH_TYPES: Array = ["8ball", "9ball", "snooker"]
const CLIENT_DICT: Dictionary = {
"id": "",
"partner_id": "",
"in_match": false,
"match_id": ""
}
const MATCH_POOL_ENTRY: Dictionary = {
"player1": "",
"player2": "",
"data": {}
}
var active_match_pool: Dictionary = {}
var match_pool: Dictionary = {}
var client_pool: Dictionary = {}
func _init() -> void:
Globals.lobby_data = self
uuid = load('res://addons/uuid/uuid.gd')
func _delete_from_match_pool(match_id: String) -> Dictionary:
if not match_pool.has(match_id): return {}
var to_delete: Dictionary = match_pool[match_id].data
match_pool.erase(match_id)
return to_delete
func _launch_game_server(
match_entry: Dictionary,
client1: Dictionary,
client2: Dictionary
) -> void:
var port: String = InstanceLauncher.launch_game_server(match_entry.data.type)
if port == "-1":
# TODO: Alert clients that the game wont be created due to
# server reaching number of allowed instances.
return
# TODO: Set address dynamically; I.E. if game on different server than lobby.
# As is, clients use the lobby address since games launch on new ports.
# Will have to change how we watch game server death if on diff server.
#Globals.game_data.rpc_id(client1.id, "set_game_address", "51.222.85.126")
#Globals.game_data.rpc_id(client2.id, "set_game_address", "51.222.85.126")
Globals.game_data.rpc_id(client1.id, "set_game_port", port)
Globals.game_data.rpc_id(client2.id, "set_game_port", port)
rpc_id(client1.id, "connect_to_game")
rpc_id(client2.id, "connect_to_game")
func match_list_add_entry(match_entry: Dictionary) -> void:
var client1 = client_pool.get( multiplayer.get_remote_sender_id() )
if not client1: return
if not client1.match_id.is_empty(): return
if match_entry.name.length() < 1 or match_entry.name.length() > 12: return
if not IS_VALID_CHARS_REGEX.search(match_entry.name): return
if not match_entry.type in MATCH_TYPES: return
match_entry["match_id"] = uuid.v4()
match_pool[match_entry.match_id] = MATCH_POOL_ENTRY.duplicate_deep()
match_pool[match_entry.match_id].player1 = client1.id
match_pool[match_entry.match_id].data = match_entry
client1.match_id = match_entry.match_id
func match_list_remove_entry(match_id: String) -> void:
var client1 = client_pool.get( multiplayer.get_remote_sender_id() )
if not client1: return
if not client1.match_id == match_id: return
client1.match_id = ""
_delete_from_match_pool(match_id)
func match_list_join_entry(match_id: String) -> void:
if active_match_pool.has(match_id):
push_error("Client Joining Match List Entry Failed. Already consumed. ", match_id)
# TODO: Need to signal to prospective client that match has been taken.
# Server is in the midst of cleanup for it once clients disconnect
# to join generated game server...
return
var match_entry = match_pool.get(match_id)
if not match_entry: return
var client1 = client_pool.get( match_entry.player1 )
var client2 = client_pool.get( multiplayer.get_remote_sender_id() )
if not client1: return
if not client2: return
match_entry.player2 = client2.id
client1.in_match = true
client1.partner_id = client2.id
client2.match_id = match_id
client2.in_match = true
client2.partner_id = client1.id
active_match_pool[match_id] = match_entry
# NOTE: Cleanup of match info and client info
# will/should happen on their disconnect...
# TODO: Need to look into moving this out of here.
# Maybe just have clients drop and internally call on their own?
# Maybe just check here if we can even launch the game server?
_launch_game_server(match_entry, client1, client2)
func server_client_connected(id: int) -> void:
push_warning("Client Connected... ID: ", id)
client_pool[id] = CLIENT_DICT.duplicate_deep()
client_pool[id].id = id
var matches: Array = []
for match_entry in match_pool.values():
matches.append(match_entry.data)
MessageBus.emit_propagation_clients_only.rpc_id(
id, "receive_match_list", matches
)
func server_client_disconnected(id: int) -> void:
push_warning("Client Disconnected... ID: ", id)
var client1 = client_pool.get(id)
if not client1: return
var match_entry = _delete_from_match_pool(client1.match_id)
if not match_entry: return
push_warning("Removing Match... Match: ", match_entry)
MessageBus.emit_local(
"match_list_remove_entry", match_entry.match_id
)
MessageBus.emit_propagation_clients_only.rpc(
"match_list_remove_entry", match_entry.match_id
)
client_pool.erase(client1.id)
# NOTE: Needed for hash check to pass between client and server but isn't used by server...
@rpc("authority", "reliable")
func connect_to_game() -> void:
pass
@rpc("authority", "reliable")
func go_back_to_match_screen() -> void:
pass