using FishNet.Broadcast;
using FishNet.Broadcast.Helping;
using FishNet.Managing.Utility;
using FishNet.Serializing;
using FishNet.Serializing.Helping;
using FishNet.Transporting;
using GameKit.Dependencies.Utilities;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
namespace FishNet.Managing.Client
{
public sealed partial class ClientManager : MonoBehaviour
{
#region Private.
///
/// Handler for registered broadcasts.
///
private readonly Dictionary _broadcastHandlers = new();
#endregion
///
/// Registers a method to call when a Broadcast arrives.
///
/// Type of broadcast being registered.
/// Method to call.
public void RegisterBroadcast(Action handler) where T : struct, IBroadcast
{
if (handler == null)
{
NetworkManager.LogError($"Broadcast cannot be registered because handler is null. This may occur when trying to register to objects which require initialization, such as events.");
return;
}
ushort key = BroadcastExtensions.GetKey();
//Create new IBroadcastHandler if needed.
BroadcastHandlerBase bhs;
if (!_broadcastHandlers.TryGetValueIL2CPP(key, out bhs))
{
bhs = new ServerBroadcastHandler();
_broadcastHandlers.Add(key, bhs);
}
//Register handler to IBroadcastHandler.
bhs.RegisterHandler(handler);
}
///
/// Unregisters a method call from a Broadcast type.
///
/// Type of broadcast being unregistered.
/// Method to unregister.
public void UnregisterBroadcast(Action handler) where T : struct, IBroadcast
{
ushort key = BroadcastExtensions.GetKey();
if (_broadcastHandlers.TryGetValueIL2CPP(key, out BroadcastHandlerBase bhs))
bhs.UnregisterHandler(handler);
}
///
/// Parses a received broadcast.
///
private void ParseBroadcast(PooledReader reader, Channel channel)
{
ushort key = reader.ReadUInt16();
int dataLength = Packets.GetPacketLength((ushort)PacketId.Broadcast, reader, channel);
// try to invoke the handler for that message
if (_broadcastHandlers.TryGetValueIL2CPP(key, out BroadcastHandlerBase bhs))
bhs.InvokeHandlers(reader, channel);
else
reader.Skip(dataLength);
}
///
/// Sends a Broadcast to the server.
///
/// Type of broadcast to send.
/// Broadcast data being sent; for example: an instance of your broadcast type.
/// Channel to send on.
public void Broadcast(T message, Channel channel = Channel.Reliable) where T : struct, IBroadcast
{
//Check local connection state.
if (!Started)
{
NetworkManager.LogWarning($"Cannot send broadcast to server because client is not active.");
return;
}
PooledWriter writer = WriterPool.Retrieve();
BroadcastsSerializers.WriteBroadcast(NetworkManager, writer, message, ref channel);
ArraySegment segment = writer.GetArraySegment();
NetworkManager.TransportManager.SendToServer((byte)channel, segment);
writer.Store();
}
}
}