refactor: try allowing multiple actors

This commit is contained in:
Anna 2024-07-22 15:06:51 -04:00
parent 97eeab1129
commit 1d5a85d188
Signed by: anna
GPG Key ID: D0943384CD9F87D1

View File

@ -1,13 +1,14 @@
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.Game.Object;
using FFXIVClientStructs.Interop;
using Lumina.Excel.GeneratedSheets; using Lumina.Excel.GeneratedSheets;
namespace OrangeGuidanceTomestone.Util; namespace OrangeGuidanceTomestone.Util;
internal class ActorManager : IDisposable { internal class ActorManager : IDisposable {
private Plugin Plugin { get; } private Plugin Plugin { get; }
private uint? _idx; private readonly Stack<uint> _idx = [];
private readonly Queue<BaseActorAction> _tasks = []; private readonly Queue<BaseActorAction> _tasks = [];
internal ActorManager(Plugin plugin) { internal ActorManager(Plugin plugin) {
@ -22,10 +23,9 @@ internal class ActorManager : IDisposable {
this.Plugin.ClientState.TerritoryChanged -= this.OnTerritoryChange; this.Plugin.ClientState.TerritoryChanged -= this.OnTerritoryChange;
this.Plugin.Framework.Update -= this.OnFramework; this.Plugin.Framework.Update -= this.OnFramework;
if (this._idx != null) { if (this._idx.Count > 0) {
unsafe { unsafe {
var objMan = ClientObjectManager.Instance(); var objMan = ClientObjectManager.Instance();
new DisableAction().Run(this, objMan);
new DeleteAction().Run(this, objMan); new DeleteAction().Run(this, objMan);
} }
} }
@ -57,7 +57,7 @@ internal class ActorManager : IDisposable {
} }
private void OnTerritoryChange(ushort obj) { private void OnTerritoryChange(ushort obj) {
this._idx = null; this._idx.Clear();
} }
private void OnView(Message? message) { private void OnView(Message? message) {
@ -75,11 +75,6 @@ internal class ActorManager : IDisposable {
} }
internal void Despawn() { internal void Despawn() {
if (this._idx == null) {
return;
}
this._tasks.Enqueue(new DisableAction());
this._tasks.Enqueue(new DeleteAction()); this._tasks.Enqueue(new DeleteAction());
} }
@ -92,36 +87,28 @@ internal class ActorManager : IDisposable {
public int Tries { get; set; } public int Tries { get; set; }
protected bool TryGetBattleChara( protected IEnumerable<Pointer<BattleChara>> GetBattleCharas(
ActorManager manager, ActorManager manager,
ClientObjectManager* objMan, Pointer<ClientObjectManager> objMan
out BattleChara* chara
) { ) {
chara = null; foreach (var idx in manager._idx) {
Pointer<BattleChara> ptr;
unsafe {
var obj = (BattleChara*) objMan.Value->GetObjectByIndex((ushort) idx);
if (obj == null) {
continue;
}
if (manager._idx is not { } idx) { ptr = obj;
Plugin.Log.Warning("tried to get battlechara but idx was null"); }
return false;
yield return ptr;
} }
var obj = objMan->GetObjectByIndex((ushort) idx);
if (obj == null) {
Plugin.Log.Warning("tried to get battlechara but it was null");
return false;
}
chara = (BattleChara*) obj;
return true;
} }
} }
private unsafe class SpawnAction(Message message) : BaseActorAction { private unsafe class SpawnAction(Message message) : BaseActorAction {
public override bool Run(ActorManager manager, ClientObjectManager* objMan) { public override bool Run(ActorManager manager, ClientObjectManager* objMan) {
if (manager._idx != null) {
Plugin.Log.Warning("refusing to spawn a second actor");
return true;
}
if (message.Emote == null) { if (message.Emote == null) {
Plugin.Log.Warning("refusing to spawn an actor for a message without an emote"); Plugin.Log.Warning("refusing to spawn an actor for a message without an emote");
return true; return true;
@ -133,7 +120,7 @@ internal class ActorManager : IDisposable {
return true; return true;
} }
manager._idx = idx; manager._idx.Push(idx);
var emote = message.Emote; var emote = message.Emote;
var emoteRow = manager.GetValidEmote(emote.Id); var emoteRow = manager.GetValidEmote(emote.Id);
@ -211,43 +198,29 @@ internal class ActorManager : IDisposable {
private unsafe class EnableAction : BaseActorAction { private unsafe class EnableAction : BaseActorAction {
public override bool Run(ActorManager manager, ClientObjectManager* objMan) { public override bool Run(ActorManager manager, ClientObjectManager* objMan) {
if (!this.TryGetBattleChara(manager, objMan, out var chara)) { var allReady = true;
return true; foreach (var chara in this.GetBattleCharas(manager, objMan)) {
if (!chara.Value->IsReadyToDraw()) {
allReady = false;
continue;
}
chara.Value->EnableDraw();
} }
if (!chara->IsReadyToDraw()) { return allReady;
return false;
}
chara->EnableDraw();
return true;
}
}
private unsafe class DisableAction : BaseActorAction {
public override bool Run(ActorManager manager, ClientObjectManager* objMan) {
if (!this.TryGetBattleChara(manager, objMan, out var chara)) {
return true;
}
chara->DisableDraw();
return true;
} }
} }
private unsafe class DeleteAction : BaseActorAction { private unsafe class DeleteAction : BaseActorAction {
public override bool Run(ActorManager manager, ClientObjectManager* objMan) { public override bool Run(ActorManager manager, ClientObjectManager* objMan) {
if (manager._idx is not { } idx) { foreach (var wrapper in this.GetBattleCharas(manager, objMan)) {
Plugin.Log.Warning("delete action but idx was null"); wrapper.Value->DisableDraw();
return true; var idx = objMan->GetIndexByObject((GameObject*) wrapper.Value);
objMan->DeleteObjectByIndex((ushort) idx, 0);
} }
if (objMan->GetObjectByIndex((ushort) idx) == null) { manager._idx.Clear();
Plugin.Log.Warning("delete action but object at idx was null");
return true;
}
manager._idx = null;
return true; return true;
} }
} }