using System; using Steamworks; using UnityEngine; namespace MegaKoop.Game.Networking { /// /// Wraps Steam lobby creation and join logic for cooperative sessions. /// [DisallowMultipleComponent] public class SteamLobbyManager : MonoBehaviour { [SerializeField] private int maxPlayers = 4; public event Action LobbyDataUpdated; public event Action LobbyCreated; public event Action LobbyJoined; public event Action LobbyMemberJoined; public event Action LobbyMemberLeft; private Callback lobbyCreatedCallback; private Callback lobbyEnterCallback; private Callback lobbyDataUpdateCallback; private Callback lobbyChatUpdateCallback; private CSteamID activeLobbyId; private void OnEnable() { lobbyCreatedCallback = Callback.Create(OnLobbyCreated); lobbyEnterCallback = Callback.Create(OnLobbyEntered); lobbyDataUpdateCallback = Callback.Create(OnLobbyDataUpdated); lobbyChatUpdateCallback = Callback.Create(OnLobbyChatUpdate); } private void OnDisable() { lobbyCreatedCallback?.Dispose(); lobbyEnterCallback?.Dispose(); lobbyDataUpdateCallback?.Dispose(); lobbyChatUpdateCallback?.Dispose(); } public void HostLobby(string lobbyName) { if (!SteamBootstrap.IsInitialized || !SteamAPI.IsSteamRunning()) { Debug.LogWarning("[SteamLobbyManager] Steam is not initialized; cannot create lobby."); return; } SteamMatchmaking.CreateLobby(ELobbyType.k_ELobbyTypePublic, Mathf.Max(2, maxPlayers)); pendingLobbyName = lobbyName; } public void JoinLobby(CSteamID lobbyId) { if (!SteamBootstrap.IsInitialized || !SteamAPI.IsSteamRunning()) { Debug.LogWarning("[SteamLobbyManager] Steam not running; cannot join lobby."); return; } SteamMatchmaking.JoinLobby(lobbyId); } public CSteamID GetActiveLobby() => activeLobbyId; private string pendingLobbyName; private void OnLobbyCreated(LobbyCreated_t callback) { if (callback.m_eResult != EResult.k_EResultOK) { Debug.LogError("[SteamLobbyManager] Lobby creation failed: " + callback.m_eResult); return; } activeLobbyId = new CSteamID(callback.m_ulSteamIDLobby); SteamMatchmaking.SetLobbyData(activeLobbyId, "name", string.IsNullOrEmpty(pendingLobbyName) ? "MegaKoop Lobby" : pendingLobbyName); SteamMatchmaking.SetLobbyData(activeLobbyId, "owner", SteamUser.GetSteamID().ToString()); LobbyCreated?.Invoke(activeLobbyId); Debug.Log("[SteamLobbyManager] Lobby created " + activeLobbyId); } private void OnLobbyEntered(LobbyEnter_t callback) { activeLobbyId = new CSteamID(callback.m_ulSteamIDLobby); LobbyJoined?.Invoke(activeLobbyId); Debug.Log("[SteamLobbyManager] Entered lobby " + activeLobbyId); } private void OnLobbyDataUpdated(LobbyDataUpdate_t callback) { LobbyDataUpdated?.Invoke(callback); } private void OnLobbyChatUpdate(LobbyChatUpdate_t callback) { CSteamID lobby = new CSteamID(callback.m_ulSteamIDLobby); CSteamID changedUser = new CSteamID(callback.m_ulSteamIDUserChanged); EChatMemberStateChange stateChange = (EChatMemberStateChange)callback.m_rgfChatMemberStateChange; if ((stateChange & EChatMemberStateChange.k_EChatMemberStateChangeEntered) != 0) { LobbyMemberJoined?.Invoke(changedUser); } if ((stateChange & (EChatMemberStateChange.k_EChatMemberStateChangeLeft | EChatMemberStateChange.k_EChatMemberStateChangeDisconnected | EChatMemberStateChange.k_EChatMemberStateChangeKicked | EChatMemberStateChange.k_EChatMemberStateChangeBanned)) != 0) { LobbyMemberLeft?.Invoke(changedUser); } } } }