diff --git a/QSB/API/AddonDataManager.cs b/QSB/API/AddonDataManager.cs new file mode 100644 index 00000000..15731ace --- /dev/null +++ b/QSB/API/AddonDataManager.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using QSB.Utility; +using UnityEngine; + +namespace QSB.API; + +public static class AddonDataManager +{ + private static Dictionary _handlerDict = new(); + + public static void OnReceiveDataMessage(string messageType, object data) + { + DebugLog.DebugWrite($"Received data message of message type \"{messageType}\"!"); + if (!_handlerDict.ContainsKey(messageType)) + { + return; + } + + _handlerDict[messageType].action(Convert.ChangeType(data, _handlerDict[messageType].objectType)); + } + + public static void RegisterHandler(string messageType, Action handler) + { + DebugLog.DebugWrite($"Registering handler for \"{messageType}\" with type of {typeof(T).Name}"); + _handlerDict.Add(messageType, (typeof(T), handler)); + } +} diff --git a/QSB/API/IQSBAPI.cs b/QSB/API/IQSBAPI.cs new file mode 100644 index 00000000..50c33d9f --- /dev/null +++ b/QSB/API/IQSBAPI.cs @@ -0,0 +1,14 @@ +using System; + +namespace QSB.API; + +internal interface IQSBAPI +{ + uint GetLocalPlayerID(); + + void SetCustomData(uint playerId, string key, T data); + T GetCustomData(uint playerId, string key); + + void SendMessage(string messageType, T data); + void RegisterHandler(string messageType, Action action); +} diff --git a/QSB/API/Messages/AddonDataMessage.cs b/QSB/API/Messages/AddonDataMessage.cs new file mode 100644 index 00000000..792fcd0c --- /dev/null +++ b/QSB/API/Messages/AddonDataMessage.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Threading.Tasks; +using QSB.Messaging; + +namespace QSB.API.Messages; +public class AddonDataMessage : QSBMessage<(string messageType, byte[] data)> +{ + public AddonDataMessage(string messageType, object data) : base((messageType, ObjectToByteArray(data))) {} + + private static byte[] ObjectToByteArray(object obj) + { + var bf = new BinaryFormatter(); + using var ms = new MemoryStream(); + bf.Serialize(ms, obj); + return ms.ToArray(); + } + + private static object ByteArrayToObject(byte[] arrBytes) + { + using var memStream = new MemoryStream(); + var binForm = new BinaryFormatter(); + memStream.Write(arrBytes, 0, arrBytes.Length); + memStream.Seek(0, SeekOrigin.Begin); + var obj = binForm.Deserialize(memStream); + return obj; + } + + public override void OnReceiveRemote() + { + var obj = ByteArrayToObject(Data.data); + AddonDataManager.OnReceiveDataMessage(Data.messageType, obj); + } +} diff --git a/QSB/API/QSBAPI.cs b/QSB/API/QSBAPI.cs new file mode 100644 index 00000000..08c83bb6 --- /dev/null +++ b/QSB/API/QSBAPI.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using QSB.API.Messages; +using QSB.Messaging; +using QSB.Player; + +namespace QSB.API; + +internal class QSBAPI : IQSBAPI +{ + public uint GetLocalPlayerID() => QSBPlayerManager.LocalPlayerId; + + public void SetCustomData(uint playerId, string key, T data) => QSBPlayerManager.GetPlayer(playerId).SetCustomData(key, data); + public T GetCustomData(uint playerId, string key) => QSBPlayerManager.GetPlayer(playerId).GetCustomData(key); + + public void SendMessage(string messageType, T data) + { + new AddonDataMessage(messageType, data).Send(); + } + + public void RegisterHandler(string messageType, Action action) + { + AddonDataManager.RegisterHandler(messageType, action); + } +} diff --git a/QSB/QSB.csproj b/QSB/QSB.csproj index 4116a8ac..3a96ae99 100644 --- a/QSB/QSB.csproj +++ b/QSB/QSB.csproj @@ -68,6 +68,7 @@ + diff --git a/QSB/QSBCore.cs b/QSB/QSBCore.cs index 67f241bb..8ab69288 100644 --- a/QSB/QSBCore.cs +++ b/QSB/QSBCore.cs @@ -16,6 +16,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using QSB.API; using UnityEngine; using UnityEngine.InputSystem; @@ -86,6 +87,8 @@ public class QSBCore : ModBehaviour "PacificEngine.OW_Randomizer", }; + public override object GetApi() => new QSBAPI(); + private static void DetermineGameVendor() { var gameAssemblyTypes = typeof(AstroObject).Assembly.GetTypes();