Harden RV interior exits (#127)
This commit is contained in:
parent
62af5e7086
commit
6eacd17846
4 changed files with 319 additions and 26 deletions
|
|
@ -81,20 +81,62 @@ func _run_host() -> void:
|
|||
session.get_local_peer_id(), upgrade_result_id, true
|
||||
)
|
||||
assert(rv_exits[0].x < rv_exits[1].x)
|
||||
var interior_anchor: Vector3 = home_world.get_interior_anchor(
|
||||
host_fingerprint
|
||||
)
|
||||
for exit_position: Vector3 in rv_exits:
|
||||
host_avatar.global_position = (
|
||||
exit_position
|
||||
+ home_world.get_interior_exit_direction_near(
|
||||
var exit_direction: Vector3 = (
|
||||
home_world.get_interior_exit_direction_near(
|
||||
host_fingerprint, exit_position
|
||||
) * 0.05
|
||||
)
|
||||
)
|
||||
assert(home_world.has_avatar_crossed_interior_exit_threshold(
|
||||
var airborne_inside: Vector3 = (
|
||||
exit_position - exit_direction * 0.8 + Vector3.UP * 0.55
|
||||
)
|
||||
var airborne_beyond_trigger: Vector3 = (
|
||||
exit_position
|
||||
+ exit_direction
|
||||
* (HomeWorldService.INTERIOR_EXIT_TRIGGER_DEPTH + 0.8)
|
||||
+ Vector3.UP * 0.75
|
||||
)
|
||||
host_avatar.global_position = airborne_beyond_trigger
|
||||
# The endpoint is deliberately beyond the narrow legacy trigger strip.
|
||||
# Only swept crossing detection can recognize this airborne frame.
|
||||
assert(not home_world.has_avatar_crossed_interior_exit_threshold(
|
||||
host_avatar, host_fingerprint
|
||||
))
|
||||
assert(home_world.has_avatar_crossed_interior_exit_threshold(
|
||||
host_avatar, host_fingerprint, airborne_inside
|
||||
))
|
||||
var wall_crossing: Vector3 = airborne_beyond_trigger + Vector3(
|
||||
0.0,
|
||||
0.0,
|
||||
HomeWorldService.INTERIOR_EXIT_DOORWAY_HALF_WIDTH + 0.5,
|
||||
)
|
||||
host_avatar.global_position = wall_crossing
|
||||
assert(not home_world.has_avatar_crossed_interior_exit_threshold(
|
||||
host_avatar,
|
||||
host_fingerprint,
|
||||
airborne_inside + Vector3(
|
||||
0.0,
|
||||
0.0,
|
||||
HomeWorldService.INTERIOR_EXIT_DOORWAY_HALF_WIDTH + 0.5,
|
||||
),
|
||||
))
|
||||
host_avatar.global_position = rv_exits[0] + Vector3(0.0, 0.0, 1.1)
|
||||
assert(not home_world.has_avatar_crossed_interior_exit_threshold(
|
||||
host_avatar, host_fingerprint
|
||||
))
|
||||
host_avatar.global_position = interior_anchor + Vector3(
|
||||
0.0, -HomeWorldService.INTERIOR_VOID_FALL_DEPTH - 0.1, 0.0
|
||||
)
|
||||
assert(home_world.is_avatar_below_interior_floor(
|
||||
host_avatar, host_fingerprint
|
||||
))
|
||||
host_avatar.global_position = interior_anchor
|
||||
assert(not home_world.is_avatar_below_interior_floor(
|
||||
host_avatar, host_fingerprint
|
||||
))
|
||||
var presentations: Dictionary = home_world.get(
|
||||
"_presentations_by_fingerprint"
|
||||
)
|
||||
|
|
@ -111,9 +153,79 @@ func _run_host() -> void:
|
|||
var wall_shape := wall_collision.get_child(0) as CollisionShape3D
|
||||
assert(wall_shape != null)
|
||||
assert((wall_shape.shape as ConcavePolygonShape3D).backface_collision)
|
||||
host_avatar.global_position = host_spawn.origin
|
||||
for door_index: int in rv_exits.size():
|
||||
var door_name: String = (
|
||||
"WallWestDoor" if door_index == 0 else "WallEastDoor"
|
||||
)
|
||||
var door_mesh := host_interior.find_child(
|
||||
door_name, true, false
|
||||
) as MeshInstance3D
|
||||
assert(door_mesh != null and door_mesh.mesh != null)
|
||||
var authored_door_center: Vector3 = (
|
||||
door_mesh.global_transform * door_mesh.get_aabb().get_center()
|
||||
)
|
||||
assert(absf(authored_door_center.z - rv_exits[door_index].z) < 0.05)
|
||||
var rv_host_spawn: Transform3D = home_world.get_exterior_spawn_transform(
|
||||
host_fingerprint
|
||||
)
|
||||
host_avatar.global_position = rv_host_spawn.origin
|
||||
assert(network_home.request_enter(host_fingerprint))
|
||||
await physics_frame
|
||||
assert(await _wait_for_home_entry(
|
||||
main, network_home, host_fingerprint
|
||||
))
|
||||
var water_recovery := main.get_node(
|
||||
"%WaterRecovery"
|
||||
) as WaterRecoveryController
|
||||
assert(not water_recovery.is_recovery_enabled())
|
||||
for exit_position: Vector3 in rv_exits:
|
||||
var exit_direction: Vector3 = (
|
||||
home_world.get_interior_exit_direction_near(
|
||||
host_fingerprint, exit_position
|
||||
)
|
||||
)
|
||||
var airborne_inside: Vector3 = (
|
||||
exit_position - exit_direction * 0.8 + Vector3.UP * 0.55
|
||||
)
|
||||
var airborne_outside: Vector3 = (
|
||||
exit_position
|
||||
+ exit_direction
|
||||
* (HomeWorldService.INTERIOR_EXIT_TRIGGER_DEPTH + 0.8)
|
||||
+ Vector3.UP * 0.75
|
||||
)
|
||||
main.set("_home_exit_tracked_owner", host_fingerprint)
|
||||
main.set("_home_exit_previous_position", airborne_inside)
|
||||
host_avatar.global_position = airborne_outside
|
||||
host_avatar.velocity = exit_direction * host_avatar.sprint_speed
|
||||
host_avatar.velocity.y = 2.0
|
||||
main.call("_maybe_begin_home_exit_transition")
|
||||
assert(bool(main.get("_home_exit_transition_active")))
|
||||
assert(not water_recovery.is_recovery_active())
|
||||
assert(await _wait_for_home_exit(main, network_home))
|
||||
assert(water_recovery.is_recovery_enabled())
|
||||
# Fade-in gives gravity time to settle the capsule from the authored
|
||||
# 0.25 m spawn lift. The horizontal authoritative target remains exact.
|
||||
assert(_same_door_horizontal_position(
|
||||
host_avatar.global_position, rv_host_spawn.origin
|
||||
))
|
||||
assert(absf(
|
||||
host_avatar.global_position.y - rv_host_spawn.origin.y
|
||||
) < 0.6)
|
||||
assert(network_home.request_enter(host_fingerprint))
|
||||
assert(await _wait_for_home_entry(
|
||||
main, network_home, host_fingerprint
|
||||
))
|
||||
assert(not water_recovery.is_recovery_enabled())
|
||||
# If imported collision ever regresses, falling beneath an active room uses
|
||||
# the same authoritative home exit instead of starting world-water recovery.
|
||||
host_avatar.global_position = interior_anchor + Vector3(
|
||||
0.0, -HomeWorldService.INTERIOR_VOID_FALL_DEPTH - 0.1, 0.0
|
||||
)
|
||||
main.call("_maybe_begin_home_exit_transition")
|
||||
assert(bool(main.get("_home_exit_transition_active")))
|
||||
assert(not water_recovery.is_recovery_active())
|
||||
main.call("_cancel_home_exit_transition", true)
|
||||
host_avatar.global_position = interior_anchor
|
||||
main.call("_reset_home_exit_position_tracking", host_fingerprint)
|
||||
|
||||
var remote_peer_id: int = await _wait_for_remote_peer(session)
|
||||
assert(remote_peer_id > 1)
|
||||
|
|
@ -153,6 +265,7 @@ func _run_host() -> void:
|
|||
):
|
||||
await process_frame
|
||||
assert(network_home.get_local_home_owner_fingerprint().is_empty())
|
||||
assert(water_recovery.is_recovery_enabled())
|
||||
var visibility_deadline: int = Time.get_ticks_msec() + 1000
|
||||
while (
|
||||
Time.get_ticks_msec() < visibility_deadline
|
||||
|
|
@ -263,6 +376,37 @@ func _wait_for_home(
|
|||
return false
|
||||
|
||||
|
||||
func _wait_for_home_entry(
|
||||
main: Node,
|
||||
network_home: NetworkHomeService,
|
||||
fingerprint: String,
|
||||
) -> bool:
|
||||
var deadline: int = Time.get_ticks_msec() + 5000
|
||||
while Time.get_ticks_msec() < deadline:
|
||||
await process_frame
|
||||
if (
|
||||
network_home.get_local_home_owner_fingerprint() == fingerprint
|
||||
and not bool(main.get("_home_entry_transition_active"))
|
||||
):
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _wait_for_home_exit(
|
||||
main: Node,
|
||||
network_home: NetworkHomeService,
|
||||
) -> bool:
|
||||
var deadline: int = Time.get_ticks_msec() + 5000
|
||||
while Time.get_ticks_msec() < deadline:
|
||||
await process_frame
|
||||
if (
|
||||
network_home.get_local_home_owner_fingerprint().is_empty()
|
||||
and not bool(main.get("_home_exit_transition_active"))
|
||||
):
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _faces_away_from_home(
|
||||
avatar: Player,
|
||||
home_world: HomeWorldService,
|
||||
|
|
@ -292,12 +436,17 @@ func _wait_for_remote_peer(session: NetworkSession) -> int:
|
|||
|
||||
func _same_door_position(first: Vector3, second: Vector3) -> bool:
|
||||
return (
|
||||
Vector2(first.x, first.z).distance_to(Vector2(second.x, second.z))
|
||||
< 0.08
|
||||
_same_door_horizontal_position(first, second)
|
||||
and absf(first.y - second.y) < 0.3
|
||||
)
|
||||
|
||||
|
||||
func _same_door_horizontal_position(first: Vector3, second: Vector3) -> bool:
|
||||
return Vector2(first.x, first.z).distance_to(
|
||||
Vector2(second.x, second.z)
|
||||
) < 0.08
|
||||
|
||||
|
||||
func _cleanup(main: Node, session: NetworkSession) -> void:
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue