Last active
September 9, 2022 20:29
-
-
Save selalipop/733202cc5b4631f55e116a1d3011d94c to your computer and use it in GitHub Desktop.
Using Server-Sent-Events in Unity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Backend; | |
using Proyecto26; | |
using UnityEngine; | |
using UnityEngine.Networking; | |
public class SSETest : MonoBehaviour | |
{ | |
void Start() | |
{ | |
var fileUrl = "mysse.com/sse"; | |
var sseHandler = new JsonServerSentEventHandler<GameState>(); | |
sseHandler.OnJsonEventReceived += gameState => | |
{ | |
//Called when the server sends an SSE event with the type "message" | |
Debug.Log($"Current Players: {string.Join(" , ", gameState.Players)}"); | |
}; | |
RestClient.Get(new RequestHelper | |
{ | |
Uri = fileUrl, | |
DownloadHandler = sseHandler, | |
Retries = int.MaxValue, | |
RetrySecondsDelay = 5 | |
}).Catch(Debug.LogError); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Newtonsoft.Json; | |
///Use of Newtonsoft.Json is fully optional | |
namespace Backend | |
{ | |
[JsonObject] | |
public struct GameState | |
{ | |
[JsonProperty("maxPlayers")] public int MaxPlayers; | |
[JsonProperty("imposterCount")] public int ImposterCount; | |
[JsonProperty("phase")] public string Phase; | |
[JsonProperty("players")] public string[] Players; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using Newtonsoft.Json; | |
public class JsonServerSentEventHandler<T> : ServerSentEventHandler | |
{ | |
public event Action<T> OnJsonEventReceived; | |
public JsonServerSentEventHandler() | |
{ | |
OnServerSentEventReceived += sse => | |
{ | |
// To Use Built-In Unity JSON Serialization, replace with this: | |
// | |
// OnJsonEventReceived?.Invoke(JsonUtility.FromJson<T>(sse.Data)); | |
// | |
OnJsonEventReceived?.Invoke(JsonConvert.DeserializeObject<T>(sse.Data)); | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public struct ServerSentEvent | |
{ | |
public ServerSentEventType Type; | |
public string Data; | |
public override string ToString() | |
{ | |
return $"{nameof(Type)}: {Type}, {nameof(Data)}: {Data}"; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Text; | |
using System.Text.RegularExpressions; | |
using UnityEngine.Networking; | |
public class ServerSentEventHandler : DownloadHandlerScript | |
{ | |
private readonly MemoryStream dataStream = new MemoryStream(1024); | |
private readonly Regex eventRegex = new Regex(@"event:?(.*)"); | |
private readonly Regex dataRegex = new Regex(@"data:?(.*)"); | |
protected override bool ReceiveData(byte[] newData, int dataLength) | |
{ | |
foreach (var character in newData) | |
{ | |
dataStream.WriteByte(character); | |
if (character != '\n') continue; | |
var stringData = new byte[dataStream.Length]; | |
Array.Copy(dataStream.GetBuffer(), stringData, dataStream.Length); | |
HandleLine(Encoding.UTF8.GetString(stringData)); | |
dataStream.SetLength(0); | |
} | |
return true; | |
} | |
private ServerSentEventType? currentType; | |
private string currentData; | |
protected void HandleLine(string newLine) | |
{ | |
var eventMatch = eventRegex.Match(newLine); | |
if (eventMatch.Success) | |
{ | |
currentType = ServerSentEventTypeExt.FromName(eventMatch.Groups[1].Value); | |
} | |
var dataMatch = dataRegex.Match(newLine); | |
if (dataMatch.Success) | |
{ | |
currentData = dataMatch.Groups[1].Value; | |
} | |
if (currentData == null || currentType == null) return; | |
OnServerSentEventReceived?.Invoke(new ServerSentEvent | |
{ | |
Data = currentData, | |
Type = currentType.Value | |
}); | |
currentData = null; | |
currentType = null; | |
} | |
public event Action<ServerSentEvent> OnServerSentEventReceived; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using UnityEngine; | |
public enum ServerSentEventType | |
{ | |
Unknown, | |
Message | |
} | |
public static class ServerSentEventTypeExt | |
{ | |
public static readonly ServerSentEventType[] Values = | |
(ServerSentEventType[]) Enum.GetValues(typeof(ServerSentEventType)); | |
public static string ToName(this ServerSentEventType eventType) | |
{ | |
switch (eventType) | |
{ | |
case ServerSentEventType.Message: | |
return "message"; | |
case ServerSentEventType.Unknown: | |
return "unknown"; | |
default: | |
return ""; | |
} | |
} | |
public static ServerSentEventType FromName(string name) | |
{ | |
foreach (var eventType in Values) | |
{ | |
if (eventType.ToName().Equals(name, StringComparison.InvariantCultureIgnoreCase)) | |
{ | |
return eventType; | |
} | |
} | |
Debug.LogWarning($"Unknown SSE event type encountered: {name}"); | |
return ServerSentEventType.Unknown; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment