682f1f89f7
Made the multiplayer core actually work (it had never run a real sim): - project.godot: physics pinned to 30 Hz -- the shared sim/snapshot/prediction rate. - server.gd: loads the world's level (real ground + collision), spawns a server Player per peer at the level's PlayerSpawn, broadcasts a full snapshot every physics frame with each peer's state AND last_seq (the last input seq applied for that peer). Accepts `--port/--world/--status-file` args (status file = player count for a future idle reaper); defaults keep `godot res://scenes/server.tscn` working standalone. - player_spawner.gd (server Player): rewrote -- drains its whole input queue each physics frame in seq order, integrates gravity/walk/jump with the shared constants, move_and_slide(), tracks last_applied_seq. No more no-op process_server_input(). - network_client.gd: rewrote reconciliation -- drops inputs the server has acked (last_seq), re-simulates the still-in-flight ones from the authoritative state, snaps only on real drift. Exposes get_remote_states() (peer_id -> latest snapshot state) for the game to render other players. predict_and_send() now also sends body yaw. - proxies trimmed to the RPC set the rewrite actually uses. - scripts/mp_test_client.gd + run_multiplayer_2p_test.sh: two real client processes vs one real server -- client A sees client B and its own movement round-trips. PASS. - run_checkpoint_tests.py: also run the 2p shell test. smoke_test_network_client 4/4, player 15/15, avatar_in_world 10/10, all green. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015jtxAiu5dAW4WxCNdGkrkJ
12 lines
562 B
GDScript
12 lines
562 B
GDScript
extends Node
|
|
## Client-side proxy for the server's PlayerNode (scripts/player_spawner.gd),
|
|
## attached at runtime as "Player_<own_peer_id>" under the /root/Server proxy.
|
|
##
|
|
## rpc_request_input is the only RPC the client sends. Godot resolves the RPC
|
|
## transfer config from the LOCAL node's declaration and verifies both peers
|
|
## declare the same @rpc set at this path, so it must match player_spawner.gd.
|
|
|
|
@rpc("any_peer", "call_remote", "reliable")
|
|
func rpc_request_input(_input: Dictionary, _seq: int) -> void:
|
|
pass # Real implementation is on the server.
|