forked from aly/qstbak
149 lines
4.4 KiB
C#
149 lines
4.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using Dalamud.Game.Addon.Lifecycle;
|
|
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
|
using Dalamud.Plugin.Services;
|
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
|
using LLib.GameUI;
|
|
using Microsoft.Extensions.Logging;
|
|
using Questionable.Model.Questing;
|
|
|
|
namespace Questionable.Controller.GameUi;
|
|
|
|
internal sealed class ChocoboNameHandler : IDisposable
|
|
{
|
|
private static readonly HashSet<ElementId> ChocoboQuestIds = new HashSet<ElementId>
|
|
{
|
|
new QuestId(700),
|
|
new QuestId(701),
|
|
new QuestId(702)
|
|
};
|
|
|
|
private readonly QuestController _questController;
|
|
|
|
private readonly Configuration _configuration;
|
|
|
|
private readonly IAddonLifecycle _addonLifecycle;
|
|
|
|
private readonly ILogger<ChocoboNameHandler> _logger;
|
|
|
|
private bool _awaitingConfirmation;
|
|
|
|
public ChocoboNameHandler(QuestController questController, Configuration configuration, IAddonLifecycle addonLifecycle, ILogger<ChocoboNameHandler> logger)
|
|
{
|
|
_questController = questController;
|
|
_configuration = configuration;
|
|
_addonLifecycle = addonLifecycle;
|
|
_logger = logger;
|
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "InputString", OnInputStringSetup);
|
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "SelectYesno", OnSelectYesNoSetup);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "SelectYesno", OnSelectYesNoSetup);
|
|
_addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "InputString", OnInputStringSetup);
|
|
}
|
|
|
|
private bool IsChocoboQuestActive()
|
|
{
|
|
QuestController.QuestProgress currentQuest = _questController.CurrentQuest;
|
|
if (currentQuest != null)
|
|
{
|
|
return ChocoboQuestIds.Contains(currentQuest.Quest.Id);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private unsafe void OnInputStringSetup(AddonEvent type, AddonArgs args)
|
|
{
|
|
if (_questController.IsRunning && IsChocoboQuestActive())
|
|
{
|
|
AtkUnitBase* address = (AtkUnitBase*)args.Addon.Address;
|
|
if (LAddon.IsAddonReady(address))
|
|
{
|
|
string validatedChocoboName = GetValidatedChocoboName(_configuration.Advanced.ChocoboName);
|
|
_logger.LogInformation("Entering chocobo name: {Name}", validatedChocoboName);
|
|
FireInputStringCallback(address, validatedChocoboName);
|
|
_awaitingConfirmation = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private unsafe void OnSelectYesNoSetup(AddonEvent type, AddonArgs args)
|
|
{
|
|
if (_questController.IsRunning && _awaitingConfirmation)
|
|
{
|
|
AtkUnitBase* address = (AtkUnitBase*)args.Addon.Address;
|
|
if (LAddon.IsAddonReady(address))
|
|
{
|
|
_logger.LogInformation("Confirming chocobo name");
|
|
ClickYes(address);
|
|
_awaitingConfirmation = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static string GetValidatedChocoboName(string? configuredName)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(configuredName))
|
|
{
|
|
return "Kweh";
|
|
}
|
|
string text = configuredName.Trim();
|
|
if (text.Length < 2 || text.Length > 20)
|
|
{
|
|
return "Kweh";
|
|
}
|
|
string text2 = text.Substring(0, 1).ToUpperInvariant();
|
|
string text3;
|
|
if (text.Length <= 1)
|
|
{
|
|
text3 = string.Empty;
|
|
}
|
|
else
|
|
{
|
|
string text4 = text;
|
|
text3 = text4.Substring(1, text4.Length - 1).ToLowerInvariant();
|
|
}
|
|
return text2 + text3;
|
|
}
|
|
|
|
private unsafe void FireInputStringCallback(AtkUnitBase* addon, string text)
|
|
{
|
|
AtkComponentNode* componentNodeById = addon->GetComponentNodeById(9u);
|
|
if (componentNodeById == null)
|
|
{
|
|
_logger.LogWarning("Could not find text input node in InputString addon");
|
|
return;
|
|
}
|
|
AtkComponentTextInput* asAtkComponentTextInput = componentNodeById->GetAsAtkComponentTextInput();
|
|
if (asAtkComponentTextInput == null)
|
|
{
|
|
_logger.LogWarning("Node is not a text input component");
|
|
return;
|
|
}
|
|
asAtkComponentTextInput->SetText(text);
|
|
AtkValue* ptr = stackalloc AtkValue[2];
|
|
ptr->Type = FFXIVClientStructs.FFXIV.Component.GUI.ValueType.Int;
|
|
ptr->Int = 0;
|
|
byte[] bytes = Encoding.UTF8.GetBytes(text);
|
|
nint num = Marshal.AllocHGlobal(bytes.Length + 1);
|
|
Marshal.Copy(bytes, 0, num, bytes.Length);
|
|
Marshal.WriteByte(num + bytes.Length, 0);
|
|
ptr[1].Type = FFXIVClientStructs.FFXIV.Component.GUI.ValueType.String;
|
|
ptr[1].String = (byte*)num;
|
|
addon->FireCallback(2u, ptr);
|
|
Marshal.FreeHGlobal(num);
|
|
}
|
|
|
|
private unsafe static void ClickYes(AtkUnitBase* addon)
|
|
{
|
|
AtkValue* ptr = stackalloc AtkValue[1];
|
|
ptr->Type = FFXIVClientStructs.FFXIV.Component.GUI.ValueType.Int;
|
|
ptr->Int = 0;
|
|
addon->FireCallback(1u, ptr);
|
|
}
|
|
}
|