diff --git a/splunk/game-logic/game_manager.gd b/splunk/game-logic/game_manager.gd index 61510e1..97093c7 100644 --- a/splunk/game-logic/game_manager.gd +++ b/splunk/game-logic/game_manager.gd @@ -1 +1,14 @@ extends Node + +@onready var debug_ui: PackedScene = preload("res://ui/multiplayer-debug-ui/multiplayer-debug-ui.tscn") +var debug_ui_instance + +func _ready() -> void: + debug_ui_instance = debug_ui.instantiate() + get_tree().root.add_child.call_deferred(debug_ui_instance) + debug_ui_instance.hide() + + +func _input(event: InputEvent) -> void: + if event.is_action_pressed("toggle_watch"): + debug_ui_instance.visible = !debug_ui_instance.visible diff --git a/splunk/levels/lobby-scene/lobby.tscn b/splunk/levels/lobby-scene/lobby.tscn index 118c94b..3a6aafe 100644 --- a/splunk/levels/lobby-scene/lobby.tscn +++ b/splunk/levels/lobby-scene/lobby.tscn @@ -1,8 +1,7 @@ -[gd_scene load_steps=9 format=3 uid="uid://bj52j4ew2lfr6"] +[gd_scene load_steps=8 format=3 uid="uid://bj52j4ew2lfr6"] [ext_resource type="PackedScene" uid="uid://5vggmy1srgxb" path="res://tools/human-height-reference.tscn" id="1_yyu2g"] [ext_resource type="PackedScene" uid="uid://b5xb0fsfpn7r3" path="res://levels/lobby-scene/lobby-terrain.blend" id="3_f73ky"] -[ext_resource type="PackedScene" uid="uid://csmfxg011xisf" path="res://player/Player.tscn" id="4_0aw1h"] [ext_resource type="PackedScene" uid="uid://c4cew4af3h306" path="res://levels/lobby-scene/tent/tent.blend" id="4_qjimh"] [ext_resource type="PackedScene" uid="uid://wcsd1tb0quj3" path="res://levels/lobby-scene/campfire/campfire.tscn" id="5_qjimh"] @@ -44,9 +43,6 @@ spawn_limit = 1 [node name="Marker3D" type="Marker3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.269072, -8.35164) -[node name="Player" parent="." instance=ExtResource("4_0aw1h")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.444747, 0.992996, -4.71496) - [node name="Campsite" type="Node3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15.724, 0, -17.6721) diff --git a/splunk/networking/steam-manager.gd b/splunk/networking/steam-manager.gd index fb31dd2..9056d4d 100644 --- a/splunk/networking/steam-manager.gd +++ b/splunk/networking/steam-manager.gd @@ -10,6 +10,8 @@ var steam_username: String = "" var lobby_id = 0 var lobby_max_members = 4 var lobby_members: Array = [] +var peer_to_steam_id_map: Dictionary = {} +var players: Dictionary = {} var steam_initialized: bool = false @@ -46,7 +48,6 @@ func _ready() -> void: func _on_p2p_session_request(steam_id_remote: int) -> void: - ## ADDED: More detailed logging to confirm P2P acceptance. print("[P2P] ==> Session request from: %s. Accepting." % steam_id_remote) var accepted = Steam.acceptP2PSessionWithUser(steam_id_remote) if not accepted: @@ -54,14 +55,12 @@ func _on_p2p_session_request(steam_id_remote: int) -> void: func _process(delta): - ## ADDED: Guard clause in case Steam fails to initialize. if not steam_initialized: return Steam.run_callbacks() if Input.is_action_just_pressed("interact"): - ## ADDED: Replaced simple print with a detailed diagnostic function. log_multiplayer_info() @@ -97,7 +96,6 @@ func init_steam() -> bool: func setup_multiplayer_peer(is_host: bool = false) -> void: - ## ADDED: Check if a peer is already active before creating a new one. if multiplayer.multiplayer_peer and multiplayer.multiplayer_peer.get_connection_status() != MultiplayerPeer.CONNECTION_DISCONNECTED: print("[Multiplayer] Peer already exists. Disconnecting old one.") multiplayer.multiplayer_peer.close() @@ -106,7 +104,7 @@ func setup_multiplayer_peer(is_host: bool = false) -> void: if is_host: print("[Multiplayer] Creating Host...") - var err = peer.create_host(0) ## REMOVED: Channel is handled by the peer automatically now. + var err = peer.create_host(0) if err != OK: print("[Multiplayer] !!! Failed to create host. Error: %s" % err) return @@ -120,7 +118,7 @@ func setup_multiplayer_peer(is_host: bool = false) -> void: var host_id = Steam.getLobbyOwner(lobby_id) print("[Multiplayer] Creating Client, attempting to connect to host: %s" % host_id) - var err = peer.create_client(host_id, 0) ## REMOVED: Channel is handled by the peer automatically. + var err = peer.create_client(host_id, 0) if err != OK: print("[Multiplayer] !!! Failed to create client. Error: %s" % err) return @@ -142,10 +140,12 @@ func _on_lobby_created(connect: int, this_lobby_id: int): Steam.setLobbyJoinable(lobby_id, true) Steam.setLobbyData(lobby_id, "name", steam_username + "'s Lobby") - Steam.setLobbyData(lobby_id, "mode", "Splunk") - Steam.allowP2PPacketRelay(true) - setup_multiplayer_peer(true) # Setup as host + + setup_multiplayer_peer(true) + + peer_to_steam_id_map[1] = steam_id + spawn_player.rpc(1) else : print("!!! Failed to create lobby.") @@ -162,7 +162,6 @@ func _on_lobby_joined(this_lobby_id: int, permissions: int, locked: bool, respon print("Successfully joined lobby: %s" % lobby_id) get_lobby_members() - # FIXED: Use Steam.getLobbyOwner() to determine if we should be host or client var lobby_owner_id = Steam.getLobbyOwner(lobby_id) var am_i_owner = (lobby_owner_id == steam_id) @@ -170,11 +169,10 @@ func _on_lobby_joined(this_lobby_id: int, permissions: int, locked: bool, respon if not am_i_owner: print("[Multiplayer] I am not the lobby owner, setting up as client...") - setup_multiplayer_peer(false) # Setup as client + setup_multiplayer_peer(false) else: print("[Multiplayer] I am the lobby owner, but multiplayer peer should already be set up as host.") else: - ## ADDED: Log the specific reason for the join failure. print("!!! Failed to join lobby. Reason: %s" % get_join_fail_reason(response)) @@ -206,7 +204,6 @@ func _on_lobby_data_update(lobby: int, user: int, success: int) -> void: func _on_persona_change(steam_id_changed: int, flag: int) -> void: - # This can be spammy, but useful for debugging name changes. # print("Persona state changed for %s. Refreshing lobby members." % steam_id_changed) get_lobby_members() @@ -226,35 +223,82 @@ func _on_lobby_chat_update(lobby_id_update: int, user_changed_id: int, user_maki print("[Lobby] Chat Update: User %s has %s." % [user_changed_id, state_string]) - # Any change in lobby membership should trigger a refresh. get_lobby_members() +@rpc("any_peer", "call_local") +func spawn_player(peer_id: int): + var steam_id_of_player = peer_to_steam_id_map.get(peer_id) + if steam_id_of_player == null: + print("!!! Cannot spawn player, peer %s not found in map." % peer_id) + return + + print("Spawning player for peer: %s" % peer_id) + var player_name = Steam.getFriendPersonaName(steam_id_of_player) + + var new_player = player_scene.instantiate() as Player + new_player.name = str(peer_id) + + add_child(new_player) + players[peer_id] = new_player + new_player.set_player_name(player_name) # Call the simple RPC on the player node + new_player.position = Vector3(0,1,0) + # The server has the final say on who owns what + if multiplayer.is_server(): + new_player.set_multiplayer_authority(peer_id) + + +@rpc("authority", "call_local") +func register_player(new_player_steam_id: int): + # This function only runs on the server + var new_player_peer_id = multiplayer.get_remote_sender_id() + print("Server: Registering peer %s with Steam ID %s" % [new_player_peer_id, new_player_steam_id]) + + # Add the new player to our map + peer_to_steam_id_map[new_player_peer_id] = new_player_steam_id + + # Now, tell the new player about everyone who is already here + for peer_id in players: + spawn_player.rpc_id(new_player_peer_id, peer_id) + + # Finally, tell EVERYONE to spawn the new player + spawn_player.rpc(new_player_peer_id) + + func _on_peer_connected(id: int) -> void: print("[Multiplayer] ✅ Peer connected: %s" % id) - var new_player = player_scene.instantiate() as Player - new_player.set_multiplayer_authority(id) - $".".add_child(new_player) - new_player.position = Vector3(0,1,0) - - # It's good practice to re-check lobby members when a peer connects successfully. + for peerd_id in players: + spawn_player.rpc_id(id, peerd_id) + spawn_player.rpc(id) + get_lobby_members() + func _on_peer_disconnected(id: int) -> void: print("[Multiplayer] ❌ Peer disconnected: %s" % id) + if players.has(id): + players[id].queue_free() + players.erase(id) + + if peer_to_steam_id_map.has(id): + peer_to_steam_id_map.erase(id) + func _on_connected_to_server() -> void: print("[Multiplayer] ✅ Successfully connected to the host.") print("[Multiplayer] - My Peer ID is now: %s" % multiplayer.get_unique_id()) + + register_player.rpc_id(1, steam_id) + func _on_connection_failed() -> void: print("[Multiplayer] ❌ Connection to the host failed.") + func _on_server_disconnected() -> void: print("[Multiplayer] ❌ Disconnected from the host.") -## ADDED: New function to log all relevant multiplayer and lobby information. func log_multiplayer_info(): print("\n--- DIAGNOSTIC INFO ---") print("## Multiplayer Status:") diff --git a/splunk/player/Player.tscn b/splunk/player/Player.tscn index 0dfa275..a5658f4 100644 --- a/splunk/player/Player.tscn +++ b/splunk/player/Player.tscn @@ -1,7 +1,6 @@ -[gd_scene load_steps=8 format=3 uid="uid://csmfxg011xisf"] +[gd_scene load_steps=7 format=3 uid="uid://csmfxg011xisf"] [ext_resource type="Script" uid="uid://dopyfulbw2mx5" path="res://player/player.gd" id="1_ulp21"] -[ext_resource type="PackedScene" uid="uid://8phs2e161db1" path="res://ui/multiplayer-debug-ui/multiplayer-debug-ui.tscn" id="2_3c3w1"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_ehsmr"] @@ -33,7 +32,6 @@ script = ExtResource("1_ulp21") [node name="Camera3D" type="Camera3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.399442, 0.0644827) cull_mask = 1048573 -current = true [node name="CollisionShape3D" type="CollisionShape3D" parent="."] shape = SubResource("CapsuleShape3D_ehsmr") @@ -72,7 +70,3 @@ replication_config = SubResource("SceneReplicationConfig_ulp21") transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.887858, 0) billboard = 1 text = "Username" - -[node name="CanvasLayer" type="CanvasLayer" parent="."] - -[node name="Multiplayer-debug-ui" parent="CanvasLayer" instance=ExtResource("2_3c3w1")] diff --git a/splunk/player/player.gd b/splunk/player/player.gd index 990cfed..8401c39 100644 --- a/splunk/player/player.gd +++ b/splunk/player/player.gd @@ -9,17 +9,22 @@ var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") var camera_node: Camera3D func _ready(): - if !is_multiplayer_authority(): - pass - Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) - camera_node = $Camera3D # Assuming Camera3D is a direct child - camera_node.current = true + if is_multiplayer_authority(): + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + camera_node = $Camera3D + camera_node.current = true + $Mesh.hide() + + var peer_id = int(name) + +@rpc("any_peer", "call_local") +func set_player_name(player_name: String): + $Label3D.text = player_name - $Label3D.text = SteamManager.steam_username func _physics_process(delta): if !is_multiplayer_authority(): - pass + return # Apply gravity if not is_on_floor(): velocity.y -= gravity * delta @@ -48,7 +53,7 @@ func _physics_process(delta): func _input(event): if !is_multiplayer_authority(): - pass + return if event is InputEventMouseMotion: # Rotate the CharacterBody3D around the Y-axis for horizontal look rotate_y(-event.relative.x * mouse_sensitivity) @@ -63,6 +68,3 @@ func _input(event): Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) else: Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) - - if event.is_action_pressed("toggle_watch"): - $"CanvasLayer/Multiplayer-debug-ui".visible = !$"CanvasLayer/Multiplayer-debug-ui".visible diff --git a/splunk/project.godot b/splunk/project.godot index aa31ded..2a11b0e 100644 --- a/splunk/project.godot +++ b/splunk/project.godot @@ -18,6 +18,7 @@ config/icon="res://icon.svg" [autoload] SteamManager="*res://networking/steam-manager.gd" +GameManager="*res://game-logic/game_manager.gd" [editor_plugins]