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

@ -68,6 +68,7 @@ func _run() -> void:
configured_generator.elevated_cliff_double_third_tier_chance = 0.0
root.add_child(region)
await process_frame
assert(region.generate_world(FIRST_SEED))
await physics_frame
var generator := region.get_node(
@ -348,6 +349,27 @@ func _validate_generated_region(
generator.get_generated_chunks_root().get_child_count()
== expected_chunk_count
)
var generated_root := generator.get_generated_chunks_root()
var terrain_collision_batches := generated_root.find_children(
"TerrainCollisionBatch_*",
"StaticBody3D",
true,
false,
)
assert(not terrain_collision_batches.is_empty())
assert(
terrain_collision_batches.size()
<= ceili(float(generator.grid_size.x) / generator.collision_batch_size)
* ceili(float(generator.grid_size.y) / generator.collision_batch_size)
)
assert(
generated_root.find_children(
"TerrainCollision",
"StaticBody3D",
true,
false,
).is_empty()
)
assert(
generator.get_primary_terrain_meshes().size()
== (
@ -769,7 +791,6 @@ func _validate_elevated_cliff_feature(
stable_id,
)
assert(source_mesh != null and source_mesh.mesh != null)
assert(source_mesh.has_node("TerrainCollision"))
continue
layered_count += 1
var base_layer := chunk_root.get_node_or_null("TerrainBaseLayer")
@ -799,8 +820,6 @@ func _validate_elevated_cliff_feature(
)
assert(base_mesh != null and base_mesh.mesh != null)
assert(overlay_mesh != null and overlay_mesh.mesh != null)
assert(base_mesh.has_node("TerrainBaseLayerCollision"))
assert(overlay_mesh.has_node("TerrainCollision"))
assert(layered_count == (29 if has_coastal_feature else 23))
var stacked_keys := generator.stacked_elevated_placement_keys()
assert(stacked_keys.size() in [0, 4])
@ -837,7 +856,6 @@ func _validate_elevated_cliff_feature(
stacked_id,
)
assert(stacked_mesh != null and stacked_mesh.mesh != null)
assert(stacked_mesh.has_node("TerrainCollision"))
assert(stacked_count == 4)
@ -1056,7 +1074,11 @@ func _validate_decoration_transform(
else:
assert(collision == null)
var query := PhysicsRayQueryParameters3D.create(
prop.global_position + Vector3.UP * 8.0,
# Stay below neighboring cliff overhangs while still beginning above the
# authored walkable surface. Regional collision batches intentionally
# keep every original shape on one body, so excluding an overhang body
# would also exclude the ground beneath the prop.
prop.global_position + Vector3.UP * 0.1,
prop.global_position + Vector3.DOWN * 8.0,
1,
)
@ -1361,7 +1383,10 @@ func _validate_pond_collision(
var hit := region.get_world_3d().direct_space_state.intersect_ray(query)
assert(not hit.is_empty())
var collider := hit.get("collider") as Node
assert(collider != null and collider.get_parent() == pond)
assert(
collider != null
and collider.has_meta(&"terrain_collision_batch")
)
func _decoration_group_count(