Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.Events;
- using UnityEngine.Networking;
- public class NetworkDownloadHandler : MonoBehaviour {
- const short ServerReceiver = 10000;
- const short ClientReceiver = 10001;
- const short ClientNotifier = 10002;
- const short ServerNotifier = 10003;
- static int defaultBufferSize = 1024; //max ethernet MTU is ~1400
- static NetworkDownloadHandler _current = null;
- static List<Guid> transmisionIds = new List<Guid>();
- static Dictionary<Guid, Data> transmissionData = new Dictionary<Guid, Data>();
- static UnityEvent<Guid, byte[]> _onCompleteReceive;
- static UnityEvent<Guid, byte[]> _onCompleteSend;
- static UnityEvent<Guid, byte[]> _onPartialReceive;
- static UnityEvent<Guid, byte[]> _onPartialSend;
- #region Properties
- static int TransmissionIDCount {
- get { return transmisionIds.Count; }
- }
- static NetworkDownloadHandler Current {
- get {
- if(_current == null) CreateNetworkDownloadHandlerObject();
- return _current;
- }
- }
- public static UnityEvent<Guid, byte[]> OnCompleteReceive {
- get { return _onCompleteReceive; }
- }
- public static UnityEvent<Guid, byte[]> OnCompleteSend {
- get { return _onCompleteSend; }
- }
- public static UnityEvent<Guid, byte[]> OnPartialReceive {
- get { return _onPartialReceive; }
- }
- public static UnityEvent<Guid, byte[]> OnPartialSend {
- get { return _onPartialSend; }
- }
- #endregion
- public static void ClearDownloadedData() {
- transmisionIds.Clear();
- transmissionData.Clear();
- }
- public static void ClearDownloadedData(Func<KeyValuePair<Guid, Data>, bool> requirements) {
- List<Guid> clearData = new List<Guid>();
- foreach(var pair in transmissionData)
- if(requirements(pair))
- clearData.Add(pair.Key);
- foreach(var clear in clearData) {
- transmisionIds.Remove(clear);
- transmissionData.Remove(clear);
- }
- }
- IEnumerator ClientSendDataRoutine(Guid id, byte[] data) {
- NotifyServerOfDataBeingSent(id, data.Length);
- yield return null;
- transmisionIds.Add(id);
- var transmitData = new Data(data);
- var bufferSize = defaultBufferSize;
- while(transmitData.currentIndex < transmitData.data.Length - 1) {
- var remaining = transmitData.data.Length - transmitData.currentIndex;
- if(remaining < bufferSize)
- bufferSize = remaining;
- var bufferedData = new byte[bufferSize];
- Array.Copy(transmitData.data, transmitData.currentIndex, bufferedData, 0, bufferSize);
- SendDataToServer(id, bufferedData);
- transmitData.currentIndex += bufferSize;
- transmitData.LastTransmissionTime = Time.realtimeSinceStartup;
- yield return null;
- OnPartialSend?.Invoke(id, bufferedData);
- }
- transmisionIds.Remove(id);
- }
- public static Guid ClientSendData(byte[] data) {
- var id = Guid.NewGuid();
- ClientSendData(id, data);
- return id;
- }
- public static void ClientSendData(Guid id, byte[] data) {
- Current.StartCoroutine(Current.ClientSendDataRoutine(id, data));
- }
- static void CreateNetworkDownloadHandlerObject() {
- var gameObject = new GameObject("Network Download Handler", typeof(NetworkDownloadHandler));
- _current = gameObject.GetComponent<NetworkDownloadHandler>();
- }
- NetworkWriter GetDataWriter(short messageType, Guid id, byte[] data) {
- var writer = new NetworkWriter();
- writer.StartMessage(messageType);
- writer.WriteBytesFull(id.ToByteArray());
- writer.WriteBytesFull(data);
- writer.FinishMessage();
- return writer;
- }
- public static Data GetStoredData(Guid id) {
- Data data;
- if(transmissionData.TryGetValue(id, out data))
- return data;
- return null;
- }
- public static Guid GetTransmissionID(int index) {
- return transmisionIds[index];
- }
- void NotifyClientsOfDataBeingSent(Guid id, int dataLength, NetworkConnection[] sendToConnections) {
- var writer = new NetworkWriter();
- writer.StartMessage(ClientNotifier);
- writer.WriteBytesFull(id.ToByteArray());
- writer.Write(dataLength);
- writer.FinishMessage();
- foreach(var connection in sendToConnections)
- connection.SendWriter(writer, Channels.DefaultReliable);
- }
- void NotifyServerOfDataBeingSent(Guid id, int dataLength) {
- var writer = new NetworkWriter();
- writer.StartMessage(ServerNotifier);
- writer.WriteBytesFull(id.ToByteArray());
- writer.Write(dataLength);
- writer.FinishMessage();
- if(ClientScene.readyConnection != null)
- ClientScene.readyConnection.SendWriter(writer, Channels.DefaultReliable);
- }
- static void ReceiveData(NetworkMessage netMsg) {
- var id = new Guid(netMsg.reader.ReadBytesAndSize());
- var bufferedData = netMsg.reader.ReadBytesAndSize();
- if(!transmissionData.ContainsKey(id))
- return;
- var storedData = transmissionData[id];
- Array.Copy(bufferedData, 0, storedData.data, storedData.currentIndex, bufferedData.Length);
- storedData.currentIndex += storedData.data.Length;
- storedData.LastTransmissionTime = Time.realtimeSinceStartup;
- OnPartialReceive?.Invoke(id, bufferedData);
- if(storedData.currentIndex < storedData.data.Length - 1)
- return;
- transmissionData.Remove(id);
- OnCompleteReceive?.Invoke(id, storedData.data);
- }
- public static void RegisterClientHandlers() {
- NetworkManager.singleton.client.RegisterHandler(ClientReceiver, ReceiveData);
- NetworkManager.singleton.client.RegisterHandler(ClientNotifier, TransmissionNotifier);
- }
- public static void RegisterServerHandlers() {
- NetworkServer.RegisterHandler(ServerReceiver, ReceiveData);
- NetworkServer.RegisterHandler(ServerNotifier, TransmissionNotifier);
- }
- public static Guid SendData(byte[] data, params NetworkConnection[] sendToConnections) {
- var id = Guid.NewGuid();
- SendData(id, data, sendToConnections);
- return id;
- }
- public static void SendData(Guid id, byte[] data, params NetworkConnection[] sendToConnections) {
- if(NetworkServer.active)
- ServerSendData(id, data, sendToConnections);
- else if(NetworkServer.active)
- ClientSendData(id, data);
- }
- void SendDataToClient(Guid id, byte[] data, NetworkConnection[] sendToConnections) {
- var writer = GetDataWriter(ClientReceiver, id, data);
- foreach(var connection in sendToConnections)
- connection.SendWriter(writer, Channels.DefaultReliable);
- }
- void SendDataToServer(Guid id, byte[] data) {
- var writer = GetDataWriter(ServerReceiver, id, data);
- if(ClientScene.readyConnection != null)
- ClientScene.readyConnection.SendWriter(writer, Channels.DefaultReliable);
- }
- public static Guid ServerSendData(byte[] data, NetworkConnection[] sendToConnections) {
- var id = Guid.NewGuid();
- ServerSendData(id, data, sendToConnections);
- return id;
- }
- public static void ServerSendData(Guid id, byte[] data, NetworkConnection[] sendToConnections) {
- Current.StartCoroutine(Current.ServerSendDataRoutine(id, data, sendToConnections));
- }
- IEnumerator ServerSendDataRoutine(Guid id, byte[] data, NetworkConnection[] sendToConnections) {
- NotifyClientsOfDataBeingSent(id, data.Length, sendToConnections);
- yield return null;
- transmisionIds.Add(id);
- var transmitData = new Data(data);
- var bufferSize = defaultBufferSize;
- while(transmitData.currentIndex < transmitData.data.Length - 1) {
- var remaining = transmitData.data.Length - transmitData.currentIndex;
- if(remaining < bufferSize)
- bufferSize = remaining;
- var bufferedData = new byte[bufferSize];
- Array.Copy(transmitData.data, transmitData.currentIndex, bufferedData, 0, bufferSize);
- SendDataToClient(id, bufferedData, sendToConnections);
- transmitData.currentIndex += bufferSize;
- transmitData.LastTransmissionTime = Time.realtimeSinceStartup;
- yield return null;
- OnPartialSend?.Invoke(id, bufferedData);
- }
- transmisionIds.Remove(id);
- }
- static void TransmissionNotifier(NetworkMessage netMsg) {
- var id = new Guid(netMsg.reader.ReadBytesAndSize());
- var size = netMsg.reader.ReadInt32();
- if(transmissionData.ContainsKey(id))
- return;
- transmissionData[id] = new Data(new byte[size]);
- }
- public class Data {
- public int currentIndex;
- public byte[] data;
- #region Properties
- /// <summary>Time since starting the download</summary>
- public float ElapsedTime {
- get { return Time.realtimeSinceStartup - TimeStarted; }
- }
- /// <summary>Last time data was sent or received</summary>
- public float LastTransmissionTime { get; set; }
- /// <summary>Time that the data was started being sent or received</summary>
- public float TimeStarted { get; private set; }
- /// <summary>Time it took to finish downloading or uploading the data</summary>
- public float TotalTransmissionTime {
- get { return LastTransmissionTime - TimeStarted; }
- }
- #endregion
- public Data(byte[] data) {
- currentIndex = 0;
- this.data = data;
- TimeStarted = Time.realtimeSinceStartup;
- }
- }
- }
Add Comment
Please, Sign In to add comment