163 lines
6.3 KiB
C#
Raw Normal View History

2024-10-17 17:23:05 +03:00
// 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