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

@ -89,6 +89,7 @@ func _run() -> void:
net_page.call("_select_view", TheNetPage.View.LIFETIME)
await process_frame
_validate_fishnet_bounds(net_page)
await _validate_compact_value_tooltips(net_page)
await _validate_unavailable_fishnet_layout()
var wallet_before: int = player.wallet.get_balance()
@ -287,6 +288,53 @@ func _validate_fishnet_bounds(page: TheNetPage) -> void:
assert(row.size.x <= jobs_scroll.size.x + 0.5)
func _validate_compact_value_tooltips(page: TheNetPage) -> void:
assert(str(page.call("_compact_integer", 2400)) == "2.4k")
assert(str(page.call("_compact_integer", 2500)) == "2.5k")
var list := page.get("_list") as VBoxContainer
assert(list != null)
var jobs: Array[Dictionary] = [{
"title": "compact tooltip check",
"description": "compact values keep their exact values on hover",
"target": 2500,
"progress": 2400,
"fish_coin": 1200,
"experience": 3400,
}]
page.call("_build_job_rows", jobs, "")
await process_frame
var row := list.get_child(list.get_child_count() - 1) as PanelContainer
assert(row != null)
var progress_bar: ProgressBar
var progress_count: Label
var reward: VBoxContainer
for child: Node in row.find_children("*", "ProgressBar", true, false):
progress_bar = child as ProgressBar
break
for child: Node in row.find_children("*", "Label", true, false):
var label := child as Label
if label != null and label.text == "2.4k / 2.5k":
progress_count = label
break
for child: Node in row.find_children("*", "VBoxContainer", true, false):
var candidate := child as VBoxContainer
if candidate != null and candidate.tooltip_text == (
"1200 fish coins · 3400 xp"
):
reward = candidate
break
assert(progress_bar != null)
assert(progress_bar.tooltip_text == "2400 / 2500")
assert(progress_bar.mouse_filter == Control.MOUSE_FILTER_STOP)
assert(progress_count != null)
assert(progress_count.tooltip_text == "2400 / 2500")
assert(progress_count.mouse_filter == Control.MOUSE_FILTER_STOP)
assert(reward != null)
assert(reward.mouse_filter == Control.MOUSE_FILTER_STOP)
row.queue_free()
await process_frame
func _validate_creature_jobs(jobs: PlayerJobService) -> void:
var fish_count: int = 0
var insect_count: int = 0