using System;
using System.Collections.Generic;
using System.Linq;
namespace Mirror.Cloud.ListServerService
{
[Serializable]
public struct ServerCollectionJson : ICanBeJson
{
public ServerJson[] servers;
}
[Serializable]
public struct ServerJson : ICanBeJson
{
public string protocol;
public int port;
public int playerCount;
public int maxPlayerCount;
///
/// optional
///
public string displayName;
///
/// Uri string of the ip and port of the server.
/// The ip is calculated by the request to the API
/// This is returns from the api, any incoming address fields will be ignored
///
public string address;
///
/// Can be used to set custom uri
/// optional
///
public string customAddress;
///
/// Array of custom data, use SetCustomData to set values
/// optional
///
public KeyValue[] customData;
///
/// Uri from address field
///
///
public Uri GetServerUri() => new Uri(address);
///
/// Uri from customAddress field
///
///
public Uri GetCustomUri() => new Uri(customAddress);
///
/// Updates the customData array
///
///
public void SetCustomData(Dictionary data)
{
if (data == null)
{
customData = null;
}
else
{
customData = data.ToKeyValueArray();
CustomDataHelper.ValidateCustomData(customData);
}
}
public bool Validate()
{
CustomDataHelper.ValidateCustomData(customData);
if (string.IsNullOrEmpty(protocol))
{
Logger.LogError("ServerJson should not have empty protocol");
return false;
}
if (port == 0)
{
Logger.LogError("ServerJson should not have port equal 0");
return false;
}
if (maxPlayerCount == 0)
{
Logger.LogError("ServerJson should not have maxPlayerCount equal 0");
return false;
}
return true;
}
}
[Serializable]
public struct PartialServerJson : ICanBeJson
{
///
/// optional
///
public int playerCount;
///
/// optional
///
public int maxPlayerCount;
///
/// optional
///
public string displayName;
///
/// Array of custom data, use SetCustomData to set values
/// optional
///
public KeyValue[] customData;
public void SetCustomData(Dictionary data)
{
if (data == null)
{
customData = null;
}
else
{
customData = data.ToKeyValueArray();
CustomDataHelper.ValidateCustomData(customData);
}
}
public void Validate()
{
CustomDataHelper.ValidateCustomData(customData);
}
}
public static class CustomDataHelper
{
const int MaxCustomData = 16;
public static Dictionary ToDictionary(this KeyValue[] keyValues)
{
return keyValues.ToDictionary(x => x.key, x => x.value);
}
public static KeyValue[] ToKeyValueArray(this Dictionary dictionary)
{
return dictionary.Select(kvp => new KeyValue(kvp.Key, kvp.Value)).ToArray();
}
public static void ValidateCustomData(KeyValue[] customData)
{
if (customData == null)
{
return;
}
if (customData.Length > MaxCustomData)
{
Logger.LogError($"There can only be {MaxCustomData} custom data but there was {customData.Length} values given");
Array.Resize(ref customData, MaxCustomData);
}
foreach (KeyValue item in customData)
{
item.Validate();
}
}
}
[Serializable]
public struct KeyValue
{
const int MaxKeySize = 32;
const int MaxValueSize = 256;
public string key;
public string value;
public KeyValue(string key, string value)
{
this.key = key;
this.value = value;
}
public void Validate()
{
if (key.Length > MaxKeySize)
{
Logger.LogError($"Custom Data must have key with length less than {MaxKeySize}");
key = key.Substring(0, MaxKeySize);
}
if (value.Length > MaxValueSize)
{
Logger.LogError($"Custom Data must have value with length less than {MaxValueSize}");
value = value.Substring(0, MaxValueSize);
}
}
}
}