199 lines
8.8 KiB
C#
199 lines
8.8 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|