163 lines
6.3 KiB
C#
163 lines
6.3 KiB
C#
|
// 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.connectionState = 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.connectionState.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.
|
||
|
#pragma warning disable CS0109
|
||
|
new void OnGUI()
|
||
|
{
|
||
|
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||
|
base.OnGUI();
|
||
|
#endif
|
||
|
if (relayGUI) OnGUIRelay();
|
||
|
}
|
||
|
|
||
|
public override string ToString() => "Edgegap Kcp Transport";
|
||
|
}
|
||
|
#pragma warning restore CS0109
|
||
|
}
|
||
|
//#endif MIRROR <- commented out because MIRROR isn't defined on first import yet
|