forked from Eauldane/SnowcloakClient
Compare commits
39 Commits
00c56b0888
...
0.3.0
Author | SHA1 | Date | |
---|---|---|---|
d6320ed16a | |||
830a401c90 | |||
3d2176693e | |||
d3295b1d8c | |||
![]() |
fe5de199a1 | ||
cbb904a8d5 | |||
2a555e6440 | |||
![]() |
42893e5b53 | ||
563ed52f90 | |||
ddef5cb2cf | |||
![]() |
684787183c | ||
![]() |
fccdd6f91e | ||
![]() |
17095147a5 | ||
752679370a | |||
b4cad9c745 | |||
100c5612dc | |||
b8e0100bdf | |||
137db42446
|
|||
956d2009eb | |||
ec66da8b5e | |||
0555ee0db7
|
|||
837b487281
|
|||
9a0f2c062c
|
|||
![]() |
6e9c69c2a8 | ||
f0cef81b5e | |||
d8160effd0
|
|||
18da07763c
|
|||
3c448f2290
|
|||
cadc7e223f | |||
e1baca7940 | |||
c2e0cf65a8 | |||
a3d0408d6f | |||
9ca6931bb8 | |||
f22eff1f72 | |||
11e097d696 | |||
f7ecb45774 | |||
00a7328e3a | |||
c39229a28b | |||
6d5ed42e60 |
File diff suppressed because it is too large
Load Diff
3
Glamourer.Api/.gitignore
vendored
3
Glamourer.Api/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
bin/
|
||||
obj/
|
||||
.vs/
|
@@ -1,14 +0,0 @@
|
||||
namespace Glamourer.Api.Api;
|
||||
|
||||
/// <summary> The full API available. </summary>
|
||||
public interface IGlamourerApi : IGlamourerApiBase
|
||||
{
|
||||
/// <inheritdoc cref="IGlamourerApiDesigns"/>
|
||||
public IGlamourerApiDesigns Designs { get; }
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiItems"/>
|
||||
public IGlamourerApiItems Items { get; }
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState"/>
|
||||
public IGlamourerApiState State { get; }
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
namespace Glamourer.Api.Api;
|
||||
|
||||
/// <summary> Basic API functions. </summary>
|
||||
public interface IGlamourerApiBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the current API version of the Glamourer available in this installation.
|
||||
/// Major version changes indicate incompatibilities, minor version changes are backward-compatible additions.
|
||||
/// </summary>
|
||||
public (int Major, int Minor) ApiVersion { get; }
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
using Glamourer.Api.Enums;
|
||||
|
||||
namespace Glamourer.Api.Api;
|
||||
|
||||
/// <summary> All functions related to Glamourer designs. </summary>
|
||||
public interface IGlamourerApiDesigns
|
||||
{
|
||||
/// <summary> Obtain a list of all available designs. </summary>
|
||||
/// <returns> A dictionary of all designs from their GUID to their current display name. </returns>
|
||||
public Dictionary<Guid, string> GetDesignList();
|
||||
|
||||
/// <summary> Apply an existing design to an actor. </summary>
|
||||
/// <param name="designId"> The GUID of the design to apply. </param>
|
||||
/// <param name="objectIndex"> The game object index of the actor to be manipulated. </param>
|
||||
/// <param name="key"> A key to unlock or lock the state if necessary. </param>
|
||||
/// <param name="flags"> The flags used for the reversion. Respects Once, Equipment, Customization, Lock (see <see cref="ApplyFlag"/>.)</param>
|
||||
/// <returns> DesignNotFound, ActorNotFound, InvalidKey, Success. </returns>
|
||||
public GlamourerApiEc ApplyDesign(Guid designId, int objectIndex, uint key, ApplyFlag flags);
|
||||
|
||||
/// <summary> Apply an existing design to an actor. </summary>
|
||||
/// <param name="designId"> The GUID of the design to apply. </param>
|
||||
/// <param name="playerName"> The name of the players to be manipulated. </param>
|
||||
/// <param name="key"> A key to unlock or lock the state if necessary. </param>
|
||||
/// <param name="flags"> The flags used for the reversion. Respects Once, Equipment, Customization, Lock (see <see cref="ApplyFlag"/>.)</param>
|
||||
/// <returns> DesignNotFound, ActorNotFound, InvalidKey, Success. </returns>
|
||||
/// /// <remarks>
|
||||
/// The player does not have to be currently available as long as he has a persisted Glamourer state.<br/>
|
||||
/// Only players are checked for name equality, no NPCs.<br/>
|
||||
/// If multiple players of the same name are found, all of them are reverted.<br/>
|
||||
/// Prefer to use the index-based function unless you need to get the state of someone currently unavailable.
|
||||
/// </remarks>
|
||||
public GlamourerApiEc ApplyDesignName(Guid designId, string playerName, uint key, ApplyFlag flags);
|
||||
}
|
@@ -1,80 +0,0 @@
|
||||
using Glamourer.Api.Enums;
|
||||
|
||||
namespace Glamourer.Api.Api;
|
||||
|
||||
/// <summary> All functions related to items. </summary>
|
||||
public interface IGlamourerApiItems
|
||||
{
|
||||
/// <summary> Set a single item on an actor. </summary>
|
||||
/// <param name="objectIndex"> The game object index of the actor to be manipulated. </param>
|
||||
/// <param name="slot"> The slot to apply the item to. </param>
|
||||
/// <param name="itemId"> The (Custom) ID of the item to apply. </param>
|
||||
/// <param name="stains"> The IDs of the stains to apply to the item. </param>
|
||||
/// <param name="key"> A key to unlock or lock the state if necessary. </param>
|
||||
/// <param name="flags"> The flags used for the reversion. Respects Once (see <see cref="ApplyFlag"/>.)</param>
|
||||
/// <returns> ItemInvalid, ActorNotFound, ActorNotHuman, InvalidKey, Success. </returns>
|
||||
/// <remarks> The item ID can be a custom item ID in Glamourer's format for models without an associated item, or a normal game item ID. </remarks>
|
||||
public GlamourerApiEc SetItem(int objectIndex, ApiEquipSlot slot, ulong itemId, IReadOnlyList<byte> stains, uint key, ApplyFlag flags);
|
||||
|
||||
/// <summary> Set a single item on players. </summary>
|
||||
/// <param name="playerName"> The name of the players to be manipulated. </param>
|
||||
/// <param name="slot"> The slot to apply the item to. </param>
|
||||
/// <param name="itemId"> The (Custom) ID of the item to apply. </param>
|
||||
/// <param name="stains"> The IDs of the stains to apply to the item. </param>
|
||||
/// <param name="key"> A key to unlock or lock the state if necessary. </param>
|
||||
/// <param name="flags"> The flags used for the reversion. Respects Once (see <see cref="ApplyFlag"/>.)</param>
|
||||
/// <returns> ItemInvalid, ActorNotFound, ActorNotHuman, InvalidKey, Success. </returns>
|
||||
/// <remarks>
|
||||
/// The item ID can be a custom item ID in Glamourer's format for models without an associated item, or a normal game item ID.<br/>
|
||||
/// The player does not have to be currently available as long as he has a persisted Glamourer state.<br/>
|
||||
/// Only players are checked for name equality, no NPCs.<br/>
|
||||
/// If multiple players of the same name are found, all of them are modified.<br/>
|
||||
/// Prefer to use the index-based function unless you need to get the state of someone currently unavailable.
|
||||
/// </remarks>
|
||||
public GlamourerApiEc SetItemName(string playerName, ApiEquipSlot slot, ulong itemId, IReadOnlyList<byte> stains, uint key,
|
||||
ApplyFlag flags);
|
||||
|
||||
/// <summary> Set a single bonus item on an actor. </summary>
|
||||
/// <param name="objectIndex"> The game object index of the actor to be manipulated. </param>
|
||||
/// <param name="slot"> The bonus slot to apply the item to. </param>
|
||||
/// <param name="bonusItemId"> The bonus item sheet ID of the item to apply (including stain). </param>
|
||||
/// <param name="key"> A key to unlock or lock the state if necessary. </param>
|
||||
/// <param name="flags"> The flags used for the reversion. Respects Once (see <see cref="ApplyFlag"/>.)</param>
|
||||
/// <returns> ItemInvalid, ActorNotFound, ActorNotHuman, InvalidKey, Success. </returns>
|
||||
/// <remarks> The bonus item ID can currently not be a custom item ID in Glamourer's format for models without an associated item. Use 0 to remove the bonus item. </remarks>
|
||||
public GlamourerApiEc SetBonusItem(int objectIndex, ApiBonusSlot slot, ulong bonusItemId, uint key, ApplyFlag flags);
|
||||
|
||||
/// <summary> Set a single bonus item on an actor. </summary>
|
||||
/// <param name="playerName"> The game object index of the actor to be manipulated. </param>
|
||||
/// <param name="slot"> The bonus slot to apply the item to. </param>
|
||||
/// <param name="bonusItemId"> The bonus item sheet ID of the item to apply (including stain). </param>
|
||||
/// <param name="key"> A key to unlock or lock the state if necessary. </param>
|
||||
/// <param name="flags"> The flags used for the reversion. Respects Once (see <see cref="ApplyFlag"/>.)</param>
|
||||
/// <returns> ItemInvalid, ActorNotFound, ActorNotHuman, InvalidKey, Success. </returns>
|
||||
/// <remarks>
|
||||
/// The bonus item ID can currently not be a custom item ID in Glamourer's format for models without an associated item. Use 0 to remove the bonus item. <br/>
|
||||
/// The player does not have to be currently available as long as he has a persisted Glamourer state.<br/>
|
||||
/// Only players are checked for name equality, no NPCs.<br/>
|
||||
/// If multiple players of the same name are found, all of them are modified.<br/>
|
||||
/// Prefer to use the index-based function unless you need to get the state of someone currently unavailable.
|
||||
/// </remarks>
|
||||
public GlamourerApiEc SetBonusItemName(string playerName, ApiBonusSlot slot, ulong bonusItemId, uint key, ApplyFlag flags);
|
||||
|
||||
/// <summary> Set the defined Meta State flags to the active or inactive state on actor. </summary>
|
||||
/// <param name="objectIndex"> The game object index of the actor to be manipulated. </param>
|
||||
/// <param name="types"> The flags defining which meta states to update to the new value. This can be multiple at once. </param>
|
||||
/// <param name="newValue"> The new value to update to. </param>
|
||||
/// <param name="key"> A key to unlock or lock the state if necessary. </param>
|
||||
/// <param name="flags"> The flags used for the reversion. Respects Once (see <see cref="ApplyFlag.Once"/>.)</param>
|
||||
/// <returns> ItemInvalid, ActorNotFound, ActorNotHuman, InvalidKey, Success. </returns>
|
||||
public GlamourerApiEc SetMetaState(int objectIndex, MetaFlag types, bool newValue, uint key, ApplyFlag flags);
|
||||
|
||||
/// <summary> Set the defined Meta State flags to the active or inactive state on actor (by name) </summary>
|
||||
/// <param name="playerName"> The name of the players to be manipulated. </param>
|
||||
/// <param name="types"> The flags defining which meta states to update to the new value. This can be multiple at once. </param>
|
||||
/// <param name="newValue"> The new value to update to. </param>
|
||||
/// <param name="key"> A key to unlock or lock the state if necessary. </param>
|
||||
/// <param name="flags"> The flags used for the reversion. Respects Once (see <see cref="ApplyFlag.Once"/>.)</param>
|
||||
/// <returns> ItemInvalid, ActorNotFound, ActorNotHuman, InvalidKey, Success. </returns>
|
||||
public GlamourerApiEc SetMetaStateName(string playerName, MetaFlag types, bool newValue, uint key, ApplyFlag flags);
|
||||
}
|
@@ -1,124 +0,0 @@
|
||||
using Glamourer.Api.Enums;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Glamourer.Api.Api;
|
||||
|
||||
/// <summary> Any functions related to Glamourer's state tracking. </summary>
|
||||
public interface IGlamourerApiState
|
||||
{
|
||||
/// <summary> Get the current Glamourer state of an actor. </summary>
|
||||
/// <param name="objectIndex"> The game object index of the desired actor. </param>
|
||||
/// <param name="key"> A key to unlock the state if necessary. </param>
|
||||
/// <returns> ActorNotFound, InvalidKey or Success, and the state on success. </returns>
|
||||
/// <remarks> The actor does not need to have a prior Glamourer state as long as it can be found. </remarks>
|
||||
public (GlamourerApiEc, JObject?) GetState(int objectIndex, uint key);
|
||||
|
||||
/// <summary> Get the current Glamourer state of a player character. </summary>
|
||||
/// <param name="playerName"> The name of the desired player. </param>
|
||||
/// <param name="key"> A key to unlock the state if necessary. </param>
|
||||
/// <returns> ActorNotFound, InvalidKey or Success, and the state on success. </returns>
|
||||
/// <remarks>
|
||||
/// The player does not have to be currently available as long as he has a persisted Glamourer state.
|
||||
/// Only players are checked for name equality, no NPCs.
|
||||
/// If multiple players of the same name are found, the first is returned.
|
||||
/// Prefer to use the index-based function unless you need to get the state of someone currently unavailable.
|
||||
/// </remarks>
|
||||
public (GlamourerApiEc, JObject?) GetStateName(string playerName, uint key);
|
||||
|
||||
/// <inheritdoc cref="GetState"/>
|
||||
public (GlamourerApiEc, string?) GetStateBase64(int objectIndex, uint key);
|
||||
|
||||
/// <inheritdoc cref="GetStateName"/>
|
||||
public (GlamourerApiEc, string?) GetStateBase64Name(string objectName, uint key);
|
||||
|
||||
/// <summary> Apply a supplied state to an actor. </summary>
|
||||
/// <param name="applyState"> The state, which can be either a Glamourer-supplied JObject or a Base64 string. </param>
|
||||
/// <param name="objectIndex"> The game object index of the actor to be manipulated. </param>
|
||||
/// <param name="key"> A key to unlock or lock the state if necessary. </param>
|
||||
/// <param name="flags"> The flags used for the application. Respects Once, Equipment, Customization and Lock (see <see cref="ApplyFlag"/>.) </param>
|
||||
/// <returns> ActorNotFound, InvalidKey, ActorNotHuman, Success. </returns>
|
||||
public GlamourerApiEc ApplyState(object applyState, int objectIndex, uint key, ApplyFlag flags);
|
||||
|
||||
/// <summary> Apply a supplied state to players. </summary>
|
||||
/// <param name="applyState"> The state, which can be either a Glamourer-supplied JObject or a Base64 string. </param>
|
||||
/// <param name="playerName"> The name of the player to be manipulated. </param>
|
||||
/// <param name="key"> A key to unlock or lock the state if necessary. </param>
|
||||
/// <param name="flags"> The flags used for the application. Respects Once, Equipment, Customization and Lock (see <see cref="ApplyFlag"/>.) </param>
|
||||
/// <returns> ActorNotFound, InvalidKey, ActorNotHuman, Success. </returns>
|
||||
/// <remarks>
|
||||
/// The player does not have to be currently available as long as he has a persisted Glamourer state.<br/>
|
||||
/// Only players are checked for name equality, no NPCs.<br/>
|
||||
/// If multiple players of the same name are found, all of them are manipulated.<br/>
|
||||
/// Prefer to use the index-based function unless you need to get the state of someone currently unavailable.
|
||||
/// </remarks>
|
||||
public GlamourerApiEc ApplyStateName(object applyState, string playerName, uint key, ApplyFlag flags);
|
||||
|
||||
/// <summary> Revert the Glamourer state of an actor to Game state. </summary>
|
||||
/// <param name="objectIndex"> The game object index of the actor to be manipulated. </param>
|
||||
/// <param name="key"> A key to unlock the state if necessary. </param>
|
||||
/// <param name="flags"> The flags used for the reversion. Respects Equipment and Customization (see <see cref="ApplyFlag"/>.) </param>
|
||||
/// <returns> ActorNotFound, InvalidKey, Success, NothingDone. </returns>
|
||||
public GlamourerApiEc RevertState(int objectIndex, uint key, ApplyFlag flags);
|
||||
|
||||
/// <summary> Revert the Glamourer state of players to game state. </summary>
|
||||
/// <param name="playerName"> The name of the players to be reverted. </param>
|
||||
/// <param name="key"> A key to unlock the state if necessary. </param>
|
||||
/// <param name="flags"> The flags used for the reversion. Respects Equipment and Customization (see <see cref="ApplyFlag"/>.) </param>
|
||||
/// <returns> ActorNotFound, InvalidKey, Success, NothingDone. </returns>
|
||||
/// /// <remarks>
|
||||
/// The player does not have to be currently available as long as he has a persisted Glamourer state.<br/>
|
||||
/// Only players are checked for name equality, no NPCs.<br/>
|
||||
/// If multiple players of the same name are found, all of them are reverted.<br/>
|
||||
/// Prefer to use the index-based function unless you need to get the state of someone currently unavailable.
|
||||
/// </remarks>
|
||||
public GlamourerApiEc RevertStateName(string playerName, uint key, ApplyFlag flags);
|
||||
|
||||
/// <summary> Unlock the Glamourer state of an actor with a key. </summary>
|
||||
/// <param name="objectIndex"> The game object index of the actor to be manipulated. </param>
|
||||
/// <param name="key"> A key to unlock the state. </param>
|
||||
/// <returns> ActorNotFound, InvalidKey, Success, NothingDone. </returns>
|
||||
public GlamourerApiEc UnlockState(int objectIndex, uint key);
|
||||
|
||||
/// <summary> Unlock the Glamourer state of players with a key. </summary>
|
||||
/// <param name="playerName"> The name of the players to be unlocked. </param>
|
||||
/// <param name="key"> A key to unlock the state. </param>
|
||||
/// <returns> InvalidKey, Success, NothingDone. </returns>
|
||||
public GlamourerApiEc UnlockStateName(string playerName, uint key);
|
||||
|
||||
/// <summary> Unlock all active glamourer states with a key. </summary>
|
||||
/// <param name="key"> The key to unlock states with. </param>
|
||||
/// <returns> The number of unlocked states. </returns>
|
||||
public int UnlockAll(uint key);
|
||||
|
||||
/// <summary> Revert the Glamourer state of an actor to automation state. </summary>
|
||||
/// <param name="objectIndex"> The game object index of the actor to be manipulated. </param>
|
||||
/// <param name="key"> A key to unlock the state if necessary. </param>
|
||||
/// <param name="flags"> The flags used for the reversion. Respects Once and Lock (see <see cref="ApplyFlag"/>.) </param>
|
||||
/// <returns> ActorNotFound, InvalidKey, Success, NothingDone. </returns>
|
||||
public GlamourerApiEc RevertToAutomation(int objectIndex, uint key, ApplyFlag flags);
|
||||
|
||||
/// <summary> Revert the Glamourer state of players to automation state. </summary>
|
||||
/// <param name="playerName"> The name of the players to be reverted. </param>
|
||||
/// <param name="key"> A key to unlock the state if necessary. </param>
|
||||
/// <param name="flags"> The flags used for the reversion. Respects Once and Lock (see <see cref="ApplyFlag"/>.) </param>
|
||||
/// <returns> ActorNotFound, InvalidKey, Success, NothingDone. </returns>
|
||||
/// /// <remarks>
|
||||
/// The player does not have to be currently available as long as he has a persisted Glamourer state.<br/>
|
||||
/// Only players are checked for name equality, no NPCs.<br/>
|
||||
/// If multiple players of the same name are found, all of them are reverted.<br/>
|
||||
/// Prefer to use the index-based function unless you need to get the state of someone currently unavailable.
|
||||
/// </remarks>
|
||||
public GlamourerApiEc RevertToAutomationName(string playerName, uint key, ApplyFlag flags);
|
||||
|
||||
/// <summary> Invoked with the game object pointer (if available) whenever an actors tracked state changes. </summary>
|
||||
public event Action<nint> StateChanged;
|
||||
|
||||
/// <summary> Invoked with the game object pointer (if available) whenever an actors tracked state changes, with the type of change. </summary>
|
||||
public event Action<nint, StateChangeType> StateChangedWithType;
|
||||
|
||||
/// <summary> Invoked with the game object pointer (if available) whenever an actors tracked state finalizes a grouped change consisting of multiple smaller changes. </summary>
|
||||
public event Action<nint, StateFinalizationType> StateFinalized;
|
||||
|
||||
/// <summary> Invoked when the player enters or leaves GPose (true => entered GPose, false => left GPose). </summary>
|
||||
public event Action<bool>? GPoseChanged;
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
namespace Glamourer.Api.Enums;
|
||||
|
||||
/// <summary> Bonus item slots restricted to API-relevant slots. </summary>
|
||||
public enum ApiBonusSlot : byte
|
||||
{
|
||||
/// <summary> No slot. </summary>
|
||||
Unknown = 0,
|
||||
|
||||
/// <summary> The Glasses slot. </summary>
|
||||
Glasses = 1,
|
||||
}
|
@@ -1,45 +0,0 @@
|
||||
namespace Glamourer.Api.Enums;
|
||||
|
||||
/// <summary> Equip slots restricted to API-relevant slots, but compatible with GameData.EquipSlots. </summary>
|
||||
public enum ApiEquipSlot : byte
|
||||
{
|
||||
/// <summary> No slot. </summary>
|
||||
Unknown = 0,
|
||||
|
||||
/// <summary> Mainhand, also used for both-handed weapons. </summary>
|
||||
MainHand = 1,
|
||||
|
||||
/// <summary> Offhand, used for shields or if you want to apply the offhand component of certain weapons. </summary>
|
||||
OffHand = 2,
|
||||
|
||||
/// <summary> Head. </summary>
|
||||
Head = 3,
|
||||
|
||||
/// <summary> Body. </summary>
|
||||
Body = 4,
|
||||
|
||||
/// <summary> Hands. </summary>
|
||||
Hands = 5,
|
||||
|
||||
/// <summary> Legs. </summary>
|
||||
Legs = 7,
|
||||
|
||||
/// <summary> Feet. </summary>
|
||||
Feet = 8,
|
||||
|
||||
/// <summary> Ears. </summary>
|
||||
Ears = 9,
|
||||
|
||||
/// <summary> Neck. </summary>
|
||||
Neck = 10,
|
||||
|
||||
/// <summary> Wrists. </summary>
|
||||
Wrists = 11,
|
||||
|
||||
/// <summary> Right Finger. </summary>
|
||||
RFinger = 12,
|
||||
|
||||
/// <summary> Left Finger. </summary>
|
||||
/// <remarks> Not officially existing, means "weapon could be equipped in either hand" for the game. </remarks>
|
||||
LFinger = 14,
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
namespace Glamourer.Api.Enums;
|
||||
|
||||
/// <summary> Application flags that can be used in different situations. </summary>
|
||||
[Flags]
|
||||
public enum ApplyFlag : ulong
|
||||
{
|
||||
/// <summary> Apply the selected manipulation only once, without forcing the state into automation. </summary>
|
||||
Once = 0x01,
|
||||
|
||||
/// <summary> Apply the selected manipulation on the equipment (might be more or less supported). </summary>
|
||||
Equipment = 0x02,
|
||||
|
||||
/// <summary> Apply the selected manipulation on the customizations (might be more or less supported). </summary>
|
||||
Customization = 0x04,
|
||||
|
||||
/// <summary> Lock the state with the given key after applying the selected manipulation </summary>
|
||||
Lock = 0x08,
|
||||
}
|
||||
|
||||
/// <summary> Extensions for apply flags. </summary>
|
||||
public static class ApplyFlagEx
|
||||
{
|
||||
/// <summary> The default application flags for design-based manipulations. </summary>
|
||||
public const ApplyFlag DesignDefault = ApplyFlag.Once | ApplyFlag.Equipment | ApplyFlag.Customization;
|
||||
|
||||
/// <summary> The default application flags for state-based manipulations. </summary>
|
||||
public const ApplyFlag StateDefault = ApplyFlag.Equipment | ApplyFlag.Customization | ApplyFlag.Lock;
|
||||
|
||||
/// <summary> The default application flags for reverse manipulations. </summary>
|
||||
public const ApplyFlag RevertDefault = ApplyFlag.Equipment | ApplyFlag.Customization;
|
||||
}
|
@@ -1,29 +0,0 @@
|
||||
namespace Glamourer.Api.Enums;
|
||||
|
||||
/// <summary> Return codes for API functions. </summary>
|
||||
public enum GlamourerApiEc
|
||||
{
|
||||
/// <summary> The function succeeded. </summary>
|
||||
Success = 0,
|
||||
|
||||
/// <summary> The function did not encounter a problem, but also did not do anything. </summary>
|
||||
NothingDone = 1,
|
||||
|
||||
/// <summary> The requested actor was not found. </summary>
|
||||
ActorNotFound = 2,
|
||||
|
||||
/// <summary> The requested actor was not human, but should have been. </summary>
|
||||
ActorNotHuman,
|
||||
|
||||
/// <summary> The requested design was not found. </summary>
|
||||
DesignNotFound,
|
||||
|
||||
/// <summary> The requested item was not found or could not be applied to the requested slot. </summary>
|
||||
ItemInvalid,
|
||||
|
||||
/// <summary> The state of an actor could not be manipulated because it was locked and the provided key could not unlock it. </summary>
|
||||
InvalidKey,
|
||||
|
||||
/// <summary> The provided object could not be converted into a valid Glamourer state to apply. </summary>
|
||||
InvalidState,
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
namespace Glamourer.Api.Enums;
|
||||
|
||||
/// <summary> Application flags for setting the meta state of an actor. </summary>
|
||||
[Flags]
|
||||
public enum MetaFlag : ulong
|
||||
{
|
||||
Wetness = 0x01,
|
||||
HatState = 0x02,
|
||||
VisorState = 0x04,
|
||||
WeaponState = 0x08,
|
||||
}
|
@@ -1,47 +0,0 @@
|
||||
namespace Glamourer.Api.Enums;
|
||||
|
||||
/// <summary> What type of information changed in a state. </summary>
|
||||
public enum StateChangeType
|
||||
{
|
||||
/// <summary> A characters saved state had the model id changed. This means everything may have changed. </summary>
|
||||
Model = 0,
|
||||
|
||||
/// <summary> A characters saved state had multiple customization values changed. </summary>
|
||||
EntireCustomize = 1,
|
||||
|
||||
/// <summary> A characters saved state had a customization value changed. </summary>
|
||||
Customize = 2,
|
||||
|
||||
/// <summary> A characters saved state had an equipment piece changed. </summary>
|
||||
Equip = 3,
|
||||
|
||||
/// <summary> A characters saved state had its weapons changed. </summary>
|
||||
Weapon = 4,
|
||||
|
||||
/// <summary> A characters saved state had a stain changed. </summary>
|
||||
Stains = 5,
|
||||
|
||||
/// <summary> A characters saved state had a crest visibility changed. </summary>
|
||||
Crest = 6,
|
||||
|
||||
/// <summary> A characters saved state had its customize parameter changed. </summary>
|
||||
Parameter = 7,
|
||||
|
||||
/// <summary> A characters saved state had a material color table value changed. </summary>
|
||||
MaterialValue = 8,
|
||||
|
||||
/// <summary> A characters saved state had a design applied. This means everything may have changed. </summary>
|
||||
Design = 9,
|
||||
|
||||
/// <summary> A characters saved state had its state reset to its game values. </summary>
|
||||
Reset = 10,
|
||||
|
||||
/// <summary> A characters saved state had a meta toggle changed. </summary>
|
||||
Other = 11,
|
||||
|
||||
/// <summary> A characters state was reapplied. Data is null. </summary>
|
||||
Reapply = 12,
|
||||
|
||||
/// <summary> A characters saved state had a bonus item changed. </summary>
|
||||
BonusItem = 13,
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
namespace Glamourer.Api.Enums;
|
||||
|
||||
/// <summary> What type of Glamourer process was performed on the actors state to update it. </summary>
|
||||
public enum StateFinalizationType
|
||||
{
|
||||
/// <summary> A characters saved state had the model id altered. </summary>
|
||||
ModelChange = 0,
|
||||
|
||||
/// <summary> A singular Design was applied to an actors state. </summary>
|
||||
DesignApplied = 1,
|
||||
|
||||
/// <summary> A characters saved state had been reset to game values. </summary>
|
||||
Revert = 2,
|
||||
|
||||
/// <summary> A characters saved state had only its customization data reset to game state. </summary>
|
||||
RevertCustomize = 3,
|
||||
|
||||
/// <summary> A characters saved state had only its equipment data reset to game state. </summary>
|
||||
RevertEquipment = 4,
|
||||
|
||||
/// <summary> A characters saved state had its advanced values reverted to game state. </summary>
|
||||
RevertAdvanced = 5,
|
||||
|
||||
/// <summary> A characters saved state was reverted to automation state on top of their game state </summary>
|
||||
RevertAutomation = 6,
|
||||
|
||||
/// <summary> A characters saved state had a generic reapply as a single operation. </summary>
|
||||
Reapply = 7,
|
||||
|
||||
/// <summary> A characters saved state had their automation state reapplied over their existing state. </summary>
|
||||
ReapplyAutomation = 8,
|
||||
|
||||
/// <summary> A characters save state finished applying all updated slots for game state on gearset change or initial load. </summary>
|
||||
Gearset = 9,
|
||||
}
|
||||
|
@@ -1,34 +0,0 @@
|
||||
<Project Sdk="Dalamud.NET.Sdk/13.0.0">
|
||||
<PropertyGroup>
|
||||
<AssemblyTitle>Glamourer.Api</AssemblyTitle>
|
||||
<Product>Glamourer</Product>
|
||||
<Copyright>Copyright © 2025</Copyright>
|
||||
<FileVersion>2.4.1.0</FileVersion>
|
||||
<AssemblyVersion>2.4.1.0</AssemblyVersion>
|
||||
<PackageVersion>2.4.1</PackageVersion>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<Title>Glamourer.Api</Title>
|
||||
<Authors>Ottermandias</Authors>
|
||||
<RepositoryUrl>https://github.com/Ottermandias/Glamourer</RepositoryUrl>
|
||||
<Description>Auxiliary functions for Glamourers external API.</Description>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<Use_DalamudPackager>false</Use_DalamudPackager>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<NoWarn>1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="README.md" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@@ -1,2 +0,0 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=ipc/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
@@ -1,4 +0,0 @@
|
||||
// Global using directives
|
||||
|
||||
global using System;
|
||||
global using System.Collections.Generic;
|
@@ -1,114 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
|
||||
namespace Glamourer.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized subscriber only allowing to invoke actions.
|
||||
/// </summary>
|
||||
public class ActionSubscriber
|
||||
{
|
||||
private readonly ICallGateSubscriber<object?>? _subscriber;
|
||||
|
||||
/// <summary> Whether the subscriber could successfully be created. </summary>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
protected ActionSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Invoke the action. See the source of the subscriber for details.</summary>
|
||||
protected void Invoke()
|
||||
=> _subscriber?.InvokeAction();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber"/>
|
||||
public class ActionSubscriber<T1>
|
||||
{
|
||||
private readonly ICallGateSubscriber<T1, object?>? _subscriber;
|
||||
|
||||
/// <summary> Whether the subscriber could successfully be created. </summary>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
protected ActionSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Invoke the action. See the source of the subscriber for details.</summary>
|
||||
protected void Invoke(T1 a)
|
||||
=> _subscriber?.InvokeAction(a);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber"/>
|
||||
public class ActionSubscriber<T1, T2>
|
||||
{
|
||||
private readonly ICallGateSubscriber<T1, T2, object?>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber{T1}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
protected ActionSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber.Invoke"/>
|
||||
protected void Invoke(T1 a, T2 b)
|
||||
=> _subscriber?.InvokeAction(a, b);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber"/>
|
||||
public class ActionSubscriber<T1, T2, T3>
|
||||
{
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, object?>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber{T1}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
protected ActionSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber.Invoke"/>
|
||||
protected void Invoke(T1 a, T2 b, T3 c)
|
||||
=> _subscriber?.InvokeAction(a, b, c);
|
||||
}
|
@@ -1,234 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
||||
namespace Glamourer.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized disposable Provider for Events.<para />
|
||||
/// Will execute the unsubscriber action on dispose if any is provided.<para />
|
||||
/// Can only be invoked and disposed.
|
||||
/// </summary>
|
||||
public sealed class EventProvider : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, (Action<Action> Add, Action<Action> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider> add, Action<EventProvider> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Invoke the event.</summary>
|
||||
public void Invoke()
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider"/>
|
||||
public sealed class EventProvider<T1> : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<T1, object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, (Action<Action<T1>> Add, Action<Action<T1>> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider<T1>> add, Action<EventProvider<T1>> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider.Invoke"/>
|
||||
public void Invoke(T1 a)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage(a);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action<T1>> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider<T1>> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider"/>
|
||||
public sealed class EventProvider<T1, T2> : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<T1, T2, object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, (Action<Action<T1, T2>> Add, Action<Action<T1, T2>> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider<T1, T2>> add, Action<EventProvider<T1, T2>> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider.Invoke"/>
|
||||
public void Invoke(T1 a, T2 b)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage(a, b);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action<T1, T2>> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider<T1, T2>> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
@@ -1,394 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
||||
namespace Glamourer.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized disposable Subscriber for Events.<para />
|
||||
/// Subscriptions are wrapped to be individually exception-safe.<para/>
|
||||
/// Can be enabled and disabled.<para/>
|
||||
/// </summary>
|
||||
public sealed class EventSubscriber : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action, Action> _delegates = new();
|
||||
private ICallGateSubscriber<object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable all currently subscribed actions registered with this EventSubscriber.
|
||||
/// Does nothing if it is already enabled.
|
||||
/// </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disable all subscribed actions registered with this EventSubscriber.
|
||||
/// Does nothing if it is already disabled.
|
||||
/// Does not forget the actions, only disables them.
|
||||
/// </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add or remove an action to the IPC event, if it is valid.
|
||||
/// </summary>
|
||||
public event Action Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action()
|
||||
{
|
||||
try
|
||||
{
|
||||
value();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber"/> </summary>
|
||||
public sealed class EventSubscriber<T1> : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action<T1>, Action<T1>> _delegates = new();
|
||||
private ICallGateSubscriber<T1, object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action<T1>[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Enable"/> </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Disable"/> </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Event"/> </summary>
|
||||
public event Action<T1> Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action(T1 a)
|
||||
{
|
||||
try
|
||||
{
|
||||
value(a);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber"/> </summary>
|
||||
public sealed class EventSubscriber<T1, T2> : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action<T1, T2>, Action<T1, T2>> _delegates = new();
|
||||
private ICallGateSubscriber<T1, T2, object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action<T1, T2>[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Enable"/> </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Disable"/> </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Event"/> </summary>
|
||||
public event Action<T1, T2> Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action(T1 a, T2 b)
|
||||
{
|
||||
try
|
||||
{
|
||||
value(a, b);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber"/> </summary>
|
||||
public sealed class EventSubscriber<T1, T2, T3> : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action<T1, T2, T3>, Action<T1, T2, T3>> _delegates = new();
|
||||
private ICallGateSubscriber<T1, T2, T3, object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action<T1, T2, T3>[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Enable"/> </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Disable"/> </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Event"/> </summary>
|
||||
public event Action<T1, T2, T3> Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action(T1 a, T2 b, T3 c)
|
||||
{
|
||||
try
|
||||
{
|
||||
value(a, b, c);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
@@ -1,224 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
|
||||
namespace Glamourer.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized disposable Provider for Funcs.
|
||||
/// </summary>
|
||||
public sealed class FuncProvider<TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, T3, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, T3, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, T3, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, T3, T4, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, T3, T4, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, T3, T4, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, T3, T4, T5, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, T3, T4, T5, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, T3, T4, T5, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, T5, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, T3, T4, T5, T6, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, T3, T4, T5, T6, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, T3, T4, T5, T6, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, T5, T6, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
@@ -1,217 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
using Dalamud.Plugin.Ipc.Exceptions;
|
||||
|
||||
namespace Glamourer.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized subscriber only allowing to invoke functions with a return.
|
||||
/// </summary>
|
||||
public class FuncSubscriber<TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<TRet>? _subscriber;
|
||||
|
||||
/// <summary> Whether the subscriber could successfully be created. </summary>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Invoke the function. See the source of the subscriber for details.</summary>
|
||||
protected TRet Invoke()
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc() : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, T3, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b, T3 c)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b, c) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, T3, T4, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, T4, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, T4, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b, T3 c, T4 d)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b, c, d) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, T3, T4, T5, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, T4, T5, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, T4, T5, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b, T3 c, T4 d, T5 e)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b, c, d, e) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, T3, T4, T5, T6, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, T4, T5, T6, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, T4, T5, T6, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b, c, d, e, f) : throw new IpcNotReadyError(_label);
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
||||
namespace Glamourer.Api.Helpers;
|
||||
|
||||
internal class PluginLogHelper
|
||||
{
|
||||
[PluginService]
|
||||
private static IPluginLog? _log { get; set; }
|
||||
|
||||
private PluginLogHelper(IDalamudPluginInterface pi)
|
||||
=> pi.Inject(this);
|
||||
|
||||
public static void WriteError(IDalamudPluginInterface pi, string errorMessage)
|
||||
=> GetLog(pi).Error(errorMessage);
|
||||
|
||||
public static IPluginLog GetLog(IDalamudPluginInterface pi)
|
||||
{
|
||||
if (_log != null)
|
||||
return _log;
|
||||
|
||||
_ = new PluginLogHelper(pi);
|
||||
return _log!;
|
||||
}
|
||||
}
|
@@ -1,52 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Glamourer.Api.Api;
|
||||
using Glamourer.Api.Enums;
|
||||
using Glamourer.Api.Helpers;
|
||||
|
||||
namespace Glamourer.Api.IpcSubscribers;
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiDesigns.GetDesignList"/>
|
||||
public sealed class GetDesignList(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<Dictionary<Guid, string>>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(GetDesignList)}.V2";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiDesigns.GetDesignList"/>
|
||||
public new Dictionary<Guid, string> Invoke()
|
||||
=> base.Invoke();
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<Dictionary<Guid, string>> Provider(IDalamudPluginInterface pi, IGlamourerApiDesigns api)
|
||||
=> new(pi, Label, api.GetDesignList);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiDesigns.ApplyDesign"/>
|
||||
public sealed class ApplyDesign(IDalamudPluginInterface pi) : FuncSubscriber<Guid, int, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(ApplyDesign)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiDesigns.ApplyDesign"/>
|
||||
public GlamourerApiEc Invoke(Guid designId, int objectIndex, uint key = 0, ApplyFlag flags = ApplyFlagEx.DesignDefault)
|
||||
=> (GlamourerApiEc)Invoke(designId, objectIndex, key, (ulong)flags);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<Guid, int, uint, ulong, int> Provider(IDalamudPluginInterface pi, IGlamourerApiDesigns api)
|
||||
=> new(pi, Label, (a, b, c, d) => (int)api.ApplyDesign(a, b, c, (ApplyFlag)d));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiDesigns.ApplyDesignName"/>
|
||||
public sealed class ApplyDesignName(IDalamudPluginInterface pi) : FuncSubscriber<Guid, string, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(ApplyDesignName)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiDesigns.ApplyDesignName"/>
|
||||
public GlamourerApiEc Invoke(Guid designId, string objectName, uint key = 0, ApplyFlag flags = ApplyFlagEx.DesignDefault)
|
||||
=> (GlamourerApiEc)Invoke(designId, objectName, key, (ulong)flags);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<Guid, string, uint, ulong, int> Provider(IDalamudPluginInterface pi, IGlamourerApiDesigns api)
|
||||
=> new(pi, Label, (a, b, c, d) => (int)api.ApplyDesignName(a, b, c, (ApplyFlag)d));
|
||||
}
|
@@ -1,110 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Glamourer.Api.Api;
|
||||
using Glamourer.Api.Enums;
|
||||
using Glamourer.Api.Helpers;
|
||||
|
||||
namespace Glamourer.Api.IpcSubscribers;
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiItems.SetItem"/>
|
||||
public sealed class SetItem(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, byte, ulong, IReadOnlyList<byte>, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(SetItem)}.V3";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiItems.SetItem"/>
|
||||
public GlamourerApiEc Invoke(int objectIndex, ApiEquipSlot slot, ulong itemId, IReadOnlyList<byte> stain, uint key = 0,
|
||||
ApplyFlag flags = ApplyFlag.Once)
|
||||
=> (GlamourerApiEc)Invoke(objectIndex, (byte)slot, itemId, stain, key, (ulong)flags);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<int, byte, ulong, IReadOnlyList<byte>, uint, ulong, int> Provider(IDalamudPluginInterface pi,
|
||||
IGlamourerApiItems api)
|
||||
=> new(pi, Label, (a, b, c, d, e, f) => (int)api.SetItem(a, (ApiEquipSlot)b, c, d, e, (ApplyFlag)f));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiItems.SetItemName"/>
|
||||
public sealed class SetItemName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, byte, ulong, IReadOnlyList<byte>, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(SetItemName)}.V2";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiItems.SetItem"/>
|
||||
public GlamourerApiEc Invoke(string objectName, ApiEquipSlot slot, ulong itemId, IReadOnlyList<byte> stain, uint key = 0,
|
||||
ApplyFlag flags = ApplyFlag.Once)
|
||||
=> (GlamourerApiEc)Invoke(objectName, (byte)slot, itemId, stain, key, (ulong)flags);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<string, byte, ulong, IReadOnlyList<byte>, uint, ulong, int> Provider(IDalamudPluginInterface pi,
|
||||
IGlamourerApiItems api)
|
||||
=> new(pi, Label, (a, b, c, d, e, f) => (int)api.SetItemName(a, (ApiEquipSlot)b, c, d, e, (ApplyFlag)f));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiItems.SetBonusItem"/>
|
||||
public sealed class SetBonusItem(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, byte, ulong, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(SetBonusItem)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiItems.SetBonusItem"/>
|
||||
public GlamourerApiEc Invoke(int objectIndex, ApiBonusSlot slot, ulong itemId, uint key = 0, ApplyFlag flags = ApplyFlag.Once)
|
||||
=> (GlamourerApiEc)Invoke(objectIndex, (byte)slot, itemId, key, (ulong)flags);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<int, byte, ulong, uint, ulong, int> Provider(IDalamudPluginInterface pi, IGlamourerApiItems api)
|
||||
=> new(pi, Label, (a, b, c, d, e) => (int)api.SetBonusItem(a, (ApiBonusSlot)b, c, d, (ApplyFlag)e));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiItems.SetBonusItemName"/>
|
||||
public sealed class SetBonusItemName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, byte, ulong, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(SetBonusItemName)}.V2";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiItems.SetBonusItemName"/>
|
||||
public GlamourerApiEc Invoke(string objectName, ApiBonusSlot slot, ulong itemId, uint key = 0, ApplyFlag flags = ApplyFlag.Once)
|
||||
=> (GlamourerApiEc)Invoke(objectName, (byte)slot, itemId, key, (ulong)flags);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<string, byte, ulong, uint, ulong, int> Provider(IDalamudPluginInterface pi, IGlamourerApiItems api)
|
||||
=> new(pi, Label, (a, b, c, d, e) => (int)api.SetBonusItemName(a, (ApiBonusSlot)b, c, d, (ApplyFlag)e));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiItems.SetMetaState"/>
|
||||
public sealed class SetMetaState(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, ulong, bool, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(SetMetaState)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiItems.SetMetaState"/>
|
||||
public GlamourerApiEc Invoke(int objectIndex, MetaFlag types, bool newValue, uint key = 0,
|
||||
ApplyFlag flags = ApplyFlag.Once)
|
||||
=> (GlamourerApiEc)Invoke(objectIndex, (ulong)types, newValue, key, (ulong)flags);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<int, ulong, bool, uint, ulong, int> Provider(IDalamudPluginInterface pi,
|
||||
IGlamourerApiItems api)
|
||||
=> new(pi, Label, (a, b, c, d, e) => (int)api.SetMetaState(a, (MetaFlag)b, c, d, (ApplyFlag)e));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiItems.SetMetaStateName"/>
|
||||
public sealed class SetMetaStateName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, ulong, bool, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(SetMetaStateName)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiItems.SetMetaStateName"/>
|
||||
public GlamourerApiEc Invoke(string objectName, MetaFlag types, bool newValue, uint key = 0,
|
||||
ApplyFlag flags = ApplyFlag.Once)
|
||||
=> (GlamourerApiEc)Invoke(objectName, (ulong)types, newValue, key, (ulong)flags);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<string, ulong, bool, uint, ulong, int> Provider(IDalamudPluginInterface pi,
|
||||
IGlamourerApiItems api)
|
||||
=> new(pi, Label, (a, b, c, d, e) => (int)api.SetMetaStateName(a, (MetaFlag)b, c, d, (ApplyFlag)e));
|
||||
}
|
@@ -1,52 +0,0 @@
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Plugin;
|
||||
using Glamourer.Api.Helpers;
|
||||
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
namespace Glamourer.Api.IpcSubscribers.Legacy;
|
||||
|
||||
public sealed class GetDesignList(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<(string Name, Guid Identifier)[]>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(GetDesignList)}";
|
||||
|
||||
public new (string Name, Guid Identifier)[] Invoke()
|
||||
=> base.Invoke();
|
||||
}
|
||||
|
||||
public sealed class ApplyByGuid(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<Guid, string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyByGuid)}";
|
||||
|
||||
public new void Invoke(Guid design, string name)
|
||||
=> base.Invoke(design, name);
|
||||
}
|
||||
|
||||
public sealed class ApplyByGuidOnce(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<Guid, string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyByGuidOnce)}";
|
||||
|
||||
public new void Invoke(Guid design, string name)
|
||||
=> base.Invoke(design, name);
|
||||
}
|
||||
|
||||
public sealed class ApplyByGuidToCharacter(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<Guid, ICharacter?>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyByGuidToCharacter)}";
|
||||
|
||||
public new void Invoke(Guid design, ICharacter? character)
|
||||
=> base.Invoke(design, character);
|
||||
}
|
||||
|
||||
public sealed class ApplyByGuidOnceToCharacter(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<Guid, ICharacter?>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyByGuidOnceToCharacter)}";
|
||||
|
||||
public new void Invoke(Guid design, ICharacter? character)
|
||||
=> base.Invoke(design, character);
|
||||
}
|
@@ -1,66 +0,0 @@
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Plugin;
|
||||
using Glamourer.Api.Api;
|
||||
using Glamourer.Api.Enums;
|
||||
using Glamourer.Api.Helpers;
|
||||
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
namespace Glamourer.Api.IpcSubscribers.Legacy;
|
||||
|
||||
public sealed class SetItem(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<ICharacter?, byte, ulong, byte, uint, int>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(SetItem)}";
|
||||
|
||||
public new GlamourerApiEc Invoke(ICharacter? character, byte slot, ulong itemId, byte stainId, uint key)
|
||||
=> (GlamourerApiEc)base.Invoke(character, slot, itemId, stainId, key);
|
||||
}
|
||||
|
||||
public sealed class SetItemOnce(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<ICharacter?, byte, ulong, byte, uint, int>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(SetItemOnce)}";
|
||||
|
||||
public new GlamourerApiEc Invoke(ICharacter? character, byte slot, ulong itemId, byte stainId, uint key)
|
||||
=> (GlamourerApiEc)base.Invoke(character, slot, itemId, stainId, key);
|
||||
}
|
||||
|
||||
public sealed class SetItemByActorName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, byte, ulong, byte, uint, int>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(SetItemByActorName)}";
|
||||
|
||||
public new GlamourerApiEc Invoke(string actorName, byte slot, ulong itemId, byte stainId, uint key)
|
||||
=> (GlamourerApiEc)base.Invoke(actorName, slot, itemId, stainId, key);
|
||||
}
|
||||
|
||||
public sealed class SetItemOnceByActorName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, byte, ulong, byte, uint, int>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(SetItemOnceByActorName)}";
|
||||
|
||||
public new GlamourerApiEc Invoke(string actorName, byte slot, ulong itemId, byte stainId, uint key)
|
||||
=> (GlamourerApiEc)base.Invoke(actorName, slot, itemId, stainId, key);
|
||||
}
|
||||
|
||||
public sealed class SetItemV2(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, byte, ulong, byte, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(SetItem)}.V2";
|
||||
|
||||
public GlamourerApiEc Invoke(int objectIndex, ApiEquipSlot slot, ulong itemId, byte stain, uint key = 0, ApplyFlag flags = ApplyFlag.Once)
|
||||
=> (GlamourerApiEc)Invoke(objectIndex, (byte)slot, itemId, stain, key, (ulong)flags);
|
||||
}
|
||||
|
||||
public sealed class SetItemName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, byte, ulong, byte, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(SetItemName)}";
|
||||
|
||||
public GlamourerApiEc Invoke(string objectName, ApiEquipSlot slot, ulong itemId, byte stain, uint key = 0, ApplyFlag flags = ApplyFlag.Once)
|
||||
=> (GlamourerApiEc)Invoke(objectName, (byte)slot, itemId, stain, key, (ulong)flags);
|
||||
|
||||
public static FuncProvider<string, byte, ulong, byte, uint, ulong, int> Provider(IDalamudPluginInterface pi, IGlamourerApiItems api)
|
||||
=> new(pi, Label, (a, b, c, d, e, f) => (int)api.SetItemName(a, (ApiEquipSlot)b, c, [d], e, (ApplyFlag)f));
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Glamourer.Api.Helpers;
|
||||
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
namespace Glamourer.Api.IpcSubscribers.Legacy;
|
||||
|
||||
public sealed class ApiVersions(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<(int, int)>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApiVersions)}";
|
||||
|
||||
public new (int Major, int Minor) Invoke()
|
||||
=> base.Invoke();
|
||||
}
|
@@ -1,250 +0,0 @@
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Plugin;
|
||||
using Glamourer.Api.Helpers;
|
||||
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
namespace Glamourer.Api.IpcSubscribers.Legacy;
|
||||
|
||||
public sealed class Revert(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(Revert)}";
|
||||
|
||||
public new void Invoke(string characterName)
|
||||
=> base.Invoke(characterName);
|
||||
}
|
||||
|
||||
public sealed class RevertCharacter(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<ICharacter?>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(RevertCharacter)}";
|
||||
|
||||
public new void Invoke(ICharacter? character)
|
||||
=> base.Invoke(character);
|
||||
}
|
||||
|
||||
public sealed class RevertLock(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<string, uint>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(RevertLock)}";
|
||||
|
||||
public new void Invoke(string characterName, uint key)
|
||||
=> base.Invoke(characterName, key);
|
||||
}
|
||||
|
||||
public sealed class RevertCharacterLock(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<ICharacter?, uint>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(RevertCharacterLock)}";
|
||||
|
||||
public new void Invoke(ICharacter? character, uint key)
|
||||
=> base.Invoke(character, key);
|
||||
}
|
||||
|
||||
public sealed class RevertToAutomation(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, uint, bool>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(RevertToAutomation)}";
|
||||
|
||||
public new bool Invoke(string characterName, uint key)
|
||||
=> base.Invoke(characterName, key);
|
||||
}
|
||||
|
||||
public sealed class RevertToAutomationCharacter(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<ICharacter?, uint, bool>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(RevertToAutomationCharacter)}";
|
||||
|
||||
public new bool Invoke(ICharacter? character, uint key)
|
||||
=> base.Invoke(character, key);
|
||||
}
|
||||
|
||||
public sealed class Unlock(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<ICharacter?, uint, bool>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(Unlock)}";
|
||||
|
||||
public new bool Invoke(ICharacter? character, uint key)
|
||||
=> base.Invoke(character, key);
|
||||
}
|
||||
|
||||
public sealed class UnlockName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, uint, bool>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(UnlockName)}";
|
||||
|
||||
public new bool Invoke(string characterName, uint key)
|
||||
=> base.Invoke(characterName, key);
|
||||
}
|
||||
|
||||
public static class StateChanged
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(StateChanged)}";
|
||||
|
||||
public static EventSubscriber<int, nint, Lazy<string>> Subscriber(IDalamudPluginInterface pi,
|
||||
params Action<int, nint, Lazy<string>>[] actions)
|
||||
=> new(pi, Label, actions);
|
||||
}
|
||||
|
||||
public sealed class GetAllCustomization(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, string?>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(GetAllCustomization)}";
|
||||
|
||||
public new string? Invoke(string characterName)
|
||||
=> base.Invoke(characterName);
|
||||
}
|
||||
|
||||
public sealed class GetAllCustomizationFromCharacter(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<ICharacter?, string?>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(GetAllCustomizationFromCharacter)}";
|
||||
|
||||
public new string? Invoke(ICharacter? character)
|
||||
=> base.Invoke(character);
|
||||
}
|
||||
|
||||
public sealed class GetAllCustomizationLocked(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, uint, string?>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(GetAllCustomizationLocked)}";
|
||||
|
||||
public new string? Invoke(string characterName, uint key)
|
||||
=> base.Invoke(characterName, key);
|
||||
}
|
||||
|
||||
public sealed class GetAllCustomizationFromLockedCharacter(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<ICharacter?, uint, string?>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(GetAllCustomizationFromLockedCharacter)}";
|
||||
|
||||
public new string? Invoke(ICharacter? character, uint key)
|
||||
=> base.Invoke(character, key);
|
||||
}
|
||||
|
||||
public sealed class ApplyAll(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<string, string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyAll)}";
|
||||
|
||||
public new void Invoke(string characterName, string stateBase64)
|
||||
=> base.Invoke(characterName, stateBase64);
|
||||
}
|
||||
|
||||
public sealed class ApplyAllOnce(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<string, string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyAllOnce)}";
|
||||
|
||||
public new void Invoke(string characterName, string stateBase64)
|
||||
=> base.Invoke(characterName, stateBase64);
|
||||
}
|
||||
|
||||
public sealed class ApplyAllToCharacter(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<ICharacter?, string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyAllToCharacter)}";
|
||||
|
||||
public new void Invoke(ICharacter? character, string stateBase64)
|
||||
=> base.Invoke(character, stateBase64);
|
||||
}
|
||||
|
||||
public sealed class ApplyAllOnceToCharacter(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<ICharacter?, string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyAllOnceToCharacter)}";
|
||||
|
||||
public new void Invoke(ICharacter? character, string stateBase64)
|
||||
=> base.Invoke(character, stateBase64);
|
||||
}
|
||||
|
||||
public sealed class ApplyOnlyEquipment(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<string, string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyOnlyEquipment)}";
|
||||
|
||||
public new void Invoke(string characterName, string stateBase64)
|
||||
=> base.Invoke(characterName, stateBase64);
|
||||
}
|
||||
|
||||
public sealed class ApplyOnlyEquipmentToCharacter(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<ICharacter?, string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyOnlyEquipmentToCharacter)}";
|
||||
|
||||
public new void Invoke(ICharacter? character, string stateBase64)
|
||||
=> base.Invoke(character, stateBase64);
|
||||
}
|
||||
|
||||
public sealed class ApplyOnlyCustomization(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<string, string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyOnlyCustomization)}";
|
||||
|
||||
public new void Invoke(string characterName, string stateBase64)
|
||||
=> base.Invoke(characterName, stateBase64);
|
||||
}
|
||||
|
||||
public sealed class ApplyOnlyCustomizationToCharacter(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<ICharacter?, string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyOnlyCustomizationToCharacter)}";
|
||||
|
||||
public new void Invoke(ICharacter? character, string stateBase64)
|
||||
=> base.Invoke(character, stateBase64);
|
||||
}
|
||||
|
||||
public sealed class ApplyAllLock(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<string, string, uint>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyAllLock)}";
|
||||
|
||||
public new void Invoke(string characterName, string stateBase64, uint key)
|
||||
=> base.Invoke(characterName, stateBase64, key);
|
||||
}
|
||||
|
||||
public sealed class ApplyAllToCharacterLock(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<ICharacter?, string, uint>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyAllToCharacterLock)}";
|
||||
|
||||
public new void Invoke(ICharacter? character, string stateBase64, uint key)
|
||||
=> base.Invoke(character, stateBase64, key);
|
||||
}
|
||||
|
||||
public sealed class ApplyOnlyEquipmentLock(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<string, string, uint>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyOnlyEquipmentLock)}";
|
||||
|
||||
public new void Invoke(string characterName, string stateBase64, uint key)
|
||||
=> base.Invoke(characterName, stateBase64, key);
|
||||
}
|
||||
|
||||
public sealed class ApplyOnlyEquipmentToCharacterLock(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<ICharacter?, string, uint>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyOnlyEquipmentToCharacterLock)}";
|
||||
|
||||
public new void Invoke(ICharacter? character, string stateBase64, uint key)
|
||||
=> base.Invoke(character, stateBase64, key);
|
||||
}
|
||||
|
||||
public sealed class ApplyOnlyCustomizationLock(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<string, string, uint>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyOnlyCustomizationLock)}";
|
||||
|
||||
public new void Invoke(string characterName, string stateBase64, uint key)
|
||||
=> base.Invoke(characterName, stateBase64, key);
|
||||
}
|
||||
|
||||
public sealed class ApplyOnlyCustomizationToCharacterLock(IDalamudPluginInterface pi)
|
||||
: ActionSubscriber<ICharacter?, string, uint>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Glamourer.{nameof(ApplyOnlyCustomizationToCharacterLock)}";
|
||||
|
||||
public new void Invoke(ICharacter? character, string stateBase64, uint key)
|
||||
=> base.Invoke(character, stateBase64, key);
|
||||
}
|
@@ -1,51 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Glamourer.Api.Api;
|
||||
using Glamourer.Api.Helpers;
|
||||
|
||||
namespace Glamourer.Api.IpcSubscribers;
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiBase.ApiVersion"/>
|
||||
public sealed class ApiVersion(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<(int, int)>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(ApiVersion)}.V2";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiBase.ApiVersion"/>
|
||||
public new (int Major, int Minor) Invoke()
|
||||
=> base.Invoke();
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<(int, int)> Provider(IDalamudPluginInterface pi, IGlamourerApiBase api)
|
||||
=> new(pi, Label, () => api.ApiVersion);
|
||||
}
|
||||
|
||||
/// <summary> Triggered when the Glamourer API is initialized and ready. </summary>
|
||||
public static class Initialized
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(Initialized)}";
|
||||
|
||||
/// <summary> Create a new event subscriber. </summary>
|
||||
public static EventSubscriber Subscriber(IDalamudPluginInterface pi, params Action[] actions)
|
||||
=> new(pi, Label, actions);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static EventProvider Provider(IDalamudPluginInterface pi)
|
||||
=> new(pi, Label);
|
||||
}
|
||||
|
||||
/// <summary> Triggered when the Glamourer API is fully disposed and unavailable. </summary>
|
||||
public static class Disposed
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(Disposed)}";
|
||||
|
||||
/// <summary> Create a new event subscriber. </summary>
|
||||
public static EventSubscriber Subscriber(IDalamudPluginInterface pi, params Action[] actions)
|
||||
=> new(pi, Label, actions);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static EventProvider Provider(IDalamudPluginInterface pi)
|
||||
=> new(pi, Label);
|
||||
}
|
@@ -1,311 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Glamourer.Api.Api;
|
||||
using Glamourer.Api.Enums;
|
||||
using Glamourer.Api.Helpers;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Glamourer.Api.IpcSubscribers;
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.GetState"/>
|
||||
public sealed class GetState(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, uint, (int, JObject?)>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(GetState)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.GetState"/>
|
||||
public new (GlamourerApiEc, JObject?) Invoke(int objectIndex, uint key = 0)
|
||||
{
|
||||
var (ec, data) = base.Invoke(objectIndex, key);
|
||||
return ((GlamourerApiEc)ec, data);
|
||||
}
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<int, uint, (int, JObject?)> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (a, b) =>
|
||||
{
|
||||
var (ec, data) = api.GetState(a, b);
|
||||
return ((int)ec, data);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.GetStateName"/>
|
||||
public sealed class GetStateName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, uint, (int, JObject?)>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(GetStateName)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.GetStateName"/>
|
||||
public new (GlamourerApiEc, JObject?) Invoke(string objectName, uint key = 0)
|
||||
{
|
||||
var (ec, data) = base.Invoke(objectName, key);
|
||||
return ((GlamourerApiEc)ec, data);
|
||||
}
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<string, uint, (int, JObject?)> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (i, k) =>
|
||||
{
|
||||
var (ec, data) = api.GetStateName(i, k);
|
||||
return ((int)ec, data);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.GetStateBase64"/>
|
||||
public sealed class GetStateBase64(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, uint, (int, string?)>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(GetStateBase64)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.GetStateBase64"/>
|
||||
public new (GlamourerApiEc, string?) Invoke(int objectIndex, uint key = 0)
|
||||
{
|
||||
var (ec, data) = base.Invoke(objectIndex, key);
|
||||
return ((GlamourerApiEc)ec, data);
|
||||
}
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<int, uint, (int, string?)> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (a, b) =>
|
||||
{
|
||||
var (ec, data) = api.GetStateBase64(a, b);
|
||||
return ((int)ec, data);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.GetStateBase64Name"/>
|
||||
public sealed class GetStateBase64Name(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, uint, (int, string?)>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(GetStateBase64Name)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.GetStateBase64Name"/>
|
||||
public new (GlamourerApiEc, string?) Invoke(string objectName, uint key = 0)
|
||||
{
|
||||
var (ec, data) = base.Invoke(objectName, key);
|
||||
return ((GlamourerApiEc)ec, data);
|
||||
}
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<string, uint, (int, string?)> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (i, k) =>
|
||||
{
|
||||
var (ec, data) = api.GetStateBase64Name(i, k);
|
||||
return ((int)ec, data);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.ApplyState"/>
|
||||
public sealed class ApplyState(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<object, int, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(ApplyState)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.ApplyState"/>
|
||||
public GlamourerApiEc Invoke(JObject state, int objectIndex, uint key = 0, ApplyFlag flags = ApplyFlagEx.StateDefault)
|
||||
=> (GlamourerApiEc)Invoke(state, objectIndex, key, (ulong)flags);
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.ApplyState"/>
|
||||
public GlamourerApiEc Invoke(string base64State, int objectIndex, uint key = 0, ApplyFlag flags = ApplyFlagEx.StateDefault)
|
||||
=> (GlamourerApiEc)Invoke(base64State, objectIndex, key, (ulong)flags);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<object, int, uint, ulong, int> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (a, b, c, d) => (int)api.ApplyState(a, b, c, (ApplyFlag)d));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.ApplyStateName"/>
|
||||
public sealed class ApplyStateName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<object, string, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(ApplyStateName)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.ApplyState"/>
|
||||
public GlamourerApiEc Invoke(JObject state, string objectName, uint key = 0, ApplyFlag flags = ApplyFlagEx.StateDefault)
|
||||
=> (GlamourerApiEc)Invoke(state, objectName, key, (ulong)flags);
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.ApplyState"/>
|
||||
public GlamourerApiEc Invoke(string base64State, string objectName, uint key = 0, ApplyFlag flags = ApplyFlagEx.StateDefault)
|
||||
=> (GlamourerApiEc)Invoke(base64State, objectName, key, (ulong)flags);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<object, string, uint, ulong, int> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (a, b, c, d) => (int)api.ApplyStateName(a, b, c, (ApplyFlag)d));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.RevertState"/>
|
||||
public sealed class RevertState(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(RevertState)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.RevertState"/>
|
||||
public GlamourerApiEc Invoke(int objectIndex, uint key = 0, ApplyFlag flags = ApplyFlagEx.RevertDefault)
|
||||
=> (GlamourerApiEc)Invoke(objectIndex, key, (ulong)flags);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<int, uint, ulong, int> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (a, b, c) => (int)api.RevertState(a, b, (ApplyFlag)c));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.RevertStateName"/>
|
||||
public sealed class RevertStateName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(RevertStateName)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.RevertStateName"/>
|
||||
public GlamourerApiEc Invoke(string objectName, uint key = 0, ApplyFlag flags = ApplyFlagEx.RevertDefault)
|
||||
=> (GlamourerApiEc)Invoke(objectName, key, (ulong)flags);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<string, uint, ulong, int> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (a, b, c) => (int)api.RevertStateName(a, b, (ApplyFlag)c));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.UnlockState"/>
|
||||
public sealed class UnlockState(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, uint, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(UnlockState)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.UnlockState"/>
|
||||
public new GlamourerApiEc Invoke(int objectIndex, uint key = 0)
|
||||
=> (GlamourerApiEc)base.Invoke(objectIndex, key);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<int, uint, int> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (a, b) => (int)api.UnlockState(a, b));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.UnlockStateName"/>
|
||||
public sealed class UnlockStateName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, uint, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(UnlockStateName)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.UnlockStateName"/>
|
||||
public new GlamourerApiEc Invoke(string objectName, uint key = 0)
|
||||
=> (GlamourerApiEc)base.Invoke(objectName, key);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<string, uint, int> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (a, b) => (int)api.UnlockStateName(a, b));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.UnlockAll"/>
|
||||
public sealed class UnlockAll(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<uint, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(UnlockAll)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.UnlockAll"/>
|
||||
public new int Invoke(uint key)
|
||||
=> base.Invoke(key);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<uint, int> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, api.UnlockAll);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.RevertToAutomation"/>
|
||||
public sealed class RevertToAutomation(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(RevertToAutomation)}.V2";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.RevertToAutomation"/>
|
||||
public GlamourerApiEc Invoke(int objectIndex, uint key = 0, ApplyFlag flags = ApplyFlagEx.RevertDefault)
|
||||
=> (GlamourerApiEc)Invoke(objectIndex, key, (ulong)flags);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<int, uint, ulong, int> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (a, b, c) => (int)api.RevertToAutomation(a, b, (ApplyFlag)c));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.RevertToAutomationName"/>
|
||||
public sealed class RevertToAutomationName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, uint, ulong, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Glamourer.{nameof(RevertToAutomationName)}";
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.RevertToAutomationName"/>
|
||||
public GlamourerApiEc Invoke(string objectName, uint key = 0, ApplyFlag flags = ApplyFlagEx.RevertDefault)
|
||||
=> (GlamourerApiEc)Invoke(objectName, key, (ulong)flags);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<string, uint, ulong, int> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (a, b, c) => (int)api.RevertToAutomationName(a, b, (ApplyFlag)c));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.StateChanged" />
|
||||
public static class StateChanged
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(StateChanged)}.V2";
|
||||
|
||||
/// <summary> Create a new event subscriber. </summary>
|
||||
public static EventSubscriber<nint> Subscriber(IDalamudPluginInterface pi, params Action<nint>[] actions)
|
||||
=> new(pi, Label, actions);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static EventProvider<nint> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (t => api.StateChanged += t, t => api.StateChanged -= t));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.StateChangedWithType" />
|
||||
public static class StateChangedWithType
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(StateChangedWithType)}";
|
||||
|
||||
/// <summary> Create a new event subscriber. </summary>
|
||||
public static EventSubscriber<nint, StateChangeType> Subscriber(IDalamudPluginInterface pi, params Action<nint, StateChangeType>[] actions)
|
||||
=> new(pi, Label, actions);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static EventProvider<nint, StateChangeType> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (t => api.StateChangedWithType += t, t => api.StateChangedWithType -= t));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.StateFinalized" />
|
||||
public static class StateFinalized
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(StateFinalized)}";
|
||||
|
||||
/// <summary> Create a new event subscriber. </summary>
|
||||
public static EventSubscriber<nint, StateFinalizationType> Subscriber(IDalamudPluginInterface pi, params Action<nint, StateFinalizationType>[] actions)
|
||||
=> new(pi, Label, actions);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static EventProvider<nint, StateFinalizationType> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (t => api.StateFinalized += t, t => api.StateFinalized -= t));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IGlamourerApiState.GPoseChanged" />
|
||||
public static class GPoseChanged
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(GPoseChanged)}";
|
||||
|
||||
/// <summary> Create a new event subscriber. </summary>
|
||||
public static EventSubscriber<bool> Subscriber(IDalamudPluginInterface pi, params Action<bool>[] actions)
|
||||
=> new(pi, Label, actions);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static EventProvider<bool> Provider(IDalamudPluginInterface pi, IGlamourerApiState api)
|
||||
=> new(pi, Label, (t => api.GPoseChanged += t, t => api.GPoseChanged -= t));
|
||||
}
|
@@ -1,4 +0,0 @@
|
||||
# Glamourer
|
||||
|
||||
This is an auxiliary repository for Glamourers external API.
|
||||
For more information, see the [main repo](https://github.com/Ottermandias/Glamourer).
|
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
"net9.0-windows7.0": {
|
||||
"DotNet.ReproducibleBuilds": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.2.25, )",
|
||||
"resolved": "1.2.25",
|
||||
"contentHash": "xCXiw7BCxHJ8pF6wPepRUddlh2dlQlbr81gXA72hdk4FLHkKXas7EH/n+fk5UCA/YfMqG1Z6XaPiUjDbUNBUzg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
.editorconfig = .editorconfig
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SnowcloakSync", "SnowcloakSync\SnowcloakSync.csproj", "{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -36,6 +38,14 @@ Global
|
||||
{5A0B7434-8D89-4E90-B55C-B4A7AE1A6ADE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5A0B7434-8D89-4E90-B55C-B4A7AE1A6ADE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{5A0B7434-8D89-4E90-B55C-B4A7AE1A6ADE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E633A968-2FB8-48FF-8136-5EBAEDF8E6F3}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@@ -7,6 +7,7 @@ namespace MareSynchronos.MareConfiguration.Configurations;
|
||||
[Serializable]
|
||||
public class MareConfig : IMareConfiguration
|
||||
{
|
||||
public bool SortSyncshellsByVRAM { get; set; } = false;
|
||||
public int ExpectedTOSVersion = 2;
|
||||
public int AcceptedTOSVersion { get; set; } = 0;
|
||||
public bool AcceptedAgreement { get; set; } = false;
|
||||
|
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Dalamud.NET.Sdk/13.0.0">
|
||||
<Project Sdk="Dalamud.NET.Sdk/13.1.0">
|
||||
<PropertyGroup>
|
||||
<AssemblyName>Snowcloak</AssemblyName>
|
||||
<Version>0.2.0.3</Version>
|
||||
<PackageProjectUrl>https://github.com/Eauldane/SnowcloakClient/</PackageProjectUrl>
|
||||
<Version>0.3.0</Version>
|
||||
<PackageProjectUrl>https://git.snowcloak-sync.com/Eauldane/SnowcloakClient/</PackageProjectUrl>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -14,37 +14,27 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Chaos.NaCl.Standard" Version="1.0.0" />
|
||||
<PackageReference Include="Downloader" Version="3.3.4" />
|
||||
<PackageReference Include="Downloader" Version="4.0.3" />
|
||||
<PackageReference Include="Glamourer.Api" Version="2.6.0" />
|
||||
<PackageReference Include="K4os.Compression.LZ4.Legacy" Version="1.3.8" />
|
||||
<PackageReference Include="K4os.Compression.LZ4.Streams" Version="1.3.8" />
|
||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.212">
|
||||
<PackageReference Include="MessagePack" Version="3.1.4" />
|
||||
<PackageReference Include="MessagePack.Annotations" Version="3.1.4" />
|
||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.219">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="9.0.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.9" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="9.0.9" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.9" />
|
||||
<PackageReference Include="Penumbra.Api" Version="5.12.0" />
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.15.0.120848">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="Exists('.\Penumbra.Api\Penumbra.Api.csproj')">
|
||||
<ProjectReference Include=".\Penumbra.Api\Penumbra.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="!Exists('.\Penumbra.Api\Penumbra.Api.csproj')">
|
||||
<PackageReference Include="Penumbra.Api" Version="5.12.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="Exists('.\Glamourer.Api\Glamourer.Api.csproj')">
|
||||
<ProjectReference Include=".\Glamourer.Api\Glamourer.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="!Exists('.\Glamourer.Api\Glamourer.Api.csproj')">
|
||||
<PackageReference Include="Glamourer.Api" Version="2.6.0" />
|
||||
<PackageReference Update="DalamudPackager" Version="13.1.0" />
|
||||
<PackageReference Include="System.IO.Pipelines" Version="9.0.9" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
@@ -54,6 +44,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MareAPI\MareSynchronosAPI\MareSynchronos.API.csproj" />
|
||||
<ProjectReference Include="..\SnowcloakSync\SnowcloakSync.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -235,11 +235,17 @@ public class Pair : DisposableMediatorSubscriberBase
|
||||
{
|
||||
string? noteOrName = GetNoteOrName();
|
||||
|
||||
if (noteOrName != null)
|
||||
if (_mareConfig.Current.SortSyncshellsByVRAM)
|
||||
{
|
||||
return($"0{LastAppliedApproximateVRAMBytes}");
|
||||
}
|
||||
else if (noteOrName != null) {
|
||||
return $"0{noteOrName}";
|
||||
else
|
||||
}
|
||||
else {
|
||||
return $"9{UserData.AliasOrUID}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string GetPlayerNameHash()
|
||||
{
|
||||
@@ -326,6 +332,11 @@ public class Pair : DisposableMediatorSubscriberBase
|
||||
_logger.LogTrace("Nothing to remove");
|
||||
return data;
|
||||
}
|
||||
if (IsPaused)
|
||||
{
|
||||
_logger.LogTrace("Skipping data removal for paused user {uid}", UserData.UID);
|
||||
return data;
|
||||
}
|
||||
|
||||
var ActiveGroupPairs = GroupPair.Where(p => !p.Value.GroupUserPermissions.IsPaused() && !p.Key.GroupUserPermissions.IsPaused()).ToList();
|
||||
|
||||
|
@@ -14,8 +14,9 @@ namespace MareSynchronos.Services;
|
||||
|
||||
public sealed class CommandManagerService : IDisposable
|
||||
{
|
||||
private const string _commandName = "/sync";
|
||||
private const string _commandName = "/snow";
|
||||
private const string _commandName2 = "/snowcloak";
|
||||
private const string _commandName3 = "/sync";
|
||||
|
||||
private const string _ssCommandPrefix = "/ss";
|
||||
|
||||
@@ -48,6 +49,10 @@ public sealed class CommandManagerService : IDisposable
|
||||
{
|
||||
HelpMessage = "Opens the Snowcloak UI"
|
||||
});
|
||||
_commandManager.AddHandler(_commandName3, new CommandInfo(OnCommand)
|
||||
{
|
||||
HelpMessage = "Opens the Snowcloak UI"
|
||||
});
|
||||
|
||||
// Lazy registration of all possible /ss# commands which tbf is what the game does for linkshells anyway
|
||||
for (int i = 1; i <= ChatService.CommandMaxNumber; ++i)
|
||||
|
@@ -9,6 +9,6 @@
|
||||
"customization"
|
||||
],
|
||||
"IconUrl": "https://raw.githubusercontent.com/Eauldane/SnowcloakClient/refs/heads/main/MareSynchronos/images/logo.png",
|
||||
"RepoUrl": "https://github.com/Eauldane/SnowcloakClient",
|
||||
"RepoUrl": "https://git.snowcloak-sync.com/Eauldane/SnowcloakClient",
|
||||
"CanUnloadAsync": true
|
||||
}
|
||||
|
@@ -1054,7 +1054,7 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase
|
||||
_configService.Current.OpenMareHubOnGposeStart = openInGpose;
|
||||
_configService.Save();
|
||||
}
|
||||
_uiSharedService.DrawHelpText("This will automatically open the import menu when loading into Gpose. If unchecked you can open the menu manually with /sync gpose");
|
||||
_uiSharedService.DrawHelpText("This will automatically open the import menu when loading into Gpose. If unchecked you can open the menu manually with /snow gpose");
|
||||
bool downloadDataOnConnection = _configService.Current.DownloadMcdDataOnConnection;
|
||||
if (ImGui.Checkbox("Download Online Character Data on connecting", ref downloadDataOnConnection))
|
||||
{
|
||||
|
@@ -10,6 +10,7 @@ using MareSynchronos.MareConfiguration;
|
||||
using MareSynchronos.PlayerData.Handlers;
|
||||
using MareSynchronos.PlayerData.Pairs;
|
||||
using MareSynchronos.Services;
|
||||
using MareSynchronos.Services.CharaData;
|
||||
using MareSynchronos.Services.Mediator;
|
||||
using MareSynchronos.Services.ServerConfiguration;
|
||||
using MareSynchronos.UI.Components;
|
||||
@@ -24,11 +25,24 @@ using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using MareSynchronos.API.Dto.Account;
|
||||
using MareSynchronos.MareConfiguration.Models;
|
||||
|
||||
namespace MareSynchronos.UI;
|
||||
|
||||
public class CompactUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
// selected menu for states
|
||||
private enum Menu
|
||||
{
|
||||
IndividualPairs,
|
||||
Syncshells
|
||||
}
|
||||
|
||||
// currebnt selected tab and sidebar state
|
||||
private Menu _selectedMenu = Menu.IndividualPairs;
|
||||
private bool _sidebarCollapsed = false;
|
||||
|
||||
public float TransferPartHeight;
|
||||
public float WindowContentWidth;
|
||||
private readonly ApiController _apiController;
|
||||
@@ -54,12 +68,19 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
private string _pairToAdd = string.Empty;
|
||||
private int _secretKeyIdx = -1;
|
||||
private bool _showModalForUserAddition;
|
||||
private bool _showSyncShells;
|
||||
private bool _wasOpen;
|
||||
private bool _registrationInProgress = false;
|
||||
private bool _registrationSuccess = false;
|
||||
private string? _registrationMessage;
|
||||
private RegisterReplyDto? _registrationReply;
|
||||
private readonly AccountRegistrationService _registerService;
|
||||
private string _secretKey = string.Empty;
|
||||
|
||||
|
||||
|
||||
public CompactUi(ILogger<CompactUi> logger, UiSharedService uiShared, MareConfigService configService, ApiController apiController, PairManager pairManager, ChatService chatService,
|
||||
ServerConfigurationManager serverManager, MareMediator mediator, FileUploadManager fileTransferManager, UidDisplayHandler uidDisplayHandler, CharaDataManager charaDataManager,
|
||||
PerformanceCollectorService performanceCollectorService)
|
||||
PerformanceCollectorService performanceCollectorService, AccountRegistrationService registerService)
|
||||
: base(logger, mediator, "###SnowcloakSyncMainUI", performanceCollectorService)
|
||||
{
|
||||
_uiSharedService = uiShared;
|
||||
@@ -67,6 +88,7 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
_apiController = apiController;
|
||||
_pairManager = pairManager;
|
||||
_serverManager = serverManager;
|
||||
_registerService = registerService;
|
||||
_fileTransferManager = fileTransferManager;
|
||||
_uidDisplayHandler = uidDisplayHandler;
|
||||
_charaDataManager = charaDataManager;
|
||||
@@ -95,133 +117,244 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
|
||||
Flags |= ImGuiWindowFlags.NoDocking;
|
||||
|
||||
// changed min size
|
||||
SizeConstraints = new WindowSizeConstraints()
|
||||
{
|
||||
MinimumSize = new Vector2(350, 400),
|
||||
MaximumSize = new Vector2(350, 2000),
|
||||
MinimumSize = new Vector2(500, 400),
|
||||
MaximumSize = new Vector2(600, 2000),
|
||||
};
|
||||
}
|
||||
|
||||
protected override void DrawInternal()
|
||||
{
|
||||
if (_serverManager.CurrentApiUrl.Equals(ApiController.SnowcloakServiceUri, StringComparison.Ordinal))
|
||||
UiSharedService.AccentColor = new(0.4275f, 0.6863f, 1f, 1f);
|
||||
UiSharedService.AccentColor = SnowcloakSync.Utils.Colours._snowcloakOnline;
|
||||
else
|
||||
UiSharedService.AccentColor = ImGuiColors.ParsedGreen;
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() - ImGui.GetStyle().WindowPadding.Y - 1f * ImGuiHelpers.GlobalScale + ImGui.GetStyle().ItemSpacing.Y);
|
||||
WindowContentWidth = UiSharedService.GetWindowContentRegionWidth();
|
||||
if (!_apiController.IsCurrentVersion)
|
||||
|
||||
DrawSidebar();
|
||||
ImGui.SameLine();
|
||||
DrawMainContent();
|
||||
}
|
||||
|
||||
//helper for buttons
|
||||
private void DrawSidebarButton(Menu menu, FontAwesomeIcon icon, string label)
|
||||
{
|
||||
bool isActive = _selectedMenu == menu;
|
||||
using var color = ImRaii.PushColor(ImGuiCol.Button, isActive ? UiSharedService.AccentColor : new Vector4(0, 0, 0, 0));
|
||||
using var colorHovered = ImRaii.PushColor(ImGuiCol.ButtonHovered, isActive ? UiSharedService.AccentColor : ImGui.GetStyle().Colors[(int)ImGuiCol.ButtonHovered]);
|
||||
using var colorActive = ImRaii.PushColor(ImGuiCol.ButtonActive, isActive ? UiSharedService.AccentColor : ImGui.GetStyle().Colors[(int)ImGuiCol.ButtonActive]);
|
||||
|
||||
if (_sidebarCollapsed)
|
||||
{
|
||||
var ver = _apiController.CurrentClientVersion;
|
||||
var unsupported = "UNSUPPORTED VERSION";
|
||||
using (_uiSharedService.UidFont.Push())
|
||||
// if the tab is collapsed state only show buttons not lable
|
||||
if (_uiSharedService.IconButton(icon))
|
||||
{
|
||||
var uidTextSize = ImGui.CalcTextSize(unsupported);
|
||||
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMax().X + ImGui.GetWindowContentRegionMin().X) / 2 - uidTextSize.X / 2);
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextColored(ImGuiColors.DalamudRed, unsupported);
|
||||
_selectedMenu = menu;
|
||||
}
|
||||
UiSharedService.ColorTextWrapped($"Your Snowcloak installation is out of date, the current version is {ver.Major}.{ver.Minor}.{ver.Build}. " +
|
||||
$"It is highly recommended to keep Snowcloak up to date. Open /xlplugins and update the plugin.", ImGuiColors.DalamudRed);
|
||||
UiSharedService.AttachToolTip(label);
|
||||
}
|
||||
|
||||
using (ImRaii.PushId("header")) DrawUIDHeader();
|
||||
ImGui.Separator();
|
||||
using (ImRaii.PushId("serverstatus")) DrawServerStatus();
|
||||
|
||||
if (_apiController.ServerState is ServerState.Connected)
|
||||
else
|
||||
{
|
||||
var hasShownSyncShells = _showSyncShells;
|
||||
if (_uiSharedService.IconTextButton(icon, label, (165 - ImGui.GetStyle().WindowPadding.X * 2) * ImGuiHelpers.GlobalScale))
|
||||
{
|
||||
_selectedMenu = menu;
|
||||
}
|
||||
}
|
||||
}
|
||||
// helper for buttons that dont cause state change
|
||||
private void DrawSidebarAction(FontAwesomeIcon icon, string label, Action onClick)
|
||||
{
|
||||
if (_sidebarCollapsed)
|
||||
{
|
||||
// if the tab is collapsed state only show buttons not lable
|
||||
if (_uiSharedService.IconButton(icon))
|
||||
{
|
||||
onClick();
|
||||
}
|
||||
UiSharedService.AttachToolTip(label);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_uiSharedService.IconTextButton(icon, label, (165 - ImGui.GetStyle().WindowPadding.X * 2) * ImGuiHelpers.GlobalScale))
|
||||
{
|
||||
onClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
private void DrawSidebar()
|
||||
{
|
||||
// Adjust both values below to change size, 40 seems good to fit the buttons
|
||||
// 150 seems decent enough to fit the text into it, could be smaller
|
||||
// Elf note: Adjusted to 165 since "Character Analysis" hung off the end a bit
|
||||
var sidebarWidth = (_sidebarCollapsed ? 40 : 165) * ImGuiHelpers.GlobalScale;
|
||||
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
if (!hasShownSyncShells)
|
||||
using (var child = ImRaii.Child("Sidebar", new Vector2(sidebarWidth, -1), true))
|
||||
{
|
||||
var collapseIcon = _sidebarCollapsed ? FontAwesomeIcon.ArrowRight : FontAwesomeIcon.ArrowLeft;
|
||||
if (_uiSharedService.IconButton(collapseIcon))
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Button, ImGui.GetStyle().Colors[(int)ImGuiCol.ButtonHovered]);
|
||||
_sidebarCollapsed = !_sidebarCollapsed;
|
||||
}
|
||||
if (ImGui.Button(FontAwesomeIcon.User.ToIconString(), new Vector2((UiSharedService.GetWindowContentRegionWidth() - ImGui.GetWindowContentRegionMin().X) / 2, 30 * ImGuiHelpers.GlobalScale)))
|
||||
{
|
||||
_showSyncShells = false;
|
||||
}
|
||||
if (!hasShownSyncShells)
|
||||
{
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
ImGui.PopFont();
|
||||
UiSharedService.AttachToolTip("Individual pairs");
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
if (hasShownSyncShells)
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Button, ImGui.GetStyle().Colors[(int)ImGuiCol.ButtonHovered]);
|
||||
}
|
||||
if (ImGui.Button(FontAwesomeIcon.UserFriends.ToIconString(), new Vector2((UiSharedService.GetWindowContentRegionWidth() - ImGui.GetWindowContentRegionMin().X) / 2, 30 * ImGuiHelpers.GlobalScale)))
|
||||
{
|
||||
_showSyncShells = true;
|
||||
}
|
||||
if (hasShownSyncShells)
|
||||
{
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
ImGui.PopFont();
|
||||
|
||||
UiSharedService.AttachToolTip("Syncshells");
|
||||
UiSharedService.AttachToolTip(_sidebarCollapsed ? "Expand Sidebar" : "Collapse Sidebar");
|
||||
|
||||
ImGui.Separator();
|
||||
if (!hasShownSyncShells)
|
||||
|
||||
// Buttons with state change
|
||||
DrawSidebarButton(Menu.IndividualPairs, FontAwesomeIcon.User, "Individual Pairs");
|
||||
DrawSidebarButton(Menu.Syncshells, FontAwesomeIcon.UserFriends, "Syncshells");
|
||||
ImGui.Separator();
|
||||
//buttons without state change
|
||||
DrawSidebarAction(FontAwesomeIcon.PersonCircleQuestion, "Character Analysis",
|
||||
() => Mediator.Publish(new UiToggleMessage(typeof(DataAnalysisUi))));
|
||||
//Abbrivated because Character Data Hub is too long and loogs ugly in the lables
|
||||
DrawSidebarAction(FontAwesomeIcon.Running, "Character Hub",
|
||||
() => Mediator.Publish(new UiToggleMessage(typeof(CharaDataHubUi))));
|
||||
DrawSidebarAction(FontAwesomeIcon.Cog, "Settings",
|
||||
() => Mediator.Publish(new UiToggleMessage(typeof(SettingsUi))));
|
||||
if (_apiController.ServerState is ServerState.Connected)
|
||||
{
|
||||
using (ImRaii.PushId("pairlist")) DrawPairList();
|
||||
ImGui.Separator();
|
||||
DrawSidebarAction(FontAwesomeIcon.UserCircle, "Edit Profile",
|
||||
() => Mediator.Publish(new UiToggleMessage(typeof(EditProfileUi))));
|
||||
}
|
||||
|
||||
float bottomElementsHeight = ImGui.GetFrameHeightWithSpacing() * 2;
|
||||
var availableSpace = ImGui.GetContentRegionAvail().Y;
|
||||
if (availableSpace > bottomElementsHeight)
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + availableSpace - bottomElementsHeight);
|
||||
|
||||
//transparent button shenenigans
|
||||
ImGui.PushStyleColor(ImGuiCol.Button, 0);
|
||||
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, 0);
|
||||
ImGui.PushStyleColor(ImGuiCol.ButtonActive, 0);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FrameBorderSize, 0);
|
||||
|
||||
|
||||
if (_apiController.ServerState is ServerState.Connected)
|
||||
{
|
||||
var userCount = _apiController.OnlineUsers.ToString(CultureInfo.InvariantCulture);
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, UiSharedService.AccentColor);
|
||||
DrawSidebarAction(FontAwesomeIcon.Users, $"{userCount} Users Online", () => { });
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
using (ImRaii.PushId("syncshells")) _groupPanel.DrawSyncshells();
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudRed);
|
||||
DrawSidebarAction(FontAwesomeIcon.ExclamationTriangle, "Not connected", () => { });
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
ImGui.Separator();
|
||||
using (ImRaii.PushId("transfers")) DrawTransfers();
|
||||
TransferPartHeight = ImGui.GetCursorPosY() - TransferPartHeight;
|
||||
using (ImRaii.PushId("group-user-popup")) _selectPairsForGroupUi.Draw(_pairManager.DirectPairs);
|
||||
using (ImRaii.PushId("grouping-popup")) _selectGroupForPairUi.Draw();
|
||||
}
|
||||
|
||||
if (_configService.Current.OpenPopupOnAdd && _pairManager.LastAddedUser != null)
|
||||
{
|
||||
_lastAddedUser = _pairManager.LastAddedUser;
|
||||
_pairManager.LastAddedUser = null;
|
||||
ImGui.OpenPopup("Set Notes for New User");
|
||||
_showModalForUserAddition = true;
|
||||
_lastAddedUserComment = string.Empty;
|
||||
}
|
||||
// restore normal button
|
||||
ImGui.PopStyleVar();
|
||||
ImGui.PopStyleColor(3);
|
||||
var connectedIcon = _serverManager.CurrentServer!.FullPause ? FontAwesomeIcon.Unlink : FontAwesomeIcon.Link;
|
||||
var color = UiSharedService.GetBoolColor(!_serverManager.CurrentServer!.FullPause);
|
||||
|
||||
if (ImGui.BeginPopupModal("Set Notes for New User", ref _showModalForUserAddition, UiSharedService.PopupWindowFlags))
|
||||
{
|
||||
if (_lastAddedUser == null)
|
||||
if (_apiController.ServerState is not (ServerState.Reconnecting or ServerState.Disconnecting))
|
||||
{
|
||||
_showModalForUserAddition = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
UiSharedService.TextWrapped($"You have successfully added {_lastAddedUser.UserData.AliasOrUID}. Set a local note for the user in the field below:");
|
||||
ImGui.InputTextWithHint("##noteforuser", $"Note for {_lastAddedUser.UserData.AliasOrUID}", ref _lastAddedUserComment, 100);
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Save, "Save Note"))
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, color);
|
||||
|
||||
DrawSidebarAction(connectedIcon, !_serverManager.CurrentServer.FullPause ? "Disconnect": "Connect",
|
||||
() =>
|
||||
{
|
||||
_serverManager.CurrentServer.FullPause = !_serverManager.CurrentServer.FullPause;
|
||||
_serverManager.Save();
|
||||
_ = _apiController.CreateConnections();
|
||||
});
|
||||
ImGui.PopStyleColor();
|
||||
UiSharedService.AttachToolTip(!_serverManager.CurrentServer.FullPause ? "Disconnect from " + _serverManager.CurrentServer.ServerName : "Connect to " + _serverManager.CurrentServer.ServerName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void DrawMainContent()
|
||||
{
|
||||
using (var child = ImRaii.Child("MainContent", new Vector2(-1, -1), false))
|
||||
{
|
||||
WindowContentWidth = UiSharedService.GetWindowContentRegionWidth();
|
||||
|
||||
if (!_apiController.IsCurrentVersion)
|
||||
{
|
||||
var ver = _apiController.CurrentClientVersion;
|
||||
var unsupported = "UNSUPPORTED VERSION";
|
||||
using (_uiSharedService.UidFont.Push())
|
||||
{
|
||||
var uidTextSize = ImGui.CalcTextSize(unsupported);
|
||||
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMax().X + ImGui.GetWindowContentRegionMin().X) / 2 - uidTextSize.X / 2);
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextColored(ImGuiColors.DalamudRed, unsupported);
|
||||
}
|
||||
UiSharedService.ColorTextWrapped($"Your Snowcloak installation is out of date, the current version is {ver.Major}.{ver.Minor}.{ver.Build}. " +
|
||||
$"It is highly recommended to keep Snowcloak up to date. Open /xlplugins and update the plugin.", ImGuiColors.DalamudRed);
|
||||
}
|
||||
|
||||
using (ImRaii.PushId("header")) DrawUIDHeader();
|
||||
|
||||
if (_apiController.ServerState is ServerState.Connected)
|
||||
{
|
||||
ImGui.Separator();
|
||||
|
||||
|
||||
switch (_selectedMenu)
|
||||
{
|
||||
case Menu.IndividualPairs:
|
||||
using (ImRaii.PushId("pairlist")) DrawPairList();
|
||||
break;
|
||||
case Menu.Syncshells:
|
||||
using (ImRaii.PushId("syncshells")) _groupPanel.DrawSyncshells();
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
using (ImRaii.PushId("transfers")) DrawTransfers();
|
||||
TransferPartHeight = ImGui.GetCursorPosY() - TransferPartHeight;
|
||||
using (ImRaii.PushId("group-user-popup")) _selectPairsForGroupUi.Draw(_pairManager.DirectPairs);
|
||||
using (ImRaii.PushId("grouping-popup")) _selectGroupForPairUi.Draw();
|
||||
}
|
||||
|
||||
if (_configService.Current.OpenPopupOnAdd && _pairManager.LastAddedUser != null)
|
||||
{
|
||||
_lastAddedUser = _pairManager.LastAddedUser;
|
||||
_pairManager.LastAddedUser = null;
|
||||
ImGui.OpenPopup("Set Notes for New User");
|
||||
_showModalForUserAddition = true;
|
||||
_lastAddedUserComment = string.Empty;
|
||||
}
|
||||
|
||||
if (ImGui.BeginPopupModal("Set Notes for New User", ref _showModalForUserAddition, UiSharedService.PopupWindowFlags))
|
||||
{
|
||||
if (_lastAddedUser == null)
|
||||
{
|
||||
_serverManager.SetNoteForUid(_lastAddedUser.UserData.UID, _lastAddedUserComment);
|
||||
_lastAddedUser = null;
|
||||
_lastAddedUserComment = string.Empty;
|
||||
_showModalForUserAddition = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
UiSharedService.TextWrapped($"You have successfully added {_lastAddedUser.UserData.AliasOrUID}. Set a local note for the user in the field below:");
|
||||
ImGui.InputTextWithHint("##noteforuser", $"Note for {_lastAddedUser.UserData.AliasOrUID}", ref _lastAddedUserComment, 100);
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Save, "Save Note"))
|
||||
{
|
||||
_serverManager.SetNoteForUid(_lastAddedUser.UserData.UID, _lastAddedUserComment);
|
||||
_lastAddedUser = null;
|
||||
_lastAddedUserComment = string.Empty;
|
||||
_showModalForUserAddition = false;
|
||||
}
|
||||
}
|
||||
UiSharedService.SetScaledWindowSize(275);
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
UiSharedService.SetScaledWindowSize(275);
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
|
||||
var pos = ImGui.GetWindowPos();
|
||||
var size = ImGui.GetWindowSize();
|
||||
if (_lastSize != size || _lastPosition != pos)
|
||||
{
|
||||
_lastSize = size;
|
||||
_lastPosition = pos;
|
||||
Mediator.Publish(new CompactUiChange(_lastSize, _lastPosition));
|
||||
var pos = ImGui.GetWindowPos();
|
||||
var size = ImGui.GetWindowSize();
|
||||
if (_lastSize != size || _lastPosition != pos)
|
||||
{
|
||||
_lastSize = size;
|
||||
_lastPosition = pos;
|
||||
Mediator.Publish(new CompactUiChange(_lastSize, _lastPosition));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,10 +368,44 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
ImGui.Dummy(new(10));
|
||||
var keys = _serverManager.CurrentServer!.SecretKeys;
|
||||
ImGui.BeginDisabled(_registrationInProgress || _uiSharedService.ApiController.ServerState == ServerState.Connecting || _uiSharedService.ApiController.ServerState == ServerState.Reconnecting);
|
||||
if (keys.Any())
|
||||
{
|
||||
if (_secretKeyIdx == -1) _secretKeyIdx = keys.First().Key;
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Plus, "Add current character with secret key"))
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Plus, "Log in with XIVAuth (experimental)"))
|
||||
{
|
||||
_registrationInProgress = true;
|
||||
_ = Task.Run(async () => {
|
||||
try
|
||||
{
|
||||
var reply = await _registerService.XIVAuth(CancellationToken.None).ConfigureAwait(false);
|
||||
if (!reply.Success)
|
||||
{
|
||||
_logger.LogWarning("Registration failed: {err}", reply.ErrorMessage);
|
||||
_registrationMessage = reply.ErrorMessage;
|
||||
if (_registrationMessage.IsNullOrEmpty())
|
||||
_registrationMessage = "An unknown error occured. Please try again later.";
|
||||
return;
|
||||
}
|
||||
_registrationMessage = "Account registered. Welcome to Snowcloak!";
|
||||
_secretKey = reply.SecretKey ?? "";
|
||||
_registrationReply = reply;
|
||||
_registrationSuccess = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Registration failed");
|
||||
_registrationSuccess = false;
|
||||
_registrationMessage = "An unknown error occured. Please try again later.";
|
||||
}
|
||||
finally
|
||||
{
|
||||
_registrationInProgress = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Plus, "Add character with existing key"))
|
||||
{
|
||||
_serverManager.CurrentServer!.Authentications.Add(new MareConfiguration.Models.Authentication()
|
||||
{
|
||||
@@ -251,7 +418,43 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
|
||||
_ = _apiController.CreateConnections();
|
||||
}
|
||||
ImGui.EndDisabled(); // _registrationInProgress || _registrationSuccess
|
||||
|
||||
if (_registrationInProgress)
|
||||
{
|
||||
ImGui.TextUnformatted("Waiting for the server...");
|
||||
}
|
||||
else if (!_registrationMessage.IsNullOrEmpty())
|
||||
{
|
||||
if (!_registrationSuccess)
|
||||
ImGui.TextColored(ImGuiColors.DalamudYellow, _registrationMessage);
|
||||
else
|
||||
ImGui.TextWrapped(_registrationMessage);
|
||||
}
|
||||
if (_secretKey.Length > 0 && _secretKey.Length != 64)
|
||||
{
|
||||
UiSharedService.ColorTextWrapped("Your secret key must be exactly 64 characters long.", ImGuiColors.DalamudRed);
|
||||
}
|
||||
else if (_secretKey.Length == 64)
|
||||
{
|
||||
using var saveDisabled = ImRaii.Disabled(_uiSharedService.ApiController.ServerState == ServerState.Connecting || _uiSharedService.ApiController.ServerState == ServerState.Reconnecting);
|
||||
if (ImGui.Button("Save and Connect"))
|
||||
{
|
||||
string keyName;
|
||||
if (_serverManager.CurrentServer == null) _serverManager.SelectServer(0);
|
||||
if (_registrationReply != null && _secretKey.Equals(_registrationReply.SecretKey, StringComparison.Ordinal))
|
||||
keyName = _registrationReply.UID + $" (registered {DateTime.Now:yyyy-MM-dd})";
|
||||
else
|
||||
keyName = $"Secret Key added on Setup ({DateTime.Now:yyyy-MM-dd})";
|
||||
_serverManager.CurrentServer!.SecretKeys.Add(_serverManager.CurrentServer.SecretKeys.Select(k => k.Key).LastOrDefault() + 1, new SecretKey()
|
||||
{
|
||||
FriendlyName = keyName,
|
||||
Key = _secretKey,
|
||||
});
|
||||
_serverManager.AddCurrentCharacterToServer(save: false);
|
||||
_ = Task.Run(() => _uiSharedService.ApiController.CreateConnections());
|
||||
}
|
||||
}
|
||||
_uiSharedService.DrawCombo("Secret Key##addCharacterSecretKey", keys, (f) => f.Value.FriendlyName, (f) => _secretKeyIdx = f.Key);
|
||||
}
|
||||
else
|
||||
@@ -362,87 +565,18 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
: (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - TransferPartHeight - ImGui.GetCursorPosY();
|
||||
var users = GetFilteredUsers().OrderBy(u => u.GetPairSortKey(), StringComparer.Ordinal);
|
||||
|
||||
var onlineUsers = users.Where(u => u.UserPair!.OtherPermissions.IsPaired() && (u.IsOnline || u.UserPair!.OwnPermissions.IsPaused())).Select(c => new DrawUserPair("Online" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||
var onlineUsers = users.Where(u => u.UserPair!.OtherPermissions.IsPaired() && (u.IsOnline && !u.IsVisible && (!u.UserPair!.OtherPermissions.IsPaused() && !u.UserPair!.OwnPermissions.IsPaused()))).Select(c => new DrawUserPair("Online" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||
var pausedUsers = users.Where(u => u.UserPair!.OtherPermissions.IsPaired() && (u.UserPair!.OtherPermissions.IsPaused() || u.UserPair!.OwnPermissions.IsPaused())).Select(c => new DrawUserPair("Paused" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||
var visibleUsers = users.Where(u => u.IsVisible).Select(c => new DrawUserPair("Visible" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||
var offlineUsers = users.Where(u => !u.UserPair!.OtherPermissions.IsPaired() || (!u.IsOnline && !u.UserPair!.OwnPermissions.IsPaused())).Select(c => new DrawUserPair("Offline" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||
var offlineUsers = users.Where(u => !u.UserPair!.OtherPermissions.IsPaired() || !u.IsOnline && (!u.UserPair!.OwnPermissions.IsPaused() && !u.UserPair.OtherPermissions.IsPaused())).Select(c => new DrawUserPair("Offline" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
|
||||
|
||||
ImGui.BeginChild("list", new Vector2(WindowContentWidth, ySize), border: false);
|
||||
|
||||
_pairGroupsUi.Draw(visibleUsers, onlineUsers, offlineUsers);
|
||||
_pairGroupsUi.Draw(visibleUsers, onlineUsers, pausedUsers, offlineUsers);
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
||||
private void DrawServerStatus()
|
||||
{
|
||||
var buttonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Link);
|
||||
var userCount = _apiController.OnlineUsers.ToString(CultureInfo.InvariantCulture);
|
||||
var userSize = ImGui.CalcTextSize(userCount);
|
||||
var textSize = ImGui.CalcTextSize("Users Online");
|
||||
string shardConnection = string.Equals(_apiController.ServerInfo.ShardName, "Main", StringComparison.OrdinalIgnoreCase) ? string.Empty : $"Shard: {_apiController.ServerInfo.ShardName}";
|
||||
var shardTextSize = ImGui.CalcTextSize(shardConnection);
|
||||
var printShard = !string.IsNullOrEmpty(_apiController.ServerInfo.ShardName) && shardConnection != string.Empty;
|
||||
|
||||
if (_apiController.ServerState is ServerState.Connected)
|
||||
{
|
||||
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth()) / 2 - (userSize.X + textSize.X) / 2 - ImGui.GetStyle().ItemSpacing.X / 2);
|
||||
if (!printShard) ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextColored(new Vector4(0.675f, 0.985f, 1f, 1f), userCount);
|
||||
ImGui.SameLine();
|
||||
if (!printShard) ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Users Online");
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextColored(ImGuiColors.DalamudRed, "Not connected to any server");
|
||||
}
|
||||
|
||||
if (printShard)
|
||||
{
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() - ImGui.GetStyle().ItemSpacing.Y);
|
||||
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth()) / 2 - shardTextSize.X / 2);
|
||||
ImGui.TextUnformatted(shardConnection);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
if (printShard)
|
||||
{
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() - ((userSize.Y + textSize.Y) / 2 + shardTextSize.Y) / 2 - ImGui.GetStyle().ItemSpacing.Y + buttonSize.Y / 2);
|
||||
}
|
||||
var color = UiSharedService.GetBoolColor(!_serverManager.CurrentServer!.FullPause);
|
||||
var connectedIcon = !_serverManager.CurrentServer.FullPause ? FontAwesomeIcon.Link : FontAwesomeIcon.Unlink;
|
||||
|
||||
if (_apiController.ServerState is ServerState.Connected)
|
||||
{
|
||||
ImGui.SetCursorPosX(0 + ImGui.GetStyle().ItemSpacing.X);
|
||||
if (_uiSharedService.IconButton(FontAwesomeIcon.UserCircle))
|
||||
{
|
||||
Mediator.Publish(new UiToggleMessage(typeof(EditProfileUi)));
|
||||
}
|
||||
UiSharedService.AttachToolTip("Edit your Profile");
|
||||
}
|
||||
|
||||
ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() - buttonSize.X);
|
||||
if (printShard)
|
||||
{
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() - ((userSize.Y + textSize.Y) / 2 + shardTextSize.Y) / 2 - ImGui.GetStyle().ItemSpacing.Y + buttonSize.Y / 2);
|
||||
}
|
||||
|
||||
if (_apiController.ServerState is not (ServerState.Reconnecting or ServerState.Disconnecting))
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, color);
|
||||
if (_uiSharedService.IconButton(connectedIcon))
|
||||
{
|
||||
_serverManager.CurrentServer.FullPause = !_serverManager.CurrentServer.FullPause;
|
||||
_serverManager.Save();
|
||||
_ = _apiController.CreateConnections();
|
||||
}
|
||||
ImGui.PopStyleColor();
|
||||
UiSharedService.AttachToolTip(!_serverManager.CurrentServer.FullPause ? "Disconnect from " + _serverManager.CurrentServer.ServerName : "Connect to " + _serverManager.CurrentServer.ServerName);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTransfers()
|
||||
{
|
||||
var currentUploads = _fileTransferManager.CurrentUploads.ToList();
|
||||
@@ -486,67 +620,39 @@ public class CompactUi : WindowMediatorSubscriberBase
|
||||
ImGui.SameLine(WindowContentWidth - textSize.X);
|
||||
ImGui.TextUnformatted(downloadText);
|
||||
}
|
||||
|
||||
var bottomButtonWidth = (WindowContentWidth - ImGui.GetStyle().ItemSpacing.X) / 2;
|
||||
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.PersonCircleQuestion, "Character Analysis", bottomButtonWidth))
|
||||
{
|
||||
Mediator.Publish(new UiToggleMessage(typeof(DataAnalysisUi)));
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Running, "Character Data Hub", bottomButtonWidth))
|
||||
{
|
||||
Mediator.Publish(new UiToggleMessage(typeof(CharaDataHubUi)));
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
private void DrawUIDHeader()
|
||||
{
|
||||
var uidText = GetUidText();
|
||||
var buttonSizeX = 0f;
|
||||
Vector2 uidTextSize;
|
||||
|
||||
using (_uiSharedService.UidFont.Push())
|
||||
{
|
||||
uidTextSize = ImGui.CalcTextSize(uidText);
|
||||
var uidTextSize = ImGui.CalcTextSize(uidText);
|
||||
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X) / 2 - (uidTextSize.X / 2));
|
||||
ImGui.TextColored(GetUidColor(), uidText);
|
||||
}
|
||||
|
||||
var originalPos = ImGui.GetCursorPos();
|
||||
ImGui.SetWindowFontScale(1.5f);
|
||||
var buttonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Cog);
|
||||
buttonSizeX -= buttonSize.X - ImGui.GetStyle().ItemSpacing.X * 2;
|
||||
ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() - buttonSize.X);
|
||||
ImGui.SetCursorPosY(originalPos.Y + uidTextSize.Y / 2 - buttonSize.Y / 2);
|
||||
if (_uiSharedService.IconButton(FontAwesomeIcon.Cog))
|
||||
{
|
||||
Mediator.Publish(new OpenSettingsUiMessage());
|
||||
}
|
||||
UiSharedService.AttachToolTip("Open the Snowcloak Settings");
|
||||
|
||||
ImGui.SameLine(); //Important to draw the uidText consistently
|
||||
ImGui.SetCursorPos(originalPos);
|
||||
|
||||
if (_apiController.ServerState is ServerState.Connected)
|
||||
{
|
||||
buttonSizeX += _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Copy).X - ImGui.GetStyle().ItemSpacing.X * 2;
|
||||
ImGui.SetCursorPosY(originalPos.Y + uidTextSize.Y / 2 - buttonSize.Y / 2);
|
||||
if (_uiSharedService.IconButton(FontAwesomeIcon.Copy))
|
||||
if (ImGui.IsItemClicked())
|
||||
{
|
||||
ImGui.SetClipboardText(_apiController.DisplayName);
|
||||
}
|
||||
UiSharedService.AttachToolTip("Copy your UID to clipboard");
|
||||
ImGui.SameLine();
|
||||
}
|
||||
ImGui.SetWindowFontScale(1f);
|
||||
UiSharedService.AttachToolTip("Click to copy");
|
||||
|
||||
ImGui.SetCursorPosY(originalPos.Y + buttonSize.Y / 2 - uidTextSize.Y / 2 - ImGui.GetStyle().ItemSpacing.Y / 2);
|
||||
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMax().X + ImGui.GetWindowContentRegionMin().X) / 2 + buttonSizeX - uidTextSize.X / 2);
|
||||
using (_uiSharedService.UidFont.Push())
|
||||
ImGui.TextColored(GetUidColor(), uidText);
|
||||
if (!string.Equals(_apiController.DisplayName, _apiController.UID, StringComparison.Ordinal))
|
||||
{
|
||||
var origTextSize = ImGui.CalcTextSize(_apiController.UID);
|
||||
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X) / 2 - (origTextSize.X / 2));
|
||||
ImGui.TextColored(GetUidColor(), _apiController.UID);
|
||||
if (ImGui.IsItemClicked())
|
||||
{
|
||||
ImGui.SetClipboardText(_apiController.UID);
|
||||
}
|
||||
UiSharedService.AttachToolTip("Click to copy");
|
||||
}
|
||||
}
|
||||
|
||||
if (_apiController.ServerState is not ServerState.Connected)
|
||||
{
|
||||
|
@@ -20,6 +20,7 @@ public class DrawGroupPair : DrawPairBase
|
||||
private readonly GroupPairFullInfoDto _fullInfoDto;
|
||||
private readonly GroupFullInfoDto _group;
|
||||
private readonly CharaDataManager _charaDataManager;
|
||||
public long VRAMUsage { get; set; }
|
||||
|
||||
public DrawGroupPair(string id, Pair entry, ApiController apiController,
|
||||
MareMediator mareMediator, GroupFullInfoDto group, GroupPairFullInfoDto fullInfoDto,
|
||||
@@ -80,6 +81,7 @@ public class DrawGroupPair : DrawPairBase
|
||||
}
|
||||
if (_pair.LastAppliedDataBytes >= 0)
|
||||
{
|
||||
|
||||
presenceText += UiSharedService.TooltipSeparator;
|
||||
presenceText += ((!_pair.IsVisible) ? "(Last) " : string.Empty) + "Mods Info" + Environment.NewLine;
|
||||
presenceText += "Files Size: " + UiSharedService.ByteToString(_pair.LastAppliedDataBytes, true);
|
||||
@@ -127,6 +129,9 @@ public class DrawGroupPair : DrawPairBase
|
||||
|
||||
protected override float DrawRightSide(float textPosY, float originalY)
|
||||
{
|
||||
var pauseIcon = _pair.IsPaused ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause;
|
||||
var pauseIconSize = _uiSharedService.GetIconButtonSize(pauseIcon);
|
||||
var spacingX = ImGui.GetStyle().ItemSpacing.X;
|
||||
var entryUID = _fullInfoDto.UserAliasOrUID;
|
||||
var entryIsMod = _fullInfoDto.GroupPairStatusInfo.IsModerator();
|
||||
var entryIsOwner = string.Equals(_pair.UserData.UID, _group.OwnerUID, StringComparison.Ordinal);
|
||||
@@ -145,19 +150,27 @@ public class DrawGroupPair : DrawPairBase
|
||||
bool showInfo = (individualAnimDisabled || individualSoundsDisabled || animDisabled || soundsDisabled);
|
||||
bool showPlus = _pair.UserPair == null;
|
||||
bool showBars = (userIsOwner || (userIsModerator && !entryIsMod && !entryIsOwner)) || !_pair.IsPaused;
|
||||
|
||||
bool showPause = true;
|
||||
var spacing = ImGui.GetStyle().ItemSpacing.X;
|
||||
var permIcon = (individualAnimDisabled || individualSoundsDisabled || individualVFXDisabled) ? FontAwesomeIcon.ExclamationTriangle
|
||||
: ((soundsDisabled || animDisabled || vfxDisabled) ? FontAwesomeIcon.InfoCircle : FontAwesomeIcon.None);
|
||||
var runningIconWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Running).X;
|
||||
var infoIconWidth = UiSharedService.GetIconSize(permIcon).X;
|
||||
var plusButtonWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Plus).X;
|
||||
var pauseButtonWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Plus).X;
|
||||
|
||||
var barButtonWidth = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars).X;
|
||||
var barButtonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars);
|
||||
|
||||
var windowEndX = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth();
|
||||
var rightSidePos = windowEndX - barButtonSize.X;
|
||||
|
||||
|
||||
var pos = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() + spacing
|
||||
- (showShared ? (runningIconWidth + spacing) : 0)
|
||||
- (showInfo ? (infoIconWidth + spacing) : 0)
|
||||
- (showPlus ? (plusButtonWidth + spacing) : 0)
|
||||
- (showPause ? (pauseButtonWidth + spacing) : 0)
|
||||
- (showBars ? (barButtonWidth + spacing) : 0);
|
||||
|
||||
ImGui.SameLine(pos);
|
||||
@@ -264,6 +277,7 @@ public class DrawGroupPair : DrawPairBase
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
|
||||
if (showPlus)
|
||||
{
|
||||
ImGui.SetCursorPosY(originalY);
|
||||
@@ -275,7 +289,37 @@ public class DrawGroupPair : DrawPairBase
|
||||
UiSharedService.AttachToolTip("Pair with " + entryUID + " individually");
|
||||
ImGui.SameLine();
|
||||
}
|
||||
if (showPause)
|
||||
{
|
||||
//rightSidePos -= pauseIconSize.X + spacingX;
|
||||
ImGui.SetCursorPosY(originalY);
|
||||
|
||||
if (_uiSharedService.IconButton(pauseIcon))
|
||||
{
|
||||
if (_pair.UserPair != null)
|
||||
{
|
||||
var perm = _pair.UserPair.OwnPermissions;
|
||||
perm.SetPaused(!perm.IsPaused());
|
||||
_ = _apiController.UserSetPairPermissions(new(_pair.UserData, perm));
|
||||
}
|
||||
else
|
||||
{
|
||||
var groupPerm = _fullInfoDto.GroupUserPermissions;
|
||||
groupPerm.SetPaused(!groupPerm.IsPaused());
|
||||
_ = _apiController.GroupChangeIndividualPermissionState(new GroupPairUserPermissionDto(
|
||||
_group.Group,
|
||||
_pair.UserData,
|
||||
groupPerm
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
UiSharedService.AttachToolTip(!_fullInfoDto.GroupUserPermissions.IsPaused()
|
||||
? "Pause pairing with " + entryUID
|
||||
: "Resume pairing with " + entryUID);
|
||||
ImGui.SameLine();
|
||||
|
||||
}
|
||||
if (showBars)
|
||||
{
|
||||
ImGui.SetCursorPosY(originalY);
|
||||
@@ -285,7 +329,6 @@ public class DrawGroupPair : DrawPairBase
|
||||
ImGui.OpenPopup("Popup");
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui.BeginPopup("Popup"))
|
||||
{
|
||||
if ((userIsModerator || userIsOwner) && !(entryIsMod || entryIsOwner))
|
||||
|
@@ -19,6 +19,7 @@ public class DrawUserPair : DrawPairBase
|
||||
protected readonly MareMediator _mediator;
|
||||
private readonly SelectGroupForPairUi _selectGroupForPairUi;
|
||||
private readonly CharaDataManager _charaDataManager;
|
||||
public long VramUsage { get; set; }
|
||||
|
||||
public DrawUserPair(string id, Pair entry, UidDisplayHandler displayHandler, ApiController apiController,
|
||||
MareMediator mareMediator, SelectGroupForPairUi selectGroupForPairUi,
|
||||
@@ -51,26 +52,27 @@ public class DrawUserPair : DrawPairBase
|
||||
{
|
||||
connectionIcon = FontAwesomeIcon.PauseCircle;
|
||||
connectionText = "Pairing status with " + _pair.UserData.AliasOrUID + " is paused";
|
||||
connectionColor = ImGuiColors.DalamudYellow;
|
||||
connectionColor = ImGuiColors.DalamudGrey;
|
||||
}
|
||||
else
|
||||
{
|
||||
connectionIcon = FontAwesomeIcon.Check;
|
||||
connectionIcon = FontAwesomeIcon.Snowflake;
|
||||
connectionText = "You are paired with " + _pair.UserData.AliasOrUID;
|
||||
connectionColor = ImGuiColors.ParsedGreen;
|
||||
connectionColor = _pair.IsOnline ? SnowcloakSync.Utils.Colours._snowcloakOnline : ImGuiColors.DalamudGrey;
|
||||
}
|
||||
|
||||
ImGui.SetCursorPosY(textPosY);
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
UiSharedService.ColorText(connectionIcon.ToIconString(), connectionColor);
|
||||
ImGui.PopFont();
|
||||
UiSharedService.AttachToolTip(connectionText);
|
||||
if (_pair is { IsOnline: true, IsVisible: true })
|
||||
if (!_pair.IsVisible)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.SetCursorPosY(textPosY);
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
UiSharedService.ColorText(FontAwesomeIcon.Eye.ToIconString(), ImGuiColors.ParsedGreen);
|
||||
UiSharedService.ColorText(connectionIcon.ToIconString(), connectionColor);
|
||||
ImGui.PopFont();
|
||||
UiSharedService.AttachToolTip(connectionText);
|
||||
}
|
||||
if (_pair is { IsOnline: true, IsVisible: true })
|
||||
{
|
||||
ImGui.SetCursorPosY(textPosY);
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
UiSharedService.ColorText(FontAwesomeIcon.Eye.ToIconString(), SnowcloakSync.Utils.Colours._snowcloakOnline);
|
||||
if (ImGui.IsItemClicked())
|
||||
{
|
||||
_mediator.Publish(new TargetPairMessage(_pair));
|
||||
@@ -84,6 +86,7 @@ public class DrawUserPair : DrawPairBase
|
||||
visibleTooltip += "Files Size: " + UiSharedService.ByteToString(_pair.LastAppliedDataBytes, true);
|
||||
if (_pair.LastAppliedApproximateVRAMBytes >= 0)
|
||||
{
|
||||
VramUsage = _pair.LastAppliedApproximateVRAMBytes;
|
||||
visibleTooltip += Environment.NewLine + "Approx. VRAM Usage: " + UiSharedService.ByteToString(_pair.LastAppliedApproximateVRAMBytes, true);
|
||||
}
|
||||
if (_pair.LastAppliedDataTris >= 0)
|
||||
@@ -97,6 +100,8 @@ public class DrawUserPair : DrawPairBase
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected override float DrawRightSide(float textPosY, float originalY)
|
||||
{
|
||||
var pauseIcon = _pair.UserPair!.OwnPermissions.IsPaused() ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause;
|
||||
|
@@ -418,21 +418,34 @@ internal sealed class GroupPanel
|
||||
ImGui.Indent(20);
|
||||
if (_expandedGroupState[groupDto.GID])
|
||||
{
|
||||
var sortedPairs = pairsInGroup
|
||||
.OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal))
|
||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator())
|
||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned())
|
||||
.ThenBy(u => u.GetPairSortKey(), StringComparer.OrdinalIgnoreCase);
|
||||
IOrderedEnumerable<Pair> sortedPairs;
|
||||
if (!_mareConfig.Current.SortSyncshellsByVRAM)
|
||||
{
|
||||
sortedPairs = pairsInGroup
|
||||
.OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal))
|
||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator())
|
||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned())
|
||||
.ThenBy(u => u.GetPairSortKey(), StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
sortedPairs = pairsInGroup
|
||||
.OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal))
|
||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator())
|
||||
.ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned())
|
||||
.ThenByDescending(u => u.LastAppliedApproximateVRAMBytes);
|
||||
}
|
||||
|
||||
var visibleUsers = new List<DrawGroupPair>();
|
||||
var onlineUsers = new List<DrawGroupPair>();
|
||||
var offlineUsers = new List<DrawGroupPair>();
|
||||
|
||||
|
||||
|
||||
foreach (var pair in sortedPairs)
|
||||
{
|
||||
var drawPair = new DrawGroupPair(
|
||||
groupDto.GID + pair.UserData.UID, pair,
|
||||
ApiController, _mainUi.Mediator, groupDto,
|
||||
ApiController, _mainUi.Mediator, groupDto,
|
||||
pair.GroupPair.Single(
|
||||
g => GroupDataComparer.Instance.Equals(g.Key.Group, groupDto.Group)
|
||||
).Value,
|
||||
@@ -453,6 +466,8 @@ internal sealed class GroupPanel
|
||||
ImGui.TextUnformatted("Visible");
|
||||
ImGui.Separator();
|
||||
_uidDisplayHandler.RenderPairList(visibleUsers);
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (onlineUsers.Count > 0)
|
||||
|
@@ -28,15 +28,15 @@ public class PairGroupsUi
|
||||
_uiSharedService = uiSharedService;
|
||||
}
|
||||
|
||||
public void Draw<T>(List<T> visibleUsers, List<T> onlineUsers, List<T> offlineUsers) where T : DrawPairBase
|
||||
public void Draw<T>(List<T> visibleUsers, List<T> onlineUsers, List<T> pausedUsers, List<T> offlineUsers) where T : DrawPairBase
|
||||
{
|
||||
// Only render those tags that actually have pairs in them, otherwise
|
||||
// we can end up with a bunch of useless pair groups
|
||||
var tagsWithPairsInThem = _tagHandler.GetAllTagsSorted();
|
||||
var allUsers = onlineUsers.Concat(offlineUsers).ToList();
|
||||
var allUsers = onlineUsers.Concat(offlineUsers).Concat(pausedUsers).ToList();
|
||||
if (typeof(T) == typeof(DrawUserPair))
|
||||
{
|
||||
DrawUserPairs(tagsWithPairsInThem, allUsers.Cast<DrawUserPair>().ToList(), visibleUsers.Cast<DrawUserPair>(), onlineUsers.Cast<DrawUserPair>(), offlineUsers.Cast<DrawUserPair>());
|
||||
DrawUserPairs(tagsWithPairsInThem, allUsers.Cast<DrawUserPair>().ToList(), visibleUsers.Cast<DrawUserPair>(), onlineUsers.Cast<DrawUserPair>(), pausedUsers.Cast<DrawUserPair>(), offlineUsers.Cast<DrawUserPair>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,13 +91,19 @@ public class PairGroupsUi
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCategory(string tag, IEnumerable<DrawPairBase> onlineUsers, IEnumerable<DrawPairBase> allUsers, IEnumerable<DrawPairBase>? visibleUsers = null)
|
||||
private void DrawCategory(string tag, IEnumerable<DrawPairBase> onlineUsers, IEnumerable<DrawPairBase> pausedUsers, IEnumerable<DrawPairBase> allUsers, IEnumerable<DrawPairBase>? visibleUsers = null)
|
||||
{
|
||||
IEnumerable<DrawPairBase> usersInThisTag;
|
||||
HashSet<string>? otherUidsTaggedWithTag = null;
|
||||
bool isSpecialTag = false;
|
||||
int visibleInThisTag = 0;
|
||||
if (tag is TagHandler.CustomOfflineTag or TagHandler.CustomOnlineTag or TagHandler.CustomVisibleTag or TagHandler.CustomUnpairedTag)
|
||||
|
||||
if (tag is TagHandler.CustomPausedTag)
|
||||
{
|
||||
usersInThisTag = pausedUsers;
|
||||
isSpecialTag = true;
|
||||
}
|
||||
else if (tag is TagHandler.CustomOfflineTag or TagHandler.CustomOnlineTag or TagHandler.CustomVisibleTag or TagHandler.CustomUnpairedTag)
|
||||
{
|
||||
usersInThisTag = onlineUsers;
|
||||
isSpecialTag = true;
|
||||
@@ -113,14 +119,13 @@ public class PairGroupsUi
|
||||
|
||||
if (isSpecialTag && !usersInThisTag.Any()) return;
|
||||
|
||||
DrawName(tag, isSpecialTag, visibleInThisTag, usersInThisTag.Count(), otherUidsTaggedWithTag?.Count);
|
||||
DrawName(tag, isSpecialTag, visibleInThisTag, usersInThisTag.Count(), pausedUsers.Count(), otherUidsTaggedWithTag?.Count);
|
||||
if (!isSpecialTag)
|
||||
{
|
||||
using (ImRaii.PushId($"group-{tag}-buttons")) DrawButtons(tag, allUsers.Cast<DrawUserPair>().Where(p => otherUidsTaggedWithTag!.Contains(p.UID)).ToList());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Avoid uncomfortably close group names
|
||||
if (!_tagHandler.IsTagOpen(tag))
|
||||
{
|
||||
var size = ImGui.CalcTextSize("").Y + ImGui.GetStyle().FramePadding.Y * 2f;
|
||||
@@ -151,18 +156,19 @@ public class PairGroupsUi
|
||||
UiSharedService.AttachToolTip($"Delete Group {tag} (Will not delete the pairs)" + Environment.NewLine + "Hold CTRL to delete");
|
||||
}
|
||||
|
||||
private void DrawName(string tag, bool isSpecialTag, int visible, int online, int? total)
|
||||
private void DrawName(string tag, bool isSpecialTag, int visible, int online, int paused, int? total)
|
||||
{
|
||||
string displayedName = tag switch
|
||||
{
|
||||
TagHandler.CustomUnpairedTag => "Unpaired",
|
||||
TagHandler.CustomOfflineTag => "Offline",
|
||||
TagHandler.CustomOnlineTag => _mareConfig.Current.ShowOfflineUsersSeparately ? "Online/Paused" : "Contacts",
|
||||
TagHandler.CustomOnlineTag => _mareConfig.Current.ShowOfflineUsersSeparately ? "Online" : "Contacts",
|
||||
TagHandler.CustomPausedTag => "Paused",
|
||||
TagHandler.CustomVisibleTag => "Visible",
|
||||
_ => tag
|
||||
};
|
||||
|
||||
string resultFolderName = !isSpecialTag ? $"{displayedName} ({visible}/{online}/{total} Pairs)" : $"{displayedName} ({online} Pairs)";
|
||||
string resultFolderName = !isSpecialTag ? $"{displayedName} ({visible}/{online}/{paused}/{total} Pairs)" : $"{displayedName} ({online} Pairs)";
|
||||
|
||||
// FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight
|
||||
var icon = _tagHandler.IsTagOpen(tag) ? FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight;
|
||||
@@ -184,7 +190,8 @@ public class PairGroupsUi
|
||||
ImGui.TextUnformatted($"Group {tag}");
|
||||
ImGui.Separator();
|
||||
ImGui.TextUnformatted($"{visible} Pairs visible");
|
||||
ImGui.TextUnformatted($"{online} Pairs online/paused");
|
||||
ImGui.TextUnformatted($"{online} Pairs online");
|
||||
ImGui.TextUnformatted($"{paused} Pairs paused");
|
||||
ImGui.TextUnformatted($"{total} Pairs total");
|
||||
ImGui.EndTooltip();
|
||||
}
|
||||
@@ -197,39 +204,45 @@ public class PairGroupsUi
|
||||
ImGui.Separator();
|
||||
}
|
||||
|
||||
private void DrawUserPairs(List<string> tagsWithPairsInThem, List<DrawUserPair> allUsers, IEnumerable<DrawUserPair> visibleUsers, IEnumerable<DrawUserPair> onlineUsers, IEnumerable<DrawUserPair> offlineUsers)
|
||||
private void DrawUserPairs(List<string> tagsWithPairsInThem, List<DrawUserPair> allUsers, IEnumerable<DrawUserPair> visibleUsers, IEnumerable<DrawUserPair> onlineUsers, IEnumerable<DrawUserPair> pausedUsers, IEnumerable<DrawUserPair> offlineUsers)
|
||||
{
|
||||
if (_mareConfig.Current.ShowVisibleUsersSeparately)
|
||||
{
|
||||
using (ImRaii.PushId("$group-VisibleCustomTag")) DrawCategory(TagHandler.CustomVisibleTag, visibleUsers, allUsers);
|
||||
using (ImRaii.PushId("$group-VisibleCustomTag")) DrawCategory(TagHandler.CustomVisibleTag, visibleUsers, Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||
}
|
||||
|
||||
foreach (var tag in tagsWithPairsInThem)
|
||||
{
|
||||
if (_mareConfig.Current.ShowOfflineUsersSeparately)
|
||||
{
|
||||
using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, onlineUsers, allUsers, visibleUsers);
|
||||
using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, onlineUsers, pausedUsers, allUsers, visibleUsers);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, allUsers, allUsers, visibleUsers);
|
||||
using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, allUsers, Enumerable.Empty<DrawUserPair>(), allUsers, visibleUsers);
|
||||
}
|
||||
}
|
||||
|
||||
if (_mareConfig.Current.ShowOfflineUsersSeparately)
|
||||
{
|
||||
using (ImRaii.PushId($"group-OnlineCustomTag")) DrawCategory(TagHandler.CustomOnlineTag,
|
||||
onlineUsers.Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), allUsers);
|
||||
onlineUsers.Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||
if (pausedUsers.Any()) using (ImRaii.PushId("group-PausedCustomTag")) DrawCategory(TagHandler.CustomPausedTag,
|
||||
Enumerable.Empty<DrawUserPair>(), pausedUsers, allUsers);
|
||||
using (ImRaii.PushId($"group-OfflineCustomTag")) DrawCategory(TagHandler.CustomOfflineTag,
|
||||
offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired()).ToList(), allUsers);
|
||||
offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired()).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (ImRaii.PushId($"group-OnlineCustomTag")) DrawCategory(TagHandler.CustomOnlineTag,
|
||||
onlineUsers.Concat(offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired())).Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), allUsers);
|
||||
onlineUsers.Concat(offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired())).Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||
}
|
||||
|
||||
using (ImRaii.PushId($"group-UnpairedCustomTag")) DrawCategory(TagHandler.CustomUnpairedTag,
|
||||
offlineUsers.Where(u => !u.UserPair!.OtherPermissions.IsPaired()).ToList(), allUsers);
|
||||
offlineUsers.Where(u => !u.UserPair!.OtherPermissions.IsPaired()).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
|
||||
}
|
||||
|
||||
|
||||
private void PauseRemainingPairs(List<DrawUserPair> availablePairs)
|
||||
{
|
||||
foreach (var pairToPause in availablePairs.Where(pair => !pair.UserPair!.OwnPermissions.IsPaused()))
|
||||
|
@@ -203,10 +203,10 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
||||
DtrStyle.Style4 => $"\xE03A {text}",
|
||||
DtrStyle.Style5 => $"\xE033 {text}",
|
||||
DtrStyle.Style6 => $"\xE038 {text}",
|
||||
DtrStyle.Style7 => $"\xE05D {text}",
|
||||
DtrStyle.Style7 => $"\xE044 {text}",
|
||||
DtrStyle.Style8 => $"\xE03C{text}",
|
||||
DtrStyle.Style9 => $"\xE040 {text} \xE041",
|
||||
_ => $"\uE044 {text}"
|
||||
_ => $"\uE05D {text}"
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -9,6 +9,7 @@ public class TagHandler
|
||||
public const string CustomOnlineTag = "Mare_Online";
|
||||
public const string CustomUnpairedTag = "Mare_Unpaired";
|
||||
public const string CustomVisibleTag = "Mare_Visible";
|
||||
public const string CustomPausedTag = "Mare_Paused";
|
||||
private readonly ServerConfigurationManager _serverConfigurationManager;
|
||||
|
||||
public TagHandler(ServerConfigurationManager serverConfigurationManager)
|
||||
|
@@ -167,7 +167,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
||||
The plugin creator tried their best to keep you secure. However, there is no guarantee for 100% security. Do not blindly pair your client with everyone.
|
||||
""");
|
||||
UiSharedService.TextWrapped("""
|
||||
Mod files that are saved on the service will remain on the service as long as there are requests for the files from clients. After a period of not being used, the mod files will be automatically deleted.
|
||||
Mod files that are saved on the service will remain on the service as long as there are requests for the files from clients. After a period of not being used, the mod files may be automatically deleted.
|
||||
""");
|
||||
UiSharedService.TextWrapped("""
|
||||
Accounts that are inactive for ninety (90) days will be deleted for privacy reasons.
|
||||
@@ -263,6 +263,39 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
||||
ImGui.BeginDisabled(_registrationInProgress || _registrationSuccess || _secretKey.Length > 0);
|
||||
ImGui.Separator();
|
||||
ImGui.TextUnformatted("If you have not used Snowcloak before, click below to register a new account.");
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.Plus, "Log in with XIVAuth (experimental)"))
|
||||
{
|
||||
_registrationInProgress = true;
|
||||
_ = Task.Run(async () => {
|
||||
try
|
||||
{
|
||||
var reply = await _registerService.XIVAuth(CancellationToken.None).ConfigureAwait(false);
|
||||
if (!reply.Success)
|
||||
{
|
||||
_logger.LogWarning("Registration failed: {err}", reply.ErrorMessage);
|
||||
_registrationMessage = reply.ErrorMessage;
|
||||
if (_registrationMessage.IsNullOrEmpty())
|
||||
_registrationMessage = "An unknown error occured. Please try again later.";
|
||||
return;
|
||||
}
|
||||
_registrationMessage = "Account registered. Welcome to Snowcloak!";
|
||||
_secretKey = reply.SecretKey ?? "";
|
||||
_registrationReply = reply;
|
||||
_registrationSuccess = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Registration failed");
|
||||
_registrationSuccess = false;
|
||||
_registrationMessage = "An unknown error occured. Please try again later.";
|
||||
}
|
||||
finally
|
||||
{
|
||||
_registrationInProgress = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.Plus, "Register a new Snowcloak account"))
|
||||
{
|
||||
_registrationInProgress = true;
|
||||
@@ -298,7 +331,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
||||
ImGui.EndDisabled(); // _registrationInProgress || _registrationSuccess
|
||||
if (_registrationInProgress)
|
||||
{
|
||||
ImGui.TextUnformatted("Sending request...");
|
||||
ImGui.TextUnformatted("Waiting for the server...");
|
||||
}
|
||||
else if (!_registrationMessage.IsNullOrEmpty())
|
||||
{
|
||||
|
@@ -956,6 +956,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_uiShared.BigText("UI");
|
||||
var showCharacterNames = _configService.Current.ShowCharacterNames;
|
||||
var showVisibleSeparate = _configService.Current.ShowVisibleUsersSeparately;
|
||||
var sortSyncshellByVRAM = _configService.Current.SortSyncshellsByVRAM;
|
||||
var showOfflineSeparate = _configService.Current.ShowOfflineUsersSeparately;
|
||||
var showProfiles = _configService.Current.ProfilesShow;
|
||||
var showNsfwProfiles = _configService.Current.ProfilesAllowNsfw;
|
||||
@@ -1074,13 +1075,20 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_configService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("This will show all currently visible users in a special 'Visible' group in the main UI.");
|
||||
if (ImGui.Checkbox("Sort visible syncshell users by VRAM usage", ref sortSyncshellByVRAM))
|
||||
{
|
||||
_configService.Current.SortSyncshellsByVRAM = sortSyncshellByVRAM;
|
||||
_logger.LogWarning("Changing value: {sortSyncshellsByVRAM}", sortSyncshellByVRAM);
|
||||
|
||||
if (ImGui.Checkbox("Show separate Offline group", ref showOfflineSeparate))
|
||||
_configService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("This will put users using the most VRAM in a syncshell at the top of the list.");
|
||||
if (ImGui.Checkbox("Group users by connection status", ref showOfflineSeparate))
|
||||
{
|
||||
_configService.Current.ShowOfflineUsersSeparately = showOfflineSeparate;
|
||||
_configService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("This will show all currently offline users in a special 'Offline' group in the main UI.");
|
||||
_uiShared.DrawHelpText("This will categorize users by their connection status in the main UI.");
|
||||
|
||||
if (ImGui.Checkbox("Show player names", ref showCharacterNames))
|
||||
{
|
||||
|
@@ -9,6 +9,8 @@ using System.Net.Http.Headers;
|
||||
using System.Net.Http.Json;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using Dalamud.Utility;
|
||||
using System.Net;
|
||||
|
||||
namespace MareSynchronos.WebAPI;
|
||||
|
||||
@@ -17,16 +19,18 @@ public sealed class AccountRegistrationService : IDisposable
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly ILogger<AccountRegistrationService> _logger;
|
||||
private readonly ServerConfigurationManager _serverManager;
|
||||
private readonly DalamudUtilService _dalamudUtilService;
|
||||
|
||||
private string GenerateSecretKey()
|
||||
{
|
||||
return Convert.ToHexString(SHA256.HashData(RandomNumberGenerator.GetBytes(64)));
|
||||
}
|
||||
|
||||
public AccountRegistrationService(ILogger<AccountRegistrationService> logger, ServerConfigurationManager serverManager)
|
||||
public AccountRegistrationService(ILogger<AccountRegistrationService> logger, DalamudUtilService dalamudUtilService, ServerConfigurationManager serverManager)
|
||||
{
|
||||
_logger = logger;
|
||||
_serverManager = serverManager;
|
||||
_dalamudUtilService = dalamudUtilService;
|
||||
_httpClient = new(
|
||||
new HttpClientHandler
|
||||
{
|
||||
@@ -43,6 +47,72 @@ public sealed class AccountRegistrationService : IDisposable
|
||||
_httpClient.Dispose();
|
||||
}
|
||||
|
||||
public async Task<RegisterReplyDto> XIVAuth(CancellationToken token)
|
||||
{
|
||||
var secretKey = GenerateSecretKey();
|
||||
var hashedSecretKey = secretKey.GetHash256();
|
||||
var playerName = _dalamudUtilService.GetPlayerNameAsync().GetAwaiter().GetResult();
|
||||
var worldId = (ushort)_dalamudUtilService.GetHomeWorldIdAsync().GetAwaiter().GetResult();
|
||||
var worldName = _dalamudUtilService.WorldData.Value[(worldId)];
|
||||
|
||||
|
||||
|
||||
var sessionID = Convert.ToBase64String(RandomNumberGenerator.GetBytes(32)).Replace('+', '-').Replace('/', '_').TrimEnd('=');
|
||||
|
||||
Uri handshakeUri = new Uri("https://account.snowcloak-sync.com/register");
|
||||
var handshakePayload = new { session_id = sessionID, hashed_secret = hashedSecretKey, character_name = playerName, home_world = worldName };
|
||||
var handshakeResponse = await _httpClient.PostAsJsonAsync(handshakeUri, handshakePayload, token).ConfigureAwait(false);
|
||||
handshakeResponse.EnsureSuccessStatusCode();
|
||||
var register = await handshakeResponse.Content.ReadFromJsonAsync<RegisterResponse>(cancellationToken: token)
|
||||
.ConfigureAwait(false);
|
||||
if (register is null || string.IsNullOrWhiteSpace(register.link_url) ||
|
||||
string.IsNullOrWhiteSpace(register.poll_url))
|
||||
{
|
||||
return new RegisterReplyDto() { Success = false, ErrorMessage = "Malformed registration response." };
|
||||
}
|
||||
|
||||
Util.OpenLink(register.link_url);
|
||||
const int maxAttempts = 600 / 15; // Try once every 15 seconds for 10 minutes
|
||||
var pollUri = new Uri(register.poll_url);
|
||||
PollResponse? lastPoll = null;
|
||||
for (int i = 0; i < maxAttempts; i++)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
using var resp = await _httpClient.GetAsync(pollUri, token).ConfigureAwait(false);
|
||||
if (resp.StatusCode == HttpStatusCode.Gone)
|
||||
{
|
||||
// Server marked this as having been consumed already OR it got TLL'd out
|
||||
return new RegisterReplyDto()
|
||||
{
|
||||
Success = false, ErrorMessage = "Registration session expired. Please try again."
|
||||
};
|
||||
}
|
||||
|
||||
if (resp.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
lastPoll = await resp.Content.ReadFromJsonAsync<PollResponse>(cancellationToken: token)
|
||||
.ConfigureAwait(false);
|
||||
if (lastPoll?.status?.Equals("bound", StringComparison.OrdinalIgnoreCase) == true)
|
||||
{
|
||||
// yay
|
||||
return new RegisterReplyDto()
|
||||
{
|
||||
Success = true, ErrorMessage = null, UID = lastPoll?.uid, SecretKey = secretKey
|
||||
};
|
||||
}
|
||||
// Pending, keep polling
|
||||
}
|
||||
await Task.Delay(TimeSpan.FromSeconds(15), token).ConfigureAwait(false);
|
||||
}
|
||||
// Timed out
|
||||
return new RegisterReplyDto()
|
||||
{
|
||||
Success = false,
|
||||
ErrorMessage =
|
||||
"Timed out waiting for authorisation. Please try again, and complete the process within 10 minutes."
|
||||
};
|
||||
|
||||
}
|
||||
public async Task<RegisterReplyDto> RegisterAccount(CancellationToken token)
|
||||
{
|
||||
var secretKey = GenerateSecretKey();
|
||||
@@ -67,4 +137,19 @@ public sealed class AccountRegistrationService : IDisposable
|
||||
SecretKey = secretKey
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class RegisterResponse
|
||||
{
|
||||
public string link_url { get; set; } = "";
|
||||
public string poll_url { get; set; } = "";
|
||||
}
|
||||
|
||||
private sealed class PollResponse
|
||||
{
|
||||
public string status { get; set; } = "";
|
||||
public string? uid { get; set; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using MareSynchronos.API.Data;
|
||||
using MareSynchronos.API.Dto.Group;
|
||||
using MareSynchronos.API.Dto.User;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
@@ -19,10 +19,10 @@ public partial class ApiController
|
||||
await _mareHub!.SendAsync(nameof(GroupChangeGroupPermissionState), dto).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task GroupChangeIndividualPermissionState(GroupPairUserPermissionDto dto)
|
||||
public Task GroupChangeIndividualPermissionState(GroupPairUserPermissionDto dto)
|
||||
{
|
||||
CheckConnection();
|
||||
await _mareHub!.SendAsync(nameof(GroupChangeIndividualPermissionState), dto).ConfigureAwait(false);
|
||||
return _mareHub!.InvokeAsync(nameof(GroupChangeIndividualPermissionState), dto);
|
||||
}
|
||||
|
||||
public async Task GroupChangeOwnership(GroupPairDto groupPair)
|
||||
|
@@ -183,10 +183,12 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
||||
|
||||
_connectionDto = await GetConnectionDto().ConfigureAwait(false);
|
||||
|
||||
await CheckClientHealth().ConfigureAwait(false);
|
||||
|
||||
ServerState = ServerState.Connected;
|
||||
|
||||
var currentClientVer = Assembly.GetExecutingAssembly().GetName().Version!;
|
||||
|
||||
|
||||
if (_connectionDto.ServerVersion != IMareHub.ApiVersion)
|
||||
{
|
||||
if (_connectionDto.CurrentClientVersion > currentClientVer)
|
||||
@@ -308,14 +310,18 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
||||
_ = Task.Run(async () => await StopConnection(ServerState.Disconnected).ConfigureAwait(false));
|
||||
_connectionCancellationTokenSource?.Cancel();
|
||||
}
|
||||
|
||||
|
||||
private async Task ClientHealthCheck(CancellationToken ct)
|
||||
{
|
||||
while (!ct.IsCancellationRequested && _mareHub != null)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(30), ct).ConfigureAwait(false);
|
||||
Logger.LogDebug("Checking Client Health State");
|
||||
_ = await CheckClientHealth().ConfigureAwait(false);
|
||||
var healthy = await CheckClientHealth().ConfigureAwait(false);
|
||||
if (!healthy || _mareHub.State != HubConnectionState.Connected)
|
||||
{
|
||||
Logger.LogWarning("Health check failed, forcing reconnect. ClientHealth: {0} HubConnected: {1}", healthy, _mareHub.State != HubConnectionState.Connected);
|
||||
await ForceResetConnection().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,7 +397,7 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
||||
{
|
||||
var users = await GroupsGetUsersInGroup(group).ConfigureAwait(false);
|
||||
foreach (var user in users)
|
||||
{
|
||||
{
|
||||
Logger.LogDebug("Group Pair: {user}", user);
|
||||
_pairManager.AddGroupPair(user);
|
||||
}
|
||||
@@ -478,5 +484,30 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM
|
||||
|
||||
ServerState = state;
|
||||
}
|
||||
//Because this plugin really likes to bug out with connections, lets "fix" it....
|
||||
public async Task ForceResetConnection()
|
||||
{
|
||||
if (!_initialized) return;
|
||||
Logger.LogInformation("ForceReconnect called");
|
||||
|
||||
try
|
||||
{
|
||||
await StopConnection(ServerState.Disconnected).ConfigureAwait(false);
|
||||
|
||||
// Cancel any ongoing health checks to prevent conflicts
|
||||
_healthCheckTokenSource?.Cancel();
|
||||
_healthCheckTokenSource?.Dispose();
|
||||
_healthCheckTokenSource = null;
|
||||
|
||||
await CreateConnections().ConfigureAwait(false);
|
||||
|
||||
Logger.LogInformation("ForceReconnect completed successfully");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Failure during ForceReconnect, disconnecting");
|
||||
await StopConnection(ServerState.Disconnected).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore MA0040
|
BIN
MareSynchronos/images/logo.png
Normal file
BIN
MareSynchronos/images/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 KiB |
@@ -10,9 +10,9 @@
|
||||
},
|
||||
"DalamudPackager": {
|
||||
"type": "Direct",
|
||||
"requested": "[13.0.0, )",
|
||||
"resolved": "13.0.0",
|
||||
"contentHash": "Mb3cUDSK/vDPQ8gQIeuCw03EMYrej1B4J44a1AvIJ9C759p9XeqdU9Hg4WgOmlnlPe0G7ILTD32PKSUpkQNa8w=="
|
||||
"requested": "[13.1.0, )",
|
||||
"resolved": "13.1.0",
|
||||
"contentHash": "XdoNhJGyFby5M/sdcRhnc5xTop9PHy+H50PTWpzLhJugjB19EDBiHD/AsiDF66RETM+0qKUdJBZrNuebn7qswQ=="
|
||||
},
|
||||
"DotNet.ReproducibleBuilds": {
|
||||
"type": "Direct",
|
||||
@@ -22,11 +22,11 @@
|
||||
},
|
||||
"Downloader": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.3.4, )",
|
||||
"resolved": "3.3.4",
|
||||
"contentHash": "/M/c80e1L0WW1XrLSSiQhgFxk8rrfbpWiWDn2CeBg1tPD393Neo+v184yG/ThyhE9rrNp36yCrugiCmEbRf+VQ==",
|
||||
"requested": "[4.0.3, )",
|
||||
"resolved": "4.0.3",
|
||||
"contentHash": "Vg1+UqPDstpMw2CKXV9XvB8jKHC95KQfbqPxQXvOMRMFnTov4Ixvvw6GZV5DXLnKuL2sfnmVYX9CaQtcURia1Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging.Abstractions": "8.0.1"
|
||||
"Microsoft.Extensions.Logging.Abstractions": "8.0.3"
|
||||
}
|
||||
},
|
||||
"Glamourer.Api": {
|
||||
@@ -55,60 +55,77 @@
|
||||
"System.IO.Pipelines": "6.0.3"
|
||||
}
|
||||
},
|
||||
"MessagePack": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.1.4, )",
|
||||
"resolved": "3.1.4",
|
||||
"contentHash": "BH0wlHWmVoZpbAPyyt2Awbq30C+ZsS3eHSkYdnyUAbqVJ22fAJDzn2xTieBeoT5QlcBzp61vHcv878YJGfi3mg==",
|
||||
"dependencies": {
|
||||
"MessagePack.Annotations": "3.1.4",
|
||||
"MessagePackAnalyzer": "3.1.4",
|
||||
"Microsoft.NET.StringTools": "17.11.4"
|
||||
}
|
||||
},
|
||||
"MessagePack.Annotations": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.1.4, )",
|
||||
"resolved": "3.1.4",
|
||||
"contentHash": "aVWrDAkCdqxwQsz/q0ldPh2EFn48M99YUzE9OvZjMq2RNLKz4o2z88iGFvSvbMqOWRweRvKPHBJZe22PRqzslQ=="
|
||||
},
|
||||
"Meziantou.Analyzer": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.0.212, )",
|
||||
"resolved": "2.0.212",
|
||||
"contentHash": "U91ktjjTRTccUs3Lk+hrLD9vW+2+lhnsOf4G1GpRSJi1pLn3uK5CU6wGP9Bmz1KlJs6Oz1GGoMhxQBoqQsmAuQ=="
|
||||
"requested": "[2.0.219, )",
|
||||
"resolved": "2.0.219",
|
||||
"contentHash": "vknqxTO59DkRmsuyA3GoQ8zLODHTVrt2enVozcRLY22D3LRJm3qRNYIkpFl1lfejOsahrMwObtYzKLmWf7/XTQ=="
|
||||
},
|
||||
"Microsoft.AspNetCore.SignalR.Client": {
|
||||
"type": "Direct",
|
||||
"requested": "[9.0.8, )",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "cO+TZaWdhMn2cIYfPH9oFZaisJrx7X6SBAYdmGektPUAW2BYtMbH4HyLOnJ5CYo42zP9WgqhWHKqmoDm7+Ol5w==",
|
||||
"requested": "[9.0.9, )",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "xx1VCb/cxdOgKg+dQuTpZ3xR2/qpKvwD4iLIjFD+gDgsanVFtm/hEyfRg2nUUqF0UD9kyW0YUz2dsEL3GKjCGg==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Connections.Client": "9.0.8",
|
||||
"Microsoft.AspNetCore.SignalR.Client.Core": "9.0.8"
|
||||
"Microsoft.AspNetCore.Http.Connections.Client": "9.0.9",
|
||||
"Microsoft.AspNetCore.SignalR.Client.Core": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.SignalR.Protocols.MessagePack": {
|
||||
"type": "Direct",
|
||||
"requested": "[9.0.8, )",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "e6SC/Tp+SZKeEVYdu8blz9q4MkFW08D56IkQv9V3perF3a7v+GgGZ0DAY/HRS9zBuhFrqpXhJvxeHMw3PJLcOg==",
|
||||
"requested": "[9.0.9, )",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "OgsyQ8NgbWvkMV+Gqr0gVhOXw2AQuIZk/wN2KdnIyzj4I7qImHLPzGh31gc2Hns8T3n0UaJgBayFWLOOHV81mg==",
|
||||
"dependencies": {
|
||||
"MessagePack": "2.5.187",
|
||||
"Microsoft.AspNetCore.SignalR.Common": "9.0.8"
|
||||
"Microsoft.AspNetCore.SignalR.Common": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Hosting": {
|
||||
"type": "Direct",
|
||||
"requested": "[9.0.8, )",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "O2VlzORrBbS2it203k5FOHrudDdmdrJovA73P/shdRGeLzvet4e4yXhGx52V2PNjYBQ0IO5M4xiNcL+6xIX6Bg==",
|
||||
"requested": "[9.0.9, )",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "DmRsWH3g8yZGho/pLQ79hxhM2ctE1eDTZ/HbAnrD/uw8m+P2pRRJOoBVxlrhbhMP3/y3oAJoy0yITasfmilbTg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Binder": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.FileExtensions": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Json": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.UserSecrets": "9.0.8",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.8",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Diagnostics": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Physical": "9.0.8",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Console": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Debug": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.EventLog": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.EventSource": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8"
|
||||
"Microsoft.Extensions.Configuration": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.Binder": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.FileExtensions": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.Json": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.UserSecrets": "9.0.9",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.9",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Diagnostics": "9.0.9",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.FileProviders.Physical": "9.0.9",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Logging": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.Configuration": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.Console": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.Debug": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.EventLog": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.EventSource": "9.0.9",
|
||||
"Microsoft.Extensions.Options": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Penumbra.Api": {
|
||||
@@ -133,6 +150,12 @@
|
||||
"Microsoft.IdentityModel.Tokens": "8.14.0"
|
||||
}
|
||||
},
|
||||
"System.IO.Pipelines": {
|
||||
"type": "Direct",
|
||||
"requested": "[9.0.9, )",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "VySjpsCLprojvat550Flrm3NQB982CPuDzILajqjQihFmrQXZPdQyktIbcpVPJyaExFYtAfY1DpwMdWQuS0kbw=="
|
||||
},
|
||||
"K4os.Compression.LZ4": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.3.8",
|
||||
@@ -143,329 +166,320 @@
|
||||
"resolved": "1.0.8",
|
||||
"contentHash": "Wp2F7BamQ2Q/7Hk834nV9vRQapgcr8kgv9Jvfm8J3D0IhDqZMMl+a2yxUq5ltJitvXvQfB8W6K4F4fCbw/P6YQ=="
|
||||
},
|
||||
"MessagePack": {
|
||||
"MessagePackAnalyzer": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.5.187",
|
||||
"contentHash": "uW4j8m4Nc+2Mk5n6arOChavJ9bLjkis0qWASOj2h2OwmfINuzYv+mjCHUymrYhmyyKTu3N+ObtTXAY4uQ7jIhg==",
|
||||
"dependencies": {
|
||||
"MessagePack.Annotations": "2.5.187",
|
||||
"Microsoft.NET.StringTools": "17.6.3"
|
||||
}
|
||||
},
|
||||
"MessagePack.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.5.198",
|
||||
"contentHash": "3U9OvqQGTra+Mz1k1zfNAScSdNHobnqtQ51qdMGUZppkNDZJl0X/igq6Qz5zDBLEZoYqZrFtZwFx6wBJHHI8BA=="
|
||||
"resolved": "3.1.4",
|
||||
"contentHash": "CTaSsN/liJ7MhLCAB7Z4ZLBNuVGCq9lt2BT/cbrc9vzGv89yK3CqIA+z9T19a11eQYl9etZHL6MQJgCqECRVpg=="
|
||||
},
|
||||
"Microsoft.AspNetCore.Connections.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "mONfcKx7I4h6Rg+3b20bRyuy/GWz2yLsCNzKKqh1X4OfxnI7l0rdSxBwO203ebZFhjrdXnqMl7Op0N1FQ1Q5DQ==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "bb9kWEjwFHfOxcflTdFjcYY0Cnvc0iqnEt5qQ3O73iKPx8v1jkc/LU5wohOCzIrhWsXREaLtQV1Y15SBISNJiA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Features": "9.0.8"
|
||||
"Microsoft.Extensions.Features": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Connections.Client": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "Ob2n+H3358kvubgXu9hY95MZB6X91PUGJvtWaHGEX7eZ+9bYdUCYs57ukJiIziH+aD9yO9e36bgKIT1WJEtfmA==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "Ciahjlswi4hylLMfI/gNhNYPuBp0BMP2E/vcG3J7U+wZqSSq8tEeHahEG6h9RF5zPFEISroGOIM6l1uxCP1BfA==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Connections.Common": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8",
|
||||
"System.Net.ServerSentEvents": "9.0.8"
|
||||
"Microsoft.AspNetCore.Http.Connections.Common": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Options": "9.0.9",
|
||||
"System.Net.ServerSentEvents": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Connections.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "150BRlecnjL+6C+yw/bDP49+ONh7BmaJZTRik6KtbaS+cWnEDVXnhE5PTKlFqCYBD5T8wdjKoF5+lzKHJUK47A==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "S9ssCBd7Kc0sZN5kiHgvikyNqSI5bMyWYxrfl/Hu1S8ymwEhXFiDf2yFhgkapIiIHOXHjF7mgma2Gqmglivo5g==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Connections.Abstractions": "9.0.8"
|
||||
"Microsoft.AspNetCore.Connections.Abstractions": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.SignalR.Client.Core": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "EZ4KaPVQ9rDxZYWQ1sYiPfXEbomhKwp5Fn/0q1XtOgTilV/nN2lgA06KTofVJSeVVRwYdlZggflcQNcKCG0xcg==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "DRSFXVLcgCkYGBb6vtBgYUec+QnCbtQnMabk4p5zbtrqsJ19Uvfk36zNeJKgsBGmNt5HouWPuuB7KJP+IHDAOw==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.SignalR.Common": "9.0.8",
|
||||
"Microsoft.AspNetCore.SignalR.Protocols.Json": "9.0.8",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.8",
|
||||
"Microsoft.Extensions.Logging": "9.0.8",
|
||||
"System.Threading.Channels": "9.0.8"
|
||||
"Microsoft.AspNetCore.SignalR.Common": "9.0.9",
|
||||
"Microsoft.AspNetCore.SignalR.Protocols.Json": "9.0.9",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.9",
|
||||
"Microsoft.Extensions.Logging": "9.0.9",
|
||||
"System.Threading.Channels": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.SignalR.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "oNOEDf2UGLU63Qi7LB8OJdfG1CGybVO34bhotpkvAQUJ5zH8Ewf7EvqeHlUgg6cVyrdC+vewOFxTysw212FTyw==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "Fv/0TLXCOSpLsgHvL/tMJh4RpU/Ew7p9xET5VGOFjyCLkeZTNeZivzdZ0lHgKpSsQPmxvS45Csuj3qbr1O8zSw==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Connections.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8"
|
||||
"Microsoft.AspNetCore.Connections.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Options": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.SignalR.Protocols.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "9LtBkzS2iYOSiUx1NDI91abM5xxD5MUYtdlvwCtMMr6YdsMzHvDUrgPK2N3hpYE94vmj0srt423Kwd1aOqmGPg==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "8X46a+p6AHdMDs1gNxTzQ+8rzb+/GetBmWgymUCbS8sNi2XQLlPg2jNRWykhIxqIh3UbDYV9cKe4SDLsFYSRtw==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.SignalR.Common": "9.0.8"
|
||||
"Microsoft.AspNetCore.SignalR.Common": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "6m+8Xgmf8UWL0p/oGqBM+0KbHE5/ePXbV1hKXgC59zEv0aa0DW5oiiyxDbK5kH5j4gIvyD5uWL0+HadKBJngvQ==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "w87wF/90/VI0ZQBhf4rbMEeyEy0vi2WKjFmACsNAKNaorY+ZlVz7ddyXkbADvaWouMKffNmR0yQOGcrvSSvKGg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Primitives": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "yNou2KM35RvzOh4vUFtl2l33rWPvOCoba+nzEDJ+BgD8aOL/jew4WPCibQvntRfOJ2pJU8ARygSMD+pdjvDHuA==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "p5RKAY9POvs3axwA/AQRuJeM8AHuE8h4qbP1NxQeGm0ep46aXz1oCLAp/oOYxX1GsjStgdhHrN3XXLLXr0+b3w==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
"Microsoft.Extensions.Primitives": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "0vK9DnYrYChdiH3yRZWkkp4x4LbrfkWEdBc5HOsQ8t/0CLOWKXKkkhOE8A1shlex0hGydbGrhObeypxz/QTm+w==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "6SIp/6Bngk4jm2W36JekZbiIbFPdE/eMUtrJEqIqHGpd1zar3jvgnwxnpWQfzUiGrkyY8q8s6V82zkkEZozghA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.CommandLine": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "vB6eDQ5prED5jHBqmSDNYzlCXsTSylYY7co9c7guhnz0zhx+jZ8BTHgO7y/Wl1dV2jAO15mKNWuyHRIRtWwGQg==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "9bzGOcHoTi8ijrj0MHh5qUY6n9CuittZUqEOj5iE0ZJoSCfG0BI9nhcpd8MC9bOOgjZW5OeizKO8rgta9lSVyA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8"
|
||||
"Microsoft.Extensions.Configuration": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "9qileEYXDodlPN9DfPd5sHSfU2nSrI1r5BHVqLaLyb/7mPi335cy4ar/0ix4tXb2Aer/Pu4e5/zdwxt7lrtSyQ==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "AB8suTh4STAMGDkPer5vL0YNp09eplvbkIbOfFJ1z8D1zOiFF8Hipk9FhCLU4Ea6TosWmGrK30ZIUO9KvAeFcg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8"
|
||||
"Microsoft.Extensions.Configuration": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.FileExtensions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "2jgx58Jpk3oKT7KRn8x/cFf3QDTjQP+KUbyBnynAcB2iBx1Eq9EdNMCu0QEbYuaZOaQru/Kwdffary+hn58Wwg==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "fvgubCs++wTowHWuQ5TAyZV0S6ldA59U+tBVqFr4/WLd0oEf6ESbdBN2CFaVdn4sZqnarqMnl2O3++RG/Jrf/w==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Physical": "9.0.8",
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
"Microsoft.Extensions.Configuration": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.FileProviders.Physical": "9.0.9",
|
||||
"Microsoft.Extensions.Primitives": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Json": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "vjxzcnL7ul322+kpvELisXaZl8/5MYs6JfI9DZLQWsao1nA/4FL48yPwDK986hbJTWc64JxOOaMym0SQ/dy32w==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "PiPYo1GTinR2ECM80zYdZUIFmde6jj5DryXUcOJg3yIjh+KQMQr42e+COD03QUsUiqNkJk511wVTnVpTm2AVZA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.FileExtensions": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.8"
|
||||
"Microsoft.Extensions.Configuration": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.FileExtensions": "9.0.9",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.UserSecrets": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "UgH18nQkuMJgxjn1539I83N6LhnKQlLhQm3ppe+PGsFpYsC6eGpF/1KvDRm/bmqsrg0NXhurrv4k2r0e8vWX/Q==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "bFaNxfU8gQJX3K/Dd6XT0YIJ5ZVihdAY6Z02p2nVTUHjUsaWflLIucZOgB/ecSNnN3zbbBEf1oFC7q5NHTZIHw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Json": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Physical": "9.0.8"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.Json": "9.0.9",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.FileProviders.Physical": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "JJjI2Fa+QtZcUyuNjbKn04OjIUX5IgFGFu/Xc+qvzh1rXdZHLcnqqVXhR4093bGirTwacRlHiVg1XYI9xum6QQ==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "zQV2WOSP+3z1EuK91ULxfGgo2Y75bTRnmJHp08+w/YXAyekZutX/qCd88/HOMNh35MDW9mJJJxPpMPS+1Rww8A==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "xY3lTjj4+ZYmiKIkyWitddrp1uL5uYiweQjqo4BKBw01ZC4HhcfgLghDpPZcUlppgWAFqFy9SgkiYWOMx365pw=="
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "/hymojfWbE9AlDOa0mczR44m00Jj+T3+HZO0ZnVTI032fVycI0ZbNOVFP6kqZMcXiLSYXzR2ilcwaRi6dzeGyA=="
|
||||
},
|
||||
"Microsoft.Extensions.Diagnostics": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "BKkLCFXzJvNmdngeYBf72VXoZqTJSb1orvjdzDLaGobicoGFBPW8ug2ru1nnEewMEwJzMgnsjHQY8EaKWmVhKg==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "gtzl9SD6CvFYOb92qEF41Z9rICzYniM342TWbbJwN3eLS6a5fCLFvO1pQGtpMSnP3h1zHXupMEeKSA9musWYCQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.8"
|
||||
"Microsoft.Extensions.Configuration": "9.0.9",
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "UDY7blv4DCyIJ/8CkNrQKLaAZFypXQavRZ2DWf/2zi1mxYYKKw2t8AOCBWxNntyPZHPGhtEmL3snFM98ADZqTw==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "YHGmxccrVZ2Ar3eI+/NdbOHkd1/HzrHvmQ5yBsp0Gl7jTyBe6qcXNYjUt9v9JIO+Z14la44+YYEe63JSqs1fYg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Options": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Features": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "oyPrbpRFa0uWik3PMwpK1mbAr+inZTEkaBsnMjHyT74YN0ot6knA7OnyFLg+oM4MwW5PZIS4HHW9efy0+gj+oQ=="
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "0MPp/tJ9cFsJCzEKG5g4fUSpwG7bAt9JGADPx5eAThWa9ii2wfOa6f3yxi1IoXWsWqVcq4xlRGrdUAZlpIYalw=="
|
||||
},
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "4zZbQ4w+hCMm9J+z5NOj3giIPT2MhZxx05HX/MGuAmDBbjOuXlYIIRN+t4V6OLxy5nXZIcXO+dQMB/OWubuDkw==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "M1ZhL9QkBQ/k6l/Wjgcli5zrV86HzytQ+gQiNtk9vs9Ge1fb17KKZil9T6jd15p2x/BGfXpup7Hg55CC0kkfig==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
"Microsoft.Extensions.Primitives": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.FileProviders.Physical": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "FlOe2i7UUIfY0l0ChaIYtlXjdWWutR4DMRKZaGD6z4G1uVTteFkbBfxUIoi1uGmrZQxXe/yv/cfwiT0tK2xyXA==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "sRrPtEwbK23OCFOQ36Xn6ofiB0/nl54/BOdR7lJ/Vwg3XlyvUdmyXvFUS1EU5ltn+sQtbcPuy1l0hsysO8++SQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.FileSystemGlobbing": "9.0.8",
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.FileSystemGlobbing": "9.0.9",
|
||||
"Microsoft.Extensions.Primitives": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.FileSystemGlobbing": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "96Ub5LmwYfIGVoXkbe4kjs+ivK6fLBTwKJAOMfUNV0R+AkZRItlgROFqXEWMUlXBTPM1/kKu26Ueu5As6RDzJA=="
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "iQAgORaVIlkhcpxFnVEfjqNWfQCwBEEH7x2IanTwGafA6Tb4xiBoDWySTxUo3MV2NUV/PmwS/8OhT/elPnJCnw=="
|
||||
},
|
||||
"Microsoft.Extensions.Hosting.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "WNrad20tySNCPe9aJUK7Wfwh+RiyLF+id02FKW8Qfc+HAzNQHazcqMXAbwG/kmbS89uvan/nKK1MufkRahjrJA==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "ORA4dICNz7cuwupPkjXpSuoiK6GMg0aygInBIQCCFEimwoHntRKdJqB59faxq2HHJuTPW3NsZm5EjN5P5Zh6nQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "Z/7ze+0iheT7FJeZPqJKARYvyC2bmwu3whbm/48BJjdlGVvgDguoCqJIkI/67NkroTYobd5geai1WheNQvWrgA==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "MaCB0Y9hNDs4YLu3HCJbo199WnJT8xSgajG1JYGANz9FkseQ5f3v/llu3HxLI6mjDlu7pa7ps9BLPWjKzsAAzQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8"
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Options": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "pYnAffJL7ARD/HCnnPvnFKSIHnTSmWz84WIlT9tPeQ4lHNiu0Az7N/8itihWvcF8sT+VVD5lq8V+ckMzu4SbOw==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "FEgpSF+Z9StMvrsSViaybOBwR0f0ZZxDm8xV5cSOFiXN/t+ys+rwAlTd/6yG7Ld1gfppgvLcMasZry3GsI9lGA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Configuration": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "Us4evDN3lbp1beVgrpxkSXKrbntVGAK+YbSo9P9driiU9PK05+ShhgesJ3aj7SuDfr3mqqcEgrMJ87Vu8t5dhw==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "Abuo+S0Sg+Ke6vzSh5Ell+lwJJM+CEIqg1ImtWnnqF6a/ibJkQnmFJi4/ekEw/0uAcdFKJXtGV7w6cFN0nyXeg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Binder": "9.0.8",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.8"
|
||||
"Microsoft.Extensions.Configuration": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.Binder": "9.0.9",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Logging": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Options": "9.0.9",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Console": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "mPp9xB9MjiPuodh9z/+6zEGNj2kSVeXQtdbIBHlhUYqxX22gzJkx0ycPY42q4/OT/SzFV/TJ989Pa3sA/8ZBeA==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "x3+W7IfW9Tg3sV+sU9N1039M4CqklaAecwhz9qNtjOCBdmg7h96JaL+NAvhYgZgweVJTJaxAvuO8I+ZZehE7Pg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Configuration": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Logging": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.Configuration": "9.0.9",
|
||||
"Microsoft.Extensions.Options": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Debug": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "OwHQFVITsONEoizShc1yNYTUvMq0kT9j/LhwAKMsA7OZqtrBXuqjosbSvzkJZ9o+KWAozDh5Y1Vtpe5p/8/1qA==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "q8IbjIzTjfaGfuf9LAuG3X9BytAWj2hWhLU61rEkit847oaSSbcdx/yybY3yL9RgVG1u9ctk7kbCv18M+7Fi6Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Logging": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.EventLog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "/gMwlll21UJcaXlitUqd+rs9jH36EJz5BpFVPshyOqz5u0qyV1pFnTWm5vhyx+g6gwVYENSLgpazR1urNv83xw==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "1SX5+mv16SBb5NrtLNxIvUt8PHbdvDloZazQdxz1CNM39jG7yeF6olH3sceQ4ONF0oVD5mVUsTag0iVX4xgyog==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8",
|
||||
"System.Diagnostics.EventLog": "9.0.8"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Logging": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Options": "9.0.9",
|
||||
"System.Diagnostics.EventLog": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.EventSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "aGMFc/1P+315d07iyxSe6lEoZ0JjOPJ+Mfv9rrV2PvR2DFu1/pSi/SItHw1iChJOZgslNKJE97g1a9nLX3qQYA==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "rGQi5mImot7tTFxj1tQWknWjOBHX1+gsX1WLmQNl5WHr4Sx1kXUBGDuRUjfx4c8pe/hcYHdalAmgk7RdusW6Jw==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Logging": "9.0.8",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8",
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Logging": "9.0.9",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Options": "9.0.9",
|
||||
"Microsoft.Extensions.Primitives": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "OmTaQ0v4gxGQkehpwWIqPoEiwsPuG/u4HUsbOFoWGx4DKET2AXzopnFe/fE608FIhzc/kcg2p8JdyMRCCUzitQ==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "loxGGHE1FC2AefwPHzrjPq7X92LQm64qnU/whKfo6oWaceewPUVYQJBJs3S3E2qlWwnCpeZ+dGCPTX+5dgVAuQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Primitives": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "eW2s6n06x0w6w4nsX+SvpgsFYkl+Y0CttYAt6DKUXeqprX+hzNqjSfOh637fwNJBg7wRBrOIRHe49gKiTgJxzQ==",
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "n4DCdnn2qs6V5U06Sx62FySEAZsJiJJgOzrPHDh9hPK7c2W8hEabC76F3Re3tGPjpiKa02RvB6FxZyxo8iICzg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Configuration.Binder": "9.0.8",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
|
||||
"Microsoft.Extensions.Options": "9.0.8",
|
||||
"Microsoft.Extensions.Primitives": "9.0.8"
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Configuration.Binder": "9.0.9",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9",
|
||||
"Microsoft.Extensions.Options": "9.0.9",
|
||||
"Microsoft.Extensions.Primitives": "9.0.9"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "tizSIOEsIgSNSSh+hKeUVPK7xmTIjR8s+mJWOu1KXV3htvNQiPMFRMO17OdI1y/4ZApdBVk49u/08QGC9yvLug=="
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "z4pyMePOrl733ltTowbN565PxBw1oAr8IHmIXNDiDqd22nFpYltX9KhrNC/qBWAG1/Zx5MHX+cOYhWJQYCO/iw=="
|
||||
},
|
||||
"Microsoft.IdentityModel.Abstractions": {
|
||||
"type": "Transitive",
|
||||
@@ -499,34 +513,32 @@
|
||||
},
|
||||
"Microsoft.NET.StringTools": {
|
||||
"type": "Transitive",
|
||||
"resolved": "17.6.3",
|
||||
"contentHash": "N0ZIanl1QCgvUumEL1laasU0a7sOE5ZwLZVTn0pAePnfhq8P7SvTjF8Axq+CnavuQkmdQpGNXQ1efZtu5kDFbA=="
|
||||
"resolved": "17.11.4",
|
||||
"contentHash": "mudqUHhNpeqIdJoUx2YDWZO/I9uEDYVowan89R6wsomfnUJQk6HteoQTlNjZDixhT2B4IXMkMtgZtoceIjLRmA=="
|
||||
},
|
||||
"System.Diagnostics.EventLog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "gebRF3JLLJ76jz1CQpvwezNapZUjFq20JQsaGHzBH0DzlkHBLpdhwkOei9usiOkIGMwU/L0ALWpNe1JE+5/itw=="
|
||||
},
|
||||
"System.IO.Pipelines": {
|
||||
"type": "Transitive",
|
||||
"resolved": "6.0.3",
|
||||
"contentHash": "ryTgF+iFkpGZY1vRQhfCzX0xTdlV3pyaTTqRu2ETbEv+HlV7O6y7hyQURnghNIXvctl5DuZ//Dpks6HdL/Txgw=="
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "wpsUfnyv8E5K4WQaok6weewvAbQhcLwXFcHBm5U0gdEaBs85N//ssuYvRPFWwz2rO/9/DFP3A1sGMzUFBj8y3w=="
|
||||
},
|
||||
"System.Net.ServerSentEvents": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "wrpra4YvKXL7VdsQMKPcPxyA8pXK22LcxaKGA8oEndgjLZ1ZSdKXTxEA2cPvvNpMEUBwZlgJ6oZYQ8aJcpapPg=="
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "zEISfefh8BYD5m+GMsYJnodiTaz2fDBEOrLgYH7VsQhMIzNkcuSsg9Df/d3zywYX5ohCyCJ5AOax50XLKnXyjw=="
|
||||
},
|
||||
"System.Threading.Channels": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.8",
|
||||
"contentHash": "kpvkzWJoHR9os3/4LL5feaTTLD92+XzTqPyYLU2tw2BoJ4MrWCfkjGXtL7MsdpV/20e1+SamCbrPj2L9ptwgBA=="
|
||||
"resolved": "9.0.9",
|
||||
"contentHash": "AEgG1sVSp3H7oNYoXi350GeUnZdnP38EQHNK0kN5HCC6KoVoEkuTVr40lrVag99pd/NBr3tdNjPFElLLPI5BQg=="
|
||||
},
|
||||
"maresynchronos.api": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"MessagePack.Annotations": "[2.5.198, )"
|
||||
"MessagePack.Annotations": "[2.5.129, )"
|
||||
}
|
||||
},
|
||||
"snowcloaksync": {
|
||||
"type": "Project"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
3
Penumbra.Api/.gitignore
vendored
3
Penumbra.Api/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
bin/
|
||||
obj/
|
||||
.vs/
|
@@ -1,66 +0,0 @@
|
||||
using Penumbra.Api.Enums;
|
||||
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
/// <summary> API methods pertaining to collection management. </summary>
|
||||
public interface IPenumbraApiCollection
|
||||
{
|
||||
/// <returns> A list of the GUIDs of all currently installed collections together with their display names, excluding the empty collection. </returns>
|
||||
public Dictionary<Guid, string> GetCollections();
|
||||
|
||||
/// <summary> Returns all collections for which either
|
||||
/// <list type="number">
|
||||
/// <item> the name is equal to the given identifier up to case, </item>
|
||||
/// <item> the identifier is parsable to a GUID and the GUID corresponds to an existing collection, </item>
|
||||
/// <item> or the identifier is at least 8 characters long and the GUID as a hex-string starts with the identifier. </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public List<(Guid Id, string Name)> GetCollectionsByIdentifier(string identifier);
|
||||
|
||||
/// <returns>A dictionary of affected items in <paramref name="collectionId"/> via GUID and known objects or null.</returns>
|
||||
public Dictionary<string, object?> GetChangedItemsForCollection(Guid collectionId);
|
||||
|
||||
/// <returns> The GUID and name of the collection assigned to the given <paramref name="type"/>, the empty GUID for the empty collection, or null if nothing is assigned. </returns>
|
||||
public (Guid Id, string Name)? GetCollection(ApiCollectionType type);
|
||||
|
||||
/// <returns>Return whether the object at <paramref name="gameObjectIdx" /> produces a valid identifier, if the identifier has a collection assigned, and the collection that affects the object.</returns>
|
||||
public (bool ObjectValid, bool IndividualSet, (Guid Id, string Name) EffectiveCollection) GetCollectionForObject(int gameObjectIdx);
|
||||
|
||||
/// <summary>
|
||||
/// Set a collection by GUID for a specific type.
|
||||
/// </summary>
|
||||
/// <param name="type">The collection type to set.</param>
|
||||
/// <param name="collectionId">The GUID of the collection to set it to, null to remove the association if allowed. </param>
|
||||
/// <param name="allowCreateNew">Allow only setting existing types or also creating an unset type.</param>
|
||||
/// <param name="allowDelete">Allow deleting existing collections if <paramref name="collectionId"/> is empty.</param>
|
||||
/// <returns>InvalidArgument if type is invalid,
|
||||
/// NothingChanged if the new collection is the same as the old,<br />
|
||||
/// AssignmentDeletionDisallowed if <paramref name="collectionId"/> is null and <paramref name="allowDelete"/> is false, and the assignment exists,<br />
|
||||
/// or if Default, Current or Interface would be deleted.<br />
|
||||
/// CollectionMissing if the new collection can not be found,<br />
|
||||
/// AssignmentCreationDisallowed if <paramref name="allowCreateNew"/> is false and the assignment does not exist,<br />
|
||||
/// or Success, as well as the GUID of the previous collection (empty if no assignment existed).
|
||||
/// </returns>
|
||||
public (PenumbraApiEc, (Guid Id, string Name)? OldCollection) SetCollection(ApiCollectionType type, Guid? collectionId, bool allowCreateNew,
|
||||
bool allowDelete);
|
||||
|
||||
/// <summary>
|
||||
/// Set a collection by GUID for a specific game object.
|
||||
/// </summary>
|
||||
/// <param name="gameObjectIdx">The index of the desired game object in the object table.</param>
|
||||
/// <param name="collectionId">The GUID of the collection to set it to, null to remove the association if allowed. </param>
|
||||
/// <param name="allowCreateNew">Allow only setting existing individuals or also creating a new individual assignment.</param>
|
||||
/// <param name="allowDelete">Allow deleting existing individual assignments if <paramref name="collectionId"/> is null.</param>
|
||||
/// <returns>InvalidIdentifier if <paramref name="gameObjectIdx"/> does not produce an existing game object or the object is not identifiable,
|
||||
/// NothingChanged if the new collection is the same as the old,<br />
|
||||
/// AssignmentDeletionDisallowed if <paramref name="collectionId"/> is null and <paramref name="allowDelete"/> is false, and the assignment exists,<br />
|
||||
/// CollectionMissing if the new collection can not be found,<br />
|
||||
/// AssignmentCreationDisallowed if <paramref name="allowCreateNew"/> is false and the assignment does not exist,<br />
|
||||
/// or Success, as well as the name of the previous collection (empty if no assignment existed).</returns>
|
||||
public (PenumbraApiEc, (Guid Id, string Name)? OldCollection) SetCollectionForObject(int gameObjectIdx, Guid? collectionId, bool allowCreateNew,
|
||||
bool allowDelete);
|
||||
|
||||
/// <summary> Obtain a function object that can check if the current collection contains a given changed item by listing the mods changing it. </summary>
|
||||
/// <remarks> Throws an <seealso cref="ObjectDisposedException"/> on invocation if the collection storage is not valid anymore, so clear this on <seealso cref="IpcSubscribers.Disposed"/>. </remarks>
|
||||
public Func<string, (string ModDirectory, string ModName)[]> CheckCurrentChangedItemFunc();
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
using Penumbra.Api.Enums;
|
||||
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
/// <summary> API methods pertaining to the editing of mods or game files. </summary>
|
||||
public interface IPenumbraApiEditing
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert the given texture file into a different type or format and potentially add mip maps.
|
||||
/// </summary>
|
||||
/// <param name="inputFile"> The path to the input file, which may be of .dds, .tex or .png format. </param>
|
||||
/// <param name="outputFile"> The desired output path. Can be the same as input. </param>
|
||||
/// <param name="textureType"> The file type and format to convert the data to. </param>
|
||||
/// <param name="mipMaps"> Whether to add mip maps or not. Ignored for .png. </param>
|
||||
/// <returns> A task for when the conversion is finished or has failed. </returns>
|
||||
public Task ConvertTextureFile(string inputFile, string outputFile, TextureType textureType, bool mipMaps);
|
||||
|
||||
/// <summary>
|
||||
/// Convert the given RGBA32 texture data into a different type or format and potentially add mip maps.
|
||||
/// </summary>
|
||||
/// <param name="rgbaData"> The input byte data for a picture given in RGBA32 format. </param>
|
||||
/// <param name="width"> The width of the input picture. The height is computed from the size of <paramref name="rgbaData"/> and this. </param>
|
||||
/// <param name="outputFile"> The desired output path. Can be the same as input. </param>
|
||||
/// <param name="textureType"> The file type and format to convert the data to. </param>
|
||||
/// <param name="mipMaps"> Whether to add mip maps or not. Ignored for .png. </param>
|
||||
/// <returns> A task for when the conversion is finished or has failed. </returns>
|
||||
public Task ConvertTextureData(byte[] rgbaData, int width, string outputFile, TextureType textureType, bool mipMaps);
|
||||
}
|
@@ -1,52 +0,0 @@
|
||||
using Penumbra.Api.Enums;
|
||||
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
/// <summary> API methods pertaining to the currently tracked game state. </summary>
|
||||
public interface IPenumbraApiGameState
|
||||
{
|
||||
/// <param name="drawObject"></param>
|
||||
/// <returns>The game object associated with the given <paramref name="drawObject">draw object</paramref>
|
||||
/// and the GUID and name of the collection associated with this game object.</returns>
|
||||
public (nint GameObject, (Guid Id, string Name) Collection) GetDrawObjectInfo(nint drawObject);
|
||||
|
||||
/// <summary>
|
||||
/// Obtain the parent game object index for an unnamed cutscene actor by its <paramref name="actorIdx">index</paramref>.
|
||||
/// </summary>
|
||||
/// <param name="actorIdx"></param>
|
||||
/// <returns>The parent game object index.</returns>
|
||||
public int GetCutsceneParentIndex(int actorIdx);
|
||||
|
||||
/// <summary>
|
||||
/// Set the cutscene parent of <paramref name="copyIdx"/> in Penumbras internal state to a new value.
|
||||
/// </summary>
|
||||
/// <param name="copyIdx"> The index of the cutscene actor to be changed. </param>
|
||||
/// <param name="newParentIdx"> The new index of the cutscene actors parent or -1 for no parent. </param>
|
||||
/// <returns> Success when the new parent could be set, or InvalidArgument if either index is out of its respective range. </returns>
|
||||
/// <remarks>
|
||||
/// Checks that the new parent exists as a game object if the value is not -1 before assigning. If it does not, InvalidArgument is given, too.
|
||||
/// Please only use this for good reason and if you know what you are doing, probably only for actor copies you actually create yourself.
|
||||
/// </remarks>
|
||||
public PenumbraApiEc SetCutsceneParentIndex(int copyIdx, int newParentIdx);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a character base is created and a corresponding gameObject could be found,
|
||||
/// before the Draw Object is actually created, so customize and equipdata can be manipulated beforehand.
|
||||
/// </summary>
|
||||
/// <returns><inheritdoc cref="CreatingCharacterBaseDelegate"/></returns>
|
||||
public event CreatingCharacterBaseDelegate? CreatingCharacterBase;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered after a character base was created if a corresponding gameObject could be found,
|
||||
/// so you can apply flag changes after finishing.
|
||||
/// </summary>
|
||||
/// <returns><inheritdoc cref="CreatedCharacterBaseDelegate"/></returns>
|
||||
public event CreatedCharacterBaseDelegate? CreatedCharacterBase;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered whenever a resource is redirected by Penumbra for a specific, identified game object.
|
||||
/// Does not trigger if the resource is not requested for a known game object.
|
||||
/// </summary>
|
||||
/// <returns><inheritdoc cref="GameObjectResourceResolvedDelegate"/></returns>
|
||||
public event GameObjectResourceResolvedDelegate? GameObjectResourceResolved;
|
||||
}
|
@@ -1,41 +0,0 @@
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
/// <summary> The entire API. </summary>
|
||||
public interface IPenumbraApi : IPenumbraApiBase
|
||||
{
|
||||
/// <inheritdoc cref="IPenumbraApiCollection"/>
|
||||
public IPenumbraApiCollection Collection { get; }
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiEditing"/>
|
||||
public IPenumbraApiEditing Editing { get; }
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiGameState"/>
|
||||
public IPenumbraApiGameState GameState { get; }
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiMeta"/>
|
||||
public IPenumbraApiMeta Meta { get; }
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiMods"/>
|
||||
public IPenumbraApiMods Mods { get; }
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiModSettings"/>
|
||||
public IPenumbraApiModSettings ModSettings { get; }
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiPluginState"/>
|
||||
public IPenumbraApiPluginState PluginState { get; }
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiRedraw"/>
|
||||
public IPenumbraApiRedraw Redraw { get; }
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiResolve"/>
|
||||
public IPenumbraApiResolve Resolve { get; }
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiResourceTree"/>
|
||||
public IPenumbraApiResourceTree ResourceTree { get; }
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiTemporary"/>
|
||||
public IPenumbraApiTemporary Temporary { get; }
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiUi"/>
|
||||
public IPenumbraApiUi Ui { get; }
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
/// <summary> Base interface for the API that is always available, regardless of version. </summary>
|
||||
public interface IPenumbraApiBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The API version is staggered in two parts.
|
||||
/// The major/Breaking version only increments if there are changes breaking backwards compatibility.
|
||||
/// The minor/Feature version increments any time there is something added
|
||||
/// and resets when Breaking is incremented.
|
||||
/// </summary>
|
||||
public (int Breaking, int Feature) ApiVersion { get; }
|
||||
|
||||
/// <summary> Whether the API is still usable. </summary>
|
||||
public bool Valid { get; }
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
/// <summary> API methods pertaining to current metadata manipulations. </summary>
|
||||
public interface IPenumbraApiMeta
|
||||
{
|
||||
/// <returns>A base64 encoded, zipped json-string with a prepended version-byte of the current manipulations
|
||||
/// in the collection currently associated with the player.</returns>
|
||||
public string GetPlayerMetaManipulations();
|
||||
|
||||
/// <returns>A base64 encoded, zipped json-string with a prepended version-byte of the current manipulations
|
||||
/// in the given collection applying to the given game object or the default collection if it does not exist.</returns>
|
||||
public string GetMetaManipulations(int gameObjectIdx);
|
||||
}
|
@@ -1,77 +0,0 @@
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Api.Helpers;
|
||||
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
/// <summary> API methods pertaining to the management of mod settings. </summary>
|
||||
public interface IPenumbraApiModSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Obtain the potential settings of a mod given by its <paramref name="modDirectory" /> name or <paramref name="modName" />.
|
||||
/// </summary>
|
||||
/// <returns>A dictionary of group names to lists of option names and the group type. Null if the mod could not be found.</returns>
|
||||
public AvailableModSettings? GetAvailableModSettings(string modDirectory, string modName);
|
||||
|
||||
/// <summary>
|
||||
/// Obtain the enabled state, the priority, the settings of a mod given by its <paramref name="modDirectory" /> name or <paramref name="modName" /> in the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="collectionId">Specify the collection.</param>
|
||||
/// <param name="modDirectory">Specify the mod via its directory name.</param>
|
||||
/// <param name="modName">Specify the mod via its (non-unique) display name.</param>
|
||||
/// <param name="ignoreInheritance">Whether the settings need to be from the given collection or can be inherited from any other by it. (True: given collection only)</param>
|
||||
/// <param name="ignoreTemporary"> Whether the settings need to be actual settings or can be temporary. </param>
|
||||
/// <param name="key"> The key for the settings lock. If <paramref name="ignoreTemporary"/> is false, settings with a key greater than 0 that is different from this will be ignored. </param>
|
||||
/// <returns>ModMissing, CollectionMissing or Success. <para />
|
||||
/// On Success, a tuple of Enabled State, Priority, a dictionary of option group names and lists of enabled option names and a bool whether the settings are inherited (true) or not.</returns>
|
||||
public (PenumbraApiEc, (bool, int, Dictionary<string, List<string>>, bool, bool)?) GetCurrentModSettingsWithTemp(Guid collectionId,
|
||||
string modDirectory, string modName, bool ignoreInheritance, bool ignoreTemporary, int key);
|
||||
|
||||
/// <inheritdoc cref="GetCurrentModSettingsWithTemp"/>
|
||||
public (PenumbraApiEc, (bool, int, Dictionary<string, List<string>>, bool)?) GetCurrentModSettings(Guid collectionId,
|
||||
string modDirectory, string modName, bool ignoreInheritance);
|
||||
|
||||
/// <summary> Obtain the enabled state, the priority, the settings of all mods in the specified collection. </summary>
|
||||
/// <param name="collectionId"> Specify the collection. </param>
|
||||
/// <param name="ignoreInheritance"> Whether the settings need to be from the given collection or can be inherited from any other by it. (True: given collection only) </param>
|
||||
/// <param name="ignoreTemporary"> Whether the settings need to be actual settings or can be temporary. </param>
|
||||
/// <param name="key"> The key for the settings lock. If <paramref name="ignoreTemporary"/> is false, settings with a key greater than 0 that is different from this will be ignored. </param>
|
||||
/// <returns> CollectionMissing or Success, on Success, a dictionary of mod directory names to a tuple of (Enabled, Priority, Settings, Inherited, Temporary). Mods that have no settings at all are left out. </returns>
|
||||
public (PenumbraApiEc, Dictionary<string, (bool, int, Dictionary<string, List<string>>, bool, bool)>?) GetAllModSettings(Guid collectionId,
|
||||
bool ignoreInheritance, bool ignoreTemporary, int key);
|
||||
|
||||
/// <summary> Try to set the inheritance state of a mod in a collection. </summary>
|
||||
/// <returns>ModMissing, CollectionMissing, InvalidArgument (GUID is nil), NothingChanged or Success.</returns>
|
||||
public PenumbraApiEc TryInheritMod(Guid collectionId, string modDirectory, string modName, bool inherit);
|
||||
|
||||
/// <summary> Try to set the enabled state of a mod in a collection. </summary>
|
||||
/// <returns>ModMissing, CollectionMissing, InvalidArgument (GUID is nil), NothingChanged or Success.</returns>
|
||||
public PenumbraApiEc TrySetMod(Guid collectionId, string modDirectory, string modName, bool enabled);
|
||||
|
||||
/// <summary> Try to set the priority of a mod in a collection. </summary>
|
||||
/// <returns>ModMissing, CollectionMissing, InvalidArgument (GUID is nil), NothingChanged or Success.</returns>
|
||||
public PenumbraApiEc TrySetModPriority(Guid collectionId, string modDirectory, string modName, int priority);
|
||||
|
||||
/// <summary> Try to set a specific option group of a mod in the given collection to a specific value. </summary>
|
||||
/// <remarks>Removes inheritance. Single Selection groups should provide a single option, Multi Selection can provide multiple.
|
||||
/// If any setting can not be found, it will not change anything.</remarks>
|
||||
/// <returns>ModMissing, CollectionMissing, OptionGroupMissing, SettingMissing, InvalidArgument (GUID is nil), NothingChanged or Success.</returns>
|
||||
public PenumbraApiEc TrySetModSetting(Guid collectionId, string modDirectory, string modName, string optionGroupName, string optionName);
|
||||
|
||||
/// <inheritdoc cref="TrySetModSetting"/>
|
||||
public PenumbraApiEc TrySetModSettings(Guid collectionId, string modDirectory, string modName, string optionGroupName,
|
||||
IReadOnlyList<string> optionNames);
|
||||
|
||||
/// <summary> This event gets fired when any setting in any collection changes. </summary>
|
||||
/// <returns><inheritdoc cref="ModSettingChangedDelegate" /></returns>
|
||||
public event ModSettingChangedDelegate? ModSettingChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Copy all current settings for a mod to another mod.
|
||||
/// </summary>
|
||||
/// <param name="collectionId">Specify the collection to work in, leave null to do it in all collections.</param>
|
||||
/// <param name="modDirectoryFrom">Specify the mod to take the settings from via its directory name.</param>
|
||||
/// <param name="modDirectoryTo">Specify the mod to put the settings on via its directory name. If the mod does not exist, it will be added as unused settings.</param>
|
||||
/// <returns>CollectionMissing if collectionName is not empty but does not exist or Success.</returns>
|
||||
/// <remarks>If the target mod exists, the settings will be fixed before being applied. If the source mod does not exist, it will use unused settings if available and remove existing settings otherwise.</remarks>
|
||||
public PenumbraApiEc CopyModSettings(Guid? collectionId, string modDirectoryFrom, string modDirectoryTo);
|
||||
}
|
@@ -1,78 +0,0 @@
|
||||
using Penumbra.Api.Enums;
|
||||
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
/// <summary> API methods pertaining to management of mods. </summary>
|
||||
public interface IPenumbraApiMods
|
||||
{
|
||||
/// <returns>A list of all installed mods. The first string is their directory name, the second string is their mod name.</returns>
|
||||
public Dictionary<string, string> GetModList();
|
||||
|
||||
/// <summary> Try to unpack and install a valid mod file (.pmp, .ttmp, .ttmp2) as if installed manually. </summary>
|
||||
/// <param name="modFilePackagePath">The file that should be unpacked.</param>
|
||||
/// <returns>Success, MissingFile. Success does not indicate successful installing, just successful queueing for install.</returns>
|
||||
public PenumbraApiEc InstallMod(string modFilePackagePath);
|
||||
|
||||
/// <summary> Try to reload an existing mod given by its <paramref name="modDirectory" /> name or <paramref name="modName" />.</summary>
|
||||
/// <remarks>Reload is the same as if triggered by button press and might delete the mod if it is not valid anymore.</remarks>
|
||||
/// <returns>ModMissing if the mod can not be found or Success</returns>
|
||||
public PenumbraApiEc ReloadMod(string modDirectory, string modName);
|
||||
|
||||
/// <summary> Try to add a new mod inside the mod root directory.</summary>
|
||||
/// <remarks>Note that success does only imply a successful call, not a successful mod load.</remarks>
|
||||
/// <param name="modDirectory">The name (not full name) of the mod directory.</param>
|
||||
/// <returns>FileMissing if <paramref name="modDirectory" /> does not exist, InvalidArgument if the path leads outside the root directory, Success otherwise.</returns>
|
||||
public PenumbraApiEc AddMod(string modDirectory);
|
||||
|
||||
/// <summary>Try to delete a mod given by its <paramref name="modDirectory" /> name or <paramref name="modName" />.</summary>
|
||||
/// <remarks>Note that success does only imply a successful call, not successful deletion.</remarks>
|
||||
/// <returns>NothingDone if the mod can not be found, Success otherwise.</returns>
|
||||
public PenumbraApiEc DeleteMod(string modDirectory, string modName);
|
||||
|
||||
/// <summary> Triggers whenever a mod is deleted. </summary>
|
||||
/// <returns>The base directory name of the deleted mod.</returns>
|
||||
public event Action<string>? ModDeleted;
|
||||
|
||||
/// <summary> Triggers whenever a mod is deleted. </summary>
|
||||
/// <returns>The base directory name of the new mod.</returns>
|
||||
public event Action<string>? ModAdded;
|
||||
|
||||
/// <summary> Triggers whenever a mods base name is changed from inside Penumbra. </summary>
|
||||
/// <returns>The previous base directory name of the mod and the new base directory name of the mod.</returns>
|
||||
public event Action<string, string>? ModMoved;
|
||||
|
||||
/// <summary>
|
||||
/// Get the internal full filesystem path including search order for the specified mod
|
||||
/// given by its <paramref name="modDirectory" /> name or <paramref name="modName" />.
|
||||
/// </summary>
|
||||
/// <returns>On Success, the full path, a bool indicating whether the entire path is default (true) or manually set (false),
|
||||
/// and a bool indicating whether the sort order name ignoring the folder path is default (true) or manually set (false).
|
||||
/// Otherwise, returns ModMissing if the mod can not be found.</returns>
|
||||
public (PenumbraApiEc, string, bool, bool) GetModPath(string modDirectory, string modName);
|
||||
|
||||
/// <summary>
|
||||
/// Set the internal search order and filesystem path of the specified mod
|
||||
/// given by its <paramref name="modDirectory" /> name or <paramref name="modName" />
|
||||
/// to the <paramref name="newPath" />.
|
||||
/// </summary>
|
||||
/// <returns>InvalidArgument if <paramref name="newPath" /> is empty, ModMissing if the mod can not be found,
|
||||
/// PathRenameFailed if <paramref name="newPath"/> could not be set or Success.</returns>
|
||||
public PenumbraApiEc SetModPath(string modDirectory, string modName, string newPath);
|
||||
|
||||
/// <summary> Get the overall changed items of a single mod given by its <paramref name="modDirectory"/> name or <paramref name="modName"/>, regardless of settings. </summary>
|
||||
/// <returns> A possibly empty dictionary of affected items and known objects or null. </returns>
|
||||
public Dictionary<string, object?> GetChangedItems(string modDirectory, string modName);
|
||||
|
||||
/// <summary> Get a dictionary of dictionaries to check all mods changed items. </summary>
|
||||
/// <returns> A dictionary of mod identifier to changed item dictionary. </returns>
|
||||
/// <remarks> Throws an <seealso cref="ObjectDisposedException"/> on access if the mod storage is not valid anymore, so clear this on <seealso cref="IpcSubscribers.Disposed"/>. </remarks>
|
||||
public IReadOnlyDictionary<string, IReadOnlyDictionary<string, object?>> GetChangedItemAdapterDictionary();
|
||||
|
||||
/// <summary> Get a list of dictionaries to check all mods changed items. </summary>
|
||||
/// <returns> A list all mods changed item dictionaries. </returns>
|
||||
/// <remarks>
|
||||
/// The order of mods is unspecified, but the same as in GetModList (assuming no changes in mods have taken place between calls). <br/>
|
||||
/// Throws an <seealso cref="ObjectDisposedException"/> on access if the mod storage is not valid anymore, so clear this on <seealso cref="IpcSubscribers.Disposed"/>.
|
||||
/// </remarks>
|
||||
public IReadOnlyList<(string ModDirectory, IReadOnlyDictionary<string, object?> ChangedItems)> GetChangedItemAdapterList();
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
/// <summary> API methods pertaining to Penumbras own state. </summary>
|
||||
public interface IPenumbraApiPluginState
|
||||
{
|
||||
/// <returns> The full path of the current penumbra root directory. </returns>
|
||||
public string GetModDirectory();
|
||||
|
||||
/// <returns> The entire current penumbra configuration as a json encoded string. </returns>
|
||||
public string GetConfiguration();
|
||||
|
||||
/// <summary>
|
||||
/// Fired whenever a mod directory change is finished.
|
||||
/// </summary>
|
||||
/// <returns>The full path of the mod directory and whether Penumbra treats it as valid.</returns>
|
||||
public event Action<string, bool>? ModDirectoryChanged;
|
||||
|
||||
/// <returns>True if Penumbra is enabled, false otherwise.</returns>
|
||||
public bool GetEnabledState();
|
||||
|
||||
/// <summary>
|
||||
/// Fired whenever the enabled state of Penumbra changes.
|
||||
/// </summary>
|
||||
/// <returns>True if the new state is enabled, false if the new state is disabled</returns>
|
||||
public event Action<bool>? EnabledChange;
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
using Penumbra.Api.Enums;
|
||||
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
/// <summary> API methods pertaining to the redrawing of actors. </summary>
|
||||
public interface IPenumbraApiRedraw
|
||||
{
|
||||
/// <summary>
|
||||
/// Queue redrawing of the actor with the given object <paramref name="gameObjectIndex" />, if it exists, with the given RedrawType <paramref name="setting"/>.
|
||||
/// </summary>
|
||||
public void RedrawObject(int gameObjectIndex, RedrawType setting);
|
||||
|
||||
/// <summary>
|
||||
/// Queue redrawing of all currently available actors with the given RedrawType <paramref name="setting"/>.
|
||||
/// </summary>
|
||||
public void RedrawAll(RedrawType setting);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered whenever a game object is redrawn via Penumbra.
|
||||
/// </summary>
|
||||
/// /<returns><inheritdoc cref="GameObjectRedrawnDelegate"/></returns>
|
||||
public event GameObjectRedrawnDelegate? GameObjectRedrawn;
|
||||
}
|
@@ -1,64 +0,0 @@
|
||||
using Lumina.Data;
|
||||
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
/// <summary> API methods pertaining to the resolving of paths. </summary>
|
||||
public interface IPenumbraApiResolve
|
||||
{
|
||||
/// <summary>
|
||||
/// Resolve a given <paramref name="gamePath" /> via Penumbra using the Base collection.
|
||||
/// </summary>
|
||||
/// <returns>The resolved path, or the given path if Penumbra would not manipulate it.</returns>
|
||||
public string ResolveDefaultPath(string gamePath);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a given <paramref name="gamePath" /> via Penumbra using the Interface collection.
|
||||
/// </summary>
|
||||
/// <returns>The resolved path, or the given path if Penumbra would not manipulate it.</returns>
|
||||
public string ResolveInterfacePath(string gamePath);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a given <paramref name="gamePath" /> via Penumbra using collection applying to the <paramref name="gameObjectIdx"/>
|
||||
/// given by its index in the game object table.
|
||||
/// </summary>
|
||||
/// <remarks>If the object does not exist in the table, the default collection is used.</remarks>
|
||||
/// <returns>The resolved path, or the given path if Penumbra would not manipulate it.</returns>
|
||||
public string ResolveGameObjectPath(string gamePath, int gameObjectIdx);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a given <paramref name="gamePath" /> via Penumbra using the collection currently applying to the player character.
|
||||
/// </summary>
|
||||
/// <returns>The resolved path, or the given path if Penumbra would not manipulate it.</returns>
|
||||
public string ResolvePlayerPath(string gamePath);
|
||||
|
||||
/// <summary>
|
||||
/// Reverse resolves a given local <paramref name="moddedPath" /> into its replacement in form of all applicable game paths
|
||||
/// for the collection applying to the <paramref name="gameObjectIdx"/>th game object in the game object table.
|
||||
/// </summary>
|
||||
/// <remarks>If the object does not exist in the table, the default collection is used.</remarks>
|
||||
/// <returns>A list of game paths resolving to the modded path.</returns>
|
||||
public string[] ReverseResolveGameObjectPath(string moddedPath, int gameObjectIdx);
|
||||
|
||||
/// <summary>
|
||||
/// Reverse resolves a given local <paramref name="moddedPath" /> into its replacement in form of all applicable game paths
|
||||
/// for the collection currently applying to the player character.
|
||||
/// </summary>
|
||||
/// <returns>A list of game paths resolving to the modded path.</returns>
|
||||
public string[] ReverseResolvePlayerPath(string moddedPath);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve all game paths in <paramref name="forward"/> and reserve all paths in <paramref name="reverse"/> at once.
|
||||
/// </summary>
|
||||
/// <param name="forward">Paths to forward-resolve.</param>
|
||||
/// <param name="reverse">Paths to reverse-resolve.</param>
|
||||
/// <returns>A pair of an array of forward-resolved single paths of the same length as <paramref name="forward"/> and an array of arrays of reverse-resolved paths.
|
||||
/// The outer array has the same length as <paramref name="reverse"/> while each inner array can have arbitrary length.</returns>
|
||||
public (string[], string[][]) ResolvePlayerPaths(string[] forward, string[] reverse);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve all game paths in <paramref name="forward"/> and reserve all paths in <paramref name="reverse"/> at once asynchronously.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="ResolvePlayerPaths"/>
|
||||
/// <remarks> Can be called from outside of framework. Can theoretically produce incoherent state when collections change during evaluation. </remarks>
|
||||
public Task<(string[], string[][])> ResolvePlayerPathsAsync(string[] forward, string[] reverse);
|
||||
}
|
@@ -1,73 +0,0 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Api.Helpers;
|
||||
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
/// <summary> API methods pertaining to the tracking of resources in use by actors. </summary>
|
||||
public interface IPenumbraApiResourceTree
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the given game objects' resources, as dictionaries of actual paths (that may be FS paths for redirected resources, or game paths for swapped or vanilla resources) to game paths.
|
||||
/// </summary>
|
||||
/// <param name="gameObjects"> The game object indices for which to get the resources. </param>
|
||||
/// <returns> An array of resource path dictionaries, of the same length and in the same order as the given game object index array. </returns>
|
||||
/// <remarks> This function is best called right after the game objects are redrawn, as it may fail to resolve paths if relevant mod settings have changed since then. </remarks>
|
||||
public Dictionary<string, HashSet<string>>?[] GetGameObjectResourcePaths(params ushort[] gameObjects);
|
||||
|
||||
/// <summary>
|
||||
/// Get the player and player-owned game objects' resources, as dictionaries of actual paths (that may be FS paths for redirected resources, or game paths for swapped or vanilla resources) to game paths.
|
||||
/// </summary>
|
||||
/// <returns> A dictionary of game object indices to resource path dictionaries. </returns>
|
||||
/// <remarks> This function is best called right after the game objects are redrawn, as it may fail to resolve paths if relevant mod settings have changed since then. </remarks>
|
||||
public Dictionary<ushort, Dictionary<string, HashSet<string>>> GetPlayerResourcePaths();
|
||||
|
||||
/// <summary>
|
||||
/// Get the given game objects' resources of a given type, as dictionaries of resource handles to actual paths and, optionally, names and icons.
|
||||
/// </summary>
|
||||
/// <param name="type"> Type of the resources to get, for example <see cref="ResourceType.Mtrl"/> for materials. </param>
|
||||
/// <param name="withUiData"> Whether to get names and icons along with the paths. </param>
|
||||
/// <param name="gameObjects"> The game object indices for which to get the resources. </param>
|
||||
/// <returns> An array of resource information dictionaries, of the same length and in the same order as the given game object index array. </returns>
|
||||
/// <remarks>
|
||||
/// It is the caller's responsibility to make sure the returned resource handles are still in use on the game object's draw object before using them. <para />
|
||||
/// Also, callers should not use UI data for non-UI purposes.
|
||||
/// </remarks>
|
||||
public GameResourceDict?[] GetGameObjectResourcesOfType(ResourceType type, bool withUiData,
|
||||
params ushort[] gameObjects);
|
||||
|
||||
/// <summary>
|
||||
/// Get the player and player-owned game objects' resources of a given type, as dictionaries of resource handles to actual paths and, optionally, names and icons.
|
||||
/// </summary>
|
||||
/// <param name="type"> Type of the resources to get, for example <see cref="ResourceType.Mtrl"/> for materials. </param>
|
||||
/// <param name="withUiData"> Whether to get names and icons along with the paths. </param>
|
||||
/// <returns> A dictionary of game object indices to resource information dictionaries. </returns>
|
||||
/// <remarks>
|
||||
/// It is the caller's responsibility to make sure the returned resource handles are still in use on the game object's draw object before using them. <para />
|
||||
/// Also, callers should not use UI data for non-UI purposes.
|
||||
/// </remarks>
|
||||
public Dictionary<ushort, GameResourceDict> GetPlayerResourcesOfType(ResourceType type, bool withUiData);
|
||||
|
||||
/// <summary>
|
||||
/// Get the given game objects' resource tree.
|
||||
/// </summary>
|
||||
/// <param name="withUiData"> Whether to get names and icons along with the paths. </param>
|
||||
/// <param name="gameObjects"> The game object indices for which to get the resources. </param>
|
||||
/// <returns> An array of resource tree JObjects, of the same length and in the same order as the given game object index array. </returns>
|
||||
/// <remarks>
|
||||
/// It is the caller's responsibility to make sure the returned resource handles are still in use on the game object's draw object before using them. <para />
|
||||
/// Also, callers should not use UI data for non-UI purposes.
|
||||
/// </remarks>
|
||||
public JObject?[] GetGameObjectResourceTrees(bool withUiData, params ushort[] gameObjects);
|
||||
|
||||
/// <summary>
|
||||
/// Get the player and player-owned game objects' resource trees.
|
||||
/// </summary>
|
||||
/// <param name="withUiData"> Whether to get names and icons along with the paths. </param>
|
||||
/// <returns> A dictionary of game object indices to resource trees. </returns>
|
||||
/// <remarks>
|
||||
/// It is the caller's responsibility to make sure the returned resource handles are still in use on the game object's draw object before using them. <para />
|
||||
/// Also, callers should not use UI data for non-UI purposes.
|
||||
/// </remarks>
|
||||
public Dictionary<ushort, JObject> GetPlayerResourceTrees(bool withUiData);
|
||||
}
|
@@ -1,147 +0,0 @@
|
||||
using Penumbra.Api.Enums;
|
||||
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
/// <summary> API methods pertaining to the management of temporary collections and mods. </summary>
|
||||
public interface IPenumbraApiTemporary
|
||||
{
|
||||
/// <summary> Temporarily set the settings of a mod in a collection to given values. </summary>
|
||||
/// <param name="collectionId"> The collection to manipulate. </param>
|
||||
/// <param name="modDirectory"> Specify the mod via its directory name. </param>
|
||||
/// <param name="modName"> Specify the mod via its (non-unique) display name. </param>
|
||||
/// <param name="inherit"> Whether the mod should be forced to inherit from parent collections (if this is true, the other settings do not matter). </param>
|
||||
/// <param name="enabled"> Whether the mod should be enabled or disabled. </param>
|
||||
/// <param name="priority"> The desired priority for the mod. </param>
|
||||
/// <param name="options"> The new settings for the mod, as a map of Group Name -> All enabled Options (should be only one for single select groups).</param>
|
||||
/// <param name="source"> A string to describe the source of those temporary settings. This is displayed to the user. </param>
|
||||
/// <param name="key"> An optional lock to prevent other plugins and the user from changing these settings. Changes in mod structure will still remove the settings. Use 0 for no lock, or negative numbers for an identification lock that does not prevent the user from editing the temporary settings, but allows you to use <seealso cref="RemoveAllTemporaryModSettings"/> with the same key to only remove your settings. </param>
|
||||
/// <returns> Success, CollectionMissing if the collection does not exist, TemporarySettingImpossible if the collection can not have settings, ModMissing if the mod can not be identified, TemporarySettingDisallowed if there is already a temporary setting with a different key, OptionGroupMissing if a group can not be found, OptionMissing if an option can not be found. </returns>
|
||||
/// <remarks> If not all groups are set in <paramref name="options"/>, they will be set to their default settings. </remarks>
|
||||
public PenumbraApiEc SetTemporaryModSettings(Guid collectionId, string modDirectory, string modName, bool inherit, bool enabled, int priority,
|
||||
IReadOnlyDictionary<string, IReadOnlyList<string>> options, string source, int key);
|
||||
|
||||
/// <summary> Temporarily set the settings of a mod in a collection to given values. </summary>
|
||||
/// <param name="objectIndex"> The game object index of the object whose collection you want to change. </param>
|
||||
/// <param name="modDirectory"> Specify the mod via its directory name. </param>
|
||||
/// <param name="modName"> Specify the mod via its (non-unique) display name. </param>
|
||||
/// <param name="inherit"> Whether the mod should be forced to inherit from parent collections (if this is true, the other settings do not matter). </param>
|
||||
/// <param name="enabled"> Whether the mod should be enabled or disabled. </param>
|
||||
/// <param name="priority"> The desired priority for the mod. </param>
|
||||
/// <param name="options"> The new settings for the mod, as a map of Group Name -> All enabled Options (should be only one for single select groups).</param>
|
||||
/// <param name="source"> A string to describe the source of those temporary settings. This is displayed to the user. </param>
|
||||
/// <param name="key"> An optional lock to prevent other plugins and the user from changing these settings. Changes in mod structure will still remove the settings. Use 0 for no lock. </param>
|
||||
/// <returns> Success, InvalidArgument if the game object does not exist, TemporarySettingImpossible if the collection can not have settings, ModMissing if the mod can not be identified, TemporarySettingDisallowed if there is already a temporary setting with a different key, OptionGroupMissing if a group can not be found, OptionMissing if an option can not be found. </returns>
|
||||
/// <remarks> If not all groups are set in <paramref name="options"/>, they will be set to their default settings. </remarks>
|
||||
public PenumbraApiEc SetTemporaryModSettingsPlayer(int objectIndex, string modDirectory, string modName, bool inherit, bool enabled, int priority,
|
||||
IReadOnlyDictionary<string, IReadOnlyList<string>> options, string source, int key);
|
||||
|
||||
/// <summary> Temporarily set the settings of a mod in a collection to given values. </summary>
|
||||
/// <param name="collectionId"> The collection to manipulate. </param>
|
||||
/// <param name="modDirectory"> Specify the mod via its directory name. </param>
|
||||
/// <param name="modName"> Specify the mod via its (non-unique) display name. </param>
|
||||
/// <param name="key"> An optional key to a potential lock applied to those settings. </param>
|
||||
/// <returns> Success, NothingDone if no temporary settings could be removed with this key, CollectionMissing if the collection does not exist, TemporarySettingDisallowed if the key did not correspond to the lock. </returns>
|
||||
public PenumbraApiEc RemoveTemporaryModSettings(Guid collectionId, string modDirectory, string modName, int key);
|
||||
|
||||
/// <summary> Temporarily set the settings of a mod in a collection to given values. </summary>
|
||||
/// <param name="objectIndex"> The game object index of the object whose collection you want to change. </param>
|
||||
/// <param name="modDirectory"> Specify the mod via its directory name. </param>
|
||||
/// <param name="modName"> Specify the mod via its (non-unique) display name. </param>
|
||||
/// <param name="key"> An optional key to a potential lock applied to those settings. </param>
|
||||
/// <returns> Success, NothingDone if the mod did not have temporary settings in this collection, InvalidArgument if the game object does not exist, TemporarySettingDisallowed if the key did not correspond to the lock. </returns>
|
||||
public PenumbraApiEc RemoveTemporaryModSettingsPlayer(int objectIndex, string modDirectory, string modName, int key);
|
||||
|
||||
/// <summary> Temporarily set the settings of a mod in a collection to given values. </summary>
|
||||
/// <param name="collectionId"> The collection to manipulate. </param>
|
||||
/// <param name="key"> An optional key to a lock applied to those settings. All settings that use this key will be removed, all others ignored. </param>
|
||||
/// <returns> Success, NothingDone if no temporary settings could be removed with this key, CollectionMissing if the collection does not exist. </returns>
|
||||
public PenumbraApiEc RemoveAllTemporaryModSettings(Guid collectionId, int key);
|
||||
|
||||
/// <summary> Temporarily set the settings of a mod in a collection to given values. </summary>
|
||||
/// <param name="objectIndex"> The game object index of the object whose collection you want to change. </param>
|
||||
/// <param name="key"> An optional key to a lock applied to those settings. All settings that can be removed with this key will be removed, all others ignored. </param>
|
||||
/// <returns> Success, NothingDone if no temporary settings could be removed with this key, InvalidArgument if the game object does not exist. </returns>
|
||||
public PenumbraApiEc RemoveAllTemporaryModSettingsPlayer(int objectIndex, int key);
|
||||
|
||||
/// <summary> Create a temporary collection. </summary>
|
||||
/// <param name="name"> The name for the collection. Arbitrary and only used internally for debugging. </param>
|
||||
/// <returns> The GUID of the created temporary collection. </returns>
|
||||
public Guid CreateTemporaryCollection(string name);
|
||||
|
||||
/// <summary> Remove the temporary collection of the given name. </summary>
|
||||
/// <param name="collectionId"> The chosen temporary collection to remove. </param>
|
||||
/// <returns> NothingChanged or Success. </returns>
|
||||
public PenumbraApiEc DeleteTemporaryCollection(Guid collectionId);
|
||||
|
||||
/// <summary>
|
||||
/// Assign an existing temporary collection to an actor that currently occupies a specific slot.
|
||||
/// </summary>
|
||||
/// <param name="collectionId">The chosen collection assigned to the actor.</param>
|
||||
/// <param name="actorIndex">The current object table index of the actor.</param>
|
||||
/// <param name="forceAssignment">Whether to assign even if the actor is already assigned either a temporary or a permanent collection.</param>
|
||||
/// <returns>Success, InvalidArgument if the actor can not be identified, CollectionMissing if the collection does not exist, CharacterCollectionExists if <paramref name="forceAssignment"/> is false and the actor is already assigned a collection, and AssignmentDeletionFailed if <paramref name="forceAssignment"/> is true and the existing temporary assignment could not be deleted. </returns>
|
||||
public PenumbraApiEc AssignTemporaryCollection(Guid collectionId, int actorIndex, bool forceAssignment);
|
||||
|
||||
/// <summary>
|
||||
/// Set a temporary mod with the given paths, manipulations and priority and the name tag to all regular and temporary collections.
|
||||
/// </summary>
|
||||
/// <param name="tag">Custom name for the temporary mod.</param>
|
||||
/// <param name="paths">List of redirections (can be swaps or redirections).</param>
|
||||
/// <param name="manipString">Zipped Base64 string of meta manipulations.</param>
|
||||
/// <param name="priority">Desired priority.</param>
|
||||
/// <returns>InvalidGamePath, InvalidManipulation or Success.</returns>
|
||||
public PenumbraApiEc AddTemporaryModAll(string tag, Dictionary<string, string> paths, string manipString, int priority);
|
||||
|
||||
/// <summary> Set a temporary mod with the given paths, manipulations and priority and the name tag to a specific collection.
|
||||
/// </summary>
|
||||
/// <param name="tag">Custom name for the temporary mod.</param>
|
||||
/// <param name="collectionId">GUID of the collection the mod should apply to. Can be a temporary collection.</param>
|
||||
/// <param name="paths">List of redirections (can be swaps or redirections).</param>
|
||||
/// <param name="manipString">Zipped Base64 string of meta manipulations.</param>
|
||||
/// <param name="priority">Desired priority.</param>
|
||||
/// <returns>CollectionMissing, InvalidGamePath, InvalidManipulation, InvalidArgument (GUID is nil) or Success.</returns>
|
||||
public PenumbraApiEc AddTemporaryMod(string tag, Guid collectionId, Dictionary<string, string> paths, string manipString,
|
||||
int priority);
|
||||
|
||||
/// <summary>
|
||||
/// Remove the temporary mod with the given tag and priority from the temporary mods applying to all collections, if it exists.
|
||||
/// </summary>
|
||||
/// <param name="tag">The tag to look for.</param>
|
||||
/// <param name="priority">The initially provided priority.</param>
|
||||
/// <returns>NothingDone or Success.</returns>
|
||||
public PenumbraApiEc RemoveTemporaryModAll(string tag, int priority);
|
||||
|
||||
/// <summary>
|
||||
/// Remove the temporary mod with the given tag and priority from the temporary mods applying to a specific collection, if it exists.
|
||||
/// </summary>
|
||||
/// <param name="tag">The tag to look for.</param>
|
||||
/// <param name="collectionId">GUID of the collection the mod should apply to. Can be a temporary collection.</param>
|
||||
/// <param name="priority">The initially provided priority.</param>
|
||||
/// <returns>CollectionMissing, NothingDone or Success.</returns>
|
||||
public PenumbraApiEc RemoveTemporaryMod(string tag, Guid collectionId, int priority);
|
||||
|
||||
/// <summary> Get the current temporary settings of a mod in the given collection. </summary>
|
||||
/// <param name="collectionId"> The collection to query. </param>
|
||||
/// <param name="modDirectory"> Specify the mod via its directory name. </param>
|
||||
/// <param name="modName"> Specify the mod via its (non-unique) display name. </param>
|
||||
/// <param name="key"> The key for the settings lock.</param>
|
||||
/// <returns>
|
||||
/// The settings as (ForceInherit, Enabled, Priority, Settings) or null if none are registered,
|
||||
/// the registered source for the temporary settings or empty,
|
||||
/// and Success, CollectionMissing, ModMissing or TemporarySettingDisallowed if the used key was > 0 and different from the provided key.
|
||||
/// </returns>
|
||||
public (PenumbraApiEc ErrorCode, (bool, bool, int, Dictionary<string, List<string>>)?, string) QueryTemporaryModSettings(Guid collectionId, string modDirectory,
|
||||
string modName, int key);
|
||||
|
||||
/// <summary> Get the current temporary settings of a mod in the collection assigned to a given game object. </summary>
|
||||
/// <param name="objectIndex"> The game object index of the object whose collection you want to change. </param>
|
||||
/// <param name="modDirectory"> Specify the mod via its directory name. </param>
|
||||
/// <param name="modName"> Specify the mod via its (non-unique) display name. </param>
|
||||
/// <param name="key"> The key for the settings lock.</param>
|
||||
/// <returns>
|
||||
/// The settings as (ForceInherit, Enabled, Priority, Settings) or null if none are registered,
|
||||
/// the registered source for the temporary settings or empty,
|
||||
/// and Success, InvalidArgument if the game object does not exist, ModMissing, or TemporarySettingDisallowed if the used key was > 0 and different from the provided key.
|
||||
/// </returns>
|
||||
public (PenumbraApiEc ErrorCode, (bool, bool, int, Dictionary<string, List<string>>)? Settings, string Source) QueryTemporaryModSettingsPlayer(int objectIndex, string modDirectory, string modName, int key);
|
||||
}
|
@@ -1,59 +0,0 @@
|
||||
using Penumbra.Api.Enums;
|
||||
|
||||
namespace Penumbra.Api.Api;
|
||||
|
||||
/// <summary> API methods pertaining to Penumbras UI. </summary>
|
||||
public interface IPenumbraApiUi
|
||||
{
|
||||
/// <summary>
|
||||
/// Triggered when the user hovers over a listed changed object in a mod tab.<para />
|
||||
/// Can be used to append tooltips.
|
||||
/// </summary>
|
||||
/// <returns> The type of the changed item and its ID if known. </returns>
|
||||
public event Action<ChangedItemType, uint>? ChangedItemTooltip;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when the user clicks a listed changed object in a mod tab.
|
||||
/// </summary>
|
||||
/// <returns> The mouse button clicked, the type of the changed item and its ID if known. </returns>
|
||||
public event Action<MouseButton, ChangedItemType, uint>? ChangedItemClicked;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered before the settings tab bar for a mod is drawn, after the title group is drawn.
|
||||
/// </summary>
|
||||
/// <returns>The directory name of the currently selected mod, the total used width of the title bar and the width of the title box.</returns>
|
||||
public event Action<string, float, float>? PreSettingsTabBarDraw;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered before the content of a mod settings panel is drawn.
|
||||
/// </summary>
|
||||
/// <returns>The directory name of the currently selected mod.</returns>
|
||||
public event Action<string>? PreSettingsPanelDraw;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered after the Enabled Checkbox line in settings is drawn, but before options are drawn.
|
||||
/// </summary>
|
||||
/// <returns>The directory name of the currently selected mod.</returns>
|
||||
public event Action<string>? PostEnabledDraw;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered after the content of a mod settings panel is drawn, but still in the child window.
|
||||
/// </summary>
|
||||
/// <returns>The directory name of the currently selected mod.</returns>
|
||||
public event Action<string>? PostSettingsPanelDraw;
|
||||
|
||||
/// <summary>
|
||||
/// Open the Penumbra main config window.
|
||||
/// </summary>
|
||||
/// <param name="tab">Open the window at a specific tab. Use TabType.None to not change the tab. </param>
|
||||
/// <param name="modDirectory">Select a mod specified via its directory name in the mod tab, empty if none.</param>
|
||||
/// <param name="modName">Select a mod specified via its mod name in the mod tab, empty if none.</param>
|
||||
/// <returns>InvalidArgument if <paramref name="tab"/> is invalid,
|
||||
/// ModMissing if <paramref name="modDirectory"/> or <paramref name="modName"/> are set non-empty and the mod does not exist,
|
||||
/// Success otherwise.</returns>
|
||||
/// <remarks>If <paramref name="tab"/> is not TabType.Mods, the mod will not be selected regardless of other parameters and ModMissing will not be returned.</remarks>
|
||||
public PenumbraApiEc OpenMainWindow(TabType tab, string modDirectory, string modName);
|
||||
|
||||
/// <summary> Close the Penumbra main config window. </summary>
|
||||
public void CloseMainWindow();
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
using Penumbra.Api.Enums;
|
||||
|
||||
namespace Penumbra.Api;
|
||||
|
||||
/// <summary>Used when a game object is redrawn by Penumbra.</summary>
|
||||
/// <returns>The <paramref name="objectPtr" /> to the redrawn object and its <paramref name="objectTableIndex" />.</returns>
|
||||
public delegate void GameObjectRedrawnDelegate(nint objectPtr, int objectTableIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Used when the setting of a mod is changed in any way.
|
||||
/// </summary>
|
||||
/// <returns>The <paramref name="type" /> of change, <para />
|
||||
/// the <paramref name="collectionId" /> in which the setting is changed, <para />
|
||||
/// the <paramref name="modDirectory" /> name of the mod, <para />
|
||||
/// and whether the change was <paramref name="inherited" /> or not.</returns>
|
||||
public delegate void ModSettingChangedDelegate(ModSettingChange type, Guid collectionId, string modDirectory, bool inherited);
|
||||
|
||||
/// <summary>
|
||||
/// Used before a new character base draw object is created from a <paramref name="gameObject" />.
|
||||
/// </summary>
|
||||
/// <returns>A pointer to the source <paramref name="gameObject" />, <para />
|
||||
/// the <paramref name="collectionId" /> used for the object, <para />
|
||||
/// a pointer to the used <paramref name="modelId" /> (of type <c>ushort*</c>), <para />
|
||||
/// a pointer to the <paramref name="customize" /> array, <para />
|
||||
/// and a pointer to the <paramref name="equipData" /> array.</returns>
|
||||
public delegate void CreatingCharacterBaseDelegate(nint gameObject, Guid collectionId, nint modelId, nint customize, nint equipData);
|
||||
|
||||
/// <summary>
|
||||
/// Used after a character base <paramref name="drawObject" /> has been created from a <paramref name="gameObject" />.
|
||||
/// </summary>
|
||||
/// <returns>A pointer to the source <paramref name="gameObject" />, <para />
|
||||
/// the <paramref name="collectionId" /> used for the object, <para />
|
||||
/// a pointer to newly created <paramref name="drawObject" />.</returns>
|
||||
public delegate void CreatedCharacterBaseDelegate(nint gameObject, Guid collectionId, nint drawObject);
|
||||
|
||||
/// <summary>
|
||||
/// Used when a specific game object has resolved a path to a non-default path.
|
||||
/// </summary>
|
||||
/// <returns>A pointer to the source <paramref name="gameObject" />, <para />
|
||||
/// the original <paramref name="gamePath" /> that was resolved by Penumbra, <para />
|
||||
/// the resulting <paramref name="localPath" /> returned by Penumbra.</returns>
|
||||
public delegate void GameObjectResourceResolvedDelegate(nint gameObject, string gamePath, string localPath);
|
@@ -1,97 +0,0 @@
|
||||
namespace Penumbra.Api.Enums;
|
||||
|
||||
public enum ApiCollectionType : byte
|
||||
{
|
||||
Yourself = 0,
|
||||
|
||||
MalePlayerCharacter,
|
||||
FemalePlayerCharacter,
|
||||
MaleNonPlayerCharacter,
|
||||
FemaleNonPlayerCharacter,
|
||||
NonPlayerChild,
|
||||
NonPlayerElderly,
|
||||
|
||||
MaleMidlander,
|
||||
FemaleMidlander,
|
||||
MaleHighlander,
|
||||
FemaleHighlander,
|
||||
|
||||
MaleWildwood,
|
||||
FemaleWildwood,
|
||||
MaleDuskwight,
|
||||
FemaleDuskwight,
|
||||
|
||||
MalePlainsfolk,
|
||||
FemalePlainsfolk,
|
||||
MaleDunesfolk,
|
||||
FemaleDunesfolk,
|
||||
|
||||
MaleSeekerOfTheSun,
|
||||
FemaleSeekerOfTheSun,
|
||||
MaleKeeperOfTheMoon,
|
||||
FemaleKeeperOfTheMoon,
|
||||
|
||||
MaleSeawolf,
|
||||
FemaleSeawolf,
|
||||
MaleHellsguard,
|
||||
FemaleHellsguard,
|
||||
|
||||
MaleRaen,
|
||||
FemaleRaen,
|
||||
MaleXaela,
|
||||
FemaleXaela,
|
||||
|
||||
MaleHelion,
|
||||
FemaleHelion,
|
||||
MaleLost,
|
||||
FemaleLost,
|
||||
|
||||
MaleRava,
|
||||
FemaleRava,
|
||||
MaleVeena,
|
||||
FemaleVeena,
|
||||
|
||||
MaleMidlanderNpc,
|
||||
FemaleMidlanderNpc,
|
||||
MaleHighlanderNpc,
|
||||
FemaleHighlanderNpc,
|
||||
|
||||
MaleWildwoodNpc,
|
||||
FemaleWildwoodNpc,
|
||||
MaleDuskwightNpc,
|
||||
FemaleDuskwightNpc,
|
||||
|
||||
MalePlainsfolkNpc,
|
||||
FemalePlainsfolkNpc,
|
||||
MaleDunesfolkNpc,
|
||||
FemaleDunesfolkNpc,
|
||||
|
||||
MaleSeekerOfTheSunNpc,
|
||||
FemaleSeekerOfTheSunNpc,
|
||||
MaleKeeperOfTheMoonNpc,
|
||||
FemaleKeeperOfTheMoonNpc,
|
||||
|
||||
MaleSeawolfNpc,
|
||||
FemaleSeawolfNpc,
|
||||
MaleHellsguardNpc,
|
||||
FemaleHellsguardNpc,
|
||||
|
||||
MaleRaenNpc,
|
||||
FemaleRaenNpc,
|
||||
MaleXaelaNpc,
|
||||
FemaleXaelaNpc,
|
||||
|
||||
MaleHelionNpc,
|
||||
FemaleHelionNpc,
|
||||
MaleLostNpc,
|
||||
FemaleLostNpc,
|
||||
|
||||
MaleRavaNpc,
|
||||
FemaleRavaNpc,
|
||||
MaleVeenaNpc,
|
||||
FemaleVeenaNpc,
|
||||
|
||||
Default = 0xE0,
|
||||
Interface = 0xE1,
|
||||
Current = 0xE2,
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
namespace Penumbra.Api.Enums;
|
||||
|
||||
public enum ChangedItemIcon : uint
|
||||
{
|
||||
None = 0,
|
||||
Unknown = 1,
|
||||
Head = 2,
|
||||
Body = 3,
|
||||
Hands = 4,
|
||||
Legs = 5,
|
||||
Feet = 6,
|
||||
Ears = 7,
|
||||
Neck = 8,
|
||||
Wrists = 9,
|
||||
Finger = 10,
|
||||
Mainhand = 11,
|
||||
Offhand = 12,
|
||||
Customization = 13,
|
||||
Monster = 14,
|
||||
Demihuman = 15,
|
||||
Action = 16,
|
||||
Emote = 17,
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
namespace Penumbra.Api.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Describes known types of changed items that could provide special care.
|
||||
/// </summary>
|
||||
public enum ChangedItemType
|
||||
{
|
||||
None = 0,
|
||||
Item = 1,
|
||||
Action = 2,
|
||||
Customization = 3,
|
||||
ItemOffhand = 4,
|
||||
Unknown = 5,
|
||||
Emote = 6,
|
||||
Model = 7,
|
||||
CustomArmor = 8,
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
namespace Penumbra.Api.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// The selection type for mod option groups.
|
||||
/// </summary>
|
||||
public enum GroupType
|
||||
{
|
||||
/// <summary>
|
||||
/// Exactly one option of this group has to be selected (if any exist).
|
||||
/// </summary>
|
||||
Single,
|
||||
|
||||
/// <summary>
|
||||
/// Any number of options in this group can be toggled on or off at the same time.
|
||||
/// Limits the number of options in a single group to 32 at the most.
|
||||
/// Each option is its own data container, which are independent of each other.
|
||||
/// </summary>
|
||||
Multi,
|
||||
|
||||
/// <summary>
|
||||
/// Any number of options in this group can be toggled on or off at the same time.
|
||||
/// Affects a single IMC entry, to manipulate different parts of a model in a user-facing way.
|
||||
/// </summary>
|
||||
Imc,
|
||||
|
||||
/// <summary>
|
||||
/// Any number of options in this group can be toggled on or off at the same time.
|
||||
/// Limits the number of options in a single group to 8 at the most.
|
||||
/// Each combination of options is its own data container, resulting in 2^N separate data containers.
|
||||
/// </summary>
|
||||
Combining,
|
||||
|
||||
/// <summary>
|
||||
/// A group consisting of multiple separate subgroups where the options can depend on each other.
|
||||
/// Each subgroup behaves the same way as its regular group type, just with optional dependencies on the other options.
|
||||
/// The total number of options is still limited by the settings bit size.
|
||||
/// </summary>
|
||||
Complex,
|
||||
}
|
@@ -1,34 +0,0 @@
|
||||
namespace Penumbra.Api.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Describes the way a mod can change its settings.
|
||||
/// </summary>
|
||||
public enum ModSettingChange
|
||||
{
|
||||
/// <summary> It was set to inherit from other collections or not to inherit anymore. </summary>
|
||||
Inheritance,
|
||||
|
||||
/// <summary> It was enabled or disabled. </summary>
|
||||
EnableState,
|
||||
|
||||
/// <summary> Its priority was changed. </summary>
|
||||
Priority,
|
||||
|
||||
/// <summary> A specific setting for an option group was changed. </summary>
|
||||
Setting,
|
||||
|
||||
/// <summary> Multiple mods were set to inherit from other collections or not inherit anymore at once. </summary>
|
||||
MultiInheritance,
|
||||
|
||||
/// <summary> Multiple mods were enabled or disabled at once. </summary>
|
||||
MultiEnableState,
|
||||
|
||||
/// <summary> A temporary mod was enabled or disabled. </summary>
|
||||
TemporaryMod,
|
||||
|
||||
/// <summary> A mod was edited. Only invoked on edits affecting the current players collection and for that for now. </summary>
|
||||
Edited,
|
||||
|
||||
/// <summary> A temporary setting was added, removed or changed. </summary>
|
||||
TemporarySetting,
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
namespace Penumbra.Api.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Describes which mouse button was used to click an element.
|
||||
/// </summary>
|
||||
public enum MouseButton
|
||||
{
|
||||
None,
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
namespace Penumbra.Api.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Error codes returned by some Penumbra.Api calls.
|
||||
/// </summary>
|
||||
public enum PenumbraApiEc
|
||||
{
|
||||
Success = 0,
|
||||
NothingChanged = 1,
|
||||
CollectionMissing = 2,
|
||||
ModMissing = 3,
|
||||
OptionGroupMissing = 4,
|
||||
OptionMissing = 5,
|
||||
|
||||
CharacterCollectionExists = 6,
|
||||
LowerPriority = 7,
|
||||
InvalidGamePath = 8,
|
||||
FileMissing = 9,
|
||||
InvalidManipulation = 10,
|
||||
InvalidArgument = 11,
|
||||
PathRenameFailed = 12,
|
||||
CollectionExists = 13,
|
||||
AssignmentCreationDisallowed = 14,
|
||||
AssignmentDeletionDisallowed = 15,
|
||||
InvalidIdentifier = 16,
|
||||
SystemDisposed = 17,
|
||||
AssignmentDeletionFailed = 18,
|
||||
|
||||
TemporarySettingDisallowed = 19,
|
||||
TemporarySettingImpossible = 20,
|
||||
|
||||
UnknownError = 255,
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
namespace Penumbra.Api.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// The way a specific game object shall be redrawn.
|
||||
/// Actors can be redrawn immediately or after GPose.
|
||||
/// </summary>
|
||||
public enum RedrawType
|
||||
{
|
||||
Redraw,
|
||||
AfterGPose,
|
||||
}
|
@@ -1,79 +0,0 @@
|
||||
namespace Penumbra.Api.Enums;
|
||||
|
||||
public enum ResourceType : uint
|
||||
{
|
||||
Unknown = 0,
|
||||
Aet = 0x00616574,
|
||||
Amb = 0x00616D62,
|
||||
Atch = 0x61746368,
|
||||
Atex = 0x61746578,
|
||||
Avfx = 0x61766678,
|
||||
Awt = 0x00617774,
|
||||
Bklb = 0x626B6C62,
|
||||
Cmp = 0x00636D70,
|
||||
Cutb = 0x63757462,
|
||||
Dic = 0x00646963,
|
||||
Eanb = 0x65616E62,
|
||||
Eid = 0x00656964,
|
||||
Envb = 0x656E7662,
|
||||
Eqdp = 0x65716470,
|
||||
Eqp = 0x00657170,
|
||||
Eslb = 0x65736C63,
|
||||
Essb = 0x65737362,
|
||||
Est = 0x00657374,
|
||||
Evp = 0x00657670,
|
||||
Exd = 0x00657864,
|
||||
Exh = 0x00657868,
|
||||
Exl = 0x0065786C,
|
||||
Fdt = 0x00666474,
|
||||
Fpeb = 0x66706562,
|
||||
Gfd = 0x00676664,
|
||||
Ggd = 0x00676764,
|
||||
Gmp = 0x00676D70,
|
||||
Gzd = 0x00677A64,
|
||||
Imc = 0x00696D63,
|
||||
Kdb = 0x006B6462,
|
||||
Kdlb = 0x6B646C62,
|
||||
Lcb = 0x006C6362,
|
||||
Lgb = 0x006C6762,
|
||||
Luab = 0x6C756162,
|
||||
Lvb = 0x006C7662,
|
||||
Mdl = 0x006D646C,
|
||||
Mlt = 0x006D6C74,
|
||||
Mtrl = 0x6D74726C,
|
||||
Obsb = 0x6F627362,
|
||||
Pap = 0x00706170,
|
||||
Pbd = 0x00706264,
|
||||
Pcb = 0x00706362,
|
||||
Phyb = 0x70687962,
|
||||
Plt = 0x00706C74,
|
||||
Scd = 0x00736364,
|
||||
Sgb = 0x00736762,
|
||||
Shcd = 0x73686364,
|
||||
Shpk = 0x7368706B,
|
||||
Sklb = 0x736B6C62,
|
||||
Skp = 0x00736B70,
|
||||
Stm = 0x0073746D,
|
||||
Svb = 0x00737662,
|
||||
Tera = 0x74657261,
|
||||
Tex = 0x00746578,
|
||||
Tmb = 0x00746D62,
|
||||
Ugd = 0x00756764,
|
||||
Uld = 0x00756C64,
|
||||
Waoe = 0x77616F65,
|
||||
Wtd = 0x00777464,
|
||||
}
|
||||
|
||||
public static class ResourceTypeExtensions
|
||||
{
|
||||
public static ResourceType FromExtension(ReadOnlySpan<byte> ext)
|
||||
=> ext.Length switch
|
||||
{
|
||||
0 => ResourceType.Unknown,
|
||||
1 => (ResourceType)(ext[0] | 32),
|
||||
2 => (ResourceType)(ext[0] | 32 | ((ext[1] | 32) << 8)),
|
||||
3 => (ResourceType)(ext[0] | 32 | ((ext[1] | 32) << 8) | ((ext[2] | 32) << 16)),
|
||||
4 => (ResourceType)(ext[0] | 32 | ((ext[1] | 32) << 8) | ((ext[2] | 32) << 16) | ((ext[2] | 32) << 24)),
|
||||
_ => ResourceType.Unknown,
|
||||
};
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
namespace Penumbra.Api.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// The different tabs of the main window that are available.
|
||||
/// </summary>
|
||||
public enum TabType
|
||||
{
|
||||
None = -1,
|
||||
Settings = 0,
|
||||
Mods = 1,
|
||||
Collections = 2,
|
||||
ChangedItems = 3,
|
||||
EffectiveChanges = 4,
|
||||
ResourceWatcher = 5,
|
||||
Debug = 6,
|
||||
ResourceManager = 7,
|
||||
OnScreen = 8,
|
||||
Messages = 9,
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
namespace Penumbra.Api.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// The different types of textures a given texture can be converted to.
|
||||
/// </summary>
|
||||
public enum TextureType
|
||||
{
|
||||
/// <summary> Convert the texture to .png. </summary>
|
||||
Png = 0,
|
||||
|
||||
/// <summary> Keep the texture format as it is but save as .tex. </summary>
|
||||
AsIsTex = 1,
|
||||
|
||||
/// <summary> Keep the texture format as it is but save as .dds. </summary>
|
||||
AsIsDds = 2,
|
||||
|
||||
/// <summary> Convert the texture to RGBA32 and save as .tex. </summary>
|
||||
RgbaTex = 3,
|
||||
|
||||
/// <summary> Convert the texture to RGBA32 and save as .dds. </summary>
|
||||
RgbaDds = 4,
|
||||
|
||||
/// <summary> Convert the texture to BC3 and save as .tex. </summary>
|
||||
Bc3Tex = 5,
|
||||
|
||||
/// <summary> Convert the texture to BC3 and save as .dds. </summary>
|
||||
Bc3Dds = 6,
|
||||
|
||||
/// <summary> Convert the texture to BC3 and save as .tex. </summary>
|
||||
Bc7Tex = 7,
|
||||
|
||||
/// <summary> Convert the texture to BC3 and save as .dds. </summary>
|
||||
Bc7Dds = 8,
|
||||
|
||||
/// <summary> Convert the texture to .tga. </summary>
|
||||
Targa = 9,
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
// Global using directives
|
||||
|
||||
global using System;
|
||||
global using System.Collections.Generic;
|
||||
global using System.Threading.Tasks;
|
@@ -1,136 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized disposable Provider for Actions.
|
||||
/// </summary>
|
||||
public sealed class ActionProvider : IDisposable
|
||||
{
|
||||
private ICallGateProvider<object?>? _provider;
|
||||
|
||||
public ActionProvider(IDalamudPluginInterface pi, string label, Action action)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterAction(action);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterAction();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~ActionProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specialized disposable Provider for Actions.
|
||||
/// </summary>
|
||||
public sealed class ActionProvider<T1> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, object?>? _provider;
|
||||
|
||||
public ActionProvider(IDalamudPluginInterface pi, string label, Action<T1> action)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterAction(action);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterAction();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~ActionProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="ActionProvider{T1}"/>
|
||||
/// </summary>
|
||||
public sealed class ActionProvider<T1, T2> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, object?>? _provider;
|
||||
|
||||
public ActionProvider(IDalamudPluginInterface pi, string label, Action<T1, T2> action)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterAction(action);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterAction();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~ActionProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="ActionProvider{T1}"/>
|
||||
/// </summary>
|
||||
public sealed class ActionProvider<T1, T2, T3> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, T3, object?>? _provider;
|
||||
|
||||
public ActionProvider(IDalamudPluginInterface pi, string label, Action<T1, T2, T3> action)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterAction(action);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterAction();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~ActionProvider()
|
||||
=> Dispose();
|
||||
}
|
@@ -1,114 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized subscriber only allowing to invoke actions.
|
||||
/// </summary>
|
||||
public class ActionSubscriber
|
||||
{
|
||||
private readonly ICallGateSubscriber<object?>? _subscriber;
|
||||
|
||||
/// <summary> Whether the subscriber could successfully be created. </summary>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
protected ActionSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Invoke the action. See the source of the subscriber for details.</summary>
|
||||
protected void Invoke()
|
||||
=> _subscriber?.InvokeAction();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber"/>
|
||||
public class ActionSubscriber<T1>
|
||||
{
|
||||
private readonly ICallGateSubscriber<T1, object?>? _subscriber;
|
||||
|
||||
/// <summary> Whether the subscriber could successfully be created. </summary>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
protected ActionSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Invoke the action. See the source of the subscriber for details.</summary>
|
||||
protected void Invoke(T1 a)
|
||||
=> _subscriber?.InvokeAction(a);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber"/>
|
||||
public class ActionSubscriber<T1, T2>
|
||||
{
|
||||
private readonly ICallGateSubscriber<T1, T2, object?>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber{T1}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
protected ActionSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber.Invoke"/>
|
||||
protected void Invoke(T1 a, T2 b)
|
||||
=> _subscriber?.InvokeAction(a, b);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber"/>
|
||||
public class ActionSubscriber<T1, T2, T3>
|
||||
{
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, object?>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber{T1}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
protected ActionSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, object?>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ActionSubscriber.Invoke"/>
|
||||
protected void Invoke(T1 a, T2 b, T3 c)
|
||||
=> _subscriber?.InvokeAction(a, b, c);
|
||||
}
|
@@ -1,152 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary> A dictionary that implicitly can be converted to a read-only dictionary with different value type. </summary>
|
||||
/// <typeparam name="TKey"> The type of the keys. </typeparam>
|
||||
/// <typeparam name="TValueFrom"> The actual type of the values. </typeparam>
|
||||
/// <typeparam name="TValueTo"> The read-only type of the values. </typeparam>
|
||||
public abstract class ConvertingDict<TKey, TValueFrom, TValueTo>(IReadOnlyDictionary<TKey, TValueFrom> dict)
|
||||
: IReadOnlyDictionary<TKey, TValueTo>
|
||||
where TKey : notnull
|
||||
{
|
||||
/// <summary> Obtain the original dictionary. </summary>
|
||||
public IReadOnlyDictionary<TKey, TValueFrom> Original
|
||||
=> dict;
|
||||
|
||||
/// <summary> Conversion between values. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected abstract TValueTo ConvertValue(in TValueFrom from);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool ContainsKey(TKey key)
|
||||
=> dict.ContainsKey(key);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetValue(TKey key, out TValueTo value)
|
||||
{
|
||||
if (dict.TryGetValue(key, out var v))
|
||||
{
|
||||
value = ConvertValue(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default!;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TValueTo this[TKey key]
|
||||
=> ConvertValue(dict[key]);
|
||||
|
||||
public IEnumerable<TKey> Keys
|
||||
=> dict.Keys;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<TValueTo> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var value in dict.Values)
|
||||
yield return ConvertValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Count
|
||||
=> dict.Count;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerator<KeyValuePair<TKey, TValueTo>> GetEnumerator()
|
||||
{
|
||||
foreach (var kvp in dict)
|
||||
yield return new KeyValuePair<TKey, TValueTo>(kvp.Key, ConvertValue(kvp.Value));
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
=> GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary> A dictionary that implicitly can be converted to a read-only dictionary with different value type. </summary>
|
||||
/// <typeparam name="TKeyFrom"> The actual type of the keys. </typeparam>
|
||||
/// <typeparam name="TKeyTo"> The read-only type of the keys. </typeparam>
|
||||
/// <typeparam name="TValueFrom"> The actual type of the values. </typeparam>
|
||||
/// <typeparam name="TValueTo"> The read-only type of the values. </typeparam>
|
||||
public abstract class ConvertingDict<TKeyFrom, TKeyTo, TValueFrom, TValueTo>(IReadOnlyDictionary<TKeyFrom, TValueFrom> dict)
|
||||
: IReadOnlyDictionary<TKeyTo, TValueTo>
|
||||
where TKeyFrom : notnull
|
||||
where TKeyTo : notnull
|
||||
{
|
||||
/// <summary> Obtain the original dictionary. </summary>
|
||||
public IReadOnlyDictionary<TKeyFrom, TValueFrom> Original
|
||||
=> dict;
|
||||
|
||||
/// <summary> Conversion between keys. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected abstract TKeyTo ConvertKey(in TKeyFrom from);
|
||||
|
||||
/// <summary> Conversion between keys. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected abstract TKeyFrom ConvertKeyBack(in TKeyTo from);
|
||||
|
||||
/// <summary> Conversion between values. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected abstract TValueTo ConvertValue(in TValueFrom from);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool ContainsKey(TKeyTo key)
|
||||
=> dict.ContainsKey(ConvertKeyBack(key));
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetValue(TKeyTo key, out TValueTo value)
|
||||
{
|
||||
if (dict.TryGetValue(ConvertKeyBack(key), out var v))
|
||||
{
|
||||
value = ConvertValue(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default!;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TValueTo this[TKeyTo key]
|
||||
=> ConvertValue(dict[ConvertKeyBack(key)]);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<TKeyTo> Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var key in dict.Keys)
|
||||
yield return ConvertKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<TValueTo> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var value in dict.Values)
|
||||
yield return ConvertValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerator<KeyValuePair<TKeyTo, TValueTo>> GetEnumerator()
|
||||
{
|
||||
foreach (var kvp in dict)
|
||||
yield return new KeyValuePair<TKeyTo, TValueTo>(ConvertKey(kvp.Key), ConvertValue(kvp.Value));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
=> GetEnumerator();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Count
|
||||
=> dict.Count;
|
||||
}
|
@@ -1,53 +0,0 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using Penumbra.Api.Enums;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary> Wrapper dictionary. </summary>
|
||||
public sealed class GameResourceDict(IReadOnlyDictionary<nint, (string, string, uint)> dict)
|
||||
: ConvertingDict<nint, (string, string, uint), (string, string, ChangedItemIcon)>(dict)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected override (string, string, ChangedItemIcon) ConvertValue(in (string, string, uint) from)
|
||||
=> (from.Item1, from.Item2, (ChangedItemIcon)from.Item3);
|
||||
|
||||
/// <summary> Create dictionary or null. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static GameResourceDict? Create(IReadOnlyDictionary<nint, (string, string, uint)>? dict)
|
||||
=> dict == null ? null : new GameResourceDict(dict);
|
||||
}
|
||||
|
||||
/// <summary> Wrapper dictionary. </summary>
|
||||
public sealed class AvailableModSettings(IReadOnlyDictionary<string, (string[], int)> dict)
|
||||
: ConvertingDict<string, (string[], int), (string[], GroupType)>(dict)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected override (string[], GroupType) ConvertValue(in (string[], int) from)
|
||||
=> (from.Item1, (GroupType)from.Item2);
|
||||
|
||||
/// <summary> Create dictionary or null. </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static AvailableModSettings? Create(IReadOnlyDictionary<string, (string[], int)>? dict)
|
||||
=> dict == null ? null : new AvailableModSettings(dict);
|
||||
}
|
||||
|
||||
public record ResourceNodeDto
|
||||
{
|
||||
public required ResourceType Type { get; init; }
|
||||
public required ChangedItemIcon Icon { get; init; }
|
||||
public required string? Name { get; init; }
|
||||
public required string? GamePath { get; init; }
|
||||
public required string ActualPath { get; init; }
|
||||
public required nint ObjectAddress { get; init; }
|
||||
public required nint ResourceHandle { get; init; }
|
||||
public required List<ResourceNodeDto> Children { get; init; }
|
||||
}
|
||||
|
||||
public record ResourceTreeDto
|
||||
{
|
||||
public required string Name { get; init; }
|
||||
public required ushort RaceCode { get; init; }
|
||||
public required List<ResourceNodeDto> Nodes { get; init; }
|
||||
}
|
@@ -1,465 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized disposable Provider for Events.<para />
|
||||
/// Will execute the unsubscriber action on dispose if any is provided.<para />
|
||||
/// Can only be invoked and disposed.
|
||||
/// </summary>
|
||||
public sealed class EventProvider : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, (Action<Action> Add, Action<Action> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider> add, Action<EventProvider> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Invoke the event.</summary>
|
||||
public void Invoke()
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider"/>
|
||||
public sealed class EventProvider<T1> : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<T1, object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, (Action<Action<T1>> Add, Action<Action<T1>> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider<T1>> add, Action<EventProvider<T1>> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider.Invoke"/>
|
||||
public void Invoke(T1 a)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage(a);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action<T1>> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider<T1>> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider"/>
|
||||
public sealed class EventProvider<T1, T2> : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<T1, T2, object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label,
|
||||
(Action<Action<T1, T2>> Add, Action<Action<T1, T2>> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider<T1, T2>> add, Action<EventProvider<T1, T2>> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider.Invoke"/>
|
||||
public void Invoke(T1 a, T2 b)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage(a, b);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action<T1, T2>> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider<T1, T2>> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider"/>
|
||||
public sealed class EventProvider<T1, T2, T3> : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<T1, T2, T3, object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label,
|
||||
(Action<Action<T1, T2, T3>> Add, Action<Action<T1, T2, T3>> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider<T1, T2, T3>> add, Action<EventProvider<T1, T2, T3>> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider.Invoke"/>
|
||||
public void Invoke(T1 a, T2 b, T3 c)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage(a, b, c);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action<T1, T2, T3>> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider<T1, T2, T3>> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider"/>
|
||||
public sealed class EventProvider<T1, T2, T3, T4> : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<T1, T2, T3, T4, object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label,
|
||||
(Action<Action<T1, T2, T3, T4>> Add, Action<Action<T1, T2, T3, T4>> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider<T1, T2, T3, T4>> add,
|
||||
Action<EventProvider<T1, T2, T3, T4>> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider.Invoke"/>
|
||||
public void Invoke(T1 a, T2 b, T3 c, T4 d)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage(a, b, c, d);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action<T1, T2, T3, T4>> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider<T1, T2, T3, T4>> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider"/>
|
||||
public sealed class EventProvider<T1, T2, T3, T4, T5> : IDisposable
|
||||
{
|
||||
private readonly IPluginLog _log;
|
||||
private ICallGateProvider<T1, T2, T3, T4, T5, object?>? _provider;
|
||||
private Delegate? _unsubscriber;
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label,
|
||||
(Action<Action<T1, T2, T3, T4, T5>> Add, Action<Action<T1, T2, T3, T4, T5>> Del)? subscribe = null)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, T5, object?>(label);
|
||||
subscribe?.Add(Invoke);
|
||||
_unsubscriber = subscribe?.Del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EventProvider(IDalamudPluginInterface pi, string label, Action<EventProvider<T1, T2, T3, T4, T5>> add,
|
||||
Action<EventProvider<T1, T2, T3, T4, T5>> del)
|
||||
{
|
||||
_unsubscriber = null;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, T5, object?>(label);
|
||||
add(this);
|
||||
_unsubscriber = del;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EventProvider.Invoke"/>
|
||||
public void Invoke(T1 a, T2 b, T3 c, T4 d, T5 e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider?.SendMessage(a, b, c, d, e);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error($"Exception thrown on IPC event:\n{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_unsubscriber)
|
||||
{
|
||||
case Action<Action<T1, T2, T3, T4, T5>> a:
|
||||
a(Invoke);
|
||||
break;
|
||||
case Action<EventProvider<T1, T2, T3, T4, T5>> b:
|
||||
b(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_unsubscriber = null;
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~EventProvider()
|
||||
=> Dispose();
|
||||
}
|
@@ -1,582 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized disposable Subscriber for Events.<para />
|
||||
/// Subscriptions are wrapped to be individually exception-safe.<para/>
|
||||
/// Can be enabled and disabled.<para/>
|
||||
/// </summary>
|
||||
public sealed class EventSubscriber : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action, Action> _delegates = new();
|
||||
private ICallGateSubscriber<object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable all currently subscribed actions registered with this EventSubscriber.
|
||||
/// Does nothing if it is already enabled.
|
||||
/// </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disable all subscribed actions registered with this EventSubscriber.
|
||||
/// Does nothing if it is already disabled.
|
||||
/// Does not forget the actions, only disables them.
|
||||
/// </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add or remove an action to the IPC event, if it is valid.
|
||||
/// </summary>
|
||||
public event Action Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action()
|
||||
{
|
||||
try
|
||||
{
|
||||
value();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber"/> </summary>
|
||||
public sealed class EventSubscriber<T1> : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action<T1>, Action<T1>> _delegates = new();
|
||||
private ICallGateSubscriber<T1, object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action<T1>[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Enable"/> </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Disable"/> </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Event"/> </summary>
|
||||
public event Action<T1> Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action(T1 a)
|
||||
{
|
||||
try
|
||||
{
|
||||
value(a);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber"/> </summary>
|
||||
public sealed class EventSubscriber<T1, T2> : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action<T1, T2>, Action<T1, T2>> _delegates = new();
|
||||
private ICallGateSubscriber<T1, T2, object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action<T1, T2>[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Enable"/> </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Disable"/> </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Event"/> </summary>
|
||||
public event Action<T1, T2> Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action(T1 a, T2 b)
|
||||
{
|
||||
try
|
||||
{
|
||||
value(a, b);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber"/> </summary>
|
||||
public sealed class EventSubscriber<T1, T2, T3> : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action<T1, T2, T3>, Action<T1, T2, T3>> _delegates = [];
|
||||
private ICallGateSubscriber<T1, T2, T3, object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action<T1, T2, T3>[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Enable"/> </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Disable"/> </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Event"/> </summary>
|
||||
public event Action<T1, T2, T3> Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action(T1 a, T2 b, T3 c)
|
||||
{
|
||||
try
|
||||
{
|
||||
value(a, b, c);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber"/> </summary>
|
||||
public sealed class EventSubscriber<T1, T2, T3, T4> : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action<T1, T2, T3, T4>, Action<T1, T2, T3, T4>> _delegates = new();
|
||||
private ICallGateSubscriber<T1, T2, T3, T4, object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action<T1, T2, T3, T4>[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, T4, object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Enable"/> </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Disable"/> </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Event"/> </summary>
|
||||
public event Action<T1, T2, T3, T4> Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action(T1 a, T2 b, T3 c, T4 d)
|
||||
{
|
||||
try
|
||||
{
|
||||
value(a, b, c, d);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber"/> </summary>
|
||||
public sealed class EventSubscriber<T1, T2, T3, T4, T5> : IDisposable
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly IPluginLog _log;
|
||||
private readonly Dictionary<Action<T1, T2, T3, T4, T5>, Action<T1, T2, T3, T4, T5>> _delegates = new();
|
||||
private ICallGateSubscriber<T1, T2, T3, T4, T5, object?>? _subscriber;
|
||||
private bool _disabled;
|
||||
|
||||
public EventSubscriber(IDalamudPluginInterface pi, string label, params Action<T1, T2, T3, T4, T5>[] actions)
|
||||
{
|
||||
_label = label;
|
||||
_log = PluginLogHelper.GetLog(pi);
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, T4, T5, object?>(label);
|
||||
foreach (var action in actions)
|
||||
Event += action;
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.Error($"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Enable"/> </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (_disabled && _subscriber != null)
|
||||
{
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Subscribe(action);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Disable"/> </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (!_disabled)
|
||||
{
|
||||
if (_subscriber != null)
|
||||
foreach (var action in _delegates.Values)
|
||||
_subscriber.Unsubscribe(action);
|
||||
|
||||
_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary><inheritdoc cref="EventSubscriber.Event"/> </summary>
|
||||
public event Action<T1, T2, T3, T4, T5> Event
|
||||
{
|
||||
add
|
||||
{
|
||||
if (_subscriber != null && !_delegates.ContainsKey(value))
|
||||
{
|
||||
void Action(T1 a, T2 b, T3 c, T4 d, T5 e)
|
||||
{
|
||||
try
|
||||
{
|
||||
value(a, b, c, d, e);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error($"Exception invoking IPC event {_label}:\n{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_delegates.TryAdd(value, Action) && !_disabled)
|
||||
_subscriber.Subscribe(Action);
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (_subscriber != null && _delegates.Remove(value, out var action))
|
||||
_subscriber.Unsubscribe(action);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disable();
|
||||
_subscriber = null;
|
||||
_delegates.Clear();
|
||||
}
|
||||
|
||||
~EventSubscriber()
|
||||
=> Dispose();
|
||||
}
|
@@ -1,223 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized disposable Provider for Funcs.
|
||||
/// </summary>
|
||||
public sealed class FuncProvider<TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, T3, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, T3, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, T3, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, T3, T4, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, T3, T4, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, T3, T4, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, T3, T4, T5, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, T3, T4, T5, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, T3, T4, T5, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, T5, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncProvider{TRet}"/>
|
||||
public sealed class FuncProvider<T1, T2, T3, T4, T5, T6, TRet> : IDisposable
|
||||
{
|
||||
private ICallGateProvider<T1, T2, T3, T4, T5, T6, TRet>? _provider;
|
||||
|
||||
public FuncProvider(IDalamudPluginInterface pi, string label, Func<T1, T2, T3, T4, T5, T6, TRet> func)
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider = pi.GetIpcProvider<T1, T2, T3, T4, T5, T6, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Provider for {label}\n{e}");
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
_provider?.RegisterFunc(func);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider?.UnregisterFunc();
|
||||
_provider = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FuncProvider()
|
||||
=> Dispose();
|
||||
}
|
@@ -1,217 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
using Dalamud.Plugin.Ipc.Exceptions;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Specialized subscriber only allowing to invoke functions with a return.
|
||||
/// </summary>
|
||||
public class FuncSubscriber<TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<TRet>? _subscriber;
|
||||
|
||||
/// <summary> Whether the subscriber could successfully be created. </summary>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Invoke the function. See the source of the subscriber for details.</summary>
|
||||
protected TRet Invoke()
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc() : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, T3, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b, T3 c)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b, c) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, T3, T4, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, T4, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, T4, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b, T3 c, T4 d)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b, c, d) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, T3, T4, T5, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, T4, T5, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, T4, T5, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b, T3 c, T4 d, T5 e)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b, c, d, e) : throw new IpcNotReadyError(_label);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
public class FuncSubscriber<T1, T2, T3, T4, T5, T6, TRet>
|
||||
{
|
||||
private readonly string _label;
|
||||
private readonly ICallGateSubscriber<T1, T2, T3, T4, T5, T6, TRet>? _subscriber;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Valid"/>
|
||||
public bool Valid
|
||||
=> _subscriber != null;
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}"/>
|
||||
protected FuncSubscriber(IDalamudPluginInterface pi, string label)
|
||||
{
|
||||
_label = label;
|
||||
try
|
||||
{
|
||||
_subscriber = pi.GetIpcSubscriber<T1, T2, T3, T4, T5, T6, TRet>(label);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLogHelper.WriteError(pi, $"Error registering IPC Subscriber for {label}\n{e}");
|
||||
_subscriber = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FuncSubscriber{TRet}.Invoke"/>
|
||||
protected TRet Invoke(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f)
|
||||
=> _subscriber != null ? _subscriber.InvokeFunc(a, b, c, d, e, f) : throw new IpcNotReadyError(_label);
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
||||
namespace Penumbra.Api.Helpers;
|
||||
|
||||
internal class PluginLogHelper
|
||||
{
|
||||
[PluginService]
|
||||
private static IPluginLog? _log { get; set; }
|
||||
|
||||
private PluginLogHelper(IDalamudPluginInterface pi)
|
||||
=> pi.Inject(this);
|
||||
|
||||
public static void WriteError(IDalamudPluginInterface pi, string errorMessage)
|
||||
=> GetLog(pi).Error(errorMessage);
|
||||
|
||||
public static IPluginLog GetLog(IDalamudPluginInterface pi)
|
||||
{
|
||||
if (_log != null)
|
||||
return _log;
|
||||
|
||||
_ = new PluginLogHelper(pi);
|
||||
return _log!;
|
||||
}
|
||||
}
|
@@ -1,154 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Penumbra.Api.Api;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Api.Helpers;
|
||||
|
||||
namespace Penumbra.Api.IpcSubscribers;
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.GetCollections"/>
|
||||
public sealed class GetCollections(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<Dictionary<Guid, string>>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(GetCollections)}.V5";
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.GetCollections"/>
|
||||
public new Dictionary<Guid, string> Invoke()
|
||||
=> base.Invoke();
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<Dictionary<Guid, string>> Provider(IDalamudPluginInterface pi, IPenumbraApiCollection api)
|
||||
=> new(pi, Label, api.GetCollections);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.GetCollectionsByIdentifier"/>
|
||||
public sealed class GetCollectionsByIdentifier(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, List<(Guid Id, string Name)>>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(GetCollectionsByIdentifier)}";
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.GetCollectionsByIdentifier"/>
|
||||
public new List<(Guid Id, string Name)> Invoke(string name)
|
||||
=> base.Invoke(name);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<string, List<(Guid Id, string Name)>> Provider(IDalamudPluginInterface pi, IPenumbraApiCollection api)
|
||||
=> new(pi, Label, api.GetCollectionsByIdentifier);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.GetChangedItemsForCollection"/>
|
||||
public sealed class GetChangedItemsForCollection(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<Guid, Dictionary<string, object?>>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(GetChangedItemsForCollection)}";
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.GetChangedItemsForCollection"/>
|
||||
public new Dictionary<string, object?> Invoke(Guid collectionId)
|
||||
=> base.Invoke(collectionId);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<Guid, Dictionary<string, object?>> Provider(IDalamudPluginInterface pi, IPenumbraApiCollection api)
|
||||
=> new(pi, Label, api.GetChangedItemsForCollection);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.GetCollection"/>
|
||||
public sealed class GetCollection(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<byte, (Guid Id, string Name)?>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(GetCollection)}";
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.GetCollection"/>
|
||||
public (Guid Id, string Name)? Invoke(ApiCollectionType type)
|
||||
=> Invoke((byte)type);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<byte, (Guid Id, string Name)?> Provider(IDalamudPluginInterface pi, IPenumbraApiCollection api)
|
||||
=> new(pi, Label, b => api.GetCollection((ApiCollectionType)b));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.GetCollectionForObject"/>
|
||||
public sealed class GetCollectionForObject(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, (bool ObjectValid, bool IndividualSet, (Guid Id, string Name) EffectiveCollection)>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(GetCollectionForObject)}.V5";
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.GetCollectionForObject"/>
|
||||
public new (bool ObjectValid, bool IndividualSet, (Guid Id, string Name) EffectiveCollection) Invoke(int gameObjectIdx)
|
||||
=> base.Invoke(gameObjectIdx);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<int, (bool ObjectValid, bool IndividualSet, (Guid Id, string Name) EffectiveCollection)>
|
||||
Provider(IDalamudPluginInterface pi, IPenumbraApiCollection api)
|
||||
=> new(pi, Label, api.GetCollectionForObject);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.SetCollection"/>
|
||||
public sealed class SetCollection(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<byte, Guid?, bool, bool, (int, (Guid Id, string Name)? OldCollection)>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(SetCollection)}";
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.SetCollectionForObject"/>
|
||||
public (PenumbraApiEc, (Guid Id, string Name)? OldCollection) Invoke(ApiCollectionType type, Guid? collectionId,
|
||||
bool allowCreateNew = true, bool allowDelete = true)
|
||||
{
|
||||
var (ec, pair) = Invoke((byte)type, collectionId, allowCreateNew, allowDelete);
|
||||
return ((PenumbraApiEc)ec, pair);
|
||||
}
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<byte, Guid?, bool, bool, (int, (Guid Id, string Name)? OldCollection)>
|
||||
Provider(IDalamudPluginInterface pi, IPenumbraApiCollection api)
|
||||
=> new(pi, Label, (t, g, a, b) =>
|
||||
{
|
||||
var (ret, collection) = api.SetCollection((ApiCollectionType)t, g, a, b);
|
||||
return ((int)ret, collection);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.SetCollectionForObject"/>
|
||||
public sealed class SetCollectionForObject(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, Guid?, bool, bool, (int, (Guid Id, string Name)? OldCollection)>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(SetCollectionForObject)}.V5";
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.SetCollectionForObject"/>
|
||||
public new (PenumbraApiEc, (Guid Id, string Name)? OldCollection) Invoke(int gameObjectIdx, Guid? collectionId, bool allowCreateNew = true,
|
||||
bool allowDelete = true)
|
||||
{
|
||||
var (ec, pair) = base.Invoke(gameObjectIdx, collectionId, allowCreateNew, allowDelete);
|
||||
return ((PenumbraApiEc)ec, pair);
|
||||
}
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<int, Guid?, bool, bool, (int, (Guid Id, string Name)? OldCollection)>
|
||||
Provider(IDalamudPluginInterface pi, IPenumbraApiCollection api)
|
||||
=> new(pi, Label, (i, g, a, b) =>
|
||||
{
|
||||
var (ret, collection) = api.SetCollectionForObject(i, g, a, b);
|
||||
return ((int)ret, collection);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.CheckCurrentChangedItemFunc"/>
|
||||
public sealed class CheckCurrentChangedItemFunc(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<Func<string, (string ModDirectory, string ModName)[]>>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(CheckCurrentChangedItemFunc)}";
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiCollection.CheckCurrentChangedItemFunc"/>
|
||||
public new Func<string, (string ModDirectory, string ModName)[]> Invoke()
|
||||
=> base.Invoke();
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<Func<string, (string ModDirectory, string ModName)[]>>
|
||||
Provider(IDalamudPluginInterface pi, IPenumbraApiCollection api)
|
||||
=> new(pi, Label, api.CheckCurrentChangedItemFunc);
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Penumbra.Api.Api;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Api.Helpers;
|
||||
|
||||
namespace Penumbra.Api.IpcSubscribers;
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiEditing.ConvertTextureFile"/>
|
||||
public sealed class ConvertTextureFile(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, string, int, bool, Task>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(ConvertTextureFile)}";
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiEditing.ConvertTextureFile"/>
|
||||
public Task Invoke(string inputFile, string outputFile, TextureType textureType, bool mipMaps = true)
|
||||
=> Invoke(inputFile, outputFile, (int)textureType, mipMaps);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<string, string, int, bool, Task> Provider(IDalamudPluginInterface pi, IPenumbraApiEditing api)
|
||||
=> new(pi, Label, (a, b, c, d) => api.ConvertTextureFile(a, b, (TextureType)c, d));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiEditing.ConvertTextureData"/>
|
||||
public sealed class ConvertTextureData(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<byte[], int, string, int, bool, Task>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(ConvertTextureData)}";
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiEditing.ConvertTextureData"/>
|
||||
public Task Invoke(byte[] rgbaData, int width, string outputFile, TextureType textureType, bool mipMaps = true)
|
||||
=> Invoke(rgbaData, width, outputFile, (int)textureType, mipMaps);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<byte[], int, string, int, bool, Task> Provider(IDalamudPluginInterface pi, IPenumbraApiEditing api)
|
||||
=> new(pi, Label, (a, b, c, d, e) => api.ConvertTextureData(a, b, c, (TextureType)d, e));
|
||||
}
|
@@ -1,100 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Penumbra.Api.Api;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Api.Helpers;
|
||||
|
||||
namespace Penumbra.Api.IpcSubscribers;
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiGameState.GetDrawObjectInfo"/>
|
||||
public sealed class GetDrawObjectInfo(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<nint, (nint, (Guid, string))>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(GetDrawObjectInfo)}.V5";
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiGameState.GetDrawObjectInfo"/>
|
||||
public new (nint GameObject, (Guid Id, string Name) AssociatedCollection) Invoke(nint drawObjectAddress)
|
||||
=> base.Invoke(drawObjectAddress);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<nint, (nint, (Guid, string))> Provider(IDalamudPluginInterface pi, IPenumbraApiGameState api)
|
||||
=> new(pi, Label, api.GetDrawObjectInfo);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiGameState.GetCutsceneParentIndex"/>
|
||||
public sealed class GetCutsceneParentIndex(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(GetCutsceneParentIndex)}";
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiGameState.GetCutsceneParentIndex"/>
|
||||
public new int Invoke(int actorIndex)
|
||||
=> base.Invoke(actorIndex);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<int, int> Provider(IDalamudPluginInterface pi, IPenumbraApiGameState api)
|
||||
=> new(pi, Label, api.GetCutsceneParentIndex);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiGameState.SetCutsceneParentIndex"/>
|
||||
public sealed class SetCutsceneParentIndex(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, int, int>(pi, Label)
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(SetCutsceneParentIndex)}.V5";
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiGameState.SetCutsceneParentIndex"/>
|
||||
public new PenumbraApiEc Invoke(int copyIdx, int newParentIdx)
|
||||
=> (PenumbraApiEc)base.Invoke(copyIdx, newParentIdx);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static FuncProvider<int, int, int> Provider(IDalamudPluginInterface pi, IPenumbraApiGameState api)
|
||||
=> new(pi, Label, (a, b) => (int) api.SetCutsceneParentIndex(a, b));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiGameState.CreatingCharacterBase"/>
|
||||
public static class CreatingCharacterBase
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(CreatingCharacterBase)}.V5";
|
||||
|
||||
/// <summary> Create a new event subscriber. </summary>
|
||||
public static EventSubscriber<nint, Guid, nint, nint, nint> Subscriber(IDalamudPluginInterface pi,
|
||||
params Action<nint, Guid, nint, nint, nint>[] actions)
|
||||
=> new(pi, Label, actions);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static EventProvider<nint, Guid, nint, nint, nint> Provider(IDalamudPluginInterface pi, IPenumbraApiGameState api)
|
||||
=> new(pi, Label, t => api.CreatingCharacterBase += t.Invoke, t => api.CreatingCharacterBase -= t.Invoke);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiGameState.CreatedCharacterBase"/>
|
||||
public static class CreatedCharacterBase
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(CreatedCharacterBase)}.V5";
|
||||
|
||||
/// <summary> Create a new event subscriber. </summary>
|
||||
public static EventSubscriber<nint, Guid, nint> Subscriber(IDalamudPluginInterface pi, params Action<nint, Guid, nint>[] actions)
|
||||
=> new(pi, Label, actions);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static EventProvider<nint, Guid, nint> Provider(IDalamudPluginInterface pi, IPenumbraApiGameState api)
|
||||
=> new(pi, Label, t => api.CreatedCharacterBase += t.Invoke, t => api.CreatedCharacterBase -= t.Invoke);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IPenumbraApiGameState.GameObjectResourceResolved"/>
|
||||
public static class GameObjectResourcePathResolved
|
||||
{
|
||||
/// <summary> The label. </summary>
|
||||
public const string Label = $"Penumbra.{nameof(GameObjectResourcePathResolved)}";
|
||||
|
||||
/// <summary> Create a new event subscriber. </summary>
|
||||
public static EventSubscriber<nint, string, string> Subscriber(IDalamudPluginInterface pi, params Action<nint, string, string>[] actions)
|
||||
=> new(pi, Label, actions);
|
||||
|
||||
/// <summary> Create a provider. </summary>
|
||||
public static EventProvider<nint, string, string> Provider(IDalamudPluginInterface pi, IPenumbraApiGameState api)
|
||||
=> new(pi, Label, t => api.GameObjectResourceResolved += t.Invoke, t => api.GameObjectResourceResolved -= t.Invoke);
|
||||
}
|
@@ -1,99 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Api.Helpers;
|
||||
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
namespace Penumbra.Api.IpcSubscribers.Legacy;
|
||||
|
||||
public sealed class GetCollections(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<IList<string>>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(GetCollections)}";
|
||||
|
||||
public new IList<string> Invoke()
|
||||
=> base.Invoke();
|
||||
}
|
||||
|
||||
public sealed class GetCurrentCollectionName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(GetCurrentCollectionName)}";
|
||||
|
||||
public new string Invoke()
|
||||
=> base.Invoke();
|
||||
}
|
||||
|
||||
public sealed class GetDefaultCollectionName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(GetDefaultCollectionName)}";
|
||||
|
||||
public new string Invoke()
|
||||
=> base.Invoke();
|
||||
}
|
||||
|
||||
public sealed class GetInterfaceCollectionName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(GetInterfaceCollectionName)}";
|
||||
|
||||
public new string Invoke()
|
||||
=> base.Invoke();
|
||||
}
|
||||
|
||||
public sealed class GetCharacterCollectionName(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, (string, bool)>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(GetCharacterCollectionName)}";
|
||||
|
||||
public new (string, bool) Invoke(string characterName)
|
||||
=> base.Invoke(characterName);
|
||||
}
|
||||
|
||||
public sealed class GetChangedItems(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, IReadOnlyDictionary<string, object?>>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(GetChangedItems)}";
|
||||
|
||||
public new IReadOnlyDictionary<string, object?> Invoke(string collectionName)
|
||||
=> base.Invoke(collectionName);
|
||||
}
|
||||
|
||||
public sealed class GetCollectionForType(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<ApiCollectionType, string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(GetCollectionForType)}";
|
||||
|
||||
public new string Invoke(ApiCollectionType collectionType)
|
||||
=> base.Invoke(collectionType);
|
||||
}
|
||||
|
||||
public sealed class SetCollectionForType(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<ApiCollectionType, string, bool, bool, (PenumbraApiEc, string)>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(SetCollectionForType)}";
|
||||
|
||||
public new (PenumbraApiEc ErrorCode, string OldCollectionName) Invoke(ApiCollectionType collectionType, string collectionName,
|
||||
bool allowCreateNew = true, bool allowDelete = true)
|
||||
=> base.Invoke(collectionType, collectionName, allowCreateNew, allowDelete);
|
||||
}
|
||||
|
||||
public sealed class GetCollectionForObject(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, (bool, bool, string)>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(GetCollectionForObject)}";
|
||||
|
||||
public new (bool ObjectValid, bool IndividualSet, string CollectionName) Invoke(int objectIndex)
|
||||
=> base.Invoke(objectIndex);
|
||||
}
|
||||
|
||||
public sealed class SetCollectionForObject(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, string, bool, bool, (PenumbraApiEc, string)>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(SetCollectionForObject)}";
|
||||
|
||||
public new (PenumbraApiEc ErrorCode, string OldCollectionName) Invoke(int objectIndex, string collectionName, bool allowCreateNew = true,
|
||||
bool allowDelete = true)
|
||||
=> base.Invoke(objectIndex, collectionName, allowCreateNew, allowDelete);
|
||||
}
|
@@ -1,43 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Api.Helpers;
|
||||
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
namespace Penumbra.Api.IpcSubscribers.Legacy;
|
||||
|
||||
public sealed class GetDrawObjectInfo(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<nint, (nint, string)>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(GetDrawObjectInfo)}";
|
||||
|
||||
public new (nint GameObjectAddress, string CollectionName) Invoke(nint drawObjectAddress)
|
||||
=> base.Invoke(drawObjectAddress);
|
||||
}
|
||||
|
||||
public sealed class SetCutsceneParentIndex(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, int, PenumbraApiEc>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(SetCutsceneParentIndex)}";
|
||||
|
||||
public new PenumbraApiEc Invoke(int cutsceneObjectIndex, int newParentIndex)
|
||||
=> base.Invoke(cutsceneObjectIndex, newParentIndex);
|
||||
}
|
||||
|
||||
public static class CreatingCharacterBase
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(CreatingCharacterBase)}";
|
||||
|
||||
public static EventSubscriber<nint, string, nint, nint, nint> Subscriber(IDalamudPluginInterface pi,
|
||||
params Action<nint, string, nint, nint, nint>[] actions)
|
||||
=> new(pi, Label, actions);
|
||||
}
|
||||
|
||||
public static class CreatedCharacterBase
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(CreatedCharacterBase)}";
|
||||
|
||||
public static EventSubscriber<nint, string, nint> Subscriber(IDalamudPluginInterface pi,
|
||||
params Action<nint, string, nint>[] actions)
|
||||
=> new(pi, Label, actions);
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Penumbra.Api.Helpers;
|
||||
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
namespace Penumbra.Api.IpcSubscribers.Legacy;
|
||||
|
||||
public sealed class GetMetaManipulations(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(GetMetaManipulations)}";
|
||||
|
||||
public new string Invoke(string objectName)
|
||||
=> base.Invoke(objectName);
|
||||
}
|
||||
|
||||
public sealed class GetGameObjectMetaManipulations(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<int, string>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(GetGameObjectMetaManipulations)}";
|
||||
|
||||
public new string Invoke(int objectIndex)
|
||||
=> base.Invoke(objectIndex);
|
||||
}
|
@@ -1,92 +0,0 @@
|
||||
using Dalamud.Plugin;
|
||||
using Penumbra.Api.Api;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Api.Helpers;
|
||||
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
namespace Penumbra.Api.IpcSubscribers.Legacy;
|
||||
|
||||
using CurrentSettings = ValueTuple<PenumbraApiEc, (bool, int, IDictionary<string, IList<string>>, bool)?>;
|
||||
|
||||
public sealed class GetAvailableModSettings(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, string, IDictionary<string, (IList<string>, GroupType)>?>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(GetAvailableModSettings)}";
|
||||
|
||||
public new IDictionary<string, (IList<string>, GroupType)>? Invoke(string modDirectory, string modName = "")
|
||||
=> base.Invoke(modDirectory, modName);
|
||||
}
|
||||
|
||||
public sealed class GetCurrentModSettings(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, string, string, bool, CurrentSettings>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(GetCurrentModSettings)}";
|
||||
|
||||
public new CurrentSettings Invoke(string collectionName, string modDirectory, string modName = "", bool ignoreInheritance = false)
|
||||
=> base.Invoke(collectionName, modDirectory, modName, ignoreInheritance);
|
||||
}
|
||||
|
||||
public sealed class TryInheritMod(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, string, string, bool, PenumbraApiEc>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(TryInheritMod)}";
|
||||
|
||||
public PenumbraApiEc Invoke(string collectionName, string modDirectory, bool inherit, string modName = "")
|
||||
=> Invoke(collectionName, modDirectory, modName, inherit);
|
||||
}
|
||||
|
||||
public sealed class TrySetMod(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, string, string, bool, PenumbraApiEc>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(TrySetMod)}";
|
||||
|
||||
public PenumbraApiEc Invoke(string collectionName, string modDirectory, bool enabled, string modName = "")
|
||||
=> Invoke(collectionName, modDirectory, modName, enabled);
|
||||
}
|
||||
|
||||
public sealed class TrySetModPriority(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, string, string, int, PenumbraApiEc>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(TrySetModPriority)}";
|
||||
|
||||
public PenumbraApiEc Invoke(string collectionName, string modDirectory, int priority, string modName = "")
|
||||
=> Invoke(collectionName, modDirectory, modName, priority);
|
||||
}
|
||||
|
||||
public sealed class TrySetModSetting(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, string, string, string, string, PenumbraApiEc>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(TrySetModSetting)}";
|
||||
|
||||
public new PenumbraApiEc Invoke(string collectionName, string modDirectory, string groupName, string setting, string modName = "")
|
||||
=> base.Invoke(collectionName, modDirectory, modName, groupName, setting);
|
||||
}
|
||||
|
||||
public sealed class TrySetModSettings(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, string, string, string, IReadOnlyList<string>, PenumbraApiEc>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(TrySetModSettings)}";
|
||||
|
||||
public PenumbraApiEc Invoke(string collectionName, string modDirectory, string groupName, IReadOnlyList<string> settings,
|
||||
string modName = "")
|
||||
=> Invoke(collectionName, modDirectory, modName, groupName, settings);
|
||||
}
|
||||
|
||||
public static class ModSettingChanged
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(ModSettingChanged)}.V5";
|
||||
|
||||
public static EventSubscriber<ModSettingChange, string, string, bool> Subscriber(IDalamudPluginInterface pi,
|
||||
params Action<ModSettingChange, string, string, bool>[] actions)
|
||||
=> new(pi, Label, actions);
|
||||
}
|
||||
|
||||
public sealed class CopyModSettings(IDalamudPluginInterface pi)
|
||||
: FuncSubscriber<string, string, string, PenumbraApiEc>(pi, Label)
|
||||
{
|
||||
public const string Label = $"Penumbra.{nameof(CopyModSettings)}";
|
||||
|
||||
public new PenumbraApiEc Invoke(string collectionName, string modDirectoryFrom, string modDirectoryTo)
|
||||
=> base.Invoke(collectionName, modDirectoryFrom, modDirectoryTo);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user