feat: expand progression and multiplayer systems

Add named save slots, progression import/export, and a unified play flow. Add live friend requests, presence, invitations, and relationship controls without durable discovery-server social storage. Advance the network protocol with isolated channels, movement reconciliation, late-join recovery, fishing replication, and animation synchronization. Preserve per-species catch totals, refine generated-world startup and water recovery, and complete the related input and interface improvements.
This commit is contained in:
Alexander Sellite 2026-08-23 20:48:38 -04:00
parent 1db1a5b754
commit 3b84bfe3a0
97 changed files with 7869 additions and 982 deletions

View file

@ -1,76 +1,10 @@
[gd_scene load_steps=12 format=3]
[gd_scene load_steps=5 format=3]
[ext_resource type="Script" path="res://ui/network/join_game_page.gd" id="1_script"]
[ext_resource type="Theme" path="res://ui/game_theme.tres" id="2_theme"]
[ext_resource type="Script" path="res://ui/components/organizer_tab.gd" id="3_tab"]
[ext_resource type="PackedScene" path="res://ui/components/bubble_menu/bubble_confirmation_page.tscn" id="4_confirmation"]
[sub_resource type="StyleBoxFlat" id="StyleBox_paper"]
bg_color = Color(0.051, 0.173, 0.227, 1)
corner_radius_top_left = 54
corner_radius_top_right = 46
corner_radius_bottom_right = 58
corner_radius_bottom_left = 48
[sub_resource type="StyleBoxFlat" id="StyleBox_list"]
bg_color = Color(0.071, 0.247, 0.306, 1)
corner_radius_top_left = 12
corner_radius_top_right = 9
corner_radius_bottom_right = 13
corner_radius_bottom_left = 10
[sub_resource type="StyleBoxFlat" id="StyleBox_selected"]
bg_color = Color(0.137, 0.525, 0.592, 1)
corner_radius_top_left = 8
corner_radius_top_right = 7
corner_radius_bottom_right = 9
corner_radius_bottom_left = 6
[sub_resource type="StyleBoxEmpty" id="StyleBox_focus"]
[sub_resource type="StyleBoxFlat" id="StyleBox_input"]
content_margin_left = 12.0
content_margin_top = 7.0
content_margin_right = 12.0
content_margin_bottom = 7.0
bg_color = Color(0.031, 0.122, 0.169, 1)
corner_radius_top_left = 8
corner_radius_top_right = 7
corner_radius_bottom_right = 9
corner_radius_bottom_left = 6
[sub_resource type="StyleBoxFlat" id="StyleBox_input_focus"]
content_margin_left = 12.0
content_margin_top = 7.0
content_margin_right = 12.0
content_margin_bottom = 7.0
bg_color = Color(0.137, 0.525, 0.592, 1)
corner_radius_top_left = 8
corner_radius_top_right = 7
corner_radius_bottom_right = 9
corner_radius_bottom_left = 6
[sub_resource type="StyleBoxFlat" id="StyleBox_input_read_only"]
content_margin_left = 12.0
content_margin_top = 7.0
content_margin_right = 12.0
content_margin_bottom = 7.0
bg_color = Color(0.031, 0.122, 0.169, 0.82)
corner_radius_top_left = 8
corner_radius_top_right = 7
corner_radius_bottom_right = 9
corner_radius_bottom_left = 6
[sub_resource type="StyleBoxFlat" id="StyleBox_status"]
content_margin_left = 10.0
content_margin_top = 4.0
content_margin_right = 10.0
content_margin_bottom = 4.0
bg_color = Color(0.071, 0.247, 0.306, 0.9)
corner_radius_top_left = 7
corner_radius_top_right = 6
corner_radius_bottom_right = 8
corner_radius_bottom_left = 5
[node name="JoinGamePage" type="Control"]
visible = false
layout_mode = 3
@ -82,243 +16,322 @@ grow_vertical = 2
theme = ExtResource("2_theme")
script = ExtResource("1_script")
[node name="Paper" type="PanelContainer" parent="."]
layout_mode = 0
offset_left = 230.0
offset_top = 64.0
offset_right = 1050.0
offset_bottom = 656.0
theme_override_styles/panel = SubResource("StyleBox_paper")
[node name="MainPanel" type="PanelContainer" parent="."]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -440.0
offset_top = -330.0
offset_right = 440.0
offset_bottom = 330.0
grow_horizontal = 2
grow_vertical = 2
[node name="Margin" type="MarginContainer" parent="Paper"]
[node name="OuterMargin" type="MarginContainer" parent="MainPanel"]
layout_mode = 2
theme_override_constants/margin_left = 54
theme_override_constants/margin_top = 30
theme_override_constants/margin_right = 54
theme_override_constants/margin_bottom = 30
theme_override_constants/margin_left = 24
theme_override_constants/margin_top = 18
theme_override_constants/margin_right = 24
theme_override_constants/margin_bottom = 18
[node name="Layout" type="VBoxContainer" parent="Paper/Margin"]
[node name="Layout" type="VBoxContainer" parent="MainPanel/OuterMargin"]
layout_mode = 2
theme_override_constants/separation = 10
alignment = 1
theme_override_constants/separation = -26
[node name="Title" type="Label" parent="Paper/Margin/Layout"]
[node name="Heading" type="Label" parent="MainPanel/OuterMargin/Layout"]
custom_minimum_size = Vector2(0, 66)
layout_mode = 2
theme_override_colors/font_color = Color(0.902, 0.969, 0.969, 1)
theme_override_font_sizes/font_size = 30
text = "join game"
horizontal_alignment = 1
[node name="Modes" type="HBoxContainer" parent="Paper/Margin/Layout"]
[node name="TabBar" type="HBoxContainer" parent="MainPanel/OuterMargin/Layout"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 52)
layout_mode = 2
theme_override_constants/separation = 14
theme_override_constants/separation = 8
alignment = 1
[node name="DiscoverButton" type="Button" parent="Paper/Margin/Layout/Modes"]
[node name="DiscoverButton" type="Button" parent="MainPanel/OuterMargin/Layout/TabBar"]
unique_name_in_owner = true
custom_minimum_size = Vector2(100, 72)
custom_minimum_size = Vector2(165, 52)
layout_mode = 2
toggle_mode = true
focus_mode = 2
text = "discover"
script = ExtResource("3_tab")
[node name="DirectButton" type="Button" parent="Paper/Margin/Layout/Modes"]
[node name="FriendsButton" type="Button" parent="MainPanel/OuterMargin/Layout/TabBar"]
unique_name_in_owner = true
custom_minimum_size = Vector2(100, 72)
custom_minimum_size = Vector2(140, 52)
layout_mode = 2
toggle_mode = true
focus_mode = 2
text = "friends"
script = ExtResource("3_tab")
palette_index = 1
[node name="DirectButton" type="Button" parent="MainPanel/OuterMargin/Layout/TabBar"]
unique_name_in_owner = true
custom_minimum_size = Vector2(140, 52)
layout_mode = 2
focus_mode = 2
text = "direct"
script = ExtResource("3_tab")
palette_index = 1
[node name="SavedButton" type="Button" parent="Paper/Margin/Layout/Modes"]
[node name="SavedButton" type="Button" parent="MainPanel/OuterMargin/Layout/TabBar"]
unique_name_in_owner = true
custom_minimum_size = Vector2(100, 72)
custom_minimum_size = Vector2(140, 52)
layout_mode = 2
toggle_mode = true
focus_mode = 2
text = "saved"
script = ExtResource("3_tab")
palette_index = 2
[node name="RecentButton" type="Button" parent="Paper/Margin/Layout/Modes"]
[node name="RecentButton" type="Button" parent="MainPanel/OuterMargin/Layout/TabBar"]
unique_name_in_owner = true
custom_minimum_size = Vector2(100, 72)
custom_minimum_size = Vector2(140, 52)
layout_mode = 2
toggle_mode = true
focus_mode = 2
text = "recent"
script = ExtResource("3_tab")
palette_index = 1
[node name="AddressLabel" type="Label" parent="Paper/Margin/Layout"]
[node name="ContentPanel" type="PanelContainer" parent="MainPanel/OuterMargin/Layout"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 474)
layout_mode = 2
theme_override_colors/font_color = Color(0.902, 0.969, 0.969, 1)
size_flags_vertical = 3
[node name="ContentMargin" type="MarginContainer" parent="MainPanel/OuterMargin/Layout/ContentPanel"]
layout_mode = 2
theme_override_constants/margin_left = 28
theme_override_constants/margin_top = 20
theme_override_constants/margin_right = 28
theme_override_constants/margin_bottom = 20
[node name="ContentLayout" type="VBoxContainer" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin"]
layout_mode = 2
theme_override_constants/separation = 12
[node name="PageStack" type="Control" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout"]
layout_mode = 2
size_flags_vertical = 3
[node name="ListContent" type="VBoxContainer" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/separation = 10
[node name="ListTitle" type="Label" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/ListContent"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 28)
layout_mode = 2
theme_override_font_sizes/font_size = 20
text = "public rooms"
[node name="ServerList" type="ItemList" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/ListContent"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 180)
layout_mode = 2
size_flags_vertical = 3
theme_override_font_sizes/font_size = 17
text = "server address"
horizontal_alignment = 1
[node name="Address" type="LineEdit" parent="Paper/Margin/Layout"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 42)
layout_mode = 2
theme_override_colors/font_color = Color(0.96, 0.93, 0.82, 1)
theme_override_colors/font_uneditable_color = Color(0.624, 0.812, 0.824, 1)
theme_override_colors/font_selected_color = Color(1, 0.98, 0.9, 1)
theme_override_colors/font_placeholder_color = Color(0.624, 0.812, 0.824, 0.78)
theme_override_colors/caret_color = Color(0.902, 0.969, 0.969, 1)
theme_override_colors/selection_color = Color(0.2, 0.48, 0.59, 0.9)
theme_override_font_sizes/font_size = 19
theme_override_styles/normal = SubResource("StyleBox_input")
theme_override_styles/focus = SubResource("StyleBox_input_focus")
theme_override_styles/read_only = SubResource("StyleBox_input_read_only")
placeholder_text = "example.net or 192.168.1.50:7777"
alignment = 1
max_length = 300
[node name="AddressHelper" type="Label" parent="Paper/Margin/Layout"]
unique_name_in_owner = true
layout_mode = 2
theme_override_colors/font_color = Color(0.624, 0.812, 0.824, 1)
theme_override_font_sizes/font_size = 13
text = "Hostname, IPv4, or [IPv6]. Port 7777 is used when omitted; include the port shown by a host when it differs.\nJoin Now connects once; Save Server stores this address locally."
horizontal_alignment = 1
autowrap_mode = 2
[node name="NameLabel" type="Label" parent="Paper/Margin/Layout"]
unique_name_in_owner = true
visible = false
layout_mode = 2
theme_override_colors/font_color = Color(0.902, 0.969, 0.969, 1)
theme_override_font_sizes/font_size = 17
text = "server name"
horizontal_alignment = 1
[node name="NameEdit" type="LineEdit" parent="Paper/Margin/Layout"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(0, 42)
layout_mode = 2
theme_override_colors/font_color = Color(0.96, 0.93, 0.82, 1)
theme_override_colors/font_uneditable_color = Color(0.624, 0.812, 0.824, 1)
theme_override_colors/font_selected_color = Color(1, 0.98, 0.9, 1)
theme_override_colors/font_placeholder_color = Color(0.624, 0.812, 0.824, 0.78)
theme_override_colors/caret_color = Color(0.902, 0.969, 0.969, 1)
theme_override_colors/selection_color = Color(0.2, 0.48, 0.59, 0.9)
theme_override_font_sizes/font_size = 19
theme_override_styles/normal = SubResource("StyleBox_input")
theme_override_styles/focus = SubResource("StyleBox_input_focus")
theme_override_styles/read_only = SubResource("StyleBox_input_read_only")
placeholder_text = "Friend's server"
alignment = 1
max_length = 80
[node name="NameHelper" type="Label" parent="Paper/Margin/Layout"]
unique_name_in_owner = true
visible = false
layout_mode = 2
theme_override_colors/font_color = Color(0.624, 0.812, 0.824, 1)
theme_override_font_sizes/font_size = 13
text = "Only visible on this device."
horizontal_alignment = 1
[node name="ServerList" type="ItemList" parent="Paper/Margin/Layout"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(0, 145)
layout_mode = 2
theme_override_colors/font_color = Color(0.902, 0.969, 0.969, 1)
theme_override_colors/font_selected_color = Color(0.902, 0.969, 0.969, 1)
theme_override_colors/guide_color = Color(0.624, 0.812, 0.824, 0.22)
theme_override_font_sizes/font_size = 17
theme_override_styles/panel = SubResource("StyleBox_list")
theme_override_styles/focus = SubResource("StyleBox_focus")
theme_override_styles/selected = SubResource("StyleBox_selected")
theme_override_styles/selected_focus = SubResource("StyleBox_selected")
allow_reselect = true
same_column_width = true
[node name="Details" type="Label" parent="Paper/Margin/Layout"]
[node name="DetailsPanel" type="PanelContainer" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/ListContent"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(0, 92)
custom_minimum_size = Vector2(0, 100)
layout_mode = 2
theme_override_colors/font_color = Color(0.902, 0.969, 0.969, 1)
theme_override_font_sizes/font_size = 16
[node name="Details" type="Label" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/ListContent/DetailsPanel"]
unique_name_in_owner = true
layout_mode = 2
theme_override_font_sizes/font_size = 15
text = "Select a server."
horizontal_alignment = 1
vertical_alignment = 1
autowrap_mode = 2
[node name="Status" type="Label" parent="Paper/Margin/Layout"]
[node name="DirectContent" type="VBoxContainer" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 38)
visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/separation = 10
[node name="AddressLabel" type="Label" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/DirectContent"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 28)
layout_mode = 2
theme_override_colors/font_color = Color(0.902, 0.969, 0.969, 1)
theme_override_font_sizes/font_size = 15
theme_override_styles/normal = SubResource("StyleBox_status")
text = "Direct UDP connection • default port 7777"
theme_override_font_sizes/font_size = 20
text = "server address"
[node name="Address" type="LineEdit" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/DirectContent"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 46)
layout_mode = 2
focus_mode = 2
theme_override_font_sizes/font_size = 19
placeholder_text = "example.net or 192.168.1.50:7777"
alignment = 1
max_length = 300
[node name="AddressHelper" type="Label" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/DirectContent"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 48)
layout_mode = 2
theme_override_font_sizes/font_size = 13
text = "Hostname, IPv4, or [IPv6]. Port 7777 is used when omitted; include the port shown by a host when it differs.\nJoin Now connects once; Save Server stores this address locally."
horizontal_alignment = 1
vertical_alignment = 1
autowrap_mode = 2
[node name="SessionSummary" type="Label" parent="Paper/Margin/Layout"]
[node name="NameLabel" type="Label" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/DirectContent"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(0, 24)
layout_mode = 2
theme_override_font_sizes/font_size = 16
text = "server name"
[node name="NameEdit" type="LineEdit" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/DirectContent"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(0, 46)
layout_mode = 2
focus_mode = 2
theme_override_font_sizes/font_size = 19
placeholder_text = "Friend's server"
alignment = 1
max_length = 80
[node name="NameHelper" type="Label" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/DirectContent"]
unique_name_in_owner = true
visible = false
layout_mode = 2
theme_override_colors/font_color = Color(0.624, 0.812, 0.824, 1)
theme_override_font_sizes/font_size = 15
text = "1 / 8 players"
theme_override_font_sizes/font_size = 13
text = "Only visible on this device."
horizontal_alignment = 1
[node name="Actions" type="HBoxContainer" parent="Paper/Margin/Layout"]
[node name="Spacer" type="Control" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/DirectContent"]
layout_mode = 2
theme_override_constants/separation = 7
size_flags_vertical = 3
[node name="Actions" type="HBoxContainer" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 46)
layout_mode = 2
theme_override_constants/separation = 10
alignment = 1
[node name="RefreshButton" type="Button" parent="Paper/Margin/Layout/Actions"]
[node name="RefreshButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/Actions"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(82, 72)
custom_minimum_size = Vector2(120, 46)
layout_mode = 2
focus_mode = 2
text = "refresh"
[node name="JoinButton" type="Button" parent="Paper/Margin/Layout/Actions"]
[node name="JoinButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/Actions"]
unique_name_in_owner = true
custom_minimum_size = Vector2(82, 72)
custom_minimum_size = Vector2(120, 46)
layout_mode = 2
focus_mode = 2
text = "join"
[node name="SaveButton" type="Button" parent="Paper/Margin/Layout/Actions"]
[node name="SaveButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/Actions"]
unique_name_in_owner = true
custom_minimum_size = Vector2(82, 72)
custom_minimum_size = Vector2(130, 46)
layout_mode = 2
text = "save\nserver"
focus_mode = 2
text = "save server"
[node name="EditButton" type="Button" parent="Paper/Margin/Layout/Actions"]
[node name="EditButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/Actions"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(76, 68)
custom_minimum_size = Vector2(110, 46)
layout_mode = 2
focus_mode = 2
text = "edit"
[node name="FavoriteButton" type="Button" parent="Paper/Margin/Layout/Actions"]
[node name="FavoriteButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/Actions"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(88, 68)
custom_minimum_size = Vector2(130, 46)
layout_mode = 2
focus_mode = 2
text = "favorite"
[node name="DeleteButton" type="Button" parent="Paper/Margin/Layout/Actions"]
[node name="DeleteButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/Actions"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(82, 68)
custom_minimum_size = Vector2(110, 46)
layout_mode = 2
focus_mode = 2
text = "delete"
[node name="CancelButton" type="Button" parent="Paper/Margin/Layout/Actions"]
[node name="CancelButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/Actions"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(76, 68)
custom_minimum_size = Vector2(120, 46)
layout_mode = 2
focus_mode = 2
text = "cancel"
[node name="BackButton" type="Button" parent="Paper/Margin/Layout/Actions"]
unique_name_in_owner = true
custom_minimum_size = Vector2(76, 68)
[node name="FooterGroup" type="MarginContainer" parent="MainPanel/OuterMargin/Layout"]
layout_mode = 2
theme_override_constants/margin_top = 34
[node name="FooterLayout" type="VBoxContainer" parent="MainPanel/OuterMargin/Layout/FooterGroup"]
layout_mode = 2
theme_override_constants/separation = 8
[node name="InfoRow" type="HBoxContainer" parent="MainPanel/OuterMargin/Layout/FooterGroup/FooterLayout"]
layout_mode = 2
theme_override_constants/separation = 12
[node name="Status" type="Label" parent="MainPanel/OuterMargin/Layout/FooterGroup/FooterLayout/InfoRow"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 24)
layout_mode = 2
size_flags_horizontal = 3
theme_override_font_sizes/font_size = 14
text = "looking for public rooms…"
vertical_alignment = 1
text_overrun_behavior = 3
[node name="SessionSummary" type="Label" parent="MainPanel/OuterMargin/Layout/FooterGroup/FooterLayout/InfoRow"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(210, 24)
layout_mode = 2
theme_override_font_sizes/font_size = 14
text = "1 / 8 players"
horizontal_alignment = 2
vertical_alignment = 1
[node name="Footer" type="HBoxContainer" parent="MainPanel/OuterMargin/Layout/FooterGroup/FooterLayout"]
layout_mode = 2
alignment = 2
[node name="BackButton" type="Button" parent="MainPanel/OuterMargin/Layout/FooterGroup/FooterLayout/Footer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(150, 46)
layout_mode = 2
focus_mode = 2
text = "back"
[node name="DeleteConfirmation" parent="." instance=ExtResource("4_confirmation")]