# Dalamud v15.0.2.3 Post-Tag Master Update - Public Report

Checked: `2026-07-28 05:47:50 -06:00`

> **Superseded endpoint notice - 2026-07-28 10:54:26 -06:00**
>
> Patch 7.55 Beta is active and STG now serves `15.0.3.0` at `e1922583`.
> This report remains the historical pre-Beta `42f787c9` review. Use
> `Dalamud Patch 7.55 Beta Recheck 2026-07-28 - Public Report.md` for the
> current shareable status.

## Release Status

There is no new tagged Dalamud runtime in this review.

- Latest runtime tag: `15.0.2.3` at `91ad60c8`
- Current `master`: `42f787c9`
- Formal GitHub release: still `14.0.4.0`
- Plugin SDK: still `Dalamud.NET.Sdk/15.0.0`
- Packager: still `DalamudPackager/15.0.0`

Everything after `15.0.2.3` in this report is post-tag development work. It is a preview and validation watchlist, not a requirement for plugins running on the tagged `15.0.2.3` runtime.

## Sources

- Dalamud repository: <https://github.com/goatcorp/Dalamud>
- Previous-to-current master compare: <https://github.com/goatcorp/Dalamud/compare/f042ab17b43a47f0430cdb2e0d6a4f8393e14cea...42f787c9b56c62aa12d8d4481d287689ee4491c3>
- Runtime-tag-to-current-master compare: <https://github.com/goatcorp/Dalamud/compare/91ad60c88cde1932bb1a1d9c931ff9d4a670c1ef...42f787c9b56c62aa12d8d4481d287689ee4491c3>
- Current master commit: <https://github.com/goatcorp/Dalamud/commit/42f787c9b56c62aa12d8d4481d287689ee4491c3>
- Current v15 documentation: <https://dalamud.dev/versions/v15/>
- Current API reference: <https://dalamud.dev/api/>
- FFXIVClientStructs comparison: <https://github.com/aers/FFXIVClientStructs/compare/8ff04195c4e77ef0b85d15c6fd1c67785378f0fb...79126fb2530ccf41e52f48df876d9af9a4b5789f>
- Lumina.Excel comparison: <https://github.com/NotAdam/Lumina.Excel/compare/23d2cee087e981f6ee5bd5d76ec2affb6752ff86...fe550d0871779f1bef6175017265db99e507fe57>
- Excel schema comparison: <https://github.com/xivdev/EXDSchema/compare/f5c7ec86cf0364515dd67a9162c9700242fa0f7f...15433efe54ec0130c03d1e133053b559f2aa3bda>
- Open ClientStructs update PR: <https://github.com/goatcorp/Dalamud/pull/2899>
- SDK package index: <https://api.nuget.org/v3-flatcontainer/dalamud.net.sdk/index.json>
- Packager package index: <https://api.nuget.org/v3-flatcontainer/dalamudpackager/index.json>

## Before And After

| Area | Before: 2026-07-25 review | After: 2026-07-28 review |
| --- | --- | --- |
| Runtime tag | `15.0.2.3` / `91ad60c8` | unchanged |
| `master` | `f042ab17` | `42f787c9` |
| Incremental master delta | baseline | 40 commits, 33 changed files |
| Tag-to-master delta | 33 commits, 45 files | 73 commits, 72 files |
| ClientStructs used by `master` | `8ff04195` | `79126fb2` |
| Lumina.Excel used by `master` | `23d2cee0` | `fe550d08` |
| Excel schema behind Lumina.Excel | `f5c7ec86` | `15433efe` |
| Hook package in Dalamud source | `goatcorp.Reloaded.Hooks 4.2.0-goatcorp8` | `4.2.1` |
| Public SDK and packager | `15.0.0` | unchanged |

## What Changed On Master

### 1. Shutdown And Service Unloading

Dalamud's shutdown path was substantially reworked:

- plugin unloading is now owned directly by `PluginManager`;
- framework update dispatch stops as shutdown begins;
- delayed framework tasks are cancelled and cleared;
- service-container continuations use the unload cancellation token and the default scheduler;
- shared-texture release work stops with game shutdown;
- pending HTTP work is cancelled during disposal;
- font rebuild requests stop once the font system begins shutting down;
- repeated unload requests and duplicate framework ticks are guarded;
- the framework destroy hook is global to reduce a teardown race.

This is primarily a reliability improvement inside Dalamud. For plugin authors, the practical review target is disposal code that assumes future framework ticks will still occur or that callbacks can continue after teardown begins.

### 2. Hooking And Allocator Work

The optional SafetyHook backend reported in the prior review remains post-tag. The newer master delta also:

- adds an address-space diagnostic widget for hook allocation;
- bumps `goatcorp.Reloaded.Hooks` from `4.2.0-goatcorp8` to `4.2.1`;
- aligns Reloaded hook allocation behavior with newer allocator changes.

There is no tagged public `Hook<T>` migration in this review. Hook-heavy plugins should still prioritize repeated enable, disable, reload, and dispose testing when these changes reach a runtime tag.

### 3. FFXIVClientStructs Movement

