Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of GameServer() for Unity #1169

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions examples/unity-simple/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ sysinfo.txt
# Builds
*.apk
*.unitypackage

# Rider plugins
/Assets/Plugins/
/Assets/Plugins.meta
3 changes: 3 additions & 0 deletions examples/unity-simple/Assets/Scripts/Agones/model.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions examples/unity-simple/Assets/Scripts/Agones/third_party.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions examples/unity-simple/Assets/Scripts/UdpEchoServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ async void Update()

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

case "GameServer":
var gameserver = await agones.GameServer();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[future nit.] the C# style guide recommends suffixing async methods with Async. e.g. GameServerAsync.

You should add "Async" as the suffix of every async method name you write.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be a good thing. But we already have the rest of the SDK being async, and it wasn't written that way in the first place 😞 we probably should at least be consistent?

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)
Expand Down
2 changes: 1 addition & 1 deletion examples/unity-simple/Packages/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
44 changes: 23 additions & 21 deletions examples/unity-simple/ProjectSettings/EditorSettings.asset
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion examples/unity-simple/ProjectSettings/ProjectVersion.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
m_EditorVersion: 2018.4.2f1
m_EditorVersion: 2018.4.12f1
1 change: 1 addition & 0 deletions examples/unity-simple/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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() |
6 changes: 3 additions & 3 deletions pkg/sdk/sdk.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 45 additions & 11 deletions sdks/unity/AgonesSdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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.
Expand Down Expand Up @@ -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);
Copy link
Contributor

@pooneh-m pooneh-m Nov 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need this? -> .ContinueWith(task => task.Result.ok)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are now no longer returning a Task<bool> but a Task<AsyncResult> from SendRequestAsync, since we needed more information from it.

}

/// <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>;
Copy link
Contributor

@pooneh-m pooneh-m Nov 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use a JSON deserializer, such as newtonsoft that accepts the predefined objects here with json names, instead of converting them to a dictionary and find the values?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish. We can't use NuGet, so we can't pull in newtonsoft. There is a Unity specific version of it, but it's huge, and seems like a massive dependency. And we can't force Users to pull things down from the asset store.

MiniJSON is lightweight, and does what we need, even though we have to do more work.

Copy link
Contributor

@pooneh-m pooneh-m Nov 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't use NuGet

Why not?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not something Unity supports. Also they have older / kinda hacked version of Mono running in there. It's a whole thing.

return new GameServer(data);
}

/// <summary>
Expand All @@ -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>
Expand All @@ -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>
Expand All @@ -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>
Expand All @@ -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

Expand All @@ -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();
Expand All @@ -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)
Expand Down
Loading