7ccdd3063a
checkpoint / checkpoint (push) Failing after 1m34s
scenes/server_player.tscn was a bare CharacterBody3D with NO CollisionShape3D, so on the server move_and_slide() never hit the ground and is_on_floor() was always false -> the server player fell forever, and the client (which snaps to the server's authoritative position past a drift threshold) fell with it. Give the server player the same CapsuleShape3D (r=0.35, h=1.6) as the client. The 2-player test now also asserts the server keeps the player on the ground (on_floor / min_y), which is how this slipped through -- the tests only checked "position changes" and "sees the other player". Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015jtxAiu5dAW4WxCNdGkrkJ
65 lines
2.1 KiB
GDScript
65 lines
2.1 KiB
GDScript
extends SceneTree
|
|
## One client process for the 2-player multiplayer test
|
|
## (scripts/run_multiplayer_2p_test.sh). Two real OS processes = real network.
|
|
##
|
|
## godot --headless --path . --script res://scripts/mp_test_client.gd -- --role a --port 7777
|
|
##
|
|
## role "a": moves forward for ~2 s, then prints
|
|
## RESULT a remotes=<n> moved=<bool> and exits 0 iff it both moved
|
|
## and saw >=1 remote player.
|
|
## role "b": connects, holds still for ~4 s, prints RESULT b connected exits 0.
|
|
|
|
var role := "b"
|
|
var port := 7777
|
|
|
|
|
|
func _initialize() -> void:
|
|
var args := OS.get_cmdline_user_args()
|
|
for i in args.size():
|
|
if args[i] == "--role" and i + 1 < args.size():
|
|
role = args[i + 1]
|
|
elif args[i] == "--port" and i + 1 < args.size():
|
|
port = int(args[i + 1])
|
|
_run()
|
|
|
|
|
|
func _run() -> void:
|
|
await process_frame
|
|
var net := NetworkClient.new()
|
|
root.add_child(net)
|
|
var ok: bool = await net.connect_to_server("127.0.0.1", port)
|
|
if not ok:
|
|
print("RESULT %s connect_failed" % role)
|
|
quit(1)
|
|
return
|
|
for i in 15:
|
|
await process_frame
|
|
|
|
if role == "b":
|
|
# Hold still and stay connected long enough for A to boot, connect,
|
|
# and observe us (A's Godot startup alone is a couple of seconds).
|
|
print("RESULT b connected")
|
|
for i in 1200:
|
|
await process_frame
|
|
net.disconnect_from_server()
|
|
quit(0)
|
|
return
|
|
|
|
# role a: move forward, watch for a remote and our own displacement, and
|
|
# confirm the server keeps us on the ground (not falling through it).
|
|
var start: Vector3 = net.position
|
|
var max_remotes := 0
|
|
var min_server_y := 1000.0
|
|
for i in 90:
|
|
net.predict_and_send(1.0 / 30.0, 0.0, -1.0, false, 0.0)
|
|
await process_frame
|
|
max_remotes = maxi(max_remotes, net.get_remote_states().size())
|
|
var st: Dictionary = net.get_own_server_state()
|
|
if st.has("position"):
|
|
min_server_y = minf(min_server_y, st["position"].y)
|
|
var moved: bool = net.position.distance_to(start) > 1.0
|
|
var on_floor: bool = min_server_y > -2.0
|
|
print("RESULT a remotes=%d moved=%s on_floor=%s (min_y=%.2f)" % [max_remotes, str(moved), str(on_floor), min_server_y])
|
|
net.disconnect_from_server()
|
|
quit(0 if (moved and max_remotes >= 1 and on_floor) else 1)
|