TheWatcher/AutoShutdown/Plogon.cs

158 lines
5.5 KiB
C#
Raw Permalink Normal View History

2024-03-08 23:34:40 +00:00
using System;
2024-03-21 01:01:17 +00:00
using System.Collections.Generic;
using System.Linq;
2024-03-21 18:56:30 +00:00
using System.Net.Http;
2024-03-08 23:34:40 +00:00
using System.Reflection;
2024-03-21 01:01:17 +00:00
using System.Threading.Tasks;
2024-03-10 15:38:09 +00:00
using System.Windows.Forms;
2024-03-08 23:34:40 +00:00
using AutoRetainerAPI;
2024-03-21 01:01:17 +00:00
using Dalamud;
using Dalamud.Game;
2024-03-08 23:34:40 +00:00
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using ECommons;
2024-03-12 12:03:47 +00:00
using FFXIVClientStructs.FFXIV.Client.System.Framework;
2024-03-21 01:01:17 +00:00
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using FFXIVClientStructs.FFXIV.Component.GUI;
2024-03-08 23:34:40 +00:00
using LLib;
2024-03-21 01:01:17 +00:00
using LLib.GameUI;
using Task = System.Threading.Tasks.Task;
2024-03-08 23:34:40 +00:00
namespace AutoShutdown;
2024-03-10 15:48:56 +00:00
public sealed class Plogon : IDalamudPlugin
2024-03-08 23:34:40 +00:00
{
2024-03-21 18:56:30 +00:00
private readonly HttpClient _httpClient = new() { Timeout = TimeSpan.FromSeconds(1) };
2024-03-21 01:01:17 +00:00
private readonly nint _skipMovieAddress;
private readonly byte[] _skipMovieOriginalBytes;
2024-03-08 23:34:40 +00:00
private readonly AutoRetainerApi _autoRetainerApi;
private readonly DalamudReflector _reflector;
private readonly IPluginLog _pluginLog;
private readonly IClientState _clientState;
2024-03-21 01:01:17 +00:00
private readonly IGameGui _gameGui;
private readonly IFramework _framework;
2024-03-08 23:34:40 +00:00
2024-07-02 17:39:20 +00:00
public Plogon(IDalamudPluginInterface pluginInterface, IFramework framework, IPluginLog pluginLog,
2024-03-21 01:01:17 +00:00
IClientState clientState, IGameGui gameGui, ISigScanner sigScanner)
2024-03-08 23:34:40 +00:00
{
2024-03-21 01:01:17 +00:00
_skipMovieAddress = sigScanner.ScanText("48 01 8E ?? ?? ?? ?? 48 81 BE ?? ?? ?? ?? 60 EA 00 00");
SafeMemory.ReadBytes(_skipMovieAddress, 7, out _skipMovieOriginalBytes);
2024-03-08 23:34:40 +00:00
ECommonsMain.Init(pluginInterface, this);
_autoRetainerApi = new AutoRetainerApi();
_reflector = new DalamudReflector(pluginInterface, framework, pluginLog);
2024-03-21 01:01:17 +00:00
_framework = framework;
2024-03-08 23:34:40 +00:00
_pluginLog = pluginLog;
_clientState = clientState;
2024-03-21 01:01:17 +00:00
_gameGui = gameGui;
2024-03-08 23:34:40 +00:00
2024-03-21 01:01:17 +00:00
_clientState.Logout += OnLogout;
_framework.Update += FrameworkUpdate;
2024-03-08 23:34:40 +00:00
2024-03-21 01:01:17 +00:00
_framework.RunOnTick(MoveToBackground, TimeSpan.FromSeconds(10));
// we don't want to watch movies, regardless of how long we're gone - 7 byte NOP for the 'add [rsi+1110h], rcx'
SafeMemory.WriteBytes(_skipMovieAddress, [0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00]);
unsafe
{
var lobby = AgentLobby.Instance();
if (lobby != null)
lobby->IdleTime = 0;
}
2024-03-08 23:34:40 +00:00
}
2024-03-21 01:01:17 +00:00
private DateTime ShutdownAt { get; } = DateTime.Now.AddDays(2);
private unsafe void FrameworkUpdate(IFramework _)
{
2024-03-21 18:56:30 +00:00
if (DateTime.Now > ShutdownAt && _gameGui.TryGetAddonByName<AtkUnitBase>("_TitleMenu", out var _))
2024-03-21 01:01:17 +00:00
{
Environment.Exit(0);
}
}
2024-03-08 23:34:40 +00:00
2024-03-21 01:01:17 +00:00
private bool IsMultiAndNightMode()
2024-03-08 23:34:40 +00:00
{
if (_autoRetainerApi.Ready && _reflector.TryGetDalamudPlugin("AutoRetainer", out var autoRetainer, false, true))
{
2024-03-21 01:01:17 +00:00
var mm = autoRetainer.GetType().Assembly.GetType("AutoRetainer.Modules.Multi.MultiMode")!;
bool multi = (bool)mm.GetProperty("Active", BindingFlags.Static | BindingFlags.NonPublic)!.GetValue(null)!;
2024-03-08 23:34:40 +00:00
2024-03-21 01:01:17 +00:00
var config =
autoRetainer.GetType().GetProperty("C", BindingFlags.Static | BindingFlags.NonPublic)!.GetValue(null)!;
bool nightMode = (bool)config.GetType().GetField("NightMode", BindingFlags.Instance | BindingFlags.Public)!
.GetValue(config)!;
2024-03-08 23:34:40 +00:00
2024-03-21 01:01:17 +00:00
//_pluginLog.Information($"AR: multi={multi}, night={nightMode}");
return multi && nightMode;
}
return false;
}
private void MoveToBackground()
{
if (IsMultiAndNightMode())
{
// move to background using alt+esc
unsafe
2024-03-08 23:34:40 +00:00
{
2024-03-21 01:01:17 +00:00
if (!Framework.Instance()->WindowInactive)
SendKeys.SendWait("%({esc})");
2024-03-08 23:34:40 +00:00
}
}
2024-03-21 01:01:17 +00:00
}
2024-03-10 15:38:09 +00:00
2024-03-21 01:01:17 +00:00
private void OnLogout()
{
if (IsMultiAndNightMode())
2024-03-12 12:03:47 +00:00
{
2024-03-21 01:01:17 +00:00
List<TimeSpan> nextVesselTimes =
_autoRetainerApi.GetRegisteredCharacters().SelectMany(localContentId =>
{
var data = _autoRetainerApi.GetOfflineCharacterData(localContentId);
return data.OfflineSubmarineData.Where(x => data.EnabledSubs.Contains(x.Name))
.Select(x => TimeSpan.FromSeconds(x.ReturnTime - Framework.GetServerTime()))
.Select(x => x <= TimeSpan.Zero ? TimeSpan.Zero : x)
.ToList();
})
.ToList();
if (nextVesselTimes.Count > 0)
{
TimeSpan next = nextVesselTimes.Min();
_pluginLog.Information($"Next vessel time: {next}");
2024-03-21 18:56:30 +00:00
if (next != TimeSpan.Zero)
2024-03-21 01:01:17 +00:00
{
2024-03-21 18:56:30 +00:00
Task.Factory.StartNew(async () =>
2024-03-21 01:01:17 +00:00
{
2024-03-21 18:56:30 +00:00
try
{
await _httpClient.PostAsync(new Uri($"http://localhost:12994/{next.TotalSeconds:F0}"),
null);
}
catch (Exception e)
{
_pluginLog.Warning(e, "Unable to send IPC");
}
}, TaskCreationOptions.LongRunning);
}
2024-03-21 01:01:17 +00:00
}
2024-03-12 12:03:47 +00:00
}
2024-03-21 01:01:17 +00:00
MoveToBackground();
2024-03-08 23:34:40 +00:00
}
public void Dispose()
{
2024-03-21 01:01:17 +00:00
SafeMemory.WriteBytes(_skipMovieAddress, _skipMovieOriginalBytes);
_framework.Update -= FrameworkUpdate;
_clientState.Logout -= OnLogout;
2024-03-08 23:34:40 +00:00
_reflector.Dispose();
_autoRetainerApi.Dispose();
ECommonsMain.Dispose();
}
}