1+ #if UNIFIED_NETCODE
2+ using System ;
3+ using System . Collections . Generic ;
4+ using System . Text ;
5+ using Unity . Burst ;
6+ using Unity . Burst . Intrinsics ;
7+ using Unity . Collections ;
8+ using Unity . Collections . LowLevel . Unsafe ;
9+ using Unity . Entities ;
10+ using Unity . NetCode ;
11+ using Unity . Networking . Transport ;
12+ using UnityEngine ;
13+
14+ namespace Unity . Netcode . Unified
15+ {
16+ internal struct TransportRpc : IRpcCommand , IRpcCommandSerializer < TransportRpc >
17+ {
18+ public FixedList4096Bytes < byte > Buffer ;
19+
20+ internal static string ByteArrayToString ( FixedList4096Bytes < byte > ba , int offset , int count )
21+ {
22+ var hex = new StringBuilder ( ba . Length * 2 ) ;
23+ for ( int i = offset ; i < offset + count ; ++ i )
24+ {
25+ hex . AppendFormat ( "{0:x2} " , ba [ i ] ) ;
26+ }
27+
28+ return hex . ToString ( ) ;
29+ }
30+ internal static string ByteArrayToString ( NativeArray < byte > ba , int offset , int count )
31+ {
32+ var hex = new StringBuilder ( ba . Length * 2 ) ;
33+ for ( int i = offset ; i < offset + count ; ++ i )
34+ {
35+ hex . AppendFormat ( "{0:x2} " , ba [ i ] ) ;
36+ }
37+
38+ return hex . ToString ( ) ;
39+ }
40+
41+ public unsafe void Serialize ( ref DataStreamWriter writer , in RpcSerializerState state , in TransportRpc data )
42+ {
43+ writer . WriteInt ( data . Buffer . Length ) ;
44+ var span = new Span < byte > ( data . Buffer . GetUnsafePtr ( ) , data . Buffer . Length ) ;
45+ writer . WriteBytes ( span ) ;
46+ }
47+
48+ public unsafe void Deserialize ( ref DataStreamReader reader , in RpcDeserializerState state , ref TransportRpc data )
49+ {
50+ var length = reader . ReadInt ( ) ;
51+ data . Buffer = new FixedList4096Bytes < byte > ( ) ;
52+ data . Buffer . Length = length ;
53+ var span = new Span < byte > ( data . Buffer . GetUnsafePtr ( ) , length ) ;
54+ reader . ReadBytes ( span ) ;
55+ }
56+
57+ [ BurstCompile ( DisableDirectCall = true ) ]
58+ private static void InvokeExecute ( ref RpcExecutor . Parameters parameters )
59+ {
60+ RpcExecutor . ExecuteCreateRequestComponent < TransportRpc , TransportRpc > ( ref parameters ) ;
61+ }
62+
63+ static readonly PortableFunctionPointer < RpcExecutor . ExecuteDelegate > InvokeExecuteFunctionPointer = new PortableFunctionPointer < RpcExecutor . ExecuteDelegate > ( InvokeExecute ) ;
64+
65+ public PortableFunctionPointer < RpcExecutor . ExecuteDelegate > CompileExecute ( )
66+ {
67+ return InvokeExecuteFunctionPointer ;
68+ }
69+ }
70+
71+ [ UpdateInGroup ( typeof ( RpcCommandRequestSystemGroup ) ) ]
72+ [ CreateAfter ( typeof ( RpcSystem ) ) ]
73+ [ BurstCompile ]
74+ partial struct TransportRpcCommandRequestSystem : ISystem
75+ {
76+ private RpcCommandRequest < TransportRpc , TransportRpc > m_Request ;
77+
78+ [ BurstCompile ]
79+ struct SendRpc : IJobChunk
80+ {
81+ public RpcCommandRequest < TransportRpc , TransportRpc > . SendRpcData data ;
82+
83+ public void Execute ( in ArchetypeChunk chunk , int unfilteredChunkIndex , bool useEnabledMask , in v128 chunkEnabledMask )
84+ {
85+ data . Execute ( chunk , unfilteredChunkIndex ) ;
86+ }
87+ }
88+
89+ public void OnCreate ( ref SystemState state )
90+ {
91+ m_Request . OnCreate ( ref state ) ;
92+ }
93+
94+ [ BurstCompile ]
95+ public void OnUpdate ( ref SystemState state )
96+ {
97+ var sendJob = new SendRpc { data = m_Request . InitJobData ( ref state ) } ;
98+ state . Dependency = sendJob . Schedule ( m_Request . Query , state . Dependency ) ;
99+ }
100+ }
101+
102+
103+ internal partial class UnifiedNetcodeUpdateSystem : SystemBase
104+ {
105+ public UnifiedNetcodeTransport Transport ;
106+
107+ public List < Connection > DiscconedtQueue = new List < Connection > ( ) ;
108+
109+ public void Disconnect ( Connection connection )
110+ {
111+ DiscconedtQueue . Add ( connection ) ;
112+ }
113+
114+ protected override void OnUpdate ( )
115+ {
116+ using var commandBuffer = new EntityCommandBuffer ( Allocator . Temp ) ;
117+ foreach ( var ( request , rpc , entity ) in SystemAPI . Query < RefRO < ReceiveRpcCommandRequest > , RefRW < TransportRpc > > ( ) . WithEntityAccess ( ) )
118+ {
119+ var connectionId = SystemAPI . GetComponent < NetworkId > ( request . ValueRO . SourceConnection ) . Value ;
120+
121+ var buffer = rpc . ValueRW . Buffer ;
122+ Transport . DispatchMessage ( connectionId , buffer ) ;
123+ commandBuffer . DestroyEntity ( entity ) ;
124+ }
125+
126+ foreach ( var connection in DiscconedtQueue )
127+ {
128+ commandBuffer . AddComponent < NetworkStreamRequestDisconnect > ( connection . ConnectionEntity ) ;
129+ }
130+ commandBuffer . Playback ( EntityManager ) ;
131+ DiscconedtQueue . Clear ( ) ;
132+ }
133+ }
134+
135+ internal class UnifiedNetcodeTransport : NetworkTransport
136+ {
137+ private int m_ServerClientId = - 1 ;
138+ public override ulong ServerClientId => ( ulong ) m_ServerClientId ;
139+
140+ private bool m_IsClient ;
141+ private bool m_IsServer ;
142+ private bool m_StartedServerWorld = false ;
143+ private bool m_StartedClientWorld = false ;
144+
145+ private IRealTimeProvider m_RealTimeProvider ;
146+
147+ private Dictionary < int , Connection > m_Connections ;
148+
149+ internal void DispatchMessage ( int connectionId , FixedList4096Bytes < byte > buffer )
150+ {
151+ ArraySegment < byte > data = new ArraySegment < byte > ( buffer . ToArray ( ) ) ;
152+ InvokeOnTransportEvent ( NetworkEvent . Data , ( ulong ) connectionId , data , m_RealTimeProvider . RealTimeSinceStartup ) ;
153+ }
154+
155+ public override void Send ( ulong clientId , ArraySegment < byte > payload , NetworkDelivery networkDelivery )
156+ {
157+ if ( ! m_Connections . TryGetValue ( ( int ) clientId , out Connection connection ) )
158+ {
159+ return ;
160+ }
161+
162+ var rpc = new TransportRpc
163+ {
164+ Buffer = new FixedList4096Bytes < byte > ( ) ,
165+ } ;
166+
167+ unsafe
168+ {
169+ rpc . Buffer . Length = payload . Count ;
170+ fixed ( byte * data = payload . Array )
171+ {
172+ UnsafeUtility . MemCpy ( rpc . Buffer . GetUnsafePtr ( ) , ( void * ) ( data + payload . Offset ) , payload . Count ) ;
173+ }
174+ }
175+
176+ connection . SendMessage ( rpc ) ;
177+ }
178+
179+ public override NetworkEvent PollEvent ( out ulong clientId , out ArraySegment < byte > payload , out float receiveTime )
180+ {
181+ clientId = 0 ;
182+ payload = default ;
183+ receiveTime = 0 ;
184+ return NetworkEvent . Nothing ;
185+ }
186+
187+ private void OnClientConnectedToServer ( Connection connection , NetCodeConnectionEvent connectionEvent )
188+ {
189+ m_Connections [ connection . NetworkId . Value ] = connection ;
190+ m_ServerClientId = connection . NetworkId . Value ;
191+ InvokeOnTransportEvent ( NetworkEvent . Connect , ( ulong ) connection . NetworkId . Value , default , m_RealTimeProvider . RealTimeSinceStartup ) ;
192+ }
193+
194+ private void OnServerNewClientConnection ( Connection connection , NetCodeConnectionEvent connectionEvent )
195+ {
196+ m_Connections [ connection . NetworkId . Value ] = connection ;
197+ InvokeOnTransportEvent ( NetworkEvent . Connect , ( ulong ) connection . NetworkId . Value , default , m_RealTimeProvider . RealTimeSinceStartup ) ;
198+ }
199+
200+ private void OnClientDisconnectFromServer ( Connection connection , NetCodeConnectionEvent connectionEvent )
201+ {
202+ InvokeOnTransportEvent ( NetworkEvent . Disconnect , ( ulong ) connection . NetworkId . Value , default , m_RealTimeProvider . RealTimeSinceStartup ) ;
203+ }
204+
205+ private void OnServerClientDisconnected ( Connection connection , NetCodeConnectionEvent connectionEvent )
206+ {
207+ InvokeOnTransportEvent ( NetworkEvent . Disconnect , ( ulong ) connection . NetworkId . Value , default , m_RealTimeProvider . RealTimeSinceStartup ) ;
208+ }
209+
210+ public override bool StartClient ( )
211+ {
212+ if ( ! UnifiedBootStrap . HasClientWorlds )
213+ {
214+ UnifiedBootStrap . CreateClientWorld ( "ClientWorld" ) ;
215+ m_StartedClientWorld = true ;
216+ }
217+
218+ NetCode . Netcode . Client . OnConnect = OnClientConnectedToServer ;
219+ NetCode . Netcode . Client . OnDisconnect = OnClientDisconnectFromServer ;
220+ var updateSystem = NetCode . Netcode . GetWorld ( false ) . GetExistingSystemManaged < UnifiedNetcodeUpdateSystem > ( ) ;
221+ updateSystem . Transport = this ;
222+ return true ;
223+ }
224+
225+ public override bool StartServer ( )
226+ {
227+ if ( ! UnifiedBootStrap . HasServerWorld )
228+ {
229+ UnifiedBootStrap . CreateServerWorld ( "ServerWorld" ) ;
230+ m_StartedClientWorld = true ;
231+ }
232+ else
233+ {
234+ foreach ( var connection in NetCode . Netcode . Server . Connections )
235+ {
236+ OnServerNewClientConnection ( connection , default ) ;
237+ }
238+ }
239+
240+ NetCode . Netcode . Server . OnConnect = OnServerNewClientConnection ;
241+ NetCode . Netcode . Server . OnDisconnect = OnServerClientDisconnected ;
242+ var updateSystem = NetCode . Netcode . GetWorld ( true ) . GetExistingSystemManaged < UnifiedNetcodeUpdateSystem > ( ) ;
243+ updateSystem . Transport = this ;
244+ return true ;
245+ }
246+
247+ public override void DisconnectRemoteClient ( ulong clientId )
248+ {
249+ var updateSystem = NetCode . Netcode . GetWorld ( true ) . GetExistingSystemManaged < UnifiedNetcodeUpdateSystem > ( ) ;
250+ updateSystem . Disconnect ( m_Connections [ ( int ) clientId ] ) ;
251+ m_Connections . Remove ( ( int ) clientId ) ;
252+ }
253+
254+ public override void DisconnectLocalClient ( )
255+ {
256+ var updateSystem = NetCode . Netcode . GetWorld ( false ) . GetExistingSystemManaged < UnifiedNetcodeUpdateSystem > ( ) ;
257+ updateSystem . Disconnect ( m_Connections [ ( int ) ServerClientId ] ) ;
258+ m_Connections . Remove ( ( int ) ServerClientId ) ;
259+ }
260+
261+ public override ulong GetCurrentRtt ( ulong clientId )
262+ {
263+ // todo
264+ return 0 ;
265+ //return (ulong)m_Connections[(int)clientId].RTT;
266+ }
267+
268+ public override void Shutdown ( )
269+ {
270+ if ( m_StartedClientWorld )
271+ {
272+ UnifiedBootStrap . StopClient ( ) ;
273+ }
274+ if ( m_StartedServerWorld )
275+ {
276+ UnifiedBootStrap . StopServer ( ) ;
277+ }
278+ }
279+
280+ public override void Initialize ( NetworkManager networkManager = null )
281+ {
282+ m_Connections = new Dictionary < int , Connection > ( ) ;
283+ m_RealTimeProvider = networkManager . RealTimeProvider ;
284+ }
285+ }
286+ }
287+ #endif
0 commit comments