Partials and Comments
This commit is contained in:
parent
fddd354772
commit
6793245822
10 changed files with 562 additions and 447 deletions
|
|
@ -6,6 +6,7 @@ using Microsoft.Extensions.Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace LightReflectiveMirror.Endpoints
|
namespace LightReflectiveMirror.Endpoints
|
||||||
|
|
@ -22,7 +23,7 @@ namespace LightReflectiveMirror.Endpoints
|
||||||
[RestResource]
|
[RestResource]
|
||||||
public class Endpoint
|
public class Endpoint
|
||||||
{
|
{
|
||||||
private List<Room> _rooms { get => Program.instance.GetRooms(); }
|
private List<Room> _rooms { get => Program.instance.GetRooms().Where(x => x.isPublic).ToList(); }
|
||||||
|
|
||||||
private RelayStats _stats { get => new RelayStats
|
private RelayStats _stats { get => new RelayStats
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,32 +13,8 @@ using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace LightReflectiveMirror
|
namespace LightReflectiveMirror
|
||||||
{
|
{
|
||||||
class Program
|
partial class Program
|
||||||
{
|
{
|
||||||
public static Transport transport;
|
|
||||||
public static Program instance;
|
|
||||||
public static Config conf;
|
|
||||||
|
|
||||||
private RelayHandler _relay;
|
|
||||||
private MethodInfo _awakeMethod;
|
|
||||||
private MethodInfo _startMethod;
|
|
||||||
private MethodInfo _updateMethod;
|
|
||||||
private MethodInfo _lateUpdateMethod;
|
|
||||||
|
|
||||||
private DateTime _startupTime;
|
|
||||||
public static string publicIP;
|
|
||||||
private List<int> _currentConnections = new List<int>();
|
|
||||||
public Dictionary<int, IPEndPoint> NATConnections = new Dictionary<int, IPEndPoint>();
|
|
||||||
private BiDictionary<int, string> _pendingNATPunches = new BiDictionary<int, string>();
|
|
||||||
private int _currentHeartbeatTimer = 0;
|
|
||||||
|
|
||||||
private byte[] _NATRequest = new byte[500];
|
|
||||||
private int _NATRequestPosition = 0;
|
|
||||||
|
|
||||||
private UdpClient _punchServer;
|
|
||||||
|
|
||||||
private const string CONFIG_PATH = "config.json";
|
|
||||||
|
|
||||||
public static void Main(string[] args) => new Program().MainAsync().GetAwaiter().GetResult();
|
public static void Main(string[] args) => new Program().MainAsync().GetAwaiter().GetResult();
|
||||||
|
|
||||||
public int GetConnections() => _currentConnections.Count;
|
public int GetConnections() => _currentConnections.Count;
|
||||||
|
|
@ -245,57 +221,6 @@ namespace LightReflectiveMirror
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunNATPunchLoop()
|
|
||||||
{
|
|
||||||
WriteLogMessage("OK\n", ConsoleColor.Green);
|
|
||||||
IPEndPoint remoteEndpoint = new(IPAddress.Any, conf.NATPunchtroughPort);
|
|
||||||
|
|
||||||
// Stock Data server sends to everyone:
|
|
||||||
var serverResponse = new byte[1] { 1 };
|
|
||||||
|
|
||||||
byte[] readData;
|
|
||||||
bool isConnectionEstablishment;
|
|
||||||
int pos;
|
|
||||||
string connectionID;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
readData = _punchServer.Receive(ref remoteEndpoint);
|
|
||||||
pos = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
isConnectionEstablishment = readData.ReadBool(ref pos);
|
|
||||||
|
|
||||||
if (isConnectionEstablishment)
|
|
||||||
{
|
|
||||||
connectionID = readData.ReadString(ref pos);
|
|
||||||
|
|
||||||
if (_pendingNATPunches.TryGetBySecond(connectionID, out pos))
|
|
||||||
{
|
|
||||||
NATConnections.Add(pos, new IPEndPoint(remoteEndpoint.Address, remoteEndpoint.Port));
|
|
||||||
_pendingNATPunches.Remove(pos);
|
|
||||||
Console.WriteLine("Client Successfully Established Puncher Connection. " + remoteEndpoint.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_punchServer.Send(serverResponse, 1, remoteEndpoint);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignore, packet got fucked up or something.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteLogMessage(string message, ConsoleColor color = ConsoleColor.White, bool oneLine = false)
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = color;
|
|
||||||
if (oneLine)
|
|
||||||
Console.Write(message);
|
|
||||||
else
|
|
||||||
Console.WriteLine(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckMethods(Type type)
|
void CheckMethods(Type type)
|
||||||
{
|
{
|
||||||
_awakeMethod = type.GetMethod("Awake", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
_awakeMethod = type.GetMethod("Awake", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
|
|
@ -303,26 +228,5 @@ namespace LightReflectiveMirror
|
||||||
_updateMethod = type.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
_updateMethod = type.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
_lateUpdateMethod = type.GetMethod("LateUpdate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
_lateUpdateMethod = type.GetMethod("LateUpdate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteTitle()
|
|
||||||
{
|
|
||||||
string t = @"
|
|
||||||
w c(..)o (
|
|
||||||
_ _____ __ __ \__(-) __)
|
|
||||||
| | | __ \ | \/ | /\ (
|
|
||||||
| | | |__) || \ / | /(_)___)
|
|
||||||
| | | _ / | |\/| | w /|
|
|
||||||
| |____ | | \ \ | | | | | \
|
|
||||||
|______||_| \_\|_| |_| m m copyright monkesoft 2021
|
|
||||||
|
|
||||||
";
|
|
||||||
|
|
||||||
string load = $"Chimp Event Listener Initializing... OK" +
|
|
||||||
"\nHarambe Memorial Initializing... OK" +
|
|
||||||
"\nBananas Initializing... OK\n";
|
|
||||||
|
|
||||||
WriteLogMessage(t, ConsoleColor.Green);
|
|
||||||
WriteLogMessage(load, ConsoleColor.Cyan);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LightReflectiveMirror
|
||||||
|
{
|
||||||
|
partial class Program
|
||||||
|
{
|
||||||
|
|
||||||
|
static void WriteLogMessage(string message, ConsoleColor color = ConsoleColor.White, bool oneLine = false)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = color;
|
||||||
|
if (oneLine)
|
||||||
|
Console.Write(message);
|
||||||
|
else
|
||||||
|
Console.WriteLine(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteTitle()
|
||||||
|
{
|
||||||
|
string t = @"
|
||||||
|
w c(..)o (
|
||||||
|
_ _____ __ __ \__(-) __)
|
||||||
|
| | | __ \ | \/ | /\ (
|
||||||
|
| | | |__) || \ / | /(_)___)
|
||||||
|
| | | _ / | |\/| | w /|
|
||||||
|
| |____ | | \ \ | | | | | \
|
||||||
|
|______||_| \_\|_| |_| m m copyright monkesoft 2021
|
||||||
|
|
||||||
|
";
|
||||||
|
|
||||||
|
string load = $"Chimp Event Listener Initializing... OK" +
|
||||||
|
"\nHarambe Memorial Initializing... OK" +
|
||||||
|
"\nBananas Initializing... OK\n";
|
||||||
|
|
||||||
|
WriteLogMessage(t, ConsoleColor.Green);
|
||||||
|
WriteLogMessage(load, ConsoleColor.Cyan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace LightReflectiveMirror
|
||||||
|
{
|
||||||
|
partial class Program
|
||||||
|
{
|
||||||
|
void RunNATPunchLoop()
|
||||||
|
{
|
||||||
|
WriteLogMessage("OK\n", ConsoleColor.Green);
|
||||||
|
IPEndPoint remoteEndpoint = new(IPAddress.Any, conf.NATPunchtroughPort);
|
||||||
|
|
||||||
|
// Stock Data server sends to everyone:
|
||||||
|
var serverResponse = new byte[1] { 1 };
|
||||||
|
|
||||||
|
byte[] readData;
|
||||||
|
bool isConnectionEstablishment;
|
||||||
|
int pos;
|
||||||
|
string connectionID;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
readData = _punchServer.Receive(ref remoteEndpoint);
|
||||||
|
pos = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
isConnectionEstablishment = readData.ReadBool(ref pos);
|
||||||
|
|
||||||
|
if (isConnectionEstablishment)
|
||||||
|
{
|
||||||
|
connectionID = readData.ReadString(ref pos);
|
||||||
|
|
||||||
|
if (_pendingNATPunches.TryGetBySecond(connectionID, out pos))
|
||||||
|
{
|
||||||
|
NATConnections.Add(pos, new IPEndPoint(remoteEndpoint.Address, remoteEndpoint.Port));
|
||||||
|
_pendingNATPunches.Remove(pos);
|
||||||
|
Console.WriteLine("Client Successfully Established Puncher Connection. " + remoteEndpoint.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_punchServer.Send(serverResponse, 1, remoteEndpoint);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore, packet got fucked up or something.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
using Mirror;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace LightReflectiveMirror
|
||||||
|
{
|
||||||
|
partial class Program
|
||||||
|
{
|
||||||
|
public static Transport transport;
|
||||||
|
public static Program instance;
|
||||||
|
public static Config conf;
|
||||||
|
|
||||||
|
private RelayHandler _relay;
|
||||||
|
private MethodInfo _awakeMethod;
|
||||||
|
private MethodInfo _startMethod;
|
||||||
|
private MethodInfo _updateMethod;
|
||||||
|
private MethodInfo _lateUpdateMethod;
|
||||||
|
|
||||||
|
private DateTime _startupTime;
|
||||||
|
public static string publicIP;
|
||||||
|
private List<int> _currentConnections = new List<int>();
|
||||||
|
public Dictionary<int, IPEndPoint> NATConnections = new Dictionary<int, IPEndPoint>();
|
||||||
|
private BiDictionary<int, string> _pendingNATPunches = new BiDictionary<int, string>();
|
||||||
|
private int _currentHeartbeatTimer = 0;
|
||||||
|
|
||||||
|
private byte[] _NATRequest = new byte[500];
|
||||||
|
private int _NATRequestPosition = 0;
|
||||||
|
|
||||||
|
private UdpClient _punchServer;
|
||||||
|
|
||||||
|
private const string CONFIG_PATH = "config.json";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,349 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Buffers;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace LightReflectiveMirror
|
|
||||||
{
|
|
||||||
public class RelayHandler
|
|
||||||
{
|
|
||||||
public List<Room> rooms = new List<Room>();
|
|
||||||
private List<int> _pendingAuthentication = new List<int>();
|
|
||||||
private ArrayPool<byte> _sendBuffers;
|
|
||||||
private int _maxPacketSize = 0;
|
|
||||||
|
|
||||||
public RelayHandler(int maxPacketSize)
|
|
||||||
{
|
|
||||||
this._maxPacketSize = maxPacketSize;
|
|
||||||
_sendBuffers = ArrayPool<byte>.Create(maxPacketSize, 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClientConnected(int clientId)
|
|
||||||
{
|
|
||||||
_pendingAuthentication.Add(clientId);
|
|
||||||
var buffer = _sendBuffers.Rent(1);
|
|
||||||
int pos = 0;
|
|
||||||
buffer.WriteByte(ref pos, (byte)OpCodes.AuthenticationRequest);
|
|
||||||
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(buffer, 0, pos));
|
|
||||||
_sendBuffers.Return(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleMessage(int clientId, ArraySegment<byte> segmentData, int channel)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var data = segmentData.Array;
|
|
||||||
int pos = segmentData.Offset;
|
|
||||||
|
|
||||||
OpCodes opcode = (OpCodes)data.ReadByte(ref pos);
|
|
||||||
|
|
||||||
if (_pendingAuthentication.Contains(clientId))
|
|
||||||
{
|
|
||||||
if (opcode == OpCodes.AuthenticationResponse)
|
|
||||||
{
|
|
||||||
string authResponse = data.ReadString(ref pos);
|
|
||||||
if (authResponse == Program.conf.AuthenticationKey)
|
|
||||||
{
|
|
||||||
_pendingAuthentication.Remove(clientId);
|
|
||||||
int writePos = 0;
|
|
||||||
var sendBuffer = _sendBuffers.Rent(1);
|
|
||||||
sendBuffer.WriteByte(ref writePos, (byte)OpCodes.Authenticated);
|
|
||||||
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendBuffer, 0, writePos));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (opcode)
|
|
||||||
{
|
|
||||||
case OpCodes.CreateRoom:
|
|
||||||
CreateRoom(clientId, data.ReadInt(ref pos), data.ReadString(ref pos), data.ReadBool(ref pos), data.ReadString(ref pos), data.ReadBool(ref pos), data.ReadString(ref pos), data.ReadBool(ref pos), data.ReadInt(ref pos));
|
|
||||||
break;
|
|
||||||
case OpCodes.RequestID:
|
|
||||||
SendClientID(clientId);
|
|
||||||
break;
|
|
||||||
case OpCodes.LeaveRoom:
|
|
||||||
LeaveRoom(clientId);
|
|
||||||
break;
|
|
||||||
case OpCodes.JoinServer:
|
|
||||||
JoinRoom(clientId, data.ReadInt(ref pos), data.ReadBool(ref pos), data.ReadString(ref pos));
|
|
||||||
break;
|
|
||||||
case OpCodes.KickPlayer:
|
|
||||||
LeaveRoom(data.ReadInt(ref pos), clientId);
|
|
||||||
break;
|
|
||||||
case OpCodes.SendData:
|
|
||||||
ProcessData(clientId, data.ReadBytes(ref pos), channel, data.ReadInt(ref pos));
|
|
||||||
break;
|
|
||||||
case OpCodes.UpdateRoomData:
|
|
||||||
var plyRoom = GetRoomForPlayer(clientId);
|
|
||||||
|
|
||||||
if (plyRoom == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool newName = data.ReadBool(ref pos);
|
|
||||||
if (newName)
|
|
||||||
plyRoom.serverName = data.ReadString(ref pos);
|
|
||||||
|
|
||||||
bool newData = data.ReadBool(ref pos);
|
|
||||||
if (newData)
|
|
||||||
plyRoom.serverData = data.ReadString(ref pos);
|
|
||||||
|
|
||||||
bool newPublicStatus = data.ReadBool(ref pos);
|
|
||||||
if (newPublicStatus)
|
|
||||||
plyRoom.isPublic = data.ReadBool(ref pos);
|
|
||||||
|
|
||||||
bool newPlayerCap = data.ReadBool(ref pos);
|
|
||||||
if (newPlayerCap)
|
|
||||||
plyRoom.maxPlayers = data.ReadInt(ref pos);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Do Nothing. Client probably sent some invalid data.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleDisconnect(int clientId) => LeaveRoom(clientId);
|
|
||||||
|
|
||||||
void ProcessData(int clientId, byte[] clientData, int channel, int sendTo = -1)
|
|
||||||
{
|
|
||||||
Room playersRoom = GetRoomForPlayer(clientId);
|
|
||||||
|
|
||||||
if(playersRoom != null)
|
|
||||||
{
|
|
||||||
Room room = playersRoom;
|
|
||||||
|
|
||||||
if(room.hostId == clientId)
|
|
||||||
{
|
|
||||||
if (room.clients.Contains(sendTo))
|
|
||||||
{
|
|
||||||
int pos = 0;
|
|
||||||
byte[] sendBuffer = _sendBuffers.Rent(_maxPacketSize);
|
|
||||||
|
|
||||||
sendBuffer.WriteByte(ref pos, (byte)OpCodes.GetData);
|
|
||||||
sendBuffer.WriteBytes(ref pos, clientData);
|
|
||||||
|
|
||||||
Program.transport.ServerSend(sendTo, channel, new ArraySegment<byte>(sendBuffer, 0, pos));
|
|
||||||
_sendBuffers.Return(sendBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// We are not the host, so send the data to the host.
|
|
||||||
int pos = 0;
|
|
||||||
byte[] sendBuffer = _sendBuffers.Rent(_maxPacketSize);
|
|
||||||
|
|
||||||
sendBuffer.WriteByte(ref pos, (byte)OpCodes.GetData);
|
|
||||||
sendBuffer.WriteBytes(ref pos, clientData);
|
|
||||||
sendBuffer.WriteInt(ref pos, clientId);
|
|
||||||
|
|
||||||
Program.transport.ServerSend(room.hostId, channel, new ArraySegment<byte>(sendBuffer, 0, pos));
|
|
||||||
_sendBuffers.Return(sendBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Room GetRoomForPlayer(int clientId)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < rooms.Count; i++)
|
|
||||||
{
|
|
||||||
if (rooms[i].hostId == clientId)
|
|
||||||
return rooms[i];
|
|
||||||
|
|
||||||
if (rooms[i].clients.Contains(clientId))
|
|
||||||
return rooms[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JoinRoom(int clientId, int serverId, bool canDirectConnect, string localIP)
|
|
||||||
{
|
|
||||||
LeaveRoom(clientId);
|
|
||||||
|
|
||||||
for(int i = 0; i < rooms.Count; i++)
|
|
||||||
{
|
|
||||||
if(rooms[i].serverId == serverId)
|
|
||||||
{
|
|
||||||
if(rooms[i].clients.Count < rooms[i].maxPlayers)
|
|
||||||
{
|
|
||||||
rooms[i].clients.Add(clientId);
|
|
||||||
|
|
||||||
int sendJoinPos = 0;
|
|
||||||
byte[] sendJoinBuffer = _sendBuffers.Rent(500);
|
|
||||||
|
|
||||||
if (canDirectConnect && Program.instance.NATConnections.ContainsKey(clientId))
|
|
||||||
{
|
|
||||||
sendJoinBuffer.WriteByte(ref sendJoinPos, (byte)OpCodes.DirectConnectIP);
|
|
||||||
|
|
||||||
if (Program.instance.NATConnections[clientId].Address.Equals(rooms[i].hostIP.Address))
|
|
||||||
sendJoinBuffer.WriteString(ref sendJoinPos, rooms[i].hostLocalIP == localIP ? "127.0.0.1" : rooms[i].hostLocalIP);
|
|
||||||
else
|
|
||||||
sendJoinBuffer.WriteString(ref sendJoinPos, rooms[i].hostIP.Address.ToString());
|
|
||||||
|
|
||||||
sendJoinBuffer.WriteInt(ref sendJoinPos, rooms[i].useNATPunch ? rooms[i].hostIP.Port : rooms[i].port);
|
|
||||||
sendJoinBuffer.WriteBool(ref sendJoinPos, rooms[i].useNATPunch);
|
|
||||||
|
|
||||||
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
|
|
||||||
|
|
||||||
if (rooms[i].useNATPunch)
|
|
||||||
{
|
|
||||||
sendJoinPos = 0;
|
|
||||||
sendJoinBuffer.WriteByte(ref sendJoinPos, (byte)OpCodes.DirectConnectIP);
|
|
||||||
Console.WriteLine(Program.instance.NATConnections[clientId].Address.ToString());
|
|
||||||
sendJoinBuffer.WriteString(ref sendJoinPos, Program.instance.NATConnections[clientId].Address.ToString());
|
|
||||||
sendJoinBuffer.WriteInt(ref sendJoinPos, Program.instance.NATConnections[clientId].Port);
|
|
||||||
sendJoinBuffer.WriteBool(ref sendJoinPos, true);
|
|
||||||
|
|
||||||
Program.transport.ServerSend(rooms[i].hostId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
|
|
||||||
}
|
|
||||||
|
|
||||||
_sendBuffers.Return(sendJoinBuffer);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
sendJoinBuffer.WriteByte(ref sendJoinPos, (byte)OpCodes.ServerJoined);
|
|
||||||
sendJoinBuffer.WriteInt(ref sendJoinPos, clientId);
|
|
||||||
|
|
||||||
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
|
|
||||||
Program.transport.ServerSend(rooms[i].hostId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
|
|
||||||
_sendBuffers.Return(sendJoinBuffer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it got to here, then the server was not found, or full. Tell the client.
|
|
||||||
int pos = 0;
|
|
||||||
byte[] sendBuffer = _sendBuffers.Rent(1);
|
|
||||||
|
|
||||||
sendBuffer.WriteByte(ref pos, (byte)OpCodes.ServerLeft);
|
|
||||||
|
|
||||||
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendBuffer, 0, pos));
|
|
||||||
_sendBuffers.Return(sendBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreateRoom(int clientId, int maxPlayers, string serverName, bool isPublic, string serverData, bool useDirectConnect, string hostLocalIP, bool useNatPunch, int port)
|
|
||||||
{
|
|
||||||
LeaveRoom(clientId);
|
|
||||||
Program.instance.NATConnections.TryGetValue(clientId, out IPEndPoint hostIP);
|
|
||||||
|
|
||||||
Room room = new Room
|
|
||||||
{
|
|
||||||
hostId = clientId,
|
|
||||||
maxPlayers = maxPlayers,
|
|
||||||
serverName = serverName,
|
|
||||||
isPublic = isPublic,
|
|
||||||
serverData = serverData,
|
|
||||||
clients = new List<int>(),
|
|
||||||
|
|
||||||
// hard coded for now REMEMBER TO UN-HARDCODE RETARD
|
|
||||||
// this is needed for load balancer to know which server this room
|
|
||||||
// belongs to
|
|
||||||
relayInfo = new RelayAddress { Address = Program.publicIP, Port = 7777, EndpointPort = Program.conf.EndpointPort },
|
|
||||||
|
|
||||||
serverId = GetRandomServerID(),
|
|
||||||
hostIP = hostIP,
|
|
||||||
hostLocalIP = hostLocalIP,
|
|
||||||
supportsDirectConnect = hostIP == null ? false : useDirectConnect,
|
|
||||||
port = port,
|
|
||||||
useNATPunch = useNatPunch
|
|
||||||
};
|
|
||||||
|
|
||||||
rooms.Add(room);
|
|
||||||
|
|
||||||
int pos = 0;
|
|
||||||
byte[] sendBuffer = _sendBuffers.Rent(5);
|
|
||||||
|
|
||||||
sendBuffer.WriteByte(ref pos, (byte)OpCodes.RoomCreated);
|
|
||||||
sendBuffer.WriteInt(ref pos, clientId);
|
|
||||||
|
|
||||||
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendBuffer, 0, pos));
|
|
||||||
_sendBuffers.Return(sendBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LeaveRoom(int clientId, int requiredHostId = -1)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < rooms.Count; i++)
|
|
||||||
{
|
|
||||||
if(rooms[i].hostId == clientId)
|
|
||||||
{
|
|
||||||
int pos = 0;
|
|
||||||
byte[] sendBuffer = _sendBuffers.Rent(1);
|
|
||||||
sendBuffer.WriteByte(ref pos, (byte)OpCodes.ServerLeft);
|
|
||||||
|
|
||||||
for(int x = 0; x < rooms[i].clients.Count; x++)
|
|
||||||
Program.transport.ServerSend(rooms[i].clients[x], 0, new ArraySegment<byte>(sendBuffer, 0, pos));
|
|
||||||
|
|
||||||
_sendBuffers.Return(sendBuffer);
|
|
||||||
rooms[i].clients.Clear();
|
|
||||||
rooms.RemoveAt(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (requiredHostId >= 0 && rooms[i].hostId != requiredHostId)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(rooms[i].clients.RemoveAll(x => x == clientId) > 0)
|
|
||||||
{
|
|
||||||
int pos = 0;
|
|
||||||
byte[] sendBuffer = _sendBuffers.Rent(5);
|
|
||||||
|
|
||||||
sendBuffer.WriteByte(ref pos, (byte)OpCodes.PlayerDisconnected);
|
|
||||||
sendBuffer.WriteInt(ref pos, clientId);
|
|
||||||
|
|
||||||
Program.transport.ServerSend(rooms[i].hostId, 0, new ArraySegment<byte>(sendBuffer, 0, pos));
|
|
||||||
_sendBuffers.Return(sendBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SendClientID(int clientId)
|
|
||||||
{
|
|
||||||
int pos = 0;
|
|
||||||
byte[] sendBuffer = _sendBuffers.Rent(5);
|
|
||||||
|
|
||||||
sendBuffer.WriteByte(ref pos, (byte)OpCodes.GetID);
|
|
||||||
sendBuffer.WriteInt(ref pos, clientId);
|
|
||||||
|
|
||||||
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendBuffer, 0, pos));
|
|
||||||
_sendBuffers.Return(sendBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetRandomServerID()
|
|
||||||
{
|
|
||||||
Random rand = new Random();
|
|
||||||
int temp = rand.Next(int.MinValue, int.MaxValue);
|
|
||||||
|
|
||||||
while (DoesServerIdExist(temp))
|
|
||||||
temp = rand.Next(int.MinValue, int.MaxValue);
|
|
||||||
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DoesServerIdExist(int id)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < rooms.Count; i++)
|
|
||||||
if (rooms[i].serverId == id)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum OpCodes
|
|
||||||
{
|
|
||||||
Default = 0, RequestID = 1, JoinServer = 2, SendData = 3, GetID = 4, ServerJoined = 5, GetData = 6, CreateRoom = 7, ServerLeft = 8, PlayerDisconnected = 9, RoomCreated = 10,
|
|
||||||
LeaveRoom = 11, KickPlayer = 12, AuthenticationRequest = 13, AuthenticationResponse = 14, Authenticated = 17, UpdateRoomData = 18, ServerConnectionData = 19, RequestNATConnection = 20,
|
|
||||||
DirectConnectIP = 21
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
|
|
||||||
|
namespace LightReflectiveMirror
|
||||||
|
{
|
||||||
|
public partial class RelayHandler
|
||||||
|
{
|
||||||
|
|
||||||
|
public RelayHandler(int maxPacketSize)
|
||||||
|
{
|
||||||
|
this._maxPacketSize = maxPacketSize;
|
||||||
|
_sendBuffers = ArrayPool<byte>.Create(maxPacketSize, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is called when a client wants to send data to another player.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientId">The ID of the client who is sending the data</param>
|
||||||
|
/// <param name="clientData">The binary data the client is sending</param>
|
||||||
|
/// <param name="channel">The channel the client is sending this data on</param>
|
||||||
|
/// <param name="sendTo">Who to relay the data to</param>
|
||||||
|
void ProcessData(int clientId, byte[] clientData, int channel, int sendTo = -1)
|
||||||
|
{
|
||||||
|
Room playersRoom = GetRoomForPlayer(clientId);
|
||||||
|
|
||||||
|
if(playersRoom != null)
|
||||||
|
{
|
||||||
|
Room room = playersRoom;
|
||||||
|
|
||||||
|
if(room.hostId == clientId)
|
||||||
|
{
|
||||||
|
if (room.clients.Contains(sendTo))
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
byte[] sendBuffer = _sendBuffers.Rent(_maxPacketSize);
|
||||||
|
|
||||||
|
sendBuffer.WriteByte(ref pos, (byte)OpCodes.GetData);
|
||||||
|
sendBuffer.WriteBytes(ref pos, clientData);
|
||||||
|
|
||||||
|
Program.transport.ServerSend(sendTo, channel, new ArraySegment<byte>(sendBuffer, 0, pos));
|
||||||
|
_sendBuffers.Return(sendBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We are not the host, so send the data to the host.
|
||||||
|
int pos = 0;
|
||||||
|
byte[] sendBuffer = _sendBuffers.Rent(_maxPacketSize);
|
||||||
|
|
||||||
|
sendBuffer.WriteByte(ref pos, (byte)OpCodes.GetData);
|
||||||
|
sendBuffer.WriteBytes(ref pos, clientData);
|
||||||
|
sendBuffer.WriteInt(ref pos, clientId);
|
||||||
|
|
||||||
|
Program.transport.ServerSend(room.hostId, channel, new ArraySegment<byte>(sendBuffer, 0, pos));
|
||||||
|
_sendBuffers.Return(sendBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when a client wants to request their own ID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientId">The client requesting their ID</param>
|
||||||
|
void SendClientID(int clientId)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
byte[] sendBuffer = _sendBuffers.Rent(5);
|
||||||
|
|
||||||
|
sendBuffer.WriteByte(ref pos, (byte)OpCodes.GetID);
|
||||||
|
sendBuffer.WriteInt(ref pos, clientId);
|
||||||
|
|
||||||
|
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendBuffer, 0, pos));
|
||||||
|
_sendBuffers.Return(sendBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a random server ID.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
int GetRandomServerID()
|
||||||
|
{
|
||||||
|
Random rand = new Random();
|
||||||
|
int temp = rand.Next(int.MinValue, int.MaxValue);
|
||||||
|
|
||||||
|
while (DoesServerIdExist(temp))
|
||||||
|
temp = rand.Next(int.MinValue, int.MaxValue);
|
||||||
|
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a server id already is in use.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The ID to check for</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool DoesServerIdExist(int id)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < rooms.Count; i++)
|
||||||
|
if (rooms[i].serverId == id)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum OpCodes
|
||||||
|
{
|
||||||
|
Default = 0, RequestID = 1, JoinServer = 2, SendData = 3, GetID = 4, ServerJoined = 5, GetData = 6, CreateRoom = 7, ServerLeft = 8, PlayerDisconnected = 9, RoomCreated = 10,
|
||||||
|
LeaveRoom = 11, KickPlayer = 12, AuthenticationRequest = 13, AuthenticationResponse = 14, Authenticated = 17, UpdateRoomData = 18, ServerConnectionData = 19, RequestNATConnection = 20,
|
||||||
|
DirectConnectIP = 21
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LightReflectiveMirror
|
||||||
|
{
|
||||||
|
public partial class RelayHandler
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when a client connects to this LRM server.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientId">The ID of the client who connected.</param>
|
||||||
|
public void ClientConnected(int clientId)
|
||||||
|
{
|
||||||
|
_pendingAuthentication.Add(clientId);
|
||||||
|
var buffer = _sendBuffers.Rent(1);
|
||||||
|
int pos = 0;
|
||||||
|
buffer.WriteByte(ref pos, (byte)OpCodes.AuthenticationRequest);
|
||||||
|
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(buffer, 0, pos));
|
||||||
|
_sendBuffers.Return(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the processing of data from a client.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientId">The client who sent the data</param>
|
||||||
|
/// <param name="segmentData">The binary data</param>
|
||||||
|
/// <param name="channel">The channel the client sent the data on</param>
|
||||||
|
public void HandleMessage(int clientId, ArraySegment<byte> segmentData, int channel)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = segmentData.Array;
|
||||||
|
int pos = segmentData.Offset;
|
||||||
|
|
||||||
|
OpCodes opcode = (OpCodes)data.ReadByte(ref pos);
|
||||||
|
|
||||||
|
if (_pendingAuthentication.Contains(clientId))
|
||||||
|
{
|
||||||
|
if (opcode == OpCodes.AuthenticationResponse)
|
||||||
|
{
|
||||||
|
string authResponse = data.ReadString(ref pos);
|
||||||
|
if (authResponse == Program.conf.AuthenticationKey)
|
||||||
|
{
|
||||||
|
_pendingAuthentication.Remove(clientId);
|
||||||
|
int writePos = 0;
|
||||||
|
var sendBuffer = _sendBuffers.Rent(1);
|
||||||
|
sendBuffer.WriteByte(ref writePos, (byte)OpCodes.Authenticated);
|
||||||
|
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendBuffer, 0, writePos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opcode)
|
||||||
|
{
|
||||||
|
case OpCodes.CreateRoom:
|
||||||
|
CreateRoom(clientId, data.ReadInt(ref pos), data.ReadString(ref pos), data.ReadBool(ref pos), data.ReadString(ref pos), data.ReadBool(ref pos), data.ReadString(ref pos), data.ReadBool(ref pos), data.ReadInt(ref pos));
|
||||||
|
break;
|
||||||
|
case OpCodes.RequestID:
|
||||||
|
SendClientID(clientId);
|
||||||
|
break;
|
||||||
|
case OpCodes.LeaveRoom:
|
||||||
|
LeaveRoom(clientId);
|
||||||
|
break;
|
||||||
|
case OpCodes.JoinServer:
|
||||||
|
JoinRoom(clientId, data.ReadInt(ref pos), data.ReadBool(ref pos), data.ReadString(ref pos));
|
||||||
|
break;
|
||||||
|
case OpCodes.KickPlayer:
|
||||||
|
LeaveRoom(data.ReadInt(ref pos), clientId);
|
||||||
|
break;
|
||||||
|
case OpCodes.SendData:
|
||||||
|
ProcessData(clientId, data.ReadBytes(ref pos), channel, data.ReadInt(ref pos));
|
||||||
|
break;
|
||||||
|
case OpCodes.UpdateRoomData:
|
||||||
|
var plyRoom = GetRoomForPlayer(clientId);
|
||||||
|
|
||||||
|
if (plyRoom == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool newName = data.ReadBool(ref pos);
|
||||||
|
if (newName)
|
||||||
|
plyRoom.serverName = data.ReadString(ref pos);
|
||||||
|
|
||||||
|
bool newData = data.ReadBool(ref pos);
|
||||||
|
if (newData)
|
||||||
|
plyRoom.serverData = data.ReadString(ref pos);
|
||||||
|
|
||||||
|
bool newPublicStatus = data.ReadBool(ref pos);
|
||||||
|
if (newPublicStatus)
|
||||||
|
plyRoom.isPublic = data.ReadBool(ref pos);
|
||||||
|
|
||||||
|
bool newPlayerCap = data.ReadBool(ref pos);
|
||||||
|
if (newPlayerCap)
|
||||||
|
plyRoom.maxPlayers = data.ReadInt(ref pos);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Do Nothing. Client probably sent some invalid data.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when a client disconnects from the relay.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientId">The ID of the client who disconnected</param>
|
||||||
|
public void HandleDisconnect(int clientId) => LeaveRoom(clientId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,199 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace LightReflectiveMirror
|
||||||
|
{
|
||||||
|
public partial class RelayHandler
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the current room the client is in, null if client is not in a room.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientId">The client we are getting the room for</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Room GetRoomForPlayer(int clientId)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < rooms.Count; i++)
|
||||||
|
{
|
||||||
|
if (rooms[i].hostId == clientId)
|
||||||
|
return rooms[i];
|
||||||
|
|
||||||
|
if (rooms[i].clients.Contains(clientId))
|
||||||
|
return rooms[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to join a room for a client.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientId">The client requesting to join the room</param>
|
||||||
|
/// <param name="serverId">The server ID of the room</param>
|
||||||
|
/// <param name="canDirectConnect">If the client is capable of a direct connection</param>
|
||||||
|
/// <param name="localIP">The local IP of the client joining</param>
|
||||||
|
void JoinRoom(int clientId, int serverId, bool canDirectConnect, string localIP)
|
||||||
|
{
|
||||||
|
LeaveRoom(clientId);
|
||||||
|
|
||||||
|
for (int i = 0; i < rooms.Count; i++)
|
||||||
|
{
|
||||||
|
if (rooms[i].serverId == serverId)
|
||||||
|
{
|
||||||
|
if (rooms[i].clients.Count < rooms[i].maxPlayers)
|
||||||
|
{
|
||||||
|
rooms[i].clients.Add(clientId);
|
||||||
|
|
||||||
|
int sendJoinPos = 0;
|
||||||
|
byte[] sendJoinBuffer = _sendBuffers.Rent(500);
|
||||||
|
|
||||||
|
if (canDirectConnect && Program.instance.NATConnections.ContainsKey(clientId))
|
||||||
|
{
|
||||||
|
sendJoinBuffer.WriteByte(ref sendJoinPos, (byte)OpCodes.DirectConnectIP);
|
||||||
|
|
||||||
|
if (Program.instance.NATConnections[clientId].Address.Equals(rooms[i].hostIP.Address))
|
||||||
|
sendJoinBuffer.WriteString(ref sendJoinPos, rooms[i].hostLocalIP == localIP ? "127.0.0.1" : rooms[i].hostLocalIP);
|
||||||
|
else
|
||||||
|
sendJoinBuffer.WriteString(ref sendJoinPos, rooms[i].hostIP.Address.ToString());
|
||||||
|
|
||||||
|
sendJoinBuffer.WriteInt(ref sendJoinPos, rooms[i].useNATPunch ? rooms[i].hostIP.Port : rooms[i].port);
|
||||||
|
sendJoinBuffer.WriteBool(ref sendJoinPos, rooms[i].useNATPunch);
|
||||||
|
|
||||||
|
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
|
||||||
|
|
||||||
|
if (rooms[i].useNATPunch)
|
||||||
|
{
|
||||||
|
sendJoinPos = 0;
|
||||||
|
sendJoinBuffer.WriteByte(ref sendJoinPos, (byte)OpCodes.DirectConnectIP);
|
||||||
|
Console.WriteLine(Program.instance.NATConnections[clientId].Address.ToString());
|
||||||
|
sendJoinBuffer.WriteString(ref sendJoinPos, Program.instance.NATConnections[clientId].Address.ToString());
|
||||||
|
sendJoinBuffer.WriteInt(ref sendJoinPos, Program.instance.NATConnections[clientId].Port);
|
||||||
|
sendJoinBuffer.WriteBool(ref sendJoinPos, true);
|
||||||
|
|
||||||
|
Program.transport.ServerSend(rooms[i].hostId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
_sendBuffers.Return(sendJoinBuffer);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
sendJoinBuffer.WriteByte(ref sendJoinPos, (byte)OpCodes.ServerJoined);
|
||||||
|
sendJoinBuffer.WriteInt(ref sendJoinPos, clientId);
|
||||||
|
|
||||||
|
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
|
||||||
|
Program.transport.ServerSend(rooms[i].hostId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
|
||||||
|
_sendBuffers.Return(sendJoinBuffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it got to here, then the server was not found, or full. Tell the client.
|
||||||
|
int pos = 0;
|
||||||
|
byte[] sendBuffer = _sendBuffers.Rent(1);
|
||||||
|
|
||||||
|
sendBuffer.WriteByte(ref pos, (byte)OpCodes.ServerLeft);
|
||||||
|
|
||||||
|
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendBuffer, 0, pos));
|
||||||
|
_sendBuffers.Return(sendBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a room on the LRM node.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientId">The client requesting to create a room</param>
|
||||||
|
/// <param name="maxPlayers">The maximum amount of players for this room</param>
|
||||||
|
/// <param name="serverName">The name for the server</param>
|
||||||
|
/// <param name="isPublic">Weather or not the server should show up on the server list</param>
|
||||||
|
/// <param name="serverData">Extra data the host can include</param>
|
||||||
|
/// <param name="useDirectConnect">Weather or not, the host is capable of doing direct connections</param>
|
||||||
|
/// <param name="hostLocalIP">The hosts local IP</param>
|
||||||
|
/// <param name="useNatPunch">Weather or not, the host is supporting NAT Punch</param>
|
||||||
|
/// <param name="port">The port of the direct connect transport on the host</param>
|
||||||
|
void CreateRoom(int clientId, int maxPlayers, string serverName, bool isPublic, string serverData, bool useDirectConnect, string hostLocalIP, bool useNatPunch, int port)
|
||||||
|
{
|
||||||
|
LeaveRoom(clientId);
|
||||||
|
Program.instance.NATConnections.TryGetValue(clientId, out IPEndPoint hostIP);
|
||||||
|
|
||||||
|
Room room = new Room
|
||||||
|
{
|
||||||
|
hostId = clientId,
|
||||||
|
maxPlayers = maxPlayers,
|
||||||
|
serverName = serverName,
|
||||||
|
isPublic = isPublic,
|
||||||
|
serverData = serverData,
|
||||||
|
clients = new List<int>(),
|
||||||
|
|
||||||
|
// hard coded for now REMEMBER TO UN-HARDCODE RETARD
|
||||||
|
// this is needed for load balancer to know which server this room
|
||||||
|
// belongs to
|
||||||
|
relayInfo = new RelayAddress { Address = Program.publicIP, Port = 7777, EndpointPort = Program.conf.EndpointPort },
|
||||||
|
|
||||||
|
serverId = GetRandomServerID(),
|
||||||
|
hostIP = hostIP,
|
||||||
|
hostLocalIP = hostLocalIP,
|
||||||
|
supportsDirectConnect = hostIP == null ? false : useDirectConnect,
|
||||||
|
port = port,
|
||||||
|
useNATPunch = useNatPunch
|
||||||
|
};
|
||||||
|
|
||||||
|
rooms.Add(room);
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
byte[] sendBuffer = _sendBuffers.Rent(5);
|
||||||
|
|
||||||
|
sendBuffer.WriteByte(ref pos, (byte)OpCodes.RoomCreated);
|
||||||
|
sendBuffer.WriteInt(ref pos, clientId);
|
||||||
|
|
||||||
|
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendBuffer, 0, pos));
|
||||||
|
_sendBuffers.Return(sendBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Makes the client leave their room.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientId">The client of which to remove from their room</param>
|
||||||
|
/// <param name="requiredHostId">The ID of the client who kicked the client. -1 if the client left on their own terms</param>
|
||||||
|
void LeaveRoom(int clientId, int requiredHostId = -1)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < rooms.Count; i++)
|
||||||
|
{
|
||||||
|
if (rooms[i].hostId == clientId)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
byte[] sendBuffer = _sendBuffers.Rent(1);
|
||||||
|
sendBuffer.WriteByte(ref pos, (byte)OpCodes.ServerLeft);
|
||||||
|
|
||||||
|
for (int x = 0; x < rooms[i].clients.Count; x++)
|
||||||
|
Program.transport.ServerSend(rooms[i].clients[x], 0, new ArraySegment<byte>(sendBuffer, 0, pos));
|
||||||
|
|
||||||
|
_sendBuffers.Return(sendBuffer);
|
||||||
|
rooms[i].clients.Clear();
|
||||||
|
rooms.RemoveAt(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (requiredHostId >= 0 && rooms[i].hostId != requiredHostId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (rooms[i].clients.RemoveAll(x => x == clientId) > 0)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
byte[] sendBuffer = _sendBuffers.Rent(5);
|
||||||
|
|
||||||
|
sendBuffer.WriteByte(ref pos, (byte)OpCodes.PlayerDisconnected);
|
||||||
|
sendBuffer.WriteInt(ref pos, clientId);
|
||||||
|
|
||||||
|
Program.transport.ServerSend(rooms[i].hostId, 0, new ArraySegment<byte>(sendBuffer, 0, pos));
|
||||||
|
_sendBuffers.Return(sendBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System.Buffers;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace LightReflectiveMirror
|
||||||
|
{
|
||||||
|
public partial class RelayHandler
|
||||||
|
{
|
||||||
|
public List<Room> rooms = new List<Room>();
|
||||||
|
private List<int> _pendingAuthentication = new List<int>();
|
||||||
|
private ArrayPool<byte> _sendBuffers;
|
||||||
|
private int _maxPacketSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue