15 Commits
v0.3 ... api9

12 changed files with 166 additions and 18 deletions

View File

@@ -35,7 +35,7 @@ namespace Pilz.Dalamud.ActivityContexts
PluginServices.ClientState.TerritoryChanged -= ClientState_TerritoryChanged; PluginServices.ClientState.TerritoryChanged -= ClientState_TerritoryChanged;
} }
private void ClientState_TerritoryChanged(object? sender, ushort e) private void ClientState_TerritoryChanged(ushort obj)
{ {
CheckCurrentTerritory(); CheckCurrentTerritory();
} }

View File

@@ -24,7 +24,7 @@ namespace Pilz.Dalamud
/// Removes a Payload from a given list. /// Removes a Payload from a given list.
/// Using <code>List.Remove()</code> does not use the reference to compare for some reason. Tis is a workaround. /// Using <code>List.Remove()</code> does not use the reference to compare for some reason. Tis is a workaround.
/// </summary> /// </summary>
/// <param name="seString"></param> /// <param name="payloads"></param>
/// <param name="payload"></param> /// <param name="payload"></param>
public static void Remove(this List<Payload> payloads, Payload payload) public static void Remove(this List<Payload> payloads, Payload payload)
{ {

View File

@@ -12,6 +12,7 @@ namespace Pilz.Dalamud.Nameplates.EventArgs
public IntPtr TitlePtr { get; set; } public IntPtr TitlePtr { get; set; }
public IntPtr NamePtr { get; set; } public IntPtr NamePtr { get; set; }
public IntPtr FreeCompanyPtr { get; set; } public IntPtr FreeCompanyPtr { get; set; }
public IntPtr PrefixPtr { get; set; }
public bool IsTitleAboveName { get; set; } public bool IsTitleAboveName { get; set; }
public bool IsTitleVisible { get; set; } public bool IsTitleVisible { get; set; }
public int IconID { get; set; } public int IconID { get; set; }

View File

@@ -19,7 +19,8 @@ namespace Pilz.Dalamud.Nameplates.EventArgs
public SafeNameplateObject SafeNameplateObject { get; set; } public SafeNameplateObject SafeNameplateObject { get; set; }
public SeString Title { get; internal set; } public SeString Title { get; internal set; }
public SeString Name { get; internal set; } public SeString Name { get; internal set; }
public SeString FreeCompany { get; set; } public SeString FreeCompany { get; internal set; }
public SeString Prefix { get; internal set; }
public bool IsTitleAboveName public bool IsTitleAboveName
{ {

View File

@@ -10,6 +10,7 @@ using System.Threading.Tasks;
using Pilz.Dalamud.Nameplates.Model; using Pilz.Dalamud.Nameplates.Model;
using Lumina.Excel.GeneratedSheets; using Lumina.Excel.GeneratedSheets;
using System.Xml.Linq; using System.Xml.Linq;
using Dalamud.Plugin.Services;
namespace Pilz.Dalamud.Nameplates namespace Pilz.Dalamud.Nameplates
{ {
@@ -28,9 +29,9 @@ namespace Pilz.Dalamud.Nameplates
public event AddonNamePlate_SetPlayerNameManagedEventHandler AddonNamePlate_SetPlayerNameManaged; public event AddonNamePlate_SetPlayerNameManagedEventHandler AddonNamePlate_SetPlayerNameManaged;
public delegate void AddonNamePlate_SetPlayerNameManagedEventHandler(AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs); public delegate void AddonNamePlate_SetPlayerNameManagedEventHandler(AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs);
[Signature("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 54 41 56 41 57 48 83 EC 40 44 0F B6 E2", DetourName = nameof(SetPlayerNameplateDetour))] [Signature("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8B 5C 24 ?? 45 38 BE", DetourName = nameof(SetPlayerNameplateDetour))]
private readonly Hook<AddonNamePlate_SetPlayerNameplateDetour>? hook_AddonNamePlate_SetPlayerNameplateDetour = null; private Hook<AddonNamePlate_SetPlayerNameplateDetour>? hook_AddonNamePlate_SetPlayerNameplateDetour = null;
private unsafe delegate IntPtr AddonNamePlate_SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId); private unsafe delegate IntPtr AddonNamePlate_SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, IntPtr prefix, int iconId);
/// <summary> /// <summary>
/// Defines if all hooks are enabled. If this is false, then there might be something wrong or the class already has been disposed. /// Defines if all hooks are enabled. If this is false, then there might be something wrong or the class already has been disposed.
@@ -52,7 +53,7 @@ namespace Pilz.Dalamud.Nameplates
/// </summary> /// </summary>
public NameplateHooks() public NameplateHooks()
{ {
SignatureHelper.Initialise(this); PluginServices.GameInteropProvider.InitializeFromAttributes(this);
} }
~NameplateHooks() ~NameplateHooks()
@@ -86,7 +87,7 @@ namespace Pilz.Dalamud.Nameplates
return hook != null && hook.IsEnabled; return hook != null && hook.IsEnabled;
} }
private IntPtr SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId) private IntPtr SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, IntPtr prefix, int iconId)
{ {
var result = IntPtr.Zero; var result = IntPtr.Zero;
@@ -98,6 +99,7 @@ namespace Pilz.Dalamud.Nameplates
TitlePtr = titlePtr, TitlePtr = titlePtr,
NamePtr = namePtr, NamePtr = namePtr,
FreeCompanyPtr = freeCompanyPtr, FreeCompanyPtr = freeCompanyPtr,
PrefixPtr = prefix,
IsTitleAboveName = isTitleAboveName, IsTitleAboveName = isTitleAboveName,
IsTitleVisible = isTitleVisible, IsTitleVisible = isTitleVisible,
IconID = iconId IconID = iconId
@@ -118,6 +120,7 @@ namespace Pilz.Dalamud.Nameplates
eventArgs.TitlePtr, eventArgs.TitlePtr,
eventArgs.NamePtr, eventArgs.NamePtr,
eventArgs.FreeCompanyPtr, eventArgs.FreeCompanyPtr,
prefix,
eventArgs.IconID); eventArgs.IconID);
}; };
@@ -130,6 +133,7 @@ namespace Pilz.Dalamud.Nameplates
var freeTitle = false; var freeTitle = false;
var freeName = false; var freeName = false;
var freeFreeCompany = false; var freeFreeCompany = false;
var freePrefix = false;
// Create NamePlateObject if possible // Create NamePlateObject if possible
var namePlateObj = new SafeNameplateObject(playerNameplateObjectPtr); var namePlateObj = new SafeNameplateObject(playerNameplateObjectPtr);
@@ -141,18 +145,20 @@ namespace Pilz.Dalamud.Nameplates
SafeNameplateObject = namePlateObj, SafeNameplateObject = namePlateObj,
Title = GameInterfaceHelper.ReadSeString(eventArgs.TitlePtr), Title = GameInterfaceHelper.ReadSeString(eventArgs.TitlePtr),
Name = GameInterfaceHelper.ReadSeString(eventArgs.NamePtr), Name = GameInterfaceHelper.ReadSeString(eventArgs.NamePtr),
FreeCompany = GameInterfaceHelper.ReadSeString(eventArgs.FreeCompanyPtr) FreeCompany = GameInterfaceHelper.ReadSeString(eventArgs.FreeCompanyPtr),
Prefix = GameInterfaceHelper.ReadSeString(eventArgs.PrefixPtr)
}; };
// Get raw string content // Get raw string content
var titleRaw = managedEventArgs.Title.Encode(); var titleRaw = managedEventArgs.Title.Encode();
var nameRaw = managedEventArgs.Name.Encode(); var nameRaw = managedEventArgs.Name.Encode();
var freeCompanyRaw = managedEventArgs.FreeCompany.Encode(); var freeCompanyRaw = managedEventArgs.FreeCompany.Encode();
var prefixRaw = managedEventArgs.Prefix.Encode();
// Invoke Managed Event // Invoke Managed Event
AddonNamePlate_SetPlayerNameManaged.Invoke(managedEventArgs); AddonNamePlate_SetPlayerNameManaged.Invoke(managedEventArgs);
// Get new Title string ontent // Get new Title string content
var titleNewRaw = managedEventArgs.Title.Encode(); var titleNewRaw = managedEventArgs.Title.Encode();
if (!titleRaw.SequenceEqual(titleNewRaw)) if (!titleRaw.SequenceEqual(titleNewRaw))
{ {
@@ -160,7 +166,7 @@ namespace Pilz.Dalamud.Nameplates
freeTitle = true; freeTitle = true;
} }
// Get new Name string ontent // Get new Name string content
var nameNewRaw = managedEventArgs.Name.Encode(); var nameNewRaw = managedEventArgs.Name.Encode();
if (!nameRaw.SequenceEqual(nameNewRaw)) if (!nameRaw.SequenceEqual(nameNewRaw))
{ {
@@ -168,7 +174,7 @@ namespace Pilz.Dalamud.Nameplates
freeName = true; freeName = true;
} }
// Get new Free Company string ontent // Get new Free Company string content
var freeCompanyNewRaw = managedEventArgs.FreeCompany.Encode(); var freeCompanyNewRaw = managedEventArgs.FreeCompany.Encode();
if (!freeCompanyRaw.SequenceEqual(freeCompanyNewRaw)) if (!freeCompanyRaw.SequenceEqual(freeCompanyNewRaw))
{ {
@@ -176,6 +182,14 @@ namespace Pilz.Dalamud.Nameplates
freeFreeCompany = true; freeFreeCompany = true;
} }
// Get new Prefix string content
var prefixNewRaw = managedEventArgs.Prefix.Encode();
if (!prefixRaw.SequenceEqual(prefixNewRaw))
{
eventArgs.PrefixPtr = GameInterfaceHelper.PluginAllocate(prefixNewRaw);
freePrefix = true;
}
// Call Original as we changed something // Call Original as we changed something
callOriginal(); callOriginal();
@@ -186,6 +200,8 @@ namespace Pilz.Dalamud.Nameplates
GameInterfaceHelper.PluginFree(eventArgs.NamePtr); GameInterfaceHelper.PluginFree(eventArgs.NamePtr);
if (freeFreeCompany) if (freeFreeCompany)
GameInterfaceHelper.PluginFree(eventArgs.FreeCompanyPtr); GameInterfaceHelper.PluginFree(eventArgs.FreeCompanyPtr);
if (freePrefix)
GameInterfaceHelper.PluginFree(eventArgs.PrefixPtr);
} }
else if(!hasDefaultHookEvent) else if(!hasDefaultHookEvent)
{ {

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Pilz.Dalamud.Nameplates.EventArgs;
using Pilz.Dalamud.Tools.Strings; using Pilz.Dalamud.Tools.Strings;
namespace Pilz.Dalamud.Nameplates.Tools namespace Pilz.Dalamud.Nameplates.Tools
@@ -18,6 +19,13 @@ namespace Pilz.Dalamud.Nameplates.Tools
changes.Add(NameplateElements.FreeCompany, new()); changes.Add(NameplateElements.FreeCompany, new());
} }
public NameplateChanges(AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs) : this()
{
GetProps(NameplateElements.Title).Destination = eventArgs.Title;
GetProps(NameplateElements.Name).Destination = eventArgs.Name;
GetProps(NameplateElements.FreeCompany).Destination = eventArgs.FreeCompany;
}
/// <summary> /// <summary>
/// Gets the properties with the changes of an element of your choice where you can add your payloads to a change and setup some options. /// Gets the properties with the changes of an element of your choice where you can add your payloads to a change and setup some options.
/// </summary> /// </summary>
@@ -42,6 +50,7 @@ namespace Pilz.Dalamud.Nameplates.Tools
/// Gets a change of the position of the element of your choice where you can add your payloads. /// Gets a change of the position of the element of your choice where you can add your payloads.
/// </summary> /// </summary>
/// <param name="element">The position of your choice.</param> /// <param name="element">The position of your choice.</param>
/// <param name="position">The position of your choice.</param>
/// <returns></returns> /// <returns></returns>
public StringChange GetChange(NameplateElements element, StringPosition position) public StringChange GetChange(NameplateElements element, StringPosition position)
{ {

View File

@@ -12,5 +12,14 @@ namespace Pilz.Dalamud.Nameplates.Tools
/// All the changes to the nameplate that should be made. /// All the changes to the nameplate that should be made.
/// </summary> /// </summary>
public NameplateChanges Changes { get; set; } public NameplateChanges Changes { get; set; }
public NameplateChangesProps()
{
}
public NameplateChangesProps(NameplateChanges changes) : this()
{
Changes = changes;
}
} }
} }

