mirror of
				https://github.com/DerTyp7/defrain-shooter-unity.git
				synced 2025-10-30 04:57:10 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			170 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| 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
 | |
|     public class LocalConnectionToClient : NetworkConnectionToClient
 | |
|     {
 | |
|         internal LocalConnectionToServer connectionToServer;
 | |
| 
 | |
|         public LocalConnectionToClient() : base(LocalConnectionId) {}
 | |
| 
 | |
|         public override string address => "localhost";
 | |
| 
 | |
|         // Send stage two: serialized NetworkMessage as ArraySegment<byte>
 | |
|         internal override void Send(ArraySegment<byte> segment, int channelId = Channels.Reliable)
 | |
|         {
 | |
|             // get a writer to copy the message into since the segment is only
 | |
|             // valid until returning.
 | |
|             // => pooled writer will be returned to pool when dequeuing.
 | |
|             // => WriteBytes instead of WriteArraySegment because the latter
 | |
|             //    includes a 4 bytes header. we just want to write raw.
 | |
|             //Debug.Log($"Enqueue {BitConverter.ToString(segment.Array, segment.Offset, segment.Count)}");
 | |
|             PooledNetworkWriter writer = NetworkWriterPool.GetWriter();
 | |
|             writer.WriteBytes(segment.Array, segment.Offset, segment.Count);
 | |
|             connectionToServer.queue.Enqueue(writer);
 | |
|         }
 | |
| 
 | |
|         // 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;
 | |
|             RemoveFromObservingsObservers();
 | |
|         }
 | |
| 
 | |
|         /// <summary>Disconnects this connection.</summary>
 | |
|         public override void Disconnect()
 | |
|         {
 | |
|             DisconnectInternal();
 | |
|             connectionToServer.DisconnectInternal();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // a localClient's connection TO a server.
 | |
|     // send messages on this connection causes the server's handler function to be invoked directly.
 | |
|     public class LocalConnectionToServer : NetworkConnectionToServer
 | |
|     {
 | |
|         internal LocalConnectionToClient connectionToClient;
 | |
| 
 | |
|         // packet queue
 | |
|         internal readonly Queue<PooledNetworkWriter> queue = new Queue<PooledNetworkWriter>();
 | |
| 
 | |
|         public override string address => "localhost";
 | |
| 
 | |
|         // see caller for comments on why we need this
 | |
|         bool connectedEventPending;
 | |
|         bool disconnectedEventPending;
 | |
|         internal void QueueConnectedEvent() => connectedEventPending = true;
 | |
|         internal void QueueDisconnectedEvent() => disconnectedEventPending = true;
 | |
| 
 | |
|         // Send stage two: serialized NetworkMessage as ArraySegment<byte>
 | |
|         internal override void Send(ArraySegment<byte> segment, int channelId = Channels.Reliable)
 | |
|         {
 | |
|             if (segment.Count == 0)
 | |
|             {
 | |
|                 Debug.LogError("LocalConnection.SendBytes cannot send zero bytes");
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             // OnTransportData assumes batching.
 | |
|             // so let's make a batch with proper timestamp prefix.
 | |
|             Batcher batcher = GetBatchForChannelId(channelId);
 | |
|             batcher.AddMessage(segment);
 | |
| 
 | |
|             // flush it to the server's OnTransportData immediately.
 | |
|             // local connection to server always invokes immediately.
 | |
|             using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
 | |
|             {
 | |
|                 // make a batch with our local time (double precision)
 | |
|                 if (batcher.MakeNextBatch(writer, NetworkTime.localTime))
 | |
|                 {
 | |
|                     NetworkServer.OnTransportData(connectionId, writer.ToArraySegment(), channelId);
 | |
|                 }
 | |
|                 else Debug.LogError("Local connection failed to make batch. This should never happen.");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal override void Update()
 | |
|         {
 | |
|             base.Update();
 | |
| 
 | |
|             // should we still process a connected event?
 | |
|             if (connectedEventPending)
 | |
|             {
 | |
|                 connectedEventPending = false;
 | |
|                 NetworkClient.OnConnectedEvent?.Invoke();
 | |
|             }
 | |
| 
 | |
|             // process internal messages so they are applied at the correct time
 | |
|             while (queue.Count > 0)
 | |
|             {
 | |
|                 // call receive on queued writer's content, return to pool
 | |
|                 PooledNetworkWriter writer = queue.Dequeue();
 | |
|                 ArraySegment<byte> message = writer.ToArraySegment();
 | |
| 
 | |
|                 // OnTransportData assumes a proper batch with timestamp etc.
 | |
|                 // let's make a proper batch and pass it to OnTransportData.
 | |
|                 Batcher batcher = GetBatchForChannelId(Channels.Reliable);
 | |
|                 batcher.AddMessage(message);
 | |
| 
 | |
|                 using (PooledNetworkWriter batchWriter = NetworkWriterPool.GetWriter())
 | |
|                 {
 | |
|                     // make a batch with our local time (double precision)
 | |
|                     if (batcher.MakeNextBatch(batchWriter, NetworkTime.localTime))
 | |
|                     {
 | |
|                         NetworkClient.OnTransportData(batchWriter.ToArraySegment(), Channels.Reliable);
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 NetworkWriterPool.Recycle(writer);
 | |
|             }
 | |
| 
 | |
|             // should we still process a disconnected event?
 | |
|             if (disconnectedEventPending)
 | |
|             {
 | |
|                 disconnectedEventPending = false;
 | |
|                 NetworkClient.OnDisconnectedEvent?.Invoke();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>Disconnects this connection.</summary>
 | |
|         internal void DisconnectInternal()
 | |
|         {
 | |
|             // set not ready and handle clientscene disconnect in any case
 | |
|             // (might be client or host mode here)
 | |
|             // TODO remove redundant state. have one source of truth for .ready!
 | |
|             isReady = false;
 | |
|             NetworkClient.ready = false;
 | |
|         }
 | |
| 
 | |
|         /// <summary>Disconnects this connection.</summary>
 | |
|         public override void Disconnect()
 | |
|         {
 | |
|             connectionToClient.DisconnectInternal();
 | |
|             DisconnectInternal();
 | |
| 
 | |
|             // simulate what a true remote connection would do:
 | |
|             // first, the server should remove it:
 | |
|             // TODO should probably be in connectionToClient.DisconnectInternal
 | |
|             //      because that's the NetworkServer's connection!
 | |
|             NetworkServer.RemoveLocalConnection();
 | |
| 
 | |
|             // then call OnTransportDisconnected for proper disconnect handling,
 | |
|             // callbacks & cleanups.
 | |
|             // => otherwise OnClientDisconnected() is never called!
 | |
|             // => see NetworkClientTests.DisconnectCallsOnClientDisconnect_HostMode()
 | |
|             NetworkClient.OnTransportDisconnected();
 | |
|         }
 | |
| 
 | |
|         // true because local connections never timeout
 | |
|         internal override bool IsAlive(float timeout) => true;
 | |
|     }
 | |
| }
 | 
