Skip to content

Commit

Permalink
Merge branch 'main' of github.com:goatcorp/dalamud-docs into update-g…
Browse files Browse the repository at this point in the history
…uidelines
  • Loading branch information
philpax committed Mar 11, 2024
2 parents 04b379f + 66c3a44 commit b17f873
Show file tree
Hide file tree
Showing 12 changed files with 811 additions and 526 deletions.
24 changes: 15 additions & 9 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
name: Lint

on:
pull_request:
branches:
- main
on: [push, pull_request]

permissions:
checks: write
Expand All @@ -13,10 +10,19 @@ jobs:
name: Run linters
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
- name: Checkout
uses: actions/checkout@v3
- name: Run linters
uses: wearerequired/lint-action@v2
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
eslint: true
eslint_extensions: js,jsx,ts,tsx,md,mdx
version: 8
run_install: false
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Run lint
run: pnpm run lint-ci
2 changes: 2 additions & 0 deletions docs/faq/development.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
sidebar_position: 5
---

{/* lint disable maximum-heading-length */}

# Development

```mdx-code-block
Expand Down
2 changes: 2 additions & 0 deletions docs/faq/reverse-engineering.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
sidebar_position: 6
---

{/* lint disable maximum-heading-length */}

# Reverse Engineering

```mdx-code-block
Expand Down
63 changes: 44 additions & 19 deletions docs/plugin-development/how-tos/AddonEventManager.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
<!--lint disable no-file-name-mixed-case-->

# AddonEventManager

This service provides a manager for adding and removing custom events from the native game ui.
These events are tracked and managed by Dalamud and automatically removed if your plugin unloads or if the addon they are attached to is unloaded.
This service provides a manager for adding and removing custom events from the
native game ui. These events are tracked and managed by Dalamud and
automatically removed if your plugin unloads or if the addon they are attached
to is unloaded.

When adding events you will be given a handle to that event, you'll need that handle to manually unregister that event.
When adding events you will be given a handle to that event, you'll need that
handle to manually unregister that event.

## Provided Interface

```cs
public interface IAddonEventManager
{
Expand All @@ -22,21 +28,27 @@ public interface IAddonEventManager
```

## Node and Components
*You must register a `Node` for events, you can not register a `Component`, attempting to register the address of a `Component` will result in a crash.*

_You must register a `Node` for events, you can not register a `Component`,
attempting to register the address of a `Component` will result in a crash._

Valid Node types will have their type names ending in `Node`.

In the picture below, if you have a `AtkComponentButton*` you will likely want to access the `OwnerNode` property and use that node for registration.
In the picture below, if you have a `AtkComponentButton*` you will likely want
to access the `OwnerNode` property and use that node for registration.

