refactor: move to net5
This commit is contained in:
parent
d9e30396f4
commit
581b469d79
|
@ -1,11 +1,13 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net48</TargetFramework>
|
<TargetFramework>net5-windows</TargetFramework>
|
||||||
<Version>1.3.4</Version>
|
<Version>1.3.4</Version>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
||||||
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -13,6 +15,10 @@
|
||||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Dalamud.dll</HintPath>
|
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Dalamud.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="FFXIVClientStructs">
|
||||||
|
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\FFXIVClientStructs.dll</HintPath>
|
||||||
|
<Private>False</Private>
|
||||||
|
</Reference>
|
||||||
<Reference Include="ImGui.NET">
|
<Reference Include="ImGui.NET">
|
||||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\ImGui.NET.dll</HintPath>
|
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\ImGui.NET.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
|
@ -29,10 +35,12 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AngleSharp" Version="1.0.0-alpha-844"/>
|
<PackageReference Include="AngleSharp" Version="1.0.0-alpha-844"/>
|
||||||
<PackageReference Include="DalamudPackager" Version="1.2.1"/>
|
<PackageReference Include="DalamudPackager" Version="2.1.2"/>
|
||||||
<PackageReference Include="Fody" Version="6.5.2" PrivateAssets="all"/>
|
|
||||||
<PackageReference Include="ILMerge.Fody" Version="1.16.0" PrivateAssets="all"/>
|
|
||||||
<PackageReference Include="Nager.PublicSuffix" Version="2.2.2"/>
|
<PackageReference Include="Nager.PublicSuffix" Version="2.2.2"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="..\icon.png" Link="images/icon.png" CopyToOutputDirectory="PreserveNewest" Visible="false"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
author: ascclemens
|
author: ascclemens
|
||||||
name: Expanded Search Info
|
name: Expanded Search Info
|
||||||
|
punchline: Displays extra information pulled from search info when examining.
|
||||||
description: |-
|
description: |-
|
||||||
Displays extra information pulled from search info when examining.
|
Displays extra information pulled from search info when examining.
|
||||||
|
|
||||||
|
@ -12,4 +13,6 @@ description: |-
|
||||||
|
|
||||||
Simply examine someone with a search info containing pointers to one of
|
Simply examine someone with a search info containing pointers to one of
|
||||||
these locations and the plugin will display information automatically.
|
these locations and the plugin will display information automatically.
|
||||||
|
|
||||||
|
Icon: expand by Gregor Cresnar from the Noun Project
|
||||||
repo_url: https://git.sr.ht/~jkcclemens/ExpandedSearchInfo
|
repo_url: https://git.sr.ht/~jkcclemens/ExpandedSearchInfo
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
|
||||||
<ILMerge/>
|
|
||||||
</Weavers>
|
|
|
@ -1,8 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Logging;
|
||||||
|
|
||||||
namespace ExpandedSearchInfo {
|
namespace ExpandedSearchInfo {
|
||||||
public class GameFunctions : IDisposable {
|
public class GameFunctions : IDisposable {
|
||||||
|
@ -12,15 +11,15 @@ namespace ExpandedSearchInfo {
|
||||||
|
|
||||||
private readonly Hook<SearchInfoDownloadedDelegate>? _searchInfoDownloadedHook;
|
private readonly Hook<SearchInfoDownloadedDelegate>? _searchInfoDownloadedHook;
|
||||||
|
|
||||||
internal delegate void ReceiveSearchInfoEventDelegate(int actorId, SeString info);
|
internal delegate void ReceiveSearchInfoEventDelegate(uint objectId, SeString info);
|
||||||
|
|
||||||
internal event ReceiveSearchInfoEventDelegate? ReceiveSearchInfo;
|
internal event ReceiveSearchInfoEventDelegate? ReceiveSearchInfo;
|
||||||
|
|
||||||
internal GameFunctions(Plugin plugin) {
|
internal GameFunctions(Plugin plugin) {
|
||||||
this.Plugin = plugin;
|
this.Plugin = plugin;
|
||||||
|
|
||||||
var sidPtr = this.Plugin.Interface.TargetModuleScanner.ScanText("48 89 5C 24 ?? 48 89 6C 24 ?? 56 48 83 EC 20 49 8B E8 8B DA");
|
var sidPtr = this.Plugin.SigScanner.ScanText("48 89 5C 24 ?? 48 89 6C 24 ?? 56 48 83 EC 20 49 8B E8 8B DA");
|
||||||
this._searchInfoDownloadedHook = new Hook<SearchInfoDownloadedDelegate>(sidPtr, new SearchInfoDownloadedDelegate(this.SearchInfoDownloaded));
|
this._searchInfoDownloadedHook = new Hook<SearchInfoDownloadedDelegate>(sidPtr, this.SearchInfoDownloaded);
|
||||||
this._searchInfoDownloadedHook.Enable();
|
this._searchInfoDownloadedHook.Enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,14 +27,14 @@ namespace ExpandedSearchInfo {
|
||||||
this._searchInfoDownloadedHook?.Dispose();
|
this._searchInfoDownloadedHook?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte SearchInfoDownloaded(IntPtr data, IntPtr a2, IntPtr searchInfoPtr, IntPtr a4) {
|
private unsafe byte SearchInfoDownloaded(IntPtr data, IntPtr a2, IntPtr searchInfoPtr, IntPtr a4) {
|
||||||
var result = this._searchInfoDownloadedHook!.Original(data, a2, searchInfoPtr, a4);
|
var result = this._searchInfoDownloadedHook!.Original(data, a2, searchInfoPtr, a4);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Updated: 4.5
|
// Updated: 4.5
|
||||||
var actorId = Marshal.ReadInt32(data + 48);
|
var actorId = *(uint*) (data + 48);
|
||||||
|
|
||||||
var searchInfo = this.Plugin.Interface.SeStringManager.ReadRawSeString(searchInfoPtr);
|
var searchInfo = this.Plugin.SeStringManager.ReadRawSeString(searchInfoPtr);
|
||||||
|
|
||||||
this.ReceiveSearchInfo?.Invoke(actorId, searchInfo);
|
this.ReceiveSearchInfo?.Invoke(actorId, searchInfo);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
using Dalamud.Game.Command;
|
using Dalamud.Game;
|
||||||
|
using Dalamud.Game.ClientState.Objects;
|
||||||
|
using Dalamud.Game.Command;
|
||||||
|
using Dalamud.Game.Gui;
|
||||||
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
|
using Dalamud.IoC;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
|
|
||||||
namespace ExpandedSearchInfo {
|
namespace ExpandedSearchInfo {
|
||||||
|
@ -6,15 +11,30 @@ namespace ExpandedSearchInfo {
|
||||||
public class Plugin : IDalamudPlugin {
|
public class Plugin : IDalamudPlugin {
|
||||||
public string Name => "Expanded Search Info";
|
public string Name => "Expanded Search Info";
|
||||||
|
|
||||||
internal PluginConfiguration Config { get; private set; } = null!;
|
[PluginService]
|
||||||
internal DalamudPluginInterface Interface { get; private set; } = null!;
|
internal DalamudPluginInterface Interface { get; init; } = null!;
|
||||||
internal GameFunctions Functions { get; private set; } = null!;
|
|
||||||
internal SearchInfoRepository Repository { get; private set; } = null!;
|
|
||||||
private PluginUi Ui { get; set; } = null!;
|
|
||||||
|
|
||||||
public void Initialize(DalamudPluginInterface pluginInterface) {
|
[PluginService]
|
||||||
this.Interface = pluginInterface;
|
internal CommandManager CommandManager { get; init; } = null!;
|
||||||
|
|
||||||
|
[PluginService]
|
||||||
|
internal GameGui GameGui { get; init; } = null!;
|
||||||
|
|
||||||
|
[PluginService]
|
||||||
|
internal ObjectTable ObjectTable { get; init; } = null!;
|
||||||
|
|
||||||
|
[PluginService]
|
||||||
|
internal SeStringManager SeStringManager { get; init; } = null!;
|
||||||
|
|
||||||
|
[PluginService]
|
||||||
|
internal SigScanner SigScanner { get; init; } = null!;
|
||||||
|
|
||||||
|
internal PluginConfiguration Config { get; }
|
||||||
|
internal GameFunctions Functions { get; }
|
||||||
|
internal SearchInfoRepository Repository { get; }
|
||||||
|
private PluginUi Ui { get; }
|
||||||
|
|
||||||
|
public Plugin() {
|
||||||
this.Config = (PluginConfiguration?) this.Interface.GetPluginConfig() ?? new PluginConfiguration();
|
this.Config = (PluginConfiguration?) this.Interface.GetPluginConfig() ?? new PluginConfiguration();
|
||||||
this.Config.Initialise(this);
|
this.Config.Initialise(this);
|
||||||
|
|
||||||
|
@ -22,13 +42,13 @@ namespace ExpandedSearchInfo {
|
||||||
this.Repository = new SearchInfoRepository(this);
|
this.Repository = new SearchInfoRepository(this);
|
||||||
this.Ui = new PluginUi(this);
|
this.Ui = new PluginUi(this);
|
||||||
|
|
||||||
this.Interface.CommandManager.AddHandler("/esi", new CommandInfo(this.OnCommand) {
|
this.CommandManager.AddHandler("/esi", new CommandInfo(this.OnCommand) {
|
||||||
HelpMessage = "Toggles Expanded Search Info's configuration window",
|
HelpMessage = "Toggles Expanded Search Info's configuration window",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
this.Interface.CommandManager.RemoveHandler("/esi");
|
this.CommandManager.RemoveHandler("/esi");
|
||||||
this.Ui.Dispose();
|
this.Ui.Dispose();
|
||||||
this.Repository.Dispose();
|
this.Repository.Dispose();
|
||||||
this.Functions.Dispose();
|
this.Functions.Dispose();
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
|
||||||
namespace ExpandedSearchInfo {
|
namespace ExpandedSearchInfo {
|
||||||
|
@ -18,17 +19,17 @@ namespace ExpandedSearchInfo {
|
||||||
internal PluginUi(Plugin plugin) {
|
internal PluginUi(Plugin plugin) {
|
||||||
this.Plugin = plugin;
|
this.Plugin = plugin;
|
||||||
|
|
||||||
this.Plugin.Interface.UiBuilder.OnBuildUi += this.Draw;
|
this.Plugin.Interface.UiBuilder.Draw += this.Draw;
|
||||||
this.Plugin.Interface.UiBuilder.OnOpenConfigUi += this.OnOpenConfigUi;
|
this.Plugin.Interface.UiBuilder.OpenConfigUi += this.OnOpenConfigUi;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnOpenConfigUi(object sender, EventArgs e) {
|
private void OnOpenConfigUi() {
|
||||||
this.ConfigVisible = true;
|
this.ConfigVisible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
this.Plugin.Interface.UiBuilder.OnOpenConfigUi -= this.OnOpenConfigUi;
|
this.Plugin.Interface.UiBuilder.OpenConfigUi -= this.OnOpenConfigUi;
|
||||||
this.Plugin.Interface.UiBuilder.OnBuildUi -= this.Draw;
|
this.Plugin.Interface.UiBuilder.Draw -= this.Draw;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IconButton(FontAwesomeIcon icon, string? id = null) {
|
private static bool IconButton(FontAwesomeIcon icon, string? id = null) {
|
||||||
|
@ -128,30 +129,31 @@ namespace ExpandedSearchInfo {
|
||||||
ImGui.End();
|
ImGui.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawExpandedSearchInfo() {
|
private unsafe void DrawExpandedSearchInfo() {
|
||||||
// check if the examine window is open
|
// check if the examine window is open
|
||||||
var addon = this.Plugin.Interface.Framework.Gui.GetAddonByName("CharacterInspect", 1);
|
var addonPtr = this.Plugin.GameGui.GetAddonByName("CharacterInspect", 1);
|
||||||
if (addon is not {Visible: true}) {
|
if (addonPtr == IntPtr.Zero) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var addon = (AtkUnitBase*) addonPtr;
|
||||||
|
if (addon->IsVisible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get examine window info
|
// get examine window info
|
||||||
float width;
|
var rootNode = addon->RootNode;
|
||||||
float height;
|
if (rootNode == null) {
|
||||||
short x;
|
|
||||||
short y;
|
|
||||||
|
|
||||||
try {
|
|
||||||
width = addon.Width;
|
|
||||||
height = addon.Height;
|
|
||||||
x = addon.X;
|
|
||||||
y = addon.Y;
|
|
||||||
} catch (Exception) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var width = rootNode->Width * addon->Scale;
|
||||||
|
var height = rootNode->Height * addon->Scale;
|
||||||
|
var x = addon->X;
|
||||||
|
var y = addon->Y;
|
||||||
|
|
||||||
// check the last actor id recorded (should be who the examine window is showing)
|
// check the last actor id recorded (should be who the examine window is showing)
|
||||||
var actorId = this.Plugin.Repository.LastActorId;
|
var actorId = this.Plugin.Repository.LastObjectId;
|
||||||
if (actorId == 0 || !this.Plugin.Repository.SearchInfos.TryGetValue(actorId, out var expanded)) {
|
if (actorId == 0 || !this.Plugin.Repository.SearchInfos.TryGetValue(actorId, out var expanded)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace ExpandedSearchInfo.Providers {
|
||||||
|
|
||||||
public abstract bool Matches(Uri uri);
|
public abstract bool Matches(Uri uri);
|
||||||
|
|
||||||
public abstract IEnumerable<Uri>? ExtractUris(int actorId, string info);
|
public abstract IEnumerable<Uri>? ExtractUris(uint objectId, string info);
|
||||||
|
|
||||||
public abstract Task<ISearchInfoSection?> ExtractInfo(HttpResponseMessage response);
|
public abstract Task<ISearchInfoSection?> ExtractInfo(HttpResponseMessage response);
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace ExpandedSearchInfo.Providers {
|
||||||
|
|
||||||
public override bool Matches(Uri uri) => Domains.Any(domain => uri.Host.EndsWith(domain));
|
public override bool Matches(Uri uri) => Domains.Any(domain => uri.Host.EndsWith(domain));
|
||||||
|
|
||||||
public override IEnumerable<Uri>? ExtractUris(int actorId, string info) => null;
|
public override IEnumerable<Uri>? ExtractUris(uint objectId, string info) => null;
|
||||||
|
|
||||||
public override async Task<ISearchInfoSection?> ExtractInfo(HttpResponseMessage response) {
|
public override async Task<ISearchInfoSection?> ExtractInfo(HttpResponseMessage response) {
|
||||||
var document = await this.DownloadDocument(response);
|
var document = await this.DownloadDocument(response);
|
||||||
|
@ -83,7 +83,7 @@ namespace ExpandedSearchInfo.Providers {
|
||||||
return new TextSection(
|
return new TextSection(
|
||||||
this,
|
this,
|
||||||
$"{document.Title} (Carrd)",
|
$"{document.Title} (Carrd)",
|
||||||
response.RequestMessage.RequestUri,
|
response.RequestMessage!.RequestUri!,
|
||||||
text
|
text
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,19 +27,19 @@ namespace ExpandedSearchInfo.Providers {
|
||||||
public override void DrawConfig() {
|
public override void DrawConfig() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Matches(Uri uri) => (uri.Host == "www.f-list.net" || uri.Host == "f-list.net") && uri.AbsolutePath.StartsWith("/c/");
|
public override bool Matches(Uri uri) => uri.Host is "www.f-list.net" or "f-list.net" && uri.AbsolutePath.StartsWith("/c/");
|
||||||
|
|
||||||
public override IEnumerable<Uri>? ExtractUris(int actorId, string info) {
|
public override IEnumerable<Uri>? ExtractUris(uint objectId, string info) {
|
||||||
if (!info.ToLowerInvariant().Contains("c/")) {
|
if (!info.ToLowerInvariant().Contains("c/")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var actor = this.Plugin.Interface.ClientState.Actors.FirstOrDefault(actor => actor.ActorId == actorId);
|
var obj = this.Plugin.ObjectTable.FirstOrDefault(obj => obj.ObjectId == objectId);
|
||||||
if (actor == null) {
|
if (obj == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var safeName = actor.Name.Replace("'", "");
|
var safeName = obj.Name.ToString().Replace("'", "");
|
||||||
|
|
||||||
return new[] {
|
return new[] {
|
||||||
new Uri($"https://www.f-list.net/c/{Uri.EscapeUriString(safeName)}"),
|
new Uri($"https://www.f-list.net/c/{Uri.EscapeUriString(safeName)}"),
|
||||||
|
@ -99,7 +99,7 @@ namespace ExpandedSearchInfo.Providers {
|
||||||
return new FListSection(
|
return new FListSection(
|
||||||
this,
|
this,
|
||||||
$"{charName} (F-List)",
|
$"{charName} (F-List)",
|
||||||
response.RequestMessage.RequestUri,
|
response.RequestMessage!.RequestUri!,
|
||||||
info,
|
info,
|
||||||
stats,
|
stats,
|
||||||
fave,
|
fave,
|
||||||
|
|
|
@ -34,10 +34,10 @@ namespace ExpandedSearchInfo.Providers {
|
||||||
/// For providers that require Uris, this can return null.
|
/// For providers that require Uris, this can return null.
|
||||||
/// For providers that don't require Uris, this must return a Uri extracted from the given search info.
|
/// For providers that don't require Uris, this must return a Uri extracted from the given search info.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="actorId">The actor ID associated with the search info</param>
|
/// <param name="objectId">The actor ID associated with the search info</param>
|
||||||
/// <param name="info">A character's full search info</param>
|
/// <param name="info">A character's full search info</param>
|
||||||
/// <returns>null for providers that require Uris, a Uri for providers that don't</returns>
|
/// <returns>null for providers that require Uris, a Uri for providers that don't</returns>
|
||||||
IEnumerable<Uri>? ExtractUris(int actorId, string info);
|
IEnumerable<Uri>? ExtractUris(uint objectId, string info);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extract the search info to be displayed given the HTTP response from a Uri.
|
/// Extract the search info to be displayed given the HTTP response from a Uri.
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace ExpandedSearchInfo.Providers {
|
||||||
|
|
||||||
public bool Matches(Uri uri) => uri.Host == "pastebin.com" && uri.AbsolutePath.Length > 1;
|
public bool Matches(Uri uri) => uri.Host == "pastebin.com" && uri.AbsolutePath.Length > 1;
|
||||||
|
|
||||||
public IEnumerable<Uri>? ExtractUris(int actorId, string info) {
|
public IEnumerable<Uri>? ExtractUris(uint objectId, string info) {
|
||||||
var matches = Matcher.Matches(info);
|
var matches = Matcher.Matches(info);
|
||||||
return matches.Count == 0
|
return matches.Count == 0
|
||||||
? null
|
? null
|
||||||
|
@ -38,11 +38,11 @@ namespace ExpandedSearchInfo.Providers {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ISearchInfoSection?> ExtractInfo(HttpResponseMessage response) {
|
public async Task<ISearchInfoSection?> ExtractInfo(HttpResponseMessage response) {
|
||||||
if (response.Content.Headers.ContentType.MediaType != "text/plain") {
|
if (response.Content.Headers.ContentType?.MediaType != "text/plain") {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var id = response.RequestMessage.RequestUri.AbsolutePath.Split('/').LastOrDefault();
|
var id = response.RequestMessage!.RequestUri!.AbsolutePath.Split('/').LastOrDefault();
|
||||||
|
|
||||||
var info = await response.Content.ReadAsStringAsync();
|
var info = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
|
|
@ -26,17 +26,17 @@ namespace ExpandedSearchInfo.Providers {
|
||||||
|
|
||||||
public bool Matches(Uri uri) => true;
|
public bool Matches(Uri uri) => true;
|
||||||
|
|
||||||
public IEnumerable<Uri>? ExtractUris(int actorId, string info) => null;
|
public IEnumerable<Uri>? ExtractUris(uint objectId, string info) => null;
|
||||||
|
|
||||||
public async Task<ISearchInfoSection?> ExtractInfo(HttpResponseMessage response) {
|
public async Task<ISearchInfoSection?> ExtractInfo(HttpResponseMessage response) {
|
||||||
if (response.Content.Headers.ContentType.MediaType != "text/plain") {
|
if (response.Content.Headers.ContentType?.MediaType != "text/plain") {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var info = await response.Content.ReadAsStringAsync();
|
var info = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
var uri = response.RequestMessage.RequestUri;
|
var uri = response.RequestMessage!.RequestUri!;
|
||||||
return new TextSection(this, $"Text##{uri}", response.RequestMessage.RequestUri, info);
|
return new TextSection(this, $"Text##{uri}", uri, info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,9 @@ namespace ExpandedSearchInfo.Providers {
|
||||||
public override void DrawConfig() {
|
public override void DrawConfig() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Matches(Uri uri) => uri.Host == "refsheet.net" || uri.Host == "ref.st";
|
public override bool Matches(Uri uri) => uri.Host is "refsheet.net" or "ref.st";
|
||||||
|
|
||||||
public override IEnumerable<Uri>? ExtractUris(int actorId, string info) => null;
|
public override IEnumerable<Uri>? ExtractUris(uint objectId, string info) => null;
|
||||||
|
|
||||||
public override async Task<ISearchInfoSection?> ExtractInfo(HttpResponseMessage response) {
|
public override async Task<ISearchInfoSection?> ExtractInfo(HttpResponseMessage response) {
|
||||||
var document = await this.DownloadDocument(response);
|
var document = await this.DownloadDocument(response);
|
||||||
|
@ -52,6 +52,10 @@ namespace ExpandedSearchInfo.Providers {
|
||||||
|
|
||||||
var json = jsonLine.Substring(JsonLineStart.Length, jsonLine.Length - JsonLineStart.Length - 1);
|
var json = jsonLine.Substring(JsonLineStart.Length, jsonLine.Length - JsonLineStart.Length - 1);
|
||||||
var parsed = JsonConvert.DeserializeObject<RefsheetData>(json);
|
var parsed = JsonConvert.DeserializeObject<RefsheetData>(json);
|
||||||
|
if (parsed == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var character = parsed.EagerLoad.Character;
|
var character = parsed.EagerLoad.Character;
|
||||||
|
|
||||||
// get character name
|
// get character name
|
||||||
|
@ -113,7 +117,7 @@ namespace ExpandedSearchInfo.Providers {
|
||||||
return new RefsheetSection(
|
return new RefsheetSection(
|
||||||
this,
|
this,
|
||||||
$"{name} (Refsheet)",
|
$"{name} (Refsheet)",
|
||||||
response.RequestMessage.RequestUri,
|
response.RequestMessage!.RequestUri!,
|
||||||
attributes,
|
attributes,
|
||||||
notes,
|
notes,
|
||||||
cards
|
cards
|
||||||
|
|
|
@ -4,10 +4,9 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Logging;
|
||||||
using ExpandedSearchInfo.Providers;
|
using ExpandedSearchInfo.Providers;
|
||||||
using ExpandedSearchInfo.Sections;
|
using ExpandedSearchInfo.Sections;
|
||||||
using Nager.PublicSuffix;
|
using Nager.PublicSuffix;
|
||||||
|
@ -26,8 +25,8 @@ namespace ExpandedSearchInfo {
|
||||||
public class SearchInfoRepository : IDisposable {
|
public class SearchInfoRepository : IDisposable {
|
||||||
private Plugin Plugin { get; }
|
private Plugin Plugin { get; }
|
||||||
private DomainParser Parser { get; }
|
private DomainParser Parser { get; }
|
||||||
internal ConcurrentDictionary<int, ExpandedSearchInfo> SearchInfos { get; } = new();
|
internal ConcurrentDictionary<uint, ExpandedSearchInfo> SearchInfos { get; } = new();
|
||||||
internal int LastActorId { get; private set; }
|
internal uint LastObjectId { get; private set; }
|
||||||
|
|
||||||
private List<IProvider> Providers { get; } = new();
|
private List<IProvider> Providers { get; } = new();
|
||||||
internal IEnumerable<IProvider> AllProviders => this.Providers;
|
internal IEnumerable<IProvider> AllProviders => this.Providers;
|
||||||
|
@ -62,48 +61,48 @@ namespace ExpandedSearchInfo {
|
||||||
this.Providers.Add(new PlainTextProvider(this.Plugin));
|
this.Providers.Add(new PlainTextProvider(this.Plugin));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessSearchInfo(int actorId, SeString raw) {
|
private void ProcessSearchInfo(uint objectId, SeString raw) {
|
||||||
this.LastActorId = actorId;
|
this.LastObjectId = objectId;
|
||||||
|
|
||||||
var info = raw.TextValue;
|
var info = raw.TextValue;
|
||||||
|
|
||||||
// if empty search info, short circuit
|
// if empty search info, short circuit
|
||||||
if (string.IsNullOrWhiteSpace(info)) {
|
if (string.IsNullOrWhiteSpace(info)) {
|
||||||
// remove any existing search info
|
// remove any existing search info
|
||||||
this.SearchInfos.TryRemove(actorId, out _);
|
this.SearchInfos.TryRemove(objectId, out _);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check to see if info has changed
|
// check to see if info has changed
|
||||||
#if RELEASE
|
#if RELEASE
|
||||||
if (this.SearchInfos.TryGetValue(actorId, out var existing)) {
|
if (this.SearchInfos.TryGetValue(objectId, out var existing)) {
|
||||||
if (existing.Info == info) {
|
if (existing.Info == info) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
new Thread(async () => {
|
Task.Run(async () => {
|
||||||
try {
|
try {
|
||||||
await this.DoExtraction(actorId, info);
|
await this.DoExtraction(objectId, info);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
PluginLog.LogError($"Error in extraction thread:\n{ex}");
|
PluginLog.LogError($"Error in extraction thread:\n{ex}");
|
||||||
}
|
}
|
||||||
}).Start();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DoExtraction(int actorId, string info) {
|
private async Task DoExtraction(uint objectId, string info) {
|
||||||
var downloadUris = new List<Uri>();
|
var downloadUris = new List<Uri>();
|
||||||
|
|
||||||
// extract uris from the search info with providers
|
// extract uris from the search info with providers
|
||||||
var extractedUris = this.Providers
|
var extractedUris = this.Providers
|
||||||
.Where(provider => provider.Config.Enabled && provider.ExtractsUris)
|
.Where(provider => provider.Config.Enabled && provider.ExtractsUris)
|
||||||
.Select(provider => provider.ExtractUris(actorId, info))
|
.Select(provider => provider.ExtractUris(objectId, info))
|
||||||
.Where(uris => uris != null)
|
.Where(uris => uris != null)
|
||||||
.SelectMany(uris => uris);
|
.SelectMany(uris => uris!);
|
||||||
|
|
||||||
// add the extracted uris to the list
|
// add the extracted uris to the list
|
||||||
downloadUris.AddRange(extractedUris!);
|
downloadUris.AddRange(extractedUris);
|
||||||
|
|
||||||
// go word-by-word and try to parse a uri
|
// go word-by-word and try to parse a uri
|
||||||
foreach (var word in info.Split(' ', '\n', '\r')) {
|
foreach (var word in info.Split(' ', '\n', '\r')) {
|
||||||
|
@ -128,15 +127,15 @@ namespace ExpandedSearchInfo {
|
||||||
|
|
||||||
// if there were no uris found or extracted, remove existing search info and stop
|
// if there were no uris found or extracted, remove existing search info and stop
|
||||||
if (downloadUris.Count == 0) {
|
if (downloadUris.Count == 0) {
|
||||||
this.SearchInfos.TryRemove(actorId, out _);
|
this.SearchInfos.TryRemove(objectId, out _);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// do the downloads
|
// do the downloads
|
||||||
await this.DownloadAndExtract(actorId, info, downloadUris);
|
await this.DownloadAndExtract(objectId, info, downloadUris);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DownloadAndExtract(int actorId, string info, IEnumerable<Uri> uris) {
|
private async Task DownloadAndExtract(uint objectId, string info, IEnumerable<Uri> uris) {
|
||||||
var handler = new HttpClientHandler {
|
var handler = new HttpClientHandler {
|
||||||
UseCookies = true,
|
UseCookies = true,
|
||||||
AllowAutoRedirect = true,
|
AllowAutoRedirect = true,
|
||||||
|
@ -183,12 +182,12 @@ namespace ExpandedSearchInfo {
|
||||||
|
|
||||||
// remove expanded search info if no sections resulted
|
// remove expanded search info if no sections resulted
|
||||||
if (sections.Count == 0) {
|
if (sections.Count == 0) {
|
||||||
this.SearchInfos.TryRemove(actorId, out _);
|
this.SearchInfos.TryRemove(objectId, out _);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise set the expanded search info for this actor id
|
// otherwise set the expanded search info for this actor id
|
||||||
this.SearchInfos[actorId] = new ExpandedSearchInfo(info, sections);
|
this.SearchInfos[objectId] = new ExpandedSearchInfo(info, sections);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 98.199997 98.199997"
|
||||||
|
enable-background="new 0 0 100 100"
|
||||||
|
xml:space="preserve"
|
||||||
|
id="svg8"
|
||||||
|
sodipodi:docname="icon.svg"
|
||||||
|
width="98.199997"
|
||||||
|
height="98.199997"
|
||||||
|
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||||
|
inkscape:export-filename="D:\code\ExpandedSearchInfo\icon.png"
|
||||||
|
inkscape:export-xdpi="500.53"
|
||||||
|
inkscape:export-ydpi="500.53"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs12" /><sodipodi:namedview
|
||||||
|
id="namedview10"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#ffffff"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="6.656"
|
||||||
|
inkscape:cx="49.053486"
|
||||||
|
inkscape:cy="49.654447"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1017"
|
||||||
|
inkscape:window-x="1592"
|
||||||
|
inkscape:window-y="32"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1" /><g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer2"
|
||||||
|
inkscape:label="Layer 2"
|
||||||
|
transform="translate(-0.9,-0.9)"><path
|
||||||
|
d="M 28.3,50 C 28.3,38 38,28.3 50,28.3 62,28.3 71.7,38 71.7,50 71.7,62 62,71.7 50,71.7 38,71.7 28.3,62 28.3,50 Z"
|
||||||
|
id="path1024"
|
||||||
|
style="fill:#1720a9;fill-opacity:1" /></g><g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
transform="translate(-0.9,-0.9)"><path
|
||||||
|
d="m 35.7,50 c 0,4.2 1.8,7.9 4.6,10.5 0.4,-3.6 2.9,-6.7 6.2,-8 -1.9,-1.2 -3.1,-3.3 -3.1,-5.6 0,-3.7 3,-6.7 6.7,-6.7 3.7,0 6.7,3 6.7,6.7 0,2.4 -1.2,4.5 -3.1,5.6 3.3,1.3 5.7,4.3 6.2,8 2.8,-2.6 4.6,-6.3 4.6,-10.5 0,-7.9 -6.4,-14.3 -14.3,-14.3 -8.1,0 -14.5,6.4 -14.5,14.3 z"
|
||||||
|
id="path1026"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" /><path
|
||||||
|
d="m 50,77.8 c -1.5,0 -3.1,-0.2 -4.5,-0.4 v 9.2 h -4.8 c -0.5,0 -0.8,0.6 -0.5,1 l 9.2,11.2 c 0.3,0.4 0.9,0.4 1.2,0 l 9.2,-11.2 c 0.3,-0.4 0,-1 -0.5,-1 h -4.8 v -9.2 c -1.4,0.2 -3,0.4 -4.5,0.4 z"
|
||||||
|
id="path1022"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" /><path
|
||||||
|
d="m 30.7,82.5 -3.4,-3.4 6.5,-6.5 c -2.5,-1.8 -4.6,-3.9 -6.4,-6.4 l -6.5,6.5 -3.4,-3.4 c -0.4,-0.4 -1,-0.1 -1,0.4 l -1.4,14.4 c 0,0.5 0.4,0.9 0.8,0.8 l 14.4,-1.4 c 0.5,-0.1 0.8,-0.7 0.4,-1 z"
|
||||||
|
id="path1020"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" /><path
|
||||||
|
d="m 77.8,50 c 0,1.5 -0.2,3 -0.4,4.5 h 9.2 v 4.8 c 0,0.5 0.6,0.8 1,0.5 l 11.2,-9.2 c 0.4,-0.3 0.4,-0.9 0,-1.2 L 87.6,40.2 c -0.4,-0.3 -1,0 -1,0.5 v 4.8 h -9.2 c 0.2,1.5 0.4,3 0.4,4.5 z"
|
||||||
|
id="path1018"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" /><path
|
||||||
|
d="m 22.2,50 c 0,-1.5 0.2,-3 0.4,-4.5 h -9.2 v -4.8 c 0,-0.5 -0.6,-0.8 -1,-0.5 L 1.2,49.4 c -0.4,0.3 -0.4,0.9 0,1.2 l 11.2,9.2 c 0.4,0.3 1,0 1,-0.5 v -4.8 h 9.2 C 22.4,53 22.2,51.5 22.2,50 Z"
|
||||||
|
id="path1016"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" /><path
|
||||||
|
d="m 69.7,83.5 14.4,1.4 c 0.5,0 0.9,-0.4 0.8,-0.8 L 83.5,69.7 c -0.1,-0.5 -0.7,-0.7 -1,-0.4 l -3.4,3.4 -6.5,-6.5 c -1.8,2.5 -3.9,4.6 -6.4,6.4 l 6.5,6.5 -3.4,3.4 c -0.4,0.3 -0.1,0.9 0.4,1 z"
|
||||||
|
id="path1014"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" /><path
|
||||||
|
d="m 72.5,33.9 6.5,-6.5 3.4,3.4 c 0.4,0.4 1,0.1 1,-0.4 L 84.8,16 c 0,-0.5 -0.4,-0.9 -0.8,-0.8 l -14.4,1.4 c -0.5,0.1 -0.7,0.7 -0.4,1 l 3.4,3.4 -6.5,6.5 c 2.5,1.7 4.7,3.9 6.4,6.4 z"
|
||||||
|
id="path1012"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" /><path
|
||||||
|
d="m 17.5,30.7 3.4,-3.4 6.5,6.5 c 1.8,-2.5 3.9,-4.6 6.4,-6.4 l -6.5,-6.5 3.4,-3.4 c 0.4,-0.4 0.1,-1 -0.4,-1 L 15.9,15.1 c -0.5,0 -0.9,0.4 -0.8,0.8 l 1.4,14.4 c 0.1,0.5 0.7,0.8 1,0.4 z"
|
||||||
|
id="path1010"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" /><path
|
||||||
|
d="M 40.2,12.4 49.4,1.2 c 0.3,-0.4 0.9,-0.4 1.2,0 l 9.2,11.2 c 0.3,0.4 0,1 -0.5,1 h -4.8 v 9.2 c -1.5,-0.2 -3,-0.4 -4.5,-0.4 -1.5,0 -3.1,0.2 -4.5,0.4 v -9.2 h -4.8 c -0.5,0 -0.8,-0.6 -0.5,-1 z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" /></g></svg>
|
After Width: | Height: | Size: 4.1 KiB |
Loading…
Reference in New Issue