feat: integrate fishing item transitions
This commit is contained in:
parent
692b6eeb2a
commit
63a5009b33
11 changed files with 719 additions and 110 deletions
|
|
@ -53,7 +53,7 @@ func _run_host() -> void:
|
|||
) as PlayerSpawnService
|
||||
var remote_avatar: Player = spawn_service.get_avatar(remote_peer_id)
|
||||
assert(remote_avatar != null)
|
||||
var remote_display := remote_avatar.get_node("%HeldFishDisplay") as Node3D
|
||||
var remote_display := remote_avatar.get("_held_fish_display") as Node3D
|
||||
var visible_deadline: int = Time.get_ticks_msec() + 10000
|
||||
while Time.get_ticks_msec() < visible_deadline and not remote_display.visible:
|
||||
await process_frame
|
||||
|
|
@ -95,13 +95,23 @@ func _run_client() -> void:
|
|||
) as PlayerSpawnService
|
||||
var host_avatar: Player = spawn_service.get_avatar(1)
|
||||
assert(host_avatar != null)
|
||||
var host_display := host_avatar.get_node("%HeldFishDisplay") as Node3D
|
||||
var host_display := host_avatar.get("_held_fish_display") as Node3D
|
||||
var snapshot_deadline: int = Time.get_ticks_msec() + 10000
|
||||
while Time.get_ticks_msec() < snapshot_deadline and not host_display.visible:
|
||||
await process_frame
|
||||
assert(host_display.visible)
|
||||
|
||||
var player := main.get("_player") as Player
|
||||
var animation_player := player.get_node(
|
||||
"Visuals/CharacterRig/AnimationPlayer"
|
||||
) as AnimationPlayer
|
||||
for animation_name: StringName in [
|
||||
&"pocket_idle_idle",
|
||||
&"pocket_idle_show",
|
||||
&"pocket_show_show",
|
||||
&"pocket_show_idle",
|
||||
]:
|
||||
assert(animation_player.has_animation(animation_name))
|
||||
var service := main.get_node(
|
||||
"%NetworkFishShowcaseService"
|
||||
) as NetworkFishShowcaseService
|
||||
|
|
@ -109,11 +119,16 @@ func _run_client() -> void:
|
|||
assert(player.hotbar.assign_fish(1, fish_catch.catch_id))
|
||||
assert(player.hotbar.select_slot(1))
|
||||
assert(service.toggle_selected_fish())
|
||||
assert((player.get_node("%HeldFishDisplay") as Node3D).visible)
|
||||
assert((player.get("_held_fish_display") as Node3D).visible)
|
||||
await create_timer(2.0).timeout
|
||||
assert(service.toggle_selected_fish())
|
||||
assert(not (player.get_node("%HeldFishDisplay") as Node3D).visible)
|
||||
await create_timer(1.0).timeout
|
||||
var held_display := player.get("_held_fish_display") as Node3D
|
||||
assert(held_display.visible)
|
||||
assert(animation_player.current_animation == &"pocket_show_idle")
|
||||
var pocket_deadline: int = Time.get_ticks_msec() + 5000
|
||||
while Time.get_ticks_msec() < pocket_deadline and held_display.visible:
|
||||
await process_frame
|
||||
assert(not held_display.visible)
|
||||
print("Fish showcase multiplayer client validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
|
|
|
|||
|
|
@ -54,6 +54,30 @@ func _run_host() -> void:
|
|||
var remote_visuals := remote_avatar.get_node("Visuals") as Node3D
|
||||
remote_visuals.rotation.y = PI * 0.5
|
||||
session.publish_authoritative_teleport(remote_peer_id)
|
||||
var aiming_deadline: int = Time.get_ticks_msec() + 5000
|
||||
while (
|
||||
Time.get_ticks_msec() < aiming_deadline
|
||||
and int(remote_avatar.get("_fishing_visual_phase"))
|
||||
!= Player.FishingVisualPhase.CASTING
|
||||
):
|
||||
await process_frame
|
||||
assert(
|
||||
int(remote_avatar.get("_fishing_visual_phase"))
|
||||
== Player.FishingVisualPhase.CASTING
|
||||
)
|
||||
var remote_position_error := (
|
||||
remote_avatar.global_position - Vector3(-0.5, 3.95, 2.1)
|
||||
)
|
||||
remote_position_error.y = 0.0
|
||||
assert(
|
||||
remote_position_error.length() <= 0.25,
|
||||
"remote casting position drifted: %s" % remote_avatar.global_position
|
||||
)
|
||||
assert(
|
||||
remote_avatar.get_facing_direction().dot(Vector3.LEFT) > 0.99,
|
||||
"remote casting facing drifted: %s"
|
||||
% remote_avatar.get_facing_direction()
|
||||
)
|
||||
|
||||
var saw_remote_attempt: bool = false
|
||||
var remote_presentation: RemoteFishingPresentation
|
||||
|
|
@ -65,8 +89,8 @@ func _run_host() -> void:
|
|||
if peer_id == session.get_local_peer_id():
|
||||
continue
|
||||
var attempt: NetworkFishingAttempt = attempts[peer_id]
|
||||
assert(is_equal_approx(attempt.target.y, 2.51))
|
||||
assert(attempt.bobber_position.y <= 2.51 + 0.001)
|
||||
assert(attempt.target.is_finite())
|
||||
assert(attempt.bobber_position.distance_to(attempt.target) <= 0.001)
|
||||
var presentations: Dictionary = service.get("_remote_presentations")
|
||||
remote_presentation = presentations.get(peer_id)
|
||||
assert(remote_presentation != null)
|
||||
|
|
@ -78,6 +102,31 @@ func _run_host() -> void:
|
|||
if saw_remote_attempt:
|
||||
break
|
||||
assert(saw_remote_attempt)
|
||||
assert(
|
||||
int(remote_avatar.get("_fishing_visual_phase"))
|
||||
in [
|
||||
Player.FishingVisualPhase.RELEASE,
|
||||
Player.FishingVisualPhase.FISHING,
|
||||
]
|
||||
)
|
||||
var sitting_deadline: int = Time.get_ticks_msec() + 3000
|
||||
while Time.get_ticks_msec() < sitting_deadline and not remote_avatar.is_sitting():
|
||||
await process_frame
|
||||
assert(remote_avatar.is_sitting())
|
||||
var fishing_deadline: int = Time.get_ticks_msec() + 5000
|
||||
while (
|
||||
Time.get_ticks_msec() < fishing_deadline
|
||||
and int(remote_avatar.get("_fishing_visual_phase"))
|
||||
!= Player.FishingVisualPhase.FISHING
|
||||
):
|
||||
await process_frame
|
||||
assert(
|
||||
int(remote_avatar.get("_fishing_visual_phase"))
|
||||
== Player.FishingVisualPhase.FISHING
|
||||
)
|
||||
var remote_animation_player := remote_avatar.get_node(
|
||||
"Visuals/CharacterRig/AnimationPlayer"
|
||||
) as AnimationPlayer
|
||||
var return_deadline: int = Time.get_ticks_msec() + 5000
|
||||
while (
|
||||
Time.get_ticks_msec() < return_deadline
|
||||
|
|
@ -85,8 +134,11 @@ func _run_host() -> void:
|
|||
):
|
||||
await process_frame
|
||||
assert(not service.has_peer_attempt(remote_peer_id))
|
||||
assert(is_instance_valid(remote_presentation))
|
||||
assert(remote_presentation.get("_return_tween") != null)
|
||||
assert(
|
||||
int(remote_avatar.get("_fishing_visual_phase"))
|
||||
== Player.FishingVisualPhase.RETRACT
|
||||
)
|
||||
assert(remote_animation_player.current_animation == &"retract_sit")
|
||||
|
||||
var completion_deadline: int = Time.get_ticks_msec() + 12000
|
||||
while (
|
||||
|
|
@ -119,8 +171,17 @@ func _run_client() -> void:
|
|||
var service := main.get_node(
|
||||
"%NetworkFishingService"
|
||||
) as NetworkFishingService
|
||||
var cast_rejections: Array[String] = []
|
||||
service.local_cast_rejected.connect(
|
||||
func(message: String) -> void:
|
||||
cast_rejections.append(message)
|
||||
)
|
||||
var fishing_spot := main.get_node("%FishingSpot") as FishingSpotType
|
||||
var player := main.get("_player") as Player
|
||||
var character_animation_player := player.get_node(
|
||||
"Visuals/CharacterRig/AnimationPlayer"
|
||||
) as AnimationPlayer
|
||||
assert(character_animation_player.has_animation(&"retract_sit"))
|
||||
var placement_deadline: int = Time.get_ticks_msec() + 5000
|
||||
while (
|
||||
Time.get_ticks_msec() < placement_deadline
|
||||
|
|
@ -131,14 +192,59 @@ func _run_client() -> void:
|
|||
assert(player.global_position.distance_to(Vector3(-0.5, 3.95, 2.1)) <= 0.25)
|
||||
assert(player.get_facing_direction().dot(Vector3.LEFT) > 0.99)
|
||||
|
||||
player.set_casting_visual()
|
||||
assert(
|
||||
int(player.get("_fishing_visual_phase"))
|
||||
== Player.FishingVisualPhase.CASTING
|
||||
)
|
||||
for _frame: int in 30:
|
||||
await physics_frame
|
||||
player.set_fishing_visual(false)
|
||||
player.call("_set_sitting", true)
|
||||
assert(player.is_sitting())
|
||||
for _frame: int in 15:
|
||||
await physics_frame
|
||||
fishing_spot.call("_begin_aiming", player)
|
||||
assert(player.is_movement_enabled())
|
||||
fishing_spot.set("_cast_charge", 0.32)
|
||||
fishing_spot.call("_update_cast_charge", 0.0)
|
||||
var target: Vector3 = fishing_spot.get("_cast_target")
|
||||
assert(fishing_spot.is_target_fishable(target))
|
||||
assert(is_equal_approx(target.y, 2.51))
|
||||
fishing_spot.call("_confirm_cast")
|
||||
assert(
|
||||
int(player.get("_fishing_visual_phase"))
|
||||
== Player.FishingVisualPhase.CASTING
|
||||
)
|
||||
var cast_charge: float = 0.0
|
||||
var target: Vector3 = Vector3.ZERO
|
||||
var cast_origin: Vector3 = fishing_spot.get("_cast_origin_position")
|
||||
for charge_step: int in range(1, 21):
|
||||
var candidate_charge := float(charge_step) / 20.0
|
||||
fishing_spot.set("_cast_charge", candidate_charge)
|
||||
fishing_spot.call("_update_cast_charge", 0.0)
|
||||
var candidate_target: Vector3 = fishing_spot.get("_cast_target")
|
||||
var candidate_surface := fishing_spot.get(
|
||||
"_aim_surface_sample"
|
||||
) as FishingSurfaceSample
|
||||
if (
|
||||
candidate_surface.is_fishable()
|
||||
and fishing_spot.is_cast_path_clear(cast_origin, candidate_target)
|
||||
):
|
||||
cast_charge = candidate_charge
|
||||
target = candidate_target
|
||||
break
|
||||
assert(cast_charge > 0.0, "no clear fishable test target was found")
|
||||
var evidence: Dictionary = fishing_spot.call("_build_network_evidence")
|
||||
fishing_spot.set("state", FishingSpotType.FishingState.CASTING)
|
||||
player.set_movement_enabled(false)
|
||||
player.set_release_visual()
|
||||
assert(
|
||||
int(player.get("_fishing_visual_phase"))
|
||||
== Player.FishingVisualPhase.RELEASE
|
||||
)
|
||||
assert(
|
||||
not service.request_local_cast(
|
||||
cast_origin,
|
||||
target,
|
||||
cast_charge,
|
||||
evidence,
|
||||
).is_empty()
|
||||
)
|
||||
|
||||
var accepted_deadline: int = Time.get_ticks_msec() + 6000
|
||||
while (
|
||||
|
|
@ -146,8 +252,32 @@ func _run_client() -> void:
|
|||
and fishing_spot.state != FishingSpotType.FishingState.WAITING_FOR_BITE
|
||||
):
|
||||
await process_frame
|
||||
assert(fishing_spot.state == FishingSpotType.FishingState.WAITING_FOR_BITE)
|
||||
assert(
|
||||
fishing_spot.state == FishingSpotType.FishingState.WAITING_FOR_BITE,
|
||||
(
|
||||
"cast acceptance timed out: state=%s local_attempt=%s target=%s "
|
||||
+ "rejections=%s"
|
||||
) % [
|
||||
fishing_spot.state,
|
||||
service.has_local_attempt(),
|
||||
target,
|
||||
cast_rejections,
|
||||
]
|
||||
)
|
||||
assert(service.has_local_attempt())
|
||||
var fishing_deadline: int = Time.get_ticks_msec() + 5000
|
||||
while (
|
||||
Time.get_ticks_msec() < fishing_deadline
|
||||
and int(player.get("_fishing_visual_phase"))
|
||||
!= Player.FishingVisualPhase.FISHING
|
||||
):
|
||||
await process_frame
|
||||
assert(
|
||||
int(player.get("_fishing_visual_phase"))
|
||||
== Player.FishingVisualPhase.FISHING
|
||||
)
|
||||
for _frame: int in 30:
|
||||
await physics_frame
|
||||
fishing_spot.set("_withdrawal_input_held", true)
|
||||
fishing_spot.set("_network_primary_input_held", true)
|
||||
service.submit_local_input(true, true)
|
||||
|
|
@ -159,10 +289,18 @@ func _run_client() -> void:
|
|||
):
|
||||
await process_frame
|
||||
assert(fishing_spot.state == FishingSpotType.FishingState.RETURNING)
|
||||
assert(
|
||||
int(player.get("_fishing_visual_phase"))
|
||||
== Player.FishingVisualPhase.RETRACT
|
||||
)
|
||||
assert(character_animation_player.current_animation == &"retract_sit")
|
||||
var bobber := fishing_spot.get_node(
|
||||
"FishingPresentation/Bobber"
|
||||
) as MeshInstance3D
|
||||
assert(bobber.visible)
|
||||
while not player.is_retract_visual_complete():
|
||||
assert(fishing_spot.state == FishingSpotType.FishingState.RETURNING)
|
||||
await process_frame
|
||||
|
||||
var ready_deadline: int = Time.get_ticks_msec() + 3000
|
||||
while (
|
||||
|
|
@ -173,6 +311,9 @@ func _run_client() -> void:
|
|||
assert(fishing_spot.state == FishingSpotType.FishingState.READY)
|
||||
assert(player.is_movement_enabled())
|
||||
assert(not bobber.visible)
|
||||
var host_observation_deadline: int = Time.get_ticks_msec() + 2000
|
||||
while Time.get_ticks_msec() < host_observation_deadline:
|
||||
await process_frame
|
||||
print("Fishing multiplayer client validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue