# This file is part of open-fpsz. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . class_name MultiplayerPanelContainer extends PanelContainer const DEFAULT_HOST : String = "localhost" const DEFAULT_PORT : int = 9000 const CONFIG_FILE_PATH : String = "user://profile.cfg" var _join_address : RegEx = RegEx.new() var _registered_ports : RegEx = RegEx.new() var _config_file : ConfigFile = ConfigFile.new() signal menu_pressed # reuse signal for all tabs signal start_server(port : int, map : PackedScene, mode: Multiplayer.Mode, username: String) signal join_server(host : String, port : int) @export var tab_container : TabContainer @export var profile_panel : ProfilePanel @export var join_panel : JoinPanel @export var host_panel : HostPanel @onready var modal : Control = $Modal func _ready() -> void: # see https://datatracker.ietf.org/doc/html/rfc1700 _registered_ports.compile(r'^(?:102[4-9]|10[3-9]\d|1[1-9]\d{2}|[2-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$') _join_address.compile(r'^(?[a-zA-Z0-9.-]+)(:(?:102[4-9]|10[3-9]\d|1[1-9]\d{2}|[2-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5]))?$') # connect signals join_panel.join_button.pressed.connect(_on_join_pressed) host_panel.host_button.pressed.connect(_on_host_pressed) for panel:Control in [profile_panel, host_panel, join_panel]: panel.menu_button.pressed.connect(_on_menu_pressed) panel.quit_button.pressed.connect(_on_quit_pressed) # load configuration file _load_config() func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("exit"): modal.hide() func _load_config() -> void: var error : Error = _config_file.load(CONFIG_FILE_PATH) if error != OK: return profile_panel.profile_name.text = _config_file.get_value("profile", "name", "Newblood") func _on_save_pressed() -> void: _config_file.set_value("profile", "name", profile_panel.profile_name.text) _config_file.save(CONFIG_FILE_PATH) func _on_menu_pressed() -> void: menu_pressed.emit() func _on_quit_pressed() -> void: get_tree().quit() func _on_host_pressed() -> void: var port : int = DEFAULT_PORT # check for registered ports number matches if host_panel.server_port.text: var result : RegExMatch = _registered_ports.search(host_panel.server_port.text) if result: # port is valid port = int(result.get_string()) else: # port is not valid push_warning("A valid port number in the range 1024-65535 is required.") return start_server.emit( port, MapsManager.maps[host_panel.map_selector.selected], host_panel.mode_selector.selected, profile_panel.profile_name.text ) func _on_join_pressed() -> void: var addr : Array = [DEFAULT_HOST, DEFAULT_PORT] # validate join address input var result : RegExMatch = _join_address.search(join_panel.join_address.text) if result: # address is valid addr[0] = result.get_string("host") var rport : String = result.get_string("port") if rport: addr[1] = int(rport) modal.show() join_server.emit(addr[0], addr[1], profile_panel.profile_name.text)