Skip to content
Permalink
Browse files

Implementation of GameServer() for Unity (#1169)

- Refactored `SendRequestAsync` to return a `AsyncResult` which contains
  both a success bool, and the returned body text from the http call.
- Used the swagger.json to generate the basic structure of the
  `GameServer` object, and then hand modified as needed.
- Had to include third_party/MiniJSON because Unity doesn't natively
  support `Dictionary`, which means we can't get Label or Annotation
  data. Then had to manually import the MiniJSON data into GameServer
  and related model objects.
- Used a set of symlinks to share the Agones Unity SDK code with the
  unity-simple example. Couldn't think of a better way.
- Minor version update on the example project as that is the earliest
  version I could get in 2018.4.x
- Added `GameServer` command to the simple-unity example as well.

Work on #927
  • Loading branch information...
markmandel committed Nov 7, 2019
1 parent 72523e2 commit 7c507198837fba9640e549ac9d596918ab27bd6b
Showing with 1,442 additions and 37 deletions.
  1. +4 −0 examples/unity-simple/.gitignore
  2. +3 −0 examples/unity-simple/Assets/Scripts/Agones/model.meta
  3. +1 −0 examples/unity-simple/Assets/Scripts/Agones/model/GameServer.cs
  4. +3 −0 examples/unity-simple/Assets/Scripts/Agones/model/GameServer.cs.meta
  5. +1 −0 examples/unity-simple/Assets/Scripts/Agones/model/GameServerObjectMeta.cs
  6. +3 −0 examples/unity-simple/Assets/Scripts/Agones/model/GameServerObjectMeta.cs.meta
  7. +1 −0 examples/unity-simple/Assets/Scripts/Agones/model/GameServerSpec.cs
  8. +3 −0 examples/unity-simple/Assets/Scripts/Agones/model/GameServerSpec.cs.meta
  9. +1 −0 examples/unity-simple/Assets/Scripts/Agones/model/GameServerStatus.cs
  10. +3 −0 examples/unity-simple/Assets/Scripts/Agones/model/GameServerStatus.cs.meta
  11. +1 −0 examples/unity-simple/Assets/Scripts/Agones/model/SpecHealth.cs
  12. +3 −0 examples/unity-simple/Assets/Scripts/Agones/model/SpecHealth.cs.meta
  13. +1 −0 examples/unity-simple/Assets/Scripts/Agones/model/StatusPort.cs
  14. +3 −0 examples/unity-simple/Assets/Scripts/Agones/model/StatusPort.cs.meta
  15. +3 −0 examples/unity-simple/Assets/Scripts/Agones/third_party.meta
  16. +1 −0 examples/unity-simple/Assets/Scripts/Agones/third_party/MiniJSON.cs
  17. +11 −0 examples/unity-simple/Assets/Scripts/Agones/third_party/MiniJSON.cs.meta
  18. +8 −0 examples/unity-simple/Assets/Scripts/UdpEchoServer.cs
  19. +1 −1 examples/unity-simple/Packages/manifest.json
  20. +23 −21 examples/unity-simple/ProjectSettings/EditorSettings.asset
  21. +1 −1 examples/unity-simple/ProjectSettings/ProjectVersion.txt
  22. +1 −0 examples/unity-simple/README.md
  23. +3 −3 pkg/sdk/sdk.pb.go
  24. +45 −11 sdks/unity/AgonesSdk.cs
  25. +128 −0 sdks/unity/model/GameServer.cs
  26. +194 −0 sdks/unity/model/GameServerObjectMeta.cs
  27. +93 −0 sdks/unity/model/GameServerSpec.cs
  28. +123 −0 sdks/unity/model/GameServerStatus.cs
  29. +115 −0 sdks/unity/model/SpecHealth.cs
  30. +101 −0 sdks/unity/model/StatusPort.cs
  31. +547 −0 sdks/unity/third_party/MiniJSON.cs
  32. +2 −0 site/content/en/docs/Examples/_index.md
  33. +11 −0 site/content/en/docs/Guides/Client SDKs/unity.md
@@ -34,3 +34,7 @@ sysinfo.txt
# Builds
*.apk
*.unitypackage

# Rider plugins
/Assets/Plugins/
/Assets/Plugins.meta

Some generated files are not rendered by default. Learn more.

Some generated files are not rendered by default. Learn more.

Some generated files are not rendered by default. Learn more.

Some generated files are not rendered by default. Learn more.

Some generated files are not rendered by default. Learn more.

Some generated files are not rendered by default. Learn more.

Some generated files are not rendered by default. Learn more.

Some generated files are not rendered by default. Learn more.

Some generated files are not rendered by default. Learn more.

@@ -73,6 +73,14 @@ async void Update()

echoBytes = Encoding.UTF8.GetBytes($"Allocate {ok}");
break;

case "GameServer":
var gameserver = await agones.GameServer();
Debug.Log($"Server - GameServer {gameserver}");

ok = gameserver != null;
echoBytes = Encoding.UTF8.GetBytes(ok ? $"GameServer() Name: {gameserver.ObjectMeta.Name} {ok}" : $"GameServer(): {ok}");
break;

case "Label":
if (recvTexts.Length == 3)
@@ -3,7 +3,7 @@
"com.unity.ads": "2.0.8",
"com.unity.analytics": "3.2.2",
"com.unity.collab-proxy": "1.2.15",
"com.unity.package-manager-ui": "2.0.7",
"com.unity.package-manager-ui": "2.0.8",
"com.unity.purchasing": "2.0.3",
"com.unity.textmeshpro": "1.4.1",
"com.unity.modules.ai": "1.0.0",
@@ -1,21 +1,23 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!159 &1
EditorSettings:
m_ObjectHideFlags: 0
serializedVersion: 7
m_ExternalVersionControlSupport: Visible Meta Files
m_SerializationMode: 2
m_LineEndingsForNewScripts: 2
m_DefaultBehaviorMode: 0
m_SpritePackerMode: 0
m_SpritePackerPaddingPower: 1
m_EtcTextureCompressorBehavior: 1
m_EtcTextureFastCompressor: 1
m_EtcTextureNormalCompressor: 2
m_EtcTextureBestCompressor: 4
m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd
m_ProjectGenerationRootNamespace:
m_UserGeneratedProjectSuffix:
m_CollabEditorSettings:
inProgressEnabled: 1
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!159 &1
EditorSettings:
m_ObjectHideFlags: 0
serializedVersion: 7
m_ExternalVersionControlSupport: Visible Meta Files
m_SerializationMode: 2
m_LineEndingsForNewScripts: 2
m_DefaultBehaviorMode: 0
m_PrefabRegularEnvironment: {fileID: 0}
m_PrefabUIEnvironment: {fileID: 0}
m_SpritePackerMode: 0
m_SpritePackerPaddingPower: 1
m_EtcTextureCompressorBehavior: 1
m_EtcTextureFastCompressor: 1
m_EtcTextureNormalCompressor: 2
m_EtcTextureBestCompressor: 4
m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef
m_ProjectGenerationRootNamespace:
m_CollabEditorSettings:
inProgressEnabled: 1
m_EnableTextureStreamingInPlayMode: 1
@@ -1 +1 @@
m_EditorVersion: 2018.4.2f1
m_EditorVersion: 2018.4.12f1
@@ -53,3 +53,4 @@ $ kubectl create -f gameserver.yaml
| Label $1 $2 | SetLabel($1, $2) |
| Annotation $1 $2 | SetAnnotation($1, $2) |
| Shutdown | Shutdown() |
| GaameServer | GameServer() |
@@ -19,10 +19,10 @@
package sdk

import (
fmt "fmt"
math "math"
"fmt"
"math"

proto "github.com/golang/protobuf/proto"
"github.com/golang/protobuf/proto"
context "golang.org/x/net/context"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
@@ -14,10 +14,14 @@
// limitations under the License.

using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Agones.Model;
using MiniJSON;
using UnityEngine;
using UnityEngine.Networking;

@@ -31,8 +35,7 @@ public class AgonesSdk : MonoBehaviour
/// <summary>
/// Interval of the server sending a health ping to the Agones sidecar.
/// </summary>
[Range(0.01f, 5)]
public float healthIntervalSecond = 5.0f;
[Range(0.01f, 5)] public float healthIntervalSecond = 5.0f;

/// <summary>
/// Whether the server sends a health ping to the Agones sidecar.
@@ -78,7 +81,23 @@ private void OnApplicationQuit()
/// </returns>
public async Task<bool> Ready()
{
return await SendRequestAsync("/ready", "{}");
return await SendRequestAsync("/ready", "{}").ContinueWith(task => task.Result.ok);
}

/// <summary>
/// Retrieve the GameServer details
/// </summary>
/// <returns>The current GameServer configuration</returns>
public async Task<GameServer> GameServer()
{
var result = await SendRequestAsync("/gameserver", "{}", UnityWebRequest.kHttpVerbGET);
if (!result.ok)
{
return null;
}

var data = Json.Deserialize(result.json) as Dictionary<string, object>;
return new GameServer(data);
}

/// <summary>
@@ -89,7 +108,7 @@ public async Task<bool> Ready()
/// </returns>
public async Task<bool> Shutdown()
{
return await SendRequestAsync("/shutdown", "{}");
return await SendRequestAsync("/shutdown", "{}").ContinueWith(task => task.Result.ok);
}

/// <summary>
@@ -100,7 +119,7 @@ public async Task<bool> Shutdown()
/// </returns>
public async Task<bool> Allocate()
{
return await SendRequestAsync("/allocate", "{}");
return await SendRequestAsync("/allocate", "{}").ContinueWith(task => task.Result.ok);
}

/// <summary>
@@ -114,7 +133,8 @@ public async Task<bool> Allocate()
public async Task<bool> SetLabel(string key, string value)
{
string json = JsonUtility.ToJson(new KeyValueMessage(key, value));
return await SendRequestAsync("/metadata/label", json, UnityWebRequest.kHttpVerbPUT);
return await SendRequestAsync("/metadata/label", json, UnityWebRequest.kHttpVerbPUT)
.ContinueWith(task => task.Result.ok);
}

/// <summary>
@@ -128,7 +148,8 @@ public async Task<bool> SetLabel(string key, string value)
public async Task<bool> SetAnnotation(string key, string value)
{
string json = JsonUtility.ToJson(new KeyValueMessage(key, value));
return await SendRequestAsync("/metadata/annotation", json, UnityWebRequest.kHttpVerbPUT);
return await SendRequestAsync("/metadata/annotation", json, UnityWebRequest.kHttpVerbPUT)
.ContinueWith(task => task.Result.ok);
}
#endregion

@@ -150,7 +171,17 @@ private async void HealthCheckAsync()
}
}

private async Task<bool> SendRequestAsync(string api, string json, string method = UnityWebRequest.kHttpVerbPOST)
/// <summary>
/// Result of a Async HTTP request
/// </summary>
private struct AsyncResult
{
public bool ok;
public string json;
}

private async Task<AsyncResult> SendRequestAsync(string api, string json,
string method = UnityWebRequest.kHttpVerbPOST)
{
// To prevent that an async method leaks after destroying this gameObject.
cancellationTokenSource.Token.ThrowIfCancellationRequested();
@@ -164,18 +195,21 @@ private async Task<bool> SendRequestAsync(string api, string json, string method

await new AgonesAsyncOperationWrapper(req.SendWebRequest());

bool ok = req.responseCode == (long)System.Net.HttpStatusCode.OK;
var result = new AsyncResult();

result.ok = req.responseCode == (long) HttpStatusCode.OK;

if (ok)
if (result.ok)
{
result.json = req.downloadHandler.text;
Log($"Agones SendRequest ok: {api} {req.downloadHandler.text}");
}
else
{
Log($"Agones SendRequest failed: {api} {req.error}");
}

return ok;
return result;
}

private void Log(object message)

0 comments on commit 7c50719

Please sign in to comment.
You can’t perform that action at this time.