monopoly/Assets/Mirror/Cloud/ListServer/ListServerServerApi.cs
2020-11-30 08:12:07 +00:00

220 lines
6.5 KiB
C#

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
namespace Mirror.Cloud.ListServerService
{
public sealed class ListServerServerApi : ListServerBaseApi, IListServerServerApi
{
const int PingInterval = 20;
const int MaxPingFails = 15;
ServerJson currentServer;
string serverId;
Coroutine _pingCoroutine;
/// <summary>
/// If the server has already been added
/// </summary>
bool added;
/// <summary>
/// if a request is currently sending
/// </summary>
bool sending;
/// <summary>
/// If an update request was recently sent
/// </summary>
bool skipNextPing;
/// <summary>
/// How many failed pings in a row
/// </summary>
int pingFails = 0;
public bool ServerInList => added;
public ListServerServerApi(ICoroutineRunner runner, IRequestCreator requestCreator) : base(runner, requestCreator)
{
}
public void Shutdown()
{
stopPingCoroutine();
if (added)
{
removeServerWithoutCoroutine();
}
added = false;
}
public void AddServer(ServerJson server)
{
if (added) { Logger.LogWarning("AddServer called when server was already adding or added"); return; }
bool valid = server.Validate();
if (!valid) { return; }
runner.StartCoroutine(addServer(server));
}
public void UpdateServer(int newPlayerCount)
{
if (!added) { Logger.LogWarning("UpdateServer called when before server was added"); return; }
currentServer.playerCount = newPlayerCount;
UpdateServer(currentServer);
}
public void UpdateServer(ServerJson server)
{
// TODO, use PartialServerJson as Arg Instead
if (!added) { Logger.LogWarning("UpdateServer called when before server was added"); return; }
PartialServerJson partialServer = new PartialServerJson
{
displayName = server.displayName,
playerCount = server.playerCount,
maxPlayerCount = server.maxPlayerCount,
customData = server.customData,
};
partialServer.Validate();
runner.StartCoroutine(updateServer(partialServer));
}
public void RemoveServer()
{
if (!added) { return; }
if (string.IsNullOrEmpty(serverId))
{
Logger.LogWarning("Can not remove server because serverId was empty");
return;
}
stopPingCoroutine();
runner.StartCoroutine(removeServer());
}
void stopPingCoroutine()
{
if (_pingCoroutine != null)
{
runner.StopCoroutine(_pingCoroutine);
_pingCoroutine = null;
}
}
IEnumerator addServer(ServerJson server)
{
added = true;
sending = true;
currentServer = server;
UnityWebRequest request = requestCreator.Post("servers", currentServer);
yield return requestCreator.SendRequestEnumerator(request, onSuccess, onFail);
sending = false;
void onSuccess(string responseBody)
{
CreatedIdJson created = JsonUtility.FromJson<CreatedIdJson>(responseBody);
serverId = created.id;
// Start ping to keep server alive
_pingCoroutine = runner.StartCoroutine(ping());
}
void onFail(string responseBody)
{
added = false;
}
}
IEnumerator updateServer(PartialServerJson server)
{
// wait to not be sending
while (sending)
{
yield return new WaitForSeconds(1);
}
// We need to check added incase Update is called soon after Add, and add failed
if (!added) { Logger.LogWarning("UpdateServer called when before server was added"); yield break; }
sending = true;
UnityWebRequest request = requestCreator.Patch("servers/" + serverId, server);
yield return requestCreator.SendRequestEnumerator(request, onSuccess);
sending = false;
void onSuccess(string responseBody)
{
skipNextPing = true;
if (_pingCoroutine == null)
{
_pingCoroutine = runner.StartCoroutine(ping());
}
}
}
/// <summary>
/// Keeps server alive in database
/// </summary>
/// <returns></returns>
IEnumerator ping()
{
while (pingFails <= MaxPingFails)
{
yield return new WaitForSeconds(PingInterval);
if (skipNextPing)
{
skipNextPing = false;
continue;
}
sending = true;
UnityWebRequest request = requestCreator.Patch("servers/" + serverId, new EmptyJson());
yield return requestCreator.SendRequestEnumerator(request, onSuccess, onFail);
sending = false;
}
Logger.LogWarning("Max ping fails reached, stoping to ping server");
_pingCoroutine = null;
void onSuccess(string responseBody)
{
pingFails = 0;
}
void onFail(string responseBody)
{
pingFails++;
}
}
IEnumerator removeServer()
{
sending = true;
UnityWebRequest request = requestCreator.Delete("servers/" + serverId);
yield return requestCreator.SendRequestEnumerator(request);
sending = false;
added = false;
}
void removeServerWithoutCoroutine()
{
if (string.IsNullOrEmpty(serverId))
{
Logger.LogWarning("Can not remove server becuase serverId was empty");
return;
}
UnityWebRequest request = requestCreator.Delete("servers/" + serverId);
UnityWebRequestAsyncOperation operation = request.SendWebRequest();
operation.completed += (op) =>
{
Logger.LogResponse(request);
};
}
}
}