Skip to content

Commit 4d574b0

Browse files
feat: add edgegap allocator (#11)
Add Edgegap Hosting integration for Cloud Code Allocator Co-authored-by: Bastien Roy <bastien@edgegap.com>
1 parent 21de299 commit 4d574b0

13 files changed

Lines changed: 881 additions & 0 deletions

MatchmakerHostingProviders.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44
<Project Path="modules/MultiplayAllocator/Project/MultiplayAllocator.csproj" />
55
<Project Path="modules/PlayfabAllocator/Project/PlayFabAllocator.csproj" />
66
<Project Path="modules/AgonesAllocator/Project/AgonesAllocator.csproj" />
7+
<Project Path="modules/EdgegapAllocator/Project/EdgegapAllocator.csproj" />
78
</Solution>

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Select the hosting provider that you want to use under `modules/<provider_name>`
2929
- **GameLiftAllocator** - AWS GameLift integration
3030
- **MultiplayAllocator** - Unity Multiplay integration
3131
- **PlayFabAllocator** - Microsoft PlayFab integration
32+
- **EdgegapAllocator** - Edgegap integration
3233

3334
### Configure the module
3435

@@ -38,6 +39,7 @@ Each module contains a `CONFIGURATION.md` file with detailed instructions on upd
3839
- [GameLiftAllocator/CONFIGURATION.md](modules/GameLiftAllocator/CONFIGURATION.md)
3940
- [MultiplayAllocator/CONFIGURATION.md](modules/MultiplayAllocator/CONFIGURATION.md)
4041
- [PlayFabAllocator/CONFIGURATION.md](modules/PlayFabAllocator/CONFIGURATION.md)
42+
- [EdgegapAllocator/CONFIGURATION.md](modules/EdgegapAllocator/CONFIGURATION.md)
4143

4244
Once you've completed the configuration steps for your chosen provider, proceed to deploying the module.
4345

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Edgegap allocator configuration
2+
3+
Get started with [Edgegap's Documentation](https://docs.edgegap.com).
4+
5+
[Read more about switching from Multiplay.](https://docs.edgegap.com/docs/tools-and-integrations/switch-from-multiplay#start-deployments-from-ugs-matchmaker).
6+
7+
## Required secrets
8+
9+
Add these secrets in the [Unity Dashboard](https://cloud.unity.com) under **Administration** > **Secrets**:
10+
11+
- `EDGEGAP_API_TOKEN` - Your Edgegap API token.
12+
13+
Find your token in the [Edgegap Console](https://app.edgegap.com/user-settings?tab=tokens).
14+
15+
## Required code changes
16+
17+
Edit `Project/EdgegapAllocator.cs` and update these constants:
18+
19+
### ApplicationName (line 34)
20+
21+
```csharp
22+
private const string ApplicationName = "MyApp"; // TODO: Replace with actual application name
23+
```
24+
25+
Replace with your Edgegap application name from
26+
the [Applications List](https://app.edgegap.com/application-management/applications/list).
27+
28+
### VersionName (line 35)
29+
30+
```csharp
31+
private const string VersionName = "MyVersion"; // TODO: Replace with actual version name
32+
```
33+
34+
Replace with your Edgegap application's version name you want to use.
35+
36+
### PortName (line 36)
37+
38+
```csharp
39+
private const string PortName = "gameport"; // TODO: Replace with actual port name
40+
```
41+
42+
Replace with your Edgegap application version's port name that will be used for players to connect.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.30114.105
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Project", "Project", "{EB1B1211-640D-0C76-A929-990D115248FD}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EdgegapAllocator", "Project\EdgegapAllocator.csproj", "{92C38FA8-1BD2-4B53-B015-C6BC1FB5C40F}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Debug|x64 = Debug|x64
14+
Debug|x86 = Debug|x86
15+
Release|Any CPU = Release|Any CPU
16+
Release|x64 = Release|x64
17+
Release|x86 = Release|x86
18+
EndGlobalSection
19+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
20+
{92C38FA8-1BD2-4B53-B015-C6BC1FB5C40F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{92C38FA8-1BD2-4B53-B015-C6BC1FB5C40F}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{92C38FA8-1BD2-4B53-B015-C6BC1FB5C40F}.Debug|x64.ActiveCfg = Debug|Any CPU
23+
{92C38FA8-1BD2-4B53-B015-C6BC1FB5C40F}.Debug|x64.Build.0 = Debug|Any CPU
24+
{92C38FA8-1BD2-4B53-B015-C6BC1FB5C40F}.Debug|x86.ActiveCfg = Debug|Any CPU
25+
{92C38FA8-1BD2-4B53-B015-C6BC1FB5C40F}.Debug|x86.Build.0 = Debug|Any CPU
26+
{92C38FA8-1BD2-4B53-B015-C6BC1FB5C40F}.Release|Any CPU.ActiveCfg = Release|Any CPU
27+
{92C38FA8-1BD2-4B53-B015-C6BC1FB5C40F}.Release|Any CPU.Build.0 = Release|Any CPU
28+
{92C38FA8-1BD2-4B53-B015-C6BC1FB5C40F}.Release|x64.ActiveCfg = Release|Any CPU
29+
{92C38FA8-1BD2-4B53-B015-C6BC1FB5C40F}.Release|x64.Build.0 = Release|Any CPU
30+
{92C38FA8-1BD2-4B53-B015-C6BC1FB5C40F}.Release|x86.ActiveCfg = Release|Any CPU
31+
{92C38FA8-1BD2-4B53-B015-C6BC1FB5C40F}.Release|x86.Build.0 = Release|Any CPU
32+
EndGlobalSection
33+
GlobalSection(SolutionProperties) = preSolution
34+
HideSolutionNode = FALSE
35+
EndGlobalSection
36+
GlobalSection(NestedProjects) = preSolution
37+
{92C38FA8-1BD2-4B53-B015-C6BC1FB5C40F} = {EB1B1211-640D-0C76-A929-990D115248FD}
38+
EndGlobalSection
39+
GlobalSection(ExtensibilityGlobals) = postSolution
40+
SolutionGuid = {73F08B91-CC46-4FF7-8832-4C5C94770423}
41+
EndGlobalSection
42+
EndGlobal
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System.Net.Http;
2+
3+
namespace EdgegapAllocatorModule.Client;
4+
5+
public interface IEdgegapHttpClientFactory
6+
{
7+
HttpClient Create(string apiToken);
8+
}
9+
10+
public class EdgegapHttpClientFactory : IEdgegapHttpClientFactory
11+
{
12+
public HttpClient Create(string apiToken)
13+
{
14+
var client = new HttpClient();
15+
client.DefaultRequestHeaders.Add("Authorization", $"{apiToken}");
16+
return client;
17+
}
18+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using System.Collections.Generic;
2+
using System.ComponentModel;
3+
using Newtonsoft.Json;
4+
5+
namespace EdgegapAllocatorModule.Client.Models;
6+
7+
public class DeploymentRequest
8+
{
9+
[JsonProperty("application")]
10+
public required string Application { get; set; }
11+
12+
[JsonProperty("version")]
13+
public required string Version { get; set; }
14+
15+
[JsonProperty("require_cached_locations")]
16+
[DefaultValue(false)]
17+
public bool RequireCachedLocations { get; set; }
18+
19+
[JsonProperty("users")]
20+
public List<DeploymentUser>? Users { get; set; }
21+
22+
[JsonProperty("environment_variables")]
23+
public List<EnvironmentVariable>? EnvironmentVariables { get; set; }
24+
25+
[JsonProperty("tags")]
26+
public List<string>? Tags { get; set; }
27+
}
28+
29+
public class DeploymentUser
30+
{
31+
[JsonProperty("user_type")]
32+
public required string UserType { get; set; }
33+
34+
[JsonProperty("user_data")]
35+
public required UserData UserData { get; set; }
36+
}
37+
38+
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
39+
public class UserData
40+
{
41+
// For user_type = "ip_address"
42+
[JsonProperty("ip_address")]
43+
public string? IpAddress { get; set; }
44+
45+
// For user_type = "geo_coordinates"
46+
[JsonProperty("latitude")]
47+
public double? Latitude { get; set; }
48+
49+
[JsonProperty("longitude")]
50+
public double? Longitude { get; set; }
51+
}
52+
53+
public class EnvironmentVariable
54+
{
55+
[JsonProperty("key")]
56+
public required string Key { get; set; }
57+
58+
[JsonProperty("value")]
59+
public required string Value { get; set; }
60+
61+
[JsonProperty("is_hidden")]
62+
[DefaultValue(false)]
63+
public bool IsHidden { get; set; }
64+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using Newtonsoft.Json;
2+
3+
namespace EdgegapAllocatorModule.Client.Models;
4+
5+
public class DeploymentResponse
6+
{
7+
[JsonProperty("request_id")]
8+
public required string RequestId { get; set; }
9+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Newtonsoft.Json;
4+
5+
namespace EdgegapAllocatorModule.Client.Models;
6+
7+
public class DeploymentStatusResponse
8+
{
9+
[JsonProperty("request_id")]
10+
public required string RequestId { get; set; }
11+
12+
[JsonProperty("fqdn")]
13+
public string? Fqdn { get; set; }
14+
15+
[JsonProperty("current_status")]
16+
[JsonConverter(typeof(StatusConverter))]
17+
public DeploymentStatus CurrentStatus { get; set; }
18+
19+
[JsonProperty("running")]
20+
public bool Running { get; set; }
21+
22+
[JsonProperty("start_time")]
23+
public string? StartTime { get; set; }
24+
25+
[JsonProperty("error")]
26+
public bool Error { get; set; }
27+
28+
[JsonProperty("error_detail")]
29+
public string? ErrorDetail { get; set; }
30+
31+
[JsonProperty("ports")]
32+
public Dictionary<string, Port>? Ports { get; set; }
33+
34+
[JsonProperty("public_ip")]
35+
public string? PublicIp { get; set; }
36+
37+
[JsonProperty("location")]
38+
public Location? Location { get; set; }
39+
40+
[JsonProperty("tags")]
41+
public List<string>? Tags { get; set; }
42+
43+
44+
[JsonProperty("max_duration")]
45+
public int MaxDuration { get; set; }
46+
}
47+
48+
public enum DeploymentStatus
49+
{
50+
Ready,
51+
Error,
52+
Terminated,
53+
Deploying,
54+
Seeking,
55+
Terminating
56+
}
57+
58+
public class StatusConverter : JsonConverter<DeploymentStatus>
59+
{
60+
public override DeploymentStatus ReadJson(
61+
JsonReader reader,
62+
Type objectType,
63+
DeploymentStatus existingValue,
64+
bool hasExistingValue,
65+
JsonSerializer serializer
66+
)
67+
{
68+
var raw = reader.Value?.ToString();
69+
70+
if (string.IsNullOrWhiteSpace(raw))
71+
throw new JsonSerializationException("Status value is null or empty");
72+
73+
// Strip "Status." prefix if present
74+
var normalized = raw.Replace("Status.", "", StringComparison.OrdinalIgnoreCase);
75+
76+
return normalized.ToUpperInvariant() switch
77+
{
78+
"READY" => DeploymentStatus.Ready,
79+
"ERROR" => DeploymentStatus.Error,
80+
"TERMINATED" => DeploymentStatus.Terminated,
81+
"DEPLOYING" => DeploymentStatus.Deploying,
82+
"SEEKING" => DeploymentStatus.Seeking,
83+
"TERMINATING" => DeploymentStatus.Terminating,
84+
_ => throw new JsonSerializationException($"Unknown deployment status '{raw}'")
85+
};
86+
}
87+
88+
public override void WriteJson(
89+
JsonWriter writer,
90+
DeploymentStatus value,
91+
JsonSerializer serializer
92+
)
93+
{
94+
// Serialize back in Edgegap format
95+
writer.WriteValue($"Status.{value.ToString().ToUpperInvariant()}");
96+
}
97+
}
98+
99+
public class Port
100+
{
101+
[JsonProperty("external")]
102+
public int External { get; set; }
103+
104+
[JsonProperty("internal")]
105+
public int Internal { get; set; }
106+
107+
[JsonProperty("protocol")]
108+
public string? Protocol { get; set; }
109+
110+
[JsonProperty("name")]
111+
public string? Name { get; set; }
112+
113+
[JsonProperty("link")]
114+
public string? Link { get; set; }
115+
}
116+
117+
public class Location
118+
{
119+
[JsonProperty("city")]
120+
public string? City { get; set; }
121+
122+
[JsonProperty("country")]
123+
public string? Country { get; set; }
124+
125+
[JsonProperty("continent")]
126+
public string? Continent { get; set; }
127+
128+
[JsonProperty("administrative_division")]
129+
public string? AdministrativeDivision { get; set; }
130+
131+
[JsonProperty("timezone")]
132+
public string? Timezone { get; set; }
133+
134+
[JsonProperty("latitude")]
135+
public double Latitude { get; set; }
136+
137+
[JsonProperty("longitude")]
138+
public double Longitude { get; set; }
139+
}

0 commit comments

Comments
 (0)