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 { 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.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.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(); } } }