ipc: add custom serializer for IGameObject

fixes #1924
This commit is contained in:
goat 2024-07-18 23:08:29 +02:00
parent 40624c0c12
commit 604d1b2e85
3 changed files with 98 additions and 4 deletions

View file

@ -4,6 +4,8 @@ using System.Linq;
using System.Reflection;
using Dalamud.Plugin.Ipc.Exceptions;
using Dalamud.Plugin.Ipc.Internal.Converters;
using Newtonsoft.Json;
using Serilog;
@ -206,7 +208,10 @@ internal class CallGateChannel
if (obj is null)
return null;
var json = JsonConvert.SerializeObject(obj);
var settings = new JsonSerializerSettings();
settings.Converters.Add(new GameObjectConverter());
var json = JsonConvert.SerializeObject(obj, settings);
try
{
@ -241,7 +246,7 @@ internal class CallGateChannel
try
{
return JsonConvert.DeserializeObject(json, type);
return JsonConvert.DeserializeObject(json, type, settings);
}
catch (Exception ex)
{

View file

@ -0,0 +1,49 @@
using System.IO;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Utility;
using Newtonsoft.Json;
namespace Dalamud.Plugin.Ipc.Internal.Converters;
/// <summary>
/// JSON converter for IGameObject and its derived types.
/// </summary>
internal sealed class GameObjectConverter : JsonConverter<IGameObject>
{
/// <inheritdoc/>
public override void WriteJson(JsonWriter writer, IGameObject? value, JsonSerializer serializer) =>
writer.WriteValue(value?.Address.ToString());
/// <inheritdoc/>
public override IGameObject? ReadJson(
JsonReader reader,
Type objectType,
IGameObject? existingValue,
bool hasExistingValue,
JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
if (reader.TokenType != JsonToken.String)
throw new InvalidDataException("String is expected.");
if (!nint.TryParse(reader.Value as string, out var v))
throw new InvalidDataException("Could not parse address.");
if (!ThreadSafety.IsMainThread)
throw new InvalidOperationException("Cannot send GameObjects from non-main thread over IPC.");
var ot = Service<ObjectTable>.Get();
foreach (var go in ot)
{
if (go.Address == v)
return go;
}
return ot.CreateObjectReference(v);
}
}