Skip to content

Commit 340da41

Browse files
committed
feat: Added ruffles transport
1 parent 1b19a7b commit 340da41

File tree

8 files changed

+333
-45
lines changed

8 files changed

+333
-45
lines changed

.releaserc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"@semantic-release/release-notes-generator",
99
["@semantic-release/github", {
1010
"assets": [
11-
{"path": "MLAPI/bin/Release/net35/MLAPI.dll"},
11+
{"path": "MLAPI/bin/Release/net35/MLAPI.dll"},
12+
{"path": "MLAPI/bin/Release/net35/Ruffles.dll"},
1213
{"path": "*.unitypackage"}
1314
]
1415
}]

MLAPI.EnetTransport/EnetTransport.cs

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public struct EnetChannel
2121
public ushort Port = 7777;
2222
public string Address = "127.0.0.1";
2323
public int MaxClients = 100;
24-
public List<TransportChannel> Channels = new List<TransportChannel>();
24+
public List<EnetChannel> Channels = new List<EnetChannel>();
2525
public int MessageBufferSize = 1024 * 5;
2626

2727

@@ -227,7 +227,7 @@ public override void Init()
227227
{
228228
Id = i,
229229
Name = MLAPI_CHANNELS[i].Name,
230-
Flags = ChannelTypeToPacketFlag(MLAPI_CHANNELS[i].Type)
230+
Flags = MLAPIChannelTypeToPacketFlag(MLAPI_CHANNELS[i].Type)
231231
});
232232
}
233233

@@ -242,37 +242,25 @@ public override void Init()
242242
{
243243
Id = id,
244244
Name = Channels[i].Name,
245-
Flags = ChannelTypeToPacketFlag(Channels[i].Type)
245+
Flags = Channels[i].Flags
246246
});
247247
}
248248

249249
messageBuffer = new byte[MessageBufferSize];
250250
}
251251

