using System; using Unity.Collections; using Unity.Netcode; using UnityEngine; using VContainer; namespace Unity.BossRoom.Infrastructure { /// /// This type of message channel allows the server to publish a message that will be sent to clients as well as /// being published locally. Clients and the server both can subscribe to it. /// /// public class NetworkedMessageChannel : MessageChannel where T : unmanaged, INetworkSerializeByMemcpy { NetworkManager m_NetworkManager; string m_Name; public NetworkedMessageChannel() { m_Name = $"{typeof(T).FullName}NetworkMessageChannel"; } [Inject] void InjectDependencies(NetworkManager networkManager) { m_NetworkManager = networkManager; m_NetworkManager.OnClientConnectedCallback += OnClientConnected; if (m_NetworkManager.IsListening) { RegisterHandler(); } } public override void Dispose() { if (!IsDisposed) { if (m_NetworkManager != null && m_NetworkManager.CustomMessagingManager != null) { m_NetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler(m_Name); } } base.Dispose(); } void OnClientConnected(ulong clientId) { RegisterHandler(); } void RegisterHandler() { // Only register message handler on clients if (!m_NetworkManager.IsServer) { m_NetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(m_Name, ReceiveMessageThroughNetwork); } } public override void Publish(T message) { if (m_NetworkManager.IsServer) { // send message to clients, then publish locally SendMessageThroughNetwork(message); base.Publish(message); } else { Debug.LogError("Only a server can publish in a NetworkedMessageChannel"); } } void SendMessageThroughNetwork(T message) { // Avoid throwing an exception if you are in the middle of shutting down and either // NetworkManager no longer exists or the CustomMessagingManager no longer exists. if (m_NetworkManager == null || m_NetworkManager.CustomMessagingManager == null) { return; } var writer = new FastBufferWriter(FastBufferWriter.GetWriteSize(), Allocator.Temp); writer.WriteValueSafe(message); m_NetworkManager.CustomMessagingManager.SendNamedMessageToAll(m_Name, writer); } void ReceiveMessageThroughNetwork(ulong clientID, FastBufferReader reader) { reader.ReadValueSafe(out T message); base.Publish(message); } } }