mirror of
				https://github.com/DerTyp7/defrain-shooter-unity.git
				synced 2025-10-30 21:17:09 +01:00 
			
		
		
		
	CHANGED TO MIRROR
This commit is contained in:
		
							
								
								
									
										306
									
								
								Assets/Mirror/Runtime/Transport/MultiplexTransport.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										306
									
								
								Assets/Mirror/Runtime/Transport/MultiplexTransport.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,306 @@ | ||||
| using System; | ||||
| using System.Text; | ||||
| using UnityEngine; | ||||
|  | ||||
| namespace Mirror | ||||
| { | ||||
|     // a transport that can listen to multiple underlying transport at the same time | ||||
|     [DisallowMultipleComponent] | ||||
|     public class MultiplexTransport : Transport | ||||
|     { | ||||
|         public Transport[] transports; | ||||
|  | ||||
|         Transport available; | ||||
|  | ||||
|         public void Awake() | ||||
|         { | ||||
|             if (transports == null || transports.Length == 0) | ||||
|             { | ||||
|                 Debug.LogError("Multiplex transport requires at least 1 underlying transport"); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public override void ClientEarlyUpdate() | ||||
|         { | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 transport.ClientEarlyUpdate(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public override void ServerEarlyUpdate() | ||||
|         { | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 transport.ServerEarlyUpdate(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public override void ClientLateUpdate() | ||||
|         { | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 transport.ClientLateUpdate(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public override void ServerLateUpdate() | ||||
|         { | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 transport.ServerLateUpdate(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         void OnEnable() | ||||
|         { | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 transport.enabled = true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         void OnDisable() | ||||
|         { | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 transport.enabled = false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public override bool Available() | ||||
|         { | ||||
|             // available if any of the transports is available | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 if (transport.Available()) | ||||
|                 { | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         #region Client | ||||
|  | ||||
|         public override void ClientConnect(string address) | ||||
|         { | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 if (transport.Available()) | ||||
|                 { | ||||
|                     available = transport; | ||||
|                     transport.OnClientConnected = OnClientConnected; | ||||
|                     transport.OnClientDataReceived = OnClientDataReceived; | ||||
|                     transport.OnClientError = OnClientError; | ||||
|                     transport.OnClientDisconnected = OnClientDisconnected; | ||||
|                     transport.ClientConnect(address); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             throw new ArgumentException("No transport suitable for this platform"); | ||||
|         } | ||||
|  | ||||
|         public override void ClientConnect(Uri uri) | ||||
|         { | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 if (transport.Available()) | ||||
|                 { | ||||
|                     try | ||||
|                     { | ||||
|                         available = transport; | ||||
|                         transport.OnClientConnected = OnClientConnected; | ||||
|                         transport.OnClientDataReceived = OnClientDataReceived; | ||||
|                         transport.OnClientError = OnClientError; | ||||
|                         transport.OnClientDisconnected = OnClientDisconnected; | ||||
|                         transport.ClientConnect(uri); | ||||
|                         return; | ||||
|                     } | ||||
|                     catch (ArgumentException) | ||||
|                     { | ||||
|                         // transport does not support the schema, just move on to the next one | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             throw new ArgumentException("No transport suitable for this platform"); | ||||
|         } | ||||
|  | ||||
|         public override bool ClientConnected() | ||||
|         { | ||||
|             return (object)available != null && available.ClientConnected(); | ||||
|         } | ||||
|  | ||||
|         public override void ClientDisconnect() | ||||
|         { | ||||
|             if ((object)available != null) | ||||
|                 available.ClientDisconnect(); | ||||
|         } | ||||
|  | ||||
|         public override void ClientSend(ArraySegment<byte> segment, int channelId) | ||||
|         { | ||||
|             available.ClientSend(segment, channelId); | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|         #region Server | ||||
|         // connection ids get mapped to base transports | ||||
|         // if we have 3 transports,  then | ||||
|         // transport 0 will produce connection ids [0, 3, 6, 9, ...] | ||||
|         // transport 1 will produce connection ids [1, 4, 7, 10, ...] | ||||
|         // transport 2 will produce connection ids [2, 5, 8, 11, ...] | ||||
|         int FromBaseId(int transportId, int connectionId) | ||||
|         { | ||||
|             return connectionId * transports.Length + transportId; | ||||
|         } | ||||
|  | ||||
|         int ToBaseId(int connectionId) | ||||
|         { | ||||
|             return connectionId / transports.Length; | ||||
|         } | ||||
|  | ||||
|         int ToTransportId(int connectionId) | ||||
|         { | ||||
|             return connectionId % transports.Length; | ||||
|         } | ||||
|  | ||||
|         void AddServerCallbacks() | ||||
|         { | ||||
|             // wire all the base transports to my events | ||||
|             for (int i = 0; i < transports.Length; i++) | ||||
|             { | ||||
|                 // this is required for the handlers,  if I use i directly | ||||
|                 // then all the handlers will use the last i | ||||
|                 int locali = i; | ||||
|                 Transport transport = transports[i]; | ||||
|  | ||||
|                 transport.OnServerConnected = (baseConnectionId => | ||||
|                 { | ||||
|                     OnServerConnected.Invoke(FromBaseId(locali, baseConnectionId)); | ||||
|                 }); | ||||
|  | ||||
|                 transport.OnServerDataReceived = (baseConnectionId, data, channel) => | ||||
|                 { | ||||
|                     OnServerDataReceived.Invoke(FromBaseId(locali, baseConnectionId), data, channel); | ||||
|                 }; | ||||
|  | ||||
|                 transport.OnServerError = (baseConnectionId, error) => | ||||
|                 { | ||||
|                     OnServerError.Invoke(FromBaseId(locali, baseConnectionId), error); | ||||
|                 }; | ||||
|                 transport.OnServerDisconnected = baseConnectionId => | ||||
|                 { | ||||
|                     OnServerDisconnected.Invoke(FromBaseId(locali, baseConnectionId)); | ||||
|                 }; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // for now returns the first uri, | ||||
|         // should we return all available uris? | ||||
|         public override Uri ServerUri() | ||||
|         { | ||||
|             return transports[0].ServerUri(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         public override bool ServerActive() | ||||
|         { | ||||
|             // avoid Linq.All allocations | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 if (!transport.ServerActive()) | ||||
|                 { | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         public override string ServerGetClientAddress(int connectionId) | ||||
|         { | ||||
|             int baseConnectionId = ToBaseId(connectionId); | ||||
|             int transportId = ToTransportId(connectionId); | ||||
|             return transports[transportId].ServerGetClientAddress(baseConnectionId); | ||||
|         } | ||||
|  | ||||
|         public override void ServerDisconnect(int connectionId) | ||||
|         { | ||||
|             int baseConnectionId = ToBaseId(connectionId); | ||||
|             int transportId = ToTransportId(connectionId); | ||||
|             transports[transportId].ServerDisconnect(baseConnectionId); | ||||
|         } | ||||
|  | ||||
|         public override void ServerSend(int connectionId, ArraySegment<byte> segment, int channelId) | ||||
|         { | ||||
|             int baseConnectionId = ToBaseId(connectionId); | ||||
|             int transportId = ToTransportId(connectionId); | ||||
|  | ||||
|             for (int i = 0; i < transports.Length; ++i) | ||||
|             { | ||||
|                 if (i == transportId) | ||||
|                 { | ||||
|                     transports[i].ServerSend(baseConnectionId, segment, channelId); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public override void ServerStart() | ||||
|         { | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 AddServerCallbacks(); | ||||
|                 transport.ServerStart(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public override void ServerStop() | ||||
|         { | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 transport.ServerStop(); | ||||
|             } | ||||
|         } | ||||
|         #endregion | ||||
|  | ||||
|         public override int GetMaxPacketSize(int channelId = 0) | ||||
|         { | ||||
|             // finding the max packet size in a multiplex environment has to be | ||||
|             // done very carefully: | ||||
|             // * servers run multiple transports at the same time | ||||
|             // * different clients run different transports | ||||
|             // * there should only ever be ONE true max packet size for everyone, | ||||
|             //   otherwise a spawn message might be sent to all tcp sockets, but | ||||
|             //   be too big for some udp sockets. that would be a debugging | ||||
|             //   nightmare and allow for possible exploits and players on | ||||
|             //   different platforms seeing a different game state. | ||||
|             // => the safest solution is to use the smallest max size for all | ||||
|             //    transports. that will never fail. | ||||
|             int mininumAllowedSize = int.MaxValue; | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 int size = transport.GetMaxPacketSize(channelId); | ||||
|                 mininumAllowedSize = Mathf.Min(size, mininumAllowedSize); | ||||
|             } | ||||
|             return mininumAllowedSize; | ||||
|         } | ||||
|  | ||||
|         public override void Shutdown() | ||||
|         { | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 transport.Shutdown(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public override string ToString() | ||||
|         { | ||||
|             StringBuilder builder = new StringBuilder(); | ||||
|             foreach (Transport transport in transports) | ||||
|             { | ||||
|                 builder.AppendLine(transport.ToString()); | ||||
|             } | ||||
|             return builder.ToString().Trim(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 DerTyp187
					DerTyp187