GibTreaty

NetworkDownloadHandler.cs

May 19th, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.03 KB | None | 0 0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.Events;
  6. using UnityEngine.Networking;
  7.  
  8. public class NetworkDownloadHandler : MonoBehaviour {
  9.  
  10.     const short ServerReceiver = 10000;
  11.     const short ClientReceiver = 10001;
  12.     const short ClientNotifier = 10002;
  13.     const short ServerNotifier = 10003;
  14.     static int defaultBufferSize = 1024; //max ethernet MTU is ~1400
  15.  
  16.     static NetworkDownloadHandler _current = null;
  17.  
  18.     static List<Guid> transmisionIds = new List<Guid>();
  19.     static Dictionary<Guid, Data> transmissionData = new Dictionary<Guid, Data>();
  20.  
  21.     static UnityEvent<Guid, byte[]> _onCompleteReceive;
  22.     static UnityEvent<Guid, byte[]> _onCompleteSend;
  23.     static UnityEvent<Guid, byte[]> _onPartialReceive;
  24.     static UnityEvent<Guid, byte[]> _onPartialSend;
  25.  
  26.     #region Properties
  27.     static int TransmissionIDCount {
  28.         get { return transmisionIds.Count; }
  29.     }
  30.  
  31.     static NetworkDownloadHandler Current {
  32.         get {
  33.             if(_current == null) CreateNetworkDownloadHandlerObject();
  34.  
  35.             return _current;
  36.         }
  37.     }
  38.  
  39.     public static UnityEvent<Guid, byte[]> OnCompleteReceive {
  40.         get { return _onCompleteReceive; }
  41.     }
  42.  
  43.     public static UnityEvent<Guid, byte[]> OnCompleteSend {
  44.         get { return _onCompleteSend; }
  45.     }
  46.  
  47.     public static UnityEvent<Guid, byte[]> OnPartialReceive {
  48.         get { return _onPartialReceive; }
  49.  
  50.     }
  51.  
  52.     public static UnityEvent<Guid, byte[]> OnPartialSend {
  53.         get { return _onPartialSend; }
  54.     }
  55.     #endregion
  56.  
  57.     public static void ClearDownloadedData() {
  58.         transmisionIds.Clear();
  59.         transmissionData.Clear();
  60.     }
  61.     public static void ClearDownloadedData(Func<KeyValuePair<Guid, Data>, bool> requirements) {
  62.         List<Guid> clearData = new List<Guid>();
  63.  
  64.         foreach(var pair in transmissionData)
  65.             if(requirements(pair))
  66.                 clearData.Add(pair.Key);
  67.  
  68.         foreach(var clear in clearData) {
  69.             transmisionIds.Remove(clear);
  70.             transmissionData.Remove(clear);
  71.         }
  72.     }
  73.  
  74.     IEnumerator ClientSendDataRoutine(Guid id, byte[] data) {
  75.         NotifyServerOfDataBeingSent(id, data.Length);
  76.  
  77.         yield return null;
  78.  
  79.         transmisionIds.Add(id);
  80.  
  81.         var transmitData = new Data(data);
  82.         var bufferSize = defaultBufferSize;
  83.  
  84.         while(transmitData.currentIndex < transmitData.data.Length - 1) {
  85.             var remaining = transmitData.data.Length - transmitData.currentIndex;
  86.  
  87.             if(remaining < bufferSize)
  88.                 bufferSize = remaining;
  89.  
  90.             var bufferedData = new byte[bufferSize];
  91.  
  92.             Array.Copy(transmitData.data, transmitData.currentIndex, bufferedData, 0, bufferSize);
  93.  
  94.             SendDataToServer(id, bufferedData);
  95.             transmitData.currentIndex += bufferSize;
  96.             transmitData.LastTransmissionTime = Time.realtimeSinceStartup;
  97.  
  98.             yield return null;
  99.  
  100.             OnPartialSend?.Invoke(id, bufferedData);
  101.         }
  102.  
  103.         transmisionIds.Remove(id);
  104.     }
  105.  
  106.     public static Guid ClientSendData(byte[] data) {
  107.         var id = Guid.NewGuid();
  108.  
  109.         ClientSendData(id, data);
  110.  
  111.         return id;
  112.     }
  113.     public static void ClientSendData(Guid id, byte[] data) {
  114.         Current.StartCoroutine(Current.ClientSendDataRoutine(id, data));
  115.     }
  116.  
  117.     static void CreateNetworkDownloadHandlerObject() {
  118.         var gameObject = new GameObject("Network Download Handler", typeof(NetworkDownloadHandler));
  119.  
  120.         _current = gameObject.GetComponent<NetworkDownloadHandler>();
  121.     }
  122.  
  123.     NetworkWriter GetDataWriter(short messageType, Guid id, byte[] data) {
  124.         var writer = new NetworkWriter();
  125.  
  126.         writer.StartMessage(messageType);
  127.         writer.WriteBytesFull(id.ToByteArray());
  128.         writer.WriteBytesFull(data);
  129.         writer.FinishMessage();
  130.  
  131.         return writer;
  132.     }
  133.  
  134.     public static Data GetStoredData(Guid id) {
  135.         Data data;
  136.  
  137.         if(transmissionData.TryGetValue(id, out data))
  138.             return data;
  139.  
  140.         return null;
  141.     }
  142.  
  143.     public static Guid GetTransmissionID(int index) {
  144.         return transmisionIds[index];
  145.     }
  146.  
  147.     void NotifyClientsOfDataBeingSent(Guid id, int dataLength, NetworkConnection[] sendToConnections) {
  148.         var writer = new NetworkWriter();
  149.  
  150.         writer.StartMessage(ClientNotifier);
  151.         writer.WriteBytesFull(id.ToByteArray());
  152.         writer.Write(dataLength);
  153.         writer.FinishMessage();
  154.  
  155.         foreach(var connection in sendToConnections)
  156.             connection.SendWriter(writer, Channels.DefaultReliable);
  157.     }
  158.  
  159.     void NotifyServerOfDataBeingSent(Guid id, int dataLength) {
  160.         var writer = new NetworkWriter();
  161.  
  162.         writer.StartMessage(ServerNotifier);
  163.         writer.WriteBytesFull(id.ToByteArray());
  164.         writer.Write(dataLength);
  165.         writer.FinishMessage();
  166.  
  167.         if(ClientScene.readyConnection != null)
  168.             ClientScene.readyConnection.SendWriter(writer, Channels.DefaultReliable);
  169.     }
  170.  
  171.     static void ReceiveData(NetworkMessage netMsg) {
  172.         var id = new Guid(netMsg.reader.ReadBytesAndSize());
  173.         var bufferedData = netMsg.reader.ReadBytesAndSize();
  174.  
  175.         if(!transmissionData.ContainsKey(id))
  176.             return;
  177.  
  178.         var storedData = transmissionData[id];
  179.         Array.Copy(bufferedData, 0, storedData.data, storedData.currentIndex, bufferedData.Length);
  180.  
  181.         storedData.currentIndex += storedData.data.Length;
  182.         storedData.LastTransmissionTime = Time.realtimeSinceStartup;
  183.  
  184.         OnPartialReceive?.Invoke(id, bufferedData);
  185.  
  186.         if(storedData.currentIndex < storedData.data.Length - 1)
  187.             return;
  188.  
  189.         transmissionData.Remove(id);
  190.  
  191.         OnCompleteReceive?.Invoke(id, storedData.data);
  192.     }
  193.  
  194.     public static void RegisterClientHandlers() {
  195.         NetworkManager.singleton.client.RegisterHandler(ClientReceiver, ReceiveData);
  196.         NetworkManager.singleton.client.RegisterHandler(ClientNotifier, TransmissionNotifier);
  197.     }
  198.  
  199.     public static void RegisterServerHandlers() {
  200.         NetworkServer.RegisterHandler(ServerReceiver, ReceiveData);
  201.         NetworkServer.RegisterHandler(ServerNotifier, TransmissionNotifier);
  202.     }
  203.  
  204.     public static Guid SendData(byte[] data, params NetworkConnection[] sendToConnections) {
  205.         var id = Guid.NewGuid();
  206.  
  207.         SendData(id, data, sendToConnections);
  208.  
  209.         return id;
  210.     }
  211.     public static void SendData(Guid id, byte[] data, params NetworkConnection[] sendToConnections) {
  212.         if(NetworkServer.active)
  213.             ServerSendData(id, data, sendToConnections);
  214.         else if(NetworkServer.active)
  215.             ClientSendData(id, data);
  216.     }
  217.  
  218.     void SendDataToClient(Guid id, byte[] data, NetworkConnection[] sendToConnections) {
  219.         var writer = GetDataWriter(ClientReceiver, id, data);
  220.  
  221.         foreach(var connection in sendToConnections)
  222.             connection.SendWriter(writer, Channels.DefaultReliable);
  223.     }
  224.  
  225.     void SendDataToServer(Guid id, byte[] data) {
  226.         var writer = GetDataWriter(ServerReceiver, id, data);
  227.  
  228.         if(ClientScene.readyConnection != null)
  229.             ClientScene.readyConnection.SendWriter(writer, Channels.DefaultReliable);
  230.     }
  231.  
  232.     public static Guid ServerSendData(byte[] data, NetworkConnection[] sendToConnections) {
  233.         var id = Guid.NewGuid();
  234.  
  235.         ServerSendData(id, data, sendToConnections);
  236.  
  237.         return id;
  238.     }
  239.     public static void ServerSendData(Guid id, byte[] data, NetworkConnection[] sendToConnections) {
  240.         Current.StartCoroutine(Current.ServerSendDataRoutine(id, data, sendToConnections));
  241.     }
  242.  
  243.     IEnumerator ServerSendDataRoutine(Guid id, byte[] data, NetworkConnection[] sendToConnections) {
  244.         NotifyClientsOfDataBeingSent(id, data.Length, sendToConnections);
  245.  
  246.         yield return null;
  247.  
  248.         transmisionIds.Add(id);
  249.  
  250.         var transmitData = new Data(data);
  251.         var bufferSize = defaultBufferSize;
  252.  
  253.         while(transmitData.currentIndex < transmitData.data.Length - 1) {
  254.             var remaining = transmitData.data.Length - transmitData.currentIndex;
  255.  
  256.             if(remaining < bufferSize)
  257.                 bufferSize = remaining;
  258.  
  259.             var bufferedData = new byte[bufferSize];
  260.  
  261.             Array.Copy(transmitData.data, transmitData.currentIndex, bufferedData, 0, bufferSize);
  262.  
  263.             SendDataToClient(id, bufferedData, sendToConnections);
  264.             transmitData.currentIndex += bufferSize;
  265.             transmitData.LastTransmissionTime = Time.realtimeSinceStartup;
  266.  
  267.             yield return null;
  268.  
  269.             OnPartialSend?.Invoke(id, bufferedData);
  270.         }
  271.  
  272.         transmisionIds.Remove(id);
  273.     }
  274.  
  275.     static void TransmissionNotifier(NetworkMessage netMsg) {
  276.         var id = new Guid(netMsg.reader.ReadBytesAndSize());
  277.         var size = netMsg.reader.ReadInt32();
  278.  
  279.         if(transmissionData.ContainsKey(id))
  280.             return;
  281.  
  282.         transmissionData[id] = new Data(new byte[size]);
  283.     }
  284.  
  285.     public class Data {
  286.         public int currentIndex;
  287.         public byte[] data;
  288.  
  289.         #region Properties
  290.         /// <summary>Time since starting the download</summary>
  291.         public float ElapsedTime {
  292.             get { return Time.realtimeSinceStartup - TimeStarted; }
  293.         }
  294.  
  295.         /// <summary>Last time data was sent or received</summary>
  296.         public float LastTransmissionTime { get; set; }
  297.  
  298.         /// <summary>Time that the data was started being sent or received</summary>
  299.         public float TimeStarted { get; private set; }
  300.  
  301.         /// <summary>Time it took to finish downloading or uploading the data</summary>
  302.         public float TotalTransmissionTime {
  303.             get { return LastTransmissionTime - TimeStarted; }
  304.         }
  305.         #endregion
  306.  
  307.         public Data(byte[] data) {
  308.             currentIndex = 0;
  309.             this.data = data;
  310.  
  311.             TimeStarted = Time.realtimeSinceStartup;
  312.         }
  313.     }
  314. }
Add Comment
Please, Sign In to add comment