141 lines
4.9 KiB
C#
141 lines
4.9 KiB
C#
|
using FishNet.Managing.Server;
|
|||
|
using FishNet.Object.Helping;
|
|||
|
using FishNet.Serializing;
|
|||
|
using FishNet.Transporting;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Runtime.CompilerServices;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
namespace FishNet.Object
|
|||
|
{
|
|||
|
|
|||
|
public abstract partial class NetworkBehaviour : MonoBehaviour
|
|||
|
{
|
|||
|
#region Private.
|
|||
|
/// <summary>
|
|||
|
/// Link indexes for RPCs.
|
|||
|
/// </summary>
|
|||
|
private Dictionary<uint, RpcLinkType> _rpcLinks = new Dictionary<uint, RpcLinkType>();
|
|||
|
#endregion
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Initializes RpcLinks. This will only call once even as host.
|
|||
|
/// </summary>
|
|||
|
private void InitializeOnceRpcLinks()
|
|||
|
{
|
|||
|
if (NetworkManager.IsServer)
|
|||
|
{
|
|||
|
/* Link only data from server to clients. While it is
|
|||
|
* just as easy to link client to server it's usually
|
|||
|
* not needed because server out data is more valuable
|
|||
|
* than server in data. */
|
|||
|
/* Links will be stored in the NetworkBehaviour so that
|
|||
|
* when the object is destroyed they can be added back
|
|||
|
* into availableRpcLinks, within the ServerManager. */
|
|||
|
|
|||
|
ServerManager serverManager = NetworkManager.ServerManager;
|
|||
|
//ObserverRpcs.
|
|||
|
foreach (uint rpcHash in _observersRpcDelegates.Keys)
|
|||
|
{
|
|||
|
if (!MakeLink(rpcHash, RpcType.Observers))
|
|||
|
return;
|
|||
|
}
|
|||
|
//TargetRpcs.
|
|||
|
foreach (uint rpcHash in _targetRpcDelegates.Keys)
|
|||
|
{
|
|||
|
if (!MakeLink(rpcHash, RpcType.Target))
|
|||
|
return;
|
|||
|
}
|
|||
|
//ReconcileRpcs.
|
|||
|
foreach (uint rpcHash in _reconcileRpcDelegates.Keys)
|
|||
|
{
|
|||
|
if (!MakeLink(rpcHash, RpcType.Reconcile))
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
/* Tries to make a link and returns if
|
|||
|
* successful. When a link cannot be made the method
|
|||
|
* should exit as no other links will be possible. */
|
|||
|
bool MakeLink(uint rpcHash, RpcType rpcType)
|
|||
|
{
|
|||
|
if (serverManager.GetRpcLink(out ushort linkIndex))
|
|||
|
{
|
|||
|
_rpcLinks[rpcHash] = new RpcLinkType(linkIndex, rpcType);
|
|||
|
return true;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Returns an estimated length for any Rpc header.
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
private int GetEstimatedRpcHeaderLength()
|
|||
|
{
|
|||
|
/* Imaginary number for how long RPC headers are.
|
|||
|
* They are well under this value but this exist to
|
|||
|
* ensure a writer of appropriate length is pulled
|
|||
|
* from the pool. */
|
|||
|
return 20;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Creates a PooledWriter and writes the header for a rpc.
|
|||
|
/// </summary>
|
|||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|||
|
private PooledWriter CreateLinkedRpc(RpcLinkType link, PooledWriter methodWriter, Channel channel)
|
|||
|
{
|
|||
|
int rpcHeaderBufferLength = GetEstimatedRpcHeaderLength();
|
|||
|
int methodWriterLength = methodWriter.Length;
|
|||
|
//Writer containing full packet.
|
|||
|
PooledWriter writer = WriterPool.GetWriter(rpcHeaderBufferLength + methodWriterLength);
|
|||
|
writer.WriteUInt16(link.LinkIndex);
|
|||
|
//Write length only if reliable.
|
|||
|
if (channel == Channel.Reliable)
|
|||
|
writer.WriteLength(methodWriter.Length);
|
|||
|
//Data.
|
|||
|
writer.WriteArraySegment(methodWriter.GetArraySegment());
|
|||
|
|
|||
|
return writer;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Returns RpcLinks the ServerManager.
|
|||
|
/// </summary>
|
|||
|
private void ReturnRpcLinks()
|
|||
|
{
|
|||
|
if (_rpcLinks.Count == 0)
|
|||
|
return;
|
|||
|
|
|||
|
ServerManager?.StoreRpcLinks(_rpcLinks);
|
|||
|
_rpcLinks.Clear();
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Writes rpcLinks to writer.
|
|||
|
/// </summary>
|
|||
|
internal void WriteRpcLinks(Writer writer)
|
|||
|
{
|
|||
|
PooledWriter rpcLinkWriter = WriterPool.GetWriter();
|
|||
|
foreach (KeyValuePair<uint, RpcLinkType> item in _rpcLinks)
|
|||
|
{
|
|||
|
//RpcLink index.
|
|||
|
rpcLinkWriter.WriteUInt16(item.Value.LinkIndex);
|
|||
|
//Hash.
|
|||
|
rpcLinkWriter.WriteUInt16((ushort)item.Key);
|
|||
|
//True/false if observersRpc.
|
|||
|
rpcLinkWriter.WriteByte((byte)item.Value.RpcType);
|
|||
|
}
|
|||
|
|
|||
|
writer.WriteBytesAndSize(rpcLinkWriter.GetBuffer(), 0, rpcLinkWriter.Length);
|
|||
|
rpcLinkWriter.Dispose();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|