From fb58d8657d251ca3493fe456f992c8da1ef5f537 Mon Sep 17 00:00:00 2001 From: defnotken Date: Tue, 30 Dec 2025 23:43:22 -0600 Subject: [PATCH] Lifestream IPC witrh Debug Example --- .../Enums/ResidentialAetheryteKind.cs | 10 ++ .../Interop/InteropModel/GlobalModels.cs | 1 + .../Interop/Ipc/IpcCallerLifestream.cs | 93 +++++++++++++++++++ LightlessSync/Interop/Ipc/IpcManager.cs | 7 +- LightlessSync/Plugin.cs | 9 +- LightlessSync/UI/SettingsUi.cs | 32 +++++++ LightlessSync/UI/UISharedService.cs | 6 ++ 7 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 LightlessSync/Interop/InteropModel/Enums/ResidentialAetheryteKind.cs create mode 100644 LightlessSync/Interop/InteropModel/GlobalModels.cs create mode 100644 LightlessSync/Interop/Ipc/IpcCallerLifestream.cs diff --git a/LightlessSync/Interop/InteropModel/Enums/ResidentialAetheryteKind.cs b/LightlessSync/Interop/InteropModel/Enums/ResidentialAetheryteKind.cs new file mode 100644 index 0000000..af7c18e --- /dev/null +++ b/LightlessSync/Interop/InteropModel/Enums/ResidentialAetheryteKind.cs @@ -0,0 +1,10 @@ +namespace Lifestream.Enums; + +public enum ResidentialAetheryteKind +{ + Uldah = 9, + Gridania = 2, + Limsa = 8, + Foundation = 70, + Kugane = 111, +} \ No newline at end of file diff --git a/LightlessSync/Interop/InteropModel/GlobalModels.cs b/LightlessSync/Interop/InteropModel/GlobalModels.cs new file mode 100644 index 0000000..a02cbc6 --- /dev/null +++ b/LightlessSync/Interop/InteropModel/GlobalModels.cs @@ -0,0 +1 @@ +global using AddressBookEntryTuple = (string Name, int World, int City, int Ward, int PropertyType, int Plot, int Apartment, bool ApartmentSubdivision, bool AliasEnabled, string Alias); \ No newline at end of file diff --git a/LightlessSync/Interop/Ipc/IpcCallerLifestream.cs b/LightlessSync/Interop/Ipc/IpcCallerLifestream.cs new file mode 100644 index 0000000..2ced314 --- /dev/null +++ b/LightlessSync/Interop/Ipc/IpcCallerLifestream.cs @@ -0,0 +1,93 @@ +using Dalamud.Plugin; +using Dalamud.Plugin.Ipc; +using LightlessSync.Interop.Ipc.Framework; +using LightlessSync.Services.Mediator; +using Microsoft.Extensions.Logging; + + +namespace LightlessSync.Interop.Ipc; + +public sealed class IpcCallerLifestream : IpcServiceBase +{ + private static readonly IpcServiceDescriptor LifestreamDescriptor = new("Lifestream", "Lifestream", new Version(0, 0, 0, 0)); + + private readonly ICallGateSubscriber _executeLifestreamCommand; + private readonly ICallGateSubscriber _isHere; + private readonly ICallGateSubscriber _goToHousingAddress; + private readonly ICallGateSubscriber _isBusy; + private readonly ICallGateSubscriber _abort; + private readonly ICallGateSubscriber _changeWorld; + private readonly ICallGateSubscriber _changeWorldById; + private readonly ICallGateSubscriber _aetheryteTeleport; + private readonly ICallGateSubscriber _aetheryteTeleportById; + + public IpcCallerLifestream(IDalamudPluginInterface pi, LightlessMediator lightlessMediator, ILogger logger) + : base(logger, lightlessMediator, pi, LifestreamDescriptor) + { + _executeLifestreamCommand = pi.GetIpcSubscriber("Lifestream.ExecuteCommand"); + _isHere = pi.GetIpcSubscriber("Lifestream.IsHere"); + _goToHousingAddress = pi.GetIpcSubscriber("Lifestream.GoToHousingAddress"); + _isBusy = pi.GetIpcSubscriber("Lifestream.IsBusy"); + _abort = pi.GetIpcSubscriber("Lifestream.Abort"); + _changeWorld = pi.GetIpcSubscriber("Lifestream.ChangeWorld"); + _changeWorldById = pi.GetIpcSubscriber("Lifestream.ChangeWorldById"); + _aetheryteTeleport = pi.GetIpcSubscriber("Lifestream.AetheryteTeleport"); + _aetheryteTeleportById = pi.GetIpcSubscriber("Lifestream.AetheryteTeleportById"); + CheckAPI(); + } + + public void ExecuteLifestreamCommand(string command) + { + if (!APIAvailable) return; + _executeLifestreamCommand.InvokeAction(command); + } + + public bool IsHere(AddressBookEntryTuple entry) + { + if (!APIAvailable) return false; + return _isHere.InvokeFunc(entry); + } + + public void GoToHousingAddress(AddressBookEntryTuple entry) + { + if (!APIAvailable) return; + _goToHousingAddress.InvokeAction(entry); + } + + public bool IsBusy() + { + if (!APIAvailable) return false; + return _isBusy.InvokeFunc(); + } + + public void Abort() + { + if (!APIAvailable) return; + _abort.InvokeAction(); + } + + public bool ChangeWorld(string worldName) + { + if (!APIAvailable) return false; + return _changeWorld.InvokeFunc(worldName); + } + + public bool AetheryteTeleport(string aetheryteName) + { + if (!APIAvailable) return false; + return _aetheryteTeleport.InvokeFunc(aetheryteName); + } + + public bool ChangeWorldById(uint worldId) + { + if (!APIAvailable) return false; + return _changeWorldById.InvokeFunc(worldId); + } + + + public bool AetheryteTeleportById(uint aetheryteId) + { + if (!APIAvailable) return false; + return _aetheryteTeleportById.InvokeFunc(aetheryteId); + } +} \ No newline at end of file diff --git a/LightlessSync/Interop/Ipc/IpcManager.cs b/LightlessSync/Interop/Ipc/IpcManager.cs index 59d17c7..f77b084 100644 --- a/LightlessSync/Interop/Ipc/IpcManager.cs +++ b/LightlessSync/Interop/Ipc/IpcManager.cs @@ -7,7 +7,8 @@ public sealed partial class IpcManager : DisposableMediatorSubscriberBase { public IpcManager(ILogger logger, LightlessMediator mediator, IpcCallerPenumbra penumbraIpc, IpcCallerGlamourer glamourerIpc, IpcCallerCustomize customizeIpc, IpcCallerHeels heelsIpc, - IpcCallerHonorific honorificIpc, IpcCallerMoodles moodlesIpc, IpcCallerPetNames ipcCallerPetNames, IpcCallerBrio ipcCallerBrio) : base(logger, mediator) + IpcCallerHonorific honorificIpc, IpcCallerMoodles moodlesIpc, IpcCallerPetNames ipcCallerPetNames, IpcCallerBrio ipcCallerBrio, + IpcCallerLifestream ipcCallerLifestream) : base(logger, mediator) { CustomizePlus = customizeIpc; Heels = heelsIpc; @@ -17,6 +18,7 @@ public sealed partial class IpcManager : DisposableMediatorSubscriberBase Moodles = moodlesIpc; PetNames = ipcCallerPetNames; Brio = ipcCallerBrio; + Lifestream = ipcCallerLifestream; if (Initialized) { @@ -44,8 +46,8 @@ public sealed partial class IpcManager : DisposableMediatorSubscriberBase public IpcCallerPenumbra Penumbra { get; } public IpcCallerMoodles Moodles { get; } public IpcCallerPetNames PetNames { get; } - public IpcCallerBrio Brio { get; } + public IpcCallerLifestream Lifestream { get; } private void PeriodicApiStateCheck() { @@ -58,5 +60,6 @@ public sealed partial class IpcManager : DisposableMediatorSubscriberBase Moodles.CheckAPI(); PetNames.CheckAPI(); Brio.CheckAPI(); + Lifestream.CheckAPI(); } } \ No newline at end of file diff --git a/LightlessSync/Plugin.cs b/LightlessSync/Plugin.cs index 2d46b43..e0b31b9 100644 --- a/LightlessSync/Plugin.cs +++ b/LightlessSync/Plugin.cs @@ -372,6 +372,11 @@ public sealed class Plugin : IDalamudPlugin sp.GetRequiredService(), sp.GetRequiredService())); + services.AddSingleton(sp => new IpcCallerLifestream( + pluginInterface, + sp.GetRequiredService(), + sp.GetRequiredService>())); + services.AddSingleton(sp => new IpcManager( sp.GetRequiredService>(), sp.GetRequiredService(), @@ -382,7 +387,9 @@ public sealed class Plugin : IDalamudPlugin sp.GetRequiredService(), sp.GetRequiredService(), sp.GetRequiredService(), - sp.GetRequiredService())); + sp.GetRequiredService(), + sp.GetRequiredService() + )); // Notifications / HTTP services.AddSingleton(sp => new NotificationService( diff --git a/LightlessSync/UI/SettingsUi.cs b/LightlessSync/UI/SettingsUi.cs index 1c86580..365b010 100644 --- a/LightlessSync/UI/SettingsUi.cs +++ b/LightlessSync/UI/SettingsUi.cs @@ -5,6 +5,7 @@ using Dalamud.Interface.Colors; using Dalamud.Interface.Utility; using Dalamud.Interface.Utility.Raii; using Dalamud.Utility; +using Lifestream.Enums; using LightlessSync.API.Data; using LightlessSync.API.Data.Comparer; using LightlessSync.API.Data.Enum; @@ -1259,6 +1260,37 @@ public class SettingsUi : WindowMediatorSubscriberBase UiSharedService.AttachToolTip("Use this when reporting mods being rejected from the server."); + if (_uiShared.IconTextButton(FontAwesomeIcon.Home, "Teleport to Limsa [LIFESTREAM TEST]")) + { + _ipcManager.Lifestream.ExecuteLifestreamCommand("limsa"); + } + + if (_uiShared.IconTextButton(FontAwesomeIcon.Home, "Teleport to JoyHouse [LIFESTREAM TEST]")) + { + var twintania = _dalamudUtilService.WorldData.Value + .FirstOrDefault(kvp => kvp.Value.Equals("Twintania", StringComparison.OrdinalIgnoreCase)); + + int ward = 29; + int plot = 7; + + AddressBookEntryTuple addressEntry = ( + Name: "", + World: (int)twintania.Key, + City: (int)ResidentialAetheryteKind.Kugane, + Ward: ward, + PropertyType: 0, + Plot: plot, + Apartment: 1, + ApartmentSubdivision: false, + AliasEnabled: false, + Alias: "" + ); + + _logger.LogInformation("going to: {address}", addressEntry); + + _ipcManager.Lifestream.GoToHousingAddress(addressEntry); + } + _uiShared.DrawCombo("Log Level", Enum.GetValues(), (l) => l.ToString(), (l) => { _configService.Current.LogLevel = l; diff --git a/LightlessSync/UI/UISharedService.cs b/LightlessSync/UI/UISharedService.cs index fc5225c..514f31e 100644 --- a/LightlessSync/UI/UISharedService.cs +++ b/LightlessSync/UI/UISharedService.cs @@ -79,6 +79,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase private readonly Dictionary _oauthTokenExpiry = []; private bool _penumbraExists = false; private bool _petNamesExists = false; + private bool _lifestreamExists = false; private int _serverSelectionIndex = -1; public UiSharedService(ILogger logger, IpcManager ipcManager, ApiController apiController, CacheMonitor cacheMonitor, FileDialogManager fileDialogManager, @@ -112,6 +113,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase _moodlesExists = _ipcManager.Moodles.APIAvailable; _petNamesExists = _ipcManager.PetNames.APIAvailable; _brioExists = _ipcManager.Brio.APIAvailable; + _lifestreamExists = _ipcManager.Lifestream.APIAvailable; }); UidFont = _pluginInterface.UiBuilder.FontAtlas.NewDelegateFontHandle(e => @@ -1105,6 +1107,10 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase ColorText("Brio", GetBoolColor(_brioExists)); AttachToolTip(BuildPluginTooltip("Brio", _brioExists, _ipcManager.Brio.State)); + ImGui.SameLine(); + ColorText("Lifestream", GetBoolColor(_lifestreamExists)); + AttachToolTip(BuildPluginTooltip("Lifestream", _lifestreamExists, _ipcManager.Lifestream.State)); + if (!_penumbraExists || !_glamourerExists) { ImGui.TextColored(ImGuiColors.DalamudRed, "You need to install both Penumbra and Glamourer and keep them up to date to use Lightless Sync.");