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);
}
}
}
}