using Newtonsoft.Json; using SanAndreasUnity.Utilities; using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Threading.Tasks; using UnityEngine; namespace SanAndreasUnity.Net { public class MasterServerClient : MonoBehaviour { private string _masterServerUrl; private ServerInfo _serverInfo; private bool _updating; public static MasterServerClient Instance { get; private set; } private HttpClient _client; private const int RegisterInterval = 20; public bool IsServerRegistrationEnabled { get; set; } = true; private void Awake() { Instance = this; } private void Start() { _client = new HttpClient(); _client.Timeout = System.TimeSpan.FromSeconds(7); _masterServerUrl = Config.Get("master_server_url"); if (string.IsNullOrWhiteSpace(_masterServerUrl)) Debug.LogError("Url of master server not defined in config"); NetManager.Instance.onServerStatusChanged += OnServerStatusChange; } private async void OnServerStatusChange() { if (!NetStatus.IsServer) return; if (string.IsNullOrWhiteSpace(_masterServerUrl)) return; if (!IsServerRegistrationEnabled) return; _serverInfo = GetCurrentServerInfo(); await RegisterServer(); } private static ServerInfo GetCurrentServerInfo() { return new ServerInfo { Name = Config.Get("server_name"), Port = NetManager.listenPortNumber, NumPlayersOnline = NetManager.numConnections, MaxPlayers = NetManager.maxNumPlayers, Map = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name, Version = Application.version, }; } private async Task RegisterServer() { await SendRequestToRegister(); _updating = true; Invoke(nameof(UpdateServer), RegisterInterval); } private async Task UpdateServer() { while (_updating) { _serverInfo = GetCurrentServerInfo(); await SendRequestToRegister(); await Task.Delay(RegisterInterval * 1000); } } private async Task SendRequestToRegister() { var response = await _client.PostAsync(_masterServerUrl + "/register", new StringContent(JsonConvert.SerializeObject(_serverInfo), Encoding.UTF8, "application/json")); if (!response.IsSuccessStatusCode) { string str = await response.Content.ReadAsStringAsync(); Debug.LogError($"Master server returned error while trying to register: {str}"); } } private async Task UnregisterServer() { _updating = false; if (null == _serverInfo) return; if (string.IsNullOrWhiteSpace(_masterServerUrl)) return; await _client.PostAsync(_masterServerUrl + "/unregister", new StringContent(JsonConvert.SerializeObject(_serverInfo), Encoding.UTF8, "application/json")); } public async Task> GetAllServers() { if (string.IsNullOrWhiteSpace(_masterServerUrl)) return new List(); return JsonConvert.DeserializeObject>(await _client.GetStringAsync(_masterServerUrl)); } public async void OnDestroy() { await UnregisterServer(); } } public class ServerInfo { public string Version { get; set; } public string Name { get; set; } public int NumPlayersOnline { get; set; } public string IP { get; set; } public int Port { get; set; } public int MaxPlayers { get; set; } public string Map { get; set; } } }