open-fpsz/interfaces/menus/boot/multiplayer/multiplayer_panel_container.gd
2024-10-16 21:43:01 +00:00

99 lines
3.6 KiB
GDScript

# 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 <https://www.gnu.org/licenses/>.
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'^(?<host>[a-zA-Z0-9.-]+)(:(?<port>: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)