mirror of
https://github.com/Leahnaya/TheKingsRace.git
synced 2026-09-27 19:36:42 -05:00
Added the files for the MLAPI Relay Server
- This version of the server is modified from the other open sourced one on GitHub as we ignore the port when attempting to connect. Program.cs is modified as such
This commit is contained in:
158
MLAPI.Relay/MLAPI.Relay/Transports/RufflesTransport.cs
Normal file
158
MLAPI.Relay/MLAPI.Relay/Transports/RufflesTransport.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Ruffles.Channeling;
|
||||
using Ruffles.Configuration;
|
||||
using Ruffles.Connections;
|
||||
using Ruffles.Core;
|
||||
|
||||
namespace MLAPI.Relay.Transports
|
||||
{
|
||||
public class RufflesTransport : Transport
|
||||
{
|
||||
private RuffleSocket socket;
|
||||
|
||||
private readonly Dictionary<ulong, IPEndPoint> endpoints = new Dictionary<ulong, IPEndPoint>();
|
||||
|
||||
private NetworkEvent? pendingRecycleEvent = null;
|
||||
private Connection pendingRecycleConnection = null;
|
||||
|
||||
public override void Disconnect(ulong connectionId)
|
||||
{
|
||||
socket.Disconnect(connectionId, true);
|
||||
}
|
||||
|
||||
public override object GetConfig()
|
||||
{
|
||||
return new RufflesConfig()
|
||||
{
|
||||
DefaultChannelType = ChannelType.ReliableSequenced,
|
||||
SocketConfig = new SocketConfig(),
|
||||
UseDelay = true
|
||||
};
|
||||
}
|
||||
|
||||
public override IPEndPoint GetEndPoint(ulong connectionId)
|
||||
{
|
||||
if (endpoints.ContainsKey(connectionId))
|
||||
{
|
||||
return endpoints[connectionId];
|
||||
}
|
||||
|
||||
// TODO: Handle better
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public override NetEventType Poll(out ulong connectionId, out byte channelId, out ArraySegment<byte> payload)
|
||||
{
|
||||
if (pendingRecycleEvent != null)
|
||||
{
|
||||
pendingRecycleEvent.Value.Recycle();
|
||||
pendingRecycleEvent = null;
|
||||
}
|
||||
|
||||
if (pendingRecycleConnection != null)
|
||||
{
|
||||
pendingRecycleConnection.Recycle();
|
||||
pendingRecycleConnection = null;
|
||||
}
|
||||
|
||||
socket.RunInternalLoop();
|
||||
|
||||
NetworkEvent @event = socket.Poll();
|
||||
|
||||
channelId = @event.ChannelId;
|
||||
|
||||
switch (@event.Type)
|
||||
{
|
||||
case NetworkEventType.Connect:
|
||||
{
|
||||
connectionId = @event.Connection.Id;
|
||||
payload = new ArraySegment<byte>();
|
||||
|
||||
endpoints.Add(connectionId, (IPEndPoint)@event.Connection.EndPoint);
|
||||
|
||||
return NetEventType.Connect;
|
||||
}
|
||||
case NetworkEventType.Timeout:
|
||||
case NetworkEventType.Disconnect:
|
||||
{
|
||||
connectionId = @event.Connection.Id;
|
||||
payload = new ArraySegment<byte>();
|
||||
|
||||
// Will be recycled next iteration
|
||||
pendingRecycleConnection = @event.Connection;
|
||||
|
||||
endpoints.Remove(connectionId);
|
||||
|
||||
return NetEventType.Disconnect;
|
||||
}
|
||||
case NetworkEventType.Data:
|
||||
{
|
||||
connectionId = @event.Connection.Id;
|
||||
|
||||
payload = @event.Data;
|
||||
|
||||
pendingRecycleEvent = @event;
|
||||
|
||||
return NetEventType.Data;
|
||||
}
|
||||
default:
|
||||
{
|
||||
payload = new ArraySegment<byte>();
|
||||
channelId = 0;
|
||||
connectionId = 0;
|
||||
return NetEventType.Nothing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Send(ArraySegment<byte> payload, byte channelId, ulong connectionId)
|
||||
{
|
||||
socket.Send(payload, connectionId, channelId, false);
|
||||
}
|
||||
|
||||
public override void Start(object config)
|
||||
{
|
||||
RufflesConfig rufflesConfig = null;
|
||||
|
||||
if (config is RufflesConfig) rufflesConfig = (RufflesConfig)config;
|
||||
else if (config is JObject) rufflesConfig = ((JObject)config).ToObject<RufflesConfig>();
|
||||
|
||||
rufflesConfig.SocketConfig.DualListenPort = Program.Config.ListenPort;
|
||||
|
||||
ChannelType[] channelTypes = rufflesConfig.SocketConfig.ChannelTypes;
|
||||
ChannelType[] newChannelTypes = new ChannelType[channelTypes.Length + 1];
|
||||
|
||||
// Copy old channels
|
||||
for (int i = 0; i < channelTypes.Length; i++)
|
||||
{
|
||||
newChannelTypes[i] = channelTypes[i];
|
||||
}
|
||||
|
||||
// Set the default channel
|
||||
newChannelTypes[newChannelTypes.Length - 1] = rufflesConfig.DefaultChannelType;
|
||||
|
||||
// Set the default channel byte
|
||||
Program.DEFAULT_CHANNEL_BYTE = (byte)(newChannelTypes.Length - 1);
|
||||
|
||||
// Change to the new array
|
||||
rufflesConfig.SocketConfig.ChannelTypes = newChannelTypes;
|
||||
|
||||
// Start the socket
|
||||
socket = new RuffleSocket((SocketConfig)config);
|
||||
}
|
||||
|
||||
public class RufflesConfig
|
||||
{
|
||||
public SocketConfig SocketConfig { get; set; } = new SocketConfig();
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public ChannelType DefaultChannelType { get; set; } = ChannelType.ReliableSequenced;
|
||||
public bool UseDelay { get; set; } = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
MLAPI.Relay/MLAPI.Relay/Transports/Transport.cs
Normal file
38
MLAPI.Relay/MLAPI.Relay/Transports/Transport.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace MLAPI.Relay.Transports
|
||||
{
|
||||
public abstract class Transport
|
||||
{
|
||||
public abstract void Send(ArraySegment<byte> payload, byte channelId, ulong connectionId);
|
||||
public abstract void Disconnect(ulong connectionId);
|
||||
public abstract NetEventType Poll(out ulong connectionId, out byte channelId, out ArraySegment<byte> payload);
|
||||
public abstract IPEndPoint GetEndPoint(ulong connectionId);
|
||||
public abstract void Start(object config);
|
||||
public abstract object GetConfig();
|
||||
|
||||
public virtual RelayConfig BeforeSerializeConfig(RelayConfig config)
|
||||
{
|
||||
return config;
|
||||
}
|
||||
|
||||
public virtual string ProcessSerializedJson(string json)
|
||||
{
|
||||
return json;
|
||||
}
|
||||
|
||||
public virtual RelayConfig AfterDeserializedConfig(RelayConfig config)
|
||||
{
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
public enum NetEventType
|
||||
{
|
||||
Connect,
|
||||
Disconnect,
|
||||
Data,
|
||||
Nothing
|
||||
}
|
||||
}
|
||||
161
MLAPI.Relay/MLAPI.Relay/Transports/UnetTransport.cs
Normal file
161
MLAPI.Relay/MLAPI.Relay/Transports/UnetTransport.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using UnetServerDll;
|
||||
|
||||
namespace MLAPI.Relay.Transports
|
||||
{
|
||||
public class UnetTransport : Transport
|
||||
{
|
||||
private int hostId;
|
||||
private NetLibraryManager unetManager;
|
||||
|
||||
public override void Disconnect(ulong connectionId)
|
||||
{
|
||||
unetManager.Disconnect(hostId, (int)connectionId, out byte error);
|
||||
}
|
||||
|
||||
public override object GetConfig()
|
||||
{
|
||||
return new UnetConfig()
|
||||
{
|
||||
ConnectionConfig = new ConnectionConfig(),
|
||||
GlobalConfig = new GlobalConfig()
|
||||
};
|
||||
}
|
||||
|
||||
public override IPEndPoint GetEndPoint(ulong connectionId)
|
||||
{
|
||||
unetManager.GetConnectionInfo(hostId, (int)connectionId, out string address, out int port, out byte error);
|
||||
|
||||
if ((NetworkError)error == NetworkError.Ok)
|
||||
{
|
||||
return new IPEndPoint(IPAddress.Parse(address).MapToIPv6(), port);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override NetEventType Poll(out ulong connectionId, out byte channelId, out ArraySegment<byte> payload)
|
||||
{
|
||||
NetworkEventType eventType = unetManager.ReceiveFromHost(hostId, out int _connectionId, out int _channelId, Program.MESSAGE_BUFFER, Program.MESSAGE_BUFFER.Length, out int receivedSize, out byte error);
|
||||
|
||||
// Cast to correct types (this is fine because in UNET, under the hood, connectionIds are ushort and channelIds are byte. They are just exposed in C# as int)
|
||||
connectionId = (ulong)_connectionId;
|
||||
channelId = (byte)_channelId;
|
||||
|
||||
// Wrap buffer
|
||||
payload = new ArraySegment<byte>(Program.MESSAGE_BUFFER, 0, receivedSize);
|
||||
|
||||
if ((NetworkError)error == NetworkError.Timeout)
|
||||
{
|
||||
eventType = NetworkEventType.DisconnectEvent;
|
||||
}
|
||||
|
||||
switch (eventType)
|
||||
{
|
||||
case NetworkEventType.DataEvent:
|
||||
{
|
||||
return NetEventType.Data;
|
||||
}
|
||||
case NetworkEventType.ConnectEvent:
|
||||
{
|
||||
return NetEventType.Connect;
|
||||
}
|
||||
case NetworkEventType.DisconnectEvent:
|
||||
{
|
||||
return NetEventType.Disconnect;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return NetEventType.Nothing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Send(ArraySegment<byte> payload, byte channelId, ulong connectionId)
|
||||
{
|
||||
if (payload.Offset > 0)
|
||||
{
|
||||
// UNET cannot handle offsets!
|
||||
// TODO: Copy
|
||||
|
||||
throw new Exception("UNET cannot handle offsets!");
|
||||
}
|
||||
|
||||
unetManager.Send(hostId, (int)connectionId, channelId, payload.Array, payload.Count, out byte error);
|
||||
}
|
||||
|
||||
public override void Start(object config)
|
||||
{
|
||||
UnetConfig unetConfig = null;
|
||||
|
||||
if (config is UnetConfig) unetConfig = (UnetConfig)config;
|
||||
else if (config is JObject) unetConfig = ((JObject)config).ToObject<UnetConfig>();
|
||||
|
||||
for (int i = 0; i < unetConfig.Channels.Count; i++)
|
||||
{
|
||||
unetConfig.ConnectionConfig.AddChannel(unetConfig.Channels[i]);
|
||||
}
|
||||
|
||||
Program.DEFAULT_CHANNEL_BYTE = unetConfig.ConnectionConfig.AddChannel(QosType.ReliableSequenced);
|
||||
|
||||
unetManager = new NetLibraryManager(unetConfig.GlobalConfig);
|
||||
|
||||
hostId = unetManager.AddHost(new HostTopology(unetConfig.ConnectionConfig, unetConfig.MaxConnections), Program.Config.ListenPort, null);
|
||||
}
|
||||
|
||||
public override RelayConfig BeforeSerializeConfig(RelayConfig config)
|
||||
{
|
||||
UnetConfig unetConfig = null;
|
||||
|
||||
if (config.TransportConfig is UnetConfig) unetConfig = (UnetConfig)config.TransportConfig;
|
||||
else if (config.TransportConfig is JObject) unetConfig = ((JObject)config.TransportConfig).ToObject<UnetConfig>();
|
||||
|
||||
unetConfig.Channels.Clear();
|
||||
|
||||
for (int i = 0; i < unetConfig.ConnectionConfig.Channels.Count; i++)
|
||||
{
|
||||
unetConfig.Channels.Add(unetConfig.ConnectionConfig.Channels[i].QOS);
|
||||
}
|
||||
|
||||
unetConfig.ConnectionConfig.Channels.Clear();
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
public override RelayConfig AfterDeserializedConfig(RelayConfig config)
|
||||
{
|
||||
UnetConfig unetConfig = null;
|
||||
|
||||
if (config.TransportConfig is UnetConfig) unetConfig = (UnetConfig)config.TransportConfig;
|
||||
else if (config.TransportConfig is JObject) unetConfig = ((JObject)config.TransportConfig).ToObject<UnetConfig>();
|
||||
|
||||
unetConfig.ConnectionConfig.Channels.Clear();
|
||||
|
||||
for (int i = 0; i < unetConfig.Channels.Count; i++)
|
||||
{
|
||||
unetConfig.ConnectionConfig.AddChannel(unetConfig.Channels[i]);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
public override string ProcessSerializedJson(string json)
|
||||
{
|
||||
return json.Replace(",\n \"ChannelCount\": 0,\n \"SharedOrderChannelCount\": 0,\n \"Channels\": []", "");
|
||||
}
|
||||
|
||||
public class UnetConfig
|
||||
{
|
||||
public ushort MaxConnections { get; set; } = 100;
|
||||
public ConnectionConfig ConnectionConfig { get; set; } = new ConnectionConfig();
|
||||
public GlobalConfig GlobalConfig { get; set; } = new GlobalConfig();
|
||||
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
|
||||
public List<QosType> Channels = new List<QosType>();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user