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

@ -25,13 +25,60 @@ func _run() -> void:
_validate_mail_round_trip()
_validate_collection_mastery()
_validate_version_four_migration()
assert(NetworkProtocol.PROTOCOL_VERSION == 9)
assert(NetworkProtocol.ENET_CHANNEL_COUNT == 10)
_validate_fishing_protocol_v2()
assert(NetworkProtocol.PROTOCOL_VERSION == 10)
assert(NetworkProtocol.ENET_CHANNEL_COUNT == 17)
assert(NetworkProtocol.MOVEMENT_ANIMATION_CHANNEL == 11)
assert(
NetworkProtocol.MOVEMENT_RECONCILIATION_CAPABILITY
== "movement_reconciliation_v2"
)
assert(
NetworkProtocol.FISHING_REPLICATION_CAPABILITY
== "fishing_replication_v2"
)
assert(NetworkProtocol.FISH_QUALITY_CAPABILITY == "fish_quality_v1")
print("Fish quality validation: PASS")
quit()
func _validate_fishing_protocol_v2() -> void:
var request: Dictionary = {
"request_id": "cast-1",
"session_id": "session-1",
"origin": [0.0, 1.0, 0.0],
"target": [0.0, 0.0, -4.0],
"charge": 0.5,
"rod_id": "basic_fishing_rod",
"reel_speed": 0.2,
"barrier_damage": 1,
"bite_multiplier": 1.0,
"rarity_multipliers": [],
"discovered_fish_ids": [],
"capacity_available": true,
"movement_sequence": 17,
}
assert(NetworkFishingProtocol.validate_cast_request(request).is_empty())
var missing_sequence: Dictionary = request.duplicate(true)
missing_sequence.erase("movement_sequence")
assert(
NetworkFishingProtocol.validate_cast_request(missing_sequence)
== "Malformed fishing request."
)
var invalid_sequence: Dictionary = request.duplicate(true)
invalid_sequence["movement_sequence"] = -1
assert(
NetworkFishingProtocol.validate_cast_request(invalid_sequence)
== "Fishing request values are outside allowed limits."
)
assert(NetworkFishingProtocol.OBSERVER_SNAPSHOT_CHANNEL == 10)
assert(NetworkWorldSpawnProtocol.SNAPSHOT_CHANNEL == 15)
assert(
NetworkWorldSpawnProtocol.SNAPSHOT_CHANNEL
!= NetworkFishingProtocol.SNAPSHOT_CHANNEL
)
func _validate_tiers_and_distribution() -> void:
assert(FishQualityType.TIER_COUNT == 5)
assert(FishQualityType.display_name(0) == "boring")
@ -194,7 +241,7 @@ func _validate_barrier_challenge_curve() -> void:
func _validate_fight_pacing_and_reel_upgrades() -> void:
assert(is_equal_approx(CatchController.CHASE_SPEED, 0.07))
assert(is_equal_approx(CatchController.CHASE_START_DELAY, 1.0))
assert(is_equal_approx(CatchController.CHASE_START_DELAY, 1.5))
assert(is_equal_approx(CatchController.CHASE_START_OFFSET, 0.04))
assert(is_equal_approx(Player.BASE_REEL_SPEED, 0.16))
@ -401,6 +448,11 @@ func _validate_collection_mastery() -> void:
collection.get_quality_mask(&"bluegill")
== FishQualityType.ALL_TIERS_MASK
)
assert(collection.get_catch_count(&"bluegill") == 0)
collection.record_catch(&"bluegill", FishQualityType.Tier.BORING)
collection.record_catch(&"bluegill", FishQualityType.Tier.SHINY)
assert(collection.get_catch_count(&"bluegill") == 2)
assert(int(collection.get_catch_counts()[&"bluegill"]) == 2)
collection.queue_free()