diff --git a/launcher/.gdignore b/launcher/.gdignore new file mode 100644 index 0000000..e69de29 diff --git a/launcher/scripts/config.gd b/launcher/scripts/config.gd index a706220..7368af8 100644 --- a/launcher/scripts/config.gd +++ b/launcher/scripts/config.gd @@ -1,5 +1,5 @@ extends Node -class_name Config + ## Global configuration for the Tekton Launcher # itch.io Configuration diff --git a/launcher/scripts/launcher_main.gd b/launcher/scripts/launcher_main.gd index 150c417..92e7b36 100644 --- a/launcher/scripts/launcher_main.gd +++ b/launcher/scripts/launcher_main.gd @@ -1,6 +1,12 @@ extends Control ## Main launcher scene script - orchestrates all launcher functionality +const Config = preload("config.gd") +const VersionChecker = preload("version_checker.gd") +const DownloadManager = preload("download_manager.gd") +const UpdateApplier = preload("update_applier.gd") +const NewsFetcher = preload("news_fetcher.gd") + # Child nodes (will be set up in _ready) @onready var version_checker := $VersionChecker as VersionChecker @onready var download_manager := $DownloadManager as DownloadManager @@ -36,7 +42,7 @@ func _ready() -> void: _set_state(LauncherState.CHECKING) # Start checking for updates - await get_tree().create_timer(0.5).timeout # Small delay for UI to initialize + await get_tree().create_timer(0.5).timeout # Small delay for UI to initialize version_checker.check_for_updates() news_fetcher.fetch_news() diff --git a/launcher/scripts/news_fetcher.gd b/launcher/scripts/news_fetcher.gd index 2f7b60e..983baa4 100644 --- a/launcher/scripts/news_fetcher.gd +++ b/launcher/scripts/news_fetcher.gd @@ -1,5 +1,7 @@ extends Node class_name NewsFetcher + +const Config = preload("config.gd") ## Fetches news/devlog entries from itch.io signal news_fetched(news_items: Array) @@ -65,4 +67,4 @@ func _format_changelog(changelog: Array) -> String: func _sort_by_date(a: Dictionary, b: Dictionary) -> bool: var date_a: String = a.get("date", "") var date_b: String = b.get("date", "") - return date_a > date_b # Descending order + return date_a > date_b # Descending order diff --git a/launcher/scripts/update_applier.gd b/launcher/scripts/update_applier.gd index ab1bb26..7f77e88 100644 --- a/launcher/scripts/update_applier.gd +++ b/launcher/scripts/update_applier.gd @@ -1,5 +1,7 @@ extends Node class_name UpdateApplier + +const Config = preload("config.gd") ## Handles applying downloaded updates: backup, replace, rollback signal update_started diff --git a/launcher/scripts/version_checker.gd b/launcher/scripts/version_checker.gd index 8d0c05d..fae1b4c 100644 --- a/launcher/scripts/version_checker.gd +++ b/launcher/scripts/version_checker.gd @@ -1,5 +1,7 @@ extends Node class_name VersionChecker + +const Config = preload("config.gd") ## Handles checking for game updates from the version manifest signal version_check_started @@ -96,7 +98,7 @@ func _get_changelog_since(since_version: String) -> Array: func get_download_info() -> Dictionary: ## Returns info needed to download the latest version (platform-specific) - var platform := Config.get_platform_name() # "windows", "linux", or "macos" + var platform := Config.get_platform_name() # "windows", "linux", or "macos" var releases: Array = manifest_data.get("releases", []) for release in releases: @@ -108,7 +110,7 @@ func get_download_info() -> Dictionary: var checksum_sha256: String = "" # Check for platform-specific fields - var platform_key := "pck_" + platform # e.g., "pck_windows", "pck_linux", "pck_macos" + var platform_key := "pck_" + platform # e.g., "pck_windows", "pck_linux", "pck_macos" if release.has(platform_key): var platform_data: Dictionary = release.get(platform_key, {}) pck_url = platform_data.get("url", "") diff --git a/scenes/lobby.gd b/scenes/lobby.gd index 0320c5d..15a1c85 100644 --- a/scenes/lobby.gd +++ b/scenes/lobby.gd @@ -7,6 +7,10 @@ extends Control @onready var browse_rooms_btn = $MainMenuPanel/VBoxContainer/ButtonSection/BrowseRoomsBtn @onready var main_menu_profile_btn = $MainMenuPanel/VBoxContainer/ButtonSection/ProfileBtn +# UI References - Server Selection +@onready var server_option = $MainMenuPanel/VBoxContainer/ServerSelectionSection/ServerOption +@onready var server_ip_input = $MainMenuPanel/VBoxContainer/ServerSelectionSection/ServerIPInput + # UI References - Room List @onready var room_list_panel = $RoomListPanel @onready var room_list = $RoomListPanel/VBoxContainer/RoomList @@ -68,18 +72,23 @@ var current_match_id: String = "" var scarcity_option: OptionButton var scarcity_label: Label +# Server Selection Controls (Now in tscn) +# var server_option: OptionButton +# var server_ip_input: LineEdit + func _ready(): - # Check if user is authenticated - if not AuthManager.is_logged_in(): - call_deferred("_go_to_login") - return - + # Check if user is authenticated (Commented out to allow server config on main menu) + # if not AuthManager.is_logged_in(): + # call_deferred("_go_to_login") + # return # Load character textures _load_character_textures() # Inject Scarcity UI call_deferred("_setup_scarcity_ui") + # Server config UI is now in tscn + # Get player slot references _setup_player_slots() @@ -108,6 +117,15 @@ func _ready(): if main_menu_profile_btn: main_menu_profile_btn.pressed.connect(_on_profile_btn_pressed) + # Connect Server Selection signals + if server_option: + server_option.item_selected.connect(_on_server_option_selected) + # Initialize state + _on_server_option_selected(server_option.selected) + if server_ip_input: + server_ip_input.text_submitted.connect(_on_server_ip_submitted) + server_ip_input.focus_exited.connect(func(): _on_server_ip_submitted(server_ip_input.text)) + # Connect button signals - Room List refresh_btn.pressed.connect(_on_refresh_pressed) join_btn.pressed.connect(_on_join_pressed) @@ -166,6 +184,20 @@ func _load_character_textures() -> void: else: print("[Lobby] Character texture not found: ", tex_path) +func _on_server_option_selected(index: int) -> void: + if index == 0: + # Localhost + if server_ip_input: server_ip_input.visible = false + NakamaManager.set_server("localhost") + else: + # Remote + if server_ip_input: server_ip_input.visible = true + if server_ip_input: NakamaManager.set_server(server_ip_input.text) + +func _on_server_ip_submitted(new_text: String) -> void: + if server_option and server_option.selected == 1: + NakamaManager.set_server(new_text.strip_edges()) + func _setup_scarcity_ui() -> void: """Inject scarcity controls into SettingsSection.""" if not duration_option: return diff --git a/scenes/lobby.tscn b/scenes/lobby.tscn index 463fb08..8b2f8b9 100644 --- a/scenes/lobby.tscn +++ b/scenes/lobby.tscn @@ -59,7 +59,7 @@ theme_override_constants/separation = 4 [node name="Title" type="Label" parent="MainMenuPanel/VBoxContainer/TitleContainer" unique_id=612210089] layout_mode = 2 -theme_override_colors/font_color = Color(0.647, 0.996, 0.224, 1) +theme_override_colors/font_color = Color(0.52, 0.52, 0.52, 1) theme_override_font_sizes/font_size = 44 text = "TEKTON DASH" horizontal_alignment = 1 @@ -67,7 +67,7 @@ vertical_alignment = 1 [node name="Subtitle" type="Label" parent="MainMenuPanel/VBoxContainer/TitleContainer" unique_id=670350843] layout_mode = 2 -theme_override_colors/font_color = Color(0.992, 0.796, 0.047, 1) +theme_override_colors/font_color = Color(0.71, 0.5751, 0.03550001, 1) theme_override_font_sizes/font_size = 12 text = "ARMAGEDDON VERSION" horizontal_alignment = 1 @@ -91,6 +91,36 @@ layout_mode = 2 text = "Player" placeholder_text = "Enter your name..." +[node name="ServerSelectionSection" type="VBoxContainer" parent="MainMenuPanel/VBoxContainer" unique_id=748392101] +layout_mode = 2 +theme_override_constants/separation = 10 + +[node name="ServerLabel" type="Label" parent="MainMenuPanel/VBoxContainer/ServerSelectionSection" unique_id=748392102] +layout_mode = 2 +theme_override_colors/font_color = Color(0.69, 0.529, 0.357, 1) +theme_override_font_sizes/font_size = 13 +text = "NAKAMA SERVER" + +[node name="ServerOption" type="OptionButton" parent="MainMenuPanel/VBoxContainer/ServerSelectionSection" unique_id=748392103] +custom_minimum_size = Vector2(0, 44) +layout_mode = 2 +selected = 0 +item_count = 2 +popup/item_0/text = "Localhost (Testing)" +popup/item_0/id = 0 +popup/item_1/text = "Remote Server (Host IP)" +popup/item_1/id = 1 + +[node name="ServerIPInput" type="LineEdit" parent="MainMenuPanel/VBoxContainer/ServerSelectionSection" unique_id=748392104] +visible = false +custom_minimum_size = Vector2(0, 44) +layout_mode = 2 +text = "127.0.0.1" +placeholder_text = "Enter Server IP Address..." + +[node name="ServerSeparator" type="HSeparator" parent="MainMenuPanel/VBoxContainer" unique_id=748392105] +layout_mode = 2 + [node name="ButtonSection" type="VBoxContainer" parent="MainMenuPanel/VBoxContainer" unique_id=793290187] layout_mode = 2 theme_override_constants/separation = 12 @@ -134,7 +164,7 @@ theme_override_constants/separation = 14 [node name="Header" type="Label" parent="RoomListPanel/VBoxContainer" unique_id=911540555] layout_mode = 2 -theme_override_colors/font_color = Color(0.647, 0.996, 0.224, 1) +theme_override_colors/font_color = Color(0.52156866, 0.52156866, 0.52156866, 1) theme_override_font_sizes/font_size = 28 text = "SERVER BROWSER" horizontal_alignment = 1 @@ -198,14 +228,35 @@ anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -[node name="LobbyBackground" type="ColorRect" parent="LobbyPanel" unique_id=1549298772] +[node name="TextureRect" type="TextureRect" parent="LobbyPanel" unique_id=518450226] layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -color = Color(0.06, 0.08, 0.12, 1) +texture = ExtResource("3_q60fs") +expand_mode = 2 + +[node name="TextureRect2" type="TextureRect" parent="LobbyPanel" unique_id=1500007123] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("4_nqcc7") +expand_mode = 2 + +[node name="LobbyBackground" type="ColorRect" parent="LobbyPanel" unique_id=1549298772] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_right = 2.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0.06, 0.080000006, 0.12, 0.8666667) [node name="TopBar" type="HBoxContainer" parent="LobbyPanel" unique_id=1388322915] layout_mode = 1 diff --git a/scripts/nakama_manager.gd b/scripts/nakama_manager.gd index dd2d492..d89f2a9 100644 --- a/scripts/nakama_manager.gd +++ b/scripts/nakama_manager.gd @@ -1,10 +1,10 @@ extends Node # Standard Nakama Configuration -const NAKAMA_SERVER_KEY = "defaultkey" -const NAKAMA_HOST = "localhost" -const NAKAMA_PORT = 7350 -const NAKAMA_SCHEME = "http" +var nakama_server_key = "defaultkey" +var nakama_host = "localhost" +var nakama_port = 7350 +var nakama_scheme = "http" # Core Nakama Variables var client: NakamaClient @@ -23,11 +23,20 @@ var current_match_id: String = "" func _ready(): # Initialize the Nakama Client - client = Nakama.create_client(NAKAMA_SERVER_KEY, NAKAMA_HOST, NAKAMA_PORT, NAKAMA_SCHEME) + _init_client() # Ensure we process network events set_process(true) +func _init_client(): + client = Nakama.create_client(nakama_server_key, nakama_host, nakama_port, nakama_scheme) + +func set_server(host: String, port: int = 7350): + nakama_host = host + nakama_port = port + _init_client() + print("[NakamaManager] Server updated to: ", nakama_host, ":", nakama_port) + func _process(_delta): # If using the standard socket adapter, it needs polling in some versions if socket: diff --git a/scripts/ui/login_screen.gd b/scripts/ui/login_screen.gd index 11fbda0..b50b57c 100644 --- a/scripts/ui/login_screen.gd +++ b/scripts/ui/login_screen.gd @@ -31,9 +31,14 @@ extends Control var is_loading: bool = false +# Server Selection Controls +var server_option: OptionButton +var server_ip_input: LineEdit + func _ready() -> void: _connect_signals() _setup_ui() + _setup_server_config_ui() # Check if already authenticated if AuthManager.is_logged_in(): @@ -165,6 +170,78 @@ func _on_facebook_pressed() -> void: # When you have the access token from Facebook SDK: # AuthManager.login_with_facebook(access_token) +func _setup_server_config_ui() -> void: + """Inject server configuration controls into MainPanel.""" + if not main_panel: return + + var vbox = main_panel.get_node_or_null("VBox") + if not vbox: return + + # Find where to insert (before GuestButton) + var insert_pos = 3 # Default position + if guest_button: + insert_pos = guest_button.get_index() + + # Create Server Section + var server_section = VBoxContainer.new() + server_section.name = "ServerSelectionSection" + server_section.add_theme_constant_override("separation", 10) + vbox.add_child(server_section) + vbox.move_child(server_section, insert_pos) + + # Server Label + var label = Label.new() + label.text = "NAKAMA SERVER" + label.add_theme_color_override("font_color", Color(0.69, 0.529, 0.357, 1)) + label.add_theme_font_size_override("font_size", 13) + server_section.add_child(label) + + # Server OptionButton + server_option = OptionButton.new() + server_option.name = "ServerOption" + server_option.custom_minimum_size = Vector2(0, 44) + server_option.add_item("Localhost (Testing)") + server_option.add_item("Remote Server (Host IP)") + + # Set initial state based on NakamaManager + if NakamaManager.nakama_host == "localhost": + server_option.selected = 0 + else: + server_option.selected = 1 + + server_option.item_selected.connect(_on_server_option_selected) + server_section.add_child(server_option) + + # Server IP Input + server_ip_input = LineEdit.new() + server_ip_input.name = "ServerIPInput" + server_ip_input.custom_minimum_size = Vector2(0, 44) + server_ip_input.placeholder_text = "Enter Server IP Address..." + server_ip_input.text = NakamaManager.nakama_host if NakamaManager.nakama_host != "localhost" else "127.0.0.1" + server_ip_input.visible = server_option.selected == 1 + server_ip_input.text_submitted.connect(_on_server_ip_submitted) + server_ip_input.focus_exited.connect(func(): _on_server_ip_submitted(server_ip_input.text)) + server_section.add_child(server_ip_input) + + # Add a separator after the section + var separator = HSeparator.new() + vbox.add_child(separator) + vbox.move_child(separator, insert_pos + 1) + +func _on_server_option_selected(index: int) -> void: + if index == 0: + # Localhost + server_ip_input.visible = false + NakamaManager.set_server("localhost") + else: + # Remote + server_ip_input.visible = true + NakamaManager.set_server(server_ip_input.text) + +func _on_server_ip_submitted(new_text: String) -> void: + if server_option.selected == 1: + NakamaManager.set_server(new_text.strip_edges()) + # ============================================================================= # Registration Handlers # ============================================================================= @@ -239,7 +316,7 @@ func _check_password_strength(password: String) -> void: password_strength.add_theme_stylebox_override("fill", style) func _calculate_password_strength(password: String) -> int: - var strength := 0 + var strength: float = 0.0 if password.length() >= 8: strength += 1 @@ -269,7 +346,7 @@ func _calculate_password_strength(password: String) -> int: if has_special: strength += 0.5 - return mini(int(strength), 4) + return clampi(int(strength), 0, 4) # ============================================================================= # Auth Manager Callbacks