1+ using System ;
2+ using System . Collections . Generic ;
3+ using ENet ;
4+ using MLAPI . Transports ;
5+
6+ namespace MLAPI . EnetTransport
7+ {
8+ public class EnetTransport : Transport
9+ {
10+ public struct EnetChannel
11+ {
12+ public byte Id ;
13+ public string Name ;
14+ public PacketFlags Flags ;
15+ }
16+
17+ public ushort Port = 7777 ;
18+ public string Address = "127.0.0.1" ;
19+ public int MaxClients = 100 ;
20+ public List < TransportChannel > Channels = new List < TransportChannel > ( ) ;
21+ public int MessageBufferSize = 1024 * 5 ;
22+
23+
24+ // Runtime / state
25+ private byte [ ] messageBuffer ;
26+ private WeakReference temporaryBufferReference ;
27+
28+
29+ private readonly Dictionary < uint , Peer > connectedEnetPeers = new Dictionary < uint , Peer > ( ) ;
30+
31+ private readonly Dictionary < string , byte > channelNameToId = new Dictionary < string , byte > ( ) ;
32+ private readonly Dictionary < byte , string > channelIdToName = new Dictionary < byte , string > ( ) ;
33+ private readonly Dictionary < byte , EnetChannel > internalChannels = new Dictionary < byte , EnetChannel > ( ) ;
34+
35+ private Host host ;
36+
37+ private uint serverPeerId ;
38+
39+ public override ulong ServerClientId => GetMLAPIClientId ( 0 , true ) ;
40+
41+ public override void Send ( ulong clientId , ArraySegment < byte > data , string channelName , bool skipQueue )
42+ {
43+ Packet packet = default ( Packet ) ;
44+
45+ packet . Create ( data . Array , data . Offset , data . Count , internalChannels [ channelNameToId [ channelName ] ] . Flags ) ;
46+
47+ GetEnetConnectionDetails ( clientId , out uint peerId ) ;
48+
49+ connectedEnetPeers [ peerId ] . Send ( channelNameToId [ channelName ] , ref packet ) ;
50+ }
51+
52+ public override void FlushSendQueue ( ulong clientId )
53+ {
54+ // Not needed
55+ }
56+
57+ public override NetEventType PollEvent ( out ulong clientId , out string channelName , out ArraySegment < byte > payload )
58+ {
59+ Event @event ;
60+
61+ if ( host . CheckEvents ( out @event ) <= 0 && host . Service ( 0 , out @event ) > 0 )
62+ {
63+ clientId = GetMLAPIClientId ( @event . Peer . ID , false ) ;
64+
65+ switch ( @event . Type )
66+ {
67+ case EventType . None :
68+ {
69+ channelName = null ;
70+ return NetEventType . Nothing ;
71+ }
72+ case EventType . Connect :
73+ {
74+ channelName = null ;
75+
76+ connectedEnetPeers . Add ( @event . Peer . ID , @event . Peer ) ;
77+
78+ return NetEventType . Connect ;
79+ }
80+ case EventType . Disconnect :
81+ {
82+ channelName = null ;
83+
84+ connectedEnetPeers . Remove ( @event . Peer . ID ) ;
85+
86+ return NetEventType . Disconnect ;
87+ }
88+ case EventType . Receive :
89+ {
90+ channelName = channelIdToName [ @event . ChannelID ] ;
91+ int size = @event . Packet . Length ;
92+
93+ if ( size > messageBuffer . Length )
94+ {
95+ byte [ ] tempBuffer ;
96+
97+ if ( temporaryBufferReference != null && temporaryBufferReference . IsAlive && ( ( byte [ ] ) temporaryBufferReference . Target ) . Length >= size )
98+ {
99+ tempBuffer = ( byte [ ] ) temporaryBufferReference . Target ;
100+ }
101+ else
102+ {
103+ tempBuffer = new byte [ size ] ;
104+ temporaryBufferReference = new WeakReference ( tempBuffer ) ;
105+ }
106+
107+ @event . Packet . CopyTo ( tempBuffer ) ;
108+ payload = new ArraySegment < byte > ( tempBuffer , 0 , size ) ;
109+ }
110+ else
111+ {
112+ @event . Packet . CopyTo ( messageBuffer ) ;
113+ payload = new ArraySegment < byte > ( messageBuffer , 0 , size ) ;
114+ }
115+
116+
117+ @event . Packet . Dispose ( ) ;
118+ return NetEventType . Data ;
119+ }
120+ case EventType . Timeout :
121+ {
122+ channelName = null ;
123+
124+ connectedEnetPeers . Remove ( @event . Peer . ID ) ;
125+
126+ return NetEventType . Disconnect ;
127+ }
128+ default :
129+ {
130+ channelName = null ;
131+
132+ return NetEventType . Nothing ;
133+ }
134+ }
135+ }
136+ else
137+ {
138+ channelName = null ;
139+ clientId = 0 ;
140+
141+ return NetEventType . Nothing ;
142+ }
143+ }
144+
145+ public override void StartClient ( )
146+ {
147+ host = new Host ( ) ;
148+
149+ Address address = new Address ( ) ;
150+
151+ address . Port = Port ;
152+ address . SetHost ( Address ) ;
153+
154+ host . Create ( address , 1 ) ;
155+
156+ Peer serverPeer = host . Connect ( address , MLAPI_CHANNELS . Length + Channels . Count ) ;
157+
158+ serverPeerId = serverPeer . ID ;
159+ }
160+
161+ public override void StartServer ( )
162+ {
163+ host = new Host ( ) ;
164+
165+ host . SetChannelLimit ( MLAPI_CHANNELS . Length + Channels . Count ) ;
166+
167+ Address address = new Address ( ) ;
168+
169+ address . Port = Port ;
170+
171+ host . Create ( address , MaxClients ) ;
172+ }
173+
174+ public override void DisconnectRemoteClient ( ulong clientId )
175+ {
176+ GetEnetConnectionDetails ( serverPeerId , out uint peerId ) ;
177+
178+ connectedEnetPeers [ peerId ] . DisconnectLater ( 0 ) ;
179+ }
180+
181+ public override void DisconnectLocalClient ( )
182+ {
183+ host . Flush ( ) ;
184+
185+ GetEnetConnectionDetails ( serverPeerId , out uint peerId ) ;
186+
187+ connectedEnetPeers [ peerId ] . DisconnectNow ( 0 ) ;
188+ }
189+
190+ public override ulong GetCurrentRtt ( ulong clientId )
191+ {
192+ GetEnetConnectionDetails ( serverPeerId , out uint peerId ) ;
193+
194+ return connectedEnetPeers [ peerId ] . RoundTripTime ;
195+ }
196+
197+ public override void Shutdown ( )
198+ {
199+ host . Flush ( ) ;
200+ host . Dispose ( ) ;
201+ Library . Deinitialize ( ) ;
202+ }
203+
204+ public override void Init ( )
205+ {
206+ Library . Initialize ( ) ;
207+
208+ internalChannels . Clear ( ) ;
209+ channelIdToName . Clear ( ) ;
210+ channelNameToId . Clear ( ) ;
211+
212+
213+ // MLAPI Channels
214+ for ( byte i = 0 ; i < MLAPI_CHANNELS . Length ; i ++ )
215+ {
216+ channelIdToName . Add ( i , MLAPI_CHANNELS [ i ] . Name ) ;
217+ channelNameToId . Add ( MLAPI_CHANNELS [ i ] . Name , i ) ;
218+ internalChannels . Add ( i , new EnetChannel ( )
219+ {
220+ Id = i ,
221+ Name = MLAPI_CHANNELS [ i ] . Name ,
222+ Flags = ChannelTypeToPacketFlag ( MLAPI_CHANNELS [ i ] . Type )
223+ } ) ;
224+ }
225+
226+ // Internal Channels
227+ for ( int i = 0 ; i < Channels . Count ; i ++ )
228+ {
229+ byte id = ( byte ) ( i + MLAPI_CHANNELS . Length ) ;
230+
231+ channelIdToName . Add ( id , Channels [ i ] . Name ) ;
232+ channelNameToId . Add ( Channels [ i ] . Name , id ) ;
233+ internalChannels . Add ( id , new EnetChannel ( )
234+ {
235+ Id = id ,
236+ Name = Channels [ i ] . Name ,
237+ Flags = ChannelTypeToPacketFlag ( Channels [ i ] . Type )
238+ } ) ;
239+ }
240+
241+ messageBuffer = new byte [ MessageBufferSize ] ;
242+ }
243+
244+ public PacketFlags ChannelTypeToPacketFlag ( ChannelType type )
245+ {
246+ switch ( type )
247+ {
248+ case ChannelType . Unreliable :
249+ {
250+ return PacketFlags . Unsequenced | PacketFlags . UnreliableFragment ;
251+ }
252+ case ChannelType . UnreliableFragmented :
253+ {
254+ return PacketFlags . Unsequenced | PacketFlags . UnreliableFragment ;
255+ }
256+ case ChannelType . UnreliableSequenced :
257+ {
258+ return PacketFlags . UnreliableFragment ;
259+ }
260+ case ChannelType . Reliable :
261+ {
262+ return PacketFlags . Reliable | PacketFlags . Unsequenced ;
263+ }
264+ case ChannelType . ReliableFragmented :
265+ {
266+ return PacketFlags . Reliable | PacketFlags . Unsequenced ;
267+ }
268+ case ChannelType . ReliableSequenced :
269+ {
270+ return PacketFlags . Reliable ;
271+ }
272+ case ChannelType . StateUpdate :
273+ {
274+ return PacketFlags . None ;
275+ }
276+ case ChannelType . ReliableStateUpdate :
277+ {
278+ return PacketFlags . Reliable ;
279+ }
280+ case ChannelType . AllCostDelivery :
281+ {
282+ return PacketFlags . Reliable ;
283+ }
284+ case ChannelType . UnreliableFragmentedSequenced :
285+ {
286+ return PacketFlags . UnreliableFragment ;
287+ }
288+ case ChannelType . ReliableFragmentedSequenced :
289+ {
290+ return PacketFlags . Reliable ;
291+ }
292+ default :
293+ {
294+ throw new ArgumentOutOfRangeException ( nameof ( type ) , type , null ) ;
295+ }
296+ }
297+ }
298+
299+ public ulong GetMLAPIClientId ( uint peerId , bool isServer )
300+ {
301+ if ( isServer )
302+ {
303+ return 0 ;
304+ }
305+ else
306+ {
307+ return peerId + 1 ;
308+ }
309+ }
310+
311+ public void GetEnetConnectionDetails ( ulong clientId , out uint peerId )
312+ {
313+ if ( clientId == 0 )
314+ {
315+ peerId = serverPeerId ;
316+ }
317+ else
318+ {
319+ peerId = ( uint ) clientId - 1 ;
320+ }
321+ }
322+ }
323+ }
0 commit comments