![image](https://github.com/MidoriKami/dalamud-docs/assets/9083275/e4c00a43-67e4-4164-8338-6862e4e12182)

## Registering Events
When registering events you need to provide the pointer to the addon (AtkUnitBase*),
and a pointer to an node (AtkResNode*), along with what event you want to trigger it, and your delegate.

When registering events you need to provide the pointer to the addon
(AtkUnitBase\*), and a pointer to an node (AtkResNode\*), along with what event
you want to trigger it, and your delegate.

You may need to modify the nodeflags to allow that node to respond to events.

This system pairs very well with the IAddonLifecycle service, to allow you to register events when an addon is setup easily.
This system pairs very well with the IAddonLifecycle service, to allow you to
register events when an addon is setup easily.

```cs
// Register listener for MonsterNote setup
Expand All @@ -58,7 +70,7 @@ private void OnPostSetup(AddonEvent type, AddonArgs args)
private void TooltipHandler(AddonEventType type, IntPtr addon, IntPtr node)
{
var addonId = ((AtkUnitBase*) addon)->ID;

switch (type)
{
case AddonEventType.MouseOver:
Expand All @@ -72,17 +84,23 @@ private void TooltipHandler(AddonEventType type, IntPtr addon, IntPtr node)
}
```

The result of this example code is the text node containing the class of the current selected hunting log will show a tooltip when moused over.
The result of this example code is the text node containing the class of the
current selected hunting log will show a tooltip when moused over.

![image](https://github.com/goatcorp/dalamud-docs/assets/9083275/0b859b62-085c-4879-9316-2136232a3fc5)

## Unregistering Events
For events added to non-persistent addons (addons that setup and finalize when opened and closed) they do not need to be manually removed
as the system will automatically untrack and remove any registered events when an addon closes.

For any events added to persistent addons (addons that are always present, such as "_BagWidget", "NamePlate"), you need to save the event handle returned from AddEvent and use that to unregister your events.
For events added to non-persistent addons (addons that setup and finalize when
opened and closed) they do not need to be manually removed as the system will
automatically untrack and remove any registered events when an addon closes.

All registered events are automatically removed from native when your plugin unloads.
For any events added to persistent addons (addons that are always present, such
as "\_BagWidget", "NamePlate"), you need to save the event handle returned from
AddEvent and use that to unregister your events.

All registered events are automatically removed from native when your plugin
unloads.

Here is an example of saving and removing your event handles.

Expand Down Expand Up @@ -115,9 +133,11 @@ private void UnregisterEvents()
```

## Cursor API

This service also provides access to functions to change the game cursor icon.

This is useful to indicate to your users that an element can be clicked on to trigger an on-click event.
This is useful to indicate to your users that an element can be clicked on to
trigger an on-click event.

```cs
// Register listener for MonsterNote setup
Expand All @@ -131,7 +151,7 @@ private void OnPostSetup(AddonEvent type, AddonArgs args)
var targetNode = addon->GetNodeById(22);

targetNode->NodeFlags |= NodeFlags.EmitsEvents | NodeFlags.RespondToMouse | NodeFlags.HasCollision;

EventManager.AddEvent((nint) addon, (nint) targetNode, AddonEventType.MouseOver, OnClickHandler);
EventManager.AddEvent((nint) addon, (nint) targetNode, AddonEventType.MouseOut, OnClickHandler);
EventManager.AddEvent((nint) addon, (nint) targetNode, AddonEventType.MouseClick, OnClickHandler);
Expand All @@ -148,19 +168,24 @@ private void OnClickHandler(AddonEventType type, IntPtr addon, IntPtr node)
case AddonEventType.MouseOut:
EventManager.ResetCursor();
break;

case AddonEventType.MouseClick:
// Do custom click logic here.
break;
}
}
```

The result of this example code is the text node containing the class of the current selecting hunting log will trigger your function when clicked on, and changes the game cursor to indicate it is clickable.
The result of this example code is the text node containing the class of the
current selecting hunting log will trigger your function when clicked on, and
changes the game cursor to indicate it is clickable.

![image](https://github.com/goatcorp/dalamud-docs/assets/9083275/78566abc-1f03-41cf-8973-dc3d3186b717)

## Logging
Whenever events are added or removed they are logged to `AddonEventManager` under the verbose logging channel, this can be very useful to see what is happening to your events

Whenever events are added or removed they are logged to `AddonEventManager`
under the verbose logging channel, this can be very useful to see what is
happening to your events

![image](https://github.com/goatcorp/dalamud-docs/assets/9083275/77cb00ed-e5ea-4219-82fa-ce22b92a41ad)
68 changes: 43 additions & 25 deletions docs/plugin-development/how-tos/AddonLifecycle.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
<!--lint disable no-file-name-mixed-case-->

# AddonLifecycle

This service provides you very easy access to various states and state changes for `Addons`.
This service provides you very easy access to various states and state changes
for `Addons`.

The primary goal of this service is to make it easy to modify the native ui, or
get data from addons without needing to reverse engineer and subsequently hook
each and every addon that you need to interact with.

The primary goal of this service is to make it easy to modify the native ui,
or get data from addons without needing to reverse engineer and subsequently hook each and every addon that you need to interact with.
Sometimes an addon doesn't implement its own Draw or other functions, which
makes it quite challenging to hook something that will trigger when you need to
trigger your code.

Sometimes an addon doesn't implement its own Draw or other functions,
which makes it quite challenging to hook something that will trigger when you need to trigger your code.
This service allows you to listen for any addons events by name, no addresses
required.

This service allows you to listen for any addons events by name, no addresses required.
## Provided Interface

### Provided Interface
```cs
public interface IAddonLifecycle
{
Expand All @@ -19,54 +26,65 @@ public interface IAddonLifecycle
void RegisterListener(AddonEvent eventType, IEnumerable<string> addonNames, AddonEventDelegate handler);
void RegisterListener(AddonEvent eventType, string addonName, AddonEventDelegate handler);
void RegisterListener(AddonEvent eventType, AddonEventDelegate handler);

void UnregisterListener(AddonEvent eventType, IEnumerable<string> addonNames, [Optional] AddonEventDelegate handler);
void UnregisterListener(AddonEvent eventType, string addonName, [Optional] AddonEventDelegate handler);
void UnregisterListener(AddonEvent eventType, [Optional] AddonEventDelegate handler);

void UnregisterListener(params AddonEventDelegate[] handlers);
}
```
### Registering Events
You register for event by specifying which event you want, and then optionally specifiying by name which addons you want to listen for.

If no addon names are provided then the service will send you notifications for **all** addons.
It's generally recommended to specify which addons you want.
## Registering Events

You register for event by specifying which event you want, and then optionally
specifiying by name which addons you want to listen for.

If no addon names are provided then the service will send you notifications for
**all** addons. It's generally recommended to specify which addons you want.

```cs
AddonLifecycle.RegisterListener(AddonEvent.PreDraw, "FieldMarker", OnPreDraw);
AddonLifecycle.RegisterListener(AddonEvent.PostUpdate, "FieldMarker", OnPostUpdate);
AddonLifecycle.RegisterListener(AddonEvent.PostDraw, new[] { "Character", "FieldMarker", "NamePlate" }, OnPostDraw);
```

### Unregistering Events
You have a couple options for unregistering, you can unregister using the same syntax as you registered with,
or you can unregister the functions directly without needing to specify which events or addons you want to unregister.
## Unregistering Events

You have a couple options for unregistering, you can unregister using the same
syntax as you registered with, or you can unregister the functions directly
without needing to specify which events or addons you want to unregister.

```cs
AddonLifecycle.UnregisterListener(AddonEvent.PostDraw, new[] { "Character", "FieldMarker", "NamePlate" }, OnPostDraw);
AddonLifecycle.UnregisterListener(OnPreDraw, OnPostUpdate);
```

### Available Events
## Available Events

This service provides several events you can listen for:

Setup, Update, Draw, RequestedUpdate, Refresh, Finalize

Each of these events are used in a Pre or Post listener,
for example if you want to be notified ***right before*** and addon is about to do a refresh, you can subscribe to **PreRefresh**.
Each of these events are used in a Pre or Post listener, for example if you want
to be notified **_right before_** and addon is about to do a refresh, you can
subscribe to **PreRefresh**.

*Note: There is no PostFinalize event provided. That would be after the addon has been freed from memory.
If you have a valid usecase for needing a PostFinalize event let us know.*
_Note: There is no PostFinalize event provided. That would be after the addon
has been freed from memory. If you have a valid usecase for needing a
PostFinalize event let us know._

### Available Data
When your delegate is called, it is passed an AddonArgs object,
this can be cast to a more specific object to get the argument data used in the original call.
## Available Data

Each of the events have their own specific implementation of AddonArgs with the argument data avaialble.
If you are unsure what type of AddonArgs you have, there's a `Type` property you can check.
When your delegate is called, it is passed an AddonArgs object, this can be cast
to a more specific object to get the argument data used in the original call.

Each of the events have their own specific implementation of AddonArgs with the
argument data available. If you are unsure what type of AddonArgs you have,
there's a `Type` property you can check.

For example:

```cs
private void OnPostSetup(AddonEvent type, AddonArgs args)
{
Expand Down
Loading

0 comments on commit b17f873

Please sign in to comment.