gates-multiplayer/ui/ui.gd
2025-07-12 12:46:39 -06:00

138 lines
3.2 KiB
GDScript

extends Control
signal start_server
signal connect_client(ip_address: String)
@export var hide_ui_and_connect: bool
const SAVE_FILE_PATH = "user://ip_settings.dat"
func _ready():
if Connection.is_server(): return
# Connect to connection events for error handling
var connection_node = get_node("/root/Main/Connection")
if connection_node:
connection_node.disconnected.connect(_on_connection_failed)
# Load saved IP address
_load_ip_address()
if hide_ui_and_connect:
connect_client_emit()
else:
show_ui()
func _input(event: InputEvent) -> void:
if event.is_action_pressed("quit_game"):
if $MainMenu.visible:
# If main menu is visible, quit the game
get_tree().quit()
elif $InGameUI.visible:
# If in-game UI is visible, return to main menu
# Disconnect from server/client first
if Connection.is_peer_connected:
multiplayer.multiplayer_peer.close()
show_ui()
func start_server_emit() -> void:
start_server.emit()
$MainMenu.visible = false
func connect_client_emit() -> void:
var ip_address = $MainMenu/MenuContainer/IPSection/IPInput.text.strip_edges()
if ip_address.is_empty():
ip_address = "localhost"
# Basic IP validation
if not _is_valid_ip_or_hostname(ip_address):
_show_connection_error("Invalid IP address or hostname!")
return
# Save IP address for next time
_save_ip_address(ip_address)
connect_client.emit(ip_address)
hide_ui()
func exit_game_emit() -> void:
get_tree().quit()
func hide_ui() -> void:
$MainMenu.visible = false
$InGameUI.visible = true
func show_ui() -> void:
$MainMenu.visible = true
$InGameUI.visible = false
func _is_valid_ip_or_hostname(address: String) -> bool:
if address.is_empty():
return false
# Allow localhost
if address == "localhost":
return true
# Basic hostname validation (alphanumeric, dots, hyphens)
var hostname_regex = RegEx.new()
hostname_regex.compile("^[a-zA-Z0-9.-]+$")
if hostname_regex.search(address):
return true
# Basic IP address validation
var parts = address.split(".")
if parts.size() != 4:
return false
for part in parts:
if not part.is_valid_int():
return false
var num = part.to_int()
if num < 0 or num > 255:
return false
return true
func _show_connection_error(message: String) -> void:
print("Connection error: " + message)
# Visual feedback by highlighting the IP input field
var ip_input = $MainMenu/MenuContainer/IPSection/IPInput
ip_input.modulate = Color.RED
# Reset color after 2 seconds
await get_tree().create_timer(2.0).timeout
ip_input.modulate = Color.WHITE
func _on_connection_failed() -> void:
# Show UI again if connection fails
if not $MainMenu.visible:
show_ui()
_show_connection_error("Failed to connect to server!")
func _save_ip_address(ip_address: String) -> void:
var file = FileAccess.open(SAVE_FILE_PATH, FileAccess.WRITE)
if file:
file.store_string(ip_address)
file.close()
func _load_ip_address() -> void:
if FileAccess.file_exists(SAVE_FILE_PATH):
var file = FileAccess.open(SAVE_FILE_PATH, FileAccess.READ)
if file:
var saved_ip = file.get_as_text().strip_edges()
file.close()
if not saved_ip.is_empty():
$MainMenu/MenuContainer/IPSection/IPInput.text = saved_ip