252-
public PacketFlags ChannelTypeToPacketFlag(ChannelType type)
252+
public PacketFlags MLAPIChannelTypeToPacketFlag(ChannelType type)
253253
{
254254
switch (type)
255255
{
256256
case ChannelType.Unreliable:
257257
{
258258
return PacketFlags.Unsequenced | PacketFlags.UnreliableFragment;
259259
}
260-
case ChannelType.UnreliableFragmented:
261-
{
262-
return PacketFlags.Unsequenced | PacketFlags.UnreliableFragment;
263-
}
264-
case ChannelType.UnreliableSequenced:
265-
{
266-
return PacketFlags.UnreliableFragment;
267-
}
268260
case ChannelType.Reliable:
269261
{
270262
return PacketFlags.Reliable | PacketFlags.Unsequenced;
271263
}
272-
case ChannelType.ReliableFragmented:
273-
{
274-
return PacketFlags.Reliable | PacketFlags.Unsequenced;
275-
}
276264
case ChannelType.ReliableSequenced:
277265
{
278266
return PacketFlags.Reliable;
@@ -281,18 +269,6 @@ public PacketFlags ChannelTypeToPacketFlag(ChannelType type)
281269
{
282270
return PacketFlags.None;
283271
}
284-
case ChannelType.ReliableStateUpdate:
285-
{
286-
return PacketFlags.Reliable;
287-
}
288-
case ChannelType.AllCostDelivery:
289-
{
290-
return PacketFlags.Reliable;
291-
}
292-
case ChannelType.UnreliableFragmentedSequenced:
293-
{
294-
return PacketFlags.UnreliableFragment;
295-
}
296272
case ChannelType.ReliableFragmentedSequenced:
297273
{
298274
return PacketFlags.Reliable;

MLAPI/MLAPI.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,7 @@
2020
<Private>false</Private>
2121
</Reference>
2222
</ItemGroup>
23+
<ItemGroup>
24+
<PackageReference Include="Ruffles" Version="1.0.5" />
25+
</ItemGroup>
2326
</Project>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System;
2+
3+
namespace MLAPI.Transports.Ruffles
4+
{
5+
/// <summary>
6+
/// A transport channel used by the MLAPI
7+
/// </summary>
8+
[Serializable]
9+
public class RufflesChannel
10+
{
11+
/// <summary>
12+
/// The name of the channel
13+
/// </summary>
14+
public string Name;
15+
16+
/// <summary>
17+
/// The type of channel
18+
/// </summary>
19+
public global::Ruffles.Channeling.ChannelType Type;
20+
}
21+
}
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
2+
using System;
3+
using System.Collections.Generic;
4+
using Ruffles.Core;
5+
using Ruffles.Configuration;
6+
using System.Net;
7+
8+
namespace MLAPI.Transports.Ruffles
9+
{
10+
public class RufflesTransport : Transport
11+
{
12+
// Inspector / settings
13+
public int MessageBufferSize = 1024 * 5;
14+
public int MaxConnections = 100;
15+
public string ConnectAddress = "127.0.0.1";
16+
public int ConnectPort = 7777;
17+
public int ServerListenPort = 7777;
18+
public List<RufflesChannel> Channels = new List<RufflesChannel>();
19+
20+
// Runtime / state
21+
private byte[] messageBuffer;
22+
private WeakReference temporaryBufferReference;
23+
private bool isConnector = false;
24+
25+
// Lookup / translation
26+
private readonly Dictionary<ulong, global::Ruffles.Connections.Connection> connections = new Dictionary<ulong, global::Ruffles.Connections.Connection>();
27+
private readonly Dictionary<string, byte> channelNameToId = new Dictionary<string, byte>();
28+
private readonly Dictionary<byte, string> channelIdToName = new Dictionary<byte, string>();
29+
private global::Ruffles.Connections.Connection serverConnection;
30+
31+
// Ruffles
32+
private RuffleSocket socket;
33+
34+
public override ulong ServerClientId => GetMLAPIClientId(0, true);
35+
36+
public override void Send(ulong clientId, ArraySegment<byte> data, string channelName, bool skipQueue)
37+
{
38+
GetRufflesConnectionDetails(clientId, out ulong connectionId);
39+
40+
byte channelId = channelNameToId[channelName];
41+
42+
socket.Send(data, connectionId, channelId, skipQueue);
43+
}
44+
45+
public override void FlushSendQueue(ulong clientId)
46+
{
47+
48+
}
49+
50+
public override NetEventType PollEvent(out ulong clientId, out string channelName, out ArraySegment<byte> payload)
51+
{
52+
socket.RunInternalLoop();
53+
NetworkEvent @event = socket.Poll();
54+
55+
if (@event.Type != NetworkEventType.Nothing)
56+
{
57+
clientId = GetMLAPIClientId(@event.Connection.Id, false);
58+
}
59+
else
60+
{
61+
clientId = 0;
62+
}
63+
64+
byte[] dataBuffer = messageBuffer;
65+
66+
if (@event.Type == NetworkEventType.Data)
67+
{
68+
if (@event.Data.Count > messageBuffer.Length)
69+
{
70+
if (temporaryBufferReference != null && temporaryBufferReference.IsAlive && ((byte[])temporaryBufferReference.Target).Length >= @event.Data.Count)
71+
{
72+
dataBuffer = (byte[])temporaryBufferReference.Target;
73+
}
74+
else
75+
{
76+
dataBuffer = new byte[@event.Data.Count];
77+
temporaryBufferReference = new WeakReference(dataBuffer);
78+
}
79+
}
80+
81+
Buffer.BlockCopy(@event.Data.Array, @event.Data.Offset, dataBuffer, 0, @event.Data.Count);
82+
payload = new ArraySegment<byte>(dataBuffer, 0, @event.Data.Count);
83+
}
84+
else
85+
{
86+
payload = new ArraySegment<byte>();
87+
}
88+
89+
// TODO: FIX, ruffles needs to give us the channel
90+
channelName = channelIdToName[0];
91+
92+
// Translate NetworkEventType to NetEventType
93+
switch (@event.Type)
94+
{
95+
case NetworkEventType.Data:
96+
return NetEventType.Data;
97+
case NetworkEventType.Connect:
98+
{
99+
connections.Add(@event.Connection.Id, @event.Connection);
100+
101+
// Set the server connectionId
102+
if (isConnector)
103+
{
104+
serverConnection = @event.Connection;
105+
}
106+
107+
return NetEventType.Connect;
108+
}
109+
case NetworkEventType.Timeout:
110+
case NetworkEventType.Disconnect:
111+
{
112+
if (@event.Connection == serverConnection)
113+
serverConnection = null;
114+
115+
connections.Remove(@event.Connection.Id);
116+
117+
@event.Connection.Recycle();
118+
119+
return NetEventType.Disconnect;
120+
}
121+
case NetworkEventType.Nothing:
122+
return NetEventType.Nothing;
123+
}
124+
125+
return NetEventType.Nothing;
126+
}
127+
128+
public override void StartClient()
129+
{
130+
SocketConfig config = GetConfig();
131+
// The OS will grab a port
132+
config.DualListenPort = 0;
133+
socket = new RuffleSocket(config);
134+
135+
isConnector = true;
136+
socket.Connect(new IPEndPoint(IPAddress.Parse(ConnectAddress), ConnectPort));
137+
}
138+
139+
public override void StartServer()
140+
{
141+
SocketConfig config = GetConfig();
142+
config.DualListenPort = (ushort)ServerListenPort;
143+
144+
socket = new RuffleSocket(config);
145+
}
146+
147+
public override void DisconnectRemoteClient(ulong clientId)
148+
{
149+
GetRufflesConnectionDetails(clientId, out ulong connectionId);
150+
socket.Disconnect(connections[connectionId], true);
151+
}
152+
153+
public override void DisconnectLocalClient()
154+
{
155+
socket.Disconnect(serverConnection, true);
156+
}
157+
158+
public override ulong GetCurrentRtt(ulong clientId)
159+
{
160+
GetRufflesConnectionDetails(clientId, out ulong connectionId);
161+
return (ulong)connections[connectionId].Roundtrip;
162+
}
163+
164+
public override void Shutdown()
165+
{
166+
channelIdToName.Clear();
167+
channelNameToId.Clear();
168+
connections.Clear();
169+
}
170+
171+
public override void Init()
172+
{
173+
messageBuffer = new byte[MessageBufferSize];
174+
}
175+
176+
public ulong GetMLAPIClientId(ulong connectionId, bool isServer)
177+
{
178+
if (isServer)
179+
{
180+
return 0;
181+
}
182+
else
183+
{
184+
return (ulong)connectionId + 1;
185+
}
186+
}
187+
188+
public void GetRufflesConnectionDetails(ulong clientId, out ulong connectionId)
189+
{
190+
if (clientId == 0)
191+
{
192+
connectionId = serverConnection.Id;
193+
}
194+
else
195+
{
196+
connectionId = (ushort)(clientId - 1);
197+
}
198+
}
199+
200+
private SocketConfig GetConfig()
201+
{
202+
SocketConfig config = new SocketConfig();
203+
204+
int channelCount = MLAPI_CHANNELS.Length + Channels.Count;
205+
config.ChannelTypes = new global::Ruffles.Channeling.ChannelType[channelCount];
206+
207+
for (byte i = 0; i < MLAPI_CHANNELS.Length; i++)
208+
{
209+
config.ChannelTypes[i] = ConvertChannelType(MLAPI_CHANNELS[i].Type);
210+
channelIdToName.Add(i, MLAPI_CHANNELS[i].Name);
211+
channelNameToId.Add(MLAPI_CHANNELS[i].Name, i);
212+
}
213+
214+
for (byte i = (byte)MLAPI_CHANNELS.Length; i < Channels.Count + MLAPI_CHANNELS.Length; i++)
215+
{
216+
config.ChannelTypes[i] = Channels[i].Type;
217+
channelIdToName.Add(i, Channels[i].Name);
218+
channelNameToId.Add(Channels[i].Name, i);
219+
}
220+
221+
return config;
222+
}
223+
224+
private global::Ruffles.Channeling.ChannelType ConvertChannelType(ChannelType type)
225+
{
226+
switch (type)
227+
{
228+
case ChannelType.Reliable:
229+
return global::Ruffles.Channeling.ChannelType.Reliable;
230+
case ChannelType.ReliableFragmentedSequenced:
231+
return global::Ruffles.Channeling.ChannelType.ReliableSequenced;
232+
case ChannelType.ReliableSequenced:
233+
return global::Ruffles.Channeling.ChannelType.ReliableSequenced;
234+
case ChannelType.StateUpdate:
235+
return global::Ruffles.Channeling.ChannelType.Unreliable;
236+
case ChannelType.Unreliable:
237+
return global::Ruffles.Channeling.ChannelType.Unreliable;
238+
}
239+
240+
return global::Ruffles.Channeling.ChannelType.Reliable;
241+
}
242+
}
243+
}
244+
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
245+

MLAPI/Transports/UNET/UnetChannel.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System;
2+
using UnityEngine.Networking;
3+
4+
namespace MLAPI.Transports
5+
{
6+
/// <summary>
7+
/// A transport channel used by the MLAPI
8+
/// </summary>
9+
[Serializable]
10+
public class UnetChannel
11+
{
12+
/// <summary>
13+
/// The name of the channel
14+
/// </summary>
15+
public string Name;
16+
17+
/// <summary>
18+
/// The type of channel
19+
/// </summary>
20+
public QosType Type;
21+
}
22+
}

0 commit comments

Comments
 (0)