View File

@@ -28,7 +28,7 @@ namespace Pilz.Dalamud.Nameplates.Tools
/// taking into account whether or not the player is in a duty. /// taking into account whether or not the player is in a duty.
/// </summary> /// </summary>
/// <param name="iconId">The incoming icon id that is being overwritten by the plugin.</param> /// <param name="iconId">The incoming icon id that is being overwritten by the plugin.</param>
/// <param name="priorityIconId">The icon id that should be used.</param> /// <param name="activityContext"></param>
/// <returns>Whether a priority icon was found.</returns> /// <returns>Whether a priority icon was found.</returns>
public bool IsPriorityIcon(int iconId, ActivityContext activityContext) public bool IsPriorityIcon(int iconId, ActivityContext activityContext)
{ {

View File

@@ -21,12 +21,21 @@
<GeneratePackageOnBuild>False</GeneratePackageOnBuild> <GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<Copyright>Pilzinsel64</Copyright> <Copyright>Pilzinsel64</Copyright>
<PackageProjectUrl>https://github.com/Pilzinsel64/Pilz.Dalamud</PackageProjectUrl> <PackageProjectUrl>https://github.com/Pilzinsel64/Pilz.Dalamud</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/Pilzinsel64/Pilz.Dalamud</RepositoryUrl> <RepositoryUrl>https://github.com/Pilzinsel64/Pilz.Dalamud</RepositoryUrl>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<Version>0.3.0</Version> <Version>0.5.1</Version>
<GenerateDocumentationFile>True</GenerateDocumentationFile> <GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="FFXIVClientStructs"> <Reference Include="FFXIVClientStructs">
<HintPath>$(DalamudLibPath)FFXIVClientStructs.dll</HintPath> <HintPath>$(DalamudLibPath)FFXIVClientStructs.dll</HintPath>
@@ -58,4 +67,8 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="..\README.md" Pack="true" PackagePath="\" />
</ItemGroup>
</Project> </Project>

View File

@@ -4,6 +4,7 @@ using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
using Dalamud.IoC; using Dalamud.IoC;
using Dalamud.Plugin; using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -14,11 +15,12 @@ namespace Pilz.Dalamud
{ {
public class PluginServices public class PluginServices
{ {
[PluginService] public static GameGui GameGui { get; set; } = null;
[PluginService] public static DalamudPluginInterface PluginInterface { get; set; } = null; [PluginService] public static DalamudPluginInterface PluginInterface { get; set; } = null;
[PluginService] public static ClientState ClientState { get; set; } = null; [PluginService] public static IGameGui GameGui { get; set; } = null;
[PluginService] public static DataManager DataManager { get; set; } = null; [PluginService] public static IClientState ClientState { get; set; } = null;
[PluginService] public static ObjectTable ObjectTable { get; set; } = null; [PluginService] public static IDataManager DataManager { get; set; } = null;
[PluginService] public static IObjectTable ObjectTable { get; set; } = null;
[PluginService] public static IGameInteropProvider GameInteropProvider { get; set; } = null;
public static void Initialize(DalamudPluginInterface dalamudPluginInterface) public static void Initialize(DalamudPluginInterface dalamudPluginInterface)
{ {

View File

@@ -8,6 +8,97 @@ At the moment it's far away from being complete or even good. Right now it as so
Install the latest version of `Pilz.Dalamud` via NuGet Package Manager or NuGet Console:\ Install the latest version of `Pilz.Dalamud` via NuGet Package Manager or NuGet Console:\
https://www.nuget.org/packages/Pilz.Dalamud https://www.nuget.org/packages/Pilz.Dalamud
## Get started
### Initialize Plugin Services
To be able to use most features of that lib you must initialize the Plugin Services. The best time to do this is when you initialize your own Plugin Services at your IDalamudPlugin class constructor.
```cs
public Plugin(DalamudPluginInterface pluginInterface)
{
// Initialize our own Plugin Services if we use them
PluginServices.Initialize(pluginInterface);
// Initialize Plugin Services for `Pilz.Dalamud` because the lib uses them
Pilz.Dalamud.PluginServices.Initialize(pluginInterface);
}
```
### Hook into Nameplates
To edit the nameplate, you first need to hook and listen to the Game's updates. Also don't forget to unhook and dispose on unloading the plugins!
```cs
public class NameplateFeature : IDisposable
{
public NameplateManager NameplateManager { get; init; }
/// <summary>
/// Occurs when a player nameplate is updated by the game.
/// </summary>
public event PlayerNameplateUpdatedDelegate? PlayerNameplateUpdated;
public NameplateFeature()
{
NameplateManager = new();
NameplateManager.Hooks.AddonNamePlate_SetPlayerNameManaged += Hooks_AddonNamePlate_SetPlayerNameManaged;
}
public void Dispose()
{
NameplateManager.Hooks.AddonNamePlate_SetPlayerNameManaged -= Hooks_AddonNamePlate_SetPlayerNameManaged;
NameplateManager.Dispose();
}
private void Hooks_AddonNamePlate_SetPlayerNameManaged(Pilz.Dalamud.Nameplates.EventArgs.AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs)
{
}
}
```
This is an example of editing the title to "Good Player", make the name italic and also force the title to always be above the name:
```cs
private void Hooks_AddonNamePlate_SetPlayerNameManaged(Pilz.Dalamud.Nameplates.EventArgs.AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs)
{
try
{
// Get the referenced player object for the nameplate object
PlayerCharacter? playerCharacter = NameplateManager.GetNameplateGameObject<PlayerCharacter>(eventArgs.SafeNameplateObject);
if (playerCharacter != null && playerCharacter.StatusFlags.HasFlag(StatusFlags.Friend))
{
const string TEXT_GOOD_PLAYER = "Good Player";
// Create a new change
var nameplateChanges = new NameplateChanges(eventArgs);
// Replace the title
var titleChange = nameplateChanges.GetChange(NameplateElements.Title, StringPosition.Replace);
titleChange.Payloads.Add(new TextPayload(TEXT_GOOD_PLAYER));
// Make the name italic
var nameChangeBefore = nameplateChanges.GetChange(NameplateElements.Name, StringPosition.Before);
nameChangeBefore.Payloads.Add(new EmphasisItalicPayload(true));
var nameChangeAfter = nameplateChanges.GetChange(NameplateElements.Name, StringPosition.After);
nameChangeAfter.Payloads.Add(new EmphasisItalicPayload(false));
// Forge the title to be always above the name (this we can edit directly)
eventArgs.IsTitleAboveName = true;
// Apply the string changes!
NameplateUpdateFactory.ApplyNameplateChanges(new NameplateChangesProps(nameplateChanges));
}
}
catch (Exception ex)
{
PluginLog.Error(ex, $"SetPlayerNameplateDetour");
}
}
```
## Contribute ## Contribute
- Freel free to PR changes or new features/libraries. - Freel free to PR changes or new features/libraries.

6
packages.lock.json Normal file
View File

@@ -0,0 +1,6 @@
{
"version": 1,
"dependencies": {
"net7.0-windows7.0": {}
}
}