Skip to content

Commit

Permalink
Use object table index instead of passing ICharacter/Character addres…
Browse files Browse the repository at this point in the history
…s. Seems like the dev who decided to shit talk behind my back about this forgot it was them who implemented it that way.
  • Loading branch information
RisaDev committed Jul 29, 2024
1 parent f2ea64c commit 8fcfe9e
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 70 deletions.
2 changes: 1 addition & 1 deletion CustomizePlus/Api/CustomizePlusIpc.General.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace CustomizePlus.Api;

public partial class CustomizePlusIpc
{
private readonly (int Breaking, int Feature) _apiVersion = (4, 0);
private readonly (int Breaking, int Feature) _apiVersion = (5, 0);

/// <summary>
/// When there are breaking changes the first number is bumped up and second one is reset.
Expand Down
46 changes: 22 additions & 24 deletions CustomizePlus/Api/CustomizePlusIpc.Profile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public partial class CustomizePlusIpc
/// /!\ If no profile is set on specified character profile id will be equal to Guid.Empty
/// </summary>
[EzIPCEvent("Profile.OnUpdate")]
private Action<ICharacter, Guid> OnProfileUpdate;
private Action<ushort, Guid> OnProfileUpdate;

/// <summary>
/// Retrieve list of all user profiles
Expand Down Expand Up @@ -125,12 +125,14 @@ private ErrorCode SetProfileStateInternal(Guid uniqueId, bool state)
/// Get unique id of currently active profile for character.
/// </summary>
[EzIPC("Profile.GetActiveProfileIdOnCharacter")]
private (int, Guid?) GetActiveProfileIdOnCharacter(ICharacter character)
private (int, Guid?) GetActiveProfileIdOnCharacter(ushort gameObjectIndex)
{
if (character == null)
var actor = _gameObjectService.GetActorByObjectIndex(gameObjectIndex);

if (actor == null || !actor.Value.Valid || !actor.Value.IsCharacter)
return ((int)ErrorCode.InvalidCharacter, null);

var profile = _profileManager.GetProfileByCharacterName(character.Name.ToString(), true);
var profile = _profileManager.GetProfileByCharacterName(actor.Value.Utf8Name.ToString(), true);

if (profile == null)
return ((int)ErrorCode.ProfileNotFound, null);
Expand All @@ -143,14 +145,12 @@ private ErrorCode SetProfileStateInternal(Guid uniqueId, bool state)
/// Returns profile's unique id which can be used to manipulate it at a later date.
/// </summary>
[EzIPC("Profile.SetTemporaryProfileOnCharacter")]
private (int, Guid?) SetTemporaryProfileOnCharacter(ICharacter character, string profileJson)
private (int, Guid?) SetTemporaryProfileOnCharacter(ushort gameObjectIndex, string profileJson)
{
//todo: do not allow to set temporary profile on reserved actors (examine, etc)
if (character == null)
return ((int)ErrorCode.InvalidCharacter, null);
var actor = _gameObjectService.GetActorByObjectIndex(gameObjectIndex);

var actor = (Actor)character.Address;
if (!actor.Valid)
//todo: do not allow to set temporary profile on reserved actors (examine, etc)
if (actor == null || !actor.Value.Valid || !actor.Value.IsCharacter)
return ((int)ErrorCode.InvalidCharacter, null);

try
Expand All @@ -162,26 +162,26 @@ private ErrorCode SetProfileStateInternal(Guid uniqueId, bool state)
}
catch (Exception ex)
{
_logger.Error($"IPCCharacterProfile deserialization issue. Character: {character?.Name.ToString().Incognify()}, exception: {ex}.");
_logger.Error($"IPCCharacterProfile deserialization issue. Character: {actor.Value.Utf8Name.ToString().Incognify()}, exception: {ex}.");
return ((int)ErrorCode.CorruptedProfile, null);
}

if (profile == null)
{
_logger.Error($"IPCCharacterProfile is null after deserialization. Character: {character?.Name.ToString().Incognify()}.");
_logger.Error($"IPCCharacterProfile is null after deserialization. Character: {actor.Value.Utf8Name.ToString().Incognify()}.");
return ((int)ErrorCode.CorruptedProfile, null);
}

//todo: ideally we'd probably want to make sure ID returned by that function does not have collision with other profiles
var fullProfile = IPCCharacterProfile.ToFullProfile(profile).Item1;

_profileManager.AddTemporaryProfile(fullProfile, actor);
_profileManager.AddTemporaryProfile(fullProfile, actor.Value);
return ((int)ErrorCode.Success, fullProfile.UniqueId);

}
catch (Exception ex)
{
_logger.Error($"Unable to set temporary profile. Character: {character?.Name.ToString().Incognify()}, exception: {ex}.");
_logger.Error($"Unable to set temporary profile. Character: {actor.Value.Utf8Name.ToString().Incognify()}, exception: {ex}.");
return ((int)ErrorCode.UnknownError, null);
}
}
Expand All @@ -190,18 +190,16 @@ private ErrorCode SetProfileStateInternal(Guid uniqueId, bool state)
/// Delete temporary profile currently active on character
/// </summary>
[EzIPC("Profile.DeleteTemporaryProfileOnCharacter")]
private int DeleteTemporaryProfileOnCharacter(ICharacter character)
private int DeleteTemporaryProfileOnCharacter(ushort gameObjectIndex)
{
if (character == null)
return (int)ErrorCode.InvalidCharacter;
var actor = _gameObjectService.GetActorByObjectIndex(gameObjectIndex);

var actor = (Actor)character.Address;
if (!actor.Valid)
if (actor == null || !actor.Value.Valid || !actor.Value.IsCharacter)
return (int)ErrorCode.InvalidCharacter;

try
{
_profileManager.RemoveTemporaryProfile(actor);
_profileManager.RemoveTemporaryProfile(actor.Value);
return (int)ErrorCode.Success;
}
catch(ProfileException ex)
Expand All @@ -213,13 +211,13 @@ private int DeleteTemporaryProfileOnCharacter(ICharacter character)
case ProfileNotFoundException:
return (int)ErrorCode.ProfileNotFound;
default:
_logger.Error($"Exception in DeleteTemporaryProfileOnCharacter. Character: {character?.Name.ToString().Incognify()}. Exception: {ex}");
_logger.Error($"Exception in DeleteTemporaryProfileOnCharacter. Character: {actor.Value.Utf8Name.ToString().Incognify()}. Exception: {ex}");
return (int)ErrorCode.UnknownError;
}
}
catch(Exception ex)
{
_logger.Error($"Exception in DeleteTemporaryProfileOnCharacter. Character: {character?.Name.ToString().Incognify()}. Exception: {ex}");
_logger.Error($"Exception in DeleteTemporaryProfileOnCharacter. Character: {actor.Value.Utf8Name.ToString().Incognify()}. Exception: {ex}");
return (int)ErrorCode.UnknownError;
}
}
Expand Down Expand Up @@ -309,7 +307,7 @@ private void OnArmatureChanged(ArmatureChanged.Type type, Armature armature, obj
if (type == ArmatureChanged.Type.Deleted)
{
//Do not send event if default or editor profile was used
if (armature.Profile == _profileManager.DefaultProfile || armature.Profile.ProfileType == ProfileType.Editor)
if (armature.Profile == _profileManager.DefaultProfile || armature.Profile.ProfileType == ProfileType.Editor) //todo: never send if ProfileType != normal?
return;

OnProfileUpdateInternal(localPlayerCharacter, null);
Expand All @@ -327,6 +325,6 @@ private void OnProfileUpdateInternal(ICharacter character, Profile? profile)

_logger.Debug($"Sending player update message: Character: {character.Name.ToString().Incognify()}, Profile: {(profile != null ? profile.ToString() : "no profile")}");

OnProfileUpdate(character, profile != null ? profile.UniqueId : Guid.Empty);
OnProfileUpdate(character.ObjectIndex, profile != null ? profile.UniqueId : Guid.Empty);
}
}
20 changes: 14 additions & 6 deletions CustomizePlus/Game/Services/GameObjectService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,8 @@
using Penumbra.GameData.Interop;
using ObjectManager = CustomizePlus.GameData.Services.ObjectManager;
using DalamudGameObject = Dalamud.Game.ClientState.Objects.Types.IGameObject;
using ECommons.Configuration;
using System;
using CustomizePlus.Configuration.Data;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using Penumbra.GameData;
using Penumbra.String;
using Dalamud.Logging;
using FFXIVClientStructs.FFXIV.Client.Game.Object;

namespace CustomizePlus.Game.Services;

Expand Down Expand Up @@ -145,6 +140,19 @@ public Actor GetLocalPlayerActor()
}
}

/// <summary>
/// Find actor in object manager based on its Object ID.
/// </summary>
public Actor? GetActorByObjectIndex(ushort objectIndex)
{
if (objectIndex < 0 || objectIndex >= _objectManager.TotalCount)
return null;

var ptr = _objectManager[(int)objectIndex];

return ptr;
}

public enum SpecialResult
{
PartyBanner,
Expand Down
49 changes: 10 additions & 39 deletions CustomizePlus/UI/Windows/MainWindow/Tabs/Debug/IPCTestTab.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,20 @@ public class IPCTestTab //: IDisposable
private readonly Func<Guid, int> _disableProfileByUniqueIdIpcFunc;

[EzIPC("Profile.GetActiveProfileIdOnCharacter")]
private readonly Func<ICharacter, (int, Guid?)> _getActiveProfileIdOnCharacterIpcFunc;
private readonly Func<ushort, (int, Guid?)> _getActiveProfileIdOnCharacterIpcFunc;

[EzIPC("Profile.SetTemporaryProfileOnCharacter")]
private readonly Func<ICharacter, string, (int, Guid?)> _setTemporaryProfileOnCharacterIpcFunc;
private readonly Func<ushort, string, (int, Guid?)> _setTemporaryProfileOnCharacterIpcFunc;

[EzIPC("Profile.DeleteTemporaryProfileOnCharacter")]
private readonly Func<ICharacter, int> _deleteTemporaryProfileOnCharacterIpcFunc;
private readonly Func<ushort, int> _deleteTemporaryProfileOnCharacterIpcFunc;

[EzIPC("Profile.DeleteTemporaryProfileByUniqueId")]
private readonly Func<Guid, int> _deleteTemporaryProfileByUniqueIdIpcFunc;

[EzIPC("Profile.GetByUniqueId")]
private readonly Func<Guid, (int, string?)> _getProfileByIdIpcFunc;

//private readonly ICallGateSubscriber<string, Character?, object>? _setCharacterProfile;
//private readonly ICallGateSubscriber<Character?, string>? _getProfileFromCharacter;
//private readonly ICallGateSubscriber<Character?, object>? _revertCharacter;
//private readonly ICallGateSubscriber<string?, string?, object?>? _onProfileUpdate;

private string? _rememberedProfileJson;

private (int, int) _apiVersion;
Expand Down Expand Up @@ -103,24 +98,8 @@ public IPCTestTab(

if (_getApiVersionIpcFunc != null)
_apiVersion = _getApiVersionIpcFunc();

//_setCharacterProfile = pluginInterface.GetIpcSubscriber<string, Character?, object>("CustomizePlus.SetProfileToCharacter");
//_getProfileFromCharacter = pluginInterface.GetIpcSubscriber<Character?, string>("CustomizePlus.GetProfileFromCharacter");
//_revertCharacter = pluginInterface.GetIpcSubscriber<Character?, object>("CustomizePlus.RevertCharacter");
/*_onProfileUpdate = pluginInterface.GetIpcSubscriber<string?, string?, object?>("CustomizePlus.OnProfileUpdate");
_onProfileUpdate.Subscribe(OnProfileUpdate);*/
}
/* public void Dispose()
{
_onProfileUpdate?.Unsubscribe(OnProfileUpdate);
}
private void OnProfileUpdate(string? characterName, string? profileJson)
{
_lastProfileUpdate = DateTime.Now;
_lastProfileUpdateName = characterName;
}
*/

public unsafe void Draw()
{
_objectManager.Update();
Expand All @@ -141,7 +120,6 @@ public unsafe void Draw()

ImGui.Separator();

//ImGui.Text($"Last profile update: {_lastProfileUpdate}, Character: {_lastProfileUpdateName}");
ImGui.Text($"Memory: {(string.IsNullOrWhiteSpace(_rememberedProfileJson) ? "empty" : "has data")}");

ImGui.Text("Character to operate on:");
Expand Down Expand Up @@ -171,7 +149,7 @@ public unsafe void Draw()
if (actors.Count == 0)
return;

(int result, Guid? uniqueId) = _getActiveProfileIdOnCharacterIpcFunc(FindCharacterByAddress(actors[0].Item2.Address));
(int result, Guid? uniqueId) = _getActiveProfileIdOnCharacterIpcFunc(actors[0].Item2.Index.Index);

if(result == 0)
{
Expand All @@ -193,7 +171,7 @@ public unsafe void Draw()
if (actors.Count == 0)
return;

(int result, Guid? profileGuid) = _setTemporaryProfileOnCharacterIpcFunc(FindCharacterByAddress(actors[0].Item2.Address), _rememberedProfileJson);
(int result, Guid? profileGuid) = _setTemporaryProfileOnCharacterIpcFunc(actors[0].Item2.Index.Index, _rememberedProfileJson);
if (result == 0)
{
_popupSystem.ShowPopup(PopupSystem.Messages.IPCSetProfileToChrDone);
Expand All @@ -213,7 +191,7 @@ public unsafe void Draw()
if (actors.Count == 0)
return;

int result = _deleteTemporaryProfileOnCharacterIpcFunc(FindCharacterByAddress(actors[0].Item2.Address));
int result = _deleteTemporaryProfileOnCharacterIpcFunc(actors[0].Item2.Index.Index);
if (result == 0)
_popupSystem.ShowPopup(PopupSystem.Messages.IPCRevertDone);
else
Expand Down Expand Up @@ -311,17 +289,10 @@ public unsafe void Draw()
}

[EzIPCEvent("Profile.OnUpdate")]
private void OnProfileUpdate(ICharacter Character, Guid ProfileUniqueId)
{
_logger.Debug($"IPC Test Tab - OnProfileUpdate: Character: {Character.Name.ToString().Incognify()}, Profile ID: {(ProfileUniqueId != Guid.Empty ? ProfileUniqueId.ToString() : "no id")}");
}

private ICharacter? FindCharacterByAddress(nint address)
private void OnProfileUpdate(ushort gameObjectIndex, Guid profileUniqueId)
{
foreach (var obj in _objectTable)
if (obj.Address == address)
return (ICharacter)obj;
var actor = _gameObjectService.GetActorByObjectIndex(gameObjectIndex);

return null;
_logger.Debug($"IPC Test Tab - OnProfileUpdate: Character: {actor?.Utf8Name.ToString().Incognify() ?? "None"}, Profile ID: {(profileUniqueId != Guid.Empty ? profileUniqueId.ToString() : "no id")}");
}
}

0 comments on commit 8fcfe9e

Please sign in to comment.