What's New in Dalamud v15
This version is not finalized, and all details here are subject to change.
Dalamud v15 is the current major version of Dalamud, and will release with Patch 7.5. This is a high-level overview of changes. You can see a code diff of all of these changes here.
Key Information
- Branch:
api15(view on GitHub) - Release Date: TBA
- API Level: 15
- .NET Version: .NET 10.0.0
If you haven't done so yet, we strongly recommend migrating your plugin project to Dalamud.NET.Sdk.
It includes the latest version of DalamudPackager, pinned to the current API level, and will make it easier for us to introduce changes to how we distribute SDK files in the future.
Major Changes
New Features
IAsyncDalamudPlugin
We have added a new plugin base interface centered around asynchronous functions. This new interface is designed to reduce friction when needing to do async work during load and unload (foregoing the usage of patterns like Task.Run().GetAwaiter().GetResult()), and encourage developers to not block the main thread unnecessarily, leading to hitches. It is currently still experimental, as it's somewhat fresh and not thoroughly tested, but the interface itself is stable.
Plugins utilizing this interface fully initialize and uninitialize off the main thread. It offers a new Task LoadAsync(CancellationToken) function to accomplish this and inherits from IAsyncDisposable instead of IDisposable. The load task may be cancelled after a timeout, currently set at 60 seconds (may be changed later upon feedback), and the plugin is not considered loaded until this task completes successfully.
Async disposal through IAsyncDisposable is not cancellable. The plugin must resolve this task and dispose its resources in a timely fashion.

Changes to existing features
IChatGui
- The parameters passed to events were moved into an
IChatMessageinterface.
IMutableChatMessagecontains setters for theSenderandMessageproperties.
IHandleableChatMessagecontains aPreventOriginal()function to mark the message as handled. - The value of
XivChatTypeis now properly parsed and its previously packed relation data is now exposed via theXivChatRelationKindpropertiesSourceKindandTargetKind.
This means that theXivChatTypeenum can now be used with its intended values, which are RowIds of the LogKind sheet.
Plugins that were previously relying on invalid, out-of-rangeXivChatTypevalues (above 110) will need to update their logic.
Remember to try out the LogMessage event introduced in API 14, which may be a
suitable alternative for intercepting system messages.
ImRaii
IEndObjects have been removed as they box the value and cause an impact on
performance and allocation of memory building GC pressure.
The change implements them as ref struct, which will prevent boxing and is in
general less costly than a class, only Push... functions are still classes
that can be taken across scope.
- Everything remains in the same scope, if
varwas used nothing needs to be changed. ColorDisposableandStyleDisposablereplaceIEndObjectfor properties used inPreDraw/PostDraw.
Important:
Group,Tooltip, andDisabledhave no bool conversion, they can never fail.
using (ImRaii.Tooltip())
{
ImGui.Text("Some text for the tooltip");
ImGui.Image(image.Handle, image.Size)
ImGui.Text("Final words before tooltip is ended");
}
New additions:
ImRaii.Header(ImU8String label, ImGuiTreeNodeFlags flags)ImRaii.Header(ImU8String label, ref bool visible, ImGuiTreeNodeFlags flags)ImRaii.PushColor(ImGuiCol idx, Vector4? color, bool condition = true)ImRaii.Columns(int count, ImU8String id, bool border = false)
Minor Changes
Dalamud Font Assets
Language-specific Noto Sans fonts have been unified and renamed to NotoSansCjkRegular and NotoSansCjkMedium respectively.
Additonally, the new ttc format requires the specification of
the requested language type, which has been added as FontNo to IFontSpec
/// The index corresponds to the font face order in the TTC:
/// <list type="bullet">
/// <item><description>0 = Japanese</description></item>
/// <item><description>1 = Traditional Chinese</description></item>
/// <item><description>2 = Simplified Chinese</description></item>
/// <item><description>3 = Korean</description></item>
/// </list>
New Features
IAgentLifecycle
-
PreventOriginalfunction was added to allow you to prevent an event from being processed by the game. Example use-case: preventing the game from responding to certain kinds of ReceiveEvent calls. -
Enable Agent Lifecycletoggle added to/xldevbar allows you to disable the service and restore the original virtual tables for use in debugging/tracing calls. Re-enabling the service will reapply the virtual tables on next frame.
IAddonLifecycle
-
PreventOriginalfunction was added to allow you to prevent an event from being processed by the game. Example use-case: prevent the game from opening a window. -
Enable Addon Lifecycletoggle added to/xldevbar allows you to disable the service and restore the original virtual tables for use in debugging/tracing calls. Re-enabling the service will not affect already opened windows, they will need to be closed and re-opened to re-enable the hooks.
Changes to existing features
IClientState
ZoneInitEventArgswas updated to use RowRefs. Additionally, the arraysActiveFestivalsandActiveFestivalPhaseswere merged into a singleIReadOnlyList<FestivalEntry> ActiveFestivals.
IDutyState
- A new
IDutyStateEventArgsinterface is now passed to all events, which contains the previously passed TerritoryType RowId as RowRef.
UiDebug Widget
- Widget will now show custom nodes by typename or custom name. If you are allocating nodes and attaching them to
the games ui, you can use the DataShare name:
StringMappedCustomNodeswith type:ConcurrentDictionary<nint, string>to map an address to a label to be shown in UiDebug.
Distributed manifest must be accurate
Up until now, when Dalamud installed a plugin, the InternalName.json file
inside the plugin zip archive would be overwritten with the manifest from the
repository. This is no longer the case to aid with consistency and a possible
future repo schema change, but this also means that you must ensure that your
zip contains a manifest and that it is accurate.
IGameGui
OpenMapWithMapLink(uint territory, uint map, Vector3 worldPos)has been added as overload to remove the need forMapLinkPayload
SDK & Packages
We have released new packages of the SDK and DalamudPackager for this Dalamud API version.
- Dalamud.NET.Sdk v14.0.2
- To upgrade, change the header of your plugins'
.csprojfile:<Project Sdk="Dalamud.NET.Sdk/14.0.2">
- To upgrade, change the header of your plugins'
- DalamudPackager v14.0.2
- You don't need to reference DalamudPackager manually if you use Dalamud.NET.Sdk, it is done for you.
Renames and Refactors
ICharacter.Customizeis now aSpan<byte>instead ofbyte[]- 32-bit functions and attributes have been removed from
BaseAddressResolverandISigScanner IPartyMember.ContentIdis nowulongIClientState.LocalPlayerandIClientState.LocalContentIdhave been removed in favor of equivalent attributes inIPlayerState
Known Issues
None yet.
Contributors
We want to thank the following 31 contributors for their work on Dalamud between version 14 and 15.
- 0x0ade
- allandiego
- AtmoOmen
- balloon41
- CMDRNuffin
- Critical-Impact
- Exter-N
- Glorou
- goaaats
- Haselnussbomber
- Infiziert90
- Ivinedra
- KazWolfe
- Limiana
- Loskh
- marzent
- MidoriKami
- mwalczyk81
- nebel
- NotNite
- Ottermandias
- pohky
- RedworkDE
- reiichi001
- RokasKil
- Soreepeong
- universalconquistador
- vmfunc
- wolfcomp
FFXIVClientStructs Changes
FFXIVClientStructs will introduce their own breaking changes for Patch 7.5, which will be documented on their docs page.
We want to thank aers, Caraxi, Haselnussbomber, Pohky, WildWolf and the other FFXIVClientStructs contributors for their work.