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

@ -490,7 +490,7 @@ func _validate_remote_presentation() -> void:
await process_frame
var origin: Vector3 = player.get_fishing_rod_tip().global_position
var target: Vector3 = origin + Vector3(-4.0, -0.5, 0.0)
presentation.show_cast(origin, target)
presentation.show_cast(origin, target, "cast-attempt")
var bobber := presentation.get("_bobber") as MeshInstance3D
assert(bobber.visible)
assert(presentation.get("_cast_tween") != null)
@ -500,6 +500,22 @@ func _validate_remote_presentation() -> void:
await create_timer(0.2).timeout
assert(not is_equal_approx(bobber.global_position.y, first_bob_y))
# A client joining after the reliable cast event reconstructs the current
# remote fishing state from the observer summary instead of waiting for the
# next cast. This also covers a bite/fighting transition received by an
# already active observer.
presentation.cleanup()
presentation.synchronize_active("late-attempt", target, false)
assert(bobber.visible)
assert(
int(player.get("_fishing_visual_phase"))
== Player.FishingVisualPhase.FISHING
)
presentation.synchronize_active("late-attempt", target, true)
assert(bool(player.get("_fighting_visual_active")))
presentation.synchronize_active("late-attempt", target, false)
assert(not bool(player.get("_fighting_visual_active")))
var fish_catch := FishCatchType.new()
var fish: FishData = PondPool.candidates.front()
fish_catch.fish = fish