mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
feature: Edgegap Relay from https://github.com/edgegap/distributed-relay-examples
This commit is contained in:
parent
04af0fc709
commit
52e36977fe
8
Assets/Mirror/Transports/Edgegap.meta
Normal file
8
Assets/Mirror/Transports/Edgegap.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d2959d363903444bae4333db12a9ea1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/Mirror/Transports/Edgegap/EdgegapRelay.meta
Normal file
8
Assets/Mirror/Transports/Edgegap/EdgegapRelay.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62c28e855fc644011b4079c268b46b71
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,141 @@
|
||||
// overwrite RawSend/Receive
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using Mirror;
|
||||
using UnityEngine;
|
||||
using kcp2k;
|
||||
|
||||
namespace Edgegap
|
||||
{
|
||||
public class EdgegapKcpClient : KcpClient
|
||||
{
|
||||
// need buffer larger than KcpClient.rawReceiveBuffer to add metadata
|
||||
readonly byte[] relayReceiveBuffer;
|
||||
|
||||
// authentication
|
||||
public uint userId;
|
||||
public uint sessionId;
|
||||
public ConnectionState state = ConnectionState.Disconnected;
|
||||
|
||||
// ping
|
||||
double lastPingTime;
|
||||
|
||||
public EdgegapKcpClient(
|
||||
Action OnConnected,
|
||||
Action<ArraySegment<byte>, KcpChannel> OnData,
|
||||
Action OnDisconnected,
|
||||
Action<ErrorCode, string> OnError,
|
||||
KcpConfig config)
|
||||
: base(OnConnected, OnData, OnDisconnected, OnError, config)
|
||||
{
|
||||
relayReceiveBuffer = new byte[config.Mtu + Protocol.Overhead];
|
||||
}
|
||||
|
||||
// custom start function with relay parameters; connects udp client.
|
||||
public void Connect(string relayAddress, ushort relayPort, uint userId, uint sessionId)
|
||||
{
|
||||
// reset last state
|
||||
state = ConnectionState.Checking;
|
||||
this.userId = userId;
|
||||
this.sessionId = sessionId;
|
||||
|
||||
// reuse base connect
|
||||
base.Connect(relayAddress, relayPort);
|
||||
}
|
||||
|
||||
// parse metadata, then pass to kcp
|
||||
protected override bool RawReceive(out ArraySegment<byte> segment)
|
||||
{
|
||||
segment = default;
|
||||
if (socket == null) return false;
|
||||
|
||||
try
|
||||
{
|
||||
if (socket.ReceiveNonBlocking(relayReceiveBuffer, out ArraySegment<byte> content))
|
||||
{
|
||||
using (NetworkReaderPooled reader = NetworkReaderPool.Get(content))
|
||||
{
|
||||
// parse message type
|
||||
if (reader.Remaining == 0)
|
||||
{
|
||||
Debug.LogWarning($"EdgegapClient: message of {content.Count} is too small to parse.");
|
||||
return false;
|
||||
}
|
||||
byte messageType = reader.ReadByte();
|
||||
|
||||
// handle message type
|
||||
switch (messageType)
|
||||
{
|
||||
case (byte)MessageType.Ping:
|
||||
{
|
||||
// parse state
|
||||
if (reader.Remaining < 1) return false;
|
||||
ConnectionState last = state;
|
||||
state = (ConnectionState)reader.ReadByte();
|
||||
|
||||
// log state changes for debugging.
|
||||
if (state != last) Debug.Log($"EdgegapClient: state updated to: {state}");
|
||||
|
||||
// return true indicates Mirror to keep checking
|
||||
// for further messages.
|
||||
return true;
|
||||
}
|
||||
case (byte)MessageType.Data:
|
||||
{
|
||||
segment = reader.ReadBytesSegment(reader.Remaining);
|
||||
return true;
|
||||
}
|
||||
// wrong message type. return false, don't throw.
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
Log.Info($"EdgegapClient: looks like the other end has closed the connection. This is fine: {e}");
|
||||
peer.Disconnect();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void RawSend(ArraySegment<byte> data)
|
||||
{
|
||||
using (NetworkWriterPooled writer = NetworkWriterPool.Get())
|
||||
{
|
||||
writer.WriteUInt(userId);
|
||||
writer.WriteUInt(sessionId);
|
||||
writer.WriteByte((byte)MessageType.Data);
|
||||
writer.WriteBytes(data.Array, data.Offset, data.Count);
|
||||
base.RawSend(writer);
|
||||
}
|
||||
}
|
||||
|
||||
void SendPing()
|
||||
{
|
||||
using (NetworkWriterPooled writer = NetworkWriterPool.Get())
|
||||
{
|
||||
writer.WriteUInt(userId);
|
||||
writer.WriteUInt(sessionId);
|
||||
writer.WriteByte((byte)MessageType.Ping);
|
||||
base.RawSend(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public override void TickOutgoing()
|
||||
{
|
||||
if (connected)
|
||||
{
|
||||
// ping every interval for keepalive & handshake
|
||||
if (NetworkTime.localTime >= lastPingTime + Protocol.PingInterval)
|
||||
{
|
||||
SendPing();
|
||||
lastPingTime = NetworkTime.localTime;
|
||||
}
|
||||
}
|
||||
|
||||
base.TickOutgoing();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0d6fba7098f4ea3949d0195e8276adc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 3ea6ff15cda674a57b0c7c8b7dc1878c, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,203 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using Mirror;
|
||||
using UnityEngine;
|
||||
using kcp2k;
|
||||
|
||||
namespace Edgegap
|
||||
{
|
||||
public class EdgegapKcpServer : KcpServer
|
||||
{
|
||||
// need buffer larger than KcpClient.rawReceiveBuffer to add metadata
|
||||
readonly byte[] relayReceiveBuffer;
|
||||
|
||||
// authentication
|
||||
public uint userId;
|
||||
public uint sessionId;
|
||||
public ConnectionState state = ConnectionState.Disconnected;
|
||||
|
||||
// server is an UDP client talking to relay
|
||||
protected Socket relaySocket;
|
||||
public EndPoint remoteEndPoint;
|
||||
|
||||
// ping
|
||||
double lastPingTime;
|
||||
|
||||
// custom 'active'. while connected to relay
|
||||
bool relayActive;
|
||||
|
||||
public EdgegapKcpServer(
|
||||
Action<int> OnConnected,
|
||||
Action<int, ArraySegment<byte>, KcpChannel> OnData,
|
||||
Action<int> OnDisconnected,
|
||||
Action<int, ErrorCode, string> OnError,
|
||||
KcpConfig config)
|
||||
// TODO don't call base. don't listen to local UdpServer at all?
|
||||
: base(OnConnected, OnData, OnDisconnected, OnError, config)
|
||||
{
|
||||
relayReceiveBuffer = new byte[config.Mtu + Protocol.Overhead];
|
||||
}
|
||||
|
||||
public override bool IsActive() => relayActive;
|
||||
|
||||
// custom start function with relay parameters; connects udp client.
|
||||
public void Start(string relayAddress, ushort relayPort, uint userId, uint sessionId)
|
||||
{
|
||||
// reset last state
|
||||
state = ConnectionState.Checking;
|
||||
this.userId = userId;
|
||||
this.sessionId = sessionId;
|
||||
|
||||
// try resolve host name
|
||||
if (!Common.ResolveHostname(relayAddress, out IPAddress[] addresses))
|
||||
{
|
||||
OnError(0, ErrorCode.DnsResolve, $"Failed to resolve host: {relayAddress}");
|
||||
return;
|
||||
}
|
||||
|
||||
// create socket
|
||||
remoteEndPoint = new IPEndPoint(addresses[0], relayPort);
|
||||
relaySocket = new Socket(remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
|
||||
relaySocket.Blocking = false;
|
||||
|
||||
// configure buffer sizes
|
||||
Common.ConfigureSocketBuffers(relaySocket, config.RecvBufferSize, config.SendBufferSize);
|
||||
|
||||
// bind to endpoint for Send/Receive instead of SendTo/ReceiveFrom
|
||||
relaySocket.Connect(remoteEndPoint);
|
||||
relayActive = true;
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
relayActive = false;
|
||||
}
|
||||
|
||||
protected override bool RawReceiveFrom(out ArraySegment<byte> segment, out int connectionId)
|
||||
{
|
||||
segment = default;
|
||||
connectionId = 0;
|
||||
|
||||
if (relaySocket == null) return false;
|
||||
|
||||
try
|
||||
{
|
||||
// TODO need separate buffer. don't write into result yet. only payload
|
||||
|
||||
if (relaySocket.ReceiveNonBlocking(relayReceiveBuffer, out ArraySegment<byte> content))
|
||||
{
|
||||
using (NetworkReaderPooled reader = NetworkReaderPool.Get(content))
|
||||
{
|
||||
// parse message type
|
||||
if (reader.Remaining == 0)
|
||||
{
|
||||
Debug.LogWarning($"EdgegapServer: message of {content.Count} is too small to parse header.");
|
||||
return false;
|
||||
}
|
||||
byte messageType = reader.ReadByte();
|
||||
|
||||
// handle message type
|
||||
switch (messageType)
|
||||
{
|
||||
case (byte)MessageType.Ping:
|
||||
{
|
||||
// parse state
|
||||
if (reader.Remaining < 1) return false;
|
||||
ConnectionState last = state;
|
||||
state = (ConnectionState)reader.ReadByte();
|
||||
|
||||
// log state changes for debugging.
|
||||
if (state != last) Debug.Log($"EdgegapServer: state updated to: {state}");
|
||||
|
||||
// return true indicates Mirror to keep checking
|
||||
// for further messages.
|
||||
return true;
|
||||
}
|
||||
case (byte)MessageType.Data:
|
||||
{
|
||||
// parse connectionId and payload
|
||||
if (reader.Remaining <= 4)
|
||||
{
|
||||
Debug.LogWarning($"EdgegapServer: message of {content.Count} is too small to parse connId.");
|
||||
return false;
|
||||
}
|
||||
|
||||
connectionId = reader.ReadInt();
|
||||
segment = reader.ReadBytesSegment(reader.Remaining);
|
||||
// Debug.Log($"EdgegapServer: receiving from connId={connectionId}: {segment.ToHexString()}");
|
||||
return true;
|
||||
}
|
||||
// wrong message type. return false, don't throw.
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
Log.Info($"EdgegapServer: looks like the other end has closed the connection. This is fine: {e}");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void RawSend(int connectionId, ArraySegment<byte> data)
|
||||
{
|
||||
using (NetworkWriterPooled writer = NetworkWriterPool.Get())
|
||||
{
|
||||
// Debug.Log($"EdgegapServer: sending to connId={connectionId}: {data.ToHexString()}");
|
||||
writer.WriteUInt(userId);
|
||||
writer.WriteUInt(sessionId);
|
||||
writer.WriteByte((byte)MessageType.Data);
|
||||
writer.WriteInt(connectionId);
|
||||
writer.WriteBytes(data.Array, data.Offset, data.Count);
|
||||
ArraySegment<byte> message = writer;
|
||||
|
||||
try
|
||||
{
|
||||
relaySocket.SendNonBlocking(message);
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
Log.Error($"KcpRleayServer: RawSend failed: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendPing()
|
||||
{
|
||||
using (NetworkWriterPooled writer = NetworkWriterPool.Get())
|
||||
{
|
||||
writer.WriteUInt(userId);
|
||||
writer.WriteUInt(sessionId);
|
||||
writer.WriteByte((byte)MessageType.Ping);
|
||||
ArraySegment<byte> message = writer;
|
||||
|
||||
try
|
||||
{
|
||||
relaySocket.SendNonBlocking(message);
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
Debug.LogWarning($"EdgegapServer: failed to ping. perhaps the relay isn't running? {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void TickOutgoing()
|
||||
{
|
||||
if (relayActive)
|
||||
{
|
||||
// ping every interval for keepalive & handshake
|
||||
if (NetworkTime.localTime >= lastPingTime + Protocol.PingInterval)
|
||||
{
|
||||
SendPing();
|
||||
lastPingTime = NetworkTime.localTime;
|
||||
}
|
||||
}
|
||||
|
||||
// base processing
|
||||
base.TickOutgoing();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd8551078397248b0848950352c208ee
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 3ea6ff15cda674a57b0c7c8b7dc1878c, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,160 @@
|
||||
// edgegap relay transport.
|
||||
// reuses KcpTransport with custom KcpServer/Client.
|
||||
|
||||
//#if MIRROR <- commented out because MIRROR isn't defined on first import yet
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine;
|
||||
using Mirror;
|
||||
using kcp2k;
|
||||
|
||||
namespace Edgegap
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
public class EdgegapKcpTransport : KcpTransport
|
||||
{
|
||||
[Header("Relay")]
|
||||
public string relayAddress = "127.0.0.1";
|
||||
public ushort relayGameServerPort = 8888;
|
||||
public ushort relayGameClientPort = 9999;
|
||||
|
||||
// mtu for kcp transport. respects relay overhead.
|
||||
public const int MaxPayload = Kcp.MTU_DEF - Protocol.Overhead;
|
||||
|
||||
[Header("Relay")]
|
||||
public bool relayGUI = true;
|
||||
public uint userId = 11111111;
|
||||
public uint sessionId = 22222222;
|
||||
|
||||
// helper
|
||||
internal static String ReParse(String cmd, String pattern, String defaultValue)
|
||||
{
|
||||
Match match = Regex.Match(cmd, pattern);
|
||||
return match.Success ? match.Groups[1].Value : defaultValue;
|
||||
}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
// logging
|
||||
// Log.Info should use Debug.Log if enabled, or nothing otherwise
|
||||
// (don't want to spam the console on headless servers)
|
||||
if (debugLog)
|
||||
Log.Info = Debug.Log;
|
||||
else
|
||||
Log.Info = _ => {};
|
||||
Log.Warning = Debug.LogWarning;
|
||||
Log.Error = Debug.LogError;
|
||||
|
||||
// create config from serialized settings.
|
||||
// with MaxPayload as max size to respect relay overhead.
|
||||
config = new KcpConfig(DualMode, RecvBufferSize, SendBufferSize, MaxPayload, NoDelay, Interval, FastResend, false, SendWindowSize, ReceiveWindowSize, Timeout, MaxRetransmit);
|
||||
|
||||
// client (NonAlloc version is not necessary anymore)
|
||||
client = new EdgegapKcpClient(
|
||||
() => OnClientConnected.Invoke(),
|
||||
(message, channel) => OnClientDataReceived.Invoke(message, FromKcpChannel(channel)),
|
||||
() => OnClientDisconnected.Invoke(),
|
||||
(error, reason) => OnClientError.Invoke(ToTransportError(error), reason),
|
||||
config
|
||||
);
|
||||
|
||||
// server
|
||||
server = new EdgegapKcpServer(
|
||||
(connectionId) => OnServerConnected.Invoke(connectionId),
|
||||
(connectionId, message, channel) => OnServerDataReceived.Invoke(connectionId, message, FromKcpChannel(channel)),
|
||||
(connectionId) => OnServerDisconnected.Invoke(connectionId),
|
||||
(connectionId, error, reason) => OnServerError.Invoke(connectionId, ToTransportError(error), reason),
|
||||
config);
|
||||
|
||||
if (statisticsLog)
|
||||
InvokeRepeating(nameof(OnLogStatistics), 1, 1);
|
||||
|
||||
Debug.Log("EdgegapTransport initialized!");
|
||||
}
|
||||
|
||||
protected override void OnValidate()
|
||||
{
|
||||
// show max message sizes in inspector for convenience.
|
||||
// 'config' isn't available in edit mode yet, so use MTU define.
|
||||
ReliableMaxMessageSize = KcpPeer.ReliableMaxMessageSize(MaxPayload, ReceiveWindowSize);
|
||||
UnreliableMaxMessageSize = KcpPeer.UnreliableMaxMessageSize(MaxPayload);
|
||||
}
|
||||
|
||||
// client overwrites to use EdgegapClient instead of KcpClient
|
||||
public override void ClientConnect(string address)
|
||||
{
|
||||
// connect to relay address:port instead of the expected server address
|
||||
EdgegapKcpClient client = (EdgegapKcpClient)this.client;
|
||||
client.userId = userId;
|
||||
client.sessionId = sessionId;
|
||||
client.state = ConnectionState.Checking; // reset from last time
|
||||
client.Connect(relayAddress, relayGameClientPort);
|
||||
}
|
||||
public override void ClientConnect(Uri uri)
|
||||
{
|
||||
if (uri.Scheme != Scheme)
|
||||
throw new ArgumentException($"Invalid url {uri}, use {Scheme}://host:port instead", nameof(uri));
|
||||
|
||||
// connect to relay address:port instead of the expected server address
|
||||
EdgegapKcpClient client = (EdgegapKcpClient)this.client;
|
||||
client.Connect(relayAddress, relayGameClientPort, userId, sessionId);
|
||||
}
|
||||
|
||||
// server overwrites to use EdgegapServer instead of KcpServer
|
||||
public override void ServerStart()
|
||||
{
|
||||
// start the server
|
||||
EdgegapKcpServer server = (EdgegapKcpServer)this.server;
|
||||
server.Start(relayAddress, relayGameServerPort, userId, sessionId);
|
||||
}
|
||||
|
||||
void OnGUIRelay()
|
||||
{
|
||||
// if (server.IsActive()) return;
|
||||
|
||||
GUILayout.BeginArea(new Rect(300, 30, 200, 100));
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("SessionId:");
|
||||
sessionId = Convert.ToUInt32(GUILayout.TextField(sessionId.ToString()));
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("UserId:");
|
||||
userId = Convert.ToUInt32(GUILayout.TextField(userId.ToString()));
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
if (NetworkServer.active)
|
||||
{
|
||||
EdgegapKcpServer server = (EdgegapKcpServer)this.server;
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("State:");
|
||||
GUILayout.Label(server.state.ToString());
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
else if (NetworkClient.active)
|
||||
{
|
||||
EdgegapKcpClient client = (EdgegapKcpClient)this.client;
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("State:");
|
||||
GUILayout.Label(client.state.ToString());
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
GUILayout.EndArea();
|
||||
}
|
||||
|
||||
// base OnGUI only shows in editor & development builds.
|
||||
// here we always show it because we need the sessionid & userid buttons.
|
||||
new void OnGUI()
|
||||
{
|
||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||
base.OnGUI();
|
||||
#endif
|
||||
if (relayGUI) OnGUIRelay();
|
||||
}
|
||||
|
||||
public override string ToString() => "Edgegap Kcp Transport";
|
||||
}
|
||||
}
|
||||
//#endif MIRROR <- commented out because MIRROR isn't defined on first import yet
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2d1e0e17f753449798fa27474d6b86b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 3ea6ff15cda674a57b0c7c8b7dc1878c, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
29
Assets/Mirror/Transports/Edgegap/EdgegapRelay/Protocol.cs
Normal file
29
Assets/Mirror/Transports/Edgegap/EdgegapRelay/Protocol.cs
Normal file
@ -0,0 +1,29 @@
|
||||
// relay protocol definitions
|
||||
namespace Edgegap
|
||||
{
|
||||
public enum ConnectionState : byte
|
||||
{
|
||||
Disconnected = 0, // until the user calls connect()
|
||||
Checking = 1, // recently connected, validation in progress
|
||||
Valid = 2, // validation succeeded
|
||||
Invalid = 3, // validation rejected by tower
|
||||
SessionTimeout = 4, // session owner timed out
|
||||
Error = 5, // other error
|
||||
}
|
||||
|
||||
public enum MessageType : byte
|
||||
{
|
||||
Ping = 1,
|
||||
Data = 2
|
||||
}
|
||||
|
||||
public static class Protocol
|
||||
{
|
||||
// MTU: relay adds up to 13 bytes of metadata in the worst case.
|
||||
public const int Overhead = 13;
|
||||
|
||||
// ping interval should be between 100 ms and 1 second.
|
||||
// faster ping gives faster authentication, but higher bandwidth.
|
||||
public const float PingInterval = 0.5f;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eac30312ba61470b849e368af3c3b0e9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 3ea6ff15cda674a57b0c7c8b7dc1878c, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
20
Assets/Mirror/Transports/Edgegap/EdgegapRelay/README.md
Normal file
20
Assets/Mirror/Transports/Edgegap/EdgegapRelay/README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# Edgegap Relay for Mirror
|
||||
Documentation: https://docs.edgegap.com/docs/distributed-relay-manager/
|
||||
|
||||
## Prerequisites
|
||||
- Unity project set up with the Mirror networking library installed
|
||||
- Supported Versions: [Mirror](https://assetstore.unity.com/packages/tools/network/mirror-129321) and [Mirror LTS](https://assetstore.unity.com/packages/tools/network/mirror-lts-102631)
|
||||
- EdgegapTransport module downloaded and extracted
|
||||
|
||||
## Steps
|
||||
1. Open your Unity project and navigate to the "Assets" folder.
|
||||
2. Locate the "Mirror" folder within "Assets" and open it.
|
||||
3. Within the "Mirror" folder, open the "Transports" folder.
|
||||
4. Drag and drop the "Unity" folder from the extracted EdgegapTransport files into the "Transports" folder.
|
||||
5. Open your NetworkManager script in the Unity Editor and navigate to the "Inspector" panel.
|
||||
6. In the "Inspector" panel, locate the "Network Manager" component and click the "+" button next to the "Transport" property.
|
||||
7. In the "Add Component" menu that appears, select "Edgegap Transport" to add it to the NetworkManager.
|
||||
8. Drag the newly added "Edgegap Transport" component into the "Transport" property in the "Inspector" panel.
|
||||
|
||||
## Notes
|
||||
- The EdgegapTransport module is only compatible with Mirror and Mirror LTS versions.
|
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ade7c960d8fe4e94970ddd88ede3bca
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,25 @@
|
||||
// parse session_id and user_id from command line args.
|
||||
// mac: "open mirror.app --args session_id=123 user_id=456"
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Edgegap
|
||||
{
|
||||
public class RelayCredentialsFromArgs : MonoBehaviour
|
||||
{
|
||||
void Awake()
|
||||
{
|
||||
String cmd = Environment.CommandLine;
|
||||
|
||||
// parse session_id via regex
|
||||
String sessionId = EdgegapKcpTransport.ReParse(cmd, "session_id=(\\d+)", "111111");
|
||||
String userID = EdgegapKcpTransport.ReParse(cmd, "user_id=(\\d+)", "222222");
|
||||
Debug.Log($"Parsed sessionId: {sessionId} user_id: {userID}");
|
||||
|
||||
// configure transport
|
||||
EdgegapKcpTransport transport = GetComponent<EdgegapKcpTransport>();
|
||||
transport.sessionId = UInt32.Parse(sessionId);
|
||||
transport.userId = UInt32.Parse(userID);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9ec7091b26c4d3882f4b42f10f9b8c1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 3ea6ff15cda674a57b0c7c8b7dc1878c, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
BIN
Assets/Mirror/Transports/Edgegap/edgegap.png
Normal file
BIN
Assets/Mirror/Transports/Edgegap/edgegap.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
123
Assets/Mirror/Transports/Edgegap/edgegap.png.meta
Normal file
123
Assets/Mirror/Transports/Edgegap/edgegap.png.meta
Normal file
@ -0,0 +1,123 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ea6ff15cda674a57b0c7c8b7dc1878c
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 0
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 16
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Reference in New Issue
Block a user