123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- using UnityEngine;
- using UnityEngine.Assertions;
- using Unity.Collections;
- using Unity.Networking.Transport;
- using KairoEngine.Core;
- using Sirenix.OdinInspector;
- namespace KairoEngine.Multiplayer
- {
- [HideMonoScript]
- public class ServerBehaviour : MonoBehaviour
- {
- public NetMsgController netMsgController;
- public string eventStreamName = "ServerEvents";
- public ushort port = 9000;
- public int players = 4;
- public bool autoStart = true;
-
- public bool debug = false;
- public NetworkDriver m_Driver;
- public NativeList<NetworkConnection> m_Connections;
- private bool locked = false;
- private void Awake()
- {
- if(netMsgController == null)
- {
- Debug.LogError("Server is missing NetMsgController!", this);
- return;
- }
- }
- private void Start ()
- {
- if(autoStart) StartServer();
- }
- public void StartServer()
- {
- if(locked) return;
- if(netMsgController == null)
- {
- Debug.LogError("Server cannot start with missing NetMsgController!", this);
- return;
- }
- m_Driver = NetworkDriver.Create();
- var endpoint = NetworkEndPoint.AnyIpv4;
- endpoint.Port = port;
- if (m_Driver.Bind(endpoint) != 0)
- {
- if(debug) Debug.Log($"Failed to bind to port {port}");
- GenericEvents.Trigger($"{eventStreamName}_PortError", $"Failed to bind to port {port}");
- }
- else
- {
- m_Driver.Listen();
- if(debug) Debug.Log($"Server listening on port {port}");
- GenericEvents.Trigger($"{eventStreamName}_Listening", $"Server listening on port {port}");
- locked = true;
- }
- m_Connections = new NativeList<NetworkConnection>(players, Allocator.Persistent);
- }
- public void StopServer()
- {
- NetDisconnectMsg netDisconnectMsg = new NetDisconnectMsg();
- SendNetMsgToAllClients((uint)NetOpCode.Disconnect, netDisconnectMsg);
- Timer.ExecuteRealTime(500, () => {
- if(debug) Debug.Log($"Server has stopped");
- GenericEvents.Trigger($"{eventStreamName}_Stopped", $"Server has stopped");
- m_Driver.Dispose();
- m_Connections.Dispose();
- locked = false;
- });
- }
- public void SendNetMsgToClient(int id, uint code, NetMsg netMsg)
- {
- DataStreamWriter writer = new DataStreamWriter();
- m_Driver.BeginSend(m_Connections[id], out writer);
- netMsgController.SendData(code, netMsg, ref writer, this, id);
- m_Driver.EndSend(writer);
- }
- public void SendNetMsgToAllClients(uint code, NetMsg netMsg)
- {
- for (int i = 0; i < m_Connections.Length; i++)
- {
- Assert.IsTrue(m_Connections[i].IsCreated);
- SendNetMsgToClient(i, code, netMsg);
- }
- }
- public void OnDestroy()
- {
- if(!m_Driver.IsCreated) return;
- m_Driver.Dispose();
- m_Connections.Dispose();
- }
- void Update ()
- {
- if(!m_Driver.IsCreated) return;
- m_Driver.ScheduleUpdate().Complete();
- // CleanUpConnections
- for (int i = 0; i < m_Connections.Length; i++)
- {
- if (!m_Connections[i].IsCreated)
- {
- m_Connections.RemoveAtSwapBack(i);
- --i;
- }
- }
- // AcceptNewConnections
- NetworkConnection c;
- while ((c = m_Driver.Accept()) != default(NetworkConnection))
- {
- m_Connections.Add(c);
- if(debug) Debug.Log($"Accepted a connection (ID {c.InternalId})");
- GenericEvents.Trigger($"{eventStreamName}_ClientConnected", $"Accepted a connection (ID {c.InternalId})", c.InternalId);
- }
- DataStreamReader stream;
- for (int i = 0; i < m_Connections.Length; i++)
- {
- Assert.IsTrue(m_Connections[i].IsCreated);
- NetworkEvent.Type cmd;
- while ((cmd = m_Driver.PopEventForConnection(m_Connections[i], out stream)) != NetworkEvent.Type.Empty)
- {
- if (cmd == NetworkEvent.Type.Data)
- {
- //if(debug) Debug.Log("Server received data from client");
- netMsgController.ReceiveData(ref stream, this, i);
- }
- else if (cmd == NetworkEvent.Type.Disconnect)
- {
- if(debug) Debug.Log($"Client disconnected from server (ID {m_Connections[i].InternalId})");
- GenericEvents.Trigger($"{eventStreamName}_ClientDisconnected", $"Client disconnected from server (ID {m_Connections[i].InternalId})");
- m_Connections[i] = default(NetworkConnection);
- }
- }
- }
- }
- }
- }
|