chore: housekeeping — linter & formatter setup
Add .prettierrc.json, .markdownlint.json, .yamllint.yaml, .gitattributes Run CSharpier, Prettier and markdownlint across the entire codebase. No logic changes — formatting, using order and line endings only.
This commit is contained in:
+30
-44
@@ -1,85 +1,71 @@
|
||||
# AI Assistance Disclosure
|
||||
|
||||
HellionChat uses AI assistance per the
|
||||
[Dalamud Plugin AI Usage Policy](https://github.com/goatcorp/DalamudPluginsD17/)
|
||||
HellionChat uses AI assistance per the [Dalamud Plugin AI Usage Policy](https://github.com/goatcorp/DalamudPluginsD17/)
|
||||
at the **Pair** level.
|
||||
|
||||
A note up front: HellionChat is currently not submitted to the official
|
||||
Dalamud plugin repository and technically has no obligation to disclose
|
||||
this. I would rather be upfront about how it is built.
|
||||
A note up front: HellionChat is currently not submitted to the official Dalamud plugin repository and technically has no
|
||||
obligation to disclose this. I would rather be upfront about how it is built.
|
||||
|
||||
HellionChat is my entry point into game modding and plugin development.
|
||||
I have never written a plugin for a game before. I work alone, so I get
|
||||
help where I need it. That is not something I want to hide.
|
||||
HellionChat is my entry point into game modding and plugin development. I have never written a plugin for a game before.
|
||||
I work alone, so I get help where I need it. That is not something I want to hide.
|
||||
|
||||
## How I Actually Work
|
||||
|
||||
I plan the architecture, decide what gets built, and own every design
|
||||
decision. For each change I:
|
||||
I plan the architecture, decide what gets built, and own every design decision. For each change I:
|
||||
|
||||
- Read the code Claude drafts before I integrate it
|
||||
- Test with my own tooling and in the running game
|
||||
- Read the Dalamud log output to verify behaviour
|
||||
- Run security and privacy audits on anything that touches user data
|
||||
|
||||
One of the main reasons I use AI is consistency. I want the HellionChat
|
||||
code to match the style of the upstream Chat 2 codebase and stay
|
||||
readable for anyone who opens the repo, not just for me. Claude helps
|
||||
me catch when I am drifting from upstream conventions or writing
|
||||
something that only makes sense in my own head.
|
||||
One of the main reasons I use AI is consistency. I want the HellionChat code to match the style of the upstream Chat 2
|
||||
codebase and stay readable for anyone who opens the repo, not just for me. Claude helps me catch when I am drifting from
|
||||
upstream conventions or writing something that only makes sense in my own head.
|
||||
|
||||
The balance is shifting toward more hand-written work as I get more
|
||||
comfortable with Dalamud and plugin development in general.
|
||||
The balance is shifting toward more hand-written work as I get more comfortable with Dalamud and plugin development in
|
||||
general.
|
||||
|
||||
## What AI Is Used For
|
||||
|
||||
- API explanations (Dalamud, ImGui, .NET specifics I have not worked
|
||||
with before)
|
||||
- API explanations (Dalamud, ImGui, .NET specifics I have not worked with before)
|
||||
- Code drafts that I read, edit, and integrate
|
||||
- Pattern suggestions and code review
|
||||
- Keeping style aligned with the upstream Chat 2 codebase
|
||||
|
||||
## What AI Is Not Used For
|
||||
|
||||
- **Visual assets.** Logos, icons, banners, and screenshots are
|
||||
human-drawn or taken from the running game.
|
||||
- **Visual assets.** Logos, icons, banners, and screenshots are human-drawn or taken from the running game.
|
||||
- **German translations.** Written by me as a native speaker.
|
||||
|
||||
## What Is Where
|
||||
|
||||
Upstream Chat 2 (by Infi & Anna, EUPL-1.2) is the foundation and was
|
||||
not produced with AI assistance. HellionChat-specific code lives in
|
||||
`HellionChat/Privacy/`, `HellionChat/Export/`,
|
||||
`HellionChat/Resources/HellionStrings*`, `Ui/SettingsTabs/Privacy.cs`,
|
||||
`Ui/FirstRunWizard.cs`, `Ui/HellionStyle.cs`, plus the Migrate3
|
||||
recovery and plugin layout migration in `MessageStore.cs` and
|
||||
`Plugin.cs`. These were developed with Pair-level assistance as
|
||||
described above.
|
||||
Upstream Chat 2 (by Infi & Anna, EUPL-1.2) is the foundation and was not produced with AI assistance.
|
||||
HellionChat-specific code lives in `HellionChat/Privacy/`, `HellionChat/Export/`,
|
||||
`HellionChat/Resources/HellionStrings*`, `Ui/SettingsTabs/Privacy.cs`, `Ui/FirstRunWizard.cs`, `Ui/HellionStyle.cs`,
|
||||
plus the Migrate3 recovery and plugin layout migration in `MessageStore.cs` and `Plugin.cs`. These were developed with
|
||||
Pair-level assistance as described above.
|
||||
|
||||
## If AI-Assisted Development Is a Dealbreaker for You
|
||||
|
||||
Fair enough. There are solid alternatives:
|
||||
|
||||
- [Chat 2](https://github.com/Infiziert90/ChatTwo), the upstream
|
||||
project HellionChat is built on
|
||||
- [XIV Instant Messenger](https://github.com/NightmareXIV/XIVInstantMessenger),
|
||||
a different approach to FFXIV chat
|
||||
- [Chat 2](https://github.com/Infiziert90/ChatTwo), the upstream project HellionChat is built on
|
||||
- [XIV Instant Messenger](https://github.com/NightmareXIV/XIVInstantMessenger), a different approach to FFXIV chat
|
||||
|
||||
Both are good projects. Use what fits you best.
|
||||
|
||||
## Tooling
|
||||
|
||||
| Tool | Purpose |
|
||||
| ---- | ------- |
|
||||
| [Claude](https://claude.ai) (Anthropic) | Pair-level AI assistance via Claude Code CLI |
|
||||
| [VS Code](https://code.visualstudio.com) + C# Dev Kit | Primary IDE |
|
||||
| Dedicated Windows 11 VM | Build and in-game test environment (Dalamud requires Windows) |
|
||||
| [dalamud.dev](https://dalamud.dev) | Dalamud API reference |
|
||||
| [Microsoft Learn](https://learn.microsoft.com) | .NET and C# documentation |
|
||||
| [Context7](https://context7.com) | Up-to-date library docs for Claude context |
|
||||
| [Stack Overflow](https://stackoverflow.com) | General C# and .NET problem-solving |
|
||||
| Tool | Purpose |
|
||||
| ----------------------------------------------------- | ------------------------------------------------------------- |
|
||||
| [Claude](https://claude.ai) (Anthropic) | Pair-level AI assistance via Claude Code CLI |
|
||||
| [VS Code](https://code.visualstudio.com) + C# Dev Kit | Primary IDE |
|
||||
| Dedicated Windows 11 VM | Build and in-game test environment (Dalamud requires Windows) |
|
||||
| [dalamud.dev](https://dalamud.dev) | Dalamud API reference |
|
||||
| [Microsoft Learn](https://learn.microsoft.com) | .NET and C# documentation |
|
||||
| [Context7](https://context7.com) | Up-to-date library docs for Claude context |
|
||||
| [Stack Overflow](https://stackoverflow.com) | General C# and .NET problem-solving |
|
||||
|
||||
## Contact
|
||||
|
||||
Questions about this disclosure:
|
||||
<https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/issues>
|
||||
Questions about this disclosure: <https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/issues>
|
||||
|
||||
+165
-225
@@ -1,51 +1,36 @@
|
||||
# Changelog — Hellion Chat
|
||||
|
||||
Alle nutzersichtbaren Änderungen an Hellion Chat. Das Format orientiert
|
||||
sich an [Keep a Changelog](https://keepachangelog.com/de/1.0.0/), die
|
||||
Version-Nummern folgen [Semantischer Versionierung](https://semver.org/lang/de/).
|
||||
Alle nutzersichtbaren Änderungen an Hellion Chat. Das Format orientiert sich an
|
||||
[Keep a Changelog](https://keepachangelog.com/de/1.0.0/), die Version-Nummern folgen
|
||||
[Semantischer Versionierung](https://semver.org/lang/de/).
|
||||
|
||||
Detaillierte Release-Notes pro Version stehen direkt am
|
||||
[Gitea-Release](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases)
|
||||
und im Plugin-Changelog-Block (`HellionChat/HellionChat.yaml` →
|
||||
`changelog:`). Diese Datei fasst die Releases als Überblick zusammen
|
||||
und verlinkt für Details auf die Release-Pages.
|
||||
[Gitea-Release](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases) und im Plugin-Changelog-Block
|
||||
(`HellionChat/HellionChat.yaml` → `changelog:`). Diese Datei fasst die Releases als Überblick zusammen und verlinkt für
|
||||
Details auf die Release-Pages.
|
||||
|
||||
---
|
||||
|
||||
## Hellion Chat 1.4.3 — Plugin-Load Async-Init + Repo-Cutover (2026-05-08)
|
||||
|
||||
Plugin lifecycle migrated to Dalamud's `IAsyncDalamudPlugin`
|
||||
API. The constructor now does only the bootstrap-essentials
|
||||
(config load, language init, conflict detection); migrations,
|
||||
service allocations, window construction and hook subscription
|
||||
move to `LoadAsync`. Dalamud can keep its UI responsive while
|
||||
the heavy work runs.
|
||||
Plugin lifecycle migrated to Dalamud's `IAsyncDalamudPlugin` API. The constructor now does only the bootstrap-essentials
|
||||
(config load, language init, conflict detection); migrations, service allocations, window construction and hook
|
||||
subscription move to `LoadAsync`. Dalamud can keep its UI responsive while the heavy work runs.
|
||||
|
||||
- `IAsyncDalamudPlugin` two-phase load with per-line
|
||||
`CaptureFailure` in `DisposeAsync` (mirrors LightlessSync's
|
||||
- `IAsyncDalamudPlugin` two-phase load with per-line `CaptureFailure` in `DisposeAsync` (mirrors LightlessSync's
|
||||
pattern); idempotency guard protects against reload races
|
||||
- Schema-gate replaces the v9 → v16 migration chain. Configs
|
||||
on schema v16+ load directly; older configs trigger an
|
||||
"install v1.4.2 first" error so the historic migration
|
||||
path stays intact
|
||||
- `AutoTranslate.PreloadCache` moved off the load path. First
|
||||
use may have a sub-second hitch instead of every-load; the
|
||||
- Schema-gate replaces the v9 → v16 migration chain. Configs on schema v16+ load directly; older configs trigger an
|
||||
"install v1.4.2 first" error so the historic migration path stays intact
|
||||
- `AutoTranslate.PreloadCache` moved off the load path. First use may have a sub-second hitch instead of every-load; the
|
||||
upstream chose differently, we accept first-use latency
|
||||
- `FontManager.BuildFonts` is called sync at the start of
|
||||
`LoadAsync`; Dalamud rebuilds the font atlas on its own
|
||||
pipeline so the custom Hellion-Exo2 font appears with a
|
||||
brief font-pop after load (matches ChatTwo's behaviour)
|
||||
- Custom-repo URL moved to
|
||||
`gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat`.
|
||||
GitHub repo stays as a frozen v1.4.2 snapshot; new
|
||||
releases ship from Gitea. Existing testers need to
|
||||
update the custom-repo URL once
|
||||
- Plugin-load time in this release sits at ~3.7 s median
|
||||
(5 reloads), comparable to v1.4.2. Async migration is
|
||||
foundational for v1.4.4 Lazy-Init optimisations rather
|
||||
than an immediate user-perceived win
|
||||
- `FontManager.BuildFonts` is called sync at the start of `LoadAsync`; Dalamud rebuilds the font atlas on its own
|
||||
pipeline so the custom Hellion-Exo2 font appears with a brief font-pop after load (matches ChatTwo's behaviour)
|
||||
- Custom-repo URL moved to `gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat`. GitHub repo stays as a frozen
|
||||
v1.4.2 snapshot; new releases ship from Gitea. Existing testers need to update the custom-repo URL once
|
||||
- Plugin-load time in this release sits at ~3.7 s median (5 reloads), comparable to v1.4.2. Async migration is
|
||||
foundational for v1.4.4 Lazy-Init optimisations rather than an immediate user-perceived win
|
||||
|
||||
Modding & support: join Hellion Forge — https://discord.gg/X9V7Kcv5gR
|
||||
Modding & support: join Hellion Forge — <https://discord.gg/X9V7Kcv5gR>
|
||||
|
||||
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
|
||||
@@ -53,27 +38,19 @@ Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
|
||||
## Hellion Chat 1.4.2 — ChatLog Frame-Hot-Path
|
||||
|
||||
Third sub-patch of the v1.4.x Polish Sweep series. Per-frame
|
||||
allocations from the chat-log render path eliminated.
|
||||
Third sub-patch of the v1.4.x Polish Sweep series. Per-frame allocations from the chat-log render path eliminated.
|
||||
|
||||
- `DrawMessages` card-mode hoists `theme`/`drawList`/`winLeft`/
|
||||
`winRight`/`borderColorAbgr` out of the per-message loop. About
|
||||
500 redundant calls per frame at 100 visible messages, multiplied
|
||||
by every pop-out window
|
||||
- Auto-tell tab tint and icon use a per-tab cache. Hash
|
||||
computation and string allocation only happen when the tell
|
||||
target name or world drifts. `AutoTellTabTint` stays a pure
|
||||
hash helper; cache lives in a thin `TabTintCache` wrapper
|
||||
- Status bar gates its tab aggregation behind the same
|
||||
one-second cache it already used for the format strings.
|
||||
LINQ `Sum` and `Count` replaced with a single `foreach` pass
|
||||
that runs on roughly 1 % of frames
|
||||
- `DrawMessages` card-mode hoists `theme`/`drawList`/`winLeft`/ `winRight`/`borderColorAbgr` out of the per-message
|
||||
loop. About 500 redundant calls per frame at 100 visible messages, multiplied by every pop-out window
|
||||
- Auto-tell tab tint and icon use a per-tab cache. Hash computation and string allocation only happen when the tell
|
||||
target name or world drifts. `AutoTellTabTint` stays a pure hash helper; cache lives in a thin `TabTintCache` wrapper
|
||||
- Status bar gates its tab aggregation behind the same one-second cache it already used for the format strings. LINQ
|
||||
`Sum` and `Count` replaced with a single `foreach` pass that runs on roughly 1 % of frames
|
||||
|
||||
Realistic frame-time recovery: 2-5 % in typical scenes, more
|
||||
on pop-out-heavy setups because the card-border hoist scales
|
||||
per window.
|
||||
Realistic frame-time recovery: 2-5 % in typical scenes, more on pop-out-heavy setups because the card-border hoist
|
||||
scales per window.
|
||||
|
||||
Modding & support: join Hellion Forge — https://discord.gg/X9V7Kcv5gR
|
||||
Modding & support: join Hellion Forge — <https://discord.gg/X9V7Kcv5gR>
|
||||
|
||||
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
|
||||
@@ -81,38 +58,25 @@ Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
|
||||
## Hellion Chat 1.4.1 — Theme Engine Performance
|
||||
|
||||
Second sub-patch of the v1.4.x Polish Sweep series. Heap
|
||||
pressure from the theme engine's per-frame render path
|
||||
removed, plus a tenth built-in theme and hardening for
|
||||
the custom-theme hot-reload.
|
||||
Second sub-patch of the v1.4.x Polish Sweep series. Heap pressure from the theme engine's per-frame render path removed,
|
||||
plus a tenth built-in theme and hardening for the custom-theme hot-reload.
|
||||
|
||||
- Theme records carry a pre-computed ABGR-packed cache
|
||||
for every color slot; cache is filled when the theme
|
||||
is registered and refreshed defensively on every
|
||||
`Switch()`
|
||||
- `HellionStyle.PushGlobal` reads ABGR values from the
|
||||
cache instead of calling `ColourUtil.RgbaToAbgr` per
|
||||
slot per frame; ~13 % render-time recovery measured
|
||||
in typical scenes (plan estimate was 2–6 %, real
|
||||
~10–15 %)
|
||||
- `ThemeRegistry` custom-theme reload distinguishes a
|
||||
recoverable file lock (editor mid-save) from a
|
||||
permanent IO failure; locked themes keep their
|
||||
last-known-good snapshot and retry on the next
|
||||
lookup instead of dropping out of the picker
|
||||
- New built-in: **Synthwave Sunset** — Hot Magenta + Cyan
|
||||
on midnight violet, 80s neon-grid vibes; tenth theme
|
||||
in the picker
|
||||
- Author credits refreshed: brand themes are credited
|
||||
as "Hellion Forge"; **Mint Grove** and **Forge
|
||||
Merchantman** now credited to **Carla Beleandis** as
|
||||
a community thanks
|
||||
- Theme records carry a pre-computed ABGR-packed cache for every color slot; cache is filled when the theme is
|
||||
registered and refreshed defensively on every `Switch()`
|
||||
- `HellionStyle.PushGlobal` reads ABGR values from the cache instead of calling `ColourUtil.RgbaToAbgr` per slot per
|
||||
frame; ~13 % render-time recovery measured in typical scenes (plan estimate was 2–6 %, real ~10–15 %)
|
||||
- `ThemeRegistry` custom-theme reload distinguishes a recoverable file lock (editor mid-save) from a permanent IO
|
||||
failure; locked themes keep their last-known-good snapshot and retry on the next lookup instead of dropping out of the
|
||||
picker
|
||||
- New built-in: **Synthwave Sunset** — Hot Magenta + Cyan on midnight violet, 80s neon-grid vibes; tenth theme in the
|
||||
picker
|
||||
- Author credits refreshed: brand themes are credited as "Hellion Forge"; **Mint Grove** and **Forge Merchantman** now
|
||||
credited to **Carla Beleandis** as a community thanks
|
||||
|
||||
No schema bump, no user-visible behaviour change other
|
||||
than smoother frames on GC-sensitive setups and one
|
||||
additional colour option.
|
||||
No schema bump, no user-visible behaviour change other than smoother frames on GC-sensitive setups and one additional
|
||||
colour option.
|
||||
|
||||
Modding & support: join Hellion Forge — https://discord.gg/X9V7Kcv5gR
|
||||
Modding & support: join Hellion Forge — <https://discord.gg/X9V7Kcv5gR>
|
||||
|
||||
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
|
||||
@@ -120,33 +84,22 @@ Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
|
||||
## Hellion Chat 1.4.0 — Critical Lifecycle Fixes
|
||||
|
||||
First sub-patch of the v1.4.x Polish Sweep series. Seven
|
||||
known lifecycle and race bugs eliminated before any
|
||||
performance refactor sits on top.
|
||||
First sub-patch of the v1.4.x Polish Sweep series. Seven known lifecycle and race bugs eliminated before any performance
|
||||
refactor sits on top.
|
||||
|
||||
- MessageStore disposal no longer triggers GC.Collect
|
||||
globally; Pooling=false on the SQLite connection means
|
||||
there's nothing left to clean up by hand
|
||||
- PendingMessage and RetentionSweep worker threads are
|
||||
explicitly marked IsBackground=true so the plugin domain
|
||||
can unload during XIVLauncher reload without waiting
|
||||
for them
|
||||
- EmoteCache image and gif loaders moved from async-void
|
||||
to async Task with a shared task tracker, draining
|
||||
on Dispose so an in-flight load can no longer write
|
||||
to a disposed EmoteImages entry
|
||||
- DisposeAsync 10s timeout now warns loudly instead of
|
||||
silently leaving the worker behind
|
||||
- Plugin.Dispose flushes any pending DeferredSaveFrames
|
||||
before tearing services down, so settings changes
|
||||
made in the last few frames before disable are no
|
||||
longer lost
|
||||
- The v13→v14 config migration now reads the pre-v13
|
||||
backup and carries HellionThemeWindowOpacity into the
|
||||
new WindowOpacity field instead of falling back to
|
||||
the default 0.85
|
||||
- MessageStore disposal no longer triggers GC.Collect globally; Pooling=false on the SQLite connection means there's
|
||||
nothing left to clean up by hand
|
||||
- PendingMessage and RetentionSweep worker threads are explicitly marked IsBackground=true so the plugin domain can
|
||||
unload during XIVLauncher reload without waiting for them
|
||||
- EmoteCache image and gif loaders moved from async-void to async Task with a shared task tracker, draining on Dispose
|
||||
so an in-flight load can no longer write to a disposed EmoteImages entry
|
||||
- DisposeAsync 10s timeout now warns loudly instead of silently leaving the worker behind
|
||||
- Plugin.Dispose flushes any pending DeferredSaveFrames before tearing services down, so settings changes made in the
|
||||
last few frames before disable are no longer lost
|
||||
- The v13→v14 config migration now reads the pre-v13 backup and carries HellionThemeWindowOpacity into the new
|
||||
WindowOpacity field instead of falling back to the default 0.85
|
||||
|
||||
Modding & support: join Hellion Forge — https://discord.gg/X9V7Kcv5gR
|
||||
Modding & support: join Hellion Forge — <https://discord.gg/X9V7Kcv5gR>
|
||||
|
||||
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
|
||||
@@ -154,21 +107,18 @@ Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
|
||||
## Hellion Chat 1.3.0 - Plugin Integrations: Honorific
|
||||
|
||||
First step on the plugin-integration roadmap. HellionChat now
|
||||
listens to Honorific and shows your custom title in the chat
|
||||
header. The slot auto-hides when Honorific is not installed,
|
||||
when no custom title is active, or when you are using the
|
||||
original FFXIV title.
|
||||
First step on the plugin-integration roadmap. HellionChat now listens to Honorific and shows your custom title in the
|
||||
chat header. The slot auto-hides when Honorific is not installed, when no custom title is active, or when you are using
|
||||
the original FFXIV title.
|
||||
|
||||
- New "Integrations" settings tab
|
||||
- Honorific integration with auto-detection and live updates
|
||||
- "Coming soon" preview of the next five planned integrations:
|
||||
context menu actions, smart notifications, RP status block,
|
||||
ExtraChat channels, and quick DM compose
|
||||
- "Coming soon" preview of the next five planned integrations: context menu actions, smart notifications, RP status
|
||||
block, ExtraChat channels, and quick DM compose
|
||||
- Maintainer attribution buttons for Honorific repo and Caraxi
|
||||
- New service-class pattern under HellionChat/Integrations/
|
||||
|
||||
Modding and support: join Hellion Forge - https://discord.gg/X9V7Kcv5gR
|
||||
Modding and support: join Hellion Forge - <https://discord.gg/X9V7Kcv5gR>
|
||||
|
||||
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
|
||||
@@ -177,37 +127,48 @@ Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
## v1.2.3 — Theme Expansion (2026-05-06)
|
||||
|
||||
### Added
|
||||
|
||||
- Four new built-in themes:
|
||||
- **Night Blue** — Royal Blue on deep marine, cool tech-dashboard mood
|
||||
- **Indigo Violet** — Royal Violet on deep indigo with a turquoise-mint counter (aurora glitter feel)
|
||||
- **Forge Merchantman** — Patina bronze on workshop slate with warm amber counter (Hellion Forge identity)
|
||||
- **Hellion Spectrum** — Deuteran/Protan-safe channel colours using Wong/Okabe-Ito palette tones; channel identity (Tell pink, Yell yellow, Shout orange, Party blue, FC green) preserved while keeping every channel separable under red-green colour vision deficiency
|
||||
- **Night Blue** — Royal Blue on deep marine, cool tech-dashboard mood
|
||||
- **Indigo Violet** — Royal Violet on deep indigo with a turquoise-mint counter (aurora glitter feel)
|
||||
- **Forge Merchantman** — Patina bronze on workshop slate with warm amber counter (Hellion Forge identity)
|
||||
- **Hellion Spectrum** — Deuteran/Protan-safe channel colours using Wong/Okabe-Ito palette tones; channel identity
|
||||
(Tell pink, Yell yellow, Shout orange, Party blue, FC green) preserved while keeping every channel separable under
|
||||
red-green colour vision deficiency
|
||||
- Built-in theme catalogue grown from five to nine
|
||||
|
||||
### Notes
|
||||
|
||||
- No engine changes, no settings touched, no migration
|
||||
- Default theme unchanged (Hellion Arctic). Existing custom themes keep working.
|
||||
- Hellion Spectrum covers the ~99 % of CVD cases that are red-green; a Tritan-safe variant could follow in a later cycle if there is demand.
|
||||
- Hellion Spectrum covers the ~99 % of CVD cases that are red-green; a Tritan-safe variant could follow in a later cycle
|
||||
if there is demand.
|
||||
|
||||
---
|
||||
|
||||
## v1.2.1 — Settings Cleanup (2026-05-06)
|
||||
|
||||
### Changed
|
||||
|
||||
- Settings cards re-sorted thematically: 9 cards remain, each card has one clear job and a one-line subtitle.
|
||||
- **Theme & Layout** (new) collects the theme picker, window frame style (title bar, sidebar, hide button, pop-out title bar) and the timestamp style options.
|
||||
- **Theme & Layout** (new) collects the theme picker, window frame style (title bar, sidebar, hide button, pop-out title
|
||||
bar) and the timestamp style options.
|
||||
- **Fonts & Colours** (new) houses font choice, font size and per-channel chat colours.
|
||||
- **Data Management** (new) collects retention windows, cleanup, export, the database viewer and the shift-click advanced tools.
|
||||
- **Data Management** (new) collects retention windows, cleanup, export, the database viewer and the shift-click
|
||||
advanced tools.
|
||||
- **Privacy** is now focused on the privacy filter alone.
|
||||
- **Chat** absorbs the Auto-Tell-Tabs history-preload slider that used to live under Privacy.
|
||||
- **General** groups the keybind mode under Input.
|
||||
|
||||
### Removed
|
||||
|
||||
- Legacy "Style override" option and the unused style-name field — both obsolete since the v1.1.0 themes engine.
|
||||
- Legacy `WindowAlpha` slider — if you had it set, the value is auto-migrated to Theme & Layout → Window Style → Window Transparency.
|
||||
- Legacy `WindowAlpha` slider — if you had it set, the value is auto-migrated to Theme & Layout → Window Style → Window
|
||||
Transparency.
|
||||
- Unused `ShowThemeQuickPicker` schema field.
|
||||
|
||||
### Migration
|
||||
|
||||
- v15 → v16 with backup at `pluginConfigs/HellionChat.json.pre-v16-backup`.
|
||||
- All other settings preserved unchanged.
|
||||
- One-time toast on first start if Style override was previously active.
|
||||
@@ -216,80 +177,82 @@ Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
|
||||
## v1.2.0 — Layout Refresh (2026-05-05)
|
||||
|
||||
### Added
|
||||
### 1.2.0 Added
|
||||
|
||||
- Sidebar tab modernization: icon-only at fixed 44 px, tooltip on hover, vertical accent pill for active tab
|
||||
- Top tabs: accent underline pill replaces background fill on active tab
|
||||
- Per-tab custom icons in Settings → Tabs (15-glyph FontAwesome picker)
|
||||
- Bottom status bar (22 px): channel indicator, privacy badge, counters, tells, version — updates 1×/sec
|
||||
- Card rows as default message render: sender header in channel color, subtle border between cards
|
||||
- Compact-Density toggle in Appearance: switches back to single-line `[HH:mm] Sender: Text` layout
|
||||
- Auto-Tell tabs: per-partner hashed icon (7-glyph pool: envelope/star/heart/bell/bookmark/flag/fire) plus hashed color (12-color palette) — 84 distinct icon+color combinations
|
||||
- Unread indicator: pulsing red dot in the top-right corner of any sidebar tab icon with unread messages, 2-second sine-wave pulse, respects `Configuration.ReduceMotion`
|
||||
- Auto-Tell tabs: per-partner hashed icon (7-glyph pool: envelope/star/heart/bell/bookmark/flag/fire) plus hashed color
|
||||
(12-color palette) — 84 distinct icon+color combinations
|
||||
- Unread indicator: pulsing red dot in the top-right corner of any sidebar tab icon with unread messages, 2-second
|
||||
sine-wave pulse, respects `Configuration.ReduceMotion`
|
||||
|
||||
### 1.2.0 Changed
|
||||
|
||||
### Changed
|
||||
- Migration v14 → v15: deprecated Configuration fields `HellionThemeEnabled` and `HellionThemeWindowOpacity` removed
|
||||
- Appearance settings cleaned: legacy theme-engine bindings replaced by Themes tab (introduced in v1.1.0)
|
||||
|
||||
### Fixed
|
||||
- Settings save no longer wipes chat history by default — the heavy `ClearAllTabs + FilterAllTabsAsync` cycle now only runs when a filter-relevant setting actually changed (Privacy filter, persisted channels, per-tab channel selection). Cosmetic changes keep the in-session chat intact
|
||||
- Identifier-based `MessageList` restore in `Configuration.UpdateFrom` plus TempTab skip in `ClearAllTabs`/`FilterAllTabs` ensure persistent tabs and Auto-Tell tabs both survive the save
|
||||
### 1.2.0 Fixed
|
||||
|
||||
- Settings save no longer wipes chat history by default — the heavy `ClearAllTabs + FilterAllTabsAsync` cycle now only
|
||||
runs when a filter-relevant setting actually changed (Privacy filter, persisted channels, per-tab channel selection).
|
||||
Cosmetic changes keep the in-session chat intact
|
||||
- Identifier-based `MessageList` restore in `Configuration.UpdateFrom` plus TempTab skip in
|
||||
`ClearAllTabs`/`FilterAllTabs` ensure persistent tabs and Auto-Tell tabs both survive the save
|
||||
- Sidebar buttons now align vertically with the first message row (top padding mirrors the chat header toolbar height)
|
||||
- Sidebar child window no longer paints the top padding area with its frame background
|
||||
- Status bar version slot (`vX.Y.Z · Hellion`) no longer clips its rightmost character
|
||||
|
||||
### Notes
|
||||
### 1.2.0 Notes
|
||||
|
||||
- Polish phase (animations, theme crossfade, header quick-picker) follows in v1.3.0
|
||||
- Top-Tab icon prefixes were considered but dropped: Dalamud's default font atlas does not include FontAwesome codepoints, so mixed-font in a single TabItem label renders as tofu. Underline pill alone is the v1.2.0 visual treatment for top tabs. Resolution would require Font-Atlas merge at FontManager level — out of scope.
|
||||
- Top-Tab icon prefixes were considered but dropped: Dalamud's default font atlas does not include FontAwesome
|
||||
codepoints, so mixed-font in a single TabItem label renders as tofu. Underline pill alone is the v1.2.0 visual
|
||||
treatment for top tabs. Resolution would require Font-Atlas merge at FontManager level — out of scope.
|
||||
|
||||
## [1.1.0] — 2026-05-05 — Theme Foundation
|
||||
|
||||
Erster großer UI-Cycle nach v1.0.0. Theme-Engine, fünf Built-In-Themes,
|
||||
Custom-Themes via JSON, Settings-Card-Grid.
|
||||
Erster großer UI-Cycle nach v1.0.0. Theme-Engine, fünf Built-In-Themes, Custom-Themes via JSON, Settings-Card-Grid.
|
||||
|
||||
### Hinzugefügt
|
||||
|
||||
- **Theme-Engine** mit fünf Built-In-Themes: Hellion Arctic (Default),
|
||||
Chat 2 Klassik, Event Horizon, Moonlit Bloom, Mint Grove.
|
||||
- **Settings → Themes** mit Mini-Mockup-Preview pro Theme. Klick auf
|
||||
eine Card switcht sofort das ganze Plugin (Chat, Settings, Pop-Out).
|
||||
- **Custom-Themes via JSON** in `pluginConfigs/HellionChat/themes/`.
|
||||
Beim ersten Start wird `example-theme.json` als Vorlage abgelegt.
|
||||
- **Optional Theme-Chat-Channel-Colors**: Themes können eigene
|
||||
Channel-Farben mitliefern. Beim Switch erscheint ein Banner mit
|
||||
*Übernehmen / Behalten* — nie automatisch.
|
||||
- **Settings-Card-Grid**: neue Übersicht beim Öffnen, Card-Klick führt
|
||||
in die Detail-Ansicht der Section. Breadcrumb + ESC führen zurück.
|
||||
- **`docs/THEME-AUTHORING.md`** als Anleitung zum Schreiben eigener
|
||||
Themes, mit Hellion-Forge-Branding.
|
||||
- **Theme-Engine** mit fünf Built-In-Themes: Hellion Arctic (Default), Chat 2 Klassik, Event Horizon, Moonlit Bloom,
|
||||
Mint Grove.
|
||||
- **Settings → Themes** mit Mini-Mockup-Preview pro Theme. Klick auf eine Card switcht sofort das ganze Plugin (Chat,
|
||||
Settings, Pop-Out).
|
||||
- **Custom-Themes via JSON** in `pluginConfigs/HellionChat/themes/`. Beim ersten Start wird `example-theme.json` als
|
||||
Vorlage abgelegt.
|
||||
- **Optional Theme-Chat-Channel-Colors**: Themes können eigene Channel-Farben mitliefern. Beim Switch erscheint ein
|
||||
Banner mit _Übernehmen / Behalten_ — nie automatisch.
|
||||
- **Settings-Card-Grid**: neue Übersicht beim Öffnen, Card-Klick führt in die Detail-Ansicht der Section. Breadcrumb +
|
||||
ESC führen zurück.
|
||||
- **`docs/THEME-AUTHORING.md`** als Anleitung zum Schreiben eigener Themes, mit Hellion-Forge-Branding.
|
||||
|
||||
### Geändert
|
||||
|
||||
- **Plugin-Icon** auf Hellion Forge Hammer (vorher ChatTwo-Derivat).
|
||||
- **Settings-Detail-View** verwendet die volle Breite — die zweite
|
||||
Tab-Liste links ist weg, weil die Card-Übersicht den Wechsel
|
||||
übernimmt.
|
||||
- **`HellionStyle.PushGlobal`** ist jetzt theme-driven (`PushGlobal(theme,
|
||||
opacity)`) statt const-palette-driven.
|
||||
- **Configuration v13 → v14**: alle User landen auf `hellion-arctic`.
|
||||
Wer den Upstream-Look will, wählt `chat2-classic` in Settings →
|
||||
Themes.
|
||||
- **Settings-Detail-View** verwendet die volle Breite — die zweite Tab-Liste links ist weg, weil die Card-Übersicht den
|
||||
Wechsel übernimmt.
|
||||
- **`HellionStyle.PushGlobal`** ist jetzt theme-driven (`PushGlobal(theme, opacity)`) statt const-palette-driven.
|
||||
- **Configuration v13 → v14**: alle User landen auf `hellion-arctic`. Wer den Upstream-Look will, wählt `chat2-classic`
|
||||
in Settings → Themes.
|
||||
|
||||
### Veraltet
|
||||
|
||||
- `Configuration.HellionThemeEnabled` und `HellionThemeWindowOpacity`
|
||||
bleiben für ein Release lesbar als Safety-Net, werden aber nicht
|
||||
mehr ausgewertet. Entfernung geplant in v1.2.0.
|
||||
- `Configuration.HellionThemeEnabled` und `HellionThemeWindowOpacity` bleiben für ein Release lesbar als Safety-Net,
|
||||
werden aber nicht mehr ausgewertet. Entfernung geplant in v1.2.0.
|
||||
|
||||
### Sicherheit
|
||||
|
||||
- Custom-Theme-JSON-Loader prüft `schemaVersion`, Pflichtfelder und
|
||||
Hex-Format. Ungültige Themes werden mit Warning übersprungen, das
|
||||
Plugin lädt mit Built-Ins weiter.
|
||||
- Custom-Theme-JSON-Loader prüft `schemaVersion`, Pflichtfelder und Hex-Format. Ungültige Themes werden mit Warning
|
||||
übersprungen, das Plugin lädt mit Built-Ins weiter.
|
||||
|
||||
### Intern
|
||||
|
||||
- 51 lokale Unit-Tests (Theme-Records, Registry, JSON-Round-Trip,
|
||||
Sanity pro Built-In-Theme). Tests sind gitignored.
|
||||
- 51 lokale Unit-Tests (Theme-Records, Registry, JSON-Round-Trip, Sanity pro Built-In-Theme). Tests sind gitignored.
|
||||
|
||||
---
|
||||
|
||||
@@ -297,92 +260,72 @@ Custom-Themes via JSON, Settings-Card-Grid.
|
||||
|
||||
Vier kleine Polish-Items aus dem Backlog gebündelt:
|
||||
|
||||
- **Hide bei New Game+ Menü**: Optionaler globaler Toggle der Hellion
|
||||
Chat (und alle weiteren Plugin-Fenster wie Settings, DB-Viewer,
|
||||
Pop-Outs) ausblendet, solange das NG+-Menü offen ist. Settings →
|
||||
Fenster → Rahmen, Default aus. Skipt analog zum bestehenden
|
||||
LoadingScreens-Pattern den gesamten `WindowSystem.Draw()`-Pfad.
|
||||
- **Channel-Selector-Färbung**: Optionales Tinting des
|
||||
Channel-Auswahl-Knopfs (Comment-Icon) neben dem Eingabefeld in der
|
||||
aktuellen Channel-Farbe. Settings → Aussehen → Chat-Farben, Default
|
||||
an. Konsistent zur bestehenden Eingabetext-Färbung, ExtraChat-Override
|
||||
wird übernommen.
|
||||
- **(De)Buff-Icon Aspect-Ratio-Fix**: `PayloadHandler.InlineIcon` quetschte
|
||||
alle Hover-Icons auf 32×32. Status-Icons mit nicht-quadratischen
|
||||
Dimensionen (Debuffs mit Pfeil-Indikator) sind jetzt aspekt-erhaltend
|
||||
geshrinkt. Eigenständige Float-Math-Implementierung mit Zero-Size-Guard
|
||||
statt Cherry-Pick aus dem offenen ChatTwo PR #157 (der hatte eine
|
||||
- **Hide bei New Game+ Menü**: Optionaler globaler Toggle der Hellion Chat (und alle weiteren Plugin-Fenster wie
|
||||
Settings, DB-Viewer, Pop-Outs) ausblendet, solange das NG+-Menü offen ist. Settings → Fenster → Rahmen, Default aus.
|
||||
Skipt analog zum bestehenden LoadingScreens-Pattern den gesamten `WindowSystem.Draw()`-Pfad.
|
||||
- **Channel-Selector-Färbung**: Optionales Tinting des Channel-Auswahl-Knopfs (Comment-Icon) neben dem Eingabefeld in
|
||||
der aktuellen Channel-Farbe. Settings → Aussehen → Chat-Farben, Default an. Konsistent zur bestehenden
|
||||
Eingabetext-Färbung, ExtraChat-Override wird übernommen.
|
||||
- **(De)Buff-Icon Aspect-Ratio-Fix**: `PayloadHandler.InlineIcon` quetschte alle Hover-Icons auf 32×32. Status-Icons mit
|
||||
nicht-quadratischen Dimensionen (Debuffs mit Pfeil-Indikator) sind jetzt aspekt-erhaltend geshrinkt. Eigenständige
|
||||
Float-Math-Implementierung mit Zero-Size-Guard statt Cherry-Pick aus dem offenen ChatTwo PR #157 (der hatte eine
|
||||
int-Division-Falle).
|
||||
- **HideState-Logging-Sweep**: Alle HideState-Transitions
|
||||
(Battle/Cutscene/User/Override plus die Pop-Out-Spiegelung) loggen sich
|
||||
auf Verbose-Level. Aus by default, Aktivierung via
|
||||
`/xllog set HellionChat verbose` für Bug-Report-Diagnose.
|
||||
- **HideState-Logging-Sweep**: Alle HideState-Transitions (Battle/Cutscene/User/Override plus die Pop-Out-Spiegelung)
|
||||
loggen sich auf Verbose-Level. Aus by default, Aktivierung via `/xllog set HellionChat verbose` für
|
||||
Bug-Report-Diagnose.
|
||||
|
||||
[Release-Notes 1.0.3](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v1.0.3)
|
||||
|
||||
## [1.0.1] — 2026-05-04 — Window Position Recovery
|
||||
|
||||
Fixes an off-screen-window scenario the user could end up in after a
|
||||
monitor disconnect or display layout change between sessions. An
|
||||
automatic one-shot bounds check on the first draw after plugin load
|
||||
snaps the window back into the visible viewport, and a new
|
||||
"Reset Window Position" button in Settings → Window → Frame serves as
|
||||
the manual escape hatch for edge cases.
|
||||
Fixes an off-screen-window scenario the user could end up in after a monitor disconnect or display layout change between
|
||||
sessions. An automatic one-shot bounds check on the first draw after plugin load snaps the window back into the visible
|
||||
viewport, and a new "Reset Window Position" button in Settings → Window → Frame serves as the manual escape hatch for
|
||||
edge cases.
|
||||
|
||||
Bundled housekeeping since v1.0.0: documentation restructured into
|
||||
`docs/`, stale ChatTwo/* paths in repo configs cleaned up, Pidgin
|
||||
parser library bumped from 3.3.0 to 3.5.1, GitHub Actions bumps for
|
||||
`actions/setup-dotnet` (4 → 5) and `github/codeql-action` (3 → 4).
|
||||
Bundled housekeeping since v1.0.0: documentation restructured into `docs/`, stale ChatTwo/\* paths in repo configs
|
||||
cleaned up, Pidgin parser library bumped from 3.3.0 to 3.5.1, GitHub Actions bumps for `actions/setup-dotnet` (4 → 5)
|
||||
and `github/codeql-action` (3 → 4).
|
||||
|
||||
[Release-Notes 1.0.1](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v1.0.1)
|
||||
|
||||
## [1.0.0] — 2026-05-03 — Standalone Major Release
|
||||
|
||||
Erste vollständig eigenständige Version. Code-Namespace, IPC-Kanäle und
|
||||
Source-Tree-Struktur wurden auf `HellionChat.*` konsolidiert. Plugin
|
||||
verweigert den Start bei aktivem Upstream Chat 2 (bilinguale
|
||||
Konflikt-Meldung). SQLite-Native auf 3.50.3 gepinnt (CVE-2025-6965,
|
||||
CVE-2025-7709). Tab-Layout-Default für neue Installationen und für
|
||||
User auf Config-Version 12 oder älter neu strukturiert (5 thematische
|
||||
Tabs statt 6+ kitchen-sink). Sweep aus Critical- und Major-Findings
|
||||
aus dem Codebase-Audit eingearbeitet.
|
||||
Erste vollständig eigenständige Version. Code-Namespace, IPC-Kanäle und Source-Tree-Struktur wurden auf `HellionChat.*`
|
||||
konsolidiert. Plugin verweigert den Start bei aktivem Upstream Chat 2 (bilinguale Konflikt-Meldung). SQLite-Native auf
|
||||
3.50.3 gepinnt (CVE-2025-6965, CVE-2025-7709). Tab-Layout-Default für neue Installationen und für User auf
|
||||
Config-Version 12 oder älter neu strukturiert (5 thematische Tabs statt 6+ kitchen-sink). Sweep aus Critical- und
|
||||
Major-Findings aus dem Codebase-Audit eingearbeitet.
|
||||
|
||||
[Release-Notes 1.0.0](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v1.0.0)
|
||||
|
||||
## [0.6.1] — 2026-05-03 — Pop-Out Discoverability & /tell Auto-Pop-Out
|
||||
|
||||
Pop-Out-Button im Chat-Header sichtbar, einmaliger Hint-Banner für die
|
||||
Pop-Out-Funktionalität. Neue Einstellung "Neue /tell-Tabs direkt als
|
||||
Pop-Out öffnen". Pop-Out-Input ist jetzt standardmäßig aktiv.
|
||||
Bugfixes: Ghost-Windows bei LRU-Drop / Logout, Dead-Zone unter dem
|
||||
Input-Bar bei aktivem Hint-Banner.
|
||||
Pop-Out-Button im Chat-Header sichtbar, einmaliger Hint-Banner für die Pop-Out-Funktionalität. Neue Einstellung "Neue
|
||||
/tell-Tabs direkt als Pop-Out öffnen". Pop-Out-Input ist jetzt standardmäßig aktiv. Bugfixes: Ghost-Windows bei LRU-Drop
|
||||
/ Logout, Dead-Zone unter dem Input-Bar bei aktivem Hint-Banner.
|
||||
|
||||
[Release-Notes 0.6.1](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v0.6.1)
|
||||
|
||||
## [0.6.0] — 2026-05-03 — UX Polish: Pop-Out Input + Colour Presets
|
||||
|
||||
Zwei opt-in UX-Features. Pop-Out-Fenster bekommen optional eine
|
||||
kompakte Eingabe-Bar mit channel-farbigem Icon-Button und unabhängigem
|
||||
Text-Buffer pro Pop-Out. Sieben Built-in-Color-Presets (Klassik,
|
||||
High-Contrast, Pastell, Dark-Mode-Tuned, Hellion, Night Blue, Indigo
|
||||
Violet) zum One-Click-Apply. Konfigurations-Migration v10 → v11.
|
||||
Zwei opt-in UX-Features. Pop-Out-Fenster bekommen optional eine kompakte Eingabe-Bar mit channel-farbigem Icon-Button
|
||||
und unabhängigem Text-Buffer pro Pop-Out. Sieben Built-in-Color-Presets (Klassik, High-Contrast, Pastell,
|
||||
Dark-Mode-Tuned, Hellion, Night Blue, Indigo Violet) zum One-Click-Apply. Konfigurations-Migration v10 → v11.
|
||||
|
||||
[Release-Notes 0.6.0](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v0.6.0)
|
||||
|
||||
## [0.5.4] — 2026-05-02 — WrapText Hardening
|
||||
|
||||
`ImGuiUtil.WrapText` von Pointer-Arithmetik auf Span- und
|
||||
Index-basierten Control-Flow umgestellt. Schließt das wiederkehrende
|
||||
CodeQL-Critical-Alert "unvalidated local pointer arithmetic"
|
||||
dauerhaft. Keine nutzersichtbare Verhaltensänderung — Word-Wrap-Output
|
||||
ist byte-identisch zu 0.5.3.
|
||||
`ImGuiUtil.WrapText` von Pointer-Arithmetik auf Span- und Index-basierten Control-Flow umgestellt. Schließt das
|
||||
wiederkehrende CodeQL-Critical-Alert "unvalidated local pointer arithmetic" dauerhaft. Keine nutzersichtbare
|
||||
Verhaltensänderung — Word-Wrap-Output ist byte-identisch zu 0.5.3.
|
||||
|
||||
[Release-Notes 0.5.4](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v0.5.4)
|
||||
|
||||
## [0.5.3] — 2026-05-02 — Pointer Arithmetic Hardening
|
||||
|
||||
Erster Anlauf zur Schließung des CodeQL-Critical-Alerts in
|
||||
`ImGuiUtil.WrapText`. Encoded-Byte-Buffer-Length wird vor der
|
||||
Erster Anlauf zur Schließung des CodeQL-Critical-Alerts in `ImGuiUtil.WrapText`. Encoded-Byte-Buffer-Length wird vor der
|
||||
Pointer-Arithmetik via `GetByteCount` validiert.
|
||||
|
||||
[Release-Notes 0.5.3](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v0.5.3)
|
||||
@@ -391,8 +334,7 @@ Pointer-Arithmetik via `GetByteCount` validiert.
|
||||
|
||||
## Frühere Versionen
|
||||
|
||||
Releases vor 0.5.3 (Bootstrap-Phase 0.1.0 bis 0.5.2) sind direkt am
|
||||
GitHub-Release-Stream einsehbar:
|
||||
Releases vor 0.5.3 (Bootstrap-Phase 0.1.0 bis 0.5.2) sind direkt am GitHub-Release-Stream einsehbar:
|
||||
|
||||
[Alle Releases](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases)
|
||||
|
||||
@@ -400,8 +342,6 @@ GitHub-Release-Stream einsehbar:
|
||||
|
||||
## Pflege-Hinweis
|
||||
|
||||
Die Source-of-Truth für den nutzersichtbaren Changelog ist der
|
||||
`changelog:`-Block in `HellionChat/HellionChat.yaml`. `repo.json` und
|
||||
der GitHub-Release-Body werden daraus gespeist. Diese Datei
|
||||
(`docs/CHANGELOG.md`) ist eine kuratierte Zusammenfassung mit Verweis
|
||||
auf die Release-Pages und wird beim Versions-Bump manuell ergänzt.
|
||||
Die Source-of-Truth für den nutzersichtbaren Changelog ist der `changelog:`-Block in `HellionChat/HellionChat.yaml`.
|
||||
`repo.json` und der GitHub-Release-Body werden daraus gespeist. Diese Datei (`docs/CHANGELOG.md`) ist eine kuratierte
|
||||
Zusammenfassung mit Verweis auf die Release-Pages und wird beim Versions-Bump manuell ergänzt.
|
||||
|
||||
+42
-16
@@ -1,8 +1,11 @@
|
||||
# Contributors — Hellion Chat
|
||||
|
||||
Hellion Chat ist von der Code-Seite ein Ein-Personen-Projekt. Aber ohne die Leute auf dieser Seite gäbe es weder die Bug-Fixes noch die UX-Verbesserungen, die seit den frühen Versionen reingelaufen sind. Jeder Eintrag hier hat das Plugin konkret besser gemacht.
|
||||
Hellion Chat ist von der Code-Seite ein Ein-Personen-Projekt. Aber ohne die Leute auf dieser Seite gäbe es weder die
|
||||
Bug-Fixes noch die UX-Verbesserungen, die seit den frühen Versionen reingelaufen sind. Jeder Eintrag hier hat das Plugin
|
||||
konkret besser gemacht.
|
||||
|
||||
Die Anerkennung an die Upstream-Autoren von Chat 2 (Infi und Anna) liegt bewusst in [`../NOTICE.md`](../NOTICE.md), nicht hier. Diese Datei deckt explizit Beiträge zur Hellion-Chat-Seite ab.
|
||||
Die Anerkennung an die Upstream-Autoren von Chat 2 (Infi und Anna) liegt bewusst in [`../NOTICE.md`](../NOTICE.md),
|
||||
nicht hier. Diese Datei deckt explizit Beiträge zur Hellion-Chat-Seite ab.
|
||||
|
||||
---
|
||||
|
||||
@@ -10,9 +13,13 @@ Die Anerkennung an die Upstream-Autoren von Chat 2 (Infi und Anna) liegt bewusst
|
||||
|
||||
### JonKazama (Florian Wathling) — Maintainer
|
||||
|
||||
Hellion Chat ist mein erstes FFXIV-Plugin und mein erstes größeres C#-/Dalamud-Projekt. Mein beruflicher Hintergrund ist Webentwicklung (Next.js, React, TypeScript, Prisma). Plugin-Entwicklung in einer fremden Codebase, ImGui, FFXIV-Game-Hooks und der gesamte Dalamud-Stack waren Neuland.
|
||||
Hellion Chat ist mein erstes FFXIV-Plugin und mein erstes größeres C#-/Dalamud-Projekt. Mein beruflicher Hintergrund ist
|
||||
Webentwicklung (Next.js, React, TypeScript, Prisma). Plugin-Entwicklung in einer fremden Codebase, ImGui,
|
||||
FFXIV-Game-Hooks und der gesamte Dalamud-Stack waren Neuland.
|
||||
|
||||
Privacy-First-Defaults, Per-Channel-Retention, Auto-Tell-Tabs, Pop-Out-Input, ChatColours-Presets, Hellion-Theme plus Exo-2-Font und der v1.0.0-Standalone-Cut sind die Hellion-spezifischen Surface-Areas, die ich auf das Chat-2-Fundament aufgebaut habe. Die Lern-Geschichte dahinter steht in [`LEARNING-JOURNEY.md`](LEARNING-JOURNEY.md).
|
||||
Privacy-First-Defaults, Per-Channel-Retention, Auto-Tell-Tabs, Pop-Out-Input, ChatColours-Presets, Hellion-Theme plus
|
||||
Exo-2-Font und der v1.0.0-Standalone-Cut sind die Hellion-spezifischen Surface-Areas, die ich auf das Chat-2-Fundament
|
||||
aufgebaut habe. Die Lern-Geschichte dahinter steht in [`LEARNING-JOURNEY.md`](LEARNING-JOURNEY.md).
|
||||
|
||||
Hellion Chat ist Teil von [Hellion Online Media](https://hellion-media.de).
|
||||
|
||||
@@ -20,26 +27,41 @@ Hellion Chat ist Teil von [Hellion Online Media](https://hellion-media.de).
|
||||
|
||||
## Tester
|
||||
|
||||
Eine kurze Notiz vorneweg: Ich teste das Plugin nicht allein. Die Leute hier haben mir Bugs gemeldet, bevor sie bei mehr Nutzern aufgeschlagen wären. Sie haben UX-Probleme angesprochen, die ich blind nicht mehr gesehen habe. Und sie haben Feature-Wünsche eingebracht, die das Plugin in Richtungen geschoben haben, in die ich von alleine nicht gegangen wäre. Das ist nicht selbstverständlich. Externe Tester sind ihre Zeit wert.
|
||||
Eine kurze Notiz vorneweg: Ich teste das Plugin nicht allein. Die Leute hier haben mir Bugs gemeldet, bevor sie bei mehr
|
||||
Nutzern aufgeschlagen wären. Sie haben UX-Probleme angesprochen, die ich blind nicht mehr gesehen habe. Und sie haben
|
||||
Feature-Wünsche eingebracht, die das Plugin in Richtungen geschoben haben, in die ich von alleine nicht gegangen wäre.
|
||||
Das ist nicht selbstverständlich. Externe Tester sind ihre Zeit wert.
|
||||
|
||||
### Carl Beleandis (Carla) — Beta-Tester
|
||||
|
||||
Carl testet seit der Bootstrap-Phase und hat sowohl die Pop-Out-Mechanik als auch die Theme-Richtung geprägt. Sein Feedback kommt direkt und ohne Umschweife und das ist genau, was ich beim Testen brauche.
|
||||
Carl testet seit der Bootstrap-Phase und hat sowohl die Pop-Out-Mechanik als auch die Theme-Richtung geprägt. Sein
|
||||
Feedback kommt direkt und ohne Umschweife und das ist genau, was ich beim Testen brauche.
|
||||
|
||||
Konkrete Beiträge:
|
||||
|
||||
- **Pop-Out-Discoverability** — der Hinweis, dass Pop-Outs nur per Rechtsklick erreichbar waren, hat den Header-Button und den einmaligen Hint-Banner in v0.6.1 ausgelöst. Ich kannte den Rechtsklick-Pfad blind, deshalb hatte ich nicht mehr gesehen, dass neue Nutzer die Funktion gar nicht finden.
|
||||
- **/tell-Pop-Out-Mode** — der Wunsch, /tell-Tabs direkt als Pop-Out zu öffnen statt über den Tab-Umweg, ist in v0.6.1 als opt-in Settings-Toggle gelandet. Bonus: Bei der Implementation ist ein alter Ghost-Window-Bug aufgefallen (LRU-Drop ließ Pop-Out-Fenster als Geister stehen), der gleich mit gefixt wurde.
|
||||
- **Theme-Varianten mit Helligkeits-Abstufungen** — der Wunsch nach einer Grün-Familie hat mein Verständnis von "ein Theme = eine Farbe" auf "Theme-Familien mit Stimmungs-Varianten" verschoben. Steht in der [Roadmap](ROADMAP.md) für einen späteren Cycle.
|
||||
- **Pop-Out-Discoverability** — der Hinweis, dass Pop-Outs nur per Rechtsklick erreichbar waren, hat den Header-Button
|
||||
und den einmaligen Hint-Banner in v0.6.1 ausgelöst. Ich kannte den Rechtsklick-Pfad blind, deshalb hatte ich nicht
|
||||
mehr gesehen, dass neue Nutzer die Funktion gar nicht finden.
|
||||
- **/tell-Pop-Out-Mode** — der Wunsch, /tell-Tabs direkt als Pop-Out zu öffnen statt über den Tab-Umweg, ist in v0.6.1
|
||||
als opt-in Settings-Toggle gelandet. Bonus: Bei der Implementation ist ein alter Ghost-Window-Bug aufgefallen
|
||||
(LRU-Drop ließ Pop-Out-Fenster als Geister stehen), der gleich mit gefixt wurde.
|
||||
- **Theme-Varianten mit Helligkeits-Abstufungen** — der Wunsch nach einer Grün-Familie hat mein Verständnis von "ein
|
||||
Theme = eine Farbe" auf "Theme-Familien mit Stimmungs-Varianten" verschoben. Steht in der [Roadmap](ROADMAP.md) für
|
||||
einen späteren Cycle.
|
||||
|
||||
### Jin (Jingliu) — Alpha-Tester
|
||||
|
||||
Jin ist der aktive Tester der ersten Stunde und hat den Pop-Out-Workflow architektonisch in eine andere Richtung geschoben.
|
||||
Jin ist der aktive Tester der ersten Stunde und hat den Pop-Out-Workflow architektonisch in eine andere Richtung
|
||||
geschoben.
|
||||
|
||||
Konkrete Beiträge:
|
||||
|
||||
- **Pop-Out-Tab mit Input-Feld** — der Vorschlag, in einem Pop-Out auch tippen zu können (statt nur lesen), hat die v0.6.0 Pop-Out-Input-Bar ausgelöst. Das war ein größerer Refactor: Der Input-Layer aus `ChatLogWindow` musste so geöffnet werden, dass er auch in `Popout.cs` lebt, mit unabhängigem Text-Buffer und History-Cursor pro Pop-Out. Hat den Cycle dominiert, weil das Design erst sauber sein musste, bevor Code passieren konnte.
|
||||
- **TempTell Persistence** — der Wunsch, /tell-Tabs per Pin-Toggle einen Relog überleben zu lassen, steht in der [Roadmap](ROADMAP.md) für einen späteren Cycle. Berührt das Tab-System architektonisch und braucht eigenes Design.
|
||||
- **Pop-Out-Tab mit Input-Feld** — der Vorschlag, in einem Pop-Out auch tippen zu können (statt nur lesen), hat die
|
||||
v0.6.0 Pop-Out-Input-Bar ausgelöst. Das war ein größerer Refactor: Der Input-Layer aus `ChatLogWindow` musste so
|
||||
geöffnet werden, dass er auch in `Popout.cs` lebt, mit unabhängigem Text-Buffer und History-Cursor pro Pop-Out. Hat
|
||||
den Cycle dominiert, weil das Design erst sauber sein musste, bevor Code passieren konnte.
|
||||
- **TempTell Persistence** — der Wunsch, /tell-Tabs per Pin-Toggle einen Relog überleben zu lassen, steht in der
|
||||
[Roadmap](ROADMAP.md) für einen späteren Cycle. Berührt das Tab-System architektonisch und braucht eigenes Design.
|
||||
|
||||
---
|
||||
|
||||
@@ -49,13 +71,17 @@ Hellion-eigene UI-Strings werden in `HellionChat/Resources/HellionStrings.<lang>
|
||||
|
||||
- **Deutsch (DE):** JonKazama (Native Speaker, Hauptsprache des Projekts)
|
||||
|
||||
Die Upstream-Sprach-Dateien (`Language.<lang>.resx`) sind nicht Teil dieser Datei. Sie werden über das [Chat-2-Crowdin-Projekt](https://github.com/Infiziert90/ChatTwo) gepflegt; Crowdin-Übersetzer findest du in den Plugin-Settings unter **Info → "Chat 2 community translators"**.
|
||||
Die Upstream-Sprach-Dateien (`Language.<lang>.resx`) sind nicht Teil dieser Datei. Sie werden über das
|
||||
[Chat-2-Crowdin-Projekt](https://github.com/Infiziert90/ChatTwo) gepflegt; Crowdin-Übersetzer findest du in den
|
||||
Plugin-Settings unter **Info → "Chat 2 community translators"**.
|
||||
|
||||
---
|
||||
|
||||
## Wie du beitragen kannst
|
||||
|
||||
Bug-Reports, Feature-Wünsche und Pull-Requests laufen über [Gitea Issues](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/issues). Workflow und Erwartungen stehen in [`../CONTRIBUTING.md`](../CONTRIBUTING.md), Code of Conduct in [`../CODE_OF_CONDUCT.md`](../CODE_OF_CONDUCT.md).
|
||||
|
||||
Tester-Pool für neue Versionen läuft über den Hellion-Forge-Discord: [discord.gg/X9V7Kcv5gR](https://discord.gg/X9V7Kcv5gR). Wer in den Tester-Channel rein will, einfach im Forge melden.
|
||||
Bug-Reports, Feature-Wünsche und Pull-Requests laufen über
|
||||
[Gitea Issues](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/issues). Workflow und Erwartungen stehen
|
||||
in [`../CONTRIBUTING.md`](../CONTRIBUTING.md), Code of Conduct in [`../CODE_OF_CONDUCT.md`](../CODE_OF_CONDUCT.md).
|
||||
|
||||
Tester-Pool für neue Versionen läuft über den Hellion-Forge-Discord:
|
||||
[discord.gg/X9V7Kcv5gR](https://discord.gg/X9V7Kcv5gR). Wer in den Tester-Channel rein will, einfach im Forge melden.
|
||||
|
||||
+58
-79
@@ -1,69 +1,58 @@
|
||||
# Hellion Chat IPC Integration Guide
|
||||
|
||||
This document describes the inter-plugin-communication (IPC) channels that
|
||||
Hellion Chat exposes to other Dalamud plugins. Two integration surfaces are
|
||||
covered: the **Context Menu IPC** for adding custom items to Hellion Chat's
|
||||
right-click menus, and the **Typing State IPC** for reacting to the user's
|
||||
input-box activity.
|
||||
This document describes the inter-plugin-communication (IPC) channels that Hellion Chat exposes to other Dalamud
|
||||
plugins. Two integration surfaces are covered: the **Context Menu IPC** for adding custom items to Hellion Chat's
|
||||
right-click menus, and the **Typing State IPC** for reacting to the user's input-box activity.
|
||||
|
||||
---
|
||||
|
||||
## Compatibility with Chat 2
|
||||
|
||||
Hellion Chat is a standalone fork of [Chat 2](https://github.com/Infiziert90/ChatTwo)
|
||||
(EUPL-1.2). The IPC surface is one of the parts the fork inherits directly:
|
||||
the same call shapes, the same tuple payloads, the same call semantics, the
|
||||
same lifecycle. We did not redesign the API, we re-published it under our own
|
||||
plugin name.
|
||||
Hellion Chat is a standalone fork of [Chat 2](https://github.com/Infiziert90/ChatTwo) (EUPL-1.2). The IPC surface is one
|
||||
of the parts the fork inherits directly: the same call shapes, the same tuple payloads, the same call semantics, the
|
||||
same lifecycle. We did not redesign the API, we re-published it under our own plugin name.
|
||||
|
||||
Concretely, this means:
|
||||
|
||||
- **Tuple shapes are identical.** A subscriber that worked against Chat 2's
|
||||
`ChatTwo.Invoke` works against Hellion Chat's `HellionChat.Invoke` without
|
||||
any code change beyond the channel string.
|
||||
- **Lifecycle is identical.** The `Available` ping fires when the plugin
|
||||
becomes ready, your subscriber re-registers, and the registration ID is
|
||||
returned by the same `Register` call as before.
|
||||
- **Channel-name prefix changed in v1.0.0.** Every `ChatTwo.*` channel name
|
||||
is now `HellionChat.*`. Existing third-party integrations need a one-line
|
||||
rename per channel string and nothing else.
|
||||
- **Tuple shapes are identical.** A subscriber that worked against Chat 2's `ChatTwo.Invoke` works against Hellion
|
||||
Chat's `HellionChat.Invoke` without any code change beyond the channel string.
|
||||
- **Lifecycle is identical.** The `Available` ping fires when the plugin becomes ready, your subscriber re-registers,
|
||||
and the registration ID is returned by the same `Register` call as before.
|
||||
- **Channel-name prefix changed in v1.0.0.** Every `ChatTwo.*` channel name is now `HellionChat.*`. Existing third-party
|
||||
integrations need a one-line rename per channel string and nothing else.
|
||||
|
||||
If your plugin already supports Chat 2 and you want to add Hellion Chat
|
||||
support, the cleanest path is to bind both prefixes and treat whichever one
|
||||
becomes available first as the active host.
|
||||
If your plugin already supports Chat 2 and you want to add Hellion Chat support, the cleanest path is to bind both
|
||||
prefixes and treat whichever one becomes available first as the active host.
|
||||
|
||||
---
|
||||
|
||||
## Channel Reference
|
||||
|
||||
| Surface | Channel | Direction | Payload |
|
||||
| ------------- | ------------------------------------ | --------------- | ---------------------------------------------------------------------------------------- |
|
||||
| Context Menu | `HellionChat.Available` | plugin → caller | event, no payload |
|
||||
| Context Menu | `HellionChat.Register` | caller → plugin | returns registration `string` ID |
|
||||
| Context Menu | `HellionChat.Unregister` | caller → plugin | takes registration ID `string` |
|
||||
| Context Menu | `HellionChat.Invoke` | plugin → caller | event, see Context Menu section |
|
||||
| Typing State | `HellionChat.GetChatInputState` | caller → plugin | returns the typing-state tuple |
|
||||
| Typing State | `HellionChat.ChatInputStateChanged` | plugin → caller | event, fires once on subscribe and on every state change, payload is the same tuple |
|
||||
| Surface | Channel | Direction | Payload |
|
||||
| ------------ | ----------------------------------- | --------------- | ----------------------------------------------------------------------------------- |
|
||||
| Context Menu | `HellionChat.Available` | plugin → caller | event, no payload |
|
||||
| Context Menu | `HellionChat.Register` | caller → plugin | returns registration `string` ID |
|
||||
| Context Menu | `HellionChat.Unregister` | caller → plugin | takes registration ID `string` |
|
||||
| Context Menu | `HellionChat.Invoke` | plugin → caller | event, see Context Menu section |
|
||||
| Typing State | `HellionChat.GetChatInputState` | caller → plugin | returns the typing-state tuple |
|
||||
| Typing State | `HellionChat.ChatInputStateChanged` | plugin → caller | event, fires once on subscribe and on every state change, payload is the same tuple |
|
||||
|
||||
---
|
||||
|
||||
## Context Menu IPC
|
||||
|
||||
Use this surface to draw your own selectables inside Hellion Chat's
|
||||
right-click context menus. All registrations are called inside an ImGui
|
||||
`BeginMenu`, so anything you draw appears as a regular menu entry.
|
||||
Use this surface to draw your own selectables inside Hellion Chat's right-click context menus. All registrations are
|
||||
called inside an ImGui `BeginMenu`, so anything you draw appears as a regular menu entry.
|
||||
|
||||
### Lifecycle
|
||||
|
||||
1. Subscribe to `HellionChat.Available`. The host fires this once when it
|
||||
loads or reloads, so your plugin can re-register without polling.
|
||||
2. Call `HellionChat.Register` to obtain a registration ID. Save it. You
|
||||
need it to filter `Invoke` callbacks that target your registration and
|
||||
to call `Unregister` later.
|
||||
3. Subscribe to `HellionChat.Invoke` and draw your menu items inside the
|
||||
handler when the `id` matches your saved registration ID.
|
||||
4. On plugin disable or unload, call `HellionChat.Unregister` with your
|
||||
saved ID and unsubscribe from `Invoke`.
|
||||
1. Subscribe to `HellionChat.Available`. The host fires this once when it loads or reloads, so your plugin can
|
||||
re-register without polling.
|
||||
2. Call `HellionChat.Register` to obtain a registration ID. Save it. You need it to filter `Invoke` callbacks that
|
||||
target your registration and to call `Unregister` later.
|
||||
3. Subscribe to `HellionChat.Invoke` and draw your menu items inside the handler when the `id` matches your saved
|
||||
registration ID.
|
||||
4. On plugin disable or unload, call `HellionChat.Unregister` with your saved ID and unsubscribe from `Invoke`.
|
||||
|
||||
### Example
|
||||
|
||||
@@ -131,8 +120,7 @@ public class HellionChatContextMenu {
|
||||
|
||||
### Migration from Chat 2
|
||||
|
||||
If your plugin already integrates with `ChatTwo.*`, the rename is the only
|
||||
required change:
|
||||
If your plugin already integrates with `ChatTwo.*`, the rename is the only required change:
|
||||
|
||||
```diff
|
||||
-this.Register = @interface.GetIpcSubscriber<string>("ChatTwo.Register");
|
||||
@@ -149,50 +137,42 @@ required change:
|
||||
|
||||
## Typing State IPC
|
||||
|
||||
Use this surface when you need to know whether the player is currently
|
||||
interacting with Hellion Chat's input box. Useful for typing indicators,
|
||||
keyboard-shortcut suppression, or HUD elements that hide while the user is
|
||||
typing.
|
||||
Use this surface when you need to know whether the player is currently interacting with Hellion Chat's input box. Useful
|
||||
for typing indicators, keyboard-shortcut suppression, or HUD elements that hide while the user is typing.
|
||||
|
||||
### Tuple Payload
|
||||
|
||||
Both `HellionChat.GetChatInputState` (poll) and
|
||||
`HellionChat.ChatInputStateChanged` (event) return the same tuple:
|
||||
Both `HellionChat.GetChatInputState` (poll) and `HellionChat.ChatInputStateChanged` (event) return the same tuple:
|
||||
|
||||
```cs
|
||||
(bool InputVisible, bool InputFocused, bool HasText, bool IsTyping, int TextLength, ChatType ChannelType)
|
||||
```
|
||||
|
||||
| Field | Type | Meaning |
|
||||
| -------------- | ---------- | -------------------------------------------------------------------------------- |
|
||||
| `InputVisible` | `bool` | True when Hellion Chat is not hidden by user, cutscene or battle settings. |
|
||||
| `InputFocused` | `bool` | True while the input box currently has keyboard focus. |
|
||||
| `HasText` | `bool` | True when the input buffer contains more than whitespace. |
|
||||
| `IsTyping` | `bool` | Convenience flag, equivalent to `InputFocused && HasText`. |
|
||||
| `TextLength` | `int` | Length of the raw input buffer in characters. |
|
||||
| `ChannelType` | `ChatType` | The channel/mode that will be used if the buffer is submitted right now. |
|
||||
| Field | Type | Meaning |
|
||||
| -------------- | ---------- | -------------------------------------------------------------------------- |
|
||||
| `InputVisible` | `bool` | True when Hellion Chat is not hidden by user, cutscene or battle settings. |
|
||||
| `InputFocused` | `bool` | True while the input box currently has keyboard focus. |
|
||||
| `HasText` | `bool` | True when the input buffer contains more than whitespace. |
|
||||
| `IsTyping` | `bool` | Convenience flag, equivalent to `InputFocused && HasText`. |
|
||||
| `TextLength` | `int` | Length of the raw input buffer in characters. |
|
||||
| `ChannelType` | `ChatType` | The channel/mode that will be used if the buffer is submitted right now. |
|
||||
|
||||
### Where `ChannelType` comes from
|
||||
|
||||
`ChannelType` is the `HellionChat.Code.ChatType` enum value representing the
|
||||
target channel for the current submission. It is sourced from the active
|
||||
tab's `UsedChannel` (`HellionChat/Configuration.cs`), which the plugin keeps
|
||||
in sync by hooking the in-game shell (`HellionChat/GameFunctions/Chat.cs`)
|
||||
and by resolving temporary overrides inside the chat UI
|
||||
(`HellionChat/Ui/ChatLogWindow.cs:597`). `InputChannel` values are converted
|
||||
into the exported `ChatType` via
|
||||
`ChannelType` is the `HellionChat.Code.ChatType` enum value representing the target channel for the current submission.
|
||||
It is sourced from the active tab's `UsedChannel` (`HellionChat/Configuration.cs`), which the plugin keeps in sync by
|
||||
hooking the in-game shell (`HellionChat/GameFunctions/Chat.cs`) and by resolving temporary overrides inside the chat UI
|
||||
(`HellionChat/Ui/ChatLogWindow.cs:597`). `InputChannel` values are converted into the exported `ChatType` via
|
||||
`HellionChat/Code/InputChannelExt.ToChatType`.
|
||||
|
||||
### Behavior
|
||||
|
||||
- `ChatInputStateChanged` fires once immediately after subscribe so you do
|
||||
not need a separate `GetChatInputState` poll for the initial snapshot.
|
||||
- After that it fires only when one or more fields actually change, so it
|
||||
is safe to subscribe without rate-limiting.
|
||||
- `GetChatInputState` is available for one-shot polls, e.g. on plugin
|
||||
enable.
|
||||
- `ChatInputStateChanged` fires once immediately after subscribe so you do not need a separate `GetChatInputState` poll
|
||||
for the initial snapshot.
|
||||
- After that it fires only when one or more fields actually change, so it is safe to subscribe without rate-limiting.
|
||||
- `GetChatInputState` is available for one-shot polls, e.g. on plugin enable.
|
||||
|
||||
### Example
|
||||
### Example 2
|
||||
|
||||
```cs
|
||||
public sealed class HellionChatTypingIntegration {
|
||||
@@ -228,10 +208,9 @@ public sealed class HellionChatTypingIntegration {
|
||||
}
|
||||
```
|
||||
|
||||
### Migration from Chat 2
|
||||
### Migration
|
||||
|
||||
Same shape as the Context Menu surface — only the channel-name prefix needs
|
||||
the rename:
|
||||
Same shape as the Context Menu surface — only the channel-name prefix needs the rename:
|
||||
|
||||
```diff
|
||||
-this.GetChatInputState = @interface.GetIpcSubscriber<...>("ChatTwo.GetChatInputState");
|
||||
@@ -244,7 +223,7 @@ the rename:
|
||||
|
||||
## License & Attribution
|
||||
|
||||
This guide and the IPC surface it documents derive directly from the Chat 2
|
||||
codebase. Hellion Chat is licensed under [EUPL-1.2](LICENSE), and credit for
|
||||
the original IPC design and implementation goes to **Infiziert90 (Infi)**
|
||||
and **Anna Clemens** — see [`NOTICE.md`](NOTICE.md) for full attribution.
|
||||
This guide and the IPC surface it documents derive directly from the Chat 2 codebase. Hellion Chat is licensed under
|
||||
[EUPL-1.2](LICENSE), and credit for the original IPC design and implementation goes to
|
||||
**[Infiziert90 (Infi)](https://github.com/Infiziert90)** and **[Anna](https://github.com/anna-is-cute)**,— see
|
||||
[`NOTICE.md`](NOTICE.md) for full attribution.
|
||||
|
||||
+164
-47
@@ -2,27 +2,40 @@
|
||||
|
||||
## Hintergrund
|
||||
|
||||
Ich bin Autodidakt. Hellion Chat ist mein erstes FFXIV-Plugin und mein erstes größeres C#-Projekt. Mein beruflicher Hintergrund ist Webentwicklung (Next.js, React, TypeScript, Prisma, MySQL), also Browser-Welt mit JavaScript-Toolchain. C# kannte ich vor diesem Projekt nur oberflächlich, ImGui gar nicht, Dalamud nur als Endnutzer über andere Plugins.
|
||||
Ich bin Autodidakt. Hellion Chat ist mein erstes FFXIV-Plugin und mein erstes größeres C#-Projekt. Mein beruflicher
|
||||
Hintergrund ist Webentwicklung (Next.js, React, TypeScript, Prisma, MySQL), also Browser-Welt mit JavaScript-Toolchain.
|
||||
C# kannte ich vor diesem Projekt nur oberflächlich, ImGui gar nicht, Dalamud nur als Endnutzer über andere Plugins.
|
||||
|
||||
Wenn ich an einer Stelle nicht weiterkomme, nutze ich AI-Tools wie Claude Code als Pair-Hilfsmittel. Wie das genau aussieht und welche Klassifikation ich verwende, steht transparent in [`AI_DISCLOSURE.md`](AI_DISCLOSURE.md).
|
||||
Wenn ich an einer Stelle nicht weiterkomme, nutze ich AI-Tools wie Claude Code als Pair-Hilfsmittel. Wie das genau
|
||||
aussieht und welche Klassifikation ich verwende, steht transparent in [`AI_DISCLOSURE.md`](AI_DISCLOSURE.md).
|
||||
|
||||
---
|
||||
|
||||
## Warum überhaupt ein Chat-Plugin?
|
||||
|
||||
Hellion Chat soll Chat 2 nicht ersetzen. Chat 2 liefert ein vollständiges Chat-Erlebnis mit kompletter Historie, Filtern, Suche und Replay. Für die meisten Nutzer ist genau das richtig.
|
||||
Hellion Chat soll Chat 2 nicht ersetzen. Chat 2 liefert ein vollständiges Chat-Erlebnis mit kompletter Historie,
|
||||
Filtern, Suche und Replay. Für die meisten Nutzer ist genau das richtig.
|
||||
|
||||
### Zwei Millionen Nachrichten in zwei Jahren
|
||||
|
||||
Mein Wunsch nach einem engeren Default war ehrlich gesagt erstmal persönlich. Nach zwei Jahren mit Chat 2 lag meine Datenbank bei über zwei Millionen Nachrichten, der Großteil davon /say, /shout und /yell von wildfremden Leuten in Limsa. Genau diese Daten machen Chat 2's Voll-Historie nützlich, und die meisten Nutzer behalten sie auch gerne. Mein eigener Geschmack wollte einen kleineren Default. Also habe ich diesen Fork gebaut.
|
||||
Mein Wunsch nach einem engeren Default war ehrlich gesagt erstmal persönlich. Nach zwei Jahren mit Chat 2 lag meine
|
||||
Datenbank bei über zwei Millionen Nachrichten, der Großteil davon /say, /shout und /yell von wildfremden Leuten in
|
||||
Limsa. Genau diese Daten machen Chat 2's Voll-Historie nützlich, und die meisten Nutzer behalten sie auch gerne. Mein
|
||||
eigener Geschmack wollte einen kleineren Default. Also habe ich diesen Fork gebaut.
|
||||
|
||||
### Greeter in mehreren Clubs
|
||||
|
||||
Dazu kam ein zweiter Use-Case: Ich bin in mehreren FFXIV-Clubs als Greeter aktiv. Für die Greeter-Arbeit reicht die Vanilla-Chat-Oberfläche nicht. Parallel laufende /tell-Gespräche schreiben in einem einzigen Tab durcheinander, und ich verliere ständig den Faden, wer mir gerade was geschrieben hat. Auto-Tell-Tabs (eines der frühen Hellion-Chat-Features) ist genau für diesen Workflow entstanden: ein Tab pro Gesprächspartner, automatisch gespawnt, mit manuellem Greeted-Status. Dass das auch der Privacy-Hygiene gut tut, war ein netter Bonus, nicht der Auslöser.
|
||||
Dazu kam ein zweiter Use-Case: Ich bin in mehreren FFXIV-Clubs als Greeter aktiv. Für die Greeter-Arbeit reicht die
|
||||
Vanilla-Chat-Oberfläche nicht. Parallel laufende /tell-Gespräche schreiben in einem einzigen Tab durcheinander, und ich
|
||||
verliere ständig den Faden, wer mir gerade was geschrieben hat. Auto-Tell-Tabs (eines der frühen Hellion-Chat-Features)
|
||||
ist genau für diesen Workflow entstanden: ein Tab pro Gesprächspartner, automatisch gespawnt, mit manuellem
|
||||
Greeted-Status. Dass das auch der Privacy-Hygiene gut tut, war ein netter Bonus, nicht der Auslöser.
|
||||
|
||||
### Hellion Online Media
|
||||
|
||||
Die Privacy-Defaults sind außerdem eine Position aus meinem Hauptberuf. Hellion Online Media ist mein Einzelunternehmen, und Datenschutz gegenüber Kunden ist da kein Marketing-Slogan, sondern operativ relevant. Dieser Fork ist die Plugin-Form derselben Haltung.
|
||||
Die Privacy-Defaults sind außerdem eine Position aus meinem Hauptberuf. Hellion Online Media ist mein Einzelunternehmen,
|
||||
und Datenschutz gegenüber Kunden ist da kein Marketing-Slogan, sondern operativ relevant. Dieser Fork ist die
|
||||
Plugin-Form derselben Haltung.
|
||||
|
||||
---
|
||||
|
||||
@@ -32,51 +45,89 @@ Drei Gründe, in absteigender Wichtigkeit.
|
||||
|
||||
### Defaults sind nicht verhandelbar, auch nicht meine
|
||||
|
||||
Privacy-First als Standard ist eine Minderheits-Position. Chat 2 bedient zu Recht die breite Masse mit Voll-Historie als Default. Diese Defaults im Upstream zu ändern wäre falsch gewesen. Ich hätte den Standard für eine große Nutzerbasis umgekippt, die ihn so wollte, wie er ist. Saubere Trennung über einen eigenen Plugin-Slot war der respektvollere Weg.
|
||||
Privacy-First als Standard ist eine Minderheits-Position. Chat 2 bedient zu Recht die breite Masse mit Voll-Historie als
|
||||
Default. Diese Defaults im Upstream zu ändern wäre falsch gewesen. Ich hätte den Standard für eine große Nutzerbasis
|
||||
umgekippt, die ihn so wollte, wie er ist. Saubere Trennung über einen eigenen Plugin-Slot war der respektvollere Weg.
|
||||
|
||||
### Das Webinterface musste weg
|
||||
|
||||
Das ist ein zentrales Chat-2-Feature für Remote-Zugriff vom Zweitgerät. Ein PR der das entfernt, hat in einem gepflegten Upstream-Projekt keine Chance, und das ist auch richtig so. Aber genau das Webinterface kollidiert mit der Privacy-First-These dieses Forks: Ein Chat-Plugin das einen lokalen HTTP-Server startet, ist für mein Threat-Model eine zu große Angriffsfläche. Also raus damit.
|
||||
Das ist ein zentrales Chat-2-Feature für Remote-Zugriff vom Zweitgerät. Ein PR der das entfernt, hat in einem gepflegten
|
||||
Upstream-Projekt keine Chance, und das ist auch richtig so. Aber genau das Webinterface kollidiert mit der
|
||||
Privacy-First-These dieses Forks: Ein Chat-Plugin das einen lokalen HTTP-Server startet, ist für mein Threat-Model eine
|
||||
zu große Angriffsfläche. Also raus damit.
|
||||
|
||||
### Tempo
|
||||
|
||||
Ein Solo-Maintainer-Projekt mit kleinem Tester-Pool kann schneller iterieren als ein etabliertes Plugin mit großer Nutzerbasis. Das ist kein Vorwurf an Upstream, sondern eine andere Optimierung. Ich brauche keine Roadmap-Abstimmung, keine Reviewer-Verfügbarkeit, und kann Audit-Konsequenzen wie das Webinterface-Removal in einer einzigen Version durchziehen statt über mehrere Releases.
|
||||
Ein Solo-Maintainer-Projekt mit kleinem Tester-Pool kann schneller iterieren als ein etabliertes Plugin mit großer
|
||||
Nutzerbasis. Das ist kein Vorwurf an Upstream, sondern eine andere Optimierung. Ich brauche keine Roadmap-Abstimmung,
|
||||
keine Reviewer-Verfügbarkeit, und kann Audit-Konsequenzen wie das Webinterface-Removal in einer einzigen Version
|
||||
durchziehen statt über mehrere Releases.
|
||||
|
||||
EUPL-1.2 erlaubt das alles ausdrücklich, mit klarer Attribution. Der Code liegt offen unter derselben Lizenz wie Chat 2. Infi, Anna oder sonst jemand dürfen reinschauen, Ideen mitnehmen, Fragen stellen oder den Fork einfach ignorieren. Alles drei ist für mich okay.
|
||||
EUPL-1.2 erlaubt das alles ausdrücklich, mit klarer Attribution. Der Code liegt offen unter derselben Lizenz wie Chat 2.
|
||||
Infi, Anna oder sonst jemand dürfen reinschauen, Ideen mitnehmen, Fragen stellen oder den Fork einfach ignorieren. Alles
|
||||
drei ist für mich okay.
|
||||
|
||||
---
|
||||
|
||||
## Wie ich so schnell release
|
||||
|
||||
Wer auf den Repo schaut, sieht in kurzer Zeit viele Releases und sehr viele Commits. Beides wird von außen gerne als Red-Flag gelesen: KI-Slop, Salami-Taktik, Code-Spam. Bei Hellion Chat ist beides eine bewusste Entscheidung, und ich erkläre lieber einmal warum, als mich später dafür zu rechtfertigen.
|
||||
Wer auf den Repo schaut, sieht in kurzer Zeit viele Releases und sehr viele Commits. Beides wird von außen gerne als
|
||||
Red-Flag gelesen: KI-Slop, Salami-Taktik, Code-Spam. Bei Hellion Chat ist beides eine bewusste Entscheidung, und ich
|
||||
erkläre lieber einmal warum, als mich später dafür zu rechtfertigen.
|
||||
|
||||
### Vorarbeit, lange bevor der Fork existierte
|
||||
|
||||
Bevor ich die erste Zeile in `HellionChat/` getippt habe, war ich wochenlang nur Leser. Chat 2 ingame nutzen und damit rumspielen. Issues im Upstream-Tracker durchgehen, vor allem die geschlossenen, weil dort steht, wie Infi und Anna Bugs einkreisen. Commits lesen, gerne auch ältere, um zu verstehen, warum eine Architektur-Entscheidung getroffen wurde, nicht nur, dass sie getroffen wurde. Wenn ich heute weiß, wo im Code was liegt, dann nicht, weil ich besonders schnell durch eine Codebase navigiere, sondern weil ich den Code vorher gelesen habe.
|
||||
Bevor ich die erste Zeile in `HellionChat/` getippt habe, war ich wochenlang nur Leser. Chat 2 ingame nutzen und damit
|
||||
rumspielen. Issues im Upstream-Tracker durchgehen, vor allem die geschlossenen, weil dort steht, wie Infi und Anna Bugs
|
||||
einkreisen. Commits lesen, gerne auch ältere, um zu verstehen, warum eine Architektur-Entscheidung getroffen wurde,
|
||||
nicht nur, dass sie getroffen wurde. Wenn ich heute weiß, wo im Code was liegt, dann nicht, weil ich besonders schnell
|
||||
durch eine Codebase navigiere, sondern weil ich den Code vorher gelesen habe.
|
||||
|
||||
Klingt nach Selbstverständlichkeit, ist es aber nicht. Die übliche Reihenfolge bei Solo-Forks heißt erst forken, dann verstehen. Ich habe es andersrum gemacht.
|
||||
Klingt nach Selbstverständlichkeit, ist es aber nicht. Die übliche Reihenfolge bei Solo-Forks heißt erst forken, dann
|
||||
verstehen. Ich habe es andersrum gemacht.
|
||||
|
||||
### Die Codebase von Infi und Anna
|
||||
|
||||
Hellion Chat baut auf einem Boden auf, der schon flach ist. Chat 2 ist sauber strukturiert, die Naming-Konventionen sind konsistent, die Trennung zwischen Layern (Storage, UI, Game-Hooks, IPC) ist klar gezogen. Das ist in Open-Source-Plugin-Welten nicht selbstverständlich, und es ist der Hauptgrund, warum sich Hellion-spezifische Features oft "fast nativ" einbauen lassen. Ich muss nicht erst Spaghetti entwirren bevor ich was Eigenes danebenstellen kann.
|
||||
Hellion Chat baut auf einem Boden auf, der schon flach ist. Chat 2 ist sauber strukturiert, die Naming-Konventionen sind
|
||||
konsistent, die Trennung zwischen Layern (Storage, UI, Game-Hooks, IPC) ist klar gezogen. Das ist in
|
||||
Open-Source-Plugin-Welten nicht selbstverständlich, und es ist der Hauptgrund, warum sich Hellion-spezifische Features
|
||||
oft "fast nativ" einbauen lassen. Ich muss nicht erst Spaghetti entwirren bevor ich was Eigenes danebenstellen kann.
|
||||
|
||||
Side-Fact: Selbst beim ersten Codebase-Walkthrough mit Claude kam mehrfach der Hinweis, dass die Architektur ungewöhnlich gut aufgeräumt ist und mehrere Erweiterungspunkte vorbereitet. Das hat Gewicht, weil es von außen kommt, aber den eigentlichen Kredit kriegen Infi und Anna, nicht Claude.
|
||||
Side-Fact: Selbst beim ersten Codebase-Walkthrough mit Claude kam mehrfach der Hinweis, dass die Architektur
|
||||
ungewöhnlich gut aufgeräumt ist und mehrere Erweiterungspunkte vorbereitet. Das hat Gewicht, weil es von außen kommt,
|
||||
aber den eigentlichen Kredit kriegen Infi und Anna, nicht Claude.
|
||||
|
||||
### Atomar arbeiten, kleine Commits
|
||||
|
||||
Ein Commit, eine logische Änderung. Wenn ich einen Bug fixe, parallel eine Variable umbenenne und nebenbei einen Kommentar einbaue, sind das drei Commits, nicht einer. Klingt nach Mikro-Management, ist es aber nicht. Wenn in sechs Monaten ein Bug auftaucht und ich `git bisect` brauche, finde ich die kaputte Änderung in zwei Minuten statt in zwei Stunden. Bei einem 4000-Zeilen-Mega-Commit darf ich raten, welche der hundert Änderungen die kaputte ist.
|
||||
Ein Commit, eine logische Änderung. Wenn ich einen Bug fixe, parallel eine Variable umbenenne und nebenbei einen
|
||||
Kommentar einbaue, sind das drei Commits, nicht einer. Klingt nach Mikro-Management, ist es aber nicht. Wenn in sechs
|
||||
Monaten ein Bug auftaucht und ich `git bisect` brauche, finde ich die kaputte Änderung in zwei Minuten statt in zwei
|
||||
Stunden. Bei einem 4000-Zeilen-Mega-Commit darf ich raten, welche der hundert Änderungen die kaputte ist.
|
||||
|
||||
Den Stil habe ich bewusst auch deshalb beibehalten, weil Infi im Upstream häufig genauso arbeitet. Manchmal ein Sechs-Zeilen-Commit, manchmal nur ein Typo-Fix. Das ist keine Schwäche, das ist eine Entscheidung für lesbare Git-History. Den Stil im Fork beizubehalten ist ein Respekt-Move: Wer die beiden Repos vergleicht, soll den gleichen Lese-Rhythmus haben.
|
||||
Den Stil habe ich bewusst auch deshalb beibehalten, weil Infi im Upstream häufig genauso arbeitet. Manchmal ein
|
||||
Sechs-Zeilen-Commit, manchmal nur ein Typo-Fix. Das ist keine Schwäche, das ist eine Entscheidung für lesbare
|
||||
Git-History. Den Stil im Fork beizubehalten ist ein Respekt-Move: Wer die beiden Repos vergleicht, soll den gleichen
|
||||
Lese-Rhythmus haben.
|
||||
|
||||
Bonus für mich persönlich: Kleine Commits zwingen mich, jeden Schritt einzeln zu durchdenken und zu benennen. Wenn ich nicht in zwei Sätzen erklären kann, was ein Commit macht, ist die Änderung wahrscheinlich noch nicht klar genug. Auf Beginner-Niveau ist das ein eingebauter Sanity-Check, den ich bei einem Big-Bang-Commit nicht hätte.
|
||||
Bonus für mich persönlich: Kleine Commits zwingen mich, jeden Schritt einzeln zu durchdenken und zu benennen. Wenn ich
|
||||
nicht in zwei Sätzen erklären kann, was ein Commit macht, ist die Änderung wahrscheinlich noch nicht klar genug. Auf
|
||||
Beginner-Niveau ist das ein eingebauter Sanity-Check, den ich bei einem Big-Bang-Commit nicht hätte.
|
||||
|
||||
### AI als Beschleuniger, ehrlich
|
||||
|
||||
Ja, AI hilft beim Tempo, und nicht zu knapp. Ohne CodeRabbit hätte ich Critical-Bugs der Klasse `Equals/GetHashCode`-Anti-Pattern, Hook-Subscription-Leaks und TOCTOU-Races nicht gefunden. Ich bin schlicht zu unerfahren für diese Klasse von Findings, das schreibe ich genau so hin.
|
||||
Ja, AI hilft beim Tempo, und nicht zu knapp. Ohne CodeRabbit hätte ich Critical-Bugs der Klasse
|
||||
`Equals/GetHashCode`-Anti-Pattern, Hook-Subscription-Leaks und TOCTOU-Races nicht gefunden. Ich bin schlicht zu
|
||||
unerfahren für diese Klasse von Findings, das schreibe ich genau so hin.
|
||||
|
||||
Was ich aber nicht mache: blind Code übernehmen, weil ein Tool ihn als Fix markiert hat. Bei mehreren CodeRabbit-Findings stand in den Original-Commits von Infi oder Anna sogar ein Stackoverflow-Link mit Begründung dabei, warum eine bestimmte Stelle so aussieht wie sie aussieht. Die habe ich gelesen, bevor ich was geändert habe. Erst verstehen, dann anfassen, dann committen. Das ist der Unterschied zwischen "AI gibt mir Code, ich pushe" und "AI zeigt mir wo's klemmt, ich entscheide".
|
||||
Was ich aber nicht mache: blind Code übernehmen, weil ein Tool ihn als Fix markiert hat. Bei mehreren
|
||||
CodeRabbit-Findings stand in den Original-Commits von Infi oder Anna sogar ein Stackoverflow-Link mit Begründung dabei,
|
||||
warum eine bestimmte Stelle so aussieht wie sie aussieht. Die habe ich gelesen, bevor ich was geändert habe. Erst
|
||||
verstehen, dann anfassen, dann committen. Das ist der Unterschied zwischen "AI gibt mir Code, ich pushe" und "AI zeigt
|
||||
mir wo's klemmt, ich entscheide".
|
||||
|
||||
Klassifikation und konkrete Beispiele zur AI-Nutzung stehen in [`AI_DISCLOSURE.md`](AI_DISCLOSURE.md). Hier in dieser Sektion ging es nur um den Tempo-Aspekt: Recherche plus saubere Codebase plus atomare Commits plus AI-gestütztes Review-Sparring sind die vier Faktoren zusammen. Kein einzelner davon erklärt das Tempo allein.
|
||||
Klassifikation und konkrete Beispiele zur AI-Nutzung stehen in [`AI_DISCLOSURE.md`](AI_DISCLOSURE.md). Hier in dieser
|
||||
Sektion ging es nur um den Tempo-Aspekt: Recherche plus saubere Codebase plus atomare Commits plus AI-gestütztes
|
||||
Review-Sparring sind die vier Faktoren zusammen. Kein einzelner davon erklärt das Tempo allein.
|
||||
|
||||
---
|
||||
|
||||
@@ -84,27 +135,49 @@ Klassifikation und konkrete Beispiele zur AI-Nutzung stehen in [`AI_DISCLOSURE.m
|
||||
|
||||
### Type-System? Weniger Schock als erwartet
|
||||
|
||||
C# nach TypeScript war angenehmer als gedacht. Properties statt getter/setter sind sauber, nullable reference types fühlen sich an wie `strict: true` in TypeScript. Ungewohnt war Wert-Typen vs. Referenz-Typen explizit denken zu müssen (`struct` vs. `class` mit echten Verhaltens-Konsequenzen), und Generics mit Constraints sind syntaktisch anders genug, dass ich beim Lesen kurz stocke. `async`/`await` ist semantisch ähnlich, aber Threading-Modelle sind in C# expliziter: `Task.Run`, `ConfigureAwait`, Synchronization-Contexts. Das hat mich mehrere Bugs gekostet, bevor ich verstanden hatte, wann der Main-Thread (in Plugin-Welt: der Framework-Tick) wirklich kritisch ist.
|
||||
C# nach TypeScript war angenehmer als gedacht. Properties statt getter/setter sind sauber, nullable reference types
|
||||
fühlen sich an wie `strict: true` in TypeScript. Ungewohnt war Wert-Typen vs. Referenz-Typen explizit denken zu müssen
|
||||
(`struct` vs. `class` mit echten Verhaltens-Konsequenzen), und Generics mit Constraints sind syntaktisch anders genug,
|
||||
dass ich beim Lesen kurz stocke. `async`/`await` ist semantisch ähnlich, aber Threading-Modelle sind in C# expliziter:
|
||||
`Task.Run`, `ConfigureAwait`, Synchronization-Contexts. Das hat mich mehrere Bugs gekostet, bevor ich verstanden hatte,
|
||||
wann der Main-Thread (in Plugin-Welt: der Framework-Tick) wirklich kritisch ist.
|
||||
|
||||
### Build-Toolchain: ähnlich, aber anders
|
||||
|
||||
`dotnet` CLI, csproj-XML, NuGet sind funktional nicht weit weg von npm und tsconfig. Aber das XML-Format der csproj ist eine andere Sprache als JSON-Configs. Die Lock-Datei (`packages.lock.json`) musste ich erst aktiv aktivieren (`RestorePackagesWithLockFile=true`); das ist nicht Default. Im Web-Stack ist Lock-File-First Standard, im .NET-Stack offenbar nicht. Das war eine echte Überraschung.
|
||||
`dotnet` CLI, csproj-XML, NuGet sind funktional nicht weit weg von npm und tsconfig. Aber das XML-Format der csproj ist
|
||||
eine andere Sprache als JSON-Configs. Die Lock-Datei (`packages.lock.json`) musste ich erst aktiv aktivieren
|
||||
(`RestorePackagesWithLockFile=true`); das ist nicht Default. Im Web-Stack ist Lock-File-First Standard, im .NET-Stack
|
||||
offenbar nicht. Das war eine echte Überraschung.
|
||||
|
||||
### ImGui ist eine andere Welt
|
||||
|
||||
Immediate-Mode-Rendering hat mit React-Component-Trees nichts gemein. Es gibt keine virtuelle DOM, keine Reconciliation, keinen "State der Komponente". Pro Frame zeichnet der Code die UI komplett neu, und der State lebt entweder in lokalen Variablen, die ich selbst verwalten muss, oder in der ImGui-eigenen ID-Stack-Logik.
|
||||
Immediate-Mode-Rendering hat mit React-Component-Trees nichts gemein. Es gibt keine virtuelle DOM, keine Reconciliation,
|
||||
keinen "State der Komponente". Pro Frame zeichnet der Code die UI komplett neu, und der State lebt entweder in lokalen
|
||||
Variablen, die ich selbst verwalten muss, oder in der ImGui-eigenen ID-Stack-Logik.
|
||||
|
||||
Was in React zwei Zeilen `useState` sind, ist in ImGui ein Member-Field plus manuelle ID-Stempel auf den Widgets, sonst kollidieren zwei Selectables in derselben Loop, weil sie auf die gleiche ID zurückfallen. Die ID-Stack-Kollision in `SearchSelector` (gefixt in v1.0.0) war genau dieses Symptom: Alle Selectables fielen auf dieselbe ambiguous ID zurück, bis ich den Row-Index in den Push-ID gemixt habe. Klassischer "warum klickt der falsche Eintrag"-Bug, den man nur findet, wenn man verstanden hat, wie ImGui IDs intern handhabt.
|
||||
Was in React zwei Zeilen `useState` sind, ist in ImGui ein Member-Field plus manuelle ID-Stempel auf den Widgets, sonst
|
||||
kollidieren zwei Selectables in derselben Loop, weil sie auf die gleiche ID zurückfallen. Die ID-Stack-Kollision in
|
||||
`SearchSelector` (gefixt in v1.0.0) war genau dieses Symptom: Alle Selectables fielen auf dieselbe ambiguous ID zurück,
|
||||
bis ich den Row-Index in den Push-ID gemixt habe. Klassischer "warum klickt der falsche Eintrag"-Bug, den man nur
|
||||
findet, wenn man verstanden hat, wie ImGui IDs intern handhabt.
|
||||
|
||||
### Dalamud-Spezifika
|
||||
|
||||
Plugin-Lifecycle, IPC-Subscriber-Pattern, Hook-System für Game-Functions, Game-Object-Threading. Viel davon war nur durch Lesen der Upstream-Codebase und durch [dalamud.dev](https://dalamud.dev) zu verstehen. Meine Trainings- und Such-Ergebnisse für "Dalamud" liefern oft veraltete API-Beispiele aus alten Versionen. dalamud.dev ist die zuverlässige Quelle. Wenn jemand neu anfängt: dort hin, nicht zu Stack Overflow.
|
||||
Plugin-Lifecycle, IPC-Subscriber-Pattern, Hook-System für Game-Functions, Game-Object-Threading. Viel davon war nur
|
||||
durch Lesen der Upstream-Codebase und durch [dalamud.dev](https://dalamud.dev) zu verstehen. Meine Trainings- und
|
||||
Such-Ergebnisse für "Dalamud" liefern oft veraltete API-Beispiele aus alten Versionen. dalamud.dev ist die zuverlässige
|
||||
Quelle. Wenn jemand neu anfängt: dort hin, nicht zu Stack Overflow.
|
||||
|
||||
### Der Tag, an dem mich der DalamudPackager einen Tag gekostet hat
|
||||
|
||||
Dalamud SDK 15 liefert seinen eigenen Default-Packager mit, der Icons und Image-URLs ins Manifest einträgt. Ich hatte aus dem Upstream-Repo eine eigene `DalamudPackager.targets`-Datei mit `HandleImages`-Override übernommen, und die hat den SDK-Default überschrieben. Resultat: Das Manifest hatte keinen `IconUrl` mehr, und das Plugin tauchte in der Plugin-Liste ohne Icon auf.
|
||||
Dalamud SDK 15 liefert seinen eigenen Default-Packager mit, der Icons und Image-URLs ins Manifest einträgt. Ich hatte
|
||||
aus dem Upstream-Repo eine eigene `DalamudPackager.targets`-Datei mit `HandleImages`-Override übernommen, und die hat
|
||||
den SDK-Default überschrieben. Resultat: Das Manifest hatte keinen `IconUrl` mehr, und das Plugin tauchte in der
|
||||
Plugin-Liste ohne Icon auf.
|
||||
|
||||
Symptom war einfach zu sehen, Ursache hat einen Tag gekostet. Ich hatte die Override-Datei für eine Pflicht-Datei gehalten, war sie aber nicht. Removal in v0.5.2, seitdem läuft der SDK-Default. Lektion: Erstmal mit Defaults arbeiten, Overrides erst wenn der Default nachweislich nicht passt.
|
||||
Symptom war einfach zu sehen, Ursache hat einen Tag gekostet. Ich hatte die Override-Datei für eine Pflicht-Datei
|
||||
gehalten, war sie aber nicht. Removal in v0.5.2, seitdem läuft der SDK-Default. Lektion: Erstmal mit Defaults arbeiten,
|
||||
Overrides erst wenn der Default nachweislich nicht passt.
|
||||
|
||||
---
|
||||
|
||||
@@ -112,45 +185,77 @@ Symptom war einfach zu sehen, Ursache hat einen Tag gekostet. Ich hatte die Over
|
||||
|
||||
### Refactor in einer fremden Codebase
|
||||
|
||||
Der Standalone-Cut in v1.0.0 hat die `ChatTwo.*`-Identität komplett auf `HellionChat.*` migriert. Klingt nach Find-and-Replace. War es nicht.
|
||||
Der Standalone-Cut in v1.0.0 hat die `ChatTwo.*`-Identität komplett auf `HellionChat.*` migriert. Klingt nach
|
||||
Find-and-Replace. War es nicht.
|
||||
|
||||
Konkret bedeutete das: Code-Namespace über alle 80 Source-Files plus 100 using-Direktiven plus zwei FQN-Aliases plus die Resource-Designer-Strings. Sechs IPC-Channels umbenannt (Breaking Change für Drittplugins, keine bekannten Anbindungen). Repo-Ordner-Struktur (`ChatTwo/` → `HellionChat/`) inklusive csproj, sln, allen GitHub-Workflows und der dependabot.yml. Public-Facing-Branding in README, repo.json, yaml auf Standalone-Framing umformuliert.
|
||||
Konkret bedeutete das: Code-Namespace über alle 80 Source-Files plus 100 using-Direktiven plus zwei FQN-Aliases plus die
|
||||
Resource-Designer-Strings. Sechs IPC-Channels umbenannt (Breaking Change für Drittplugins, keine bekannten Anbindungen).
|
||||
Repo-Ordner-Struktur (`ChatTwo/` → `HellionChat/`) inklusive csproj, sln, allen GitHub-Workflows und der dependabot.yml.
|
||||
Public-Facing-Branding in README, repo.json, yaml auf Standalone-Framing umformuliert.
|
||||
|
||||
Das war kein Solo-Find-and-Replace, weil Unicode-String-Pfade in Workflow-YAMLs anders quotiert werden müssen als C#-Strings. Weil Resource-Designer-Files generierte Inhalte haben, die nicht jede Toolchain im Blick hat. Und weil die `ChatTwo.*`-IPC-Channel-Namen Strings in `GetIpcSubscriber`-Calls sind: kein Symbol, kein Compile-Error, wenn man einen vergisst. Da merkst du, was alles still bleibt.
|
||||
Das war kein Solo-Find-and-Replace, weil Unicode-String-Pfade in Workflow-YAMLs anders quotiert werden müssen als
|
||||
C#-Strings. Weil Resource-Designer-Files generierte Inhalte haben, die nicht jede Toolchain im Blick hat. Und weil die
|
||||
`ChatTwo.*`-IPC-Channel-Namen Strings in `GetIpcSubscriber`-Calls sind: kein Symbol, kein Compile-Error, wenn man einen
|
||||
vergisst. Da merkst du, was alles still bleibt.
|
||||
|
||||
### Sicherheit ist kein abstraktes Thema mehr
|
||||
|
||||
Vor diesem Projekt war Supply-Chain-Sicherheit für mich akademisch. Drei konkrete Lektionen haben das geändert.
|
||||
|
||||
**SQLite-Native-Binary.** Ich musste auf 3.50.3 pinnen (`SQLitePCLRaw.lib.e_sqlite3` Override), weil `Microsoft.Data.Sqlite` die transitiv nachgezogene Lib in einer Version mitschleppte, die CVE-2025-6965 (Memory-Corruption durch Aggregate-Term-Overflow) und CVE-2025-7709 enthielt. Der Managed-Wrapper war neu, die Native-Lib war es nicht. Lektion: Transitive Dependencies prüfen sich nicht von selbst, du musst hinschauen.
|
||||
**SQLite-Native-Binary.** Ich musste auf 3.50.3 pinnen (`SQLitePCLRaw.lib.e_sqlite3` Override), weil
|
||||
`Microsoft.Data.Sqlite` die transitiv nachgezogene Lib in einer Version mitschleppte, die CVE-2025-6965
|
||||
(Memory-Corruption durch Aggregate-Term-Overflow) und CVE-2025-7709 enthielt. Der Managed-Wrapper war neu, die
|
||||
Native-Lib war es nicht. Lektion: Transitive Dependencies prüfen sich nicht von selbst, du musst hinschauen.
|
||||
|
||||
**Lock-File-Drift.** `packages.lock.json` honored bei `dotnet restore` (per `RestorePackagesWithLockFile=true` in der csproj) verhindert, dass transitive Versionen zwischen meiner Maschine und CI silent driften. Erst nach einem Build-Output-Mismatch zwischen lokal und GitHub-Actions hatte ich überhaupt verstanden, warum das nicht der Default ist.
|
||||
**Lock-File-Drift.** `packages.lock.json` honored bei `dotnet restore` (per `RestorePackagesWithLockFile=true` in der
|
||||
csproj) verhindert, dass transitive Versionen zwischen meiner Maschine und CI silent driften. Erst nach einem
|
||||
Build-Output-Mismatch zwischen lokal und GitHub-Actions hatte ich überhaupt verstanden, warum das nicht der Default ist.
|
||||
|
||||
**WrapText und der CodeQL-Alarm der drei Releases gekostet hat.** CodeQL hat in `ImGuiUtil.WrapText` einen Critical-Alert wegen "unvalidated local pointer arithmetic" geworfen. v0.5.2 hat einen Edge-Case validiert. Alert kam wieder. v0.5.3 hat den Buffer-Length via `GetByteCount` vor der Pointer-Math gecheckt. Alert kam wieder. v0.5.4 hat den ganzen Algorithmus auf `Span` und int-Offsets umgebaut, mit einem 16-KiB-Cap auf den ArrayPool-Rent. Erst da war Ruhe.
|
||||
**WrapText und der CodeQL-Alarm der drei Releases gekostet hat.** CodeQL hat in `ImGuiUtil.WrapText` einen
|
||||
Critical-Alert wegen "unvalidated local pointer arithmetic" geworfen. v0.5.2 hat einen Edge-Case validiert. Alert kam
|
||||
wieder. v0.5.3 hat den Buffer-Length via `GetByteCount` vor der Pointer-Math gecheckt. Alert kam wieder. v0.5.4 hat den
|
||||
ganzen Algorithmus auf `Span` und int-Offsets umgebaut, mit einem 16-KiB-Cap auf den ArrayPool-Rent. Erst da war Ruhe.
|
||||
|
||||
Lektion: Wenn ein statischer Analyzer drei Mal hintereinander meckert, ist nicht der Analyzer überempfindlich. Die Datenflusslogik ist es.
|
||||
Lektion: Wenn ein statischer Analyzer drei Mal hintereinander meckert, ist nicht der Analyzer überempfindlich. Die
|
||||
Datenflusslogik ist es.
|
||||
|
||||
### CodeRabbit als externer Code-Reviewer
|
||||
|
||||
Der v1.0.0-Sweep hat 3 Critical und 21 Major Findings hochgespült. Drei Klassen davon waren besonders lehrreich:
|
||||
|
||||
- **`Equals`-Methoden die `GetHashCode()` vergleichen.** Klassisches Hash-Kollisions-Anti-Pattern. Klingt nach "ist doch egal, wenn Hashes gleich sind, sind die Objekte auch gleich", ist aber genau falsch. Hashes können kollidieren, Objekte sind dann nicht gleich.
|
||||
- **`Dispose`-Methoden die nur einen Teil der Subscriptions wieder abmelden.** Leak bei jedem Plugin-Reload. Im Nutzer-Alltag merkst du das nicht sofort, im Long-Running-Test schon.
|
||||
- **TOCTOU-Races.** Zwischen Bounds-Check und Read kann ein anderer Thread das Array unter dir austauschen (`GlobalParametersCache`, `AutoTranslate`).
|
||||
- **`Equals`-Methoden die `GetHashCode()` vergleichen.** Klassisches Hash-Kollisions-Anti-Pattern. Klingt nach "ist doch
|
||||
egal, wenn Hashes gleich sind, sind die Objekte auch gleich", ist aber genau falsch. Hashes können kollidieren,
|
||||
Objekte sind dann nicht gleich.
|
||||
- **`Dispose`-Methoden die nur einen Teil der Subscriptions wieder abmelden.** Leak bei jedem Plugin-Reload. Im
|
||||
Nutzer-Alltag merkst du das nicht sofort, im Long-Running-Test schon.
|
||||
- **TOCTOU-Races.** Zwischen Bounds-Check und Read kann ein anderer Thread das Array unter dir austauschen
|
||||
(`GlobalParametersCache`, `AutoTranslate`).
|
||||
|
||||
Davon hatte ich vorher bestenfalls die Theorie gelesen, nicht selbst diagnostiziert. CodeRabbit war für mich der Moment, wo "akademisches Wissen" zu "okay, das ist mein Code, das ist mein Bug" wurde.
|
||||
Davon hatte ich vorher bestenfalls die Theorie gelesen, nicht selbst diagnostiziert. CodeRabbit war für mich der Moment,
|
||||
wo "akademisches Wissen" zu "okay, das ist mein Code, das ist mein Bug" wurde.
|
||||
|
||||
### Externe Tester sind ihr Gewicht in Gold wert
|
||||
|
||||
Carlas Feedback zur Pop-Out-Discoverability hat den Header-Button in v0.6.1 ausgelöst. Dass Pop-Outs nur per Rechtsklick erreichbar waren, hatte ich als Maintainer nicht mehr gesehen, ich kannte den Pfad blind. Carls Wunsch nach Theme-Varianten mit Helligkeits-Abstufungen hat mein Verständnis von "ein Theme = eine Farbe" auf "Theme-Familien mit Stimmungs-Varianten" verschoben. Jingliu hat TempTell-Persistence gefordert, was das Tab-System architektonisch in Frage stellt.
|
||||
Carlas Feedback zur Pop-Out-Discoverability hat den Header-Button in v0.6.1 ausgelöst. Dass Pop-Outs nur per Rechtsklick
|
||||
erreichbar waren, hatte ich als Maintainer nicht mehr gesehen, ich kannte den Pfad blind. Carls Wunsch nach
|
||||
Theme-Varianten mit Helligkeits-Abstufungen hat mein Verständnis von "ein Theme = eine Farbe" auf "Theme-Familien mit
|
||||
Stimmungs-Varianten" verschoben. Jingliu hat TempTell-Persistence gefordert, was das Tab-System architektonisch in Frage
|
||||
stellt.
|
||||
|
||||
Solo hätte ich diese drei Dinge nicht erkannt. Punkt.
|
||||
|
||||
### release.yml und die Markdown-Hölle
|
||||
|
||||
Der `release.yml`-Workflow ist beim ersten v0.6.0-Tag-Push einfach nicht losgegangen. Ich habe Stunden in Permissions, Secret-Scopes und Tag-Trigger-Konfiguration gegraben, bevor ich verstand, was eigentlich los war: Der PowerShell-Heredoc-Footer im "Generate release body"-Step enthielt eine `---`-Markdown-Horizontal-Rule an Spalte 1, und genau das hat das YAML-Block-Scalar von `run: |` beendet. GitHub konnte die Workflow-Datei nicht parsen, also hat der Push-Tag-Trigger nie registriert.
|
||||
Der `release.yml`-Workflow ist beim ersten v0.6.0-Tag-Push einfach nicht losgegangen. Ich habe Stunden in Permissions,
|
||||
Secret-Scopes und Tag-Trigger-Konfiguration gegraben, bevor ich verstand, was eigentlich los war: Der
|
||||
PowerShell-Heredoc-Footer im "Generate release body"-Step enthielt eine `---`-Markdown-Horizontal-Rule an Spalte 1, und
|
||||
genau das hat das YAML-Block-Scalar von `run: |` beendet. GitHub konnte die Workflow-Datei nicht parsen, also hat der
|
||||
Push-Tag-Trigger nie registriert.
|
||||
|
||||
Fix: Footer in eine externe `.github/release-footer.md` extrahiert, Workflow liest sie via `Get-Content` ein. Lektion: Wenn ein Workflow nicht triggert, verifiziere als Erstes, dass GitHub die Datei überhaupt parsen kann. Das war einer der Bugs, bei denen ich nach dem Fix kurz gelacht habe und mich dann gefragt, wie viele andere YAML-Dateien ich noch habe, die so eine Falle drin haben könnten.
|
||||
Fix: Footer in eine externe `.github/release-footer.md` extrahiert, Workflow liest sie via `Get-Content` ein. Lektion:
|
||||
Wenn ein Workflow nicht triggert, verifiziere als Erstes, dass GitHub die Datei überhaupt parsen kann. Das war einer der
|
||||
Bugs, bei denen ich nach dem Fix kurz gelacht habe und mich dann gefragt, wie viele andere YAML-Dateien ich noch habe,
|
||||
die so eine Falle drin haben könnten.
|
||||
|
||||
---
|
||||
|
||||
@@ -158,19 +263,29 @@ Fix: Footer in eine externe `.github/release-footer.md` extrahiert, Workflow lie
|
||||
|
||||
### Performance-Profiling im Game-Context
|
||||
|
||||
Der FPS-Drop-Bug aus Upstream Chat 2 ([#145](https://github.com/Infiziert90/ChatTwo/issues/145)) ist auch in Hellion Chat noch nicht reproduziert oder verifiziert. v1.0.0 hat mehrere Fixes auf den verdächtigen Pfaden (DbViewer O(N²) → O(N), AutoTranslate Lock-Serialisierung, EmoteCache HttpClient-Reuse), aber das systematische Vermessen unter Last fehlt mir. Ich muss noch lernen, wie man im Plugin-Kontext sauber misst, was wirklich das Frame-Budget frisst.
|
||||
Der FPS-Drop-Bug aus Upstream Chat 2 ([#145](https://github.com/Infiziert90/ChatTwo/issues/145)) ist auch in Hellion
|
||||
Chat noch nicht reproduziert oder verifiziert. v1.0.0 hat mehrere Fixes auf den verdächtigen Pfaden (DbViewer O(N²) →
|
||||
O(N), AutoTranslate Lock-Serialisierung, EmoteCache HttpClient-Reuse), aber das systematische Vermessen unter Last fehlt
|
||||
mir. Ich muss noch lernen, wie man im Plugin-Kontext sauber misst, was wirklich das Frame-Budget frisst.
|
||||
|
||||
### Native-Interop und Pointer-Math
|
||||
|
||||
Auch nach dem WrapText-Span-Refactor in v0.5.4 ist mir Pointer-Math unsicher. ImGui zwingt einen an mehreren Stellen in `unsafe`-Code, und der Sicherheitsabstand zur "unbounded ArrayPool allocation"-Klasse von Bugs ist schmaler als mir lieb ist. Da will ich besser werden, bevor ich tieferes ImGui-Custom-Drawing anfasse.
|
||||
Auch nach dem WrapText-Span-Refactor in v0.5.4 ist mir Pointer-Math unsicher. ImGui zwingt einen an mehreren Stellen in
|
||||
`unsafe`-Code, und der Sicherheitsabstand zur "unbounded ArrayPool allocation"-Klasse von Bugs ist schmaler als mir lieb
|
||||
ist. Da will ich besser werden, bevor ich tieferes ImGui-Custom-Drawing anfasse.
|
||||
|
||||
### Test-Disziplin für Plugin-Code
|
||||
|
||||
Aktuell hat das Repo kein Test-Projekt. Das ist eine bewusste Entscheidung, keine vergessene. Plugin-Code mit FFXIV-Hooks und Dalamud-Lifecycle sauber zu testen ist nicht trivial, und ich hatte keinen Ansatz gefunden, der ohne riesiges Mocking-Gerüst sinnvoll wirkte. Privacy-Filter und Configuration-Migration wären gute Testkandidaten, weil sie isoliert sind. Steht auf der Liste, ist aber kein Quick-Win.
|
||||
Aktuell hat das Repo kein Test-Projekt. Das ist eine bewusste Entscheidung, keine vergessene. Plugin-Code mit
|
||||
FFXIV-Hooks und Dalamud-Lifecycle sauber zu testen ist nicht trivial, und ich hatte keinen Ansatz gefunden, der ohne
|
||||
riesiges Mocking-Gerüst sinnvoll wirkte. Privacy-Filter und Configuration-Migration wären gute Testkandidaten, weil sie
|
||||
isoliert sind. Steht auf der Liste, ist aber kein Quick-Win.
|
||||
|
||||
### Linux-Eigenheiten unter Wine
|
||||
|
||||
XDG-Compliance, libnotify-Integration, WireGuard-Network-Detection, alles in der [Roadmap](ROADMAP.md), und alles technisch noch nicht ganz klar. Wine und sandboxed Plugin-Code teilen nicht alle System-APIs, und ich weiß nicht, wo die Stolperfallen liegen, bevor ich sie gefunden habe.
|
||||
XDG-Compliance, libnotify-Integration, WireGuard-Network-Detection, alles in der [Roadmap](ROADMAP.md), und alles
|
||||
technisch noch nicht ganz klar. Wine und sandboxed Plugin-Code teilen nicht alle System-APIs, und ich weiß nicht, wo die
|
||||
Stolperfallen liegen, bevor ich sie gefunden habe.
|
||||
|
||||
---
|
||||
|
||||
@@ -192,7 +307,9 @@ Ich verwende Claude Code als Hilfsmittel, nicht als Ersatz für eigene Arbeit.
|
||||
- Tester-Kommunikation und Roadmap-Priorisierung
|
||||
- Reviewen, Verifizieren, Pushen
|
||||
|
||||
Die Klassifikation und konkrete Beispiele stehen in [`AI_DISCLOSURE.md`](AI_DISCLOSURE.md). Mir ist wichtig, dass Nutzer und potenzielle Beiträger verstehen, wie der Code zustande gekommen ist, gerade bei einem Plugin, das mit Nutzerdaten arbeitet.
|
||||
Die Klassifikation und konkrete Beispiele stehen in [`AI_DISCLOSURE.md`](AI_DISCLOSURE.md). Mir ist wichtig, dass Nutzer
|
||||
und potenzielle Beiträger verstehen, wie der Code zustande gekommen ist, gerade bei einem Plugin, das mit Nutzerdaten
|
||||
arbeitet.
|
||||
|
||||
Ja, AI. Ja, alleine. Beides öfter erwähnt als nötig. Willkommen im Open-Source-Plugin-Klima.
|
||||
|
||||
|
||||
+95
-150
@@ -1,145 +1,108 @@
|
||||
# Hellion Chat — Roadmap
|
||||
|
||||
Geplante Arbeit nach dem v1.0.0 Standalone-Cut. Diese Liste ist absichtlich
|
||||
grob: konkrete Specs, Größenschätzungen und Repro-Steps liegen im
|
||||
internen Backlog. Tracking nach außen läuft über
|
||||
[Gitea Issues](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/issues)
|
||||
mit dem `roadmap`-Label, sobald ein Item für einen Cycle eingeplant ist.
|
||||
Geplante Arbeit nach dem v1.0.0 Standalone-Cut. Diese Liste ist absichtlich grob: konkrete Specs, Größenschätzungen und
|
||||
Repro-Steps liegen im internen Backlog. Tracking nach außen läuft über
|
||||
[Gitea Issues](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/issues) mit dem `roadmap`-Label, sobald
|
||||
ein Item für einen Cycle eingeplant ist.
|
||||
|
||||
Reihenfolge ist Priorität, nicht Garantie. Items können sich verschieben
|
||||
oder ganz wegfallen wenn sie sich beim Brainstorm als nicht passend zur
|
||||
Privacy-First-Schnittmenge des Plugins erweisen.
|
||||
Reihenfolge ist Priorität, nicht Garantie. Items können sich verschieben oder ganz wegfallen wenn sie sich beim
|
||||
Brainstorm als nicht passend zur Privacy-First-Schnittmenge des Plugins erweisen.
|
||||
|
||||
---
|
||||
|
||||
## Nächster Cycle (v1.4.4)
|
||||
|
||||
**Window-Lazy-Open + Render-Init-Cost-Optimisation** — die in v1.4.3
|
||||
gelegte IAsyncDalamudPlugin-Foundation jetzt für die echten User-
|
||||
spürbaren Wins nutzen. Window-Konstruktion erst beim ersten Open,
|
||||
Render-Path-Init-Kosten in den ersten Frames runter. Konkrete
|
||||
Kandidaten und Größenschätzungen werden im v1.4.4-Brainstorm
|
||||
konsolidiert.
|
||||
**Window-Lazy-Open + Render-Init-Cost-Optimisation** — die in v1.4.3 gelegte IAsyncDalamudPlugin-Foundation jetzt für
|
||||
die echten User- spürbaren Wins nutzen. Window-Konstruktion erst beim ersten Open, Render-Path-Init-Kosten in den ersten
|
||||
Frames runter. Konkrete Kandidaten und Größenschätzungen werden im v1.4.4-Brainstorm konsolidiert.
|
||||
|
||||
## v1.4.3 — Plugin-Load Async-Init + Repo-Cutover (released 2026-05-08)
|
||||
|
||||
Vierter und größter Sub-Patch der v1.4.x Polish-Sweep-Serie. Plugin
|
||||
auf Dalamud's IAsyncDalamudPlugin-API migriert: der Konstruktor
|
||||
übernimmt nur noch Bootstrap-Essentials (Config-Load, Language-Init,
|
||||
Conflict-Detection), Migrationen, Service-Allokationen, Window-
|
||||
Konstruktion und Hook-Subscription wandern in LoadAsync. Schema-
|
||||
Gate ersetzt die v9 → v16 Migrations-Kette; Configs auf Schema
|
||||
v16+ laden direkt, ältere Configs triggern eine "install v1.4.2
|
||||
first"-Fehlermeldung. AutoTranslate.PreloadCache vom Load-Pfad
|
||||
runter. FontManager.BuildFonts läuft sync am Start von LoadAsync,
|
||||
Dalamud baut den Font-Atlas auf seiner eigenen Pipeline.
|
||||
Custom-Repo-URL auf `gitea.hellion-forge.cloud` cut-over, das
|
||||
GitHub-Repo bleibt als eingefrorener v1.4.2-Snapshot stehen.
|
||||
Plugin-Load-Zeit liegt bei ~3.7 s Median (5 Reloads), vergleichbar
|
||||
mit v1.4.2: Async-Migration ist Foundation für v1.4.4 Lazy-Init-
|
||||
Optimierungen, kein direkter User-spürbarer Win.
|
||||
Vierter und größter Sub-Patch der v1.4.x Polish-Sweep-Serie. Plugin auf Dalamud's IAsyncDalamudPlugin-API migriert: der
|
||||
Konstruktor übernimmt nur noch Bootstrap-Essentials (Config-Load, Language-Init, Conflict-Detection), Migrationen,
|
||||
Service-Allokationen, Window- Konstruktion und Hook-Subscription wandern in LoadAsync. Schema- Gate ersetzt die v9 → v16
|
||||
Migrations-Kette; Configs auf Schema v16+ laden direkt, ältere Configs triggern eine "install v1.4.2
|
||||
first"-Fehlermeldung. AutoTranslate.PreloadCache vom Load-Pfad runter. FontManager.BuildFonts läuft sync am Start von
|
||||
LoadAsync, Dalamud baut den Font-Atlas auf seiner eigenen Pipeline. Custom-Repo-URL auf `gitea.hellion-forge.cloud`
|
||||
cut-over, das GitHub-Repo bleibt als eingefrorener v1.4.2-Snapshot stehen. Plugin-Load-Zeit liegt bei ~3.7 s Median (5
|
||||
Reloads), vergleichbar mit v1.4.2: Async-Migration ist Foundation für v1.4.4 Lazy-Init- Optimierungen, kein direkter
|
||||
User-spürbarer Win.
|
||||
|
||||
## v1.4.2 — ChatLog Frame-Hot-Path (released <Datum>)
|
||||
|
||||
Dritter Sub-Patch der v1.4.x Polish-Sweep-Serie. Per-Frame-
|
||||
Allokationen aus dem ChatLogWindow-Render-Pfad und der
|
||||
Settings-StatusBar eliminiert. Card-Mode-Border-Loop in
|
||||
DrawMessages hebt fünf Invarianten in einen Pre-Loop-Hoist,
|
||||
AutoTellTabTint bekommt einen Per-Tab-Cache via TabTintCache
|
||||
(separate Validation-Keys pro Cache, kein Cross-Invalidation),
|
||||
StatusBar zieht den Cache-Gate-Check vor die Aggregations
|
||||
und ersetzt LINQ Sum+Count durch eine Single-Pass-Foreach.
|
||||
Dritter Sub-Patch der v1.4.x Polish-Sweep-Serie. Per-Frame- Allokationen aus dem ChatLogWindow-Render-Pfad und der
|
||||
Settings-StatusBar eliminiert. Card-Mode-Border-Loop in DrawMessages hebt fünf Invarianten in einen Pre-Loop-Hoist,
|
||||
AutoTellTabTint bekommt einen Per-Tab-Cache via TabTintCache (separate Validation-Keys pro Cache, kein
|
||||
Cross-Invalidation), StatusBar zieht den Cache-Gate-Check vor die Aggregations und ersetzt LINQ Sum+Count durch eine
|
||||
Single-Pass-Foreach.
|
||||
|
||||
## v1.4.1 — Theme Engine Performance (released <Datum>)
|
||||
|
||||
Zweiter Sub-Patch der v1.4.x Polish-Sweep-Serie. ABGR-Cache
|
||||
auf den Theme-Records pre-computed, HellionStyle.PushGlobal
|
||||
liest aus dem Cache statt pro Slot pro Frame zu konvertieren.
|
||||
**~13 % Render-Time-Recovery** im Smoke-Test (Plan-Erwartung
|
||||
2-6 % war konservativ, real ~10-15 %). Custom-Theme-Hot-Reload
|
||||
überlebt transient File-Locks via Last-Known-Good-Snapshot.
|
||||
Plus: Synthwave Sunset als zehnter Built-In, Author-Credits
|
||||
auf Hellion Forge konsolidiert, Mint Grove + Forge Merchantman
|
||||
auf Carla Beleandis als Community-Thanks.
|
||||
Zweiter Sub-Patch der v1.4.x Polish-Sweep-Serie. ABGR-Cache auf den Theme-Records pre-computed, HellionStyle.PushGlobal
|
||||
liest aus dem Cache statt pro Slot pro Frame zu konvertieren. **~13 % Render-Time-Recovery** im Smoke-Test
|
||||
(Plan-Erwartung 2-6 % war konservativ, real ~10-15 %). Custom-Theme-Hot-Reload überlebt transient File-Locks via
|
||||
Last-Known-Good-Snapshot. Plus: Synthwave Sunset als zehnter Built-In, Author-Credits auf Hellion Forge konsolidiert,
|
||||
Mint Grove + Forge Merchantman auf Carla Beleandis als Community-Thanks.
|
||||
|
||||
## v1.4.0 — Critical Lifecycle Fixes (released 2026-05-07)
|
||||
|
||||
Erster Sub-Patch der v1.4.x Polish-Sweep-Serie. Sieben P0-
|
||||
Findings aus Audit-Pass-3 und Pass-4 abgearbeitet:
|
||||
async-void-Loads, fehlende IsBackground-Flags, GC.Collect
|
||||
in Dispose, DeferredSave-Race und Pre-v13-Backup-Lookup für
|
||||
WindowOpacity. Keine Schema-Bumps, keine Funktions-
|
||||
Änderungen für den User außer dass Reload und Shutdown
|
||||
spürbar sauberer laufen.
|
||||
Erster Sub-Patch der v1.4.x Polish-Sweep-Serie. Sieben P0- Findings aus Audit-Pass-3 und Pass-4 abgearbeitet:
|
||||
async-void-Loads, fehlende IsBackground-Flags, GC.Collect in Dispose, DeferredSave-Race und Pre-v13-Backup-Lookup für
|
||||
WindowOpacity. Keine Schema-Bumps, keine Funktions- Änderungen für den User außer dass Reload und Shutdown spürbar
|
||||
sauberer laufen.
|
||||
|
||||
## v1.3.0 - Plugin Integrations: Honorific (released 2026-05-07)
|
||||
|
||||
Erster Cycle der Plugin-Integrations-Roadmap. Honorific-Custom-
|
||||
Titles werden im Chat-Header angezeigt, mit Auto-Detect und
|
||||
silent Fallback. Neuer Integrations-Settings-Tab. Pattern-
|
||||
Etablierer für die fünf folgenden Cycles (Context-Menu,
|
||||
Erster Cycle der Plugin-Integrations-Roadmap. Honorific-Custom- Titles werden im Chat-Header angezeigt, mit Auto-Detect
|
||||
und silent Fallback. Neuer Integrations-Settings-Tab. Pattern- Etablierer für die fünf folgenden Cycles (Context-Menu,
|
||||
NotificationMaster, RP-Status-Block, ExtraChat, XIVIM).
|
||||
|
||||
Spec: [Plugin-Integrationen-Übersicht](../Hellion%20Chat%20Plugin-Integrationen.md)
|
||||
|
||||
## v1.2.3 — Theme Expansion (released 2026-05-06)
|
||||
|
||||
Vier neue Built-In-Themes: Night Blue, Indigo Violet, Forge
|
||||
Merchantman, Hellion Spectrum (Deuteran/Protan-safe).
|
||||
Keine Engine-Änderungen. Siehe `docs/CHANGELOG.md`.
|
||||
Vier neue Built-In-Themes: Night Blue, Indigo Violet, Forge Merchantman, Hellion Spectrum (Deuteran/Protan-safe). Keine
|
||||
Engine-Änderungen. Siehe `docs/CHANGELOG.md`.
|
||||
|
||||
(v1.2.2 wurde verbrannt weil das `repo.json`-Manifest beim
|
||||
ersten Push nicht synchron mitgebumpt wurde — Re-Release als
|
||||
(v1.2.2 wurde verbrannt weil das `repo.json`-Manifest beim ersten Push nicht synchron mitgebumpt wurde — Re-Release als
|
||||
v1.2.3 mit kompletter Manifest-Synchronisation.)
|
||||
|
||||
## v1.2.1 — Settings Cleanup (released 2026-05-06)
|
||||
|
||||
Re-sortierte Settings (9 Cards thematisch), 4 tote Settings entfernt,
|
||||
Auto-Migration v15 → v16 ohne Daten-Verlust.
|
||||
Re-sortierte Settings (9 Cards thematisch), 4 tote Settings entfernt, Auto-Migration v15 → v16 ohne Daten-Verlust.
|
||||
|
||||
## v1.2.0 — Layout Refresh (released 2026-05-05)
|
||||
|
||||
Top-Tabs-Refresh, Sidebar-Tab-Icons, Bottom-Status-Bar, Card-Rows als
|
||||
Default-Message-Render, Auto-Tell-Tab-Hashing.
|
||||
Top-Tabs-Refresh, Sidebar-Tab-Icons, Bottom-Status-Bar, Card-Rows als Default-Message-Render, Auto-Tell-Tab-Hashing.
|
||||
|
||||
## v1.1.0 — Theme Foundation (released 2026-05-05)
|
||||
|
||||
Theme-Engine mit fünf Built-In-Themes, Settings-Card-Grid, Custom-
|
||||
Themes via JSON, Theme-Authoring-Doku. Plugin-Icon auf Hellion Forge.
|
||||
Siehe `docs/CHANGELOG.md` für Details.
|
||||
Theme-Engine mit fünf Built-In-Themes, Settings-Card-Grid, Custom- Themes via JSON, Theme-Authoring-Doku. Plugin-Icon
|
||||
auf Hellion Forge. Siehe `docs/CHANGELOG.md` für Details.
|
||||
|
||||
Aus dem ursprünglichen v1.1.0-Plan (Ad-Block / Spam-Filter, Receive-
|
||||
Suppressed-Tells-Toggle) wurden zugunsten der Theme-Engine zurück
|
||||
gestellt — beide Items leben weiter im Mittelfrist-Block.
|
||||
Aus dem ursprünglichen v1.1.0-Plan (Ad-Block / Spam-Filter, Receive- Suppressed-Tells-Toggle) wurden zugunsten der
|
||||
Theme-Engine zurück gestellt — beide Items leben weiter im Mittelfrist-Block.
|
||||
|
||||
## Mittelfristig (v1.4.x+)
|
||||
|
||||
- **Plugin-Integrations-Roadmap (Cycles 2-6)** - sechs Plugin-
|
||||
Integrationen geplant, Honorific (Cycle 1) ist live, danach folgen
|
||||
Context-Menu, NotificationMaster, RP-Status-Block, ExtraChat und
|
||||
XIVIM in eigenen Cycles. Spec und Cycle-Reihenfolge in
|
||||
[Plugin-Integrationen-Übersicht](../Hellion%20Chat%20Plugin-Integrationen.md).
|
||||
- **Ad-Block / Spam-Filter** — Hybrid-Konzept aus eigenem Light-Filter und
|
||||
optionaler `NoSoliciting`-IPC-Integration. Adressiert Werbe-Spam in
|
||||
öffentlichen Channels und Tells. Aus dem v1.1.0-Plan zurückgestellt.
|
||||
- **Receive-Suppressed-Tells-Toggle** — Auto-Tell-Tabs greift auch wenn ein
|
||||
Drittplugin (z.B. XIVMessenger) die /tell-Anzeige global suppressed.
|
||||
Gleicher Hook-Layer wie Ad-Block, deshalb gebündelt.
|
||||
- **Database-Viewer Inline-Search** — Volltext-Suche im DB-Viewer via
|
||||
SQLite FTS5. Aktuell gibt es nur Datums- und Channel-Filter.
|
||||
- **TempTell Persistence** — Pin-Toggle auf TempTell-Tabs damit ausgewählte
|
||||
Tells einen Relog überleben. Tester-Wunsch von Jingliu.
|
||||
- **FontManager Async-Refactor** — `LoadGameSymFontAsync` aus dem
|
||||
blockierenden Plugin-Constructor herausziehen. Cold-Start-Hitching beim
|
||||
ersten Plugin-Start beheben (Severity niedrig, Plugin ist funktional).
|
||||
- **Separate Opacity Active vs. Inactive** — zweiter Slider für inaktive
|
||||
Fenster-Deckkraft. Upstream lehnt das ab; wir können hier anders
|
||||
entscheiden.
|
||||
- **Failed-Tell-Notification** — sichtbare Nachricht bei /tell-Fail
|
||||
(offline, restricted instance, blacklisted, world-mismatch) statt
|
||||
stillem Failure.
|
||||
- **Per-Tab Sound-Notification** — Sound-Toggle und optional eigene .wav
|
||||
pro Tab, mit Mute-In-Combat-Option.
|
||||
- **Plugin-Integrations-Roadmap (Cycles 2-6)** - sechs Plugin- Integrationen geplant, Honorific (Cycle 1) ist live,
|
||||
danach folgen Context-Menu, NotificationMaster, RP-Status-Block, ExtraChat und XIVIM in eigenen Cycles. Spec und
|
||||
Cycle-Reihenfolge in [Plugin-Integrationen-Übersicht](../Hellion%20Chat%20Plugin-Integrationen.md).
|
||||
- **Ad-Block / Spam-Filter** — Hybrid-Konzept aus eigenem Light-Filter und optionaler `NoSoliciting`-IPC-Integration.
|
||||
Adressiert Werbe-Spam in öffentlichen Channels und Tells. Aus dem v1.1.0-Plan zurückgestellt.
|
||||
- **Receive-Suppressed-Tells-Toggle** — Auto-Tell-Tabs greift auch wenn ein Drittplugin (z.B. XIVMessenger) die
|
||||
/tell-Anzeige global suppressed. Gleicher Hook-Layer wie Ad-Block, deshalb gebündelt.
|
||||
- **Database-Viewer Inline-Search** — Volltext-Suche im DB-Viewer via SQLite FTS5. Aktuell gibt es nur Datums- und
|
||||
Channel-Filter.
|
||||
- **TempTell Persistence** — Pin-Toggle auf TempTell-Tabs damit ausgewählte Tells einen Relog überleben. Tester-Wunsch
|
||||
von Jingliu.
|
||||
- **FontManager Async-Refactor** — `LoadGameSymFontAsync` aus dem blockierenden Plugin-Constructor herausziehen.
|
||||
Cold-Start-Hitching beim ersten Plugin-Start beheben (Severity niedrig, Plugin ist funktional).
|
||||
- **Separate Opacity Active vs. Inactive** — zweiter Slider für inaktive Fenster-Deckkraft. Upstream lehnt das ab; wir
|
||||
können hier anders entscheiden.
|
||||
- **Failed-Tell-Notification** — sichtbare Nachricht bei /tell-Fail (offline, restricted instance, blacklisted,
|
||||
world-mismatch) statt stillem Failure.
|
||||
- **Per-Tab Sound-Notification** — Sound-Toggle und optional eigene .wav pro Tab, mit Mute-In-Combat-Option.
|
||||
|
||||
## Langfrist (v1.x+)
|
||||
|
||||
@@ -157,38 +120,30 @@ gestellt — beide Items leben weiter im Mittelfrist-Block.
|
||||
|
||||
### UX und Tab-Management
|
||||
|
||||
- **Regex Tab Routing** — Plugin-Output-Spam in eigene Tabs, Tells
|
||||
bestimmter Personen automatisch sortieren. Klar abgegrenzt zum Ad-Block:
|
||||
Routing sortiert in Views, Block versteckt global.
|
||||
- **Regex Tab Routing** — Plugin-Output-Spam in eigene Tabs, Tells bestimmter Personen automatisch sortieren. Klar
|
||||
abgegrenzt zum Ad-Block: Routing sortiert in Views, Block versteckt global.
|
||||
- **Auto-Detect Duties** — Tab-Switch beim Duty-Start via Condition-Flag.
|
||||
- **UX Bundle** — Vertical-Tab-Bar als Layout-Option, Shift+Mousewheel zum
|
||||
Tab-Header-Scrollen ohne Aktivierung, globaler Hotkey zum Schließen des
|
||||
aktiven Tabs.
|
||||
- **Configure Tab Title** — konfigurierbares Tab-Title-Format
|
||||
(Name / Name + abgekürzter World / voller Name / Custom), pro Tab
|
||||
überschreibbar.
|
||||
- **Name Display Options** — analog zu FFXIV-Vanilla (voller Name, Vorname
|
||||
abgekürzt, Initialen), per-Channel-Override möglich.
|
||||
- **Item & Flag Linking** — Outgoing: Shift-Klick auf Item/Flag sendet ins
|
||||
fokussierte Plugin-Input. Incoming: Item-Links und Map-Coords klickbar.
|
||||
- **Color Currently Selected Input Channel** — Channel-Selector-Button im
|
||||
Input-Bar mit Channel-Farbe einfärben.
|
||||
- **Plugin-Disclosure Pre-Send Filter** — konfigurierbare Wort-/Regex-Liste
|
||||
blockiert das Senden mit Pre-Send-Confirm. Schutz vor versehentlicher
|
||||
Plugin-Nennung in öffentlichen Channels.
|
||||
- **Chat Clear on Name Change** — bei Charakter-Namensänderung lokalen
|
||||
Verlauf migrieren oder löschen, Default Wipe für maximale Privacy.
|
||||
- **Hide Plugin Window on NG+ Screen** — Hide-Logik um zusätzliche
|
||||
Addon-Namen erweitern.
|
||||
- **Kick from Novice Network** — Mentor-Nische, Context-Menü-Eintrag mit
|
||||
Confirmation.
|
||||
- **Text-to-Speech für /tell** — eingehende Tells via TTS, optional pro
|
||||
Sender, mit Channel-Filter und Mute-In-Combat. Geringe Priorität.
|
||||
- **UX Bundle** — Vertical-Tab-Bar als Layout-Option, Shift+Mousewheel zum Tab-Header-Scrollen ohne Aktivierung,
|
||||
globaler Hotkey zum Schließen des aktiven Tabs.
|
||||
- **Configure Tab Title** — konfigurierbares Tab-Title-Format (Name / Name + abgekürzter World / voller Name / Custom),
|
||||
pro Tab überschreibbar.
|
||||
- **Name Display Options** — analog zu FFXIV-Vanilla (voller Name, Vorname abgekürzt, Initialen), per-Channel-Override
|
||||
möglich.
|
||||
- **Item & Flag Linking** — Outgoing: Shift-Klick auf Item/Flag sendet ins fokussierte Plugin-Input. Incoming:
|
||||
Item-Links und Map-Coords klickbar.
|
||||
- **Color Currently Selected Input Channel** — Channel-Selector-Button im Input-Bar mit Channel-Farbe einfärben.
|
||||
- **Plugin-Disclosure Pre-Send Filter** — konfigurierbare Wort-/Regex-Liste blockiert das Senden mit Pre-Send-Confirm.
|
||||
Schutz vor versehentlicher Plugin-Nennung in öffentlichen Channels.
|
||||
- **Chat Clear on Name Change** — bei Charakter-Namensänderung lokalen Verlauf migrieren oder löschen, Default Wipe für
|
||||
maximale Privacy.
|
||||
- **Hide Plugin Window on NG+ Screen** — Hide-Logik um zusätzliche Addon-Namen erweitern.
|
||||
- **Kick from Novice Network** — Mentor-Nische, Context-Menü-Eintrag mit Confirmation.
|
||||
- **Text-to-Speech für /tell** — eingehende Tells via TTS, optional pro Sender, mit Channel-Filter und Mute-In-Combat.
|
||||
Geringe Priorität.
|
||||
|
||||
### Distribution und Branding
|
||||
|
||||
- Hand-gezeichnetes Hellion-Logo (aktuell Platzhalter aus dem
|
||||
Hellion-Online-Media-Brand-Repo)
|
||||
- Hand-gezeichnetes Hellion-Logo (aktuell Platzhalter aus dem Hellion-Online-Media-Brand-Repo)
|
||||
- GitHub Action für automatischen `repo.json`-Sync nach Tag-Push
|
||||
- Submission ans Dalamud-Main-Plugin-Repo (zusätzlich zum Custom-Repo)
|
||||
|
||||
@@ -196,34 +151,24 @@ gestellt — beide Items leben weiter im Mittelfrist-Block.
|
||||
|
||||
## Bug-Verifizierungen
|
||||
|
||||
Aus dem Upstream-Issue-Tracker übernommen, in Hellion Chat 1.0.0 noch
|
||||
nicht reproduziert oder verifiziert. Werden bei Gelegenheit gegen den
|
||||
aktuellen Stand getestet.
|
||||
Aus dem Upstream-Issue-Tracker übernommen, in Hellion Chat 1.0.0 noch nicht reproduziert oder verifiziert. Werden bei
|
||||
Gelegenheit gegen den aktuellen Stand getestet.
|
||||
|
||||
- **Right-Click Whisper Error** in Field Ops / Special Instances (Eureka,
|
||||
Bozja, Occult Crescent, DRS) — Upstream
|
||||
[#168](https://github.com/Infiziert90/ChatTwo/issues/168). Reply-Helper
|
||||
scheint `@World`-Suffix zu schlucken.
|
||||
- **FPS Drops with Plugin active** — Upstream
|
||||
[#145](https://github.com/Infiziert90/ChatTwo/issues/145). 10–20 % Drop
|
||||
seit upstream v1.29.19.0. v1.0.0 hat mehrere Fixes auf den verdächtigen
|
||||
Pfaden, Repro-Test gegen aktuellen Stand offen.
|
||||
- **Add Blacklist from Plugin Window** — Upstream
|
||||
[#140](https://github.com/Infiziert90/ChatTwo/issues/140). Right-Click
|
||||
Add-to-Blacklist wirft "Cannot locate character with that name", via
|
||||
Vanilla-Chat funktioniert es.
|
||||
- **DB-Viewer Column Sort** — sortiert State-Column lexikografisch statt
|
||||
numerisch (10 vor 2). XIVIM
|
||||
[#82](https://github.com/NightmareXIV/XIVInstantMessenger/issues/82),
|
||||
Repro in Hellion Chat offen.
|
||||
- **Right-Click Whisper Error** in Field Ops / Special Instances (Eureka, Bozja, Occult Crescent, DRS) — Upstream
|
||||
[#168](https://github.com/Infiziert90/ChatTwo/issues/168). Reply-Helper scheint `@World`-Suffix zu schlucken.
|
||||
- **FPS Drops with Plugin active** — Upstream [#145](https://github.com/Infiziert90/ChatTwo/issues/145). 10–20 % Drop
|
||||
seit upstream v1.29.19.0. v1.0.0 hat mehrere Fixes auf den verdächtigen Pfaden, Repro-Test gegen aktuellen Stand
|
||||
offen.
|
||||
- **Add Blacklist from Plugin Window** — Upstream [#140](https://github.com/Infiziert90/ChatTwo/issues/140). Right-Click
|
||||
Add-to-Blacklist wirft "Cannot locate character with that name", via Vanilla-Chat funktioniert es.
|
||||
- **DB-Viewer Column Sort** — sortiert State-Column lexikografisch statt numerisch (10 vor 2). XIVIM
|
||||
[#82](https://github.com/NightmareXIV/XIVInstantMessenger/issues/82), Repro in Hellion Chat offen.
|
||||
|
||||
---
|
||||
|
||||
## Lizenz-Boundary
|
||||
|
||||
Hellion Chat ist EUPL-1.2-lizenziert. Konzept-Imports aus AGPL-3.0-Plugins
|
||||
(z.B. XIV Instant Messenger) sind ausschließlich architektonische
|
||||
Inspiration, kein Code-Port. Code-Imports aus dem Upstream-Bestand
|
||||
sind seit v1.4.x abgeschlossen, weil Chat 2 in einem grundlegenden
|
||||
Rework ist und selektive Patches nicht mehr sauber portierbar sind.
|
||||
Hellion Chat ist EUPL-1.2-lizenziert. Konzept-Imports aus AGPL-3.0-Plugins (z.B. XIV Instant Messenger) sind
|
||||
ausschließlich architektonische Inspiration, kein Code-Port. Code-Imports aus dem Upstream-Bestand sind seit v1.4.x
|
||||
abgeschlossen, weil Chat 2 in einem grundlegenden Rework ist und selektive Patches nicht mehr sauber portierbar sind.
|
||||
Stand und Begründung in [`UPSTREAM_SYNC.md`](UPSTREAM_SYNC.md).
|
||||
|
||||
+81
-66
@@ -4,7 +4,8 @@
|
||||
|
||||
# Theme Authoring Guide
|
||||
|
||||
> Built by **Hellion Forge** — the plugin workshop arm of [Hellion Online Media](https://hellion-media.de). HellionChat ships with nine built-in themes; this guide walks you through writing your own.
|
||||
> Built by **Hellion Forge** — the plugin workshop arm of [Hellion Online Media](https://hellion-media.de). HellionChat
|
||||
> ships with nine built-in themes; this guide walks you through writing your own.
|
||||
|
||||
## TL;DR
|
||||
|
||||
@@ -18,13 +19,14 @@ That's the whole loop. The rest of this document is reference.
|
||||
|
||||
## File location
|
||||
|
||||
```
|
||||
```txt
|
||||
%APPDATA%\XIVLauncher\pluginConfigs\HellionChat\themes\
|
||||
```
|
||||
|
||||
(or the equivalent path on Linux/macOS — Settings → Themes → "Open themes folder" opens it directly).
|
||||
|
||||
Each `*.json` file in this folder is loaded as one theme. The `example-theme.json` that HellionChat seeds on first launch is your starting template.
|
||||
Each `*.json` file in this folder is loaded as one theme. The `example-theme.json` that HellionChat seeds on first
|
||||
launch is your starting template.
|
||||
|
||||
## File format
|
||||
|
||||
@@ -45,63 +47,64 @@ Theme JSON has four blocks:
|
||||
|
||||
### Top-level fields
|
||||
|
||||
| Field | Type | Required | Notes |
|
||||
|---|---|---|---|
|
||||
| `schemaVersion` | int | yes | Always `1` for HellionChat 1.1.0. The plugin warns and skips themes with a different number. |
|
||||
| `slug` | string | yes | Lowercase, hyphenated. Must be unique across all themes (built-in slugs are reserved). |
|
||||
| `name` | string | yes | Display name in the picker. |
|
||||
| `author` | string | yes | Shown small under the theme name. |
|
||||
| `description` | string | yes | One short sentence. |
|
||||
| `colors` | object | yes | All 21 slots required (see below). |
|
||||
| `layout` | object | yes | All 9 slots required (see below). |
|
||||
| `chatChannels` | object | no | Optional channel-name → hex map (see below). |
|
||||
| Field | Type | Required | Notes |
|
||||
| --------------- | ------ | -------- | -------------------------------------------------------------------------------------------- |
|
||||
| `schemaVersion` | int | yes | Always `1` for HellionChat 1.1.0. The plugin warns and skips themes with a different number. |
|
||||
| `slug` | string | yes | Lowercase, hyphenated. Must be unique across all themes (built-in slugs are reserved). |
|
||||
| `name` | string | yes | Display name in the picker. |
|
||||
| `author` | string | yes | Shown small under the theme name. |
|
||||
| `description` | string | yes | One short sentence. |
|
||||
| `colors` | object | yes | All 21 slots required (see below). |
|
||||
| `layout` | object | yes | All 9 slots required (see below). |
|
||||
| `chatChannels` | object | no | Optional channel-name → hex map (see below). |
|
||||
|
||||
### Color slots
|
||||
|
||||
All values are 6-digit `#RRGGBB` or 8-digit `#RRGGBBAA` hex strings. Six-digit values get an implicit `FF` alpha.
|
||||
|
||||
| Slot | Role |
|
||||
|---|---|
|
||||
| `primary` | Brand color — used on buttons, sliders, check marks, highlighted separators. |
|
||||
| `primaryDark` | Pressed-button stage. |
|
||||
| `primaryLight` | Hovered-button / link-text stage. |
|
||||
| `primaryGlow` | Glow / subtle accent (typically primary with ~60% alpha). |
|
||||
| `accent` | Counter-accent — scrollbar grab on hover/active, resize grip, optional CTA. |
|
||||
| `accentDark` / `accentLight` | Dark/light siblings of accent. |
|
||||
| `identity` | Title-bar active color and active-tab color. Often equals `primaryDark`. |
|
||||
| `windowBg` | Outermost window background. |
|
||||
| `childBg` | Inner panel / popup background. |
|
||||
| `frameBg` | Input fields, sliders, combos. |
|
||||
| `surface` | Card surfaces, headers, selectables. |
|
||||
| `surfaceHover` | Hovered card / header step. |
|
||||
| `border` | Panel borders. Typically primary with ~40% alpha for a brand-tinted edge. |
|
||||
| `textPrimary` | Body text. Soft off-white reads better than pure `#FFFFFF` on dark backgrounds. |
|
||||
| `textMuted` | Captions, secondary lines. |
|
||||
| `textDim` | Disabled / hint text, separators. |
|
||||
| `statusSuccess` | Green-ish for success notifications. |
|
||||
| `statusDanger` | Red for errors. |
|
||||
| `statusWarning` | Amber for warnings. |
|
||||
| `statusInfo` | Cyan-ish info. Often equals primary. |
|
||||
| Slot | Role |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------- |
|
||||
| `primary` | Brand color — used on buttons, sliders, check marks, highlighted separators. |
|
||||
| `primaryDark` | Pressed-button stage. |
|
||||
| `primaryLight` | Hovered-button / link-text stage. |
|
||||
| `primaryGlow` | Glow / subtle accent (typically primary with ~60% alpha). |
|
||||
| `accent` | Counter-accent — scrollbar grab on hover/active, resize grip, optional CTA. |
|
||||
| `accentDark` / `accentLight` | Dark/light siblings of accent. |
|
||||
| `identity` | Title-bar active color and active-tab color. Often equals `primaryDark`. |
|
||||
| `windowBg` | Outermost window background. |
|
||||
| `childBg` | Inner panel / popup background. |
|
||||
| `frameBg` | Input fields, sliders, combos. |
|
||||
| `surface` | Card surfaces, headers, selectables. |
|
||||
| `surfaceHover` | Hovered card / header step. |
|
||||
| `border` | Panel borders. Typically primary with ~40% alpha for a brand-tinted edge. |
|
||||
| `textPrimary` | Body text. Soft off-white reads better than pure `#FFFFFF` on dark backgrounds. |
|
||||
| `textMuted` | Captions, secondary lines. |
|
||||
| `textDim` | Disabled / hint text, separators. |
|
||||
| `statusSuccess` | Green-ish for success notifications. |
|
||||
| `statusDanger` | Red for errors. |
|
||||
| `statusWarning` | Amber for warnings. |
|
||||
| `statusInfo` | Cyan-ish info. Often equals primary. |
|
||||
|
||||
### Layout slots
|
||||
|
||||
All values are floats in pixels. `BorderSize` is 0 or 1 (no thicker borders look right with ImGui's edge anti-aliasing).
|
||||
|
||||
| Slot | Typical range | Notes |
|
||||
|---|---|---|
|
||||
| `windowRounding` | 0–8 | 0 = sharp upstream look; 4–6 = softer "app" feel. |
|
||||
| `childRounding` | 0–6 | Usually 1 less than `windowRounding`. |
|
||||
| `popupRounding` | 0–6 | Same as `childRounding`. |
|
||||
| `frameRounding` | 0–4 | For inputs, sliders. |
|
||||
| `grabRounding` | 0–4 | Slider grab dot. |
|
||||
| `tabRounding` | 0–4 | Tab corners. |
|
||||
| `scrollbarRounding` | 0–4 | Scrollbar grab. |
|
||||
| `windowBorderSize` | 0 or 1 | 1 reads better in dark themes. |
|
||||
| `frameBorderSize` | 0 or 1 | Usually matches windowBorderSize. |
|
||||
| Slot | Typical range | Notes |
|
||||
| ------------------- | ------------- | ------------------------------------------------- |
|
||||
| `windowRounding` | 0–8 | 0 = sharp upstream look; 4–6 = softer "app" feel. |
|
||||
| `childRounding` | 0–6 | Usually 1 less than `windowRounding`. |
|
||||
| `popupRounding` | 0–6 | Same as `childRounding`. |
|
||||
| `frameRounding` | 0–4 | For inputs, sliders. |
|
||||
| `grabRounding` | 0–4 | Slider grab dot. |
|
||||
| `tabRounding` | 0–4 | Tab corners. |
|
||||
| `scrollbarRounding` | 0–4 | Scrollbar grab. |
|
||||
| `windowBorderSize` | 0 or 1 | 1 reads better in dark themes. |
|
||||
| `frameBorderSize` | 0 or 1 | Usually matches windowBorderSize. |
|
||||
|
||||
### Optional `chatChannels`
|
||||
|
||||
If present, your theme proposes its own chat-channel colors. Property names are `ChatType` enum values (case-insensitive). Unknown names are skipped silently — safe for forward-compat.
|
||||
If present, your theme proposes its own chat-channel colors. Property names are `ChatType` enum values
|
||||
(case-insensitive). Unknown names are skipped silently — safe for forward-compat.
|
||||
|
||||
```json
|
||||
"chatChannels": {
|
||||
@@ -117,35 +120,42 @@ If present, your theme proposes its own chat-channel colors. Property names are
|
||||
}
|
||||
```
|
||||
|
||||
The user is asked **once per theme switch** whether to apply these colors — never auto-overwriting existing picks. The banner shows up only if your suggested colors differ from the user's current `Configuration.ChatColours`.
|
||||
The user is asked **once per theme switch** whether to apply these colors — never auto-overwriting existing picks. The
|
||||
banner shows up only if your suggested colors differ from the user's current `Configuration.ChatColours`.
|
||||
|
||||
#### Channel-identity rule
|
||||
|
||||
**Don't break FFXIV channel identity.** Players have used these conventions for over a decade:
|
||||
|
||||
| Channel | Convention | Why |
|
||||
|---|---|---|
|
||||
| Say | white / off-white | Default-readable speech. |
|
||||
| Yell | yellow | Urgent broadcast. |
|
||||
| Shout | orange | Local urgent. |
|
||||
| Tell | pink-magenta | Whisper, must stand out. |
|
||||
| Party | light blue | Group ops. |
|
||||
| FreeCompany | cyan-teal | Guild ops. |
|
||||
| NoviceNetwork | lime-green | Mentor channel. |
|
||||
| Channel | Convention | Why |
|
||||
| ------------- | ----------------- | ------------------------ |
|
||||
| Say | white / off-white | Default-readable speech. |
|
||||
| Yell | yellow | Urgent broadcast. |
|
||||
| Shout | orange | Local urgent. |
|
||||
| Tell | pink-magenta | Whisper, must stand out. |
|
||||
| Party | light blue | Group ops. |
|
||||
| FreeCompany | cyan-teal | Guild ops. |
|
||||
| NoviceNetwork | lime-green | Mentor channel. |
|
||||
|
||||
A theme can tint these toward its brand family (e.g., a purple theme can shift Tell from `#FF99CC` to `#E090FF`), but **don't** flip them (Tell suddenly green, Yell suddenly cyan). RP groups and combat-spec setups depend on the visual hierarchy.
|
||||
A theme can tint these toward its brand family (e.g., a purple theme can shift Tell from `#FF99CC` to `#E090FF`), but
|
||||
**don't** flip them (Tell suddenly green, Yell suddenly cyan). RP groups and combat-spec setups depend on the visual
|
||||
hierarchy.
|
||||
|
||||
The eight colored built-in themes (Hellion Arctic, Hellion Spectrum, Event Horizon, Moonlit Bloom, Mint Grove, Night Blue, Indigo Violet, Forge Merchantman) all follow this rule — read their source for reference. Chat 2 Klassik intentionally ships without `chatChannels` so the user keeps their existing picks.
|
||||
The eight colored built-in themes (Hellion Arctic, Hellion Spectrum, Event Horizon, Moonlit Bloom, Mint Grove, Night
|
||||
Blue, Indigo Violet, Forge Merchantman) all follow this rule — read their source for reference. Chat 2 Klassik
|
||||
intentionally ships without `chatChannels` so the user keeps their existing picks.
|
||||
|
||||
## Theme families
|
||||
|
||||
Naming convention `<color>-<modifier>` is recommended for theme families. The first member of a family is the lightest/brightest:
|
||||
Naming convention `<color>-<modifier>` is recommended for theme families. The first member of a family is the
|
||||
lightest/brightest:
|
||||
|
||||
- `mint-grove` (current built-in, light mint)
|
||||
- `forest-grove` (planned, dark emerald)
|
||||
- `moss-grove` (planned, mid muted)
|
||||
|
||||
Code-wise families have no special handling — only the slug naming hints at the relationship. The picker may group families later, but that's not required.
|
||||
Code-wise families have no special handling — only the slug naming hints at the relationship. The picker may group
|
||||
families later, but that's not required.
|
||||
|
||||
## Validation and errors
|
||||
|
||||
@@ -154,7 +164,8 @@ When HellionChat loads your theme:
|
||||
- **Schema mismatch** (`schemaVersion != 1`): theme is skipped, warning written to `/xllog`.
|
||||
- **Missing required field** (e.g., no `slug`): theme is skipped, warning written.
|
||||
- **Invalid hex** (e.g., `#GGHHII`): theme is skipped, warning written.
|
||||
- **Unknown channel name** in `chatChannels`: that one channel is skipped silently, the rest of the theme loads normally.
|
||||
- **Unknown channel name** in `chatChannels`: that one channel is skipped silently, the rest of the theme loads
|
||||
normally.
|
||||
|
||||
Check `/xllog` after a plugin reload to see what loaded and what didn't.
|
||||
|
||||
@@ -170,15 +181,19 @@ Tip: the **Settings → Themes** picker shows a mini-mockup per theme — your c
|
||||
|
||||
## Sharing themes
|
||||
|
||||
Themes are JSON, so sharing is just a file. Drop it into someone's `pluginConfigs/HellionChat/themes/` folder and their plugin picks it up on next reload.
|
||||
Themes are JSON, so sharing is just a file. Drop it into someone's `pluginConfigs/HellionChat/themes/` folder and their
|
||||
plugin picks it up on next reload.
|
||||
|
||||
A community theme repository is on the Hellion Forge roadmap. Until then: share via Discord or any pastebin.
|
||||
|
||||
## Reference
|
||||
|
||||
- `docs/example-theme.json` (seeded automatically on first launch into `pluginConfigs/HellionChat/themes/`) — minimal valid theme.
|
||||
- The five built-in themes live in source under `HellionChat/Themes/Builtin/`. They are a good reference for Color choices that work.
|
||||
- [Hellion Online Media branding](https://hellion-media.de) — the Arctic Cyan + Ember Glow palette that drives the default Hellion Arctic theme.
|
||||
- `docs/example-theme.json` (seeded automatically on first launch into `pluginConfigs/HellionChat/themes/`) — minimal
|
||||
valid theme.
|
||||
- The five built-in themes live in source under `HellionChat/Themes/Builtin/`. They are a good reference for Color
|
||||
choices that work.
|
||||
- [Hellion Online Media branding](https://hellion-media.de) — the Arctic Cyan + Ember Glow palette that drives the
|
||||
default Hellion Arctic theme.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+35
-45
@@ -1,8 +1,7 @@
|
||||
# Third-party notices
|
||||
|
||||
HellionChat ships and depends on a number of third-party components.
|
||||
This document lists them, their licences and which of them touch the
|
||||
network. It is the inventory referenced by `PRIVACY.md`.
|
||||
HellionChat ships and depends on a number of third-party components. This document lists them, their licences and which
|
||||
of them touch the network. It is the inventory referenced by `PRIVACY.md`.
|
||||
|
||||
Last reviewed: 2026-05-05 (HellionChat v1.1.0).
|
||||
|
||||
@@ -12,63 +11,56 @@ Last reviewed: 2026-05-05 (HellionChat v1.1.0).
|
||||
|
||||
Pinned in `HellionChat/HellionChat.csproj`. Versions reflect the v1.1.0 build.
|
||||
|
||||
| Package | Version | Licence | Network | Purpose |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| [MessagePack](https://github.com/MessagePack-CSharp/MessagePack-CSharp) | 3.1.4 | MIT | no | Binary serialisation for the SQLite message store. |
|
||||
| [Microsoft.Data.Sqlite](https://learn.microsoft.com/dotnet/standard/data/sqlite/) | 10.0.7 | MIT | no | Local SQLite access for the message database. |
|
||||
| [morelinq](https://github.com/morelinq/MoreLINQ) | 4.4.0 | Apache-2.0 | no | LINQ helper extensions. |
|
||||
| [Pidgin](https://github.com/benjamin-hodgson/Pidgin) | 3.5.1 | MIT | no | Parser combinator library used for chat-input parsing. CIString Unicode fix relevant for non-ASCII channel/tab names. |
|
||||
| [SixLabors.ImageSharp](https://github.com/SixLabors/ImageSharp) | 3.1.12 | [Six Labors Split License 1.0](https://github.com/SixLabors/ImageSharp/blob/main/LICENSE) (OSI-approved; free for open-source / non-commercial use, commercial licence required for closed-source commercial use) | no | Image decoding for cached emotes. |
|
||||
| [SQLitePCLRaw.lib.e_sqlite3](https://github.com/ericsink/SQLitePCL.raw) | 3.50.3 | MIT | no | Native SQLite binary, explicitly pinned to override the transitive default for CVE-2025-6965 (memory corruption from aggregate-term overflow) and CVE-2025-7709. |
|
||||
| Package | Version | Licence | Network | Purpose |
|
||||
| --------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [MessagePack](https://github.com/MessagePack-CSharp/MessagePack-CSharp) | 3.1.4 | MIT | no | Binary serialisation for the SQLite message store. |
|
||||
| [Microsoft.Data.Sqlite](https://learn.microsoft.com/dotnet/standard/data/sqlite/) | 10.0.7 | MIT | no | Local SQLite access for the message database. |
|
||||
| [morelinq](https://github.com/morelinq/MoreLINQ) | 4.4.0 | Apache-2.0 | no | LINQ helper extensions. |
|
||||
| [Pidgin](https://github.com/benjamin-hodgson/Pidgin) | 3.5.1 | MIT | no | Parser combinator library used for chat-input parsing. CIString Unicode fix relevant for non-ASCII channel/tab names. |
|
||||
| [SixLabors.ImageSharp](https://github.com/SixLabors/ImageSharp) | 3.1.12 | [Six Labors Split License 1.0](https://github.com/SixLabors/ImageSharp/blob/main/LICENSE) (OSI-approved; free for open-source / non-commercial use, commercial licence required for closed-source commercial use) | no | Image decoding for cached emotes. |
|
||||
| [SQLitePCLRaw.lib.e_sqlite3](https://github.com/ericsink/SQLitePCL.raw) | 3.50.3 | MIT | no | Native SQLite binary, explicitly pinned to override the transitive default for CVE-2025-6965 (memory corruption from aggregate-term overflow) and CVE-2025-7709. |
|
||||
|
||||
Six Labors note: HellionChat is an EUPL-1.2-licensed open-source
|
||||
project distributed at no cost. Use of ImageSharp 3.x under the
|
||||
Six Labors Split License 1.0 is permitted on that basis. Anyone
|
||||
forking HellionChat for closed-source or commercial redistribution
|
||||
should review the
|
||||
[Six Labors licence terms](https://github.com/SixLabors/ImageSharp/blob/main/LICENSE)
|
||||
and obtain a commercial licence if required.
|
||||
Six Labors note: HellionChat is an EUPL-1.2-licensed open-source project distributed at no cost. Use of ImageSharp 3.x
|
||||
under the Six Labors Split License 1.0 is permitted on that basis. Anyone forking HellionChat for closed-source or
|
||||
commercial redistribution should review the
|
||||
[Six Labors licence terms](https://github.com/SixLabors/ImageSharp/blob/main/LICENSE) and obtain a commercial licence if
|
||||
required.
|
||||
|
||||
## SDK and tooling
|
||||
|
||||
| Component | Licence | Notes |
|
||||
| --- | --- | --- |
|
||||
| Component | Licence | Notes |
|
||||
| ------------------------------------------------------------- | ------------------------------------------- | -------------------------------------------- |
|
||||
| [Dalamud.NET.Sdk](https://github.com/goatcorp/Dalamud) 15.0.0 | AGPL-3.0 (Dalamud) / SDK terms per goatcorp | Plugin SDK; pulls in DalamudPackager 15.0.0. |
|
||||
| [.NET 10 SDK](https://dotnet.microsoft.com/) | MIT | Build toolchain. |
|
||||
| [.NET 10 SDK](https://dotnet.microsoft.com/) | MIT | Build toolchain. |
|
||||
|
||||
## Bundled assets
|
||||
|
||||
| Asset | Licence | Source |
|
||||
| --- | --- | --- |
|
||||
| Exo 2 (`HellionFont.ttf`) | SIL Open Font License 1.1 | [Google Fonts / Natanael Gama](https://fonts.google.com/specimen/Exo+2). The OFL licence text travels embedded next to the font (`HellionFont-OFL.txt`) to satisfy the "licence must be distributed with the font" clause. |
|
||||
| Hellion plugin icon (`images/icon.png`) | © Hellion Media, included under the project licence (EUPL-1.2). | Original artwork. |
|
||||
| Asset | Licence | Source |
|
||||
| --------------------------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Exo 2 (`HellionFont.ttf`) | SIL Open Font License 1.1 | [Google Fonts / Natanael Gama](https://fonts.google.com/specimen/Exo+2). The OFL licence text travels embedded next to the font (`HellionFont-OFL.txt`) to satisfy the "licence must be distributed with the font" clause. |
|
||||
| Hellion plugin icon (`images/icon.png`) | © Hellion Media, included under the project licence (EUPL-1.2). | Original artwork. |
|
||||
|
||||
---
|
||||
|
||||
## Upstream code
|
||||
|
||||
HellionChat is a fork of [Chat 2](https://github.com/Infiziert90/ChatTwo)
|
||||
by Infiziert90 (Infi) and Anna Clemens, also licensed under EUPL-1.2.
|
||||
The bulk of the code, including the message store architecture, the
|
||||
channel logic, the hook system and the ImGui chat window, originates
|
||||
from upstream. See `../NOTICE.md` for the attribution; `UPSTREAM_SYNC.md`
|
||||
documents the upstream-sync history, including the close of active
|
||||
cherry-picking in the v1.4.x cycle.
|
||||
HellionChat is a fork of [Chat 2](https://github.com/Infiziert90/ChatTwo) by Infiziert90 (Infi) and Anna Clemens, also
|
||||
licensed under EUPL-1.2. The bulk of the code, including the message store architecture, the channel logic, the hook
|
||||
system and the ImGui chat window, originates from upstream. See `../NOTICE.md` for the attribution; `UPSTREAM_SYNC.md`
|
||||
documents the upstream-sync history, including the close of active cherry-picking in the v1.4.x cycle.
|
||||
|
||||
---
|
||||
|
||||
## Components that touch the network
|
||||
|
||||
Of everything listed above, **none** of the bundled or NuGet
|
||||
components opens network connections on their own. All outbound
|
||||
traffic is initiated explicitly by HellionChat's own source files
|
||||
and is documented in `PRIVACY.md` under "Outbound network calls":
|
||||
Of everything listed above, **none** of the bundled or NuGet components opens network connections on their own. All
|
||||
outbound traffic is initiated explicitly by HellionChat's own source files and is documented in `PRIVACY.md` under
|
||||
"Outbound network calls":
|
||||
|
||||
- `HellionChat/EmoteCache.cs` → BetterTTV API + CDN (opt-out via setting)
|
||||
|
||||
The earlier Square Enix Lodestone font download (`FontManager.cs`)
|
||||
was removed in v1.0.4 — it was a leftover from upstream's removed
|
||||
webinterface feature and was no longer consumed.
|
||||
The earlier Square Enix Lodestone font download (`FontManager.cs`) was removed in v1.0.4 — it was a leftover from
|
||||
upstream's removed webinterface feature and was no longer consumed.
|
||||
|
||||
---
|
||||
|
||||
@@ -80,10 +72,8 @@ To regenerate the dependency inventory after a version bump:
|
||||
dotnet list HellionChat.sln package --include-transitive
|
||||
```
|
||||
|
||||
The "direct NuGet dependencies" table above only lists direct
|
||||
references. Transitive dependencies pulled in by Dalamud SDK or by
|
||||
the listed packages are covered by the SDK / package licences and
|
||||
documented by their respective maintainers.
|
||||
The "direct NuGet dependencies" table above only lists direct references. Transitive dependencies pulled in by Dalamud
|
||||
SDK or by the listed packages are covered by the SDK / package licences and documented by their respective maintainers.
|
||||
|
||||
To re-audit the network-call inventory:
|
||||
|
||||
@@ -92,5 +82,5 @@ grep -rn -E "HttpClient|HttpRequest|new Uri\(|https?://" \
|
||||
--include="*.cs" HellionChat/
|
||||
```
|
||||
|
||||
Any new hit that is not a click-through (`Util.OpenLink`) or a
|
||||
payload-parsing call must be added to `PRIVACY.md` before release.
|
||||
Any new hit that is not a click-through (`Util.OpenLink`) or a payload-parsing call must be added to `PRIVACY.md` before
|
||||
release.
|
||||
|
||||
+58
-92
@@ -1,127 +1,93 @@
|
||||
# Upstream Sync
|
||||
|
||||
HellionChat is a standalone EUPL-1.2 plugin that originated from
|
||||
[Chat 2](https://github.com/Infiziert90/ChatTwo). Since v1.0.0 it
|
||||
lives under its own namespace, IPC channels and source tree. The
|
||||
active cherry-pick pipeline from upstream Chat 2 is closed since
|
||||
the v1.4.x cycle.
|
||||
HellionChat is a standalone EUPL-1.2 plugin that originated from [Chat 2](https://github.com/Infiziert90/ChatTwo). Since
|
||||
v1.0.0 it lives under its own namespace, IPC channels and source tree. The active cherry-pick pipeline from upstream
|
||||
Chat 2 is closed since the v1.4.x cycle.
|
||||
|
||||
This document covers what that means, why I closed it, and what
|
||||
stays in place.
|
||||
This document covers what that means, why I closed it, and what stays in place.
|
||||
|
||||
## A Word on Intent
|
||||
|
||||
HellionChat is not trying to replace Chat 2. I build it for myself,
|
||||
and maybe for people who want the same things I do: a privacy-first
|
||||
chat plugin with tighter defaults and no remote-access surface. If
|
||||
that is not you, Chat 2 is the better choice and a well-maintained
|
||||
project.
|
||||
HellionChat is not trying to replace Chat 2. I build it for myself, and maybe for people who want the same things I do:
|
||||
a privacy-first chat plugin with tighter defaults and no remote-access surface. If that is not you, Chat 2 is the better
|
||||
choice and a well-maintained project.
|
||||
|
||||
I am available to Infi if he ever has questions about HellionChat or
|
||||
how I have diverged from the upstream code. What I will not do is
|
||||
interfere with Chat 2's direction or push unsolicited opinions into
|
||||
his project.
|
||||
I am available to Infi if he ever has questions about HellionChat or how I have diverged from the upstream code. What I
|
||||
will not do is interfere with Chat 2's direction or push unsolicited opinions into his project.
|
||||
|
||||
Long-term compatibility between Chat 2 and HellionChat is not
|
||||
guaranteed and, frankly, not technically possible. I am building a
|
||||
new UI from scratch and making deliberate architectural decisions that
|
||||
pull in a different direction. Some upstream patches will simply stop
|
||||
applying cleanly and that is expected.
|
||||
Long-term compatibility between Chat 2 and HellionChat is not guaranteed and, frankly, not technically possible. I am
|
||||
building a new UI from scratch and making deliberate architectural decisions that pull in a different direction. Some
|
||||
upstream patches will simply stop applying cleanly and that is expected.
|
||||
|
||||
## Why Cherry-Picking Stopped in v1.4.x
|
||||
|
||||
Two things converged:
|
||||
|
||||
1. **Chat 2 is in a rework cycle.** Infi mentioned directly that
|
||||
parts of ChatTwo are being reworked and "stuff may not be able to
|
||||
be cherry picked anymore." Once the upstream code paths I would
|
||||
pull from no longer exist in the same shape, `git cherry-pick`
|
||||
stops being a meaningful tool — what would land would not be the
|
||||
change Infi wrote, it would be a hand-port of his concept.
|
||||
2. **HellionChat has drifted enough that selective patches require
|
||||
adaptation anyway.** The UI is being rebuilt, the theme engine
|
||||
sits on top of HellionStyle which has no upstream equivalent, the
|
||||
privacy filter changes how messages flow through MessageManager.
|
||||
Even before the rework was announced, more and more upstream
|
||||
patches needed adaptation rather than a clean apply.
|
||||
1. **Chat 2 is in a rework cycle.** Infi mentioned directly that parts of ChatTwo are being reworked and "stuff may not
|
||||
be able to be cherry picked anymore." Once the upstream code paths I would pull from no longer exist in the same
|
||||
shape, `git cherry-pick` stops being a meaningful tool — what would land would not be the change Infi wrote, it would
|
||||
be a hand-port of his concept.
|
||||
2. **HellionChat has drifted enough that selective patches require adaptation anyway.** The UI is being rebuilt, the
|
||||
theme engine sits on top of HellionStyle which has no upstream equivalent, the privacy filter changes how messages
|
||||
flow through MessageManager. Even before the rework was announced, more and more upstream patches needed adaptation
|
||||
rather than a clean apply.
|
||||
|
||||
Together those two points mean continuing to call this an "active
|
||||
cherry-pick pipeline" was no longer honest. So I closed it.
|
||||
Together those two points mean continuing to call this an "active cherry-pick pipeline" was no longer honest. So I
|
||||
closed it.
|
||||
|
||||
## What Closing the Pipeline Means in Practice
|
||||
|
||||
- The `upstream` git remote was removed locally on 2026-05-08.
|
||||
Anyone setting up a fresh clone does **not** add it back.
|
||||
- New commits will not carry `(cherry picked from commit ...)`
|
||||
trailers. Anything that originates from Chat 2 from this point
|
||||
forward will be a hand-port at most, and it gets called out as
|
||||
such in its own commit message and in the relevant source comments.
|
||||
- The existing cherry-pick trail stays in the git history exactly as
|
||||
it is. Every `(cherry picked from commit ...)` line that was added
|
||||
with `-x` in earlier releases remains intact; that is the
|
||||
attribution paper trail and removing it would be wrong.
|
||||
- The `upstream` git remote was removed locally on 2026-05-08. Anyone setting up a fresh clone does **not** add it back.
|
||||
- New commits will not carry `(cherry picked from commit ...)` trailers. Anything that originates from Chat 2 from this
|
||||
point forward will be a hand-port at most, and it gets called out as such in its own commit message and in the
|
||||
relevant source comments.
|
||||
- The existing cherry-pick trail stays in the git history exactly as it is. Every `(cherry picked from commit ...)` line
|
||||
that was added with `-x` in earlier releases remains intact; that is the attribution paper trail and removing it would
|
||||
be wrong.
|
||||
|
||||
## What Does Not Change
|
||||
|
||||
- **EUPL-1.2 anchor lines in source files.** Files that originated
|
||||
from Chat 2 keep their licence headers and any "based on
|
||||
Infiziert90/ChatTwo" notice exactly as they are. The licence
|
||||
obligations under EUPL-1.2 do not lapse because cherry-picking
|
||||
stopped.
|
||||
- **NOTICE.md** stays canonical. Attribution to Infi and Anna for the
|
||||
message store, channel logic, hook system, ImGui chat window and
|
||||
the localisation infrastructure remains the foundation statement of
|
||||
this fork.
|
||||
- **README acknowledgements.** The Acknowledgements section in
|
||||
`README.md`, the maintainer thanks in the About tab, and the
|
||||
`Language.*.resx` Crowdin translator credit list all stay as they
|
||||
are.
|
||||
- **The original `Language.*.resx` files** remain in the source tree
|
||||
in their last upstream-sync state. They are the work of the Chat 2
|
||||
Crowdin community and the existing translations stay valuable. They
|
||||
will not receive automatic upstream updates anymore — see
|
||||
CONTRIBUTING.md for what that means for translators.
|
||||
- **EUPL-1.2 anchor lines in source files.** Files that originated from Chat 2 keep their licence headers and any "based
|
||||
on Infiziert90/ChatTwo" notice exactly as they are. The licence obligations under EUPL-1.2 do not lapse because
|
||||
cherry-picking stopped.
|
||||
- **NOTICE.md** stays canonical. Attribution to Infi and Anna for the message store, channel logic, hook system, ImGui
|
||||
chat window and the localisation infrastructure remains the foundation statement of this fork.
|
||||
- **README acknowledgements.** The Acknowledgements section in `README.md`, the maintainer thanks in the About tab, and
|
||||
the `Language.*.resx` Crowdin translator credit list all stay as they are.
|
||||
- **The original `Language.*.resx` files** remain in the source tree in their last upstream-sync state. They are the
|
||||
work of the Chat 2 Crowdin community and the existing translations stay valuable. They will not receive automatic
|
||||
upstream updates anymore — see CONTRIBUTING.md for what that means for translators.
|
||||
|
||||
## What Could Re-Open Later
|
||||
|
||||
If Chat 2's rework lands and stabilises, and there is a piece of
|
||||
upstream code that I genuinely want in HellionChat, the path forward
|
||||
is **study and re-implement**, not cherry-pick. That means:
|
||||
If Chat 2's rework lands and stabilises, and there is a piece of upstream code that I genuinely want in HellionChat, the
|
||||
path forward is **study and re-implement**, not cherry-pick. That means:
|
||||
|
||||
- Read the upstream change, understand the design, port the concept
|
||||
to HellionChat's actual code paths.
|
||||
- Credit the upstream author in the commit message and, if the
|
||||
ported code is non-trivial, in a source-file comment.
|
||||
- Pre-clear with Infi if the port is large enough to warrant a
|
||||
conversation.
|
||||
- Read the upstream change, understand the design, port the concept to HellionChat's actual code paths.
|
||||
- Credit the upstream author in the commit message and, if the ported code is non-trivial, in a source-file comment.
|
||||
- Pre-clear with Infi if the port is large enough to warrant a conversation.
|
||||
|
||||
This is heavier than `git cherry-pick -x` and that is the point.
|
||||
Cherry-picking was light because both codebases shared structure;
|
||||
once they do not, the proper attribution costs a real conversation
|
||||
rather than a flag on a git command.
|
||||
This is heavier than `git cherry-pick -x` and that is the point. Cherry-picking was light because both codebases shared
|
||||
structure; once they do not, the proper attribution costs a real conversation rather than a flag on a git command.
|
||||
|
||||
## Contributing Back
|
||||
|
||||
HellionChat benefits from Chat 2's work, so I try to give something
|
||||
back where I can. If I fix a bug or improve something that would be
|
||||
useful to Chat 2 and is not HellionChat-specific, I submit a
|
||||
good-will PR to [Infiziert90/ChatTwo](https://github.com/Infiziert90/ChatTwo).
|
||||
HellionChat benefits from Chat 2's work, so I try to give something back where I can. If I fix a bug or improve
|
||||
something that would be useful to Chat 2 and is not HellionChat-specific, I submit a good-will PR to
|
||||
[Infiziert90/ChatTwo](https://github.com/Infiziert90/ChatTwo).
|
||||
|
||||
A few things to note about that process:
|
||||
|
||||
- Good-will PRs are validated in a separate fork first to make sure
|
||||
the fix stands on its own without HellionChat context.
|
||||
- They are written by hand. No AI-generated code goes to Infi's
|
||||
project. He did not ask for Pair-level AI involvement and I will
|
||||
not push that decision onto his codebase.
|
||||
- This is not guaranteed for every change, only where it makes sense
|
||||
and where I am confident the fix is clean and self-contained.
|
||||
- Good-will PRs are validated in a separate fork first to make sure the fix stands on its own without HellionChat
|
||||
context.
|
||||
- They are written by hand. No AI-generated code goes to Infi's project. He did not ask for Pair-level AI involvement
|
||||
and I will not push that decision onto his codebase.
|
||||
- This is not guaranteed for every change, only where it makes sense and where I am confident the fix is clean and
|
||||
self-contained.
|
||||
- Whether it gets accepted is Infi's call, and a "no" is fine.
|
||||
|
||||
## When Upstream Takes a Direction I Cannot Follow
|
||||
|
||||
If a future Chat 2 release breaks compatibility with the HellionChat
|
||||
privacy philosophy in a way that cannot be resolved (mandatory cloud
|
||||
sync, removal of the local message store, an incompatible licence
|
||||
change), HellionChat continues from where it is. The inherited
|
||||
history stays under EUPL-1.2 and stays attributed.
|
||||
If a future Chat 2 release breaks compatibility with the HellionChat privacy philosophy in a way that cannot be resolved
|
||||
(mandatory cloud sync, removal of the local message store, an incompatible licence change), HellionChat continues from
|
||||
where it is. The inherited history stays under EUPL-1.2 and stays attributed.
|
||||
|
||||
Reference in New Issue
Block a user