using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Plugin; using Dalamud.Plugin.Ipc; using LightlessSync.Interop.Ipc.Framework; using LightlessSync.Services; using LightlessSync.Services.Mediator; using Microsoft.Extensions.Logging; namespace LightlessSync.Interop.Ipc; public sealed class IpcCallerPetNames : IpcServiceBase { private static readonly IpcServiceDescriptor PetRenamerDescriptor = new("PetRenamer", "Pet Renamer", new Version(0, 0, 0, 0)); private readonly ILogger _logger; private readonly DalamudUtilService _dalamudUtil; private readonly LightlessMediator _lightlessMediator; private readonly ICallGateSubscriber _petnamesReady; private readonly ICallGateSubscriber _petnamesDisposing; private readonly ICallGateSubscriber<(uint, uint)> _apiVersion; private readonly ICallGateSubscriber _enabled; private readonly ICallGateSubscriber _playerDataChanged; private readonly ICallGateSubscriber _getPlayerData; private readonly ICallGateSubscriber _setPlayerData; private readonly ICallGateSubscriber _clearPlayerData; public IpcCallerPetNames(ILogger logger, IDalamudPluginInterface pi, DalamudUtilService dalamudUtil, LightlessMediator lightlessMediator) : base(logger, lightlessMediator, pi, PetRenamerDescriptor) { _logger = logger; _dalamudUtil = dalamudUtil; _lightlessMediator = lightlessMediator; _petnamesReady = pi.GetIpcSubscriber("PetRenamer.OnReady"); _petnamesDisposing = pi.GetIpcSubscriber("PetRenamer.OnDisposing"); _apiVersion = pi.GetIpcSubscriber<(uint, uint)>("PetRenamer.ApiVersion"); _enabled = pi.GetIpcSubscriber("PetRenamer.IsEnabled"); _playerDataChanged = pi.GetIpcSubscriber("PetRenamer.OnPlayerDataChanged"); _getPlayerData = pi.GetIpcSubscriber("PetRenamer.GetPlayerData"); _setPlayerData = pi.GetIpcSubscriber("PetRenamer.SetPlayerData"); _clearPlayerData = pi.GetIpcSubscriber("PetRenamer.ClearPlayerData"); _petnamesReady.Subscribe(OnPetNicknamesReady); _petnamesDisposing.Subscribe(OnPetNicknamesDispose); _playerDataChanged.Subscribe(OnLocalPetNicknamesDataChange); CheckAPI(); } private void OnPetNicknamesReady() { CheckAPI(); _lightlessMediator.Publish(new PetNamesReadyMessage()); } private void OnPetNicknamesDispose() { _lightlessMediator.Publish(new PetNamesMessage(string.Empty)); } protected override IpcConnectionState EvaluateState() { var state = base.EvaluateState(); if (state != IpcConnectionState.Available) { return state; } try { var enabled = _enabled?.InvokeFunc() ?? false; if (!enabled) { return IpcConnectionState.PluginDisabled; } var version = _apiVersion?.InvokeFunc() ?? (0u, 0u); return version.Item1 == 4 && version.Item2 >= 0 ? IpcConnectionState.Available : IpcConnectionState.VersionMismatch; } catch (Exception ex) { _logger.LogDebug(ex, "Failed to query Pet Renamer API version"); return IpcConnectionState.Error; } } public string GetLocalNames() { if (!APIAvailable) return string.Empty; try { string localNameData = _getPlayerData.InvokeFunc(); return string.IsNullOrEmpty(localNameData) ? string.Empty : localNameData; } catch (Exception e) { _logger.LogWarning(e, "Could not obtain Pet Nicknames data"); } return string.Empty; } public async Task SetPlayerData(nint character, string playerData) { if (!APIAvailable) return; _logger.LogTrace("Applying Pet Nicknames data to {chara}", character.ToString("X")); try { await _dalamudUtil.RunOnFrameworkThread(() => { if (string.IsNullOrEmpty(playerData)) { var gameObj = _dalamudUtil.CreateGameObject(character); if (gameObj is IPlayerCharacter pc) { _clearPlayerData.InvokeAction(pc.ObjectIndex); } } else { _setPlayerData.InvokeAction(playerData); } }).ConfigureAwait(false); } catch (Exception e) { _logger.LogWarning(e, "Could not apply Pet Nicknames data"); } } public async Task ClearPlayerData(nint characterPointer) { if (!APIAvailable) return; try { await _dalamudUtil.RunOnFrameworkThread(() => { var gameObj = _dalamudUtil.CreateGameObject(characterPointer); if (gameObj is IPlayerCharacter pc) { _logger.LogTrace("Pet Nicknames removing for {addr}", pc.Address.ToString("X")); _clearPlayerData.InvokeAction(pc.ObjectIndex); } }).ConfigureAwait(false); } catch (Exception e) { _logger.LogWarning(e, "Could not clear Pet Nicknames data"); } } private void OnLocalPetNicknamesDataChange(string data) { _lightlessMediator.Publish(new PetNamesMessage(data)); } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (!disposing) { return; } _petnamesReady.Unsubscribe(OnPetNicknamesReady); _petnamesDisposing.Unsubscribe(OnPetNicknamesDispose); _playerDataChanged.Unsubscribe(OnLocalPetNicknamesDataChange); } }