qstcompanion v1.0.1
This commit is contained in:
parent
3e10cbbbf2
commit
44c67ab71b
79 changed files with 21148 additions and 0 deletions
|
|
@ -0,0 +1,262 @@
|
|||
using System;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
||||
namespace QuestionableCompanion.Services;
|
||||
|
||||
public class LifestreamIPC : IDisposable
|
||||
{
|
||||
private readonly IPluginLog log;
|
||||
|
||||
private readonly IDalamudPluginInterface pluginInterface;
|
||||
|
||||
private ICallGateSubscriber<bool>? isBusySubscriber;
|
||||
|
||||
private ICallGateSubscriber<string, bool>? changeWorldSubscriber;
|
||||
|
||||
private ICallGateSubscriber<uint, bool>? changeWorldByIdSubscriber;
|
||||
|
||||
private ICallGateSubscriber<object>? abortSubscriber;
|
||||
|
||||
private bool _isAvailable;
|
||||
|
||||
private bool _ipcInitialized;
|
||||
|
||||
private DateTime lastAvailabilityCheck = DateTime.MinValue;
|
||||
|
||||
private const int AvailabilityCheckCooldownSeconds = 5;
|
||||
|
||||
private bool hasPerformedInitialCheck;
|
||||
|
||||
public bool IsAvailable
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isAvailable;
|
||||
}
|
||||
private set
|
||||
{
|
||||
_isAvailable = value;
|
||||
}
|
||||
}
|
||||
|
||||
public LifestreamIPC(IPluginLog log, IDalamudPluginInterface pluginInterface)
|
||||
{
|
||||
this.log = log;
|
||||
this.pluginInterface = pluginInterface;
|
||||
}
|
||||
|
||||
private void InitializeIPC()
|
||||
{
|
||||
if (_ipcInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
isBusySubscriber = pluginInterface.GetIpcSubscriber<bool>("Lifestream.IsBusy");
|
||||
changeWorldSubscriber = pluginInterface.GetIpcSubscriber<string, bool>("Lifestream.ChangeWorld");
|
||||
changeWorldByIdSubscriber = pluginInterface.GetIpcSubscriber<uint, bool>("Lifestream.ChangeWorldById");
|
||||
abortSubscriber = pluginInterface.GetIpcSubscriber<object>("Lifestream.Abort");
|
||||
_ipcInitialized = true;
|
||||
log.Debug("[LifestreamIPC] IPC subscribers initialized (lazy-loading enabled)");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error("[LifestreamIPC] Failed to initialize subscribers: " + ex.Message);
|
||||
_isAvailable = false;
|
||||
_ipcInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryEnsureAvailable(bool forceCheck = false)
|
||||
{
|
||||
if (_isAvailable)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!_ipcInitialized)
|
||||
{
|
||||
InitializeIPC();
|
||||
}
|
||||
if (!_ipcInitialized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DateTime now = DateTime.Now;
|
||||
if (!forceCheck && hasPerformedInitialCheck && (now - lastAvailabilityCheck).TotalSeconds < 5.0)
|
||||
{
|
||||
log.Debug($"[LifestreamIPC] Cooldown active - skipping check (last check: {(now - lastAvailabilityCheck).TotalSeconds:F1}s ago)");
|
||||
return false;
|
||||
}
|
||||
if (forceCheck)
|
||||
{
|
||||
log.Information("[LifestreamIPC] FORCED availability check requested");
|
||||
}
|
||||
lastAvailabilityCheck = now;
|
||||
hasPerformedInitialCheck = true;
|
||||
try
|
||||
{
|
||||
if (isBusySubscriber == null)
|
||||
{
|
||||
log.Debug("[LifestreamIPC] isBusySubscriber is NULL - cannot check availability");
|
||||
_isAvailable = false;
|
||||
return false;
|
||||
}
|
||||
log.Debug("[LifestreamIPC] Attempting to invoke Lifestream.IsBusy()...");
|
||||
bool testBusy = isBusySubscriber.InvokeFunc();
|
||||
if (!_isAvailable)
|
||||
{
|
||||
_isAvailable = true;
|
||||
log.Information($"[LifestreamIPC] Lifestream is now available (Busy: {testBusy})");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.Debug($"[LifestreamIPC] Lifestream still available (Busy: {testBusy})");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!hasPerformedInitialCheck)
|
||||
{
|
||||
log.Warning("[LifestreamIPC] First availability check FAILED: " + ex.GetType().Name + ": " + ex.Message);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.Debug("[LifestreamIPC] Lifestream not yet available: " + ex.Message);
|
||||
}
|
||||
_isAvailable = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsBusy()
|
||||
{
|
||||
TryEnsureAvailable();
|
||||
if (!_isAvailable || isBusySubscriber == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
return isBusySubscriber.InvokeFunc();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error("[LifestreamIPC] Error checking busy status: " + ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ForceCheckAvailability()
|
||||
{
|
||||
log.Information("[LifestreamIPC] ========================================");
|
||||
log.Information("[LifestreamIPC] === FORCING AVAILABILITY CHECK ===");
|
||||
log.Information("[LifestreamIPC] ========================================");
|
||||
bool result = TryEnsureAvailable(forceCheck: true);
|
||||
log.Information($"[LifestreamIPC] Force check result: {result}");
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool ChangeWorld(string worldName)
|
||||
{
|
||||
TryEnsureAvailable();
|
||||
log.Information("[LifestreamIPC] ========================================");
|
||||
log.Information("[LifestreamIPC] === CHANGE WORLD REQUEST ===");
|
||||
log.Information("[LifestreamIPC] ========================================");
|
||||
log.Information("[LifestreamIPC] Target World: '" + worldName + "'");
|
||||
log.Information($"[LifestreamIPC] IsAvailable: {_isAvailable}");
|
||||
log.Information($"[LifestreamIPC] changeWorldSubscriber != null: {changeWorldSubscriber != null}");
|
||||
if (!_isAvailable || changeWorldSubscriber == null)
|
||||
{
|
||||
log.Error("[LifestreamIPC] CANNOT CHANGE WORLD - Lifestream not available!");
|
||||
log.Error("[LifestreamIPC] Make sure Lifestream plugin is installed and enabled!");
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
log.Information("[LifestreamIPC] Invoking Lifestream.ChangeWorld('" + worldName + "')...");
|
||||
bool num = changeWorldSubscriber.InvokeFunc(worldName);
|
||||
if (num)
|
||||
{
|
||||
log.Information("[LifestreamIPC] ========================================");
|
||||
log.Information("[LifestreamIPC] WORLD CHANGE ACCEPTED: " + worldName);
|
||||
log.Information("[LifestreamIPC] ========================================");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.Warning("[LifestreamIPC] ========================================");
|
||||
log.Warning("[LifestreamIPC] WORLD CHANGE REJECTED: " + worldName);
|
||||
log.Warning("[LifestreamIPC] ========================================");
|
||||
log.Warning("[LifestreamIPC] Possible reasons:");
|
||||
log.Warning("[LifestreamIPC] - Lifestream is busy");
|
||||
log.Warning("[LifestreamIPC] - World name is invalid");
|
||||
log.Warning("[LifestreamIPC] - Cannot visit this world");
|
||||
}
|
||||
return num;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error("[LifestreamIPC] ========================================");
|
||||
log.Error("[LifestreamIPC] ERROR REQUESTING WORLD CHANGE!");
|
||||
log.Error("[LifestreamIPC] ========================================");
|
||||
log.Error("[LifestreamIPC] Error: " + ex.Message);
|
||||
log.Error("[LifestreamIPC] Stack: " + ex.StackTrace);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ChangeWorldById(uint worldId)
|
||||
{
|
||||
TryEnsureAvailable();
|
||||
if (!_isAvailable || changeWorldByIdSubscriber == null)
|
||||
{
|
||||
log.Warning("[LifestreamIPC] Lifestream not available for world change");
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
log.Information($"[LifestreamIPC] Requesting world change to ID: {worldId}");
|
||||
bool num = changeWorldByIdSubscriber.InvokeFunc(worldId);
|
||||
if (num)
|
||||
{
|
||||
log.Information($"[LifestreamIPC] World change request accepted for ID: {worldId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.Warning($"[LifestreamIPC] World change request rejected for ID: {worldId}");
|
||||
}
|
||||
return num;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error("[LifestreamIPC] Error requesting world change by ID: " + ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Abort()
|
||||
{
|
||||
TryEnsureAvailable();
|
||||
if (!_isAvailable || abortSubscriber == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
abortSubscriber.InvokeAction();
|
||||
log.Information("[LifestreamIPC] Abort request sent to Lifestream");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.Error("[LifestreamIPC] Error aborting Lifestream: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
log.Information("[LifestreamIPC] Service disposed");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue