Skip to content

Instantly share code, notes, and snippets.

@selalipop
Last active September 9, 2022 20:29
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save selalipop/733202cc5b4631f55e116a1d3011d94c to your computer and use it in GitHub Desktop.
Save selalipop/733202cc5b4631f55e116a1d3011d94c to your computer and use it in GitHub Desktop.
Using Server-Sent-Events in Unity
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);
}
}
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;
}
}
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));
};
}
}
public struct ServerSentEvent
{
public ServerSentEventType Type;
public string Data;
public override string ToString()
{
return $"{nameof(Type)}: {Type}, {nameof(Data)}: {Data}";
}
}
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;
}
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