199 lines
6.1 KiB
C#
199 lines
6.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Steamworks;
|
|
using UnityEngine;
|
|
|
|
namespace MegaKoop.Game.Networking
|
|
{
|
|
/// <summary>
|
|
/// High level orchestrator for Steam lobby + P2P messaging. Keeps track of handlers per message type.
|
|
/// </summary>
|
|
[DisallowMultipleComponent]
|
|
public class SteamCoopNetworkManager : MonoBehaviour
|
|
{
|
|
public static SteamCoopNetworkManager Instance { get; private set; }
|
|
|
|
[SerializeField] private SteamLobbyManager lobbyManager;
|
|
[SerializeField] private SteamP2PTransport p2pTransport;
|
|
|
|
private readonly Dictionary<NetworkMessageType, Action<NetworkMessage>> handlers = new();
|
|
private bool isHost;
|
|
private bool isConnected;
|
|
|
|
public bool IsHost => isHost;
|
|
public bool IsConnected => isConnected;
|
|
public CSteamID ActiveLobby => lobbyManager != null ? lobbyManager.GetActiveLobby() : CSteamID.Nil;
|
|
|
|
private void Awake()
|
|
{
|
|
if (Instance != null)
|
|
{
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
|
|
Instance = this;
|
|
DontDestroyOnLoad(gameObject);
|
|
|
|
if (lobbyManager == null)
|
|
{
|
|
lobbyManager = GetComponentInChildren<SteamLobbyManager>();
|
|
}
|
|
|
|
if (p2pTransport == null)
|
|
{
|
|
p2pTransport = GetComponentInChildren<SteamP2PTransport>();
|
|
}
|
|
|
|
if (lobbyManager != null)
|
|
{
|
|
lobbyManager.LobbyCreated += HandleLobbyCreated;
|
|
lobbyManager.LobbyJoined += HandleLobbyJoined;
|
|
lobbyManager.LobbyMemberJoined += HandleLobbyMemberJoined;
|
|
lobbyManager.LobbyMemberLeft += HandleLobbyMemberLeft;
|
|
}
|
|
|
|
if (p2pTransport != null)
|
|
{
|
|
p2pTransport.MessageReceived += DispatchMessage;
|
|
}
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (Instance == this)
|
|
{
|
|
Instance = null;
|
|
}
|
|
|
|
if (lobbyManager != null)
|
|
{
|
|
lobbyManager.LobbyCreated -= HandleLobbyCreated;
|
|
lobbyManager.LobbyJoined -= HandleLobbyJoined;
|
|
lobbyManager.LobbyMemberJoined -= HandleLobbyMemberJoined;
|
|
lobbyManager.LobbyMemberLeft -= HandleLobbyMemberLeft;
|
|
}
|
|
|
|
if (p2pTransport != null)
|
|
{
|
|
p2pTransport.MessageReceived -= DispatchMessage;
|
|
}
|
|
}
|
|
|
|
public void RegisterHandler(NetworkMessageType type, Action<NetworkMessage> handler)
|
|
{
|
|
if (handlers.TryGetValue(type, out Action<NetworkMessage> existing))
|
|
{
|
|
existing += handler;
|
|
handlers[type] = existing;
|
|
}
|
|
else
|
|
{
|
|
handlers[type] = handler;
|
|
}
|
|
}
|
|
|
|
public void UnregisterHandler(NetworkMessageType type, Action<NetworkMessage> handler)
|
|
{
|
|
if (!handlers.TryGetValue(type, out Action<NetworkMessage> existing))
|
|
{
|
|
return;
|
|
}
|
|
|
|
existing -= handler;
|
|
if (existing == null)
|
|
{
|
|
handlers.Remove(type);
|
|
}
|
|
else
|
|
{
|
|
handlers[type] = existing;
|
|
}
|
|
}
|
|
|
|
public void SendToAll(NetworkMessageType type, byte[] payload, EP2PSend sendType = EP2PSend.k_EP2PSendReliable)
|
|
{
|
|
p2pTransport?.Broadcast(type, payload, sendType);
|
|
}
|
|
|
|
public void SendToPlayer(CSteamID target, NetworkMessageType type, byte[] payload, EP2PSend sendType = EP2PSend.k_EP2PSendReliable)
|
|
{
|
|
p2pTransport?.Send(target, type, payload, sendType);
|
|
}
|
|
|
|
public void SynchronizeWithLobby(MegaKoop.Steam.SteamLobbyService steamService)
|
|
{
|
|
if (steamService == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
isConnected = steamService.IsInLobby;
|
|
isHost = steamService.IsHost;
|
|
|
|
#if STEAMWORKSNET
|
|
if (p2pTransport != null)
|
|
{
|
|
if (steamService.IsInLobby)
|
|
{
|
|
CSteamID lobbyId = steamService.LobbyId;
|
|
if (lobbyId != CSteamID.Nil)
|
|
{
|
|
p2pTransport.SetActiveLobby(lobbyId);
|
|
}
|
|
else if (ulong.TryParse(steamService.LobbyIdString, out ulong lobbyValue) && lobbyValue != 0)
|
|
{
|
|
p2pTransport.SetActiveLobby(new CSteamID(lobbyValue));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p2pTransport.SetActiveLobby(CSteamID.Nil);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
private void DispatchMessage(NetworkMessage message)
|
|
{
|
|
if (handlers.TryGetValue(message.Type, out Action<NetworkMessage> handler))
|
|
{
|
|
handler?.Invoke(message);
|
|
}
|
|
}
|
|
|
|
private void HandleLobbyCreated(CSteamID lobbyId)
|
|
{
|
|
isHost = true;
|
|
isConnected = true;
|
|
p2pTransport?.SetActiveLobby(lobbyId);
|
|
}
|
|
|
|
private void HandleLobbyJoined(CSteamID lobbyId)
|
|
{
|
|
isConnected = true;
|
|
p2pTransport?.SetActiveLobby(lobbyId);
|
|
|
|
string ownerId = SteamMatchmaking.GetLobbyData(lobbyId, "owner");
|
|
if (!string.IsNullOrEmpty(ownerId) && ulong.TryParse(ownerId, out ulong ownerSteamId))
|
|
{
|
|
isHost = ownerSteamId == SteamUser.GetSteamID().m_SteamID;
|
|
}
|
|
else
|
|
{
|
|
isHost = SteamMatchmaking.GetLobbyOwner(lobbyId) == SteamUser.GetSteamID();
|
|
}
|
|
}
|
|
|
|
private void HandleLobbyMemberJoined(CSteamID member)
|
|
{
|
|
Debug.Log("[SteamCoopNetworkManager] Member joined: " + member);
|
|
}
|
|
|
|
private void HandleLobbyMemberLeft(CSteamID member)
|
|
{
|
|
Debug.Log("[SteamCoopNetworkManager] Member left: " + member);
|
|
}
|
|
}
|
|
}
|