156 lines
5.0 KiB
C#
156 lines
5.0 KiB
C#
using Dalamud.Game.ClientState.Objects.SubKinds;
|
|
using Dalamud.Game.ClientState.Objects.Types;
|
|
using Dalamud.Game.Gui.ContextMenu;
|
|
using Dalamud.Plugin;
|
|
using Dalamud.Plugin.Services;
|
|
using LightlessSync.LightlessConfiguration;
|
|
using LightlessSync.Services;
|
|
using LightlessSync.Utils;
|
|
using LightlessSync.WebAPI;
|
|
using Lumina.Excel.Sheets;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace LightlessSync.UI;
|
|
|
|
internal class ContextMenu : IHostedService
|
|
{
|
|
private readonly IContextMenu _contextMenu;
|
|
private readonly IDalamudPluginInterface _pluginInterface;
|
|
private readonly IDataManager _gameData;
|
|
private readonly ILogger<ContextMenu> _logger;
|
|
private readonly DalamudUtilService _dalamudUtil;
|
|
private readonly LightlessConfigService _configService;
|
|
private readonly ApiController _apiController;
|
|
private readonly IObjectTable _objectTable;
|
|
|
|
private static readonly string[] ValidAddons = new[]
|
|
{
|
|
null,
|
|
"PartyMemberList", "FriendList", "FreeCompany", "LinkShell", "CrossWorldLinkshell",
|
|
"_PartyList", "ChatLog", "LookingForGroup", "BlackList", "ContentMemberList",
|
|
"SocialList", "ContactList", "BeginnerChatList", "MuteList"
|
|
};
|
|
|
|
public ContextMenu(
|
|
IContextMenu contextMenu,
|
|
IDalamudPluginInterface pluginInterface,
|
|
IDataManager gameData,
|
|
ILogger<ContextMenu> logger,
|
|
DalamudUtilService dalamudUtil,
|
|
ApiController apiController,
|
|
IObjectTable objectTable,
|
|
LightlessConfigService configService)
|
|
{
|
|
_contextMenu = contextMenu;
|
|
_pluginInterface = pluginInterface;
|
|
_gameData = gameData;
|
|
_logger = logger;
|
|
_dalamudUtil = dalamudUtil;
|
|
_apiController = apiController;
|
|
_objectTable = objectTable;
|
|
_configService = configService;
|
|
}
|
|
|
|
public Task StartAsync(CancellationToken cancellationToken)
|
|
{
|
|
_contextMenu.OnMenuOpened += OnMenuOpened;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task StopAsync(CancellationToken cancellationToken)
|
|
{
|
|
_contextMenu.OnMenuOpened -= OnMenuOpened;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public void Enable()
|
|
{
|
|
_contextMenu.OnMenuOpened += OnMenuOpened;
|
|
_logger.LogDebug("Context menu enabled.");
|
|
}
|
|
|
|
public void Disable()
|
|
{
|
|
_contextMenu.OnMenuOpened -= OnMenuOpened;
|
|
_logger.LogDebug("Context menu disabled.");
|
|
}
|
|
|
|
private void OnMenuOpened(IMenuOpenedArgs args)
|
|
{
|
|
if (!_pluginInterface.UiBuilder.ShouldModifyUi)
|
|
return;
|
|
|
|
if (!ValidAddons.Contains(args.AddonName))
|
|
return;
|
|
|
|
if (args.Target is not MenuTargetDefault target)
|
|
return;
|
|
|
|
if (string.IsNullOrEmpty(target.TargetName) || target.TargetObjectId == 0 || target.TargetHomeWorld.RowId == 0)
|
|
return;
|
|
|
|
var world = GetWorld(target.TargetHomeWorld.RowId);
|
|
if (!IsWorldValid(world))
|
|
return;
|
|
|
|
args.AddMenuItem(new MenuItem
|
|
{
|
|
Name = "Send Pair Request",
|
|
PrefixChar = 'L',
|
|
UseDefaultPrefix = false,
|
|
PrefixColor = 708,
|
|
OnClicked = async _ => await HandleSelection(args)
|
|
});
|
|
}
|
|
|
|
private async Task HandleSelection(IMenuArgs args)
|
|
{
|
|
if (args.Target is not MenuTargetDefault target)
|
|
return;
|
|
|
|
var world = GetWorld(target.TargetHomeWorld.RowId);
|
|
if (!IsWorldValid(world))
|
|
return;
|
|
|
|
try
|
|
{
|
|
var targetData = _objectTable
|
|
.OfType<IPlayerCharacter>()
|
|
.FirstOrDefault(p =>
|
|
string.Equals(p.Name.TextValue, target.TargetName, StringComparison.OrdinalIgnoreCase) &&
|
|
p.HomeWorld.RowId == target.TargetHomeWorld.RowId);
|
|
|
|
if (targetData == null || targetData.Address == IntPtr.Zero)
|
|
{
|
|
_logger.LogWarning("Target player {TargetName}@{World} not found in object table.", target.TargetName, world.Name);
|
|
return;
|
|
}
|
|
|
|
var senderCid = (await _dalamudUtil.GetCIDAsync()).ToString().GetHash256();
|
|
var receiverCid = DalamudUtilService.GetHashedCIDFromPlayerPointer(targetData.Address);
|
|
|
|
_logger.LogInformation("Sending pair request: sender {SenderCid}, receiver {ReceiverCid}", senderCid, receiverCid);
|
|
await _apiController.TryPairWithContentId(receiverCid, senderCid);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error sending pair request.");
|
|
}
|
|
}
|
|
|
|
private World GetWorld(uint worldId)
|
|
{
|
|
var sheet = _gameData.GetExcelSheet<World>()!;
|
|
return sheet.TryGetRow(worldId, out var world) ? world : sheet.First();
|
|
}
|
|
|
|
public bool IsWorldValid(uint worldId) => IsWorldValid(GetWorld(worldId));
|
|
|
|
public static bool IsWorldValid(World world)
|
|
{
|
|
var name = world.Name.ToString();
|
|
return !string.IsNullOrWhiteSpace(name) && char.IsUpper(name[0]);
|
|
}
|
|
}
|