Harden multiplayer validation for portable homes
This commit is contained in:
parent
d2dce7f900
commit
b48cb73f3a
5 changed files with 381 additions and 49 deletions
|
|
@ -593,15 +593,22 @@ func _run_host() -> void:
|
|||
var main: Node = await _create_initialized_main()
|
||||
var session := main.get_node("%NetworkSession") as NetworkSession
|
||||
var save_manager := main.get("_save_manager") as PlayerSaveManager
|
||||
assert(session.set_host_world(
|
||||
assert(bool(main.call(
|
||||
"_apply_world",
|
||||
WorldLayout.STARTER_ISLAND,
|
||||
NetworkProtocol.DEFAULT_WORLD_SEED,
|
||||
))
|
||||
assert(session.start_private_host(TEST_PORT))
|
||||
true,
|
||||
)))
|
||||
assert(bool(main.call(
|
||||
"_prepare_host_world",
|
||||
WorldLayout.STARTER_ISLAND,
|
||||
NetworkProtocol.DEFAULT_WORLD_SEED,
|
||||
)))
|
||||
assert(save_manager.initialize_new_game(
|
||||
NetworkProtocol.DEFAULT_WORLD_SEED,
|
||||
WorldLayout.STARTER_ISLAND,
|
||||
))
|
||||
assert(session.start_private_host(TEST_PORT))
|
||||
main.call("_enter_gameplay")
|
||||
for _frame: int in 4:
|
||||
await physics_frame
|
||||
|
|
@ -613,31 +620,40 @@ func _run_host() -> void:
|
|||
# to settle before emitting the one-shot locomotion/action sequence.
|
||||
await create_timer(3.0).timeout
|
||||
var player := main.get("_player") as Player
|
||||
var world := main.get_node("TestWorld") as TestWorld
|
||||
player.configure_network_remote(true)
|
||||
player.apply_authoritative_network_input(_movement_input(1, true))
|
||||
await create_timer(2.5).timeout
|
||||
player.apply_authoritative_network_input(_movement_input(2, false))
|
||||
await create_timer(2.5).timeout
|
||||
player.apply_authoritative_network_input(
|
||||
_movement_input(3, false, true, true)
|
||||
await _reset_locomotion_test_position(player, session, world)
|
||||
var input_sequence: int = 1
|
||||
input_sequence = await _sustain_locomotion_input(
|
||||
player, input_sequence, 1.5, true
|
||||
)
|
||||
await create_timer(2.0).timeout
|
||||
player.apply_authoritative_network_input(
|
||||
_movement_input(4, false, false, true)
|
||||
await _reset_locomotion_test_position(player, session, world)
|
||||
input_sequence = await _sustain_locomotion_input(
|
||||
player, input_sequence, 1.5, false
|
||||
)
|
||||
await create_timer(2.0).timeout
|
||||
player.apply_authoritative_network_input(
|
||||
_movement_input(5, false, false, true, &"draw", 1)
|
||||
await _reset_locomotion_test_position(player, session, world)
|
||||
input_sequence = await _sustain_locomotion_input(
|
||||
player, input_sequence, 1.5, false, true, true
|
||||
)
|
||||
input_sequence = await _sustain_locomotion_input(
|
||||
player, input_sequence, 1.5, false, false, true
|
||||
)
|
||||
player.apply_authoritative_network_input(
|
||||
_movement_input(input_sequence, false, false, true, &"draw", 1)
|
||||
)
|
||||
input_sequence += 1
|
||||
await create_timer(1.0).timeout
|
||||
player.apply_authoritative_network_input(
|
||||
_movement_input(6, false, false, true, &"strike", 2, true)
|
||||
_movement_input(
|
||||
input_sequence, false, false, true, &"strike", 2, true
|
||||
)
|
||||
)
|
||||
input_sequence += 1
|
||||
await create_timer(2.0).timeout
|
||||
player.apply_authoritative_network_input(
|
||||
_movement_input(7, false, false, false, &"", 3)
|
||||
_movement_input(input_sequence, false, false, false, &"", 3)
|
||||
)
|
||||
var disconnect_deadline: int = Time.get_ticks_msec() + 8000
|
||||
var disconnect_deadline: int = Time.get_ticks_msec() + 15000
|
||||
while (
|
||||
Time.get_ticks_msec() < disconnect_deadline
|
||||
and session.is_authenticated_peer(remote_peer_id)
|
||||
|
|
@ -686,12 +702,27 @@ func _run_client() -> void:
|
|||
var saw_net_strike_paused: bool = false
|
||||
var saw_animation_advance: bool = false
|
||||
var saw_dust: bool = false
|
||||
var observed_animations: Dictionary = {}
|
||||
var observed_locomotion_states: Dictionary = {}
|
||||
var maximum_sneak_speed: float = 0.0
|
||||
var previous_animation: StringName = &""
|
||||
var previous_animation_position: float = -1.0
|
||||
var observation_deadline: int = Time.get_ticks_msec() + 18000
|
||||
var observation_deadline: int = Time.get_ticks_msec() + 22000
|
||||
while Time.get_ticks_msec() < observation_deadline:
|
||||
await process_frame
|
||||
var current_animation: StringName = animation_player.current_animation
|
||||
observed_animations[current_animation] = true
|
||||
var target_locomotion_state: int = int(host_avatar.get(
|
||||
"_network_target_locomotion_state"
|
||||
))
|
||||
observed_locomotion_states[target_locomotion_state] = true
|
||||
if target_locomotion_state == Player.LocomotionState.SNEAKING:
|
||||
maximum_sneak_speed = maxf(
|
||||
maximum_sneak_speed,
|
||||
Vector2(
|
||||
host_avatar.velocity.x, host_avatar.velocity.z
|
||||
).length(),
|
||||
)
|
||||
saw_running = saw_running or current_animation.begins_with("running")
|
||||
saw_walking = saw_walking or current_animation.begins_with("walking")
|
||||
saw_sneaking = saw_sneaking or current_animation == &"sneaking"
|
||||
|
|
@ -732,15 +763,44 @@ func _run_client() -> void:
|
|||
and saw_dust
|
||||
):
|
||||
break
|
||||
assert(saw_running)
|
||||
assert(saw_walking)
|
||||
assert(saw_sneaking)
|
||||
assert(saw_idle_sneak)
|
||||
assert(saw_net_draw)
|
||||
assert(saw_net_strike)
|
||||
assert(saw_net_strike_paused)
|
||||
assert(saw_animation_advance)
|
||||
assert(saw_dust)
|
||||
var missing_observations: Array[String] = []
|
||||
if not saw_running:
|
||||
missing_observations.append("running")
|
||||
if not saw_walking:
|
||||
missing_observations.append("walking")
|
||||
if not saw_sneaking:
|
||||
missing_observations.append("sneaking")
|
||||
if not saw_idle_sneak:
|
||||
missing_observations.append("idle_sneak")
|
||||
if not saw_net_draw:
|
||||
missing_observations.append("net_draw")
|
||||
if not saw_net_strike:
|
||||
missing_observations.append("net_strike")
|
||||
if not saw_net_strike_paused:
|
||||
missing_observations.append("net_strike_paused")
|
||||
if not saw_animation_advance:
|
||||
missing_observations.append("animation_advance")
|
||||
if not saw_dust:
|
||||
missing_observations.append("sprint_dust")
|
||||
if not missing_observations.is_empty():
|
||||
push_error(
|
||||
(
|
||||
"Missing movement observations %s; observed animations: %s; "
|
||||
+ "locomotion states: %s; maximum sneak speed: %.3f"
|
||||
) % [
|
||||
missing_observations,
|
||||
observed_animations.keys(),
|
||||
observed_locomotion_states.keys(),
|
||||
maximum_sneak_speed,
|
||||
]
|
||||
)
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit(1)
|
||||
return
|
||||
print("Movement multiplayer client validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
|
|
@ -778,6 +838,39 @@ func _movement_input(
|
|||
}
|
||||
|
||||
|
||||
func _sustain_locomotion_input(
|
||||
player: Player,
|
||||
starting_sequence: int,
|
||||
duration_seconds: float,
|
||||
sprinting: bool,
|
||||
moving: bool = true,
|
||||
sneaking: bool = false,
|
||||
) -> int:
|
||||
var sequence: int = starting_sequence
|
||||
var deadline: int = (
|
||||
Time.get_ticks_msec() + roundi(duration_seconds * 1000.0)
|
||||
)
|
||||
while Time.get_ticks_msec() < deadline:
|
||||
player.apply_authoritative_network_input(
|
||||
_movement_input(sequence, sprinting, moving, sneaking)
|
||||
)
|
||||
sequence += 1
|
||||
await create_timer(0.1).timeout
|
||||
return sequence
|
||||
|
||||
|
||||
func _reset_locomotion_test_position(
|
||||
player: Player,
|
||||
session: NetworkSession,
|
||||
world: TestWorld,
|
||||
) -> void:
|
||||
player.velocity = Vector3.ZERO
|
||||
player.global_transform = world.get_player_spawn_transform()
|
||||
session.publish_authoritative_teleport(1)
|
||||
for _frame: int in 4:
|
||||
await physics_frame
|
||||
|
||||
|
||||
func _create_initialized_main() -> Node:
|
||||
root.size = Vector2i(1280, 720)
|
||||
var main: Node = MainScene.instantiate()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue