Compare commits
4 Commits
aaa605e806
...
ab78a726be
Author | SHA1 | Date | |
---|---|---|---|
ab78a726be | |||
798b089462 | |||
c780d8d6f7 | |||
4b8ee3d648 |
@ -48,6 +48,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2021.3.0"/>
|
<PackageReference Include="JetBrains.Annotations" Version="2021.3.0"/>
|
||||||
|
<PackageReference Include="Siggingway" Version="1.1.1"/>
|
||||||
<PackageReference Include="XivCommon" Version="4.0.0"/>
|
<PackageReference Include="XivCommon" Version="4.0.0"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System.Runtime.InteropServices;
|
using System.Text;
|
||||||
using System.Text;
|
|
||||||
using ChatTwo.Code;
|
using ChatTwo.Code;
|
||||||
using ChatTwo.Util;
|
using ChatTwo.Util;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
@ -13,6 +12,7 @@ using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
|||||||
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Shell;
|
using FFXIVClientStructs.FFXIV.Client.UI.Shell;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
|
using Siggingway;
|
||||||
|
|
||||||
namespace ChatTwo;
|
namespace ChatTwo;
|
||||||
|
|
||||||
@ -20,64 +20,79 @@ internal unsafe class GameFunctions : IDisposable {
|
|||||||
private static class Signatures {
|
private static class Signatures {
|
||||||
internal const string ChatLogRefresh = "40 53 56 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 49 8B F0 8B FA";
|
internal const string ChatLogRefresh = "40 53 56 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 49 8B F0 8B FA";
|
||||||
internal const string ChangeChannelName = "E8 ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8D 4D B0 48 8B F8 E8 ?? ?? ?? ?? 41 8B D6";
|
internal const string ChangeChannelName = "E8 ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8D 4D B0 48 8B F8 E8 ?? ?? ?? ?? 41 8B D6";
|
||||||
|
internal const string IsMentorA1 = "48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 74 71 0F B6 86";
|
||||||
|
|
||||||
internal const string CurrentChatEntryOffset = "8B 77 ?? 8D 46 01 89 47 14 81 FE ?? ?? ?? ?? 72 03 FF 47";
|
internal const string CurrentChatEntryOffset = "8B 77 ?? 8D 46 01 89 47 14 81 FE ?? ?? ?? ?? 72 03 FF 47";
|
||||||
internal const string AgentContextYesNo = "E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8B CB E8 ?? ?? ?? ?? 84 C0 74 3A";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Functions
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? 0F B7 44 37 ??", Fallibility = Fallibility.Fallible)]
|
||||||
|
private readonly delegate* unmanaged<RaptureShellModule*, int, uint, Utf8String*, byte, void> _changeChatChannel = null!;
|
||||||
|
|
||||||
|
[Signature("4C 8B 81 ?? ?? ?? ?? 4D 85 C0 74 17", Fallibility = Fallibility.Fallible)]
|
||||||
|
private readonly delegate* unmanaged<RaptureLogModule*, uint, ulong> _getContentIdForChatEntry = null!;
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? 8B FD 8B CD", Fallibility = Fallibility.Fallible)]
|
||||||
|
private readonly delegate* unmanaged<IntPtr, uint, IntPtr> _indexer = null!;
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? 33 C0 EB 51", Fallibility = Fallibility.Fallible)]
|
||||||
|
private readonly delegate* unmanaged<IntPtr, ulong, byte*, ushort, void> _inviteToParty = null!;
|
||||||
|
|
||||||
|
[Signature(("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8B CB E8 ?? ?? ?? ?? 45 33 C9"), Fallibility = Fallibility.Fallible)]
|
||||||
|
private readonly delegate* unmanaged<IntPtr, ulong, ushort, byte*, byte> _inviteToNoviceNetwork = null!;
|
||||||
|
|
||||||
|
[Signature("40 53 48 83 EC 20 48 8B D9 48 8B 49 10 48 8B 01 FF 90 ?? ?? ?? ?? 48 8B 48 48", Fallibility = Fallibility.Fallible)]
|
||||||
|
private readonly delegate* unmanaged<AgentInterface*, byte> _friendRequestBool = null!;
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? EB 35 BA", Fallibility = Fallibility.Fallible)]
|
||||||
|
private readonly delegate* unmanaged<uint, uint, ulong, uint, byte, byte> _tryOn = null!;
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? EB 7B 49 8B 06", Fallibility = Fallibility.Fallible)]
|
||||||
|
private readonly delegate* unmanaged<AgentInterface*, uint, void> _linkItem = null!;
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? EB 3F 83 F8 FE", Fallibility = Fallibility.Fallible)]
|
||||||
|
private readonly delegate* unmanaged<AgentInterface*, ushort, uint, byte, void> _itemComparison = null!;
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 41 B4 01", Fallibility = Fallibility.Fallible)]
|
||||||
|
private readonly delegate* unmanaged<IntPtr, uint, void> _searchForRecipesUsingItem = null!;
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? EB 45 45 33 C9", Fallibility = Fallibility.Fallible)]
|
||||||
|
private readonly delegate* unmanaged<void*, uint, byte, void> _searchForItem = null!;
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8B CB E8 ?? ?? ?? ?? 84 C0 74 3A", Fallibility = Fallibility.Fallible)]
|
||||||
|
private readonly delegate* unmanaged<AgentInterface*, uint, byte*, ushort, uint, byte, void> _agentContextYesNo = null!;
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? 84 C0 74 0D B0 02", Fallibility = Fallibility.Fallible)]
|
||||||
|
private readonly delegate* unmanaged<IntPtr, byte> _isMentor = null!;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Hooks
|
||||||
|
|
||||||
private delegate byte ChatLogRefreshDelegate(IntPtr log, ushort eventId, AtkValue* value);
|
private delegate byte ChatLogRefreshDelegate(IntPtr log, ushort eventId, AtkValue* value);
|
||||||
|
|
||||||
private delegate IntPtr ChangeChannelNameDelegate(IntPtr agent);
|
private delegate IntPtr ChangeChannelNameDelegate(IntPtr agent);
|
||||||
|
|
||||||
private delegate IntPtr AgentContextYesNoDelegate(AgentInterface* context, uint a2, byte* playerName, ushort playerWorld, uint a5, byte a6);
|
[Signature(Signatures.ChatLogRefresh, DetourName = nameof(ChatLogRefreshDetour))]
|
||||||
|
private Hook<ChatLogRefreshDelegate>? ChatLogRefreshHook { get; init; }
|
||||||
|
|
||||||
internal delegate void ChatActivatedEventDelegate(string? input);
|
[Signature(Signatures.ChangeChannelName, DetourName = nameof(ChangeChannelNameDetour))]
|
||||||
|
private Hook<ChangeChannelNameDelegate>? ChangeChannelNameHook { get; init; }
|
||||||
#region Functions
|
|
||||||
|
|
||||||
[Signature("E8 ?? ?? ?? ?? 0F B7 44 37 ??")]
|
|
||||||
private readonly delegate* unmanaged<RaptureShellModule*, int, uint, Utf8String*, byte, void> _changeChatChannel;
|
|
||||||
|
|
||||||
[Signature("4C 8B 81 ?? ?? ?? ?? 4D 85 C0 74 17")]
|
|
||||||
private readonly delegate* unmanaged<RaptureLogModule*, uint, ulong> _getContentIdForChatEntry;
|
|
||||||
|
|
||||||
[Signature("E8 ?? ?? ?? ?? 8B FD 8B CD")]
|
|
||||||
private readonly delegate* unmanaged<IntPtr, uint, IntPtr> _indexer;
|
|
||||||
|
|
||||||
[Signature("E8 ?? ?? ?? ?? 33 C0 EB 51")]
|
|
||||||
private readonly delegate* unmanaged<IntPtr, ulong, byte*, ushort, void> _inviteToParty;
|
|
||||||
|
|
||||||
[Signature(("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8B CB E8 ?? ?? ?? ?? 45 33 C9"))]
|
|
||||||
private readonly delegate* unmanaged<IntPtr, ulong, ushort, byte*, byte> _inviteToNoviceNetwork;
|
|
||||||
|
|
||||||
[Signature("40 53 48 83 EC 20 48 8B D9 48 8B 49 10 48 8B 01 FF 90 ?? ?? ?? ?? 48 8B 48 48")]
|
|
||||||
private readonly delegate* unmanaged<AgentInterface*, byte> _friendRequestBool;
|
|
||||||
|
|
||||||
[Signature("E8 ?? ?? ?? ?? EB 35 BA")]
|
|
||||||
private readonly delegate* unmanaged<uint, uint, ulong, uint, byte, byte> _tryOn;
|
|
||||||
|
|
||||||
[Signature("E8 ?? ?? ?? ?? EB 7B 49 8B 06")]
|
|
||||||
private readonly delegate* unmanaged<AgentInterface*, uint, void> _linkItem;
|
|
||||||
|
|
||||||
[Signature("E8 ?? ?? ?? ?? EB 3F 83 F8 FE")]
|
|
||||||
private readonly delegate* unmanaged<AgentInterface*, ushort, uint, byte, void> _itemComparison;
|
|
||||||
|
|
||||||
[Signature("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 41 B4 01")]
|
|
||||||
private readonly delegate* unmanaged<IntPtr, uint, void> _searchForRecipesUsingItem;
|
|
||||||
|
|
||||||
[Signature("E8 ?? ?? ?? ?? EB 45 45 33 C9")]
|
|
||||||
private readonly delegate* unmanaged<void*, uint, byte, void> _searchForItem;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
[Signature(Signatures.CurrentChatEntryOffset, Offset = 2)]
|
||||||
|
private readonly byte? _currentChatEntryOffset;
|
||||||
|
|
||||||
|
[Signature(Signatures.IsMentorA1, ScanType = ScanType.StaticAddress)]
|
||||||
|
private readonly IntPtr? _isMentorA1;
|
||||||
|
|
||||||
internal const int HqItemOffset = 1_000_000;
|
internal const int HqItemOffset = 1_000_000;
|
||||||
|
|
||||||
private Plugin Plugin { get; }
|
private Plugin Plugin { get; }
|
||||||
private Hook<ChatLogRefreshDelegate>? ChatLogRefreshHook { get; }
|
|
||||||
private Hook<ChangeChannelNameDelegate>? ChangeChannelNameHook { get; }
|
|
||||||
|
|
||||||
private readonly int? _currentChatEntryOffset;
|
internal delegate void ChatActivatedEventDelegate(string? input);
|
||||||
private readonly AgentContextYesNoDelegate? _agentContextYesNo;
|
|
||||||
|
|
||||||
internal event ChatActivatedEventDelegate? ChatActivated;
|
internal event ChatActivatedEventDelegate? ChatActivated;
|
||||||
|
|
||||||
@ -86,25 +101,10 @@ internal unsafe class GameFunctions : IDisposable {
|
|||||||
internal GameFunctions(Plugin plugin) {
|
internal GameFunctions(Plugin plugin) {
|
||||||
this.Plugin = plugin;
|
this.Plugin = plugin;
|
||||||
|
|
||||||
this.Plugin.SigScanner.ScanFunctions(this);
|
Siggingway.Siggingway.Initialise(this.Plugin.SigScanner, this);
|
||||||
|
|
||||||
if (this.Plugin.SigScanner.TryScanText(Signatures.ChatLogRefresh, out var chatLogPtr)) {
|
this.ChatLogRefreshHook?.Enable();
|
||||||
this.ChatLogRefreshHook = new Hook<ChatLogRefreshDelegate>(chatLogPtr, this.ChatLogRefreshDetour);
|
this.ChangeChannelNameHook?.Enable();
|
||||||
this.ChatLogRefreshHook.Enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.Plugin.SigScanner.TryScanText(Signatures.ChangeChannelName, out var channelNamePtr)) {
|
|
||||||
this.ChangeChannelNameHook = new Hook<ChangeChannelNameDelegate>(channelNamePtr, this.ChangeChannelNameDetour);
|
|
||||||
this.ChangeChannelNameHook.Enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.Plugin.SigScanner.TryScanText(Signatures.CurrentChatEntryOffset, out var entryOffsetPtr)) {
|
|
||||||
this._currentChatEntryOffset = *(byte*) (entryOffsetPtr + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.Plugin.SigScanner.TryScanText(Signatures.AgentContextYesNo, out var sendFriendRequestPtr)) {
|
|
||||||
this._agentContextYesNo = Marshal.GetDelegateForFunctionPointer<AgentContextYesNoDelegate>(sendFriendRequestPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Plugin.ClientState.Login += this.Login;
|
this.Plugin.ClientState.Login += this.Login;
|
||||||
this.Login(null, null);
|
this.Login(null, null);
|
||||||
@ -170,7 +170,7 @@ internal unsafe class GameFunctions : IDisposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.Context);
|
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.Context);
|
||||||
var a6 = this._friendRequestBool(agent);
|
var a6 = this._friendRequestBool(agent) == 0 ? (byte) 1 : (byte) 0;
|
||||||
|
|
||||||
fixed (byte* namePtr = name.ToTerminatedBytes()) {
|
fixed (byte* namePtr = name.ToTerminatedBytes()) {
|
||||||
// 6.05: 20DA57
|
// 6.05: 20DA57
|
||||||
@ -229,7 +229,7 @@ internal unsafe class GameFunctions : IDisposable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SetChatInteractable(bool interactable) {
|
internal static void SetChatInteractable(bool interactable) {
|
||||||
for (var i = 0; i < 4; i++) {
|
for (var i = 0; i < 4; i++) {
|
||||||
SetAddonInteractable($"ChatLogPanel_{i}", interactable);
|
SetAddonInteractable($"ChatLogPanel_{i}", interactable);
|
||||||
}
|
}
|
||||||
@ -249,7 +249,7 @@ internal unsafe class GameFunctions : IDisposable {
|
|||||||
return (*flags & (1 << 22)) == 0;
|
return (*flags & (1 << 22)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OpenItemTooltip(uint id) {
|
internal static void OpenItemTooltip(uint id) {
|
||||||
var atkStage = AtkStage.GetSingleton();
|
var atkStage = AtkStage.GetSingleton();
|
||||||
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ItemDetail);
|
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ItemDetail);
|
||||||
var addon = atkStage->RaptureAtkUnitManager->GetAddonByName("ItemDetail");
|
var addon = atkStage->RaptureAtkUnitManager->GetAddonByName("ItemDetail");
|
||||||
@ -289,7 +289,7 @@ internal unsafe class GameFunctions : IDisposable {
|
|||||||
(*vf5)(addon, 0, 15);
|
(*vf5)(addon, 0, 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void CloseItemTooltip() {
|
internal static void CloseItemTooltip() {
|
||||||
// hide addon first to prevent the "addon close" sound
|
// hide addon first to prevent the "addon close" sound
|
||||||
var addon = AtkStage.GetSingleton()->RaptureAtkUnitManager->GetAddonByName("ItemDetail");
|
var addon = AtkStage.GetSingleton()->RaptureAtkUnitManager->GetAddonByName("ItemDetail");
|
||||||
if (addon != null) {
|
if (addon != null) {
|
||||||
@ -382,7 +382,6 @@ internal unsafe class GameFunctions : IDisposable {
|
|||||||
// 0x10005: copy item name
|
// 0x10005: copy item name
|
||||||
// 0x10006: search recipes using this material
|
// 0x10006: search recipes using this material
|
||||||
|
|
||||||
|
|
||||||
internal void TryOn(uint itemId, byte stainId) {
|
internal void TryOn(uint itemId, byte stainId) {
|
||||||
if (this._tryOn == null) {
|
if (this._tryOn == null) {
|
||||||
return;
|
return;
|
||||||
@ -428,4 +427,31 @@ internal unsafe class GameFunctions : IDisposable {
|
|||||||
var itemFinder = Framework.Instance()->GetUiModule()->GetItemFinderModule();
|
var itemFinder = Framework.Instance()->GetUiModule()->GetItemFinderModule();
|
||||||
this._searchForItem(itemFinder, itemId, 1);
|
this._searchForItem(itemFinder, itemId, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void OpenPartyFinder() {
|
||||||
|
// this whole method: 6.05: 84433A
|
||||||
|
var lfg = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.LookingForGroup);
|
||||||
|
if (lfg->IsAgentActive()) {
|
||||||
|
var addonId = lfg->GetAddonID();
|
||||||
|
var atkModule = Framework.Instance()->GetUiModule()->GetRaptureAtkModule();
|
||||||
|
var atkModuleVtbl = (void**) atkModule->AtkModule.vtbl;
|
||||||
|
var vf27 = (delegate* unmanaged<RaptureAtkModule*, ulong, ulong, byte>) atkModuleVtbl[27];
|
||||||
|
vf27(atkModule, addonId, 1);
|
||||||
|
} else {
|
||||||
|
// 6.05: 8443DD
|
||||||
|
if (*(uint*) ((IntPtr) lfg + 0x2AB8) > 0) {
|
||||||
|
lfg->Hide();
|
||||||
|
} else {
|
||||||
|
lfg->Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool IsMentor() {
|
||||||
|
if (this._isMentor == null || this._isMentorA1 == null || this._isMentorA1.Value == IntPtr.Zero) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._isMentor(this._isMentorA1.Value) > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ internal sealed class PayloadHandler {
|
|||||||
this.DrawPopups();
|
this.DrawPopups();
|
||||||
|
|
||||||
if (this._handleTooltips && ++this._hoverCounter - this._lastHoverCounter > 1) {
|
if (this._handleTooltips && ++this._hoverCounter - this._lastHoverCounter > 1) {
|
||||||
this.Ui.Plugin.Functions.CloseItemTooltip();
|
GameFunctions.CloseItemTooltip();
|
||||||
this._hoveredItem = 0;
|
this._hoveredItem = 0;
|
||||||
this._hoverCounter = this._lastHoverCounter = 0;
|
this._hoverCounter = this._lastHoverCounter = 0;
|
||||||
this._handleTooltips = false;
|
this._handleTooltips = false;
|
||||||
@ -91,7 +91,7 @@ internal sealed class PayloadHandler {
|
|||||||
}
|
}
|
||||||
case ItemPayload item: {
|
case ItemPayload item: {
|
||||||
if (this.Ui.Plugin.Config.NativeItemTooltips) {
|
if (this.Ui.Plugin.Config.NativeItemTooltips) {
|
||||||
this.Ui.Plugin.Functions.OpenItemTooltip(item.ItemId);
|
GameFunctions.OpenItemTooltip(item.ItemId);
|
||||||
|
|
||||||
this._handleTooltips = true;
|
this._handleTooltips = true;
|
||||||
if (this._hoveredItem != item.ItemId) {
|
if (this._hoveredItem != item.ItemId) {
|
||||||
@ -175,6 +175,13 @@ internal sealed class PayloadHandler {
|
|||||||
this.ClickLinkPayload(chunk, payload, link);
|
this.ClickLinkPayload(chunk, payload, link);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case RawPayload raw: {
|
||||||
|
if (Equals(raw, ChunkUtil.PeriodicRecruitmentLink)) {
|
||||||
|
GameFunctions.OpenPartyFinder();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,7 +294,7 @@ internal sealed class PayloadHandler {
|
|||||||
this.Ui.Plugin.Functions.SendFriendRequest(player.PlayerName, (ushort) player.World.RowId);
|
this.Ui.Plugin.Functions.SendFriendRequest(player.PlayerName, (ushort) player.World.RowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui.Selectable("Invite to Novice Network")) {
|
if (this.Ui.Plugin.Functions.IsMentor() && ImGui.Selectable("Invite to Novice Network")) {
|
||||||
// FIXME: only show if character is mentor and target is sprout/returner
|
// FIXME: only show if character is mentor and target is sprout/returner
|
||||||
this.Ui.Plugin.Functions.InviteToNoviceNetwork(player.PlayerName, (ushort) player.World.RowId);
|
this.Ui.Plugin.Functions.InviteToNoviceNetwork(player.PlayerName, (ushort) player.World.RowId);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ public sealed class Plugin : IDalamudPlugin {
|
|||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
this.Framework.Update -= this.FrameworkUpdate;
|
this.Framework.Update -= this.FrameworkUpdate;
|
||||||
this.Functions.SetChatInteractable(true);
|
GameFunctions.SetChatInteractable(true);
|
||||||
|
|
||||||
this.Ui.Dispose();
|
this.Ui.Dispose();
|
||||||
this.Store.Dispose();
|
this.Store.Dispose();
|
||||||
|
@ -197,7 +197,7 @@ internal sealed class Settings : IUiComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this._hideChat && hideChatChanged) {
|
if (!this._hideChat && hideChatChanged) {
|
||||||
this.Ui.Plugin.Functions.SetChatInteractable(true);
|
GameFunctions.SetChatInteractable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Initialise();
|
this.Initialise();
|
||||||
|
@ -70,6 +70,8 @@ internal static class ChunkUtil {
|
|||||||
glow.Pop();
|
glow.Pop();
|
||||||
} else if (Equals(rawPayload, RawPayload.LinkTerminator)) {
|
} else if (Equals(rawPayload, RawPayload.LinkTerminator)) {
|
||||||
link = null;
|
link = null;
|
||||||
|
} else if (Equals(rawPayload, PeriodicRecruitmentLink)) {
|
||||||
|
link = rawPayload;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -84,4 +86,8 @@ internal static class ChunkUtil {
|
|||||||
|
|
||||||
return chunks;
|
return chunks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static readonly RawPayload PeriodicRecruitmentLink = new(new byte[] {
|
||||||
|
0x02, 0x27, 0x07, 0x08, 0x01, 0x01, 0x01, 0xFF, 0x01, 0x03,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using Dalamud.Game;
|
|
||||||
using Dalamud.Logging;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
|
|
||||||
namespace ChatTwo.Util;
|
|
||||||
|
|
||||||
internal static class SigFinder {
|
|
||||||
internal static void ScanFunctions(this SigScanner scanner, object self) {
|
|
||||||
var selfType = self.GetType();
|
|
||||||
var funcs = selfType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
|
||||||
.Select(field => (field, field.GetCustomAttribute<SignatureAttribute>()))
|
|
||||||
.Where(tuple => tuple.Item2 != null);
|
|
||||||
foreach (var (field, attr) in funcs) {
|
|
||||||
if (!scanner.TryScanText(attr!.Signature, out var ptr)) {
|
|
||||||
PluginLog.LogWarning($"Could not find signature for {selfType.Name}.{field.Name}: {attr.Signature}");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
field.SetValue(self, ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Field)]
|
|
||||||
[MeansImplicitUse(ImplicitUseKindFlags.Assign, ImplicitUseTargetFlags.Itself)]
|
|
||||||
internal class SignatureAttribute : Attribute {
|
|
||||||
internal readonly string Signature;
|
|
||||||
|
|
||||||
internal SignatureAttribute(string signature) {
|
|
||||||
this.Signature = signature;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user