using System.Collections.Immutable; namespace LuckerParty; /// /// Listens to Network events and creates Client GameObjects /// public sealed class NetworkManager : Component, Component.INetworkListener { /// /// Map from Connection to Client GameObject /// private readonly Dictionary _clientMap = new(); private readonly List _clients = new(); /// /// A GameObject used for organizational grouping of Clients /// private GameObject _clientGroup; public ImmutableList Clients => _clients.ToImmutableList(); public void OnActive( Connection channel ) { // Set up the Client GameObject var gameObject = new GameObject( _clientGroup ) { Name = $"{channel.DisplayName} ({channel.SteamId})" }; _clientMap.Add( channel, gameObject ); var client = gameObject.AddComponent(); client.Connection = channel; // Spawn it on remote clients gameObject.NetworkSpawn( channel ); _clients.Add( client ); IClientEvent.Post( e => e.OnConnected( client ) ); } public void OnDisconnected( Connection channel ) { if ( !_clientMap.TryGetValue( channel, out var clientGameObject ) ) { Log.Warning( $"Disconnected client {channel.SteamId} has no associated GameObject." ); return; } var client = clientGameObject.GetComponent(); IClientEvent.Post( e => e.OnDisconnected( client ) ); clientGameObject.Destroy(); _clientMap.Remove( channel ); _clients.Remove( client ); } protected override void OnAwake() { _clientGroup = new GameObject( Scene.Root ) { Name = "Clients", NetworkMode = NetworkMode.Object }; } protected override void OnDestroy() { _clientGroup.Destroy(); } public interface IClientEvent : ISceneEvent { void OnConnected( Client client ) { } void OnDisconnected( Client client ) { } } }