Harden multiplayer validation for portable homes

This commit is contained in:
Alexander Sellite 2026-08-30 23:52:25 -04:00
parent d2dce7f900
commit b48cb73f3a
5 changed files with 381 additions and 49 deletions

View file

@ -27,10 +27,12 @@ func _run_host() -> void:
assert(bool(main.call(
"_apply_world", WorldLayout.STARTER_ISLAND, 1, true
)))
assert(session.set_host_world(WorldLayout.STARTER_ISLAND, 1))
assert(session.start_private_host(TEST_PORT))
assert(bool(main.call(
"_prepare_host_world", WorldLayout.STARTER_ISLAND, 1
)))
var save_manager := main.get("_save_manager") as PlayerSaveManager
assert(save_manager.initialize_new_game())
assert(save_manager.initialize_new_game(1, WorldLayout.STARTER_ISLAND))
assert(session.start_private_host(TEST_PORT))
main.call("_enter_gameplay")
await physics_frame
await physics_frame
@ -62,6 +64,40 @@ func _run_host() -> void:
remote_peer_id
)
assert(remote_record != null)
var network_home := main.get_node(
"%NetworkHomeService"
) as NetworkHomeService
var home_world := main.get_node("%HomeWorldService") as HomeWorldService
var spawn_service := main.get_node(
"%PlayerSpawnService"
) as PlayerSpawnService
assert(await _wait_for_home(
network_home, remote_record.identity_fingerprint
))
var remote_avatar: Player = spawn_service.get_avatar(remote_peer_id)
assert(remote_avatar != null)
var exterior_spawn: Transform3D = home_world.get_exterior_spawn_transform(
remote_record.identity_fingerprint
)
var exterior_deadline: int = Time.get_ticks_msec() + 5000
while (
Time.get_ticks_msec() < exterior_deadline
and remote_avatar.global_position.distance_to(exterior_spawn.origin) > 0.25
):
await physics_frame
assert(remote_avatar.global_position.distance_to(exterior_spawn.origin) <= 0.25)
var canvas_state: Dictionary = service.get_canvas_state(canvas_id)
var canvas_origin: Vector3 = SurfaceDrawingProtocol.array_to_vector(
canvas_state["origin"]
)
remote_avatar.global_position = Vector3(
canvas_origin.x + 1.0,
player.global_position.y,
canvas_origin.z,
)
session.publish_authoritative_teleport(remote_peer_id)
for _frame: int in 4:
await physics_frame
assert(session.peer_supports_capability(
remote_peer_id, SurfaceDrawingProtocol.CAPABILITY
))
@ -152,6 +188,9 @@ func _run_host() -> void:
):
await process_frame
assert(service.get_canvas_ids().size() == 1)
# Keep the second stamp observable on the client before the ban removes all
# artwork carrying that participant fingerprint.
await create_timer(1.0).timeout
var player_list := main.get_node(
"%NetworkPlayerListService"
) as NetworkPlayerListService
@ -221,6 +260,20 @@ func _run_client() -> void:
var canvas_id: String = service.get_canvas_ids()[0]
var snapshot: Dictionary = service.get_canvas_state(canvas_id)
assert(str(_find_cell(snapshot, 7, 7).get("color_id", "")) == "coral")
var canvas_origin: Vector3 = SurfaceDrawingProtocol.array_to_vector(
snapshot["origin"]
)
var placement_deadline: int = Time.get_ticks_msec() + 10000
while (
Time.get_ticks_msec() < placement_deadline
and player.global_position.distance_to(canvas_origin)
> NetworkSurfaceDrawingService.MAX_DRAW_DISTANCE + 2.0
):
await physics_frame
assert(
player.global_position.distance_to(canvas_origin)
<= NetworkSurfaceDrawingService.MAX_DRAW_DISTANCE + 2.0
)
assert(service.request_cell_edits(canvas_id, [{
"x": 7,
"y": 7,
@ -381,3 +434,18 @@ func _create_initialized_main() -> Node:
await process_frame
assert(bool(main.get("_application_initialized")))
return main
func _wait_for_home(
network_home: NetworkHomeService,
fingerprint: String,
) -> bool:
var deadline: int = Time.get_ticks_msec() + 10000
while Time.get_ticks_msec() < deadline:
await process_frame
var manifests: Dictionary = network_home.get(
"_manifests_by_fingerprint"
)
if manifests.has(fingerprint):
return true
return false