using System.Linq; using UnityEngine; using UnityEngine.Networking; using System.Collections; using System.Collections.Generic; using System.Net.Sockets; using System.Net; using System.Text; using System; using System.IO; using UnityEngine.UI; public class Client : MonoBehaviour { const byte PING_PACKET = 30; enum ImageCMD { receiveImage, streamStart, streamStop }; public GameObject UserInfo; public GameObject UserCameraImage; public static Client instance; public const int socketPort = 87; public const int webglPort = 86; public uint account_id = 0; //id акка public uint company_id; string ACCOUNT_NAME = ""; bool login_sent; bool entered = false; bool dc = false; public bool connected = false; int lag = 0; double last_ping_time = 0; static string[] Servers = { "dev.prmsys.net", "localhost", "corp.prmsys.net" }; static bool ShowPacketsSent = true; static bool printPacketsShort = true; //private const bool ShowPacketsSent = false; // private const bool ShowPackets = true; //ставится только в редакторе static bool ShowPackets = false; //ставится только в редакторе double initial_timer; int internal_timer = 0; public double timer { get { return DateTime.Now.Ticks / 10000000.0; //секунды } } public static string ServerName; public static bool StartConnectFlag = false; #if UNITY_WEBGL public static WebSocket Mysocket; #else public static Socket Mysocket; #endif Dictionary PacketLength = new Dictionary(); public delegate void OnReceive(byte[] bytedata); public static OnReceive[] packets = new OnReceive[255]; public string _dataPath = ""; GameObject drone; public static ClientType clientType; public enum ClientType { Desktop, Web } public static void SendEnqueue(byte[] bytedata) { SendQueue.Enqueue(bytedata); } private void Awake() { instance = this; ServerName = PlayerPrefs.GetString("server"); if (ServerName == "") ServerName = Servers[0]; Register(1, Disconnect, 5); Register(2, Login, 9); Register(3, User.CoordinatesReceive); Register(30, Myping, 3); Register(47, User.UsersReceive); Register(48, Beacon.ReceiveBeacons); Register(51, Wall.ReceiveWalls); Register(52, Zone.ReceiveZones); Register(54, Location.ReceiveLocations); Register(55, ImageReceive); //set data path //if (Application.platform == RuntimePlatform.WindowsWebPlayer || // Application.platform == RuntimePlatform.OSXWebPlayer) if (Application.platform == RuntimePlatform.WebGLPlayer) { _dataPath = Application.dataPath + "/StreamingAssets"; clientType = ClientType.Web; } else if (Application.platform == RuntimePlatform.Android) { _dataPath = "jar:file://" + Application.dataPath + "!/assets"; clientType = ClientType.Web; } else { _dataPath = "file://" + Application.dataPath + "/StreamingAssets"; ; clientType = ClientType.Desktop; } _dataPath = Application.streamingAssetsPath; //Debug.Log("_dataPath " + _dataPath); } public int LagCount { get { return lagpoints.Count; } } int totallag { get { int q = 0; foreach (var g in lagpoints) { q += g; } return q; } } Queue lagpoints = new Queue(); public int Averagelag { get { if (lagpoints.Count > 0) return totallag / lagpoints.Count; return 0; } } public void Myping(byte[] bytedata) { last_ping_time = timer; int lag = BitConverter.ToUInt16(bytedata, 1); //print("Myping " + lag); this.lag = lag; if (lagpoints.Count > 5) lagpoints.Dequeue(); lagpoints.Enqueue(lag); List list = new List(); list.Add(30); list.Add(1); SendEnqueue(list.ToArray()); } public void Disconnect(byte[] bytedata) { uint bid = BitConverter.ToUInt32(bytedata, 1); if (bid == account_id) Exit(); else { print("disc id " + bid); } } public void Exit() { print("Client Exit"); connected = false; login_sent = false; if (Mysocket != null) { Mysocket.Close(); Mysocket = null; } connect_started = new DateTime(); totalbytes = 0; account_id = 0; ACCOUNT_NAME = ""; connected = false; sendDone = false; receiveDone = false; connectDone = false; StartConnectFlag = false; UnityEngine.SceneManagement.SceneManager.LoadScene(0); } //пакет с 1 параметром = 1 public static void SendOneBytePacket(byte num) { SendOneByteParamPacket(num, 1); } public static void SendOneByteTwoParamsPacket(byte num, byte param1, byte param2) { byte[] data = { num, param1, param2 }; SendEnqueue(data); } public static void SendThreeParamsIntPacket(byte num, int param1, int param2, int param3) { List list = new List(); list.Add(num); list.AddRange(BitConverter.GetBytes(param1)); list.AddRange(BitConverter.GetBytes(param2)); list.AddRange(BitConverter.GetBytes(param3)); SendEnqueue(list.ToArray()); } //пакет с 1 1-байтовым параметром public static void SendOneByteParamPacket(byte num, byte param) { byte[] data = { num, param }; byteSend(data); } //пакет с 1 4-байтовым параметром public static void SendTwoByteParamPacket(byte num, ushort param) { List list = new List(); list.Add(num); list.AddRange(BitConverter.GetBytes(param)); SendEnqueue(list.ToArray()); } //пакет с 1 4-байтовым параметром public static void SendFourByteParamPacket(byte num, uint param) { List list = new List(); list.Add(num); list.AddRange(BitConverter.GetBytes(param)); SendEnqueue(list.ToArray()); } public static DateTime connect_started; public void Login(byte[] bytedata) { uint accid = BitConverter.ToUInt32(bytedata, 1); if (accid == 0xFFFFFFFF) { Debug.LogError("Login or password incorrect"); AuthorizationController.error = true; return; } else if (accid == 0xFFFFFFFE) { Debug.LogError("Account was already connected"); return; } else if (accid == 0xFFFFFFFD) { Debug.LogError("Incorrect client version"); return; } company_id = BitConverter.ToUInt32(bytedata, 5); AuthorizationController.success = true; account_id = accid; //Location.LocationsRequest(); } #region system functions public void Register(int packnum, OnReceive func) { packets[packnum] = func; } private void Register(int packnum, OnReceive func, int len) { packets[packnum] = func; if (len > 1) PacketLength[packnum] = len; } public int GetLength(byte[] data, int num, int offset) { int leng; if (!PacketLength.ContainsKey(num)) { var rest = data.Length - offset; //packet not full if (rest < 5) return 1; leng = BitConverter.ToInt32(data, offset + 1); } else leng = PacketLength[num]; return leng; } int maximumPacketsPerUpdate = 50; public string tempflag; public static void printBytes(byte[] bytedata, bool sent = false) { var num = bytedata[0]; if (num == PING_PACKET) return; var func = packets[num]; string callBackName = "Unknown packet "; if (func != null) callBackName = packets[num].Method.Name + " "; string prefix; if (!sent) { if (!ShowPackets) return; prefix = "received "; } else { if (!ShowPacketsSent) return; prefix = "sent "; } byte[] newbuf = new byte[bytedata.Length]; Array.Copy(bytedata, newbuf, bytedata.Length); string mygg = prefix + $"{callBackName}[{num}] length " + bytedata.Length; //Печатаем отправленные байты! if (!printPacketsShort) { mygg += " bytes: "; foreach (byte b in newbuf) { mygg += b + " "; } } Debug.Log(mygg); } public void Update() { #if UNITY_WEBGL Receive(); #endif if (instance == null || !entered) //вход не нажат, ждем { return; } else { if (!StartConnectFlag) { StartCoroutine(Connect()); StartConnectFlag = true; } } int from_connect = DateTime.Now.Subtract(connect_started).Seconds; if (from_connect > 7 && from_connect != DateTime.Now.Second && account_id == 0) { Exit(); } var processedCount = 0; while (PacketQueue.Count > 0 && processedCount < maximumPacketsPerUpdate) //если длина очереди с пакетами ==0 { byte[] packetbytes; lock (packetqueuelock) { packetbytes = PacketQueue.Dequeue(); } int offset = 0; int totallen = 0; int num = packetbytes[0]; int leng = GetLength(packetbytes, packetbytes[0], 0); if (leng <= packetbytes.Length) { while (offset < packetbytes.Length) { num = packetbytes[offset]; leng = GetLength(packetbytes, num, offset); totallen += leng; byte[] newpack = new byte[leng]; Array.Copy(packetbytes, offset, newpack, 0, leng); offset += leng; printBytes(newpack); processedCount++; packets[num](newpack); //запустить OnReceive функцию } } } } public void Start() { tempflag = ""; entered = true; CreateCameraImage(); } void CreateCameraImage() { UserInfo = new GameObject(); var canvas = GameObject.Find("Canvas"); UserCameraImage = new GameObject(); UserCameraImage.transform.parent = canvas.transform; var rawimg = UserCameraImage.AddComponent(); UserCameraImage.name = "UserCameraImage"; UserCameraImage.transform.localScale = new Vector3(1, 1, 1); UserCameraImage.transform.localPosition = new Vector3(0, 0, 0); UserCameraImage.transform.localEulerAngles = new Vector3(0, 0, 0); rawimg.rectTransform.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Right, 0f, 640f); rawimg.rectTransform.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, 0f, 480f); var button = UserCameraImage.AddComponent