dba865ae4b
- Session autoload: carries {world_id, host, port} from the world browser
to the game scene.
- world_list.gd "Enter World": POST /api/worlds/{id}/join -> Session.begin
-> load game.tscn. On 503 (backend has no orchestration) falls back to
local single-player; other errors surface on the card.
- api_client.gd: join_world().
- game.gd (new, on game.tscn root): local single-player by default; when
Session.active, connects a NetworkClient to the world's dedicated server
and runs networked -- forwards the local Player's input each physics
frame, snaps to the server position past a generous drift threshold
(the Player keeps predicting locally with real collision), renders other
players from snapshots (labelled capsules, lerped -- avatar appearance
sync is a follow-up, the server doesn't replicate loadouts yet), and
returns to the world list on disconnect.
- player.gd: exposes net_input (the input frame it applied) and
apply_server_correction().
- network_client.gd: send_input() + get_own_server_state() for callers that
do their own collision-aware prediction.
- scripts/mp_game_flow_client.gd + run_game_multiplayer_test.sh: two real
clients each register -> join via the API -> game.tscn -> networked;
A sees B and moves. PASS.
Verified end to end against an orchestration-enabled backend. Non-networked
smokes green (enter_world 9/9, world_list 5/5, player 15/15,
avatar_in_world 10/10, main_menu_full_flow 12/12).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015jtxAiu5dAW4WxCNdGkrkJ
59 lines
2.2 KiB
Plaintext
59 lines
2.2 KiB
Plaintext
; Engine configuration file.
|
|
; It's best edited using the editor UI and not directly,
|
|
; but it can also be edited by hand.
|
|
|
|
config_version=5
|
|
|
|
[application]
|
|
|
|
config/name="AGP-Game"
|
|
run/main_scene="res://scenes/main_menu.tscn"
|
|
config/features=PackedStringArray("4.6.2")
|
|
agp/api_base_url="http://127.0.0.1:8000"
|
|
|
|
[autoload]
|
|
|
|
ApiClient="*res://scripts/api_client.gd"
|
|
AvatarSystem="*res://scripts/avatar/avatar_system.gd"
|
|
Session="*res://scripts/session.gd"
|
|
|
|
[display]
|
|
|
|
window/size/viewport_width=1920
|
|
window/size/viewport_height=1080
|
|
window/stretch/mode="canvas_items"
|
|
|
|
[input]
|
|
|
|
move_forward={
|
|
"deadzone": 0.5,
|
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
|
|
]
|
|
}
|
|
move_left={
|
|
"deadzone": 0.5,
|
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
|
]
|
|
}
|
|
move_right={
|
|
"deadzone": 0.5,
|
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
|
|
]
|
|
}
|
|
move_down={
|
|
"deadzone": 0.5,
|
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
|
|
]
|
|
}
|
|
|
|
[physics]
|
|
|
|
; Fixed 30 Hz sim -- the multiplayer server, client prediction, and snapshot
|
|
; rate all key off this. See docs/architecture/networking.md 3.1.
|
|
common/physics_ticks_per_second=30
|
|
|
|
[rendering]
|
|
|
|
renderer/rendering_method="gl_compatibility"
|
|
renderer/rendering_method.mobile="gl_compatibility"
|