refactor: update for api 10
This commit is contained in:
parent
cfdc84a4bb
commit
4c838b1ee5
@ -8,11 +8,11 @@ namespace PeepingTom.Ipc {
|
||||
public const string FromRegistrationName = "PeepingTom.From";
|
||||
public const string ToRegistrationName = "PeepingTom.To";
|
||||
|
||||
public static ICallGateProvider<IToMessage, object> GetProvider(DalamudPluginInterface @interface) {
|
||||
public static ICallGateProvider<IToMessage, object> GetProvider(IDalamudPluginInterface @interface) {
|
||||
return @interface.GetIpcProvider<IToMessage, object>(ToRegistrationName);
|
||||
}
|
||||
|
||||
public static ICallGateSubscriber<IFromMessage, object> GetSubscriber(DalamudPluginInterface @interface) {
|
||||
public static ICallGateSubscriber<IFromMessage, object> GetSubscriber(IDalamudPluginInterface @interface) {
|
||||
return @interface.GetIpcSubscriber<IFromMessage, object>(FromRegistrationName);
|
||||
}
|
||||
}
|
||||
|
@ -10,27 +10,31 @@ namespace PeepingTom.Ipc {
|
||||
public class Targeter {
|
||||
[JsonConverter(typeof(SeStringConverter))]
|
||||
public SeString Name { get; }
|
||||
|
||||
public uint HomeWorldId { get; }
|
||||
public uint ObjectId { get; }
|
||||
public ulong GameObjectId { get; }
|
||||
public uint EntityId { get; }
|
||||
public DateTime When { get; }
|
||||
|
||||
public Targeter(PlayerCharacter character) {
|
||||
public Targeter(IPlayerCharacter character) {
|
||||
this.Name = character.Name;
|
||||
this.HomeWorldId = character.HomeWorld.Id;
|
||||
this.ObjectId = character.ObjectId;
|
||||
this.EntityId = character.EntityId;
|
||||
this.GameObjectId = character.GameObjectId;
|
||||
this.When = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
[JsonConstructor]
|
||||
public Targeter(SeString name, uint homeWorldId, uint objectId, DateTime when) {
|
||||
public Targeter(SeString name, uint homeWorldId, uint entityId, ulong gameObjectId, DateTime when) {
|
||||
this.Name = name;
|
||||
this.HomeWorldId = homeWorldId;
|
||||
this.ObjectId = objectId;
|
||||
this.EntityId = entityId;
|
||||
this.GameObjectId = gameObjectId;
|
||||
this.When = when;
|
||||
}
|
||||
|
||||
public PlayerCharacter? GetPlayerCharacter(IObjectTable objectTable) {
|
||||
return objectTable.FirstOrDefault(actor => actor.ObjectId == this.ObjectId && actor is PlayerCharacter) as PlayerCharacter;
|
||||
public IPlayerCharacter? GetPlayerCharacter(IObjectTable objectTable) {
|
||||
return objectTable.FirstOrDefault(actor => actor.GameObjectId == this.GameObjectId && actor is IPlayerCharacter) as IPlayerCharacter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ namespace PeepingTom {
|
||||
internal class Configuration : IPluginConfiguration {
|
||||
public int Version { get; set; } = 1;
|
||||
|
||||
private DalamudPluginInterface Interface { get; set; } = null!;
|
||||
private IDalamudPluginInterface Interface { get; set; } = null!;
|
||||
|
||||
public bool MarkTargeted { get; set; }
|
||||
|
||||
@ -52,7 +52,7 @@ namespace PeepingTom {
|
||||
|
||||
public int PollFrequency { get; set; } = 100;
|
||||
|
||||
public void Initialize(DalamudPluginInterface pluginInterface) {
|
||||
public void Initialize(IDalamudPluginInterface pluginInterface) {
|
||||
this.Interface = pluginInterface;
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,10 @@
|
||||
<HintPath>$(DalamudLibPath)\ImGui.NET.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="FFXIVClientStructs">
|
||||
<HintPath>$(DalamudLibPath)\FFXIVClientStructs.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Lumina">
|
||||
<HintPath>$(DalamudLibPath)\Lumina.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
@ -51,12 +55,11 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DalamudPackager" Version="2.1.12"/>
|
||||
<PackageReference Include="Fody" Version="6.8.0" PrivateAssets="all"/>
|
||||
<PackageReference Include="DalamudPackager" Version="2.1.13" />
|
||||
<PackageReference Include="Fody" Version="6.8.1" PrivateAssets="all" />
|
||||
<PackageReference Include="NAudio.Core" Version="2.2.1"/>
|
||||
<PackageReference Include="NAudio.Wasapi" Version="2.2.1"/>
|
||||
<PackageReference Include="Resourcer.Fody" Version="1.8.1" PrivateAssets="all"/>
|
||||
<PackageReference Include="XivCommon" Version="9.0.0"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Peeping Tom.Ipc\Peeping Tom.Ipc.csproj"/>
|
||||
|
@ -7,7 +7,6 @@ using Dalamud.IoC;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using PeepingTom.Resources;
|
||||
using XivCommon;
|
||||
|
||||
namespace PeepingTom {
|
||||
// ReSharper disable once ClassNeverInstantiated.Global
|
||||
@ -18,7 +17,7 @@ namespace PeepingTom {
|
||||
internal static IPluginLog Log { get; private set; } = null!;
|
||||
|
||||
[PluginService]
|
||||
internal DalamudPluginInterface Interface { get; init; } = null!;
|
||||
internal IDalamudPluginInterface Interface { get; init; } = null!;
|
||||
|
||||
[PluginService]
|
||||
internal IChatGui ChatGui { get; init; } = null!;
|
||||
@ -53,13 +52,11 @@ namespace PeepingTom {
|
||||
internal Configuration Config { get; }
|
||||
internal PluginUi Ui { get; }
|
||||
internal TargetWatcher Watcher { get; }
|
||||
internal XivCommonBase Common { get; }
|
||||
internal IpcManager IpcManager { get; }
|
||||
|
||||
internal bool InPvp { get; private set; }
|
||||
|
||||
public Plugin() {
|
||||
this.Common = new XivCommonBase(this.Interface);
|
||||
this.Config = this.Interface.GetPluginConfig() as Configuration ?? new Configuration();
|
||||
this.Config.Initialize(this.Interface);
|
||||
this.Watcher = new TargetWatcher(this);
|
||||
@ -99,7 +96,6 @@ namespace PeepingTom {
|
||||
this.IpcManager.Dispose();
|
||||
this.Ui.Dispose();
|
||||
this.Watcher.Dispose();
|
||||
this.Common.Dispose();
|
||||
}
|
||||
|
||||
private static void OnLanguageChange(string langCode) {
|
||||
|
@ -16,12 +16,13 @@ using PeepingTom.Ipc;
|
||||
using PeepingTom.Resources;
|
||||
using Dalamud.Interface.ImGuiFileDialog;
|
||||
using Dalamud.Interface;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||
|
||||
namespace PeepingTom {
|
||||
internal class PluginUi : IDisposable {
|
||||
private Plugin Plugin { get; }
|
||||
|
||||
private uint? PreviousFocus { get; set; } = new();
|
||||
private ulong? PreviousFocus { get; set; } = new();
|
||||
|
||||
private bool _wantsOpen;
|
||||
|
||||
@ -115,9 +116,9 @@ namespace PeepingTom {
|
||||
}
|
||||
|
||||
var targeting = this.Plugin.Watcher.CurrentTargeters
|
||||
.Select(targeter => this.Plugin.ObjectTable.FirstOrDefault(obj => obj.ObjectId == targeter.ObjectId))
|
||||
.Where(targeter => targeter is PlayerCharacter)
|
||||
.Cast<PlayerCharacter>()
|
||||
.Select(targeter => this.Plugin.ObjectTable.FirstOrDefault(obj => obj.GameObjectId == targeter.GameObjectId))
|
||||
.Where(targeter => targeter is IPlayerCharacter)
|
||||
.Cast<IPlayerCharacter>()
|
||||
.ToArray();
|
||||
foreach (var targeter in targeting) {
|
||||
this.MarkPlayer(targeter, this.Plugin.Config.TargetingColour, this.Plugin.Config.TargetingSize);
|
||||
@ -408,15 +409,15 @@ namespace PeepingTom {
|
||||
|
||||
// to prevent looping over a subset of the actors repeatedly when multiple people are targeting,
|
||||
// create a dictionary for O(1) lookups by actor id
|
||||
Dictionary<uint, GameObject>? objects = null;
|
||||
Dictionary<ulong, IGameObject>? objects = null;
|
||||
if (targeting.Count + (previousTargeters?.Count ?? 0) > 1) {
|
||||
var dict = new Dictionary<uint, GameObject>();
|
||||
var dict = new Dictionary<ulong, IGameObject>();
|
||||
foreach (var obj in this.Plugin.ObjectTable) {
|
||||
if (dict.ContainsKey(obj.ObjectId) || obj.ObjectKind != ObjectKind.Player) {
|
||||
if (dict.ContainsKey(obj.GameObjectId) || obj.ObjectKind != ObjectKind.Player) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dict.Add(obj.ObjectId, obj);
|
||||
dict.Add(obj.GameObjectId, obj);
|
||||
}
|
||||
|
||||
objects = dict;
|
||||
@ -459,20 +460,20 @@ namespace PeepingTom {
|
||||
// }
|
||||
|
||||
foreach (var targeter in targeting) {
|
||||
GameObject? obj = null;
|
||||
objects?.TryGetValue(targeter.ObjectId, out obj);
|
||||
IGameObject? obj = null;
|
||||
objects?.TryGetValue(targeter.GameObjectId, out obj);
|
||||
this.AddEntry(targeter, obj, ref anyHovered);
|
||||
}
|
||||
|
||||
if (this.Plugin.Config.KeepHistory) {
|
||||
// get a list of the previous targeters that aren't currently targeting
|
||||
var previous = (previousTargeters ?? new List<Targeter>())
|
||||
.Where(old => targeting.All(actor => actor.ObjectId != old.ObjectId))
|
||||
.Where(old => targeting.All(actor => actor.GameObjectId != old.GameObjectId))
|
||||
.Take(this.Plugin.Config.NumHistory);
|
||||
// add previous targeters to the list
|
||||
foreach (var oldTargeter in previous) {
|
||||
GameObject? obj = null;
|
||||
objects?.TryGetValue(oldTargeter.ObjectId, out obj);
|
||||
IGameObject? obj = null;
|
||||
objects?.TryGetValue(oldTargeter.GameObjectId, out obj);
|
||||
this.AddEntry(oldTargeter, obj, ref anyHovered, ImGuiSelectableFlags.Disabled);
|
||||
}
|
||||
}
|
||||
@ -485,7 +486,7 @@ namespace PeepingTom {
|
||||
if (previousFocus == uint.MaxValue) {
|
||||
this.Plugin.TargetManager.FocusTarget = null;
|
||||
} else {
|
||||
var actor = this.Plugin.ObjectTable.FirstOrDefault(a => a.ObjectId == previousFocus);
|
||||
var actor = this.Plugin.ObjectTable.FirstOrDefault(a => a.GameObjectId == previousFocus);
|
||||
// either target the actor if still present or target nothing
|
||||
this.Plugin.TargetManager.FocusTarget = actor;
|
||||
}
|
||||
@ -510,7 +511,7 @@ namespace PeepingTom {
|
||||
ImGui.EndTooltip();
|
||||
}
|
||||
|
||||
private void AddEntry(Targeter targeter, GameObject? obj, ref bool anyHovered, ImGuiSelectableFlags flags = ImGuiSelectableFlags.None) {
|
||||
private void AddEntry(Targeter targeter, IGameObject? obj, ref bool anyHovered, ImGuiSelectableFlags flags = ImGuiSelectableFlags.None) {
|
||||
ImGui.BeginGroup();
|
||||
|
||||
ImGui.Selectable(targeter.Name.TextValue, false, flags);
|
||||
@ -539,7 +540,7 @@ namespace PeepingTom {
|
||||
var left = hover && ImGui.IsMouseClicked(ImGuiMouseButton.Left);
|
||||
var right = hover && ImGui.IsMouseClicked(ImGuiMouseButton.Right);
|
||||
|
||||
obj ??= this.Plugin.ObjectTable.FirstOrDefault(a => a.ObjectId == targeter.ObjectId);
|
||||
obj ??= this.Plugin.ObjectTable.FirstOrDefault(a => a.GameObjectId == targeter.GameObjectId);
|
||||
|
||||
// don't count as hovered if the actor isn't here (clears focus target when hovering missing actors)
|
||||
if (obj != null) {
|
||||
@ -547,21 +548,23 @@ namespace PeepingTom {
|
||||
}
|
||||
|
||||
if (this.Plugin.Config.FocusTargetOnHover && hover && obj != null) {
|
||||
this.PreviousFocus ??= this.Plugin.TargetManager.FocusTarget?.ObjectId ?? uint.MaxValue;
|
||||
this.PreviousFocus ??= this.Plugin.TargetManager.FocusTarget?.GameObjectId ?? uint.MaxValue;
|
||||
this.Plugin.TargetManager.FocusTarget = obj;
|
||||
}
|
||||
|
||||
if (left) {
|
||||
if (this.Plugin.Config.OpenExamine && ImGui.GetIO().KeyAlt) {
|
||||
if (obj != null) {
|
||||
this.Plugin.Common.Functions.Examine.OpenExamineWindow(obj);
|
||||
unsafe {
|
||||
AgentInspect.Instance()->ExamineCharacter(obj.EntityId);
|
||||
}
|
||||
} else {
|
||||
var error = string.Format(Language.ExamineErrorToast, targeter.Name);
|
||||
this.Plugin.ToastGui.ShowError(error);
|
||||
}
|
||||
} else {
|
||||
var payload = new PlayerPayload(targeter.Name.TextValue, targeter.HomeWorldId);
|
||||
Payload[] payloads = { payload };
|
||||
Payload[] payloads = [payload];
|
||||
this.Plugin.ChatGui.Print(new XivChatEntry {
|
||||
Message = new SeString(payloads),
|
||||
});
|
||||
@ -571,7 +574,7 @@ namespace PeepingTom {
|
||||
}
|
||||
}
|
||||
|
||||
private void MarkPlayer(GameObject? player, Vector4 colour, float size) {
|
||||
private void MarkPlayer(IGameObject? player, Vector4 colour, float size) {
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
@ -592,7 +595,7 @@ namespace PeepingTom {
|
||||
ImGui.PopClipRect();
|
||||
}
|
||||
|
||||
private PlayerCharacter? GetCurrentTarget() {
|
||||
private IPlayerCharacter? GetCurrentTarget() {
|
||||
var player = this.Plugin.ClientState.LocalPlayer;
|
||||
if (player == null) {
|
||||
return null;
|
||||
@ -604,8 +607,8 @@ namespace PeepingTom {
|
||||
}
|
||||
|
||||
return this.Plugin.ObjectTable
|
||||
.Where(actor => actor.ObjectId == targetId && actor is PlayerCharacter)
|
||||
.Select(actor => actor as PlayerCharacter)
|
||||
.Where(actor => actor.GameObjectId == targetId && actor is IPlayerCharacter)
|
||||
.Select(actor => actor as IPlayerCharacter)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
@ -21,11 +21,11 @@ namespace PeepingTom {
|
||||
private Stopwatch? SoundWatch { get; set; }
|
||||
private int LastTargetAmount { get; set; }
|
||||
|
||||
private Targeter[] Current { get; set; } = Array.Empty<Targeter>();
|
||||
private Targeter[] Current { get; set; } = [];
|
||||
|
||||
public IReadOnlyCollection<Targeter> CurrentTargeters => this.Current;
|
||||
|
||||
private List<Targeter> Previous { get; } = new();
|
||||
private List<Targeter> Previous { get; } = [];
|
||||
|
||||
public IReadOnlyCollection<Targeter> PreviousTargeters => this.Previous;
|
||||
|
||||
@ -63,7 +63,7 @@ namespace PeepingTom {
|
||||
// get targeters and set a copy so we can release the mutex faster
|
||||
var newCurrent = this.GetTargeting(this.Plugin.ObjectTable, player);
|
||||
|
||||
foreach (var newTargeter in newCurrent.Where(t => this.Current.All(c => c.ObjectId != t.ObjectId))) {
|
||||
foreach (var newTargeter in newCurrent.Where(t => this.Current.All(c => c.GameObjectId != t.GameObjectId))) {
|
||||
try {
|
||||
this.Plugin.IpcManager.SendNewTargeter(newTargeter);
|
||||
} catch (Exception ex) {
|
||||
@ -71,7 +71,7 @@ namespace PeepingTom {
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var stopped in this.Current.Where(t => newCurrent.All(c => c.ObjectId != t.ObjectId))) {
|
||||
foreach (var stopped in this.Current.Where(t => newCurrent.All(c => c.GameObjectId != t.GameObjectId))) {
|
||||
try {
|
||||
this.Plugin.IpcManager.SendStoppedTargeting(stopped);
|
||||
} catch (Exception ex) {
|
||||
@ -99,42 +99,42 @@ namespace PeepingTom {
|
||||
|
||||
foreach (var targeter in targeting) {
|
||||
// add the targeter to the previous list
|
||||
if (this.Previous.Any(old => old.ObjectId == targeter.ObjectId)) {
|
||||
this.Previous.RemoveAll(old => old.ObjectId == targeter.ObjectId);
|
||||
if (this.Previous.Any(old => old.GameObjectId == targeter.GameObjectId)) {
|
||||
this.Previous.RemoveAll(old => old.GameObjectId == targeter.GameObjectId);
|
||||
}
|
||||
|
||||
this.Previous.Insert(0, targeter);
|
||||
}
|
||||
|
||||
// only keep the configured number of previous targeters (ignoring ones that are currently targeting)
|
||||
while (this.Previous.Count(old => targeting.All(actor => actor.ObjectId != old.ObjectId)) > this.Plugin.Config.NumHistory) {
|
||||
while (this.Previous.Count(old => targeting.All(actor => actor.GameObjectId != old.GameObjectId)) > this.Plugin.Config.NumHistory) {
|
||||
this.Previous.RemoveAt(this.Previous.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
private Targeter[] GetTargeting(IEnumerable<GameObject> objects, GameObject player) {
|
||||
private Targeter[] GetTargeting(IEnumerable<IGameObject> objects, IGameObject player) {
|
||||
return objects
|
||||
.Where(obj => obj.TargetObjectId == player.ObjectId && obj is PlayerCharacter)
|
||||
.Where(obj => obj.TargetObjectId == player.GameObjectId && obj is IPlayerCharacter)
|
||||
// .Where(obj => Marshal.ReadByte(obj.Address + ActorOffsets.PlayerCharacterTargetActorId + 4) == 0)
|
||||
.Cast<PlayerCharacter>()
|
||||
.Cast<IPlayerCharacter>()
|
||||
.Where(actor => this.Plugin.Config.LogParty || !InParty(actor))
|
||||
.Where(actor => this.Plugin.Config.LogAlliance || !InAlliance(actor))
|
||||
.Where(actor => this.Plugin.Config.LogInCombat || !InCombat(actor))
|
||||
.Where(actor => this.Plugin.Config.LogSelf || actor.ObjectId != player.ObjectId)
|
||||
.Where(actor => this.Plugin.Config.LogSelf || actor.GameObjectId != player.GameObjectId)
|
||||
.Select(actor => new Targeter(actor))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private static byte GetStatus(GameObject actor) {
|
||||
private static byte GetStatus(IGameObject actor) {
|
||||
var statusPtr = actor.Address + 0x1980; // updated 5.4
|
||||
return Marshal.ReadByte(statusPtr);
|
||||
}
|
||||
|
||||
private static bool InCombat(GameObject actor) => (GetStatus(actor) & 2) > 0;
|
||||
private static bool InCombat(IGameObject actor) => (GetStatus(actor) & 2) > 0;
|
||||
|
||||
private static bool InParty(GameObject actor) => (GetStatus(actor) & 16) > 0;
|
||||
private static bool InParty(IGameObject actor) => (GetStatus(actor) & 16) > 0;
|
||||
|
||||
private static bool InAlliance(GameObject actor) => (GetStatus(actor) & 32) > 0;
|
||||
private static bool InAlliance(IGameObject actor) => (GetStatus(actor) & 32) > 0;
|
||||
|
||||
private bool CanPlaySound() {
|
||||
if (!this.Plugin.Config.PlaySoundOnTarget) {
|
||||
@ -178,10 +178,9 @@ namespace PeepingTom {
|
||||
return;
|
||||
}
|
||||
|
||||
using var channel = new WaveChannel32(reader) {
|
||||
Volume = this.Plugin.Config.SoundVolume,
|
||||
PadWithZeroes = false,
|
||||
};
|
||||
using var channel = new WaveChannel32(reader);
|
||||
channel.Volume = this.Plugin.Config.SoundVolume;
|
||||
channel.PadWithZeroes = false;
|
||||
|
||||
using (reader) {
|
||||
using var output = new DirectSoundOut(soundDevice.Guid);
|
||||
|
18
Peeping Tom/packages.lock.json
Normal file → Executable file
18
Peeping Tom/packages.lock.json
Normal file → Executable file
@ -4,15 +4,15 @@
|
||||
"net8.0-windows7.0": {
|
||||
"DalamudPackager": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.1.12, )",
|
||||
"resolved": "2.1.12",
|
||||
"contentHash": "Sc0PVxvgg4NQjcI8n10/VfUQBAS4O+Fw2pZrAqBdRMbthYGeogzu5+xmIGCGmsEZ/ukMOBuAqiNiB5qA3MRalg=="
|
||||
"requested": "[2.1.13, )",
|
||||
"resolved": "2.1.13",
|
||||
"contentHash": "rMN1omGe8536f4xLMvx9NwfvpAc9YFFfeXJ1t4P4PE6Gu8WCIoFliR1sh07hM+bfODmesk/dvMbji7vNI+B/pQ=="
|
||||
},
|
||||
"Fody": {
|
||||
"type": "Direct",
|
||||
"requested": "[6.8.0, )",
|
||||
"resolved": "6.8.0",
|
||||
"contentHash": "hfZ/f8Mezt8aTkgv9nsvFdYoQ809/AqwsJlOGOPYIfBcG2aAIG3v3ex9d8ZqQuFYyMoucjRg4eKy3VleeGodKQ=="
|
||||
"requested": "[6.8.1, )",
|
||||
"resolved": "6.8.1",
|
||||
"contentHash": "pwk2/No1kL1ft+zMT2y0MvzB6W5cpkdOTj+0+T2u7LGJMTw37qtlnHzCSCyvwRiZVoJ/V/DE78eQ/WEcutUVDw=="
|
||||
},
|
||||
"NAudio.Core": {
|
||||
"type": "Direct",
|
||||
@ -38,12 +38,6 @@
|
||||
"Fody": "6.6.4"
|
||||
}
|
||||
},
|
||||
"XivCommon": {
|
||||
"type": "Direct",
|
||||
"requested": "[9.0.0, )",
|
||||
"resolved": "9.0.0",
|
||||
"contentHash": "avaBp3FmSCi/PiQhntCeBDYOHejdyTWmFtz4pRBVQQ8vHkmRx+YTk1la9dkYBMlXxRXKckEdH1iI1Fu61JlE7w=="
|
||||
},
|
||||
"PeepingTom.Ipc": {
|
||||
"type": "Project"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user