using System.Collections.Generic; using UnityEngine; using Unity.Jobs; using Unity.Collections; using Unity.Networking.Transport; using Sirenix.OdinInspector; using KairoEngine.Core; namespace KairoEngine.Multiplayer { [HideMonoScript] public class JobifiedClientBehaviour : MonoBehaviour { [HideInInspector] public NetworkDriver m_Driver; [HideInInspector] public NativeArray m_Connection; [HideInInspector] public NativeArray m_Done; [HideInInspector] public JobHandle ClientJobHandle; [HideInInspector] private NativeQueue m_eventQueue; public string address = "192.168.1.1"; public ushort port = 9000; public bool autoConnectOnStart = true; private bool resourceLock = false; private int disconnectNow = 0; void Start () { if(autoConnectOnStart) ConnectToServer(); } public void ConnectToServer() { resourceLock = true; m_eventQueue = new NativeQueue(Allocator.Persistent); m_Driver = NetworkDriver.Create(); m_Connection = new NativeArray(1, Allocator.Persistent); m_Done = new NativeArray(1, Allocator.Persistent); var endpoint = NetworkEndPoint.Parse(address, port); m_Connection[0] = m_Driver.Connect(endpoint); GenericEvents.Trigger("ClientEvent", $"Connecting to {address}:{port}"); } public void DisconnectFromServer() { disconnectNow = 1; //m_Connection[0].Disconnect(m_Driver); //m_Connection[0] = default(NetworkConnection); //resourceLock = false; //Cleanup(); //GenericEvents.Trigger("ClientEvent", $"Disconected from server"); } public void OnDestroy() { Cleanup(); } void Update() { if(resourceLock == false) return; ClientJobHandle.Complete(); while(m_eventQueue.TryDequeue(out JobEvent jobEvent)) { TriggerJobEvent(jobEvent); } if (!m_Connection[0].IsCreated && disconnectNow == 1) { Cleanup(); return; } if (!m_Connection[0].IsCreated) return; var job = new ClientUpdateJob { driver = m_Driver, connection = m_Connection, done = m_Done, eventQueue = m_eventQueue.AsParallelWriter(), disconnect = disconnectNow }; ClientJobHandle = m_Driver.ScheduleUpdate(); ClientJobHandle = job.Schedule(ClientJobHandle); } public virtual void SendToServer(NetMsg msg) { DataStreamWriter writer; m_Driver.BeginSend(m_Connection[0], out writer); msg.Serialize(ref writer); m_Driver.EndSend(writer); } private void Cleanup() { if(resourceLock == false) return; ClientJobHandle.Complete(); m_Connection.Dispose(); m_Driver.Dispose(); m_Done.Dispose(); m_eventQueue.Dispose(); resourceLock = false; disconnectNow = 0; } public void TriggerJobEvent(JobEvent jobEvent) { switch (jobEvent.code) { case 1: GenericEvents.Trigger("ClientEvent", $"Connected to server"); break; case 2: GenericEvents.Trigger("ClientEvent", $"Disconnected from server"); break; case 3: GenericEvents.Trigger("ClientEvent", $"Data received from server"); break; case 4: GenericEvents.Trigger("ClientEvent", $"Error connecting to server"); break; default: break; } } } struct ClientUpdateJob : IJob { public NetworkDriver driver; public NativeArray connection; public NativeArray done; public NativeQueue.ParallelWriter eventQueue; public int disconnect; public void Execute() { if (!connection[0].IsCreated) { if (done[0] != 1) Debug.Log("Something went wrong during connect"); eventQueue.Enqueue(new JobEvent((int)NetworkingEvents.Message.ErrorConnectingToServer)); return; } // Receive Data from connections DataStreamReader stream; NetworkEvent.Type cmd; while ((cmd = connection[0].PopEvent(driver, out stream)) != NetworkEvent.Type.Empty) { if (cmd == NetworkEvent.Type.Connect) { Debug.Log("We are now connected to the server"); eventQueue.Enqueue(new JobEvent((int)NetworkingEvents.Message.ClientConnected)); uint value = 1; DataStreamWriter writer = new DataStreamWriter(); var result = driver.BeginSend(connection[0], out writer); writer.WriteUInt(value); driver.EndSend(writer); } else if (cmd == NetworkEvent.Type.Data) { uint value = stream.ReadUInt(); Debug.Log("Got the value = " + value + " back from the server"); eventQueue.Enqueue(new JobEvent((int)NetworkingEvents.Message.ClientReceivedData)); // And finally change the `done[0]` to `1` done[0] = 1; //connection[0].Disconnect(driver); //connection[0] = default(NetworkConnection); //eventQueue.Enqueue(new JobEvent((int)NetworkingEvents.Message.Disconnected)); } else if (cmd == NetworkEvent.Type.Disconnect) { eventQueue.Enqueue(new JobEvent((int)NetworkingEvents.Message.ClientDisconnected)); Debug.Log("Client got disconnected from server"); connection[0] = default(NetworkConnection); } } // Send Data to connections // Disconnect if(disconnect == 1) { eventQueue.Enqueue(new JobEvent((int)NetworkingEvents.Message.ClientDisconnected)); Debug.Log("Client disconnected from server"); connection[0].Disconnect(driver); connection[0] = default(NetworkConnection); } } } }