mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
feature: Edgegap Plugin V2 (#3692)
* Edgegap Plugin V2 from https://github.com/dylanh724/edgegap-unity-plugin-v2/tree/feat/plugin-v2.2 * fix things * fix warnings * fix u2020 support * fix nre * fix logo hardcoded path * fix clipboard image hardcoded path and remove fonts * syntax * fix unity 2019/2020 breaking all editor UIs * fix NRE on first open due to old window * fix 2019 asserts * link to our documentation * disable warning * fix unity 2019 unsupported syntax error * Mirror.Hosting.asmdef: fix missing ref * fix: remove all fonts to avoid the errors * readme: two click hosting * readme * better * fix 2019 errors * fix U2020 async warning --------- Co-authored-by: mischa <16416509+vis2k@users.noreply.github.com>
This commit is contained in:
parent
608429c314
commit
67f32f2d90
3
Assets/Mirror/Hosting/Edgegap/Dependencies.meta
Normal file
3
Assets/Mirror/Hosting/Edgegap/Dependencies.meta
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 14024ce6d2e64d5ba58ab20409ac648f
|
||||||
|
timeCreated: 1701785018
|
704
Assets/Mirror/Hosting/Edgegap/Dependencies/HttpEncoder.cs
Normal file
704
Assets/Mirror/Hosting/Edgegap/Dependencies/HttpEncoder.cs
Normal file
@ -0,0 +1,704 @@
|
|||||||
|
// MIRROR CHANGE: drop in Codice.Utils HttpUtility subset to not depend on Unity's plastic scm package
|
||||||
|
// SOURCE: Unity Plastic SCM package
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Edgegap.Codice.Utils // MIRROR CHANGE: namespace Edgegap.* to not collide if anyone has Plastic SCM installed already
|
||||||
|
{
|
||||||
|
public class HttpEncoder
|
||||||
|
{
|
||||||
|
private static char[] hexChars = "0123456789abcdef".ToCharArray();
|
||||||
|
private static object entitiesLock = new object();
|
||||||
|
private static SortedDictionary<string, char> entities;
|
||||||
|
private static HttpEncoder defaultEncoder = new HttpEncoder();
|
||||||
|
private static HttpEncoder currentEncoder = HttpEncoder.defaultEncoder;
|
||||||
|
|
||||||
|
private static IDictionary<string, char> Entities
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (HttpEncoder.entitiesLock)
|
||||||
|
{
|
||||||
|
if (HttpEncoder.entities == null)
|
||||||
|
HttpEncoder.InitEntities();
|
||||||
|
return (IDictionary<string, char>) HttpEncoder.entities;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpEncoder Current
|
||||||
|
{
|
||||||
|
get => HttpEncoder.currentEncoder;
|
||||||
|
set => HttpEncoder.currentEncoder = value != null ? value : throw new ArgumentNullException(nameof (value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpEncoder Default => HttpEncoder.defaultEncoder;
|
||||||
|
|
||||||
|
protected internal virtual void HeaderNameValueEncode(
|
||||||
|
string headerName,
|
||||||
|
string headerValue,
|
||||||
|
out string encodedHeaderName,
|
||||||
|
out string encodedHeaderValue)
|
||||||
|
{
|
||||||
|
encodedHeaderName = !string.IsNullOrEmpty(headerName) ? HttpEncoder.EncodeHeaderString(headerName) : headerName;
|
||||||
|
if (string.IsNullOrEmpty(headerValue))
|
||||||
|
encodedHeaderValue = headerValue;
|
||||||
|
else
|
||||||
|
encodedHeaderValue = HttpEncoder.EncodeHeaderString(headerValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void StringBuilderAppend(string s, ref StringBuilder sb)
|
||||||
|
{
|
||||||
|
if (sb == null)
|
||||||
|
sb = new StringBuilder(s);
|
||||||
|
else
|
||||||
|
sb.Append(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string EncodeHeaderString(string input)
|
||||||
|
{
|
||||||
|
StringBuilder sb = (StringBuilder) null;
|
||||||
|
for (int index = 0; index < input.Length; ++index)
|
||||||
|
{
|
||||||
|
char ch = input[index];
|
||||||
|
if (ch < ' ' && ch != '\t' || ch == '\u007F')
|
||||||
|
HttpEncoder.StringBuilderAppend(string.Format("%{0:x2}", (object) (int) ch), ref sb);
|
||||||
|
}
|
||||||
|
return sb != null ? sb.ToString() : input;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected internal virtual void HtmlAttributeEncode(string value, TextWriter output)
|
||||||
|
{
|
||||||
|
if (output == null)
|
||||||
|
throw new ArgumentNullException(nameof (output));
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
return;
|
||||||
|
output.Write(HttpEncoder.HtmlAttributeEncode(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected internal virtual void HtmlDecode(string value, TextWriter output)
|
||||||
|
{
|
||||||
|
if (output == null)
|
||||||
|
throw new ArgumentNullException(nameof (output));
|
||||||
|
output.Write(HttpEncoder.HtmlDecode(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected internal virtual void HtmlEncode(string value, TextWriter output)
|
||||||
|
{
|
||||||
|
if (output == null)
|
||||||
|
throw new ArgumentNullException(nameof (output));
|
||||||
|
output.Write(HttpEncoder.HtmlEncode(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected internal virtual byte[] UrlEncode(byte[] bytes, int offset, int count) => HttpEncoder.UrlEncodeToBytes(bytes, offset, count);
|
||||||
|
|
||||||
|
protected internal virtual string UrlPathEncode(string value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
return value;
|
||||||
|
MemoryStream result = new MemoryStream();
|
||||||
|
int length = value.Length;
|
||||||
|
for (int index = 0; index < length; ++index)
|
||||||
|
HttpEncoder.UrlPathEncodeChar(value[index], (Stream) result);
|
||||||
|
return Encoding.ASCII.GetString(result.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static byte[] UrlEncodeToBytes(byte[] bytes, int offset, int count)
|
||||||
|
{
|
||||||
|
int num1 = bytes != null ? bytes.Length : throw new ArgumentNullException(nameof (bytes));
|
||||||
|
if (num1 == 0)
|
||||||
|
return new byte[0];
|
||||||
|
if (offset < 0 || offset >= num1)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof (offset));
|
||||||
|
if (count < 0 || count > num1 - offset)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof (count));
|
||||||
|
MemoryStream result = new MemoryStream(count);
|
||||||
|
int num2 = offset + count;
|
||||||
|
for (int index = offset; index < num2; ++index)
|
||||||
|
HttpEncoder.UrlEncodeChar((char) bytes[index], (Stream) result, false);
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string HtmlEncode(string s)
|
||||||
|
{
|
||||||
|
switch (s)
|
||||||
|
{
|
||||||
|
case "":
|
||||||
|
return string.Empty;
|
||||||
|
case null:
|
||||||
|
return (string) null;
|
||||||
|
default:
|
||||||
|
bool flag = false;
|
||||||
|
for (int index = 0; index < s.Length; ++index)
|
||||||
|
{
|
||||||
|
char ch = s[index];
|
||||||
|
if (ch == '&' || ch == '"' || ch == '<' || ch == '>' || ch > '\u009F' || ch == '\'')
|
||||||
|
{
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!flag)
|
||||||
|
return s;
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
int length = s.Length;
|
||||||
|
for (int index = 0; index < length; ++index)
|
||||||
|
{
|
||||||
|
char ch = s[index];
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case '"':
|
||||||
|
stringBuilder.Append(""");
|
||||||
|
break;
|
||||||
|
case '&':
|
||||||
|
stringBuilder.Append("&");
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
stringBuilder.Append("'");
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
stringBuilder.Append("<");
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
stringBuilder.Append(">");
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
stringBuilder.Append("<");
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
stringBuilder.Append(">");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (ch > '\u009F' && ch < 'Ā')
|
||||||
|
{
|
||||||
|
stringBuilder.Append("&#");
|
||||||
|
stringBuilder.Append(((int) ch).ToString((IFormatProvider) CultureInfo.InvariantCulture));
|
||||||
|
stringBuilder.Append(";");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stringBuilder.Append(ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stringBuilder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string HtmlAttributeEncode(string s)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(s))
|
||||||
|
return string.Empty;
|
||||||
|
bool flag = false;
|
||||||
|
for (int index = 0; index < s.Length; ++index)
|
||||||
|
{
|
||||||
|
char ch = s[index];
|
||||||
|
int num;
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case '"':
|
||||||
|
case '&':
|
||||||
|
case '<':
|
||||||
|
num = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
num = ch != '\'' ? 1 : 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (num == 0)
|
||||||
|
{
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!flag)
|
||||||
|
return s;
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
int length = s.Length;
|
||||||
|
for (int index = 0; index < length; ++index)
|
||||||
|
{
|
||||||
|
char ch = s[index];
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case '"':
|
||||||
|
stringBuilder.Append(""");
|
||||||
|
break;
|
||||||
|
case '&':
|
||||||
|
stringBuilder.Append("&");
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
stringBuilder.Append("'");
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
stringBuilder.Append("<");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
stringBuilder.Append(ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stringBuilder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string HtmlDecode(string s)
|
||||||
|
{
|
||||||
|
switch (s)
|
||||||
|
{
|
||||||
|
case "":
|
||||||
|
return string.Empty;
|
||||||
|
case null:
|
||||||
|
return (string) null;
|
||||||
|
default:
|
||||||
|
if (s.IndexOf('&') == -1)
|
||||||
|
return s;
|
||||||
|
StringBuilder stringBuilder1 = new StringBuilder();
|
||||||
|
StringBuilder stringBuilder2 = new StringBuilder();
|
||||||
|
StringBuilder stringBuilder3 = new StringBuilder();
|
||||||
|
int length = s.Length;
|
||||||
|
int num1 = 0;
|
||||||
|
int num2 = 0;
|
||||||
|
bool flag1 = false;
|
||||||
|
bool flag2 = false;
|
||||||
|
for (int index = 0; index < length; ++index)
|
||||||
|
{
|
||||||
|
char ch = s[index];
|
||||||
|
if (num1 == 0)
|
||||||
|
{
|
||||||
|
if (ch == '&')
|
||||||
|
{
|
||||||
|
stringBuilder2.Append(ch);
|
||||||
|
stringBuilder1.Append(ch);
|
||||||
|
num1 = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
stringBuilder3.Append(ch);
|
||||||
|
}
|
||||||
|
else if (ch == '&')
|
||||||
|
{
|
||||||
|
num1 = 1;
|
||||||
|
if (flag2)
|
||||||
|
{
|
||||||
|
stringBuilder2.Append(num2.ToString((IFormatProvider) CultureInfo.InvariantCulture));
|
||||||
|
flag2 = false;
|
||||||
|
}
|
||||||
|
stringBuilder3.Append(stringBuilder2.ToString());
|
||||||
|
stringBuilder2.Length = 0;
|
||||||
|
stringBuilder2.Append('&');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (num1)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
if (ch == ';')
|
||||||
|
{
|
||||||
|
num1 = 0;
|
||||||
|
stringBuilder3.Append(stringBuilder2.ToString());
|
||||||
|
stringBuilder3.Append(ch);
|
||||||
|
stringBuilder2.Length = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
num2 = 0;
|
||||||
|
flag1 = false;
|
||||||
|
num1 = ch == '#' ? 3 : 2;
|
||||||
|
stringBuilder2.Append(ch);
|
||||||
|
stringBuilder1.Append(ch);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
stringBuilder2.Append(ch);
|
||||||
|
if (ch == ';')
|
||||||
|
{
|
||||||
|
string str = stringBuilder2.ToString();
|
||||||
|
if (str.Length > 1 && HttpEncoder.Entities.ContainsKey(str.Substring(1, str.Length - 2)))
|
||||||
|
str = HttpEncoder.Entities[str.Substring(1, str.Length - 2)].ToString();
|
||||||
|
stringBuilder3.Append(str);
|
||||||
|
num1 = 0;
|
||||||
|
stringBuilder2.Length = 0;
|
||||||
|
stringBuilder1.Length = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (ch == ';')
|
||||||
|
{
|
||||||
|
if (num2 == 0)
|
||||||
|
stringBuilder3.Append(stringBuilder1.ToString() + ";");
|
||||||
|
else if (num2 > (int) ushort.MaxValue)
|
||||||
|
{
|
||||||
|
stringBuilder3.Append("&#");
|
||||||
|
stringBuilder3.Append(num2.ToString((IFormatProvider) CultureInfo.InvariantCulture));
|
||||||
|
stringBuilder3.Append(";");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
stringBuilder3.Append((char) num2);
|
||||||
|
num1 = 0;
|
||||||
|
stringBuilder2.Length = 0;
|
||||||
|
stringBuilder1.Length = 0;
|
||||||
|
flag2 = false;
|
||||||
|
}
|
||||||
|
else if (flag1 && Uri.IsHexDigit(ch))
|
||||||
|
{
|
||||||
|
num2 = num2 * 16 + Uri.FromHex(ch);
|
||||||
|
flag2 = true;
|
||||||
|
stringBuilder1.Append(ch);
|
||||||
|
}
|
||||||
|
else if (char.IsDigit(ch))
|
||||||
|
{
|
||||||
|
num2 = num2 * 10 + ((int) ch - 48);
|
||||||
|
flag2 = true;
|
||||||
|
stringBuilder1.Append(ch);
|
||||||
|
}
|
||||||
|
else if (num2 == 0 && (ch == 'x' || ch == 'X'))
|
||||||
|
{
|
||||||
|
flag1 = true;
|
||||||
|
stringBuilder1.Append(ch);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num1 = 2;
|
||||||
|
if (flag2)
|
||||||
|
{
|
||||||
|
stringBuilder2.Append(num2.ToString((IFormatProvider) CultureInfo.InvariantCulture));
|
||||||
|
flag2 = false;
|
||||||
|
}
|
||||||
|
stringBuilder2.Append(ch);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stringBuilder2.Length > 0)
|
||||||
|
stringBuilder3.Append(stringBuilder2.ToString());
|
||||||
|
else if (flag2)
|
||||||
|
stringBuilder3.Append(num2.ToString((IFormatProvider) CultureInfo.InvariantCulture));
|
||||||
|
return stringBuilder3.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool NotEncoded(char c) => c == '!' || c == '(' || c == ')' || c == '*' || c == '-' || c == '.' || c == '_';
|
||||||
|
|
||||||
|
internal static void UrlEncodeChar(char c, Stream result, bool isUnicode)
|
||||||
|
{
|
||||||
|
if (c > 'ÿ')
|
||||||
|
{
|
||||||
|
int num = (int) c;
|
||||||
|
result.WriteByte((byte) 37);
|
||||||
|
result.WriteByte((byte) 117);
|
||||||
|
int index1 = num >> 12;
|
||||||
|
result.WriteByte((byte) HttpEncoder.hexChars[index1]);
|
||||||
|
int index2 = num >> 8 & 15;
|
||||||
|
result.WriteByte((byte) HttpEncoder.hexChars[index2]);
|
||||||
|
int index3 = num >> 4 & 15;
|
||||||
|
result.WriteByte((byte) HttpEncoder.hexChars[index3]);
|
||||||
|
int index4 = num & 15;
|
||||||
|
result.WriteByte((byte) HttpEncoder.hexChars[index4]);
|
||||||
|
}
|
||||||
|
else if (c > ' ' && HttpEncoder.NotEncoded(c))
|
||||||
|
result.WriteByte((byte) c);
|
||||||
|
else if (c == ' ')
|
||||||
|
result.WriteByte((byte) 43);
|
||||||
|
else if (c < '0' || c < 'A' && c > '9' || c > 'Z' && c < 'a' || c > 'z')
|
||||||
|
{
|
||||||
|
if (isUnicode && c > '\u007F')
|
||||||
|
{
|
||||||
|
result.WriteByte((byte) 37);
|
||||||
|
result.WriteByte((byte) 117);
|
||||||
|
result.WriteByte((byte) 48);
|
||||||
|
result.WriteByte((byte) 48);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result.WriteByte((byte) 37);
|
||||||
|
int index5 = (int) c >> 4;
|
||||||
|
result.WriteByte((byte) HttpEncoder.hexChars[index5]);
|
||||||
|
int index6 = (int) c & 15;
|
||||||
|
result.WriteByte((byte) HttpEncoder.hexChars[index6]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result.WriteByte((byte) c);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void UrlPathEncodeChar(char c, Stream result)
|
||||||
|
{
|
||||||
|
if (c < '!' || c > '~')
|
||||||
|
{
|
||||||
|
byte[] bytes = Encoding.UTF8.GetBytes(c.ToString());
|
||||||
|
for (int index1 = 0; index1 < bytes.Length; ++index1)
|
||||||
|
{
|
||||||
|
result.WriteByte((byte) 37);
|
||||||
|
int index2 = (int) bytes[index1] >> 4;
|
||||||
|
result.WriteByte((byte) HttpEncoder.hexChars[index2]);
|
||||||
|
int index3 = (int) bytes[index1] & 15;
|
||||||
|
result.WriteByte((byte) HttpEncoder.hexChars[index3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == ' ')
|
||||||
|
{
|
||||||
|
result.WriteByte((byte) 37);
|
||||||
|
result.WriteByte((byte) 50);
|
||||||
|
result.WriteByte((byte) 48);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result.WriteByte((byte) c);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void InitEntities()
|
||||||
|
{
|
||||||
|
HttpEncoder.entities = new SortedDictionary<string, char>((IComparer<string>) StringComparer.Ordinal);
|
||||||
|
HttpEncoder.entities.Add("nbsp", ' ');
|
||||||
|
HttpEncoder.entities.Add("iexcl", '¡');
|
||||||
|
HttpEncoder.entities.Add("cent", '¢');
|
||||||
|
HttpEncoder.entities.Add("pound", '£');
|
||||||
|
HttpEncoder.entities.Add("curren", '¤');
|
||||||
|
HttpEncoder.entities.Add("yen", '¥');
|
||||||
|
HttpEncoder.entities.Add("brvbar", '¦');
|
||||||
|
HttpEncoder.entities.Add("sect", '§');
|
||||||
|
HttpEncoder.entities.Add("uml", '¨');
|
||||||
|
HttpEncoder.entities.Add("copy", '©');
|
||||||
|
HttpEncoder.entities.Add("ordf", 'ª');
|
||||||
|
HttpEncoder.entities.Add("laquo", '«');
|
||||||
|
HttpEncoder.entities.Add("not", '¬');
|
||||||
|
HttpEncoder.entities.Add("shy", '\u00AD');
|
||||||
|
HttpEncoder.entities.Add("reg", '®');
|
||||||
|
HttpEncoder.entities.Add("macr", '¯');
|
||||||
|
HttpEncoder.entities.Add("deg", '°');
|
||||||
|
HttpEncoder.entities.Add("plusmn", '±');
|
||||||
|
HttpEncoder.entities.Add("sup2", '\u00B2');
|
||||||
|
HttpEncoder.entities.Add("sup3", '\u00B3');
|
||||||
|
HttpEncoder.entities.Add("acute", '´');
|
||||||
|
HttpEncoder.entities.Add("micro", 'µ');
|
||||||
|
HttpEncoder.entities.Add("para", '¶');
|
||||||
|
HttpEncoder.entities.Add("middot", '·');
|
||||||
|
HttpEncoder.entities.Add("cedil", '¸');
|
||||||
|
HttpEncoder.entities.Add("sup1", '\u00B9');
|
||||||
|
HttpEncoder.entities.Add("ordm", 'º');
|
||||||
|
HttpEncoder.entities.Add("raquo", '»');
|
||||||
|
HttpEncoder.entities.Add("frac14", '\u00BC');
|
||||||
|
HttpEncoder.entities.Add("frac12", '\u00BD');
|
||||||
|
HttpEncoder.entities.Add("frac34", '\u00BE');
|
||||||
|
HttpEncoder.entities.Add("iquest", '¿');
|
||||||
|
HttpEncoder.entities.Add("Agrave", 'À');
|
||||||
|
HttpEncoder.entities.Add("Aacute", 'Á');
|
||||||
|
HttpEncoder.entities.Add("Acirc", 'Â');
|
||||||
|
HttpEncoder.entities.Add("Atilde", 'Ã');
|
||||||
|
HttpEncoder.entities.Add("Auml", 'Ä');
|
||||||
|
HttpEncoder.entities.Add("Aring", 'Å');
|
||||||
|
HttpEncoder.entities.Add("AElig", 'Æ');
|
||||||
|
HttpEncoder.entities.Add("Ccedil", 'Ç');
|
||||||
|
HttpEncoder.entities.Add("Egrave", 'È');
|
||||||
|
HttpEncoder.entities.Add("Eacute", 'É');
|
||||||
|
HttpEncoder.entities.Add("Ecirc", 'Ê');
|
||||||
|
HttpEncoder.entities.Add("Euml", 'Ë');
|
||||||
|
HttpEncoder.entities.Add("Igrave", 'Ì');
|
||||||
|
HttpEncoder.entities.Add("Iacute", 'Í');
|
||||||
|
HttpEncoder.entities.Add("Icirc", 'Î');
|
||||||
|
HttpEncoder.entities.Add("Iuml", 'Ï');
|
||||||
|
HttpEncoder.entities.Add("ETH", 'Ð');
|
||||||
|
HttpEncoder.entities.Add("Ntilde", 'Ñ');
|
||||||
|
HttpEncoder.entities.Add("Ograve", 'Ò');
|
||||||
|
HttpEncoder.entities.Add("Oacute", 'Ó');
|
||||||
|
HttpEncoder.entities.Add("Ocirc", 'Ô');
|
||||||
|
HttpEncoder.entities.Add("Otilde", 'Õ');
|
||||||
|
HttpEncoder.entities.Add("Ouml", 'Ö');
|
||||||
|
HttpEncoder.entities.Add("times", '×');
|
||||||
|
HttpEncoder.entities.Add("Oslash", 'Ø');
|
||||||
|
HttpEncoder.entities.Add("Ugrave", 'Ù');
|
||||||
|
HttpEncoder.entities.Add("Uacute", 'Ú');
|
||||||
|
HttpEncoder.entities.Add("Ucirc", 'Û');
|
||||||
|
HttpEncoder.entities.Add("Uuml", 'Ü');
|
||||||
|
HttpEncoder.entities.Add("Yacute", 'Ý');
|
||||||
|
HttpEncoder.entities.Add("THORN", 'Þ');
|
||||||
|
HttpEncoder.entities.Add("szlig", 'ß');
|
||||||
|
HttpEncoder.entities.Add("agrave", 'à');
|
||||||
|
HttpEncoder.entities.Add("aacute", 'á');
|
||||||
|
HttpEncoder.entities.Add("acirc", 'â');
|
||||||
|
HttpEncoder.entities.Add("atilde", 'ã');
|
||||||
|
HttpEncoder.entities.Add("auml", 'ä');
|
||||||
|
HttpEncoder.entities.Add("aring", 'å');
|
||||||
|
HttpEncoder.entities.Add("aelig", 'æ');
|
||||||
|
HttpEncoder.entities.Add("ccedil", 'ç');
|
||||||
|
HttpEncoder.entities.Add("egrave", 'è');
|
||||||
|
HttpEncoder.entities.Add("eacute", 'é');
|
||||||
|
HttpEncoder.entities.Add("ecirc", 'ê');
|
||||||
|
HttpEncoder.entities.Add("euml", 'ë');
|
||||||
|
HttpEncoder.entities.Add("igrave", 'ì');
|
||||||
|
HttpEncoder.entities.Add("iacute", 'í');
|
||||||
|
HttpEncoder.entities.Add("icirc", 'î');
|
||||||
|
HttpEncoder.entities.Add("iuml", 'ï');
|
||||||
|
HttpEncoder.entities.Add("eth", 'ð');
|
||||||
|
HttpEncoder.entities.Add("ntilde", 'ñ');
|
||||||
|
HttpEncoder.entities.Add("ograve", 'ò');
|
||||||
|
HttpEncoder.entities.Add("oacute", 'ó');
|
||||||
|
HttpEncoder.entities.Add("ocirc", 'ô');
|
||||||
|
HttpEncoder.entities.Add("otilde", 'õ');
|
||||||
|
HttpEncoder.entities.Add("ouml", 'ö');
|
||||||
|
HttpEncoder.entities.Add("divide", '÷');
|
||||||
|
HttpEncoder.entities.Add("oslash", 'ø');
|
||||||
|
HttpEncoder.entities.Add("ugrave", 'ù');
|
||||||
|
HttpEncoder.entities.Add("uacute", 'ú');
|
||||||
|
HttpEncoder.entities.Add("ucirc", 'û');
|
||||||
|
HttpEncoder.entities.Add("uuml", 'ü');
|
||||||
|
HttpEncoder.entities.Add("yacute", 'ý');
|
||||||
|
HttpEncoder.entities.Add("thorn", 'þ');
|
||||||
|
HttpEncoder.entities.Add("yuml", 'ÿ');
|
||||||
|
HttpEncoder.entities.Add("fnof", 'ƒ');
|
||||||
|
HttpEncoder.entities.Add("Alpha", 'Α');
|
||||||
|
HttpEncoder.entities.Add("Beta", 'Β');
|
||||||
|
HttpEncoder.entities.Add("Gamma", 'Γ');
|
||||||
|
HttpEncoder.entities.Add("Delta", 'Δ');
|
||||||
|
HttpEncoder.entities.Add("Epsilon", 'Ε');
|
||||||
|
HttpEncoder.entities.Add("Zeta", 'Ζ');
|
||||||
|
HttpEncoder.entities.Add("Eta", 'Η');
|
||||||
|
HttpEncoder.entities.Add("Theta", 'Θ');
|
||||||
|
HttpEncoder.entities.Add("Iota", 'Ι');
|
||||||
|
HttpEncoder.entities.Add("Kappa", 'Κ');
|
||||||
|
HttpEncoder.entities.Add("Lambda", 'Λ');
|
||||||
|
HttpEncoder.entities.Add("Mu", 'Μ');
|
||||||
|
HttpEncoder.entities.Add("Nu", 'Ν');
|
||||||
|
HttpEncoder.entities.Add("Xi", 'Ξ');
|
||||||
|
HttpEncoder.entities.Add("Omicron", 'Ο');
|
||||||
|
HttpEncoder.entities.Add("Pi", 'Π');
|
||||||
|
HttpEncoder.entities.Add("Rho", 'Ρ');
|
||||||
|
HttpEncoder.entities.Add("Sigma", 'Σ');
|
||||||
|
HttpEncoder.entities.Add("Tau", 'Τ');
|
||||||
|
HttpEncoder.entities.Add("Upsilon", 'Υ');
|
||||||
|
HttpEncoder.entities.Add("Phi", 'Φ');
|
||||||
|
HttpEncoder.entities.Add("Chi", 'Χ');
|
||||||
|
HttpEncoder.entities.Add("Psi", 'Ψ');
|
||||||
|
HttpEncoder.entities.Add("Omega", 'Ω');
|
||||||
|
HttpEncoder.entities.Add("alpha", 'α');
|
||||||
|
HttpEncoder.entities.Add("beta", 'β');
|
||||||
|
HttpEncoder.entities.Add("gamma", 'γ');
|
||||||
|
HttpEncoder.entities.Add("delta", 'δ');
|
||||||
|
HttpEncoder.entities.Add("epsilon", 'ε');
|
||||||
|
HttpEncoder.entities.Add("zeta", 'ζ');
|
||||||
|
HttpEncoder.entities.Add("eta", 'η');
|
||||||
|
HttpEncoder.entities.Add("theta", 'θ');
|
||||||
|
HttpEncoder.entities.Add("iota", 'ι');
|
||||||
|
HttpEncoder.entities.Add("kappa", 'κ');
|
||||||
|
HttpEncoder.entities.Add("lambda", 'λ');
|
||||||
|
HttpEncoder.entities.Add("mu", 'μ');
|
||||||
|
HttpEncoder.entities.Add("nu", 'ν');
|
||||||
|
HttpEncoder.entities.Add("xi", 'ξ');
|
||||||
|
HttpEncoder.entities.Add("omicron", 'ο');
|
||||||
|
HttpEncoder.entities.Add("pi", 'π');
|
||||||
|
HttpEncoder.entities.Add("rho", 'ρ');
|
||||||
|
HttpEncoder.entities.Add("sigmaf", 'ς');
|
||||||
|
HttpEncoder.entities.Add("sigma", 'σ');
|
||||||
|
HttpEncoder.entities.Add("tau", 'τ');
|
||||||
|
HttpEncoder.entities.Add("upsilon", 'υ');
|
||||||
|
HttpEncoder.entities.Add("phi", 'φ');
|
||||||
|
HttpEncoder.entities.Add("chi", 'χ');
|
||||||
|
HttpEncoder.entities.Add("psi", 'ψ');
|
||||||
|
HttpEncoder.entities.Add("omega", 'ω');
|
||||||
|
HttpEncoder.entities.Add("thetasym", 'ϑ');
|
||||||
|
HttpEncoder.entities.Add("upsih", 'ϒ');
|
||||||
|
HttpEncoder.entities.Add("piv", 'ϖ');
|
||||||
|
HttpEncoder.entities.Add("bull", '•');
|
||||||
|
HttpEncoder.entities.Add("hellip", '…');
|
||||||
|
HttpEncoder.entities.Add("prime", '′');
|
||||||
|
HttpEncoder.entities.Add("Prime", '″');
|
||||||
|
HttpEncoder.entities.Add("oline", '‾');
|
||||||
|
HttpEncoder.entities.Add("frasl", '⁄');
|
||||||
|
HttpEncoder.entities.Add("weierp", '℘');
|
||||||
|
HttpEncoder.entities.Add("image", 'ℑ');
|
||||||
|
HttpEncoder.entities.Add("real", 'ℜ');
|
||||||
|
HttpEncoder.entities.Add("trade", '™');
|
||||||
|
HttpEncoder.entities.Add("alefsym", 'ℵ');
|
||||||
|
HttpEncoder.entities.Add("larr", '←');
|
||||||
|
HttpEncoder.entities.Add("uarr", '↑');
|
||||||
|
HttpEncoder.entities.Add("rarr", '→');
|
||||||
|
HttpEncoder.entities.Add("darr", '↓');
|
||||||
|
HttpEncoder.entities.Add("harr", '↔');
|
||||||
|
HttpEncoder.entities.Add("crarr", '↵');
|
||||||
|
HttpEncoder.entities.Add("lArr", '⇐');
|
||||||
|
HttpEncoder.entities.Add("uArr", '⇑');
|
||||||
|
HttpEncoder.entities.Add("rArr", '⇒');
|
||||||
|
HttpEncoder.entities.Add("dArr", '⇓');
|
||||||
|
HttpEncoder.entities.Add("hArr", '⇔');
|
||||||
|
HttpEncoder.entities.Add("forall", '∀');
|
||||||
|
HttpEncoder.entities.Add("part", '∂');
|
||||||
|
HttpEncoder.entities.Add("exist", '∃');
|
||||||
|
HttpEncoder.entities.Add("empty", '∅');
|
||||||
|
HttpEncoder.entities.Add("nabla", '∇');
|
||||||
|
HttpEncoder.entities.Add("isin", '∈');
|
||||||
|
HttpEncoder.entities.Add("notin", '∉');
|
||||||
|
HttpEncoder.entities.Add("ni", '∋');
|
||||||
|
HttpEncoder.entities.Add("prod", '∏');
|
||||||
|
HttpEncoder.entities.Add("sum", '∑');
|
||||||
|
HttpEncoder.entities.Add("minus", '−');
|
||||||
|
HttpEncoder.entities.Add("lowast", '∗');
|
||||||
|
HttpEncoder.entities.Add("radic", '√');
|
||||||
|
HttpEncoder.entities.Add("prop", '∝');
|
||||||
|
HttpEncoder.entities.Add("infin", '∞');
|
||||||
|
HttpEncoder.entities.Add("ang", '∠');
|
||||||
|
HttpEncoder.entities.Add("and", '∧');
|
||||||
|
HttpEncoder.entities.Add("or", '∨');
|
||||||
|
HttpEncoder.entities.Add("cap", '∩');
|
||||||
|
HttpEncoder.entities.Add("cup", '∪');
|
||||||
|
HttpEncoder.entities.Add("int", '∫');
|
||||||
|
HttpEncoder.entities.Add("there4", '∴');
|
||||||
|
HttpEncoder.entities.Add("sim", '∼');
|
||||||
|
HttpEncoder.entities.Add("cong", '≅');
|
||||||
|
HttpEncoder.entities.Add("asymp", '≈');
|
||||||
|
HttpEncoder.entities.Add("ne", '≠');
|
||||||
|
HttpEncoder.entities.Add("equiv", '≡');
|
||||||
|
HttpEncoder.entities.Add("le", '≤');
|
||||||
|
HttpEncoder.entities.Add("ge", '≥');
|
||||||
|
HttpEncoder.entities.Add("sub", '⊂');
|
||||||
|
HttpEncoder.entities.Add("sup", '⊃');
|
||||||
|
HttpEncoder.entities.Add("nsub", '⊄');
|
||||||
|
HttpEncoder.entities.Add("sube", '⊆');
|
||||||
|
HttpEncoder.entities.Add("supe", '⊇');
|
||||||
|
HttpEncoder.entities.Add("oplus", '⊕');
|
||||||
|
HttpEncoder.entities.Add("otimes", '⊗');
|
||||||
|
HttpEncoder.entities.Add("perp", '⊥');
|
||||||
|
HttpEncoder.entities.Add("sdot", '⋅');
|
||||||
|
HttpEncoder.entities.Add("lceil", '⌈');
|
||||||
|
HttpEncoder.entities.Add("rceil", '⌉');
|
||||||
|
HttpEncoder.entities.Add("lfloor", '⌊');
|
||||||
|
HttpEncoder.entities.Add("rfloor", '⌋');
|
||||||
|
HttpEncoder.entities.Add("lang", '〈');
|
||||||
|
HttpEncoder.entities.Add("rang", '〉');
|
||||||
|
HttpEncoder.entities.Add("loz", '◊');
|
||||||
|
HttpEncoder.entities.Add("spades", '♠');
|
||||||
|
HttpEncoder.entities.Add("clubs", '♣');
|
||||||
|
HttpEncoder.entities.Add("hearts", '♥');
|
||||||
|
HttpEncoder.entities.Add("diams", '♦');
|
||||||
|
HttpEncoder.entities.Add("quot", '"');
|
||||||
|
HttpEncoder.entities.Add("amp", '&');
|
||||||
|
HttpEncoder.entities.Add("lt", '<');
|
||||||
|
HttpEncoder.entities.Add("gt", '>');
|
||||||
|
HttpEncoder.entities.Add("OElig", 'Œ');
|
||||||
|
HttpEncoder.entities.Add("oelig", 'œ');
|
||||||
|
HttpEncoder.entities.Add("Scaron", 'Š');
|
||||||
|
HttpEncoder.entities.Add("scaron", 'š');
|
||||||
|
HttpEncoder.entities.Add("Yuml", 'Ÿ');
|
||||||
|
HttpEncoder.entities.Add("circ", 'ˆ');
|
||||||
|
HttpEncoder.entities.Add("tilde", '˜');
|
||||||
|
HttpEncoder.entities.Add("ensp", ' ');
|
||||||
|
HttpEncoder.entities.Add("emsp", ' ');
|
||||||
|
HttpEncoder.entities.Add("thinsp", ' ');
|
||||||
|
HttpEncoder.entities.Add("zwnj", '\u200C');
|
||||||
|
HttpEncoder.entities.Add("zwj", '\u200D');
|
||||||
|
HttpEncoder.entities.Add("lrm", '\u200E');
|
||||||
|
HttpEncoder.entities.Add("rlm", '\u200F');
|
||||||
|
HttpEncoder.entities.Add("ndash", '–');
|
||||||
|
HttpEncoder.entities.Add("mdash", '—');
|
||||||
|
HttpEncoder.entities.Add("lsquo", '‘');
|
||||||
|
HttpEncoder.entities.Add("rsquo", '’');
|
||||||
|
HttpEncoder.entities.Add("sbquo", '‚');
|
||||||
|
HttpEncoder.entities.Add("ldquo", '“');
|
||||||
|
HttpEncoder.entities.Add("rdquo", '”');
|
||||||
|
HttpEncoder.entities.Add("bdquo", '„');
|
||||||
|
HttpEncoder.entities.Add("dagger", '†');
|
||||||
|
HttpEncoder.entities.Add("Dagger", '‡');
|
||||||
|
HttpEncoder.entities.Add("permil", '‰');
|
||||||
|
HttpEncoder.entities.Add("lsaquo", '‹');
|
||||||
|
HttpEncoder.entities.Add("rsaquo", '›');
|
||||||
|
HttpEncoder.entities.Add("euro", '€');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3c9f699c227f48e381db521abe59c2e1
|
||||||
|
timeCreated: 1701789490
|
230
Assets/Mirror/Hosting/Edgegap/Dependencies/HttpUtility.cs
Normal file
230
Assets/Mirror/Hosting/Edgegap/Dependencies/HttpUtility.cs
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
// MIRROR CHANGE: drop in Codice.Utils HttpUtility subset to not depend on Unity's plastic scm package
|
||||||
|
// SOURCE: Unity Plastic SCM package
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Edgegap.Codice.Utils // MIRROR CHANGE: namespace Edgegap.* to not collide if anyone has Plastic SCM installed already
|
||||||
|
{
|
||||||
|
public sealed class HttpUtility
|
||||||
|
{
|
||||||
|
private static void WriteCharBytes(IList buf, char ch, Encoding e)
|
||||||
|
{
|
||||||
|
if (ch > 'ÿ')
|
||||||
|
{
|
||||||
|
Encoding encoding = e;
|
||||||
|
char[] chars = new char[1]{ ch };
|
||||||
|
foreach (byte num in encoding.GetBytes(chars))
|
||||||
|
buf.Add((object) num);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
buf.Add((object) (byte) ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string UrlDecode(string s, Encoding e)
|
||||||
|
{
|
||||||
|
if (null == s)
|
||||||
|
return (string) null;
|
||||||
|
if (s.IndexOf('%') == -1 && s.IndexOf('+') == -1)
|
||||||
|
return s;
|
||||||
|
if (e == null)
|
||||||
|
e = Encoding.UTF8;
|
||||||
|
long length = (long) s.Length;
|
||||||
|
List<byte> buf = new List<byte>();
|
||||||
|
for (int index = 0; (long) index < length; ++index)
|
||||||
|
{
|
||||||
|
char ch = s[index];
|
||||||
|
if (ch == '%' && (long) (index + 2) < length && s[index + 1] != '%')
|
||||||
|
{
|
||||||
|
if (s[index + 1] == 'u' && (long) (index + 5) < length)
|
||||||
|
{
|
||||||
|
int num = HttpUtility.GetChar(s, index + 2, 4);
|
||||||
|
if (num != -1)
|
||||||
|
{
|
||||||
|
HttpUtility.WriteCharBytes((IList) buf, (char) num, e);
|
||||||
|
index += 5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
HttpUtility.WriteCharBytes((IList) buf, '%', e);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int num;
|
||||||
|
if ((num = HttpUtility.GetChar(s, index + 1, 2)) != -1)
|
||||||
|
{
|
||||||
|
HttpUtility.WriteCharBytes((IList) buf, (char) num, e);
|
||||||
|
index += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
HttpUtility.WriteCharBytes((IList) buf, '%', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ch == '+')
|
||||||
|
HttpUtility.WriteCharBytes((IList) buf, ' ', e);
|
||||||
|
else
|
||||||
|
HttpUtility.WriteCharBytes((IList) buf, ch, e);
|
||||||
|
}
|
||||||
|
byte[] array = buf.ToArray();
|
||||||
|
return e.GetString(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetInt(byte b)
|
||||||
|
{
|
||||||
|
char ch = (char) b;
|
||||||
|
if (ch >= '0' && ch <= '9')
|
||||||
|
return (int) ch - 48;
|
||||||
|
if (ch >= 'a' && ch <= 'f')
|
||||||
|
return (int) ch - 97 + 10;
|
||||||
|
return ch >= 'A' && ch <= 'F' ? (int) ch - 65 + 10 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetChar(string str, int offset, int length)
|
||||||
|
{
|
||||||
|
int num1 = 0;
|
||||||
|
int num2 = length + offset;
|
||||||
|
for (int index = offset; index < num2; ++index)
|
||||||
|
{
|
||||||
|
char b = str[index];
|
||||||
|
if (b > '\u007F')
|
||||||
|
return -1;
|
||||||
|
int num3 = HttpUtility.GetInt((byte) b);
|
||||||
|
if (num3 == -1)
|
||||||
|
return -1;
|
||||||
|
num1 = (num1 << 4) + num3;
|
||||||
|
}
|
||||||
|
return num1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string UrlEncode(string str) => HttpUtility.UrlEncode(str, Encoding.UTF8);
|
||||||
|
|
||||||
|
public static string UrlEncode(string s, Encoding Enc)
|
||||||
|
{
|
||||||
|
if (s == null)
|
||||||
|
return (string) null;
|
||||||
|
if (s == string.Empty)
|
||||||
|
return string.Empty;
|
||||||
|
bool flag = false;
|
||||||
|
int length = s.Length;
|
||||||
|
for (int index = 0; index < length; ++index)
|
||||||
|
{
|
||||||
|
char c = s[index];
|
||||||
|
if ((c < '0' || c < 'A' && c > '9' || c > 'Z' && c < 'a' || c > 'z') && !HttpEncoder.NotEncoded(c))
|
||||||
|
{
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!flag)
|
||||||
|
return s;
|
||||||
|
byte[] bytes1 = new byte[Enc.GetMaxByteCount(s.Length)];
|
||||||
|
int bytes2 = Enc.GetBytes(s, 0, s.Length, bytes1, 0);
|
||||||
|
return Encoding.ASCII.GetString(HttpUtility.UrlEncodeToBytes(bytes1, 0, bytes2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] UrlEncodeToBytes(byte[] bytes, int offset, int count) => bytes == null ? (byte[]) null : HttpEncoder.Current.UrlEncode(bytes, offset, count);
|
||||||
|
|
||||||
|
public static string HtmlDecode(string s)
|
||||||
|
{
|
||||||
|
if (s == null)
|
||||||
|
return (string) null;
|
||||||
|
using (StringWriter output = new StringWriter())
|
||||||
|
{
|
||||||
|
HttpEncoder.Current.HtmlDecode(s, (TextWriter) output);
|
||||||
|
return output.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NameValueCollection ParseQueryString(string query) => HttpUtility.ParseQueryString(query, Encoding.UTF8);
|
||||||
|
|
||||||
|
public static NameValueCollection ParseQueryString(
|
||||||
|
string query,
|
||||||
|
Encoding encoding)
|
||||||
|
{
|
||||||
|
if (query == null)
|
||||||
|
throw new ArgumentNullException(nameof (query));
|
||||||
|
if (encoding == null)
|
||||||
|
throw new ArgumentNullException(nameof (encoding));
|
||||||
|
if (query.Length == 0 || query.Length == 1 && query[0] == '?')
|
||||||
|
return (NameValueCollection) new HttpUtility.HttpQSCollection();
|
||||||
|
if (query[0] == '?')
|
||||||
|
query = query.Substring(1);
|
||||||
|
NameValueCollection result = (NameValueCollection) new HttpUtility.HttpQSCollection();
|
||||||
|
HttpUtility.ParseQueryString(query, encoding, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void ParseQueryString(
|
||||||
|
string query,
|
||||||
|
Encoding encoding,
|
||||||
|
NameValueCollection result)
|
||||||
|
{
|
||||||
|
if (query.Length == 0)
|
||||||
|
return;
|
||||||
|
string str1 = HttpUtility.HtmlDecode(query);
|
||||||
|
int length = str1.Length;
|
||||||
|
int num1 = 0;
|
||||||
|
bool flag = true;
|
||||||
|
while (num1 <= length)
|
||||||
|
{
|
||||||
|
int startIndex = -1;
|
||||||
|
int num2 = -1;
|
||||||
|
for (int index = num1; index < length; ++index)
|
||||||
|
{
|
||||||
|
if (startIndex == -1 && str1[index] == '=')
|
||||||
|
startIndex = index + 1;
|
||||||
|
else if (str1[index] == '&')
|
||||||
|
{
|
||||||
|
num2 = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
flag = false;
|
||||||
|
if (str1[num1] == '?')
|
||||||
|
++num1;
|
||||||
|
}
|
||||||
|
string name;
|
||||||
|
if (startIndex == -1)
|
||||||
|
{
|
||||||
|
name = (string) null;
|
||||||
|
startIndex = num1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
name = HttpUtility.UrlDecode(str1.Substring(num1, startIndex - num1 - 1), encoding);
|
||||||
|
if (num2 < 0)
|
||||||
|
{
|
||||||
|
num1 = -1;
|
||||||
|
num2 = str1.Length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
num1 = num2 + 1;
|
||||||
|
string str2 = HttpUtility.UrlDecode(str1.Substring(startIndex, num2 - startIndex), encoding);
|
||||||
|
result.Add(name, str2);
|
||||||
|
if (num1 == -1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class HttpQSCollection : NameValueCollection
|
||||||
|
{
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
int count = this.Count;
|
||||||
|
if (count == 0)
|
||||||
|
return "";
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
string[] allKeys = this.AllKeys;
|
||||||
|
for (int index = 0; index < count; ++index)
|
||||||
|
stringBuilder.AppendFormat("{0}={1}&", (object) allKeys[index], (object) HttpUtility.UrlEncode(this[allKeys[index]]));
|
||||||
|
if (stringBuilder.Length > 0)
|
||||||
|
--stringBuilder.Length;
|
||||||
|
return stringBuilder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6f83f468a8b546fd92606db56038f9e6
|
||||||
|
timeCreated: 1701785025
|
8
Assets/Mirror/Hosting/Edgegap/Editor/Api.meta
Executable file
8
Assets/Mirror/Hosting/Edgegap/Editor/Api.meta
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6d2a4589d6738cb4b82bb1ceebd1453f
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
280
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapApiBase.cs
Executable file
280
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapApiBase.cs
Executable file
@ -0,0 +1,280 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
// using Codice.Utils; // MIRROR CHANGE
|
||||||
|
using Edgegap.Codice.Utils; // MIRROR CHANGE
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Handles base URL and common methods for all Edgegap APIs.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class EdgegapApiBase
|
||||||
|
{
|
||||||
|
#region Vars
|
||||||
|
private readonly HttpClient _httpClient = new HttpClient(); // Base address set // MIRROR CHANGE: Unity 2020 support
|
||||||
|
protected ApiEnvironment SelectedApiEnvironment { get; }
|
||||||
|
protected EdgegapWindowMetadata.LogLevel LogLevel { get; set; }
|
||||||
|
protected bool IsLogLevelDebug => LogLevel == EdgegapWindowMetadata.LogLevel.Debug;
|
||||||
|
|
||||||
|
/// <summary>Based on SelectedApiEnvironment.</summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string GetBaseUrl() =>
|
||||||
|
SelectedApiEnvironment == ApiEnvironment.Staging
|
||||||
|
? ApiEnvironment.Staging.GetApiUrl()
|
||||||
|
: ApiEnvironment.Console.GetApiUrl();
|
||||||
|
#endregion // Vars
|
||||||
|
|
||||||
|
|
||||||
|
/// <param name="apiEnvironment">"console" || "staging-console"?</param>
|
||||||
|
/// <param name="apiToken">Without the "token " prefix, although we'll clear this if present</param>
|
||||||
|
/// <param name="logLevel">You may want more-verbose logs other than errs</param>
|
||||||
|
protected EdgegapApiBase(
|
||||||
|
ApiEnvironment apiEnvironment,
|
||||||
|
string apiToken,
|
||||||
|
EdgegapWindowMetadata.LogLevel logLevel = EdgegapWindowMetadata.LogLevel.Error)
|
||||||
|
{
|
||||||
|
this.SelectedApiEnvironment = apiEnvironment;
|
||||||
|
|
||||||
|
this._httpClient.BaseAddress = new Uri($"{GetBaseUrl()}/");
|
||||||
|
this._httpClient.DefaultRequestHeaders.Accept.Add(
|
||||||
|
new MediaTypeWithQualityHeaderValue("application/json"));
|
||||||
|
|
||||||
|
string cleanedApiToken = apiToken.Replace("token ", ""); // We already prefixed token below
|
||||||
|
this._httpClient.DefaultRequestHeaders.Authorization =
|
||||||
|
new AuthenticationHeaderValue("token", cleanedApiToken);
|
||||||
|
|
||||||
|
this.LogLevel = logLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region HTTP Requests
|
||||||
|
/// <summary>
|
||||||
|
/// POST | We already added "https://api.edgegap.com/" (or similar) BaseAddress via constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="relativePath"></param>
|
||||||
|
/// <param name="json">Serialize to your model via Newtonsoft</param>
|
||||||
|
/// <returns>
|
||||||
|
/// - Success => returns HttpResponseMessage result
|
||||||
|
/// - Error => Catches errs => returns null (no rethrow)
|
||||||
|
/// </returns>
|
||||||
|
protected async Task<HttpResponseMessage> PostAsync(string relativePath = "", string json = "{}")
|
||||||
|
{
|
||||||
|
StringContent stringContent = CreateStringContent(json);
|
||||||
|
Uri uri = new Uri(_httpClient.BaseAddress, relativePath); // Normalize POST uri: Can't end with `/`.
|
||||||
|
|
||||||
|
if (IsLogLevelDebug)
|
||||||
|
Debug.Log($"PostAsync to: `{uri}` with json: `{json}`");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await ExecuteRequestAsync(() => _httpClient.PostAsync(uri, stringContent));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Error: {e}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PATCH | We already added "https://api.edgegap.com/" (or similar) BaseAddress via constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="relativePath"></param>
|
||||||
|
/// <param name="json">Serialize to your model via Newtonsoft</param>
|
||||||
|
/// <returns>
|
||||||
|
/// - Success => returns HttpResponseMessage result
|
||||||
|
/// - Error => Catches errs => returns null (no rethrow)
|
||||||
|
/// </returns>
|
||||||
|
protected async Task<HttpResponseMessage> PatchAsync(string relativePath = "", string json = "{}")
|
||||||
|
{
|
||||||
|
StringContent stringContent = CreateStringContent(json);
|
||||||
|
Uri uri = new Uri(_httpClient.BaseAddress, relativePath); // Normalize PATCH uri: Can't end with `/`.
|
||||||
|
|
||||||
|
if (IsLogLevelDebug)
|
||||||
|
Debug.Log($"PatchAsync to: `{uri}` with json: `{json}`");
|
||||||
|
|
||||||
|
// (!) As of 11/15/2023, .PatchAsync() is "unsupported by Unity" -- so we manually set the verb and SendAsync()
|
||||||
|
// Create the request manually
|
||||||
|
HttpRequestMessage patchRequest = new HttpRequestMessage(new HttpMethod("PATCH"), uri)
|
||||||
|
{
|
||||||
|
Content = stringContent,
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await ExecuteRequestAsync(() => _httpClient.SendAsync(patchRequest));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Error: {e}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GET | We already added "https://api.edgegap.com/" (or similar) BaseAddress via constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="relativePath"></param>
|
||||||
|
/// <param name="customQuery">
|
||||||
|
/// To append to the URL; eg: "foo=0&bar=1"
|
||||||
|
/// (!) First query key should prefix nothing, as shown</param>
|
||||||
|
/// <returns>
|
||||||
|
/// - Success => returns HttpResponseMessage result
|
||||||
|
/// - Error => Catches errs => returns null (no rethrow)
|
||||||
|
/// </returns>
|
||||||
|
protected async Task<HttpResponseMessage> GetAsync(string relativePath = "", string customQuery = "")
|
||||||
|
{
|
||||||
|
string completeRelativeUri = prepareEdgegapUriWithQuery(
|
||||||
|
relativePath,
|
||||||
|
customQuery);
|
||||||
|
|
||||||
|
if (IsLogLevelDebug)
|
||||||
|
Debug.Log($"GetAsync to: `{completeRelativeUri} with customQuery: `{customQuery}`");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await ExecuteRequestAsync(() => _httpClient.GetAsync(completeRelativeUri));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Error: {e}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DELETE | We already added "https://api.edgegap.com/" (or similar) BaseAddress via constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="relativePath"></param>
|
||||||
|
/// <param name="customQuery">
|
||||||
|
/// To append to the URL; eg: "foo=0&bar=1"
|
||||||
|
/// (!) First query key should prefix nothing, as shown</param>
|
||||||
|
/// <returns>
|
||||||
|
/// - Success => returns HttpResponseMessage result
|
||||||
|
/// - Error => Catches errs => returns null (no rethrow)
|
||||||
|
/// </returns>
|
||||||
|
protected async Task<HttpResponseMessage> DeleteAsync(string relativePath = "", string customQuery = "")
|
||||||
|
{
|
||||||
|
string completeRelativeUri = prepareEdgegapUriWithQuery(
|
||||||
|
relativePath,
|
||||||
|
customQuery);
|
||||||
|
|
||||||
|
if (IsLogLevelDebug)
|
||||||
|
Debug.Log($"DeleteAsync to: `{completeRelativeUri} with customQuery: `{customQuery}`");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await ExecuteRequestAsync(() => _httpClient.DeleteAsync(completeRelativeUri));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Error: {e}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>POST || GET</summary>
|
||||||
|
/// <param name="requestFunc"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static async Task<HttpResponseMessage> ExecuteRequestAsync(
|
||||||
|
Func<Task<HttpResponseMessage>> requestFunc,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
HttpResponseMessage response = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
response = await requestFunc();
|
||||||
|
}
|
||||||
|
catch (HttpRequestException e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"HttpRequestException: {e.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch (TaskCanceledException e)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
Debug.LogError("Task was cancelled by caller.");
|
||||||
|
else
|
||||||
|
Debug.LogError($"TaskCanceledException: Timeout - {e.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch (Exception e) // Generic exception handler
|
||||||
|
{
|
||||||
|
Debug.LogError($"Unexpected error occurred: {e.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a successful status code
|
||||||
|
if (response == null)
|
||||||
|
{
|
||||||
|
Debug.Log("!Success (null response) - returning 500");
|
||||||
|
return CreateUnknown500Err();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
HttpMethod httpMethod = response.RequestMessage.Method;
|
||||||
|
Debug.Log($"!Success: {(short)response.StatusCode} {response.ReasonPhrase} - " +
|
||||||
|
$"{httpMethod} | {response.RequestMessage.RequestUri}` - " +
|
||||||
|
$"{response.Content?.ReadAsStringAsync().Result}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
#endregion // HTTP Requests
|
||||||
|
|
||||||
|
|
||||||
|
#region Utils
|
||||||
|
/// <summary>Creates a UTF-8 encoded application/json + json obj</summary>
|
||||||
|
/// <param name="json">Arbitrary json obj</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private StringContent CreateStringContent(string json = "{}") =>
|
||||||
|
new StringContent(json, Encoding.UTF8, "application/json"); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
|
||||||
|
private static HttpResponseMessage CreateUnknown500Err() =>
|
||||||
|
new HttpResponseMessage(HttpStatusCode.InternalServerError); // 500 - Unknown // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Merges Edgegap-required query params (source) -> merges with custom query -> normalizes.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="relativePath"></param>
|
||||||
|
/// <param name="customQuery"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string prepareEdgegapUriWithQuery(string relativePath, string customQuery)
|
||||||
|
{
|
||||||
|
// Create UriBuilder using the BaseAddress
|
||||||
|
UriBuilder uriBuilder = new UriBuilder(_httpClient.BaseAddress);
|
||||||
|
|
||||||
|
// Add the relative path to the UriBuilder's path
|
||||||
|
uriBuilder.Path += relativePath;
|
||||||
|
|
||||||
|
// Parse the existing query from the UriBuilder
|
||||||
|
NameValueCollection query = HttpUtility.ParseQueryString(uriBuilder.Query);
|
||||||
|
|
||||||
|
// Add default "source=unity" param
|
||||||
|
query["source"] = "unity";
|
||||||
|
|
||||||
|
// Parse and merge the custom query parameters
|
||||||
|
NameValueCollection customParams = HttpUtility.ParseQueryString(customQuery);
|
||||||
|
foreach (string key in customParams)
|
||||||
|
{
|
||||||
|
query[key] = customParams[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the merged query back to the UriBuilder
|
||||||
|
uriBuilder.Query = query.ToString();
|
||||||
|
|
||||||
|
// Extract the complete relative URI and return it
|
||||||
|
return uriBuilder.Uri.PathAndQuery;
|
||||||
|
}
|
||||||
|
#endregion // Utils
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapApiBase.cs.meta
Executable file
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapApiBase.cs.meta
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 50379f30f5137224aa05a5c7b6b5ebba
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
148
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapAppApi.cs
Executable file
148
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapAppApi.cs
Executable file
@ -0,0 +1,148 @@
|
|||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Edgegap.Editor.Api.Models.Requests;
|
||||||
|
using Edgegap.Editor.Api.Models.Results;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Wraps the v1/app API endpoint: Applications Control API.
|
||||||
|
/// - API Doc | https://docs.edgegap.com/api/#tag/Applications
|
||||||
|
/// </summary>
|
||||||
|
public class EdgegapAppApi : EdgegapApiBase
|
||||||
|
{
|
||||||
|
public EdgegapAppApi(
|
||||||
|
ApiEnvironment apiEnvironment,
|
||||||
|
string apiToken,
|
||||||
|
EdgegapWindowMetadata.LogLevel logLevel = EdgegapWindowMetadata.LogLevel.Error)
|
||||||
|
: base(apiEnvironment, apiToken, logLevel)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region API Methods
|
||||||
|
/// <summary>
|
||||||
|
/// POST to v1/app
|
||||||
|
/// - Create an application that will regroup application versions.
|
||||||
|
/// - API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/application-post
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Http info with GetCreateAppResult data model
|
||||||
|
/// - Success: 200
|
||||||
|
/// - Fail: 409 (app already exists), 400 (reached limit)
|
||||||
|
/// </returns>
|
||||||
|
public async Task<EdgegapHttpResult<GetCreateAppResult>> CreateApp(CreateAppRequest request)
|
||||||
|
{
|
||||||
|
HttpResponseMessage response = await PostAsync("v1/app", request.ToString());
|
||||||
|
EdgegapHttpResult<GetCreateAppResult> result = new EdgegapHttpResult<GetCreateAppResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
|
||||||
|
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
||||||
|
if (!isSuccess)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GET to v1/app
|
||||||
|
/// - Get an application that will regroup application versions.
|
||||||
|
/// - API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/application-post
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Http info with GetCreateAppResult data model
|
||||||
|
/// - Success: 200
|
||||||
|
/// </returns>
|
||||||
|
public async Task<EdgegapHttpResult<GetCreateAppResult>> GetApp(string appName)
|
||||||
|
{
|
||||||
|
HttpResponseMessage response = await GetAsync($"v1/app/{appName}");
|
||||||
|
EdgegapHttpResult<GetCreateAppResult> result = new EdgegapHttpResult<GetCreateAppResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
|
||||||
|
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
||||||
|
if (!isSuccess)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PATCH to v1/app/{app_name}/version/{version_name}
|
||||||
|
/// - Update an *existing* application version with new specifications.
|
||||||
|
/// - API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/app-versions-patch
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Http info with UpdateAppVersionRequest data model
|
||||||
|
/// - Success: 200
|
||||||
|
/// </returns>
|
||||||
|
public async Task<EdgegapHttpResult<UpsertAppVersionResult>> UpdateAppVersion(UpdateAppVersionRequest request)
|
||||||
|
{
|
||||||
|
string relativePath = $"v1/app/{request.AppName}/version/{request.VersionName}";
|
||||||
|
HttpResponseMessage response = await PatchAsync(relativePath, request.ToString());
|
||||||
|
EdgegapHttpResult<UpsertAppVersionResult> result = new EdgegapHttpResult<UpsertAppVersionResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
|
||||||
|
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
||||||
|
if (!isSuccess)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// POST to v1/app/{app_name}/version
|
||||||
|
/// - Create an new application version with new specifications.
|
||||||
|
/// - API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/app-version-post
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Http info with UpdateAppVersionRequest data model
|
||||||
|
/// - Success: 200 (no result model)
|
||||||
|
/// - Fail: 409 (app already exists), 400 (reached limit)
|
||||||
|
/// </returns>
|
||||||
|
public async Task<EdgegapHttpResult<UpsertAppVersionResult>> CreateAppVersion(CreateAppVersionRequest request)
|
||||||
|
{
|
||||||
|
string relativePath = $"v1/app/{request.AppName}/version";
|
||||||
|
HttpResponseMessage response = await PostAsync(relativePath, request.ToString());
|
||||||
|
EdgegapHttpResult<UpsertAppVersionResult> result = new EdgegapHttpResult<UpsertAppVersionResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
|
||||||
|
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
||||||
|
|
||||||
|
if (!isSuccess)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endregion // API Methods
|
||||||
|
|
||||||
|
|
||||||
|
#region Chained API Methods
|
||||||
|
/// <summary>
|
||||||
|
/// PATCH and/or POST to v1/app/: Upsert an *existing* application version with new specifications.
|
||||||
|
/// - Consumes either 1 or 2 API calls: 1st tries to PATCH, then POST if PATCH fails (!exists).
|
||||||
|
/// - API POST Doc | https://docs.edgegap.com/api/#tag/Applications/operation/app-version-post
|
||||||
|
/// - API PATCH Doc | https://docs.edgegap.com/api/#tag/Applications/operation/app-versions-patch
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Http info with UpdateAppVersionRequest data model
|
||||||
|
/// - Success: 200 (no result model)
|
||||||
|
/// - Fail: 409 (app already exists), 400 (reached limit)
|
||||||
|
/// </returns>
|
||||||
|
public async Task<EdgegapHttpResult<UpsertAppVersionResult>> UpsertAppVersion(UpdateAppVersionRequest request)
|
||||||
|
{
|
||||||
|
EdgegapHttpResult<UpsertAppVersionResult> result = await UpdateAppVersion(request); // PATCH
|
||||||
|
|
||||||
|
if (result.HasErr)
|
||||||
|
{
|
||||||
|
// Try to create, instead
|
||||||
|
CreateAppVersionRequest createAppVersionRequest = CreateAppVersionRequest.FromUpdateRequest(request);
|
||||||
|
result = await CreateAppVersion(createAppVersionRequest); // POST
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSuccess = result.StatusCode == HttpStatusCode.OK; // 200
|
||||||
|
|
||||||
|
if (!isSuccess)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endregion // Chained API Methods
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapAppApi.cs.meta
Executable file
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapAppApi.cs.meta
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3b0b3b865abe64b49a4000294c4e9593
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
177
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapDeploymentsApi.cs
Executable file
177
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapDeploymentsApi.cs
Executable file
@ -0,0 +1,177 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Edgegap.Editor.Api.Models.Requests;
|
||||||
|
using Edgegap.Editor.Api.Models.Results;
|
||||||
|
using UnityEngine.Assertions;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Wraps the v1/[deploy | status | stop] API endpoints: Deployments Control API.
|
||||||
|
/// - API Doc | https://docs.edgegap.com/api/#tag/Deployments
|
||||||
|
/// </summary>
|
||||||
|
public class EdgegapDeploymentsApi : EdgegapApiBase
|
||||||
|
{
|
||||||
|
public EdgegapDeploymentsApi(
|
||||||
|
ApiEnvironment apiEnvironment,
|
||||||
|
string apiToken,
|
||||||
|
EdgegapWindowMetadata.LogLevel logLevel = EdgegapWindowMetadata.LogLevel.Error)
|
||||||
|
: base(apiEnvironment, apiToken, logLevel)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region API Methods
|
||||||
|
/// <summary>
|
||||||
|
/// POST v1/deploy
|
||||||
|
/// - Create a new deployment. Deployment is a server instance of your application version.
|
||||||
|
/// - API Doc | https://docs.edgegap.com/api/#tag/Deployments
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Http info with CreateDeploymentResult data model
|
||||||
|
/// - Success: 200
|
||||||
|
/// </returns>
|
||||||
|
public async Task<EdgegapHttpResult<CreateDeploymentResult>> CreateDeploymentAsync(
|
||||||
|
CreateDeploymentRequest request)
|
||||||
|
{
|
||||||
|
HttpResponseMessage response = await PostAsync("v1/deploy", request.ToString());
|
||||||
|
EdgegapHttpResult<CreateDeploymentResult> result = new EdgegapHttpResult<CreateDeploymentResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
|
||||||
|
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
||||||
|
if (!isSuccess)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GET v1/status/{requestId}
|
||||||
|
/// - Retrieve the information for a deployment.
|
||||||
|
/// - API Doc | https://docs.edgegap.com/api/#tag/Deployments/operation/deployment-status-get
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="requestId">
|
||||||
|
/// Unique Identifier to keep track of your request across all Arbitrium ecosystem.
|
||||||
|
/// It's included in the response of the app deploy. Ex: "93924761ccde"</param>
|
||||||
|
/// <returns>
|
||||||
|
/// Http info with GetDeploymentStatusResult data model
|
||||||
|
/// - Success: 200
|
||||||
|
/// </returns>
|
||||||
|
public async Task<EdgegapHttpResult<GetDeploymentStatusResult>> GetDeploymentStatusAsync(string requestId)
|
||||||
|
{
|
||||||
|
HttpResponseMessage response = await GetAsync($"v1/status/{requestId}");
|
||||||
|
EdgegapHttpResult<GetDeploymentStatusResult> result = new EdgegapHttpResult<GetDeploymentStatusResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
|
||||||
|
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
||||||
|
if (!isSuccess)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DELETE v1/stop/{requestId}
|
||||||
|
/// - Delete an instance of deployment. It will stop the running container and all its games.
|
||||||
|
/// - API Doc | https://docs.edgegap.com/api/#tag/Deployments/operation/deployment-status-get
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="requestId">
|
||||||
|
/// Unique Identifier to keep track of your request across all Arbitrium ecosystem.
|
||||||
|
/// It's included in the response of the app deploy. Ex: "93924761ccde"</param>
|
||||||
|
/// <returns>
|
||||||
|
/// Http info with GetDeploymentStatusResult data model
|
||||||
|
/// - Success: 200
|
||||||
|
/// </returns>
|
||||||
|
public async Task<EdgegapHttpResult<StopActiveDeploymentResult>> StopActiveDeploymentAsync(string requestId)
|
||||||
|
{
|
||||||
|
HttpResponseMessage response = await DeleteAsync($"v1/stop/{requestId}");
|
||||||
|
EdgegapHttpResult<StopActiveDeploymentResult> result = new EdgegapHttpResult<StopActiveDeploymentResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
|
||||||
|
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
||||||
|
if (!isSuccess)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endregion // API Methods
|
||||||
|
|
||||||
|
|
||||||
|
#region Chained API Methods
|
||||||
|
/// <summary>
|
||||||
|
/// POST v1/deploy => GET v1/status/{requestId}
|
||||||
|
/// - Create a new deployment. Deployment is a server instance of your application version.
|
||||||
|
/// - Then => await READY status.
|
||||||
|
/// - API Doc | https://docs.edgegap.com/api/#tag/Deployments
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Http info with CreateDeploymentResult data model (with a READY deployment status)
|
||||||
|
/// - Success: 200
|
||||||
|
/// - Error: If createResult.HasErr, returns createResult
|
||||||
|
/// </returns>
|
||||||
|
public async Task<EdgegapHttpResult<CreateDeploymentResult>> CreateDeploymentAwaitReadyStatusAsync(
|
||||||
|
CreateDeploymentRequest request, TimeSpan pollInterval)
|
||||||
|
{
|
||||||
|
EdgegapHttpResult<CreateDeploymentResult> createResponse = await CreateDeploymentAsync(request);
|
||||||
|
|
||||||
|
// Create =>
|
||||||
|
bool isCreateSuccess = createResponse.StatusCode == HttpStatusCode.OK; // 200
|
||||||
|
if (!isCreateSuccess)
|
||||||
|
return createResponse;
|
||||||
|
|
||||||
|
// Await Status READY =>
|
||||||
|
string requestId = createResponse.Data.RequestId;
|
||||||
|
_ = await AwaitReadyStatusAsync(requestId, pollInterval);
|
||||||
|
|
||||||
|
// Return no matter what the result; no need to validate
|
||||||
|
return createResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>If you recently deployed but want to await READY status.</summary>
|
||||||
|
/// <param name="requestId"></param>
|
||||||
|
/// <param name="pollInterval"></param>
|
||||||
|
public async Task<EdgegapHttpResult<GetDeploymentStatusResult>> AwaitReadyStatusAsync(
|
||||||
|
string requestId,
|
||||||
|
TimeSpan pollInterval)
|
||||||
|
{
|
||||||
|
Assert.IsTrue(!string.IsNullOrEmpty(requestId)); // Validate
|
||||||
|
|
||||||
|
EdgegapHttpResult<GetDeploymentStatusResult> statusResponse = null;
|
||||||
|
CancellationTokenSource cts = new CancellationTokenSource (TimeSpan.FromMinutes( // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
EdgegapWindowMetadata.DEPLOYMENT_AWAIT_READY_STATUS_TIMEOUT_MINS));
|
||||||
|
bool isReady = false;
|
||||||
|
|
||||||
|
while (!isReady && !cts.Token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
await Task.Delay(pollInterval, cts.Token);
|
||||||
|
statusResponse = await GetDeploymentStatusAsync(requestId);
|
||||||
|
isReady = statusResponse.Data.CurrentStatus == EdgegapWindowMetadata.READY_STATUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return statusResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>If you recently stopped a deployment, but want to await TERMINATED (410) status.</summary>
|
||||||
|
/// <param name="requestId"></param>
|
||||||
|
/// <param name="pollInterval"></param>
|
||||||
|
public async Task<EdgegapHttpResult<StopActiveDeploymentResult>> AwaitTerminatedDeleteStatusAsync(
|
||||||
|
string requestId,
|
||||||
|
TimeSpan pollInterval)
|
||||||
|
{
|
||||||
|
EdgegapHttpResult<StopActiveDeploymentResult> deleteResponse = null;
|
||||||
|
CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromMinutes( // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
EdgegapWindowMetadata.DEPLOYMENT_AWAIT_READY_STATUS_TIMEOUT_MINS));
|
||||||
|
bool isStopped = false;
|
||||||
|
|
||||||
|
while (!isStopped && !cts.Token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
await Task.Delay(pollInterval, cts.Token);
|
||||||
|
deleteResponse = await StopActiveDeploymentAsync(requestId);
|
||||||
|
isStopped = deleteResponse.StatusCode == HttpStatusCode.Gone; // 410
|
||||||
|
}
|
||||||
|
|
||||||
|
return deleteResponse;
|
||||||
|
}
|
||||||
|
#endregion Chained API Methods
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapDeploymentsApi.cs.meta
Executable file
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapDeploymentsApi.cs.meta
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 37ecdc6abda4402419438f2284ef2d95
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
47
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapIpApi.cs
Executable file
47
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapIpApi.cs
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Edgegap.Editor.Api.Models.Results;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Wraps the v1/ip API endpoint: "IP Lookup" API.
|
||||||
|
/// - API Doc | https://docs.edgegap.com/api/#tag/IP-Lookup
|
||||||
|
/// </summary>
|
||||||
|
public class EdgegapIpApi : EdgegapApiBase
|
||||||
|
{
|
||||||
|
public EdgegapIpApi(
|
||||||
|
ApiEnvironment apiEnvironment,
|
||||||
|
string apiToken,
|
||||||
|
EdgegapWindowMetadata.LogLevel logLevel = EdgegapWindowMetadata.LogLevel.Error)
|
||||||
|
: base(apiEnvironment, apiToken, logLevel)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region API Methods
|
||||||
|
/// <summary>
|
||||||
|
/// GET to v1/app
|
||||||
|
/// - Retrieve your public IP address.
|
||||||
|
/// - API Doc | https://docs.edgegap.com/api/#tag/IP-Lookup/operation/IP
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Http info with GetCreateAppResult data model
|
||||||
|
/// - Success: 200
|
||||||
|
/// - Fail: 409 (app already exists), 400 (reached limit)
|
||||||
|
/// </returns>
|
||||||
|
public async Task<EdgegapHttpResult<GetYourPublicIpResult>> GetYourPublicIp()
|
||||||
|
{
|
||||||
|
HttpResponseMessage response = await GetAsync("v1/ip");
|
||||||
|
EdgegapHttpResult<GetYourPublicIpResult> result = new EdgegapHttpResult<GetYourPublicIpResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
|
||||||
|
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
||||||
|
if (!isSuccess)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endregion // API Methods
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapIpApi.cs.meta
Executable file
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapIpApi.cs.meta
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fac4a7425623f39488af09d60549313e
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
52
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapWizardApi.cs
Executable file
52
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapWizardApi.cs
Executable file
@ -0,0 +1,52 @@
|
|||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Edgegap.Editor.Api.Models.Results;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api
|
||||||
|
{
|
||||||
|
/// <summary>Wraps the v1/wizard API endpoint. Used for internal purposes.</summary>
|
||||||
|
public class EdgegapWizardApi : EdgegapApiBase
|
||||||
|
{
|
||||||
|
/// <summary>Extended path after the base uri</summary>
|
||||||
|
public EdgegapWizardApi(
|
||||||
|
ApiEnvironment apiEnvironment,
|
||||||
|
string apiToken,
|
||||||
|
EdgegapWindowMetadata.LogLevel logLevel = EdgegapWindowMetadata.LogLevel.Error)
|
||||||
|
: base(apiEnvironment, apiToken, logLevel)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region API Methods
|
||||||
|
/// <summary>POST to v1/wizard/init-quick-start</summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Http info with no explicit data model
|
||||||
|
/// - Success: 204 (no result model)
|
||||||
|
/// </returns>
|
||||||
|
public async Task<EdgegapHttpResult> InitQuickStart()
|
||||||
|
{
|
||||||
|
string json = new JObject { ["source"] = "unity" }.ToString();
|
||||||
|
HttpResponseMessage response = await PostAsync("v1/wizard/init-quick-start", json);
|
||||||
|
EdgegapHttpResult result = new EdgegapHttpResult(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>GET to v1/wizard/registry-credentials</summary>
|
||||||
|
/// <returns>
|
||||||
|
/// - Http info with GetRegistryCredentialsResult data model
|
||||||
|
/// - Success: 200
|
||||||
|
/// - Error: Likely if called before a successful InitQuickStart(),
|
||||||
|
/// or if called in a staging env. Soon, this will be available in production.
|
||||||
|
/// </returns>
|
||||||
|
public async Task<EdgegapHttpResult<GetRegistryCredentialsResult>> GetRegistryCredentials()
|
||||||
|
{
|
||||||
|
HttpResponseMessage response = await GetAsync("v1/wizard/registry-credentials");
|
||||||
|
EdgegapHttpResult<GetRegistryCredentialsResult> result = new EdgegapHttpResult<GetRegistryCredentialsResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endregion // API Methods
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapWizardApi.cs.meta
Executable file
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/EdgegapWizardApi.cs.meta
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f6986ee67361f0b45928ccd70c7ab12c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
8
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models.meta
Executable file
8
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models.meta
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: aed107c714fce71449ef56590221c567
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
28
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/AppPortsData.cs
Executable file
28
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/AppPortsData.cs
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Used in `UpdateAppVersionRequest`, `CreateAppVersionRequest`.
|
||||||
|
/// For GetDeploymentStatusResult, see DeploymentPortsData
|
||||||
|
/// </summary>
|
||||||
|
public class AppPortsData
|
||||||
|
{
|
||||||
|
/// <summary>1024~49151; Default 7770</summary>
|
||||||
|
[JsonProperty("port")]
|
||||||
|
public int Port { get; set; } = EdgegapWindowMetadata.PORT_DEFAULT;
|
||||||
|
|
||||||
|
/// <summary>Default "UDP"</summary>
|
||||||
|
[JsonProperty("protocol")]
|
||||||
|
public string ProtocolStr { get; set; } = EdgegapWindowMetadata.DEFAULT_PROTOCOL_TYPE.ToString();
|
||||||
|
|
||||||
|
[JsonProperty("to_check")]
|
||||||
|
public bool ToCheck { get; set; } = true;
|
||||||
|
|
||||||
|
[JsonProperty("tls_upgrade")]
|
||||||
|
public bool TlsUpgrade { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string PortName { get; set; } = "Game Port";
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/AppPortsData.cs.meta
Executable file
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/AppPortsData.cs.meta
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b6d4864ea3706574fb35920c6fab46fa
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
29
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/DeploymentPortsData.cs
Executable file
29
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/DeploymentPortsData.cs
Executable file
@ -0,0 +1,29 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models
|
||||||
|
{
|
||||||
|
/// <summary>Used in `GetDeploymentStatus`.</summary>
|
||||||
|
public class DeploymentPortsData
|
||||||
|
{
|
||||||
|
[JsonProperty("external")]
|
||||||
|
public int External { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("internal")]
|
||||||
|
public int Internal { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("protocol")]
|
||||||
|
public string Protocol { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string PortName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("tls_upgrade")]
|
||||||
|
public bool TlsUpgrade { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("link")]
|
||||||
|
public string Link { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("proxy")]
|
||||||
|
public int? Proxy { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 62d51b44b8414c9f968ca607ccb06b7e
|
||||||
|
timeCreated: 1701522748
|
28
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/LocationData.cs
Executable file
28
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/LocationData.cs
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models
|
||||||
|
{
|
||||||
|
public class LocationData
|
||||||
|
{
|
||||||
|
[JsonProperty("city")]
|
||||||
|
public string City { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("country")]
|
||||||
|
public string Country { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("continent")]
|
||||||
|
public string Continent { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("administrative_division")]
|
||||||
|
public string AdministrativeDivision { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("timezone")]
|
||||||
|
public string Timezone { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("latitude")]
|
||||||
|
public double Latitude { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("longitude")]
|
||||||
|
public double Longitude { get; set; }
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/LocationData.cs.meta
Executable file
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/LocationData.cs.meta
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 57eed0dbd556e074c992cf6599a1f6bd
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
15
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/ProtocolType.cs
Executable file
15
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/ProtocolType.cs
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
namespace Edgegap.Editor.Api.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unity default: UDP.
|
||||||
|
/// (!) UDP !works in WebGL.
|
||||||
|
/// </summary>
|
||||||
|
public enum ProtocolType
|
||||||
|
{
|
||||||
|
/// <summary>Unity default - fastest; !works in WebGL.</summary>
|
||||||
|
UDP,
|
||||||
|
|
||||||
|
/// <summary>Slower, but more reliable; works in WebGL.</summary>
|
||||||
|
TCP,
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/ProtocolType.cs.meta
Executable file
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/ProtocolType.cs.meta
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: be5acd63e783b364ebdbb783639e2d32
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
8
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/Requests.meta
Executable file
8
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/Requests.meta
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d1b2a5c481353934f906c30ba047df9b
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
55
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/Requests/CreateAppRequest.cs
Executable file
55
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/Requests/CreateAppRequest.cs
Executable file
@ -0,0 +1,55 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models.Requests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Request model for https://docs.edgegap.com/api/#tag/Applications/operation/application-post
|
||||||
|
/// </summary>
|
||||||
|
public class CreateAppRequest
|
||||||
|
{
|
||||||
|
#region Required
|
||||||
|
/// <summary>*The application name.</summary>
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string AppName { get; set; }
|
||||||
|
#endregion // Required
|
||||||
|
|
||||||
|
|
||||||
|
#region Optional
|
||||||
|
/// <summary>*If the application can be deployed.</summary>
|
||||||
|
[JsonProperty("is_active")]
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
|
||||||
|
/// <summary>*Image base64 string.</summary>
|
||||||
|
[JsonProperty("image")]
|
||||||
|
public string Image { get; set; }
|
||||||
|
|
||||||
|
/// <summary>If the telemetry agent is installed on the versions of this app.</summary>
|
||||||
|
[JsonProperty("is_telemetry_agent_active")]
|
||||||
|
public bool IsTelemetryAgentActive { get; set; }
|
||||||
|
#endregion // Optional
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>Used by Newtonsoft</summary>
|
||||||
|
public CreateAppRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Init with required info</summary>
|
||||||
|
/// <param name="appName">The application name</param>
|
||||||
|
/// <param name="isActive">If the application can be deployed</param>
|
||||||
|
/// <param name="image">Image base64 string</param>
|
||||||
|
public CreateAppRequest(
|
||||||
|
string appName,
|
||||||
|
bool isActive,
|
||||||
|
string image)
|
||||||
|
{
|
||||||
|
this.AppName = appName;
|
||||||
|
this.IsActive = isActive;
|
||||||
|
this.Image = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Parse to json str</summary>
|
||||||
|
public override string ToString() =>
|
||||||
|
JsonConvert.SerializeObject(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0a492d7c515b8894ea30b37db6b7efe4
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,225 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models.Requests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Request model for `POST v1/app/{app_name}/version`.
|
||||||
|
/// API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/app-version-post
|
||||||
|
/// </summary>
|
||||||
|
public class CreateAppVersionRequest
|
||||||
|
{
|
||||||
|
#region Required
|
||||||
|
/// <summary>*The name of the application associated.</summary>
|
||||||
|
[JsonIgnore] // *Path var
|
||||||
|
public string AppName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>*The name of the application associated.</summary>
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string VersionName { get; set; } = EdgegapWindowMetadata.DEFAULT_VERSION_TAG;
|
||||||
|
|
||||||
|
/// <summary>*The tag of your image. Default == "latest".</summary>
|
||||||
|
/// <example>"0.1.2" || "latest" (although "latest" !recommended; use actual versions in production)</example>
|
||||||
|
[JsonProperty("docker_tag")]
|
||||||
|
public string DockerTag { get; set; } = EdgegapWindowMetadata.DEFAULT_VERSION_TAG;
|
||||||
|
|
||||||
|
/// <summary>*The name of your image.</summary>
|
||||||
|
/// <example>"edgegap/demo" || "myCompany-someId/mylowercaseapp"</example>
|
||||||
|
[JsonProperty("docker_image")]
|
||||||
|
public string DockerImage { get; set; } = "";
|
||||||
|
|
||||||
|
/// <summary>*The Repository where the image is.</summary>
|
||||||
|
/// <example>"registry.edgegap.com" || "harbor.edgegap.com" || "docker.io"</example>
|
||||||
|
[JsonProperty("docker_repository")]
|
||||||
|
public string DockerRepository { get; set; } = "";
|
||||||
|
|
||||||
|
/// <summary>*Units of vCPU needed (1024 = 1vcpu)</summary>
|
||||||
|
[JsonProperty("req_cpu")]
|
||||||
|
public int ReqCpu { get; set; } = 256;
|
||||||
|
|
||||||
|
/// <summary>*Units of memory in MB needed (1024 = 1 GPU)</summary>
|
||||||
|
[JsonProperty("req_memory")]
|
||||||
|
public int ReqMemory { get; set; } = 256;
|
||||||
|
|
||||||
|
/// <summary>*Required: At least 1 { Port, ProtocolStr }.</summary>
|
||||||
|
[JsonProperty("ports")]
|
||||||
|
public AppPortsData[] Ports { get; set; } = {};
|
||||||
|
|
||||||
|
/// <summary>The username to access the docker repository</summary>
|
||||||
|
[JsonProperty("private_username")]
|
||||||
|
public string PrivateUsername { get; set; } = "";
|
||||||
|
|
||||||
|
/// <summary>The Private Password or Token of the username (We recommend to use a token)</summary>
|
||||||
|
[JsonProperty("private_token")]
|
||||||
|
public string PrivateToken { get; set; } = "";
|
||||||
|
#endregion // Required
|
||||||
|
|
||||||
|
|
||||||
|
// #region Optional
|
||||||
|
// [JsonProperty("is_active")]
|
||||||
|
// public bool IsActive { get; set; } = true;
|
||||||
|
//
|
||||||
|
// [JsonProperty("req_video")]
|
||||||
|
// public int ReqVideo { get; set; } = 256;
|
||||||
|
//
|
||||||
|
// [JsonProperty("max_duration")]
|
||||||
|
// public int MaxDuration { get; set; } = 30;
|
||||||
|
//
|
||||||
|
// [JsonProperty("use_telemetry")]
|
||||||
|
// public bool UseTelemetry { get; set; } = true;
|
||||||
|
//
|
||||||
|
// [JsonProperty("inject_context_env")]
|
||||||
|
// public bool InjectContextEnv { get; set; } = true;
|
||||||
|
//
|
||||||
|
// [JsonProperty("whitelisting_active")]
|
||||||
|
// public bool WhitelistingActive { get; set; } = true;
|
||||||
|
//
|
||||||
|
// [JsonProperty("force_cache")]
|
||||||
|
// public bool ForceCache { get; set; }
|
||||||
|
//
|
||||||
|
// [JsonProperty("cache_min_hour")]
|
||||||
|
// public int CacheMinHour { get; set; }
|
||||||
|
//
|
||||||
|
// [JsonProperty("cache_max_hour")]
|
||||||
|
// public int CacheMaxHour { get; set; }
|
||||||
|
//
|
||||||
|
// [JsonProperty("time_to_deploy")]
|
||||||
|
// public int TimeToDeploy { get; set; } = 15;
|
||||||
|
//
|
||||||
|
// [JsonProperty("enable_all_locations")]
|
||||||
|
// public bool EnableAllLocations { get; set; }
|
||||||
|
//
|
||||||
|
// [JsonProperty("termination_grace_period_seconds")]
|
||||||
|
// public int TerminationGracePeriodSeconds { get; set; } = 5;
|
||||||
|
//
|
||||||
|
// [JsonProperty("endpoint_storage")]
|
||||||
|
// public string EndpointStorage { get; set; } = "";
|
||||||
|
//
|
||||||
|
// [JsonProperty("command")]
|
||||||
|
// public string Command { get; set; }
|
||||||
|
//
|
||||||
|
// [JsonProperty("arguments")]
|
||||||
|
// public string Arguments { get; set; }
|
||||||
|
//
|
||||||
|
// [JsonProperty("verify_image")]
|
||||||
|
// public bool VerifyImage { get; set; }
|
||||||
|
//
|
||||||
|
// [JsonProperty("session_config")]
|
||||||
|
// public SessionConfigData SessionConfig { get; set; } = new();
|
||||||
|
//
|
||||||
|
// [JsonProperty("probe")]
|
||||||
|
// public ProbeData Probe { get; set; } = new();
|
||||||
|
//
|
||||||
|
// [JsonProperty("envs")]
|
||||||
|
// public EnvsData[] Envs { get; set; } = {};
|
||||||
|
//
|
||||||
|
// public class SessionConfigData
|
||||||
|
// {
|
||||||
|
// [JsonProperty("kind")]
|
||||||
|
// public string Kind { get; set; } = "Seat";
|
||||||
|
//
|
||||||
|
// [JsonProperty("sockets")]
|
||||||
|
// public int Sockets { get; set; } = 10;
|
||||||
|
//
|
||||||
|
// [JsonProperty("autodeploy")]
|
||||||
|
// public bool Autodeploy { get; set; } = true;
|
||||||
|
//
|
||||||
|
// [JsonProperty("empty_ttl")]
|
||||||
|
// public int EmptyTtl { get; set; } = 60;
|
||||||
|
//
|
||||||
|
// [JsonProperty("session_max_duration")]
|
||||||
|
// public int SessionMaxDuration { get; set; } = 60;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// public class ProbeData
|
||||||
|
// {
|
||||||
|
// [JsonProperty("optimal_ping")]
|
||||||
|
// public int OptimalPing { get; set; } = 60;
|
||||||
|
//
|
||||||
|
// [JsonProperty("rejected_ping")]
|
||||||
|
// public int RejectedPing { get; set; } = 180;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public class EnvsData
|
||||||
|
// {
|
||||||
|
// [JsonProperty("key")]
|
||||||
|
// public string Key { get; set; }
|
||||||
|
//
|
||||||
|
// [JsonProperty("value")]
|
||||||
|
// public string Value { get; set; }
|
||||||
|
//
|
||||||
|
// [JsonProperty("is_secret")]
|
||||||
|
// public bool IsSecret { get; set; } = true;
|
||||||
|
// }
|
||||||
|
// #endregion // Optional
|
||||||
|
|
||||||
|
/// <summary>Used by Newtonsoft</summary>
|
||||||
|
public CreateAppVersionRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Init with required info.
|
||||||
|
/// (!) If looking for refs, also see FromUpdateRequest() builder below.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="appName">The name of the application.</param>
|
||||||
|
/// <param name="containerRegistryUsername"></param>
|
||||||
|
/// <param name="containerRegistryPasswordToken"></param>
|
||||||
|
/// <param name="portNum"></param>
|
||||||
|
/// <param name="protocolType"></param>
|
||||||
|
public CreateAppVersionRequest(
|
||||||
|
string appName,
|
||||||
|
string containerRegistryUsername,
|
||||||
|
string containerRegistryPasswordToken,
|
||||||
|
int portNum,
|
||||||
|
ProtocolType protocolType)
|
||||||
|
{
|
||||||
|
this.AppName = appName;
|
||||||
|
this.PrivateUsername = containerRegistryUsername;
|
||||||
|
this.PrivateToken = containerRegistryPasswordToken;
|
||||||
|
this.Ports = new AppPortsData[]
|
||||||
|
{
|
||||||
|
new AppPortsData() // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
{
|
||||||
|
Port = portNum,
|
||||||
|
ProtocolStr = protocolType.ToString(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Port from Update PATCH model: If you tried to Update, but !exists, you probably want to create it next.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="updateRequest"></param>
|
||||||
|
public static CreateAppVersionRequest FromUpdateRequest(UpdateAppVersionRequest updateRequest)
|
||||||
|
{
|
||||||
|
// Convert the updateRequest to JSON
|
||||||
|
string json = JsonConvert.SerializeObject(updateRequest);
|
||||||
|
|
||||||
|
// Deserialize the JSON back to CreateAppVersionRequest
|
||||||
|
CreateAppVersionRequest createReq = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
createReq = JsonConvert.DeserializeObject<CreateAppVersionRequest>(json);
|
||||||
|
createReq.AppName = updateRequest.AppName; // Normally JsonIgnored in Update
|
||||||
|
createReq.VersionName = updateRequest.VersionName; // Normally JsonIgnored in Update
|
||||||
|
createReq.PrivateUsername = updateRequest.PrivateUsername;
|
||||||
|
createReq.PrivateToken = updateRequest.PrivateToken;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Error (when parsing CreateAppVersionRequest from CreateAppVersionRequest): {e}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return createReq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Parse to json str</summary>
|
||||||
|
public override string ToString() =>
|
||||||
|
JsonConvert.SerializeObject(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0bb645e2f9d04384a85739269cc8a4e1
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,63 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models.Requests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Request model for `POST v1/deploy`.
|
||||||
|
/// API Doc | https://docs.edgegap.com/api/#tag/Deployments/operation/deploy
|
||||||
|
/// </summary>
|
||||||
|
public class CreateDeploymentRequest
|
||||||
|
{
|
||||||
|
#region Required
|
||||||
|
/// <summary>*Required: The name of the App you want to deploy.</summary>
|
||||||
|
[JsonProperty("app_name")]
|
||||||
|
public string AppName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// *Required: The name of the App Version you want to deploy;
|
||||||
|
/// if not present, the last version created is picked.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("version_name")]
|
||||||
|
public string VersionName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// *Required: The List of IP of your user.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("ip_list")]
|
||||||
|
public string[] IpList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// *Required: The list of IP of your user with their location (latitude, longitude).
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("geo_ip_list")]
|
||||||
|
public string[] GeoIpList { get; set; } = {};
|
||||||
|
#endregion // Required
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>Used by Newtonsoft</summary>
|
||||||
|
public CreateDeploymentRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Init with required info; used for a single external IP address.</summary>
|
||||||
|
/// <param name="appName">The name of the application.</param>
|
||||||
|
/// <param name="versionName">
|
||||||
|
/// The name of the App Version you want to deploy, if not present,
|
||||||
|
/// the last version created is picked.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="externalIp">Obtain from IpApi.</param>
|
||||||
|
public CreateDeploymentRequest(
|
||||||
|
string appName,
|
||||||
|
string versionName,
|
||||||
|
string externalIp)
|
||||||
|
{
|
||||||
|
this.AppName = appName;
|
||||||
|
this.VersionName = versionName;
|
||||||
|
this.IpList = new[] { externalIp };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Parse to json str</summary>
|
||||||
|
public override string ToString() =>
|
||||||
|
JsonConvert.SerializeObject(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: aae7b317093230e419bc0f8be1097ea6
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,175 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models.Requests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Request model for `PATCH v1/app/{app_name}/version/{version_name}`.
|
||||||
|
/// Request model for https://docs.edgegap.com/api/#tag/Applications/operation/app-versions-patch
|
||||||
|
/// TODO: Split "Create" and "Update" into their own, separate models: CTRL+F for "(!)" for more info.
|
||||||
|
/// </summary>
|
||||||
|
public class UpdateAppVersionRequest
|
||||||
|
{
|
||||||
|
#region Required
|
||||||
|
/// <summary>*Required: The name of the application.</summary>
|
||||||
|
[JsonIgnore] // *Path var
|
||||||
|
public string AppName { get; set; }
|
||||||
|
#endregion // Required
|
||||||
|
|
||||||
|
|
||||||
|
#region Optional
|
||||||
|
/// <summary>The name of the application version.</summary>
|
||||||
|
[JsonIgnore] // *Path var
|
||||||
|
public string VersionName { get; set; } = EdgegapWindowMetadata.DEFAULT_VERSION_TAG;
|
||||||
|
|
||||||
|
/// <summary>At least 1 { Port, ProtocolStr }</summary>
|
||||||
|
[JsonProperty("ports")]
|
||||||
|
public AppPortsData[] Ports { get; set; } = {};
|
||||||
|
|
||||||
|
/// <summary>The Repository where the image is.</summary>
|
||||||
|
/// <example>"registry.edgegap.com" || "harbor.edgegap.com" || "docker.io"</example>
|
||||||
|
[JsonProperty("docker_repository")]
|
||||||
|
public string DockerRepository { get; set; } = "";
|
||||||
|
|
||||||
|
/// <summary>The name of your image.</summary>
|
||||||
|
/// <example>"edgegap/demo" || "myCompany-someId/mylowercaseapp"</example>
|
||||||
|
[JsonProperty("docker_image")]
|
||||||
|
public string DockerImage { get; set; } = "";
|
||||||
|
|
||||||
|
/// <summary>The tag of your image. Default == "latest".</summary>
|
||||||
|
/// <example>"0.1.2" || "latest" (although "latest" !recommended; use actual versions in production)</example>
|
||||||
|
[JsonProperty("docker_tag")]
|
||||||
|
public string DockerTag { get; set; } = EdgegapWindowMetadata.DEFAULT_VERSION_TAG;
|
||||||
|
|
||||||
|
[JsonProperty("is_active")]
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
|
||||||
|
[JsonProperty("private_username")]
|
||||||
|
public string PrivateUsername { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonProperty("private_token")]
|
||||||
|
public string PrivateToken { get; set; } = "";
|
||||||
|
|
||||||
|
#region (!) Shows in API docs for PATCH, but could be CREATE only? "Unknown Args"
|
||||||
|
// [JsonProperty("req_cpu")]
|
||||||
|
// public int ReqCpu { get; set; } = 256;
|
||||||
|
//
|
||||||
|
// [JsonProperty("req_memory")]
|
||||||
|
// public int ReqMemory { get; set; } = 256;
|
||||||
|
//
|
||||||
|
// [JsonProperty("req_video")]
|
||||||
|
// public int ReqVideo { get; set; } = 256;
|
||||||
|
#endregion // (!) Shows in API docs for PATCH, but could be CREATE only? "Unknown Args"
|
||||||
|
|
||||||
|
[JsonProperty("max_duration")]
|
||||||
|
public int MaxDuration { get; set; } = 30;
|
||||||
|
|
||||||
|
[JsonProperty("use_telemetry")]
|
||||||
|
public bool UseTelemetry { get; set; } = true;
|
||||||
|
|
||||||
|
[JsonProperty("inject_context_env")]
|
||||||
|
public bool InjectContextEnv { get; set; } = true;
|
||||||
|
|
||||||
|
[JsonProperty("whitelisting_active")]
|
||||||
|
public bool WhitelistingActive { get; set; } = true;
|
||||||
|
|
||||||
|
[JsonProperty("force_cache")]
|
||||||
|
public bool ForceCache { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("cache_min_hour")]
|
||||||
|
public int CacheMinHour { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("cache_max_hour")]
|
||||||
|
public int CacheMaxHour { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("time_to_deploy")]
|
||||||
|
public int TimeToDeploy { get; set; } = 15;
|
||||||
|
|
||||||
|
[JsonProperty("enable_all_locations")]
|
||||||
|
public bool EnableAllLocations { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("termination_grace_period_seconds")]
|
||||||
|
public int TerminationGracePeriodSeconds { get; set; } = 5;
|
||||||
|
|
||||||
|
// // (!) BUG: Expects empty string "" at minimum; however, empty string will throw server err
|
||||||
|
// [JsonProperty("endpoint_storage")]
|
||||||
|
// public string EndpointStorage { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("command")]
|
||||||
|
public string Command { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("arguments")]
|
||||||
|
public string Arguments { get; set; }
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// (!) Setting this will trigger a very specific type of game that will affect the AppVersion.
|
||||||
|
// /// TODO: Is leaving as null the same as commenting out?
|
||||||
|
// /// </summary>
|
||||||
|
// [JsonProperty("session_config")]
|
||||||
|
// public SessionConfigData SessionConfig { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("probe")]
|
||||||
|
public ProbeData Probe { get; set; } = new ProbeData(); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
||||||
|
|
||||||
|
[JsonProperty("envs")]
|
||||||
|
public EnvsData[] Envs { get; set; } = {};
|
||||||
|
|
||||||
|
public class SessionConfigData
|
||||||
|
{
|
||||||
|
[JsonProperty("kind")]
|
||||||
|
public string Kind { get; set; } = "Seat";
|
||||||
|
|
||||||
|
[JsonProperty("sockets")]
|
||||||
|
public int Sockets { get; set; } = 10;
|
||||||
|
|
||||||
|
[JsonProperty("autodeploy")]
|
||||||
|
public bool Autodeploy { get; set; } = true;
|
||||||
|
|
||||||
|
[JsonProperty("empty_ttl")]
|
||||||
|
public int EmptyTtl { get; set; } = 60;
|
||||||
|
|
||||||
|
[JsonProperty("session_max_duration")]
|
||||||
|
public int SessionMaxDuration { get; set; } = 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ProbeData
|
||||||
|
{
|
||||||
|
[JsonProperty("optimal_ping")]
|
||||||
|
public int OptimalPing { get; set; } = 60;
|
||||||
|
|
||||||
|
[JsonProperty("rejected_ping")]
|
||||||
|
public int RejectedPing { get; set; } = 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EnvsData
|
||||||
|
{
|
||||||
|
[JsonProperty("key")]
|
||||||
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("value")]
|
||||||
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("is_secret")]
|
||||||
|
public bool IsSecret { get; set; } = true;
|
||||||
|
}
|
||||||
|
#endregion // Optional
|
||||||
|
|
||||||
|
/// <summary>Used by Newtonsoft</summary>
|
||||||
|
public UpdateAppVersionRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Init with required info. Default version/tag == "default".
|
||||||
|
/// Since we're updating, we only require the AppName.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="appName">The name of the application.</param>
|
||||||
|
public UpdateAppVersionRequest(string appName)
|
||||||
|
{
|
||||||
|
this.AppName = appName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Parse to json str</summary>
|
||||||
|
public override string ToString() =>
|
||||||
|
JsonConvert.SerializeObject(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8da9712633ee1e64faca0b960d4bed31
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
8
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/Results.meta
Executable file
8
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/Results.meta
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: aa4ceffbc97b8254885a63937def2324
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,53 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models.Results
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Result model for `POST v1/deploy`.
|
||||||
|
/// </summary>
|
||||||
|
public class CreateDeploymentResult
|
||||||
|
{
|
||||||
|
[JsonProperty("request_id")]
|
||||||
|
public string RequestId { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("request_dns")]
|
||||||
|
public string RequestDns { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("request_app")]
|
||||||
|
public string RequestApp { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("request_version")]
|
||||||
|
public string RequestVersion { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("request_user_count")]
|
||||||
|
public int RequestUserCount { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("city")]
|
||||||
|
public string City { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("country")]
|
||||||
|
public string Country { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("continent")]
|
||||||
|
public string Continent { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("administrative_division")]
|
||||||
|
public string AdministrativeDivision { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("tags")]
|
||||||
|
public string[] Tags { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("container_log_storage")]
|
||||||
|
public ContainerLogStorageData ContainerLogStorage { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public class ContainerLogStorageData
|
||||||
|
{
|
||||||
|
[JsonProperty("enabled")]
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("endpoint_storage")]
|
||||||
|
public string EndpointStorage { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8361abc6f84fccd4cba26dc285d335dd
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,12 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models.Results
|
||||||
|
{
|
||||||
|
/// <summary>Edgegap error, generally just containing `message`</summary>
|
||||||
|
public class EdgegapErrorResult
|
||||||
|
{
|
||||||
|
/// <summary>Friendly, UI-facing error message from Edgegap; can be lengthy.</summary>
|
||||||
|
[JsonProperty("message")]
|
||||||
|
public string ErrorMessage { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5b29093cb10cf3040b76f4fbe77a435d
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
118
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/Results/EdgegapHttpResult.cs
Executable file
118
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/Results/EdgegapHttpResult.cs
Executable file
@ -0,0 +1,118 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models.Results
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Wraps the inner json data with outer http info.
|
||||||
|
/// This class overload contains no json-deserialiable data result.
|
||||||
|
/// </summary>
|
||||||
|
public class EdgegapHttpResult
|
||||||
|
{
|
||||||
|
/// <summary>HTTP Status code for the request.</summary>
|
||||||
|
public HttpStatusCode StatusCode { get; }
|
||||||
|
|
||||||
|
/// <summary>This could be err, success, or null.</summary>
|
||||||
|
public string Json { get; }
|
||||||
|
|
||||||
|
/// <summary>eg: "POST"</summary>
|
||||||
|
public HttpMethod HttpMethod;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Typically is sent by servers together with the status code.
|
||||||
|
/// Useful for fallback err descriptions, often based on the status code.
|
||||||
|
/// </summary>
|
||||||
|
public string ReasonPhrase { get; }
|
||||||
|
|
||||||
|
/// <summary>Contains `message` with friendly info.</summary>
|
||||||
|
public bool HasErr => Error != null;
|
||||||
|
public EdgegapErrorResult Error { get; set; }
|
||||||
|
|
||||||
|
#region Common Shortcuts
|
||||||
|
/// <summary>OK</summary>
|
||||||
|
public bool IsResultCode200 => StatusCode == HttpStatusCode.OK;
|
||||||
|
|
||||||
|
/// <summary>NoContent</summary>
|
||||||
|
public bool IsResultCode204 => StatusCode == HttpStatusCode.NoContent;
|
||||||
|
|
||||||
|
/// <summary>Forbidden</summary>
|
||||||
|
public bool IsResultCode403 => StatusCode == HttpStatusCode.Forbidden;
|
||||||
|
|
||||||
|
/// <summary>Conflict</summary>
|
||||||
|
public bool IsResultCode409 => StatusCode == HttpStatusCode.Conflict;
|
||||||
|
|
||||||
|
/// <summary>BadRequest</summary>
|
||||||
|
public bool IsResultCode400 => StatusCode == HttpStatusCode.BadRequest;
|
||||||
|
|
||||||
|
/// <summary>Gone</summary>
|
||||||
|
public bool IsResultCode410 => StatusCode == HttpStatusCode.Gone;
|
||||||
|
#endregion // Common Shortcuts
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor that initializes the class based on an HttpResponseMessage.
|
||||||
|
/// </summary>
|
||||||
|
public EdgegapHttpResult(HttpResponseMessage httpResponse)
|
||||||
|
{
|
||||||
|
this.ReasonPhrase = httpResponse.ReasonPhrase;
|
||||||
|
this.StatusCode = httpResponse.StatusCode;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// TODO: This can be read async with `await`, but can't do this in a Constructor.
|
||||||
|
// Instead, make a factory builder Task =>
|
||||||
|
this.Json = httpResponse.Content.ReadAsStringAsync().Result;
|
||||||
|
|
||||||
|
this.Error = JsonConvert.DeserializeObject<EdgegapErrorResult>(Json);
|
||||||
|
if (Error != null && string.IsNullOrEmpty(Error.ErrorMessage))
|
||||||
|
Error = null;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError("Error (reading httpResponse.Content): Client expected json, " +
|
||||||
|
$"but server returned !json: {e} - ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wraps the inner json data with outer http info.
|
||||||
|
/// This class overload contains json-deserialiable data result.
|
||||||
|
/// </summary>
|
||||||
|
public class EdgegapHttpResult<TResult> : EdgegapHttpResult
|
||||||
|
{
|
||||||
|
/// <summary>The actual result model from Json. Could be null!</summary>
|
||||||
|
public TResult Data { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public EdgegapHttpResult(HttpResponseMessage httpResponse, bool isLogLevelDebug = false)
|
||||||
|
: base(httpResponse)
|
||||||
|
{
|
||||||
|
this.HttpMethod = httpResponse.RequestMessage.Method;
|
||||||
|
|
||||||
|
// Assuming JSON content and using Newtonsoft.Json for deserialization
|
||||||
|
bool isDeserializable = httpResponse.Content != null &&
|
||||||
|
httpResponse.Content.Headers.ContentType.MediaType == "application/json";
|
||||||
|
|
||||||
|
if (isDeserializable)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.Data = JsonConvert.DeserializeObject<TResult>(Json);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Error (deserializing EdgegapHttpResult.Data): {e} - json: {Json}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLogLevelDebug)
|
||||||
|
UnityEngine.Debug.Log($"{typeof(TResult).Name} result: {JObject.Parse(Json)}"); // Prettified
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 888bfc2c113487b44a3103648d2c2ae3
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,31 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models.Results
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Result model for `[GET | POST] v1/app`.
|
||||||
|
/// POST API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/application-post
|
||||||
|
/// GET API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/application-get
|
||||||
|
/// </summary>
|
||||||
|
public class GetCreateAppResult
|
||||||
|
{
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string AppName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("is_active")]
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Optional</summary>
|
||||||
|
[JsonProperty("is_telemetry_agent_active")]
|
||||||
|
public bool IsTelemetryAgentActive { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("image")]
|
||||||
|
public string Image { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("create_time")]
|
||||||
|
public string CreateTimeStr { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("last_updated")]
|
||||||
|
public string LastUpdatedStr { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a66c935238edd8846b1e9e9e19cfab70
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,89 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models.Results
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Result model for `GET v1/status/{request_id}`.
|
||||||
|
/// API Doc | https://docs.edgegap.com/api/#tag/Deployments/operation/deployment-status-get
|
||||||
|
/// </summary>
|
||||||
|
public class GetDeploymentStatusResult
|
||||||
|
{
|
||||||
|
[JsonProperty("request_id")]
|
||||||
|
public string RequestId { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("fqdn")]
|
||||||
|
public string Fqdn { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("app_name")]
|
||||||
|
public string AppName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("app_version")]
|
||||||
|
public string AppVersion { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("current_status")]
|
||||||
|
public string CurrentStatus { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("running")]
|
||||||
|
public bool Running { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("whitelisting_active")]
|
||||||
|
public bool WhitelistingActive { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("start_time")]
|
||||||
|
public string StartTime { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("removal_time")]
|
||||||
|
public string RemovalTime { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("elapsed_time")]
|
||||||
|
public int? ElapsedTime { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("last_status")]
|
||||||
|
public string LastStatus { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("error")]
|
||||||
|
public bool Error { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("error_detail")]
|
||||||
|
public string ErrorDetail { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("public_ip")]
|
||||||
|
public string PublicIp { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sessions")]
|
||||||
|
public SessionData[] Sessions { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("location")]
|
||||||
|
public LocationData Location { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("tags")]
|
||||||
|
public string[] Tags { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sockets")]
|
||||||
|
public string Sockets { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sockets_usage")]
|
||||||
|
public string SocketsUsage { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("command")]
|
||||||
|
public string Command { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("arguments")]
|
||||||
|
public string Arguments { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TODO: Server should swap `ports` to an array of DeploymentPortsData (instead of an object of dynamic unknown objects).
|
||||||
|
/// <example>
|
||||||
|
/// {
|
||||||
|
/// "7777", {}
|
||||||
|
/// },
|
||||||
|
/// {
|
||||||
|
/// "Some Port Name", {}
|
||||||
|
/// }
|
||||||
|
/// </example>
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("ports")]
|
||||||
|
public Dictionary<string, DeploymentPortsData> PortsDict { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c658b7f5c5d5d0648934b0ae1d71de9a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,22 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models.Results
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Result model for `GET v1/wizard/registry-credentials`.
|
||||||
|
/// </summary>
|
||||||
|
public class GetRegistryCredentialsResult
|
||||||
|
{
|
||||||
|
[JsonProperty("registry_url")]
|
||||||
|
public string RegistryUrl { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("project")]
|
||||||
|
public string Project { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("username")]
|
||||||
|
public string Username { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("token")]
|
||||||
|
public string Token { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8e6af130c329d2b43b2f4b0dc8639477
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,14 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models.Results
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Result model for `GET v1/ip`.
|
||||||
|
/// GET API Doc | https://docs.edgegap.com/api/#tag/IP-Lookup/operation/IP
|
||||||
|
/// </summary>
|
||||||
|
public class GetYourPublicIpResult
|
||||||
|
{
|
||||||
|
[JsonProperty("public_ip")]
|
||||||
|
public string PublicIp { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 73c9651ef0fdfcb449ec0120016963a0
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,89 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models.Results
|
||||||
|
{
|
||||||
|
public class StopActiveDeploymentResult
|
||||||
|
{
|
||||||
|
[JsonProperty("message")]
|
||||||
|
public string Message { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("deployment_summary")]
|
||||||
|
public DeploymentSummaryData DeploymentSummary { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public class DeploymentSummaryData
|
||||||
|
{
|
||||||
|
[JsonProperty("request_id")]
|
||||||
|
public string RequestId { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("fqdn")]
|
||||||
|
public string Fqdn { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("app_name")]
|
||||||
|
public string AppName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("app_version")]
|
||||||
|
public string AppVersion { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("current_status")]
|
||||||
|
public string CurrentStatus { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("running")]
|
||||||
|
public bool Running { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("whitelisting_active")]
|
||||||
|
public bool WhitelistingActive { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("start_time")]
|
||||||
|
public string StartTime { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("removal_time")]
|
||||||
|
public string RemovalTime { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("elapsed_time")]
|
||||||
|
public int ElapsedTime { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("last_status")]
|
||||||
|
public string LastStatus { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("error")]
|
||||||
|
public bool Error { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("error_detail")]
|
||||||
|
public string ErrorDetail { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("ports")]
|
||||||
|
public PortsData Ports { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("public_ip")]
|
||||||
|
public string PublicIp { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sessions")]
|
||||||
|
public SessionData[] Sessions { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("location")]
|
||||||
|
public LocationData Location { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("tags")]
|
||||||
|
public string[] Tags { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sockets")]
|
||||||
|
public string Sockets { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sockets_usage")]
|
||||||
|
public string SocketsUsage { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("command")]
|
||||||
|
public string Command { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("arguments")]
|
||||||
|
public string Arguments { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PortsData
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9e2e4d9424ca8f7459803e631acf912f
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,165 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models.Results
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Result model for:
|
||||||
|
/// - `POST 1/app/{app_name}/version`
|
||||||
|
/// - `PATCH v1/app/{app_name}/version/{version_name}`
|
||||||
|
/// POST API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/application-post
|
||||||
|
/// PATCH API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/app-versions-patch
|
||||||
|
/// </summary>
|
||||||
|
public class UpsertAppVersionResult
|
||||||
|
{
|
||||||
|
[JsonProperty("success")]
|
||||||
|
public bool Success { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("version")]
|
||||||
|
public VersionData Version { get; set; }
|
||||||
|
|
||||||
|
public class VersionData
|
||||||
|
{
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string VersionName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("is_active")]
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("docker_repository")]
|
||||||
|
public string DockerRepository { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("docker_image")]
|
||||||
|
public string DockerImage { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("docker_tag")]
|
||||||
|
public string DockerTag { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("private_username")]
|
||||||
|
public string PrivateUsername { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("private_token")]
|
||||||
|
public string PrivateToken { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("req_cpu")]
|
||||||
|
public int? ReqCpu { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("req_memory")]
|
||||||
|
public int? ReqMemory { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("req_video")]
|
||||||
|
public int? ReqVideo { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("max_duration")]
|
||||||
|
public int? MaxDuration { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("use_telemetry")]
|
||||||
|
public bool UseTelemetry { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("inject_context_env")]
|
||||||
|
public bool InjectContextEnv { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("whitelisting_active")]
|
||||||
|
public bool WhitelistingActive { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("force_cache")]
|
||||||
|
public bool ForceCache { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("cache_min_hour")]
|
||||||
|
public int? CacheMinHour { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("cache_max_hour")]
|
||||||
|
public int? CacheMaxHour { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("time_to_deploy")]
|
||||||
|
public int? TimeToDeploy { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("enable_all_locations")]
|
||||||
|
public bool EnableAllLocations { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("session_config")]
|
||||||
|
public SessionConfigData SessionConfig { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("ports")]
|
||||||
|
public PortsData[] Ports { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("probe")]
|
||||||
|
public ProbeData Probe { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("envs")]
|
||||||
|
public EnvsData[] Envs { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("verify_image")]
|
||||||
|
public bool VerifyImage { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("termination_grace_period_seconds")]
|
||||||
|
public int? TerminationGracePeriodSeconds { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("endpoint_storage")]
|
||||||
|
public string EndpointStorage { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("command")]
|
||||||
|
public string Command { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("arguments")]
|
||||||
|
public string Arguments { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SessionConfigData
|
||||||
|
{
|
||||||
|
[JsonProperty("kind")]
|
||||||
|
public string Kind { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sockets")]
|
||||||
|
public int? Sockets { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("autodeploy")]
|
||||||
|
public bool Autodeploy { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("empty_ttl")]
|
||||||
|
public int? EmptyTtl { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("session_max_duration")]
|
||||||
|
public int? SessionMaxDuration { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PortsData
|
||||||
|
{
|
||||||
|
[JsonProperty("port")]
|
||||||
|
public int? Port { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("protocol")]
|
||||||
|
public string Protocol { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("to_check")]
|
||||||
|
public bool ToCheck { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("tls_upgrade")]
|
||||||
|
public bool TlsUpgrade { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string PortName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ProbeData
|
||||||
|
{
|
||||||
|
[JsonProperty("optimal_ping")]
|
||||||
|
public int? OptimalPing { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("rejected_ping")]
|
||||||
|
public int? RejectedPing { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EnvsData
|
||||||
|
{
|
||||||
|
[JsonProperty("key")]
|
||||||
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("value")]
|
||||||
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("is_secret")]
|
||||||
|
public bool IsSecret { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a7dde7d59c66d8c44b86af35e853f9f5
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
28
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/SessionData.cs
Executable file
28
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/SessionData.cs
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor.Api.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Shared model for `GetDeploymentStatusResult`, `StopActiveDeploymentResult`.
|
||||||
|
/// </summary>
|
||||||
|
public class SessionData
|
||||||
|
{
|
||||||
|
[JsonProperty("session_id")]
|
||||||
|
public string SessionId { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("status")]
|
||||||
|
public string Status { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("ready")]
|
||||||
|
public bool Ready { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("linked")]
|
||||||
|
public bool Linked { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("kind")]
|
||||||
|
public string Kind { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("user_count")]
|
||||||
|
public string UserCount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/SessionData.cs.meta
Executable file
11
Assets/Mirror/Hosting/Edgegap/Editor/Api/Models/SessionData.cs.meta
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5f9024e4ca5438e4788e461387313531
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
37
Assets/Mirror/Hosting/Edgegap/Editor/ButtonShaker.cs
Executable file
37
Assets/Mirror/Hosting/Edgegap/Editor/ButtonShaker.cs
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor
|
||||||
|
{
|
||||||
|
/// <summary>Slightly shake a UI button to indicate attention.</summary>
|
||||||
|
public class ButtonShaker
|
||||||
|
{
|
||||||
|
const string SHAKE_START_CLASS = "shakeStart";
|
||||||
|
const string SHAKE_STOP_CLASS = "shakeEnd";
|
||||||
|
private Button targetButton;
|
||||||
|
|
||||||
|
public ButtonShaker(Button buttonToShake) =>
|
||||||
|
targetButton = buttonToShake;
|
||||||
|
|
||||||
|
/// <summary>Shake the button x times for x msDelayBetweenShakes each.
|
||||||
|
/// 1 shake = 1 bigger -> followed by 1 smaller.</summary>
|
||||||
|
/// <param name="msDelayBetweenShakes"></param>
|
||||||
|
/// <param name="iterations"># of shakes</param>
|
||||||
|
public async Task ApplyShakeAsync(int msDelayBetweenShakes = 40, int iterations = 2)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < iterations; i++)
|
||||||
|
await shakeOnce(msDelayBetweenShakes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task shakeOnce(int msDelayBetweenShakes)
|
||||||
|
{
|
||||||
|
targetButton.AddToClassList(SHAKE_START_CLASS);
|
||||||
|
await Task.Delay(msDelayBetweenShakes); // duration of the first transition
|
||||||
|
targetButton.RemoveFromClassList(SHAKE_START_CLASS);
|
||||||
|
|
||||||
|
targetButton.AddToClassList(SHAKE_STOP_CLASS);
|
||||||
|
await Task.Delay(msDelayBetweenShakes); // duration of the second transition
|
||||||
|
targetButton.RemoveFromClassList(SHAKE_STOP_CLASS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Mirror/Hosting/Edgegap/Editor/ButtonShaker.cs.meta
Executable file
11
Assets/Mirror/Hosting/Edgegap/Editor/ButtonShaker.cs.meta
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f963d64ffcf32ba4bba54fe1cd70b5a1
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -159,7 +159,7 @@ static async Task RunCommand(string command, string arguments, Action<string> ou
|
|||||||
ConcurrentQueue<string> errors = new ConcurrentQueue<string>();
|
ConcurrentQueue<string> errors = new ConcurrentQueue<string>();
|
||||||
ConcurrentQueue<string> outputs = new ConcurrentQueue<string>();
|
ConcurrentQueue<string> outputs = new ConcurrentQueue<string>();
|
||||||
|
|
||||||
void PipeQueue(ConcurrentQueue<string> q, Action<string> opt)
|
void pipeQueue(ConcurrentQueue<string> q, Action<string> opt)
|
||||||
{
|
{
|
||||||
while (!q.IsEmpty)
|
while (!q.IsEmpty)
|
||||||
{
|
{
|
||||||
@ -180,12 +180,14 @@ void PipeQueue(ConcurrentQueue<string> q, Action<string> opt)
|
|||||||
while (!proc.HasExited)
|
while (!proc.HasExited)
|
||||||
{
|
{
|
||||||
await Task.Delay(100);
|
await Task.Delay(100);
|
||||||
PipeQueue(errors, errorReciever);
|
pipeQueue(errors, errorReciever);
|
||||||
PipeQueue(outputs, outputReciever);
|
pipeQueue(outputs, outputReciever);
|
||||||
}
|
}
|
||||||
|
|
||||||
PipeQueue(errors, errorReciever);
|
pipeQueue(errors, errorReciever);
|
||||||
PipeQueue(outputs, outputReciever);
|
pipeQueue(outputs, outputReciever);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
|
static void Proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||||
@ -229,6 +231,68 @@ RUN chmod +x /root/build/ServerBuild
|
|||||||
ENTRYPOINT [ ""/root/build/ServerBuild"", ""-batchmode"", ""-nographics""]
|
ENTRYPOINT [ ""/root/build/ServerBuild"", ""-batchmode"", ""-nographics""]
|
||||||
";
|
";
|
||||||
|
|
||||||
|
/// <summary>Run a Docker cmd with streaming log response. TODO: Plugin to other Docker cmds</summary>
|
||||||
|
/// <returns>Throws if logs contain "ERROR"</returns>
|
||||||
|
///
|
||||||
|
/// <param name="registryUrl">ex: "registry.edgegap.com"</param>
|
||||||
|
/// <param name="repoUsername">ex: "robot$mycompany-asdf+client-push"</param>
|
||||||
|
/// <param name="repoPasswordToken">Different from ApiToken; sometimes called "Container Registry Password"</param>
|
||||||
|
/// <param name="onStatusUpdate">Log stream</param>
|
||||||
|
// MIRROR CHANGE: CROSS PLATFORM SUPPORT
|
||||||
|
static async Task<bool> RunCommand_DockerLogin(
|
||||||
|
string registryUrl,
|
||||||
|
string repoUsername,
|
||||||
|
string repoPasswordToken,
|
||||||
|
Action<string> outputReciever = null, Action<string> errorReciever = null)
|
||||||
|
{
|
||||||
|
// TODO: Use --password-stdin for security (!) This is no easy task for child Process | https://stackoverflow.com/q/51489359/6541639
|
||||||
|
// (!) Don't use single quotes for cross-platform support (works unexpectedly in `cmd`).
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if UNITY_EDITOR_WIN
|
||||||
|
await RunCommand("cmd.exe", $"/c docker login -u \"{repoUsername}\" --password \"{repoPasswordToken}\" \"{registryUrl}\"", outputReciever, errorReciever);
|
||||||
|
#elif UNITY_EDITOR_OSX
|
||||||
|
await RunCommand("/bin/bash", $"-c \"docker login -u \"{repoUsername}\" --password \"{repoPasswordToken}\" \"{registryUrl}\"\"", outputReciever, errorReciever);
|
||||||
|
#elif UNITY_EDITOR_LINUX
|
||||||
|
await RunCommand("/bin/bash", $"-c \"docker login -u \"{repoUsername}\" --password \"{repoPasswordToken}\" \"{registryUrl}\"\"", outputReciever, errorReciever);
|
||||||
|
#else
|
||||||
|
Debug.LogError("The platform is not supported yet.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Error: {e}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// v2: Login to Docker Registry via RunCommand(), returning streamed log messages:
|
||||||
|
/// "docker login {registryUrl} {repository} {repoUsername} {repoPasswordToken}"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="registryUrl">ex: "registry.edgegap.com"</param>
|
||||||
|
/// <param name="repoUsername">ex: "robot$mycompany-asdf+client-push"</param>
|
||||||
|
/// <param name="repoPasswordToken">Different from ApiToken; sometimes called "Container Registry Password"</param>
|
||||||
|
/// <param name="onStatusUpdate">Log stream</param>
|
||||||
|
/// <returns>isSuccess</returns>
|
||||||
|
public static async Task<bool> LoginContainerRegistry(
|
||||||
|
string registryUrl,
|
||||||
|
string repoUsername,
|
||||||
|
string repoPasswordToken,
|
||||||
|
Action<string> onStatusUpdate)
|
||||||
|
{
|
||||||
|
string error = null;
|
||||||
|
await RunCommand_DockerLogin(registryUrl, repoUsername, repoPasswordToken, onStatusUpdate, msg => error = msg); // MIRROR CHANGE
|
||||||
|
if (error.Contains("ERROR"))
|
||||||
|
{
|
||||||
|
Debug.LogError(error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +1,25 @@
|
|||||||
// MIRROR CHANGE: removed 2023-11-06 because it doesn't seem to do anything.
|
using UnityEditor;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
using Edgegap;
|
||||||
|
|
||||||
|
[CustomEditor(typeof(EdgegapToolScript))]
|
||||||
|
public class EdgegapPluginScriptEditor : Editor
|
||||||
|
{
|
||||||
|
VisualElement _serverDataContainer;
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
_serverDataContainer = EdgegapServerDataManager.GetServerDataVisualTree();
|
||||||
|
EdgegapServerDataManager.RegisterServerDataContainer(_serverDataContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
EdgegapServerDataManager.DeregisterServerDataContainer(_serverDataContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override VisualElement CreateInspectorGUI()
|
||||||
|
{
|
||||||
|
return _serverDataContainer;
|
||||||
|
}
|
||||||
|
}
|
@ -7,20 +7,234 @@
|
|||||||
|
|
||||||
namespace Edgegap
|
namespace Edgegap
|
||||||
{
|
{
|
||||||
// MIRROR CHANGE: EdgegapServerDataManagerUtils were merged into EdgegapServerDataManager to reduce complexity & dependencies
|
static class EdgegapServerDataManagerUtils
|
||||||
// static class EdgegapServerDataManagerUtils {}
|
{
|
||||||
// END MIRROR CHANGE
|
public static Label GetHeader(string text)
|
||||||
|
{
|
||||||
|
Label header = new Label(text);
|
||||||
|
header.AddToClassList("label__header");
|
||||||
|
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static VisualElement GetHeaderRow()
|
||||||
|
{
|
||||||
|
VisualElement row = new VisualElement();
|
||||||
|
row.AddToClassList("row__port-table");
|
||||||
|
row.AddToClassList("label__header");
|
||||||
|
|
||||||
|
row.Add(new Label("Name"));
|
||||||
|
row.Add(new Label("External"));
|
||||||
|
row.Add(new Label("Internal"));
|
||||||
|
row.Add(new Label("ProtocolStr"));
|
||||||
|
row.Add(new Label("Link"));
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static VisualElement GetRowFromPortResponse(PortMapping port)
|
||||||
|
{
|
||||||
|
VisualElement row = new VisualElement();
|
||||||
|
row.AddToClassList("row__port-table");
|
||||||
|
row.AddToClassList("focusable");
|
||||||
|
|
||||||
|
|
||||||
|
row.Add(new Label(port.Name));
|
||||||
|
row.Add(new Label(port.External.ToString()));
|
||||||
|
row.Add(new Label(port.Internal.ToString()));
|
||||||
|
row.Add(new Label(port.Protocol));
|
||||||
|
row.Add(GetCopyButton("Copy", port.Link));
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Button GetCopyButton(string btnText, string copiedText)
|
||||||
|
{
|
||||||
|
Button copyBtn = new Button();
|
||||||
|
copyBtn.text = btnText;
|
||||||
|
copyBtn.clickable.clicked += () => GUIUtility.systemCopyBuffer = copiedText;
|
||||||
|
|
||||||
|
return copyBtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Button GetLinkButton(string btnText, string targetUrl)
|
||||||
|
{
|
||||||
|
Button copyBtn = new Button();
|
||||||
|
copyBtn.text = btnText;
|
||||||
|
copyBtn.clickable.clicked += () => UnityEngine.Application.OpenURL(targetUrl);
|
||||||
|
|
||||||
|
return copyBtn;
|
||||||
|
}
|
||||||
|
public static Label GetInfoText(string innerText)
|
||||||
|
{
|
||||||
|
Label infoText = new Label(innerText);
|
||||||
|
infoText.AddToClassList("label__info-text");
|
||||||
|
|
||||||
|
return infoText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Utility class to centrally manage the Edgegap server data.
|
/// Utility class to centrally manage the Edgegap server data, and create / update the elements displaying the server info.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
//
|
|
||||||
public static class EdgegapServerDataManager
|
public static class EdgegapServerDataManager
|
||||||
{
|
{
|
||||||
// MIRROR CHANGE: ServerDataManager.GetServerStatus() is still static for other scripts to access.
|
|
||||||
// However, all UI code was moved to non-static EdgegapWindow.
|
|
||||||
// this allows us to properly assign the stylesheet without hardcoding paths etc.
|
|
||||||
internal static Status _serverData;
|
internal static Status _serverData;
|
||||||
|
private static ApiEnvironment _apiEnvironment;
|
||||||
|
|
||||||
|
// UI elements
|
||||||
|
private static readonly StyleSheet _serverDataStylesheet;
|
||||||
|
private static readonly List<VisualElement> _serverDataContainers = new List<VisualElement>();
|
||||||
|
|
||||||
public static Status GetServerStatus() => _serverData;
|
public static Status GetServerStatus() => _serverData;
|
||||||
|
|
||||||
|
static EdgegapServerDataManager()
|
||||||
|
{
|
||||||
|
_serverDataStylesheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Edgegap/Editor/EdgegapServerData.uss");
|
||||||
|
}
|
||||||
|
public static void RegisterServerDataContainer(VisualElement serverDataContainer)
|
||||||
|
{
|
||||||
|
_serverDataContainers.Add(serverDataContainer);
|
||||||
|
}
|
||||||
|
public static void DeregisterServerDataContainer(VisualElement serverDataContainer)
|
||||||
|
{
|
||||||
|
_serverDataContainers.Remove(serverDataContainer);
|
||||||
|
}
|
||||||
|
public static void SetServerData(Status serverData, ApiEnvironment apiEnvironment)
|
||||||
|
{
|
||||||
|
_serverData = serverData;
|
||||||
|
_apiEnvironment = apiEnvironment;
|
||||||
|
RefreshServerDataContainers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static VisualElement GetStatusSection()
|
||||||
|
{
|
||||||
|
ServerStatus serverStatus = _serverData.GetServerStatus();
|
||||||
|
string dashboardUrl = _apiEnvironment.GetDashboardUrl();
|
||||||
|
string requestId = _serverData.RequestId;
|
||||||
|
string deploymentDashboardUrl = "";
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(requestId) && !string.IsNullOrEmpty(dashboardUrl))
|
||||||
|
{
|
||||||
|
deploymentDashboardUrl = $"{dashboardUrl}/arbitrium/deployment/read/{requestId}/";
|
||||||
|
}
|
||||||
|
|
||||||
|
VisualElement container = new VisualElement();
|
||||||
|
container.AddToClassList("container");
|
||||||
|
|
||||||
|
container.Add(EdgegapServerDataManagerUtils.GetHeader("Server Status"));
|
||||||
|
|
||||||
|
VisualElement row = new VisualElement();
|
||||||
|
row.AddToClassList("row__status");
|
||||||
|
|
||||||
|
// Status pill
|
||||||
|
Label statusLabel = new Label(serverStatus.GetLabelText());
|
||||||
|
statusLabel.AddToClassList(serverStatus.GetStatusBgClass());
|
||||||
|
statusLabel.AddToClassList("label__status");
|
||||||
|
row.Add(statusLabel);
|
||||||
|
|
||||||
|
// Link to dashboard
|
||||||
|
if (!string.IsNullOrEmpty(deploymentDashboardUrl))
|
||||||
|
{
|
||||||
|
row.Add(EdgegapServerDataManagerUtils.GetLinkButton("See in the dashboard", deploymentDashboardUrl));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
row.Add(new Label("Could not resolve link to this deployment"));
|
||||||
|
}
|
||||||
|
|
||||||
|
container.Add(row);
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static VisualElement GetDnsSection()
|
||||||
|
{
|
||||||
|
string serverDns = _serverData.Fqdn;
|
||||||
|
|
||||||
|
VisualElement container = new VisualElement();
|
||||||
|
container.AddToClassList("container");
|
||||||
|
|
||||||
|
container.Add(EdgegapServerDataManagerUtils.GetHeader("Server DNS"));
|
||||||
|
|
||||||
|
VisualElement row = new VisualElement();
|
||||||
|
row.AddToClassList("row__dns");
|
||||||
|
row.AddToClassList("focusable");
|
||||||
|
|
||||||
|
row.Add(new Label(serverDns));
|
||||||
|
row.Add(EdgegapServerDataManagerUtils.GetCopyButton("Copy", serverDns));
|
||||||
|
|
||||||
|
container.Add(row);
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static VisualElement GetPortsSection()
|
||||||
|
{
|
||||||
|
List<PortMapping> serverPorts = _serverData.Ports.Values.ToList();
|
||||||
|
|
||||||
|
VisualElement container = new VisualElement();
|
||||||
|
container.AddToClassList("container");
|
||||||
|
|
||||||
|
container.Add(EdgegapServerDataManagerUtils.GetHeader("Server PortsDict"));
|
||||||
|
container.Add(EdgegapServerDataManagerUtils.GetHeaderRow());
|
||||||
|
|
||||||
|
VisualElement portList = new VisualElement();
|
||||||
|
|
||||||
|
if (serverPorts.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (PortMapping port in serverPorts)
|
||||||
|
{
|
||||||
|
portList.Add(EdgegapServerDataManagerUtils.GetRowFromPortResponse(port));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
portList.Add(new Label("No port configured for this app version."));
|
||||||
|
}
|
||||||
|
|
||||||
|
container.Add(portList);
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static VisualElement GetServerDataVisualTree()
|
||||||
|
{
|
||||||
|
VisualElement serverDataTree = new VisualElement();
|
||||||
|
serverDataTree.styleSheets.Add(_serverDataStylesheet);
|
||||||
|
|
||||||
|
bool hasServerData = _serverData != null;
|
||||||
|
bool isReady = hasServerData && _serverData.GetServerStatus().IsOneOf(ServerStatus.Ready, ServerStatus.Error);
|
||||||
|
|
||||||
|
if (hasServerData)
|
||||||
|
{
|
||||||
|
serverDataTree.Add(GetStatusSection());
|
||||||
|
|
||||||
|
if (isReady)
|
||||||
|
{
|
||||||
|
serverDataTree.Add(GetDnsSection());
|
||||||
|
serverDataTree.Add(GetPortsSection());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serverDataTree.Add(EdgegapServerDataManagerUtils.GetInfoText("Additional information will be displayed when the server is ready."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serverDataTree.Add(EdgegapServerDataManagerUtils.GetInfoText("Server data will be displayed here when a server is running."));
|
||||||
|
}
|
||||||
|
|
||||||
|
return serverDataTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RefreshServerDataContainers()
|
||||||
|
{
|
||||||
|
foreach (VisualElement serverDataContainer in _serverDataContainers)
|
||||||
|
{
|
||||||
|
serverDataContainer.Clear();
|
||||||
|
serverDataContainer.Add(GetServerDataVisualTree()); // Cannot reuse a same instance of VisualElement
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +1,12 @@
|
|||||||
// MIRROR CHANGE: removed 2023-11-06 because it doesn't seem to do anything.
|
using UnityEngine;
|
||||||
|
using Edgegap;
|
||||||
|
using IO.Swagger.Model;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This script acts as an interface to display and use the necessary variables from the Edgegap tool.
|
||||||
|
/// The server info can be accessed from the tool window, as well as through the public script property.
|
||||||
|
/// </summary>
|
||||||
|
public class EdgegapToolScript : MonoBehaviour
|
||||||
|
{
|
||||||
|
public Status ServerStatus => EdgegapServerDataManager.GetServerStatus();
|
||||||
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// MIRROR CHANGE: disable this completely. otherwise InitUIElements can still throw NRE.
|
||||||
|
/*
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
@ -78,7 +80,8 @@ public class EdgegapWindow : EditorWindow
|
|||||||
StyleSheet _serverDataStylesheet;
|
StyleSheet _serverDataStylesheet;
|
||||||
List<VisualElement> _serverDataContainers = new List<VisualElement>();
|
List<VisualElement> _serverDataContainers = new List<VisualElement>();
|
||||||
|
|
||||||
[MenuItem("Edgegap/Edgegap Hosting")] // MIRROR CHANGE
|
[Obsolete("See EdgegapWindowV2.ShowEdgegapToolWindow()")]
|
||||||
|
// [MenuItem("Edgegap/Server Management")]
|
||||||
public static void ShowEdgegapToolWindow()
|
public static void ShowEdgegapToolWindow()
|
||||||
{
|
{
|
||||||
EdgegapWindow window = GetWindow<EdgegapWindow>();
|
EdgegapWindow window = GetWindow<EdgegapWindow>();
|
||||||
@ -634,6 +637,8 @@ void RestoreActiveDeployment()
|
|||||||
|
|
||||||
void SyncObjectWithForm()
|
void SyncObjectWithForm()
|
||||||
{
|
{
|
||||||
|
if (_apiKeyInput == null) return; // MIRROR CHANGE: fix NRE when this is called before UI elements were assgned
|
||||||
|
|
||||||
_apiKey = _apiKeyInput.value;
|
_apiKey = _apiKeyInput.value;
|
||||||
_apiEnvironment = (ApiEnvironment)_apiEnvironmentSelect.value;
|
_apiEnvironment = (ApiEnvironment)_apiEnvironmentSelect.value;
|
||||||
_appName = _appNameInput.value;
|
_appName = _appNameInput.value;
|
||||||
@ -978,3 +983,4 @@ void LoadToolData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
#serverDataContainer {
|
#serverDataContainer {
|
||||||
margin: 4px 0px 0px 0px;
|
margin: 4px 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: auto;
|
height: auto;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 8px 0px 8px 0px;
|
padding: 8px 0 8px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.background {
|
.background {
|
||||||
@ -15,7 +15,9 @@
|
|||||||
width: 400px;
|
width: 400px;
|
||||||
top: -10px;
|
top: -10px;
|
||||||
right: -150px;
|
right: -150px;
|
||||||
background-image: url("./Images/logo_transparent_400_alpha25.png");
|
/* MIRROR CHANGE: disable hardcoded image path. this is inserted from the script now.
|
||||||
|
background-image: url('project://database/Assets/Edgegap/Editor/Images/logo_transparent_400_alpha25.png?fileID=21300000&guid=b7012da4ebf9008458abc3ef9a741f3c&type=3#logo_transparent_400_alpha25');
|
||||||
|
*/
|
||||||
-unity-background-scale-mode: scale-and-crop;
|
-unity-background-scale-mode: scale-and-crop;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,15 +27,17 @@
|
|||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
-unity-text-align: middle-center;
|
-unity-text-align: middle-center;
|
||||||
-unity-font: url("./Fonts/BaronNeue.otf");
|
/* MIRROR CHANGE: disable hardcoded font path
|
||||||
|
-unity-font: url('project://database/Assets/Edgegap/Editor/Fonts/Src/BaronNeue.otf?fileID=12800000&guid=fb67205c672fbb04d829783b9f771fc9&type=3#BaronNeue');
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.text--muted {
|
.text--muted {
|
||||||
color: #8a8a8a;
|
color: rgb(192, 192, 192);
|
||||||
}
|
}
|
||||||
|
|
||||||
.text--success {
|
.text--success {
|
||||||
color: #90be6d;
|
color: rgb(144, 190, 109);
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
@ -58,3 +62,154 @@
|
|||||||
.flex--between {
|
.flex--between {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#unity-text-input {
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
border-top-right-radius: 5px;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
color: rgb(255, 255, 255);
|
||||||
|
border-top-width: 1px;
|
||||||
|
border-right-width: 1px;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
border-left-width: 1px;
|
||||||
|
height: 27px;
|
||||||
|
background-color: rgb(26, 26, 26);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-edgegap {
|
||||||
|
border-top-left-radius: 3px;
|
||||||
|
border-top-right-radius: 3px;
|
||||||
|
border-bottom-right-radius: 3px;
|
||||||
|
border-bottom-left-radius: 3px;
|
||||||
|
border-top-width: 1px;
|
||||||
|
border-right-width: 1px;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
border-left-width: 1px;
|
||||||
|
border-left-color: rgba(0, 0, 0, 0.35);
|
||||||
|
border-right-color: rgba(0, 0, 0, 0.35);
|
||||||
|
border-top-color: rgba(0, 0, 0, 0.35);
|
||||||
|
border-bottom-color: rgba(0, 0, 0, 0.35);
|
||||||
|
height: 27px;
|
||||||
|
-unity-font-style: bold;
|
||||||
|
background-color: rgb(36, 76, 87);
|
||||||
|
min-width: 170px;
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-edgegap:hover {
|
||||||
|
background-color: rgb(56, 96, 107);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-purple-hover:hover {
|
||||||
|
background-color: rgb(44, 30, 210);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-row-parent {
|
||||||
|
background-color: rgb(49, 49, 49);
|
||||||
|
border-top-color: rgb(0, 0, 0);
|
||||||
|
border-bottom-color: rgb(0, 0, 0);
|
||||||
|
border-top-width: 1px;
|
||||||
|
border-right-width: 1px;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
border-left-width: 1px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-edgegap {
|
||||||
|
font-size: 11px;
|
||||||
|
color: rgb(222, 222, 222);
|
||||||
|
/* MIRROR CHANGE: disable hardcoded font path
|
||||||
|
-unity-font-definition: url('project://database/Assets/Edgegap/Editor/Fonts/Spartan-Regular%20SDF.asset?fileID=11400000&guid=8b0fb2c68be09174f8ea5057b27a545c&type=2#Spartan-Regular SDF');
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-btnTxt {
|
||||||
|
font-size: 12px;
|
||||||
|
color: rgb(255, 255, 255);
|
||||||
|
-unity-font-style: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toggle > #unity-checkmark {
|
||||||
|
}
|
||||||
|
|
||||||
|
.unity-foldout > #unity-checkmark {
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-purple {
|
||||||
|
background-color: rgb(44, 30, 210);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-purple:hover {
|
||||||
|
background-color: rgb(64, 50, 230);
|
||||||
|
}
|
||||||
|
|
||||||
|
.unity-foldout {
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unity-text-field {
|
||||||
|
min-width: auto;
|
||||||
|
width: 400px;
|
||||||
|
padding-right: 5px;
|
||||||
|
white-space: normal;
|
||||||
|
-unity-text-align: middle-left;
|
||||||
|
opacity: 1;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
padding-top: 5px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unity-text-field > Label {
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-row {
|
||||||
|
background-color: rgb(37, 37, 37);
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkmark-edgegap {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkmark-edgegap #unity-checkmark {
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unity-text-field__input > TextElement {
|
||||||
|
color: rgb(255, 255, 255);
|
||||||
|
/* MIRROR CHANGE: disable hardcoded font path
|
||||||
|
-unity-font-definition: url('project://database/Assets/Edgegap/Editor/Fonts/UbuntuMono-R%20SDF.asset?fileID=11400000&guid=2635d61c9807d6c46bcb00a3d8645b37&type=2#UbuntuMono-R SDF');
|
||||||
|
*/
|
||||||
|
font-size: 12px;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: clip;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shakeStart {
|
||||||
|
left: 5px;
|
||||||
|
transition: left 50ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shakeEnd {
|
||||||
|
left: -5px;
|
||||||
|
transition: left 50ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customContainerChildTxt {
|
||||||
|
padding-left: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#DeploymentConnectionUrlReadOnlyTxt > #unity-text-input {
|
||||||
|
display: flex;
|
||||||
|
visibility: visible;
|
||||||
|
background-color: rgba(0, 0, 0, 0.13);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-purple-hover {
|
||||||
|
}
|
||||||
|
@ -1,52 +1,101 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" editor-extension-mode="True">
|
||||||
<engine:UXML
|
<Style src="project://database/Assets/Edgegap/Editor/EdgegapWindow.uss?fileID=7433441132597879392&guid=b1a2e4572c5de8840ac8d98377d409ae&type=3#EdgegapWindow" />
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<ui:VisualElement class="content" style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0;">
|
||||||
xmlns:engine="UnityEngine.UIElements"
|
<ui:VisualElement name="HeaderHorizGroup" style="flex-grow: 1; flex-direction: row; height: 100px; background-color: rgb(37, 37, 37); left: 0;">
|
||||||
xmlns:editor="UnityEditor.UIElements"
|
<ui:VisualElement name="header-logo-img" style="height: 67px; width: 100px; flex-direction: row; -unity-background-scale-mode: scale-to-fit; -unity-slice-left: 0; -unity-slice-top: 0; -unity-slice-right: 0; -unity-slice-bottom: 0; -unity-background-image-tint-color: rgb(255, 255, 255); -unity-slice-scale: 1px; align-self: center;" />
|
||||||
xmlns:uie="UnityEditor.UIElements"
|
<ui:Label text="EDGEGAP" name="header-logo-txt" class="text__title" style="flex-direction: row; flex-grow: 1; color: rgb(255, 255, 255); font-size: 30px; -unity-text-align: middle-left; -unity-font-style: normal; -unity-font: initial; margin-left: 0; align-items: center; height: 74px;">
|
||||||
>
|
<ui:Button text="DEBUG" parse-escape-sequences="true" display-tooltip-when-elided="true" name="DebugBtn" tooltip="Hide me @ EdgegapWindowMetadata.SHOW_DEBUG_BTN" style="-unity-text-align: middle-left; white-space: normal; text-overflow: clip; justify-content: flex-start; align-self: flex-end; position: absolute; right: 0; top: 0; padding-top: 3px;" />
|
||||||
<engine:VisualElement class="content">
|
</ui:Label>
|
||||||
<engine:VisualElement class="background" />
|
</ui:VisualElement>
|
||||||
<engine:Label class="text__title" text="Edgegap Hosting" />
|
</ui:VisualElement>
|
||||||
|
<ui:ScrollView name="BodyScrollView" style="background-color: rgb(37, 37, 37); height: 1132px; justify-content: flex-end;">
|
||||||
<engine:ScrollView>
|
<ui:GroupBox name="ApiTokenHorizGroupBox" class="container-row-parent" style="flex-direction: row; margin-left: 0; margin-right: 0; margin-bottom: 10px; align-items: center; justify-content: flex-start; align-self: auto; padding-bottom: 0; padding-top: 0;">
|
||||||
<engine:VisualElement class="container">
|
<ui:TextField name="ApiTokenMaskedTxt" label="<b>API Token</b>" tooltip="No token? Click the "Get a Token" button >> Click "Verify" after entered to unlock other features" password="true" class="text-edgegap" style="padding-left: 25px; flex-grow: 0.17;" />
|
||||||
<engine:TextField name="apiKey" label="API key" password="true" view-data-key="apiKey" />
|
<ui:Button name="ApiTokenVerifyPurpleBtn" text="Verify" tooltip="On successful validation, the remaining UI will be unlocked" class="button-edgegap text-edgegap bg-purple" style="min-width: 75px; -unity-font-style: bold; visibility: visible; display: flex; overflow: hidden;" />
|
||||||
<uie:EnumField name="environmentSelect" label="API environment" include-obsolete-values="false"/>
|
<ui:Button name="ApiTokenGetBtn" text="Get a Token" class="button-edgegap text-edgegap" style="-unity-font-style: bold; width: 125px; max-width: none; min-width: auto;" />
|
||||||
<engine:TextField name="appName" label="App name" view-data-key="appName" />
|
</ui:GroupBox>
|
||||||
<engine:TextField name="appVersionName" label="App version" view-data-key="appVersionName" />
|
<ui:VisualElement name="PostAuthContainer" usage-hints="MaskContainer" style="flex-grow: 1; transition-timing-function: ease-in; transition-duration: 0.2s;">
|
||||||
</engine:VisualElement>
|
<ui:Foldout text="<b>Application Info</b>" name="ApplicationInfoFoldout" class="text-edgegap container-row-parent" style="margin-left: 0; -unity-font-style: normal;">
|
||||||
|
<ui:VisualElement name="ApplicationNameRow" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;">
|
||||||
<engine:VisualElement class="container">
|
<ui:TextField name="ApplicationNameTxt" label="Application Name" tooltip="Arbitrary name to call your app" password="false" view-data-key="ApplicationNameTxt" class="text-edgegap" />
|
||||||
<engine:VisualElement class="flex flex--right">
|
<ui:Button name="AppLoadExistingBtn" text="Load Existing App" tooltip="Already have an existing application by this name?" class="button-edgegap text-edgegap bg-purple" style="min-width: 75px; -unity-font-style: bold; visibility: visible; display: flex; overflow: hidden;" />
|
||||||
<engine:Label name="connectionStatusLabel" class="text--muted" text="Awaiting connection" />
|
</ui:VisualElement>
|
||||||
<engine:Button name="connectionBtn" />
|
<ui:VisualElement name="ApplicationIconRow" class="container-row" style="flex-grow: 1;">
|
||||||
</engine:VisualElement>
|
<ui:VisualElement name="ApplicationIconHorizGroup" class="text-edgegap" style="flex-grow: 1; flex-direction: row; align-items: center; justify-content: flex-start; align-self: stretch; width: 600px;">
|
||||||
</engine:VisualElement>
|
<uie:ObjectField label="Application Icon" type="UnityEngine.Sprite, UnityEngine.CoreModule" name="ApplicationIconSprite" tooltip="Choose a Sprite image to use as an app icon" view-data-key="ApplicationIconSprite" style="align-items: center; justify-content: flex-start; align-self: center; width: 409px;" />
|
||||||
|
<ui:VisualElement name="SelectFileVertGroup" style="flex-grow: 0.7;">
|
||||||
<engine:VisualElement class="container">
|
<ui:VisualElement name="SelectFileHorizGroup" style="flex-grow: 1; flex-direction: row; align-items: center;">
|
||||||
<engine:TextField name="containerRegistry" tooltip="ex: docker.io or harbor.edgegap.net" label="Container Registry" view-data-key="containerRegistry" />
|
<ui:Label tabindex="-1" text="Limit 200kb" parse-escape-sequences="true" display-tooltip-when-elided="true" name="SelectFileSizeLimitTooltipLabel" class="text-edgegap" style="font-size: 11px; color: rgb(147, 147, 147); -unity-text-align: upper-left;" />
|
||||||
<engine:TextField name="containerImageRepo" tooltip="ex: edgegap/image" label="Image repository" view-data-key="containerImageRepo" />
|
</ui:VisualElement>
|
||||||
<engine:TextField name="tag" label="Tag" tooltip="ex: 1.2" view-data-key="tag" />
|
</ui:VisualElement>
|
||||||
<engine:Toggle name="autoIncrementTag" tooltip="Auto increment the tag on build for quicker iteration" label="Increment tag on build" />
|
</ui:VisualElement>
|
||||||
</engine:VisualElement>
|
</ui:VisualElement>
|
||||||
|
<ui:VisualElement name="ApplicationCreateHorizRow" style="flex-grow: 1; flex-direction: row;">
|
||||||
|
<ui:Button name="ApplicationCreateBtn" text="Create Application" class="button-edgegap text-edgegap" style="flex-direction: row; -unity-text-align: middle-center; margin-left: 0;" />
|
||||||
<engine:VisualElement class="container" />
|
<ui:Label tabindex="-1" text="{ApplicationCreateResultLabel}" parse-escape-sequences="true" display-tooltip-when-elided="true" name="ApplicationCreateResultLabel" class="text-edgegap" style="color: rgb(138, 238, 140); align-items: stretch; justify-content: flex-start; align-self: center;" />
|
||||||
|
</ui:VisualElement>
|
||||||
<engine:VisualElement class="container">
|
</ui:Foldout>
|
||||||
<engine:VisualElement class="flex">
|
<ui:VisualElement name="ContainerRegistryFoldoutHorizRow" class="container-row-parent" style="flex-grow: 1; flex-direction: row;">
|
||||||
<engine:Button name="buildAndPushBtn" text="Build and Push" />
|
<ui:Foldout text="<b>Container Registry</b>" name="ContainerRegistryFoldout" class="text-edgegap" style="flex-grow: 1; padding-bottom: 0; padding-top: 0; padding-right: 0; padding-left: 0;">
|
||||||
<engine:Button name="serverActionBtn" />
|
<ui:VisualElement name="ContainerPortRow" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;">
|
||||||
</engine:VisualElement>
|
<ui:TextField name="ContainerRegistryPortNumTxt" label="Port" tooltip="1024~49151 (Default `7770`)" value="7770" view-data-key="ContainerRegistryPortNumTxt" keyboard-type="NumberPad" class="text-edgegap" style="width: 250px;" />
|
||||||
|
<ui:VisualElement name="MIRROR_CHANGE_PORT_HARDCODED" class="MIRROR_CHANGE_PORT_HARDCODED" />
|
||||||
</engine:VisualElement>
|
</ui:VisualElement>
|
||||||
|
<ui:VisualElement name="ContainerNewVersionTagRow" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;">
|
||||||
<engine:VisualElement name="serverDataContainer" />
|
<ui:TextField name="ContainerNewVersionTagTxt" label="New Version Tag" tooltip="eg: "latest" (default), "v1.0.0", "1.0.0"" value="latest" view-data-key="ContainerNewVersionTagTxt" class="text-edgegap" />
|
||||||
|
</ui:VisualElement>
|
||||||
<engine:VisualElement class="container flex flex--right">
|
<ui:VisualElement name="ContainerUseCustomRegistryRow" view-data-key="ContainerUseCustomRegistryRow" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto; padding-top: 5px; padding-bottom: 5px;">
|
||||||
<engine:Button name="documentationBtn" text="Documentation" tooltip="Opens the documentation website. The website version changes depending on the selected API environment."/>
|
<ui:Toggle name="ContainerUseCustomRegistryToggle" label="Use Custom Container Registry" class="text-edgegap checkmark-edgegap" style="justify-content: flex-start; align-self: center; flex-direction: row-reverse; align-items: center; padding-left: 3px;" />
|
||||||
</engine:VisualElement>
|
</ui:VisualElement>
|
||||||
</engine:ScrollView>
|
<ui:VisualElement name="ContainerCustomRegistryWrapper" style="flex-grow: 1;">
|
||||||
</engine:VisualElement>
|
<ui:VisualElement name="ContainerRegistryUrlRow" class="container-row customContainerRegistryMember" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;">
|
||||||
</engine:UXML>
|
<ui:TextField name="ContainerRegistryUrlTxt" label="Registry URL" tooltip="eg: `registry.edgegap.com`, `docker.io`, `harbor.edgegap.net`" class="text-edgegap customContainerChildTxt" />
|
||||||
|
</ui:VisualElement>
|
||||||
|
<ui:VisualElement name="ContainerRepositoryRow" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;">
|
||||||
|
<ui:TextField name="ContainerImageRepositoryTxt" label="Repository" tooltip="eg: `edgegap-public/tutorial`, `mycompany-someid/mylowercaseapp-`" class="text-edgegap customContainerChildTxt" />
|
||||||
|
</ui:VisualElement>
|
||||||
|
<ui:VisualElement name="ContainerUsernameRow" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;">
|
||||||
|
<ui:TextField name="ContainerUsernameTxt" label="Username" tooltip="eg: `robot$mycompany-someid+client-push`" class="text-edgegap customContainerChildTxt" />
|
||||||
|
</ui:VisualElement>
|
||||||
|
<ui:VisualElement name="ContainerTokenRow" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;">
|
||||||
|
<ui:TextField name="ContainerTokenTxt" label="Token" tooltip="Registry pasword/token/secret (different from top-level API Token)" password="true" class="text-edgegap customContainerChildTxt" />
|
||||||
|
</ui:VisualElement>
|
||||||
|
</ui:VisualElement>
|
||||||
|
<ui:VisualElement name="ContainerBuildAndPushHorizRow" style="flex-grow: 1; flex-direction: row;">
|
||||||
|
<ui:Button name="ContainerBuildAndPushBtn" text="Build and Push" class="button-edgegap text-edgegap" style="margin-left: 0;" />
|
||||||
|
<ui:Label tabindex="-1" text="{ContainerBuildAndPushResultLabel}" parse-escape-sequences="true" display-tooltip-when-elided="true" name="ContainerBuildAndPushResultLabel" class="text-edgegap" style="color: rgb(138, 238, 140); align-items: stretch; justify-content: flex-start; align-self: center; display: none;" />
|
||||||
|
</ui:VisualElement>
|
||||||
|
</ui:Foldout>
|
||||||
|
</ui:VisualElement>
|
||||||
|
<ui:Foldout text="<b>Deployments</b>" name="DeploymentsFoldout" class="text-edgegap container-row-parent">
|
||||||
|
<ui:VisualElement name="Row" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;" />
|
||||||
|
<ui:GroupBox name="DeploymentsHorizGroupBox" style="flex-direction: row; justify-content: flex-start; align-items: stretch; align-self: flex-start; margin-left: 0; padding-left: 0;">
|
||||||
|
<ui:Button name="DeploymentsRefreshBtn" text="Refresh" class="button-edgegap text-edgegap" style="flex-grow: 0.5;" />
|
||||||
|
<ui:Button name="DeploymentsCreateBtn" text="Create New Deployment" class="button-edgegap text-edgegap" style="flex-grow: 0.5; max-width: 250px; min-width: 200px;" />
|
||||||
|
</ui:GroupBox>
|
||||||
|
<ui:Label tabindex="-1" text="{DeploymentsStatusLabel}" parse-escape-sequences="true" display-tooltip-when-elided="true" name="DeploymentsStatusLabel" class="text-edgegap" style="color: rgb(138, 238, 140); white-space: normal; text-overflow: ellipsis; width: 650px; display: none; margin-left: 3px;" />
|
||||||
|
<ui:GroupBox name="DeploymentsHeadersGroupBox" class="container-row-parent" style="flex-direction: row; padding-top: 6px; padding-right: 0; padding-bottom: 3px; padding-left: 0; margin-bottom: 0; align-self: auto; justify-content: flex-start; align-items: center;">
|
||||||
|
<ui:Label name="DeploymentsConnectionStatusHeaderLabel" text="Status" style="flex-grow: 0.5; -unity-text-align: upper-left; -unity-font-style: bold; width: 75px; flex-direction: column;" />
|
||||||
|
<ui:Label name="DeploymentsConnectionURLHeaderLabel" text="URL" style="flex-grow: 1; -unity-font-style: bold; align-items: auto; justify-content: flex-start; align-self: auto;" />
|
||||||
|
<ui:Label name="DeploymentsConnectionControlHeaderLabel" text="Control" style="flex-grow: 0.08; -unity-text-align: upper-left; -unity-font-style: bold; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0;" />
|
||||||
|
</ui:GroupBox>
|
||||||
|
<ui:GroupBox name="DeploymentsConnectionGroupBox" style="flex-direction: row; padding-left: 0; align-items: center; align-self: stretch; justify-content: flex-start; height: 32px;">
|
||||||
|
<ui:Label name="DeploymentsConnectionStatusLabel" text="Unknown" class="text--muted" style="flex-grow: 1; flex-direction: column; -unity-text-align: middle-left; justify-content: flex-start; align-items: center; width: 86px; margin-right: 15px;" />
|
||||||
|
<ui:VisualElement name="DeploymentConnectionUrlHorizGroup" style="flex-grow: 1; flex-direction: row; width: 304px; margin-left: 25px; margin-right: 25px; padding-right: 25px; padding-left: 25px;">
|
||||||
|
<ui:TextField picking-mode="Ignore" name="DeploymentConnectionUrlReadOnlyTxt" readonly="true" tooltip="Selectable" style="padding-left: 0; -unity-text-align: middle-center; width: 297px; align-items: center;">
|
||||||
|
<ui:Button name="DeploymentConnectionCopyUrlBtn" tooltip="Copy" class="text-edgegap bg-purple" style="min-width: 15px; visibility: visible; display: flex; overflow: hidden; width: 35px; -unity-background-scale-mode: scale-to-fit; min-height: 25px; background-color: rgb(44, 30, 210); -unity-background-image-tint-color: rgb(224, 224, 224); -unity-slice-left: 1; -unity-slice-top: 1; -unity-slice-right: 1; -unity-slice-bottom: 1; translate: -40px 0;" />
|
||||||
|
</ui:TextField>
|
||||||
|
</ui:VisualElement>
|
||||||
|
<ui:VisualElement name="DeploymentsConnectionServerStopHorizBtnHorizGroup" style="flex-grow: 1; flex-direction: row; align-items: center; justify-content: center;">
|
||||||
|
<ui:Button name="DeploymentsConnectionServerStopBtn" text="Stop Server" class="button-edgegap text-edgegap" style="min-width: auto; width: 125px; max-width: none; visibility: visible; display: flex;" />
|
||||||
|
</ui:VisualElement>
|
||||||
|
</ui:GroupBox>
|
||||||
|
</ui:Foldout>
|
||||||
|
<ui:VisualElement name="ServerDataContainer" />
|
||||||
|
</ui:VisualElement>
|
||||||
|
<ui:GroupBox name="FooterHorizGroup" class="container-row-parent" style="flex-direction: row; justify-content: center; align-items: auto; align-self: center; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-left-radius: 1px; border-top-right-radius: 1px; border-bottom-right-radius: 1px; border-bottom-left-radius: 1px; border-right-color: rgb(0, 0, 0); border-left-color: rgb(0, 0, 0); padding-right: 135px; padding-left: 150px; padding-top: 15px; padding-bottom: 15px;">
|
||||||
|
<ui:Button text="Documentation" tooltip="Opens the documentation website. The website version changes depending on the selected API environment." name="FooterDocumentationBtn" class="button-edgegap text-edgegap" />
|
||||||
|
<ui:Button text="Add More Game Servers!" tooltip="Opens the documentation website. The website version changes depending on the selected API environment." name="FooterNeedMoreGameServersBtn" class="button-edgegap text-edgegap bg-purple" style="width: 220px; max-width: none; min-width: auto;" />
|
||||||
|
</ui:GroupBox>
|
||||||
|
</ui:ScrollView>
|
||||||
|
</ui:UXML>
|
||||||
|
172
Assets/Mirror/Hosting/Edgegap/Editor/EdgegapWindowMetadata.cs
Executable file
172
Assets/Mirror/Hosting/Edgegap/Editor/EdgegapWindowMetadata.cs
Executable file
@ -0,0 +1,172 @@
|
|||||||
|
using System;
|
||||||
|
using Edgegap.Editor.Api.Models;
|
||||||
|
|
||||||
|
namespace Edgegap.Editor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains static metadata / options for the EdgegapWindowV2 UI.
|
||||||
|
/// - Notable:
|
||||||
|
/// * SHOW_DEBUG_BTN
|
||||||
|
/// * LOG_LEVEL
|
||||||
|
/// * DEFAULT_VERSION_TAG
|
||||||
|
/// * SKIP_SERVER_BUILD_WHEN_PUSHING
|
||||||
|
/// * SKIP_DOCKER_IMAGE_BUILD_WHEN_PUSHING
|
||||||
|
/// </summary>
|
||||||
|
public static class EdgegapWindowMetadata
|
||||||
|
{
|
||||||
|
#region Debug
|
||||||
|
/// <summary>Log Debug+, or Errors only?</summary>
|
||||||
|
public enum LogLevel
|
||||||
|
{
|
||||||
|
Debug,
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set to Debug to show more logs. Default `Error`.
|
||||||
|
/// - Error level includes "potentially-intentional" (!fatal) errors logged with Debug.Log
|
||||||
|
/// - TODO: Move opt to UI?
|
||||||
|
/// </summary>
|
||||||
|
public const LogLevel LOG_LEVEL = LogLevel.Error;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set to show a debug button at the top-right for arbitrary testing.
|
||||||
|
/// Default enables groups. Default `false`.
|
||||||
|
/// </summary>
|
||||||
|
public const bool SHOW_DEBUG_BTN = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When running a Docker-based "Build & Push" flow, skip building the Unity server binary
|
||||||
|
/// (great for testing push flow). Default false.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly bool SKIP_SERVER_BUILD_WHEN_PUSHING = false; // MIRROR CHANGE: 'const' changed to 'static readonly' to avoid 'unreachable code detected' warning
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When running a Docker-based "Build & Push" flow, skip building the Docker image
|
||||||
|
/// (great for testing registry login mechanics). Default false.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly bool SKIP_DOCKER_IMAGE_BUILD_WHEN_PUSHING = false; // MIRROR CHANGE: 'const' changed to 'static readonly' to avoid 'unreachable code detected' warning
|
||||||
|
#endregion // Debug
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>Interval at which the server status is updated</summary>
|
||||||
|
public const int SERVER_STATUS_CRON_JOB_INTERVAL_MS = 10000;
|
||||||
|
public const int PORT_DEFAULT = 7770;
|
||||||
|
public const int PORT_MIN = 1024;
|
||||||
|
public const int PORT_MAX = 49151;
|
||||||
|
public const int DEPLOYMENT_AWAIT_READY_STATUS_TIMEOUT_MINS = 1;
|
||||||
|
public const int DEPLOYMENT_READY_STATUS_POLL_SECONDS = 2;
|
||||||
|
public const int DEPLOYMENT_STOP_STATUS_POLL_SECONDS = 2;
|
||||||
|
public const ProtocolType DEFAULT_PROTOCOL_TYPE = ProtocolType.UDP;
|
||||||
|
public const string READY_STATUS = "Status.READY";
|
||||||
|
|
||||||
|
public const string EDGEGAP_GET_A_TOKEN_URL = "https://app.edgegap.com/?oneClick=true";
|
||||||
|
public const string EDGEGAP_ADD_MORE_GAME_SERVERS_URL = "https://edgegap.com/en/resources/contact";
|
||||||
|
public const string EDGEGAP_DOC_BTN_HOW_TO_LOGIN_VIA_CLI_URL = "https://docs.edgegap.com/docs/container/edgegap-container-registry/#getting-your-credentials";
|
||||||
|
public const string DEFAULT_VERSION_TAG = "latest";
|
||||||
|
public const string LOADING_RICH_STR = "<i>Loading...</i>";
|
||||||
|
public const string PROCESSING_RICH_STR = "<i>Processing...</i>";
|
||||||
|
public const string DEPLOY_REQUEST_RICH_STR = "<i>Requesting Deploy...</i>";
|
||||||
|
|
||||||
|
#region Colors
|
||||||
|
/// <summary>Earthy lime green</summary>
|
||||||
|
public const string SUCCESS_COLOR_HEX = "#8AEE8C";
|
||||||
|
|
||||||
|
/// <summary>Calming light orange</summary>
|
||||||
|
public const string WARN_COLOR_HEX = "#EEC58A";
|
||||||
|
|
||||||
|
/// <summary>Vivid blood orange</summary>
|
||||||
|
public const string FAIL_COLOR_HEX = "#EE9A8A";
|
||||||
|
|
||||||
|
/// <summary>Corn yellow</summary>
|
||||||
|
public const string PROCESSING_COLOR_HEX = "#EEEA8A";
|
||||||
|
|
||||||
|
public enum StatusColors
|
||||||
|
{
|
||||||
|
/// <summary>CornYellow</summary>
|
||||||
|
Processing,
|
||||||
|
|
||||||
|
/// <summary>EarthyLimeGreen</summary>
|
||||||
|
Success,
|
||||||
|
|
||||||
|
/// <summary>CalmingLightOrange</summary>
|
||||||
|
Warn,
|
||||||
|
|
||||||
|
/// <summary>VividBloodOrange</summary>
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <returns>Wraps string in color rich text</returns>
|
||||||
|
public static string WrapRichTextInColor(string str, StatusColors statusColor)
|
||||||
|
{
|
||||||
|
switch (statusColor)
|
||||||
|
{
|
||||||
|
case StatusColors.Processing:
|
||||||
|
return $"<color={PROCESSING_COLOR_HEX}>{str}</color>";
|
||||||
|
case StatusColors.Success:
|
||||||
|
return $"<color={SUCCESS_COLOR_HEX}>{str}</color>";
|
||||||
|
case StatusColors.Warn:
|
||||||
|
return $"<color={WARN_COLOR_HEX}>{str}</color>";
|
||||||
|
case StatusColors.Error:
|
||||||
|
return $"<color={FAIL_COLOR_HEX}>{str}</color>";
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(statusColor), statusColor, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion // Colors
|
||||||
|
|
||||||
|
#region Player Pref Key Ids for persistence
|
||||||
|
/// <summary>Cached as base64</summary>
|
||||||
|
public const string API_TOKEN_KEY_STR = "ApiToken";
|
||||||
|
public const string DEPLOYMENT_REQUEST_ID_KEY_STR = "DeploymentRequestId";
|
||||||
|
public const string DEPLOYMENT_CONNECTION_URL_KEY_STR = "DeploymentConnectionUrlLabel";
|
||||||
|
public const string DEPLOYMENT_CONNECTION_STATUS_KEY_STR = "DeploymentsConnectionStatusLabel";
|
||||||
|
#endregion // Editor Pref Key Ids for persistence
|
||||||
|
|
||||||
|
#region UI Element Ids
|
||||||
|
public const string DEBUG_BTN_ID = "DebugBtn";
|
||||||
|
public const string API_TOKEN_TXT_ID = "ApiTokenMaskedTxt";
|
||||||
|
public const string API_TOKEN_VERIFY_BTN_ID = "ApiTokenVerifyPurpleBtn";
|
||||||
|
public const string API_TOKEN_GET_BTN_ID = "ApiTokenGetBtn";
|
||||||
|
public const string POST_AUTH_CONTAINER_ID = "PostAuthContainer";
|
||||||
|
|
||||||
|
public const string APP_INFO_FOLDOUT_ID = "ApplicationInfoFoldout";
|
||||||
|
public const string APP_NAME_TXT_ID = "ApplicationNameTxt";
|
||||||
|
public const string APP_LOAD_EXISTING_BTN_ID = "AppLoadExistingBtn";
|
||||||
|
public const string APP_ICON_SPRITE_OBJ_ID = "ApplicationIconSprite";
|
||||||
|
public const string APP_CREATE_BTN_ID = "ApplicationCreateBtn";
|
||||||
|
public const string APP_CREATE_RESULT_LABEL_ID = "ApplicationCreateResultLabel";
|
||||||
|
|
||||||
|
public const string CONTAINER_REGISTRY_FOLDOUT_ID = "ContainerRegistryFoldout";
|
||||||
|
public const string CONTAINER_REGISTRY_PORT_NUM_ID = "ContainerRegistryPortNumTxt";
|
||||||
|
public const string CONTAINER_REGISTRY_TRANSPORT_TYPE_ENUM_ID = "ContainerRegistryProtocolTypeEnumField";
|
||||||
|
public const string CONTAINER_NEW_TAG_VERSION_TXT_ID = "ContainerNewVersionTagTxt";
|
||||||
|
public const string CONTAINER_USE_CUSTOM_REGISTRY_TOGGLE_ID = "ContainerUseCustomRegistryToggle";
|
||||||
|
public const string CONTAINER_CUSTOM_REGISTRY_WRAPPER_ID = "ContainerCustomRegistryWrapper";
|
||||||
|
public const string CONTAINER_REGISTRY_URL_TXT_ID = "ContainerRegistryUrlTxt";
|
||||||
|
public const string CONTAINER_IMAGE_REPOSITORY_URL_TXT_ID = "ContainerImageRepositoryTxt";
|
||||||
|
public const string CONTAINER_USERNAME_TXT_ID = "ContainerUsernameTxt";
|
||||||
|
public const string CONTAINER_TOKEN_TXT_ID = "ContainerTokenTxt";
|
||||||
|
public const string CONTAINER_BUILD_AND_PUSH_BTN_ID = "ContainerBuildAndPushBtn";
|
||||||
|
public const string CONTAINER_BUILD_AND_PUSH_RESULT_LABEL_ID = "ContainerBuildAndPushResultLabel";
|
||||||
|
|
||||||
|
public const string DEPLOYMENTS_FOLDOUT_ID = "DeploymentsFoldout";
|
||||||
|
public const string DEPLOYMENTS_REFRESH_BTN_ID = "DeploymentsRefreshBtn";
|
||||||
|
public const string DEPLOYMENTS_CREATE_BTN_ID = "DeploymentsCreateBtn";
|
||||||
|
public const string DEPLOYMENTS_STATUS_LABEL_ID = "DeploymentsStatusLabel";
|
||||||
|
public const string DEPLOYMENTS_CONTAINER_ID = "DeploymentsConnectionGroupBox";
|
||||||
|
public const string DEPLOYMENTS_CONNECTION_COPY_URL_BTN_ID = "DeploymentConnectionCopyUrlBtn";
|
||||||
|
public const string DEPLOYMENTS_CONNECTION_URL_READONLY_TXT_ID = "DeploymentConnectionUrlReadOnlyTxt"; // Dynamic
|
||||||
|
public const string DEPLOYMENTS_CONNECTION_STATUS_LABEL_ID = "DeploymentsConnectionStatusLabel"; // Dynamic
|
||||||
|
public const string DEPLOYMENTS_CONNECTION_SERVER_ACTION_STOP_BTN_ID = "DeploymentsConnectionServerStopBtn";
|
||||||
|
|
||||||
|
public const string FOOTER_DOCUMENTATION_BTN_ID = "FooterDocumentationBtn";
|
||||||
|
public const string FOOTER_NEED_MORE_GAME_SERVERS_BTN_ID = "FooterNeedMoreGameServersBtn";
|
||||||
|
#endregion // UI Element Ids
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//[Obsolete("Hard-coded; not from UI. TODO: Get from UI")] // MIRROR CHANGE: comment this out to avoid import warnings
|
||||||
|
public const ApiEnvironment API_ENVIRONMENT = ApiEnvironment.Console;
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Mirror/Hosting/Edgegap/Editor/EdgegapWindowMetadata.cs.meta
Executable file
11
Assets/Mirror/Hosting/Edgegap/Editor/EdgegapWindowMetadata.cs.meta
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c17286cfb15166442920036353163fc0
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
1762
Assets/Mirror/Hosting/Edgegap/Editor/EdgegapWindowV2.cs
Executable file
1762
Assets/Mirror/Hosting/Edgegap/Editor/EdgegapWindowV2.cs
Executable file
File diff suppressed because it is too large
Load Diff
14
Assets/Mirror/Hosting/Edgegap/Editor/EdgegapWindowV2.cs.meta
Executable file
14
Assets/Mirror/Hosting/Edgegap/Editor/EdgegapWindowV2.cs.meta
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1c3d4497250ad3e4aa500d4c599b30fe
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences:
|
||||||
|
- m_ViewDataDictionary: {instanceID: 0}
|
||||||
|
- LogoImage: {fileID: 2800000, guid: b7012da4ebf9008458abc3ef9a741f3c, type: 3}
|
||||||
|
- ClipboardImage: {fileID: 2800000, guid: caa516cdb721dd143bbc8000ca78d50a, type: 3}
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Binary file not shown.
@ -1,21 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: fb67205c672fbb04d829783b9f771fc9
|
|
||||||
TrueTypeFontImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 4
|
|
||||||
fontSize: 16
|
|
||||||
forceTextureCase: -2
|
|
||||||
characterSpacing: 0
|
|
||||||
characterPadding: 1
|
|
||||||
includeFontData: 1
|
|
||||||
fontNames:
|
|
||||||
- Baron Neue
|
|
||||||
fallbackFontReferences: []
|
|
||||||
customCharacters:
|
|
||||||
fontRenderingMode: 0
|
|
||||||
ascentCalculationMode: 1
|
|
||||||
useLegacyBoundsCalculation: 0
|
|
||||||
shouldRoundAdvanceValue: 1
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -0,0 +1 @@
|
|||||||
|
Removed font files to avoid all kinds of runtime errors.
|
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 57002d60dd8ce46b081a0a0a25e5b52b
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
BIN
Assets/Mirror/Hosting/Edgegap/Editor/Images/clipboard-128.png
Executable file
BIN
Assets/Mirror/Hosting/Edgegap/Editor/Images/clipboard-128.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
140
Assets/Mirror/Hosting/Edgegap/Editor/Images/clipboard-128.png.meta
Executable file
140
Assets/Mirror/Hosting/Edgegap/Editor/Images/clipboard-128.png.meta
Executable file
@ -0,0 +1,140 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: caa516cdb721dd143bbc8000ca78d50a
|
||||||
|
TextureImporter:
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 12
|
||||||
|
mipmaps:
|
||||||
|
mipMapMode: 0
|
||||||
|
enableMipMap: 0
|
||||||
|
sRGBTexture: 1
|
||||||
|
linearTexture: 0
|
||||||
|
fadeOut: 0
|
||||||
|
borderMipMap: 0
|
||||||
|
mipMapsPreserveCoverage: 0
|
||||||
|
alphaTestReferenceValue: 0.5
|
||||||
|
mipMapFadeDistanceStart: 1
|
||||||
|
mipMapFadeDistanceEnd: 3
|
||||||
|
bumpmap:
|
||||||
|
convertToNormalMap: 0
|
||||||
|
externalNormalMap: 0
|
||||||
|
heightScale: 0.25
|
||||||
|
normalMapFilter: 0
|
||||||
|
flipGreenChannel: 0
|
||||||
|
isReadable: 0
|
||||||
|
streamingMipmaps: 0
|
||||||
|
streamingMipmapsPriority: 0
|
||||||
|
vTOnly: 0
|
||||||
|
ignoreMipmapLimit: 0
|
||||||
|
grayScaleToAlpha: 0
|
||||||
|
generateCubemap: 6
|
||||||
|
cubemapConvolution: 0
|
||||||
|
seamlessCubemap: 0
|
||||||
|
textureFormat: 1
|
||||||
|
maxTextureSize: 2048
|
||||||
|
textureSettings:
|
||||||
|
serializedVersion: 2
|
||||||
|
filterMode: 1
|
||||||
|
aniso: 1
|
||||||
|
mipBias: 0
|
||||||
|
wrapU: 1
|
||||||
|
wrapV: 1
|
||||||
|
wrapW: 0
|
||||||
|
nPOTScale: 0
|
||||||
|
lightmap: 0
|
||||||
|
compressionQuality: 50
|
||||||
|
spriteMode: 1
|
||||||
|
spriteExtrude: 1
|
||||||
|
spriteMeshType: 1
|
||||||
|
alignment: 0
|
||||||
|
spritePivot: {x: 0.5, y: 0.5}
|
||||||
|
spritePixelsToUnits: 100
|
||||||
|
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
spriteGenerateFallbackPhysicsShape: 1
|
||||||
|
alphaUsage: 1
|
||||||
|
alphaIsTransparency: 1
|
||||||
|
spriteTessellationDetail: -1
|
||||||
|
textureType: 8
|
||||||
|
textureShape: 1
|
||||||
|
singleChannelComponent: 0
|
||||||
|
flipbookRows: 1
|
||||||
|
flipbookColumns: 1
|
||||||
|
maxTextureSizeSet: 0
|
||||||
|
compressionQualitySet: 0
|
||||||
|
textureFormatSet: 0
|
||||||
|
ignorePngGamma: 0
|
||||||
|
applyGammaDecoding: 0
|
||||||
|
swizzle: 50462976
|
||||||
|
cookieLightType: 0
|
||||||
|
platformSettings:
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: DefaultTexturePlatform
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: WebGL
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: Standalone
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: Server
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
spriteSheet:
|
||||||
|
serializedVersion: 2
|
||||||
|
sprites: []
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
bones: []
|
||||||
|
spriteID: 5e97eb03825dee720800000000000000
|
||||||
|
internalID: 0
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
secondaryTextures: []
|
||||||
|
nameFileIdTable: {}
|
||||||
|
mipmapLimitGroupName:
|
||||||
|
pSDRemoveMatte: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
@ -55,10 +55,10 @@ public static string GetDocumentationUrl(this ApiEnvironment apiEnvironment)
|
|||||||
switch (apiEnvironment)
|
switch (apiEnvironment)
|
||||||
{
|
{
|
||||||
case ApiEnvironment.Staging:
|
case ApiEnvironment.Staging:
|
||||||
apiUrl = "https://staging-docs.edgegap.com";
|
apiUrl = "https://staging-docs.edgegap.com/docs";
|
||||||
break;
|
break;
|
||||||
case ApiEnvironment.Console:
|
case ApiEnvironment.Console:
|
||||||
apiUrl = "https://docs.edgegap.com";
|
apiUrl = "https://docs.edgegap.com/docs";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
apiUrl = null;
|
apiUrl = null;
|
||||||
|
@ -1,9 +1,16 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Edgegap
|
namespace Edgegap
|
||||||
{
|
{
|
||||||
|
//[Obsolete("Use UpdateAppVersionRequest")] // MIRROR CHANGE: commented this out to avoid import warnings
|
||||||
public struct AppVersionUpdatePatchData
|
public struct AppVersionUpdatePatchData
|
||||||
{
|
{
|
||||||
|
|
||||||
[JsonProperty("docker_repository")]
|
[JsonProperty("docker_repository")]
|
||||||
public string DockerRegistry;
|
public string DockerRegistry;
|
||||||
|
|
||||||
@ -12,5 +19,6 @@ public struct AppVersionUpdatePatchData
|
|||||||
|
|
||||||
[JsonProperty("docker_tag")]
|
[JsonProperty("docker_tag")]
|
||||||
public string DockerTag;
|
public string DockerTag;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Mirror.Hosting",
|
"name": "Mirror.Hosting",
|
||||||
"rootNamespace": "",
|
"rootNamespace": "",
|
||||||
"references": [
|
"references": [],
|
||||||
""
|
|
||||||
],
|
|
||||||
"includePlatforms": [
|
"includePlatforms": [
|
||||||
"Editor"
|
"Editor"
|
||||||
],
|
],
|
||||||
|
@ -34,7 +34,7 @@ Mirror comes with a wide variety of features to support all game genres.<br>
|
|||||||
Many of our features quickly became the norm across all Unity netcodes!<br>
|
Many of our features quickly became the norm across all Unity netcodes!<br>
|
||||||
|
|
||||||
| Feature | Description | Status |
|
| Feature | Description | Status |
|
||||||
|-------------------------------|-------------------------------------------------------------|-----------------|
|
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------|
|
||||||
| 🎛 **Transports** | UDP, TCP, Websockets, Steam, Relay and more. | **Stable** |
|
| 🎛 **Transports** | UDP, TCP, Websockets, Steam, Relay and more. | **Stable** |
|
||||||
| 🪜 **Interest Management** | Spatial Hashing & Distance Checker to partition the world. | **Stable** |
|
| 🪜 **Interest Management** | Spatial Hashing & Distance Checker to partition the world. | **Stable** |
|
||||||
| ↗️ **SyncDirection** | Server & Client Authority - per component with one click. | **Stable** |
|
| ↗️ **SyncDirection** | Server & Client Authority - per component with one click. | **Stable** |
|
||||||
@ -45,6 +45,7 @@ Many of our features quickly became the norm across all Unity netcodes!<br>
|
|||||||
| 🛞 **Transform & Physics** | Transform & Physics sync built in. | **Stable** |
|
| 🛞 **Transform & Physics** | Transform & Physics sync built in. | **Stable** |
|
||||||
| 👩🍼 **Child Components** | Put networked components on anything. | **Stable** |
|
| 👩🍼 **Child Components** | Put networked components on anything. | **Stable** |
|
||||||
| 🪚️ **IL Post Processing** | Zero overhead [Rpcs] and [Commands] via IL post processing! | **Stable** |
|
| 🪚️ **IL Post Processing** | Zero overhead [Rpcs] and [Commands] via IL post processing! | **Stable** |
|
||||||
|
| ☁️ **Two Click Hosting** | (Optional) <a href="https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide">Build & Push</a> directly from Unity Editor to the Cloud. | **Preview** |
|
||||||
| | | |
|
| | | |
|
||||||
| 📏 **Snapshot Interp.** | Perfectly smooth movement for all platforms and all games. | **Stable** |
|
| 📏 **Snapshot Interp.** | Perfectly smooth movement for all platforms and all games. | **Stable** |
|
||||||
| 🔫 **Lag Compensation** | Roll back state to see what the player saw during input. | **Preview** |
|
| 🔫 **Lag Compensation** | Roll back state to see what the player saw during input. | **Preview** |
|
||||||
|
Loading…
Reference in New Issue
Block a user