SRMP-Public/SRMP/Networking/NetworkMasterServer.cs
2023-05-29 22:23:11 +02:00

209 lines
7.6 KiB
C#

using Lidgren.Network;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace SRMultiplayer.Networking
{
public class NetworkMasterServer : SRSingleton<NetworkMasterServer>
{
public const string MasterServerIP = "srmp.saty.dev";
public const int MasterServerPort = 7777;
public ConnectionStatus Status;
public long UniqueIdentifier { get { return m_Client.UniqueIdentifier; } }
private NetClient m_Client;
private float m_ReconnectTime = 30;
public enum ConnectionStatus
{
Disconnected,
Connecting,
Connected
}
public enum MessageType
{
CreateServer,
DeleteServer,
JoinServer,
UpdateServer,
UpdateName,
CreatePublicServer,
ServerList
}
private void Start()
{
TryConnect();
}
private void TryConnect()
{
if (Status != ConnectionStatus.Disconnected) return;
Status = ConnectionStatus.Connecting;
NetPeerConfiguration config = new NetPeerConfiguration("srmp-master-1");
config.EnableMessageType(NetIncomingMessageType.NatIntroductionSuccess);
m_Client = new NetClient(config);
m_Client.Start();
NetOutgoingMessage hail = CreateMessage();
hail.Write(Globals.Username);
hail.Write(Globals.Version);
m_Client.Connect(MasterServerIP, MasterServerPort, hail);
}
private void Update()
{
if (m_Client == null || m_Client.ConnectionStatus == NetConnectionStatus.Disconnected)
{
m_ReconnectTime -= Time.deltaTime;
if (m_ReconnectTime <= 0)
{
m_ReconnectTime = 30;
TryConnect();
}
}
NetIncomingMessage im;
while ((im = m_Client?.ReadMessage()) != null)
{
switch (im.MessageType)
{
case NetIncomingMessageType.DebugMessage:
case NetIncomingMessageType.ErrorMessage:
case NetIncomingMessageType.WarningMessage:
case NetIncomingMessageType.VerboseDebugMessage:
{
string text = im.ReadString();
//Debug.Log("[MasterServer] " + text);
}
break;
case NetIncomingMessageType.NatIntroductionSuccess:
{
string token = im.ReadString();
Debug.Log("[MasterServer] Nat introduction success to " + im.SenderEndPoint + " token is: " + token);
SRSingleton<NetworkClient>.Instance.Connect(im.SenderEndPoint, Globals.Username);
}
break;
case NetIncomingMessageType.StatusChanged:
{
NetConnectionStatus status = (NetConnectionStatus)im.ReadByte();
string reason = im.ReadString();
Debug.Log("[MasterServer] " + NetUtility.ToHexString(im.SenderConnection.RemoteUniqueIdentifier) + " " + status + ": " + reason);
if (status == NetConnectionStatus.Connected)
{
Status = ConnectionStatus.Connected;
}
else if (status == NetConnectionStatus.Disconnected)
{
Globals.ServerCode = "";
Status = ConnectionStatus.Disconnected;
m_ReconnectTime = 30;
}
}
break;
case NetIncomingMessageType.Data:
{
MessageType type = (MessageType)im.ReadByte();
if (type == MessageType.CreateServer)
{
Globals.ServerCode = im.ReadString();
}
else if (type == MessageType.JoinServer)
{
bool success = im.ReadBoolean();
if (success)
{
SRSingleton<NetworkClient>.Instance.Connect(im.ReadString(), im.ReadInt32(), Globals.Username);
}
else
{
MultiplayerUI.Instance.ConnectResponse(MultiplayerUI.ConnectError.InvalidServerCode);
}
}
}
break;
default:
Debug.Log("[MasterServer] " + "Unhandled type: " + im.MessageType + " " + im.LengthBytes + " bytes " + im.DeliveryMethod + "|" + im.SequenceChannel);
break;
}
m_Client.Recycle(im);
}
}
public void UpdateName(string name)
{
NetOutgoingMessage om = CreateMessage();
om.Write((byte)MessageType.UpdateName);
om.Write(name);
SendMessage(om);
}
public void JoinServer(string code)
{
NetOutgoingMessage regMsg = CreateMessage();
regMsg.Write((byte)MessageType.JoinServer);
IPAddress mask;
IPAddress adr = NetUtility.GetMyAddress(out mask);
regMsg.Write(UniqueIdentifier);
regMsg.Write(code);
regMsg.Write(new IPEndPoint(adr, NetworkClient.Instance.Port));
Debug.Log("Sending join msg to master server");
NetworkClient.Instance.SendUnconnected(regMsg, NetUtility.Resolve(MasterServerIP, MasterServerPort));
}
public void CreateServer(int port)
{
NetOutgoingMessage regMsg = CreateMessage();
regMsg.Write((byte)MessageType.CreateServer);
IPAddress mask;
IPAddress adr = NetUtility.GetMyAddress(out mask);
regMsg.Write(UniqueIdentifier);
regMsg.Write(port);
regMsg.Write(new IPEndPoint(adr, NetworkServer.Instance.Port));
Debug.Log("Sending create msg to master server");
NetworkServer.Instance.SendUnconnected(regMsg, NetUtility.Resolve(MasterServerIP, MasterServerPort));
}
public void UpdateServer(int players)
{
NetOutgoingMessage om = CreateMessage();
om.Write((byte)MessageType.UpdateServer);
om.Write(players);
SendMessage(om);
}
public void DeleteServer()
{
NetOutgoingMessage om = CreateMessage();
om.Write((byte)MessageType.DeleteServer);
SendMessage(om);
}
private void SendMessage(NetOutgoingMessage om)
{
if (m_Client == null || m_Client.ConnectionStatus != NetConnectionStatus.Connected) return;
m_Client.SendMessage(om, NetDeliveryMethod.ReliableOrdered);
}
private NetOutgoingMessage CreateMessage()
{
return m_Client?.CreateMessage();
}
}
}