From df031b878446b9082d34d684fb2bd63fc52542df Mon Sep 17 00:00:00 2001 From: Chris Bell Date: Thu, 7 Aug 2025 21:17:56 -0500 Subject: [PATCH] possible ai slop fix --- splunk/networking/steam-manager.gd | 422 ++++++++++------------------- 1 file changed, 148 insertions(+), 274 deletions(-) diff --git a/splunk/networking/steam-manager.gd b/splunk/networking/steam-manager.gd index 9056d4d..a528d9c 100644 --- a/splunk/networking/steam-manager.gd +++ b/splunk/networking/steam-manager.gd @@ -2,19 +2,18 @@ extends Node @onready var player_scene: PackedScene = preload("res://player/Player.tscn") -var is_owned: bool = false -var steam_app_id: int = 480 +# -- Game State Variables -- +var players: Dictionary = {} # Key: peer_id, Value: player_node +var peer_to_steam_id_map: Dictionary = {} # Key: peer_id, Value: steam_id + +# -- Steam Variables -- var steam_id: int = 0 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 lobby_id: int = 0 var steam_initialized: bool = false +var steam_app_id: int = 480 # Spacewar App ID for testing +# -- Godot Variables -- var peer: SteamMultiplayerPeer @@ -30,187 +29,167 @@ func _ready() -> void: # Connect Steam lobby signals Steam.lobby_created.connect(_on_lobby_created) Steam.lobby_joined.connect(_on_lobby_joined) - #Steam.lobby_match_list.connect(_on_lobby_match_list) Steam.lobby_chat_update.connect(_on_lobby_chat_update) - Steam.lobby_data_update.connect(_on_lobby_data_update) - #Steam.join_requested.connect(_on_lobby_join_requested) - Steam.persona_state_change.connect(_on_persona_change) + Steam.p2p_session_request.connect(_on_p2p_session_request) - # Setup multiplayer signals + # Connect Godot multiplayer signals multiplayer.peer_connected.connect(_on_peer_connected) multiplayer.peer_disconnected.connect(_on_peer_disconnected) multiplayer.connected_to_server.connect(_on_connected_to_server) multiplayer.connection_failed.connect(_on_connection_failed) - multiplayer.server_disconnected.connect(_on_server_disconnected) - Steam.p2p_session_request.connect(_on_p2p_session_request) check_command_line() - -func _on_p2p_session_request(steam_id_remote: int) -> void: - print("[P2P] ==> Session request from: %s. Accepting." % steam_id_remote) - var accepted = Steam.acceptP2PSessionWithUser(steam_id_remote) - if not accepted: - print("[P2P] !!! Failed to accept P2P session with %s." % steam_id_remote) - - func _process(delta): if not steam_initialized: return - Steam.run_callbacks() + +# ----------------------------------------------------------------------------- +# CORE LOGIC: STEP 1 - HOST CREATION +# ----------------------------------------------------------------------------- +func create_lobby(): + print("[HOST] 1. Attempting to create lobby...") + Steam.createLobby(Steam.LOBBY_TYPE_FRIENDS_ONLY, 4) + +func _on_lobby_created(connect: int, this_lobby_id: int): + if connect != 1: + print("[HOST] !!! Lobby creation failed.") + return + + lobby_id = this_lobby_id + print("[HOST] 2. Lobby created successfully (ID: %s)." % lobby_id) - if Input.is_action_just_pressed("interact"): - log_multiplayer_info() + Steam.setLobbyJoinable(lobby_id, true) + Steam.setLobbyData(lobby_id, "name", steam_username + "'s Lobby") + + setup_multiplayer_peer(true) + print("[HOST] 3. Multiplayer host started (My Peer ID is always 1).") + + # Register self + peer_to_steam_id_map[1] = steam_id + print("[HOST] 4. Host (Peer 1) registered in the ID map.") + # Spawn self + spawn_player.rpc(1) -func check_command_line() -> void: - var args: Array = OS.get_cmdline_args() - if args.size() > 0: - if args[0] == "+connect_lobby": - if args.size() > 1 and int(args[1]) > 0: - print("Command line lobby ID: %s" % args[1]) - join_lobby(int(args[1])) +# ----------------------------------------------------------------------------- +# CORE LOGIC: STEP 2 - CLIENT CONNECTION +# ----------------------------------------------------------------------------- +func join_lobby(this_lobby_id: int): + print("[CLIENT] 1. Attempting to join lobby (ID: %s)..." % this_lobby_id) + Steam.joinLobby(this_lobby_id) +func _on_lobby_joined(this_lobby_id: int, _p, _l, response: int): + if response != Steam.CHAT_ROOM_ENTER_RESPONSE_SUCCESS: + print("[CLIENT] !!! Failed to join lobby: %s" % get_join_fail_reason(response)) + return + + lobby_id = this_lobby_id + print("[CLIENT] 2. Successfully joined Steam lobby.") + + # Only clients should attempt to connect via peer. The host is already a peer. + if Steam.getLobbyOwner(lobby_id) != steam_id: + print("[CLIENT] 3. I am a client, creating multiplayer peer to connect to host.") + setup_multiplayer_peer(false) + +# This signal fires on the CLIENT after setup_multiplayer_peer succeeds +func _on_connected_to_server(): + print("[CLIENT] 4. Successfully connected to host's multiplayer peer.") + print("[CLIENT] 5. Sending my info to the server for registration...") + register_player_on_server.rpc_id(1, steam_id) + +# ----------------------------------------------------------------------------- +# CORE LOGIC: STEP 3 - SERVER REGISTRATION & SPAWNING +# ----------------------------------------------------------------------------- + +# This RPC is sent by a client and runs ONLY on the SERVER +@rpc("authority", "call_local") +func register_player_on_server(new_player_steam_id: int): + var new_player_peer_id = multiplayer.get_remote_sender_id() + print("[SERVER] 6. Received registration request from Peer %s." % new_player_peer_id) + + # Add the new player to the map + peer_to_steam_id_map[new_player_peer_id] = new_player_steam_id + print("[SERVER] 7. Peer %s (Steam ID: %s) added to ID map." % [new_player_peer_id, new_player_steam_id]) + + # Tell the new client about all players already in the game + print("[SERVER] 8. Telling Peer %s about existing players..." % new_player_peer_id) + for existing_peer_id in players: + spawn_player.rpc_id(new_player_peer_id, existing_peer_id) + + # Tell EVERYONE to spawn the new player + print("[SERVER] 9. Telling ALL peers to spawn the new player (Peer %s)." % new_player_peer_id) + spawn_player.rpc(new_player_peer_id) + +# This RPC is sent by the SERVER and runs on ALL clients +@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("!!! [%s] Cannot spawn player for Peer %s, not yet in map." % [multiplayer.get_unique_id(), peer_id]) + return + + if players.has(peer_id): # Prevents spawning a duplicate + return + + var player_name = Steam.getFriendPersonaName(steam_id_of_player) + print("-> [%s] Spawning character for Peer %s (Name: %s)." % [multiplayer.get_unique_id(), peer_id, player_name]) + + var new_player = player_scene.instantiate() + new_player.name = str(peer_id) + + players[peer_id] = new_player + add_child(new_player) + + new_player.set_player_name(player_name) + + if multiplayer.is_server(): + new_player.set_multiplayer_authority(peer_id) + +# ----------------------------------------------------------------------------- +# UTILITY AND CALLBACKS +# ----------------------------------------------------------------------------- +func _on_p2p_session_request(steam_id_remote: int) -> void: + print("[P2P] ==> Session request from: %s. Accepting." % steam_id_remote) + Steam.acceptP2PSessionWithUser(steam_id_remote) func init_steam() -> bool: var response: Dictionary = Steam.steamInitEx() - print("Steam init response: %s " % response) - if response['status'] > 0: print("!!! Failed to init steam! Code: %s " % response) return false - - is_owned = Steam.isSubscribed() steam_id = Steam.getSteamID() steam_username = Steam.getPersonaName() - print("Steam initialized successfully for %s (ID: %s)." % [steam_username, steam_id]) - - if !is_owned: - print("!!! WARNING: Steam reports you do not own App ID %s." % steam_app_id) - # You might want to return false here in a real game - # return false - return true - func setup_multiplayer_peer(is_host: bool = false) -> void: 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() peer = SteamMultiplayerPeer.new() - if is_host: - print("[Multiplayer] Creating Host...") - var err = peer.create_host(0) - if err != OK: - print("[Multiplayer] !!! Failed to create host. Error: %s" % err) - return - - multiplayer.multiplayer_peer = peer - print("[Multiplayer] Host created successfully. My Peer ID: %s" % multiplayer.get_unique_id()) + peer.create_host() else: - if lobby_id == 0: - print("[Multiplayer] !!! Cannot create client, not in a lobby.") - return - 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) - if err != OK: - print("[Multiplayer] !!! Failed to create client. Error: %s" % err) - return - - multiplayer.multiplayer_peer = peer - print("[Multiplayer] Client peer created. Waiting for connection...") + peer.create_client(host_id) + + multiplayer.multiplayer_peer = peer +func _on_peer_connected(id: int): + print("[INFO] Peer %s has established a multiplayer session." % id) -func create_lobby(): - if lobby_id == 0: - print("Creating lobby...") - Steam.createLobby(Steam.LOBBY_TYPE_FRIENDS_ONLY, lobby_max_members) - - -func _on_lobby_created(connect: int, this_lobby_id: int): - if connect == 1: - lobby_id = this_lobby_id - print("Lobby created with id `%s`" % lobby_id) +func _on_peer_disconnected(id: int): + print("[INFO] Peer %s has disconnected." % 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) - Steam.setLobbyJoinable(lobby_id, true) - Steam.setLobbyData(lobby_id, "name", steam_username + "'s Lobby") - Steam.allowP2PPacketRelay(true) - - setup_multiplayer_peer(true) - - peer_to_steam_id_map[1] = steam_id - spawn_player.rpc(1) - else : - print("!!! Failed to create lobby.") - - -func join_lobby(this_lobby_id: int): - print("Attempting to join lobby: %s" % this_lobby_id) - lobby_members.clear() - Steam.joinLobby(this_lobby_id) - - -func _on_lobby_joined(this_lobby_id: int, permissions: int, locked: bool, response: int): - if response == Steam.CHAT_ROOM_ENTER_RESPONSE_SUCCESS: - lobby_id = this_lobby_id - print("Successfully joined lobby: %s" % lobby_id) - get_lobby_members() - - var lobby_owner_id = Steam.getLobbyOwner(lobby_id) - var am_i_owner = (lobby_owner_id == steam_id) - - print("[Multiplayer] Lobby Owner: %s, My Steam ID: %s, Am I Owner?: %s" % [lobby_owner_id, steam_id, am_i_owner]) - - if not am_i_owner: - print("[Multiplayer] I am not the lobby owner, setting up 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: - print("!!! Failed to join lobby. Reason: %s" % get_join_fail_reason(response)) - - -func get_lobby_members() -> void: - lobby_members.clear() - if lobby_id == 0: return - - var num_members = Steam.getNumLobbyMembers(lobby_id) - print("--- Refreshing Lobby Members (%s) ---" % num_members) - for i in range(num_members): - var member_id = Steam.getLobbyMemberByIndex(lobby_id, i) - var member_name = Steam.getFriendPersonaName(member_id) - lobby_members.append({ - "steam_id": member_id, - "steam_name": member_name - }) - print(" - %s (%s)" % [member_name, member_id]) - print("---------------------------------") - - -func _on_lobby_data_update(lobby: int, user: int, success: int) -> void: - if success: - if lobby == user: - print("Lobby data for lobby %s has been updated." % lobby) - var lobby_name = Steam.getLobbyData(lobby, "name") - print(" > New lobby name: %s" % lobby_name) - else: - print("Data for member %s in lobby %s has been updated." % [user, lobby]) - - -func _on_persona_change(steam_id_changed: int, flag: int) -> void: - # print("Persona state changed for %s. Refreshing lobby members." % steam_id_changed) - get_lobby_members() - - -func leave_lobby() -> void: - pass - +func _on_connection_failed() -> void: + print("[CLIENT] !!! Connection to the host failed.") func _on_lobby_chat_update(lobby_id_update: int, user_changed_id: int, user_making_change_id: int, chat_state: int): var state_string = "UNKNOWN" @@ -218,130 +197,25 @@ func _on_lobby_chat_update(lobby_id_update: int, user_changed_id: int, user_maki Steam.CHAT_MEMBER_STATE_CHANGE_ENTERED: state_string = "ENTERED" Steam.CHAT_MEMBER_STATE_CHANGE_LEFT: state_string = "LEFT" Steam.CHAT_MEMBER_STATE_CHANGE_DISCONNECTED: state_string = "DISCONNECTED" - Steam.CHAT_MEMBER_STATE_CHANGE_KICKED: state_string = "KICKED" - Steam.CHAT_MEMBER_STATE_CHANGE_BANNED: state_string = "BANNED" - - print("[Lobby] Chat Update: User %s has %s." % [user_changed_id, state_string]) - - 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) - 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.") - - -func log_multiplayer_info(): - print("\n--- DIAGNOSTIC INFO ---") - print("## Multiplayer Status:") - if multiplayer.multiplayer_peer: - print(" - Peer State: Active") - print(" - Connection Status: %s" % get_connection_status_string(multiplayer.multiplayer_peer.get_connection_status())) - print(" - Is Server?: %s" % multiplayer.is_server()) - print(" - My Peer ID: %s" % multiplayer.get_unique_id()) - print(" - Connected Peer IDs: %s" % multiplayer.get_peers()) - else: - print(" - Peer State: Inactive (null)") - - print("\n## Steam Lobby Info:") - print(" - In Lobby?: %s" % (lobby_id != 0)) - print(" - Lobby ID: %s" % lobby_id) - if lobby_id != 0: - print(" - Lobby Owner Steam ID: %s" % Steam.getLobbyOwner(lobby_id)) - print(" - My Steam ID: %s" % steam_id) - print(" - Lobby Members Array (%s):" % lobby_members.size()) - for member in lobby_members: - print(" - %s (%s)" % [member.steam_name, member.steam_id]) - print("-------------------------\n") - - -## ADDED: Helper function to get a human-readable string for connection status. -func get_connection_status_string(status: int) -> String: - match status: - MultiplayerPeer.CONNECTION_DISCONNECTED: return "Disconnected" - MultiplayerPeer.CONNECTION_CONNECTING: return "Connecting" - MultiplayerPeer.CONNECTION_CONNECTED: return "Connected" - _: return "Unknown Status" + print("[LOBBY INFO] User %s has %s the lobby." % [user_changed_id, state_string]) +func check_command_line() -> void: + var args: Array = OS.get_cmdline_args() + if args.size() > 1 and args[0] == "+connect_lobby": + if int(args[1]) > 0: + print("[CMD] Command line join request for lobby ID: %s" % args[1]) + join_lobby(int(args[1])) func get_join_fail_reason(response: int) -> String: match response: - Steam.CHAT_ROOM_ENTER_RESPONSE_DOESNT_EXIST: return "Lobby no longer exists" - Steam.CHAT_ROOM_ENTER_RESPONSE_NOT_ALLOWED: return "Not allowed to join" - Steam.CHAT_ROOM_ENTER_RESPONSE_FULL: return "Lobby is full" - Steam.CHAT_ROOM_ENTER_RESPONSE_ERROR: return "Unknown error" - Steam.CHAT_ROOM_ENTER_RESPONSE_BANNED: return "You are banned" - Steam.CHAT_ROOM_ENTER_RESPONSE_LIMITED: return "Limited account" - Steam.CHAT_ROOM_ENTER_RESPONSE_CLAN_DISABLED: return "Lobby is locked" - Steam.CHAT_ROOM_ENTER_RESPONSE_COMMUNITY_BAN: return "Community locked" - Steam.CHAT_ROOM_ENTER_RESPONSE_MEMBER_BLOCKED_YOU: return "A member blocked you" - Steam.CHAT_ROOM_ENTER_RESPONSE_YOU_BLOCKED_MEMBER: return "You blocked a member" - _: return "Unknown reason" + 1: return "Doesnt Exist" + 2: return "Not Allowed" + 3: return "Full" + 4: return "Error" + 5: return "Banned" + 6: return "Limited" + 7: return "Clan Disabled" + 8: return "Community Ban" + 9: return "Member Blocked You" + 10: return "You Blocked Member" + _: return "Unknown Reason"