Dalamud master moved its ClientStructs pin from `8ff04195` to `79126fb2`:

- 41 ClientStructs commits;
- 29 changed files;
- new quest-effect, character draw-data, camera, network packet, layout, agent, and GUI component surfaces;
- `CameraManager` gained an offscreen-camera pointer;
- `UIModuleInterface` reward methods were corrected and renamed;
- two unknown GUI component types received XBM names;
- `DrawObjectData.DrawObject` became obsolete in favor of `DrawData.DrawObject`;
- several native signatures and generator outputs changed.

An additional open PR proposes another ClientStructs update for Patch 7.55. It is open and untagged, so it must not be treated as a current runtime requirement.

### 4. Excel Schema Movement

Lumina.Excel moved one commit and updated its schema submodule across 19 schema files. The affected sheets include shop, instance-content, model, quest, item-stain, UI constant, and field-operation data.

This does not require a new SDK version. Plugins that consume any changed sheet should rebuild and verify field meaning after the schema update reaches a runtime tag.

### 5. Nullable Reference Types

Dalamud enabled nullable reference types centrally across its own projects. This is a source-quality/build change inside Dalamud, not a new plugin API contract and not a reason to change a plugin's SDK reference.

## Before > After Codebase Examples

These examples are preparation patterns for a future tagged runtime. They are not mandatory edits for `15.0.2.3`.

### Idempotent plugin disposal

Before:

```csharp
public void Dispose()
{
    framework.Update -= OnUpdate;
    hook?.Dispose();
    windowSystem.RemoveAllWindows();
}
```

After:

```csharp
private bool disposed;

public void Dispose()
{
    if (disposed)
        return;

    disposed = true;

    framework.Update -= OnUpdate;
    windowSystem.RemoveAllWindows();

    hook?.Dispose();
    hook = null;
}
```

Reason: the new shutdown path is more explicit about cancellation and teardown ordering. Plugin cleanup should be safe if called while framework work is stopping and should not depend on another tick.

### Cancel work before releasing native resources

Before:

```csharp
public void Dispose()
{
    hook?.Dispose();
    cancellationTokenSource.Cancel();
}
```

After:

```csharp
public void Dispose()
{
    cancellationTokenSource.Cancel();
    framework.Update -= OnUpdate;

    hook?.Dispose();
    hook = null;

    cancellationTokenSource.Dispose();
}
```

Reason: stop new callbacks and cancel pending work before freeing hooks, textures, or other resources used by that work.

### Reacquire native pointers

Before:

```csharp
private CameraManager* cameraManager = CameraManager.Instance();
```

After:

```csharp
var cameraManager = CameraManager.Instance();
if (cameraManager == null || cameraManager->Camera == null)
    return;

UseCamera(cameraManager->Camera);
```

Reason: ClientStructs movement and framework teardown both make long-lived native pointers a poor ownership boundary. Reacquire and validate them at the point of use.

### Treat schema updates as typed-data changes

Before:

```csharp
var row = dataManager.GetExcelSheet<SpecialShop>().GetRow(rowId);
UseColumnByAssumedPosition(row);
```

After:

```csharp
var sheet = dataManager.GetExcelSheet<SpecialShop>();
if (sheet.TryGetRow(rowId, out var row))
    UseNamedGeneratedFields(row);
```

Reason: schema movement should be handled through current generated fields and explicit missing-row behavior, not positional assumptions.

## PR Classification

### Current runtime tag requirements

- None beyond the already reviewed `15.0.2.3` runtime.

### Merged post-tag master watch items

- cleaner service and plugin shutdown;
- framework shutdown and destroy-hook race fixes;
- global nullable reference types;
- ClientStructs and Excel schema updates;
- Reloaded.Hooks `4.2.1`;
- hook address-space diagnostics.

### Open or pending watch items

- `#2899` - another ClientStructs pin update for Patch 7.55. It is open, clean, and untagged at the time of this review.

### Closed-unmerged no-action items

- No closed-unmerged item was promoted into this report.

## Validation Checklist For A Future Tag

- Keep project SDK references at `Dalamud.NET.Sdk/15.0.0` unless the public package index changes.
- Rebuild with current generated ClientStructs bindings.
- Load, unload, and reload hook-heavy plugins repeatedly.
- Confirm no framework callback runs after plugin disposal.
- Confirm delayed `RunOnTick` work cancels or completes deterministically during unload.
- Retest managed fonts, textures, and shared textures during reload and game shutdown.
- Retest direct camera, character draw-data, `UIModuleInterface`, GUI component, agent, and packet consumers.
- Retest any consumer of the 19 changed Excel schemas.
- Recheck open PR `#2899` and FFXIVClientStructs `main` immediately before a later runtime-tag review.

## Current Conclusion

The public runtime did not change, so no plugin should claim a new runtime migration requirement from this report. The documentation update is necessary because master now contains substantial teardown, hook dependency, ClientStructs, and Excel schema movement.

The highest-value preparation is idempotent disposal, cancellation-aware framework work, hook lifecycle smoke testing, direct native-pointer validation, and a fresh schema check after these changes are included in a tagged runtime.
