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