[Add] FishNet
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
using FishNet.Connection;
|
||||
using FishNet.Managing;
|
||||
using FishNet.Serializing;
|
||||
using FishNet.Transporting;
|
||||
using GameKit.Dependencies.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FishNet.Broadcast.Helping
|
||||
{
|
||||
internal static class BroadcastsSerializers
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes a broadcast to writer.
|
||||
/// </summary>
|
||||
internal static PooledWriter WriteBroadcast<T>(NetworkManager networkManager, PooledWriter writer, T message, ref Channel channel)
|
||||
{
|
||||
writer.WritePacketIdUnpacked(PacketId.Broadcast);
|
||||
writer.WriteUInt16(typeof(T).FullName.GetStableHashU16());
|
||||
// Write data to a new writer.
|
||||
PooledWriter dataWriter = WriterPool.Retrieve();
|
||||
dataWriter.Write(message);
|
||||
// Write length of data.
|
||||
writer.WriteInt32(dataWriter.Length);
|
||||
// Write data.
|
||||
writer.WriteArraySegment(dataWriter.GetArraySegment());
|
||||
// Update channel to reliable if needed.
|
||||
networkManager.TransportManager.CheckSetReliableChannel(writer.Length, ref channel);
|
||||
|
||||
dataWriter.Store();
|
||||
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class BroadcastExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the key for a broadcast type.
|
||||
/// </summary>
|
||||
/// <typeparam name = "T"></typeparam>
|
||||
/// <param name = "broadcastType"></param>
|
||||
/// <returns></returns>
|
||||
internal static ushort GetKey<T>()
|
||||
{
|
||||
return typeof(T).FullName.GetStableHashU16();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implemented by server and client broadcast handlers.
|
||||
/// </summary>
|
||||
public abstract class BroadcastHandlerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Current index when iterating invokes.
|
||||
/// This value will be -1 when not iterating.
|
||||
/// </summary>
|
||||
protected int IteratingIndex;
|
||||
public abstract void RegisterHandler(object obj);
|
||||
public abstract void UnregisterHandler(object obj);
|
||||
public virtual void InvokeHandlers(PooledReader reader, Channel channel) { }
|
||||
public virtual void InvokeHandlers(NetworkConnection conn, PooledReader reader, Channel channel) { }
|
||||
public virtual bool RequireAuthentication => false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles broadcasts received on server, from clients.
|
||||
/// </summary>
|
||||
internal class ClientBroadcastHandler<T> : BroadcastHandlerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Action handlers for the broadcast.
|
||||
/// </summary>
|
||||
private List<Action<NetworkConnection, T, Channel>> _handlers = new();
|
||||
/// <summary>
|
||||
/// True to require authentication for the broadcast type.
|
||||
/// </summary>
|
||||
private bool _requireAuthentication;
|
||||
|
||||
public ClientBroadcastHandler(bool requireAuthentication)
|
||||
{
|
||||
_requireAuthentication = requireAuthentication;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes handlers after reading broadcast.
|
||||
/// </summary>
|
||||
/// <returns>True if a rebuild was required.</returns>
|
||||
public override void InvokeHandlers(NetworkConnection conn, PooledReader reader, Channel channel)
|
||||
{
|
||||
T result = reader.Read<T>();
|
||||
for (IteratingIndex = 0; IteratingIndex < _handlers.Count; IteratingIndex++)
|
||||
{
|
||||
Action<NetworkConnection, T, Channel> item = _handlers[IteratingIndex];
|
||||
if (item != null)
|
||||
{
|
||||
item.Invoke(conn, result, channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
_handlers.RemoveAt(IteratingIndex);
|
||||
IteratingIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
IteratingIndex = -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a handler for this type.
|
||||
/// </summary>
|
||||
public override void RegisterHandler(object obj)
|
||||
{
|
||||
Action<NetworkConnection, T, Channel> handler = (Action<NetworkConnection, T, Channel>)obj;
|
||||
_handlers.AddUnique(handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a handler from this type.
|
||||
/// </summary>
|
||||
/// <param name = "handler"></param>
|
||||
public override void UnregisterHandler(object obj)
|
||||
{
|
||||
Action<NetworkConnection, T, Channel> handler = (Action<NetworkConnection, T, Channel>)obj;
|
||||
int indexOf = _handlers.IndexOf(handler);
|
||||
// Not registered.
|
||||
if (indexOf == -1)
|
||||
return;
|
||||
|
||||
/* Has already been iterated over, need to subtract
|
||||
* 1 from iteratingIndex to accomodate
|
||||
* for the entry about to be removed. */
|
||||
if (IteratingIndex >= 0 && indexOf <= IteratingIndex)
|
||||
IteratingIndex--;
|
||||
|
||||
// Remove entry.
|
||||
_handlers.RemoveAt(indexOf);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True to require authentication for the broadcast type.
|
||||
/// </summary>
|
||||
public override bool RequireAuthentication => _requireAuthentication;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles broadcasts received on client, from server.
|
||||
/// </summary>
|
||||
internal class ServerBroadcastHandler<T> : BroadcastHandlerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Action handlers for the broadcast.
|
||||
/// Even though List lookups are slower this allows easy adding and removing of entries during iteration.
|
||||
/// </summary>
|
||||
private List<Action<T, Channel>> _handlers = new();
|
||||
|
||||
/// <summary>
|
||||
/// Invokes handlers after reading broadcast.
|
||||
/// </summary>
|
||||
/// <returns>True if a rebuild was required.</returns>
|
||||
public override void InvokeHandlers(PooledReader reader, Channel channel)
|
||||
{
|
||||
T result = reader.Read<T>();
|
||||
for (IteratingIndex = 0; IteratingIndex < _handlers.Count; IteratingIndex++)
|
||||
{
|
||||
Action<T, Channel> item = _handlers[IteratingIndex];
|
||||
if (item != null)
|
||||
{
|
||||
item.Invoke(result, channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
_handlers.RemoveAt(IteratingIndex);
|
||||
IteratingIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
IteratingIndex = -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a handler for this type.
|
||||
/// </summary>
|
||||
public override void RegisterHandler(object obj)
|
||||
{
|
||||
Action<T, Channel> handler = (Action<T, Channel>)obj;
|
||||
_handlers.AddUnique(handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a handler from this type.
|
||||
/// </summary>
|
||||
/// <param name = "handler"></param>
|
||||
public override void UnregisterHandler(object obj)
|
||||
{
|
||||
Action<T, Channel> handler = (Action<T, Channel>)obj;
|
||||
int indexOf = _handlers.IndexOf(handler);
|
||||
// Not registered.
|
||||
if (indexOf == -1)
|
||||
return;
|
||||
|
||||
/* Has already been iterated over, need to subtract
|
||||
* 1 from iteratingIndex to accomodate
|
||||
* for the entry about to be removed. */
|
||||
if (IteratingIndex >= 0 && indexOf <= IteratingIndex)
|
||||
IteratingIndex--;
|
||||
|
||||
// Remove entry.
|
||||
_handlers.RemoveAt(indexOf);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True to require authentication for the broadcast type.
|
||||
/// </summary>
|
||||
public override bool RequireAuthentication => false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user