-
Notifications
You must be signed in to change notification settings - Fork 0
Ace3 Analysis
This document is not here to dismiss Ace3.
Ace3 became popular because it solved a real problem:
- WoW addon authors kept rebuilding the same boring infrastructure
If RGX wants to be better, it needs to beat Ace3 at the outcome, not just replace names.
BLU already points in the right direction here:
- one addon-owned runtime
- one addon-owned module registry
- one addon-owned event system
RGX should build on that style of framework design instead of rebuilding Ace's embedded-library architecture.
Most authors do not use Ace3 because they love LibStub or because they specifically want CallbackHandler.
They use Ace3 because it gives them a fast way to get this list of problems off their plate:
- addon lifecycle
- module organization
- event handling
- timers
- hooks
- saved variables and profiles
- slash commands
- options UI
- addon communication
- serialization
- localization
Ace3 also became a social default because:
- many example addons already use it
- many developers already know its patterns
- it reduces decision-making
- it feels safer to depend on something familiar
That means RGX does not need to copy Ace3 line-for-line.
It does need to make addon development feel easier, safer, and faster than Ace3 does.
Problem solved:
- addon object creation
- module registration
- lifecycle callbacks like
OnInitializeandOnEnable
What RGX should keep:
- one clean addon/module lifecycle
- easy module registration
- predictable startup order
What RGX should avoid:
- unnecessary embed complexity
- making every addon author think about framework internals
Problem solved:
- event registration
- message dispatch
- callback bookkeeping
What RGX should keep:
- Blizzard event handling
- framework messages
- local callback emitters
What RGX should avoid:
- external dependency chains when native RGX dispatch already solves it
Problem solved:
- delayed and repeating work
What RGX should keep:
- a simple timer/defer utility if real addons need it
What RGX should avoid:
- adding timer machinery before the suite actually depends on it
Problem solved:
- safe function hooking
- hook cleanup
What RGX should keep:
- a lightweight hook helper only if the suite repeatedly needs it
What RGX should avoid:
- shipping hook infrastructure just because frameworks usually do
Problem solved:
- SavedVariables handling
- defaults
- namespaces
- profile support
What RGX should keep:
- strong defaults
- simple storage model
- optional profile support only if the suite truly benefits from profiles
What RGX should avoid:
- database complexity that authors do not actually need
Problem solved:
- slash commands
- command routing
- formatted framework output
What RGX should keep:
- a tiny command registration helper
What RGX should avoid:
- over-engineered command parsing unless real addons need it
Problem solved:
- reusable settings widgets
- options layout generation
- standard configuration flow
What RGX should keep:
- shared widgets
- shared layout primitives
- one-line control binding
- live preview behavior
What RGX should avoid:
- giant declarative config tables that are harder to maintain than the UI they generate
This is one of the biggest places RGX can be better.
Problem solved:
- addon communication
- chunked message transport
- structured data transport
What RGX should keep:
- comm + serialization only when RGX or RGX-Mod truly need cross-addon traffic or import/export
What RGX should avoid:
- carrying comm infrastructure before that use case exists
Problem solved:
- localization tables
What RGX should keep:
- a straightforward localization pattern if the suite needs multi-language support
What RGX should avoid:
- localization framework weight before localization work actually begins
Problem solved:
- runtime version negotiation for separately embedded libraries
What RGX should keep:
- nothing from this unless RGX starts shipping as separately embedded versioned sub-libraries
What RGX should avoid:
- pretending a single dependency addon needs embedded-library version arbitration
Preferred RGX replacement:
- BLU-style native framework services inside RGX itself
If the goal is "Ace3 but better and simpler," the real required foundation is:
- core framework object
- module registry and lifecycle
- shared media registries for fonts, textures, colors, then sounds
- event/message/callback dispatch
- native runtime services such as timers, hooks, and slash helpers
- defaults + SavedVariables helpers
- shared option controls
- one-line apply helpers
- simple command helpers
- timer/defer helpers if the suite needs them
- tab/group/frame layout primitives
- better settings binding
- sound preview and sound registry support
- BLU-compatible shared media bridging where useful
- hook helpers if repeated real use appears
- serialization
- addon comm
- import/export
- localization support
- RGX-Mod-oriented higher-level systems
RGX should not try to win by having more tiny libraries.
RGX should win by being easier to consume.
Ace3 often feels powerful because it is broad.
It also feels fragmented because authors end up thinking in terms of many small library names and embedding patterns.
RGX should feel like:
- install one addon
- depend on one addon
- call one family of APIs
Ace3 gives capability.
RGX should give capability plus polished defaults:
- curated media
- ready-made controls
- consistent styling
- built-in preview behavior
Ace3 often reduces raw implementation work but still leaves a lot of structure for the author to assemble.
RGX should prefer APIs like:
AttachFontSelectorAttachBarSelectorAttachColorSelectorApplyTextStyle
instead of pushing authors toward big generic setup tables whenever a direct helper would be clearer.
Ace3 is often used because it is functional.
RGX should be functional and visually opinionated in a good way:
- good media
- good previews
- good selector behavior
- consistent suite identity
Ace3 gives a lot of flexibility, which is useful, but it can also spread complexity into consumer addons.
RGX should keep more of the complexity internal so authors do not have to reinvent patterns.
RGX should only grow when real addons need the feature:
- SQP
- BPU
- BLU
- future RGX-Mod
That keeps the framework honest.
The strongest position for RGX is not:
- "we replaced Ace3 with our own Ace3 clone"
The strongest position is:
- RGX keeps the handful of framework capabilities addon authors actually need
- RGX removes the dependency clutter and historical baggage
- RGX gives much better shared media and shared controls
- RGX makes addon integration faster than Ace-style assembly
When deciding whether a new RGX subsystem belongs in the framework, ask:
- What real addon problem is this solving?
- Is that problem already showing up in SQP, BPU, BLU, or planned RGX-Mod work?
- Can RGX solve it with one clean native system instead of another external-style compatibility layer?
- Will this make addon authors faster, or just make RGX look more like Ace3?
If the answer is "faster and simpler for real addons," it belongs.
If the answer is "Ace3 had one, so we should too," it probably does not.
Everything below verified against shipped source, not aspiration.
| Ace3 piece | RGX today | Verdict |
|---|---|---|
| AceAddon (lifecycle/modules) |
RGXAddon declarative front door + RGX:RegisterModule
|
Better — one call replaces the OnInitialize/OnEnable ceremony |
| AceEvent + CallbackHandler |
RGX:RegisterEvent/RegisterUnitEvent, messages, house AddCb pattern (returns unsubscribe closures) |
Parity, safer — dispatch is pcall-wrapped |
| AceTimer |
RGX:After/Every/CancelTimer (core/systems/runtime.lua) |
Better — labeled, budgeted, diagnosable |
| AceConsole |
RGX:RegisterSlashCommand + the slash key |
Better — assumed handler opens the panel |
| AceDB (profiles) |
core/systems/database.lua: profiles, defaults fallback, OnProfileChanged, Serialize/DeserializeProfile
|
Parity+ — serialize included; no namespaces (not needed yet) |
| AceConfig/AceConfigDialog |
options table → panel |
Better where it counts — a fraction of the table weight; fewer control types so far (by design, growing with real need) |
| AceGUI | RGXUI + RGXDesign | Better — Ace has no design system; AceGUI widgets are unstyled |
| AceHook |
RGX:Hook (runtime.lua) |
Parity |
| AceBucket | Tier 6 #17 | Planned, need-driven |
| AceComm + AceSerializer | none (profile serialize only) | Intentionally absent until a real addon needs cross-client traffic (OmniCD-style sync is the likely first consumer) |
| AceLocale | none | Intentionally absent until localization work begins (LibLocaleOverride's per-addon override pattern is the researched direction) |
| LibSharedMedia | RGXSharedMedia | Parity |
| LibDBIcon/LDB | RGXMinimap + databroker | Better — persistence and tooltip composed in |
These are the reasons RGX is a replacement, not a clone — protect them:
-
The DSL —
RGXAddon "Name" { }with progressive disclosure: every key works bare with assumed arguments and accepts an advanced form. Ace3's equivalent is assembling five libraries and a config mega-table. -
The machine-checkable contract —
schemas/rgx-addon.schema.json+tools/rgx-mcp(validate/audit/generate) + an end-to-end test that runs the real MCP server against the real reference addon. Ace3 has zero tooling; its options tables fail at runtime or never. - Centralized WoW safety infrastructure — a guaranteed player-aura fast path, explicit restricted-value boundaries, combat-lockdown guards, and failure-isolated native tooltip hooks. This does not make arbitrary secret value reads safe; those values must remain opaque.
- A shipped visual identity — RGXDesign tokens/theming; AceGUI addons all look like AceGUI.
-
A living test suite — RGX-Hello's
/rgxvisualcovers every user-facing module in-game.
Options panels are one composable vocabulary: panel → main page + tabs →
tabs can be multi-paged → 1–2 column card grid → rows/cards holding the
widgets. BLU built this to 1–2 columns with paged tabs
(COMBAT_TRIGGER_PAGES); the contract freezes columns = 1|2|3. Tier 4
implements it declaratively without changing anything authors write today.