using System; using UnityEngine; namespace Mirror { // a server's connection TO a LocalClient. // sending messages on this connection causes the client's handler function to be invoked directly class ULocalConnectionToClient : NetworkConnectionToClient { internal ULocalConnectionToServer connectionToServer; public ULocalConnectionToClient() : base(LocalConnectionId) { } public override string address => "localhost"; internal override void Send(ArraySegment segment, int channelId = Channels.DefaultReliable) { connectionToServer.buffer.Write(segment); } // true because local connections never timeout /// internal override bool IsAlive(float timeout) => true; internal void DisconnectInternal() { // set not ready and handle clientscene disconnect in any case // (might be client or host mode here) isReady = false; RemoveObservers(); } /// /// Disconnects this connection. /// public override void Disconnect() { DisconnectInternal(); connectionToServer.DisconnectInternal(); } } internal class LocalConnectionBuffer { readonly NetworkWriter writer = new NetworkWriter(); readonly NetworkReader reader = new NetworkReader(default(ArraySegment)); // The buffer is atleast 1500 bytes long. So need to keep track of // packet count to know how many ArraySegments are in the buffer int packetCount; public void Write(ArraySegment segment) { writer.WriteBytesAndSizeSegment(segment); packetCount++; // update buffer incase writer's length has changed reader.buffer = writer.ToArraySegment(); } public bool HasPackets() { return packetCount > 0; } public ArraySegment GetNextPacket() { ArraySegment packet = reader.ReadBytesAndSizeSegment(); packetCount--; return packet; } public void ResetBuffer() { writer.Reset(); reader.Position = 0; } } // a localClient's connection TO a server. // send messages on this connection causes the server's handler function to be invoked directly. internal class ULocalConnectionToServer : NetworkConnectionToServer { static readonly ILogger logger = LogFactory.GetLogger(typeof(ULocalConnectionToClient)); internal ULocalConnectionToClient connectionToClient; internal readonly LocalConnectionBuffer buffer = new LocalConnectionBuffer(); public override string address => "localhost"; internal override void Send(ArraySegment segment, int channelId = Channels.DefaultReliable) { if (segment.Count == 0) { logger.LogError("LocalConnection.SendBytes cannot send zero bytes"); return; } // handle the server's message directly connectionToClient.TransportReceive(segment, channelId); } internal void Update() { // process internal messages so they are applied at the correct time while (buffer.HasPackets()) { ArraySegment packet = buffer.GetNextPacket(); // Treat host player messages exactly like connected client // to avoid deceptive / misleading behavior differences TransportReceive(packet, Channels.DefaultReliable); } buffer.ResetBuffer(); } /// /// Disconnects this connection. /// internal void DisconnectInternal() { // set not ready and handle clientscene disconnect in any case // (might be client or host mode here) isReady = false; ClientScene.HandleClientDisconnect(this); } /// /// Disconnects this connection. /// public override void Disconnect() { connectionToClient.DisconnectInternal(); DisconnectInternal(); } // true because local connections never timeout /// internal override bool IsAlive(float timeout) => true; } }