# RGX-Framework

## [v1.6.0-10-g593cadf](https://github.com/DonnieDice/RGX-Framework/tree/593cadff053d2a70f015275d9588f489515433ff) (2026-06-09)
[Full Changelog](https://github.com/DonnieDice/RGX-Framework/compare/v1.6.0...593cadff053d2a70f015275d9588f489515433ff) [Previous Releases](https://github.com/DonnieDice/RGX-Framework/releases)

- fix: defer Combat:Init by 0.5s after PLAYER\_LOGIN  
    - Loading screen into combat zone: InCombatLockdown() returns false  
      but RegisterEvent is still blocked — taint unavoidable during load.  
    - C\_Timer.After(0.5) ensures world is fully loaded before Init runs.  
    - Inside Init: InCombatLockdown() check with PLAYER\_REGEN\_ENABLED fallback.  
- fix: defer RGXCombat init to PLAYER\_LOGIN  
    - RegisterEvent is fundamentally blocked during ADDON\_LOADED in combat  
    - pcall catches the error but taint log still fires  
    - RGXCombat now inits on PLAYER\_LOGIN instead of ADDON\_LOADED  
    - Also: keep pcall wrapper in safeRegisterFrameEvent for edge cases  
- fix: use pcall(anonymous fn) for RegisterEvent/UnregisterEvent  
    - pcall(frame.RegisterEvent, frame, event) passes raw C function ref → taint  
    - pcall(function() frame:RegisterEvent(event) end) passes Lua closure → safe  
    - RegisterEvent silently skips frame reg on failure; handlers already registered  
    - Removed InCombatLockdown check — pcall handles all error cases  
- fix: queue frame RegisterEvent during combat lockdown  
    - Blizzard protects frame:RegisterEvent() during combat  
    - When creating the first handler for an event, check InCombatLockdown()  
    - If in combat, queue the frame registration via QueueForCombat  
    - The event will start firing after PLAYER\_REGEN\_ENABLED processes the queue  
- fix: remove pcall from RegisterEvent/UnregisterEvent to avoid taint  
    - pcall(frame.RegisterEvent, frame, event) flagged as ADDON\_ACTION\_FORBIDDEN  
      during combat lockdown — indirect call through pcall triggers taint  
    - Replaced with direct frame:RegisterEvent(event) and frame:UnregisterEvent(event)  
    - RegisterEvent/UnregisterEvent are not Lua-throwing functions; pcall was unnecessary  
- refactor: simplify database — single metatable, step-by-step NewDatabase  
    - Merge DBHandle/NewDBMeta into one DB metatable  
    - \_\_index lookup: method → global → internal → profile → defaults  
    - OpenDB is now a 4-line wrapper around NewDatabase  
    - Labeled step-by-step factory (Steps 1-6) for readability  
    - NotifySwitch guard prevents re-entrant callback chains  
    - Rename helpers: MergeDefaults, GetPath, SetPath, ActiveProfile  
- feat: add RGX:NewDatabase — metamethod-based profile access  
    - NewDBMeta proxy with \_\_index/\_\_newindex for direct db.key access  
    - db.key reads from active profile, falls back to defaults at read time  
    - db.global returns cross-character storage table  
    - OnProfileChanged, ResetProfile, GetProfiles, GetActiveProfile  
    - Override DBHandle.\_switchTo to fire new-style callbacks  
    - Also adds full DBHandle/OpenDB engine with profile CRUD  
    - Keeps existing RGX:DB, RGX:MigrateDB, RGX:OpenDB APIs  
- docs: add RGX-Mod phased dependency table to roadmap  
- v1.6.0 — code changes: font pipeline, combat queue, UI controls, options, runtime helpers  
- v1.6.0 — documentation pass: new wiki docs, README rewrite, consistency fixes  
    7 new wiki docs (API, Architecture, Fonts, Dropdowns, Theming, Troubleshooting, Migration), rewritten README and description.html, standardized dormant module wording, fixed stale file path references, font count language, and interface version across all docs.  
