PC3 Phase 2.3: networked play path in the game
- 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
This commit is contained in:
+29
-8
@@ -135,15 +135,16 @@ func _create_world_card(world_dict: Dictionary) -> Control:
|
||||
meta_label.add_theme_font_size_override("font_size", 12)
|
||||
meta_label.add_theme_color_override("font_color", Color(0.5, 0.5, 0.5, 1.0))
|
||||
|
||||
# PC2: the only thing a world actually loads into right now is the one
|
||||
# shared playable test level (scenes/game.tscn) -- there's no per-world
|
||||
# content yet, so "Enter" doesn't need the world's id for anything.
|
||||
# Real per-world level loading is a later concern once worlds actually
|
||||
# have their own content to load.
|
||||
# "Enter World" asks the backend to host this world (POST /join) and then
|
||||
# loads scenes/game.tscn networked. If the backend has no game-server
|
||||
# orchestration (a plain dev instance), it falls back to local
|
||||
# single-player. All worlds still load the same test level -- per-world
|
||||
# content is a later milestone.
|
||||
var world_id := int(world_dict.get("id", 0))
|
||||
var enter_button := Button.new()
|
||||
enter_button.text = "Enter World"
|
||||
enter_button.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
||||
enter_button.pressed.connect(_on_enter_world_pressed)
|
||||
enter_button.pressed.connect(_on_enter_world_pressed.bind(world_id, enter_button))
|
||||
|
||||
card.add_child(name_label)
|
||||
card.add_child(desc_label)
|
||||
@@ -153,5 +154,25 @@ func _create_world_card(world_dict: Dictionary) -> Control:
|
||||
return panel
|
||||
|
||||
|
||||
func _on_enter_world_pressed() -> void:
|
||||
get_tree().change_scene_to_file("res://scenes/game.tscn")
|
||||
func _on_enter_world_pressed(world_id: int, button: Button) -> void:
|
||||
button.disabled = true
|
||||
button.text = "Joining…"
|
||||
|
||||
var result := await ApiClient.join_world(world_id)
|
||||
|
||||
if result.ok and result.data is Dictionary:
|
||||
var d: Dictionary = result.data
|
||||
Session.begin(world_id, str(d.get("host", "")), int(d.get("port", 0)))
|
||||
get_tree().change_scene_to_file("res://scenes/game.tscn")
|
||||
return
|
||||
|
||||
if result.status == 503:
|
||||
# This backend can't host game servers -- go in local single-player.
|
||||
Session.clear()
|
||||
get_tree().change_scene_to_file("res://scenes/game.tscn")
|
||||
return
|
||||
|
||||
button.disabled = false
|
||||
button.text = "Enter World"
|
||||
error_label.text = "Couldn't join: %s" % result.detail
|
||||
error_label.visible = true
|
||||
|
||||
Reference in New Issue
Block a user