promotional bannermobile promotional banner

Classic Calendar - Revived

Forking and maintaining the Classic Calendar addon for WoW Classic
Back to Files

ClassicCalendar-v1.6.4

File nameClassicCalendar-ClassicCalendar-v1.6.4.zip
Uploader
PmptastyPmptasty
Uploaded
Jul 22, 2026
Downloads
3.0K
Size
373.3 KB
Flavors
ClassicClassic TBC
File ID
8488423
Type
R
Release
Supported game versions
  • 2.5.6
  • 1.15.8

What's new

Classic Calendar

[v1.6.4] (2026-07-19)

Bug Fixes

  • Fixed a Lua error when opening the Create Event window after Blizzard's Classic client API update. CalendarCreateEventDescriptionContainer_OnLoad threw ScrollUtil.RegisterScrollBoxWithScrollBar expected a 1:1 pairing, but this ScrollBar is already registered with another ScrollBox (ClassicCalendar.lua:4409). Root cause was a latent duplicate-global-name bug that Blizzard's update exposed: two EventFrames were declared with the identical global name CalendarCreateEventDescriptionContainerScrollBar — one inside the view-event description container (ClassicCalendar.xml:664, a copy-paste typo) and the correct one inside the create-event container (ClassicCalendar.xml:1020). Both OnLoads resolved that single shared global: CalendarViewEventDescriptionContainer_OnLoad registered it to the view's ScrollingFont scrollbox, then CalendarCreateEventDescriptionContainer_OnLoad tried to bind the same scrollbar frame to the create editbox's scrollbox. The old ScrollUtil silently re-registered; the updated EnsureScrollBarRegistration now error()s on that 1:1 violation. Fix: renamed the view container's scrollbar to its own unique global CalendarViewEventDescriptionContainerScrollBar, pointed CalendarViewEventDescriptionContainer_OnLoad at the corrected name, and registered the new global in .luarc.json. Pure UI/XML change shared identically by Era and BCC — no per-flavor branching. Location: ClassicCalendar.xml, ClassicCalendar.lua, .luarc.json.

Build / Packaging

  • Fixed the release zip shipping docs/ and wow-version-replication.ps1. The .pkgmeta ignore list used pattern forms the BigWigs packager doesn't honor: docs/ (a trailing slash makes the packager's directory auto-expansion produce docs//*, which matches nothing) and **/*.ps1 (the leading **/ requires a subdirectory, so it never matched the root-level .ps1). Both leaked into the packaged addon. Rewrote the ignore list to the forms the packager's case-glob matcher actually uses — bare directory name (docs, auto-expanded to docs/*) and root globs (*.ps1, *.bat) — verified against the packager's match_pattern logic. Also removed three dead entries (BUG_TRACKER.md, developer_log.md, FEATURE_TRACKER.md) that targeted the repo root but whose files live under docs/, so they're now covered by the docs exclusion. Packaging-only: no addon behavior changes; takes effect on the next release build. Location: .pkgmeta.

[v1.6.3] (2026-07-15)

Changed

  • Bumped the BCC TOC's ## Interface: to 20506. ClassicCalendar_BCC.toc still declared 20505, which the current Burning Crusade Classic client flags as out-of-date (the addon is disabled unless "Load out of date AddOns" is checked). Only the BCC TOC changes — ClassicCalendar.toc stays at Era 11508, and the two TOCs' file load lists remain identical. Location: ClassicCalendar_BCC.toc.

[v1.6.2] (2026-07-13)

New Features

  • Online/offline column in the event sign-up list. Each signed-up player now shows a presence dot next to their status — green when online, grey when offline, and hidden when the signup isn't a current guild member. Presence comes straight from LibGuildRoster (GR:GetMember(name).isOnline via a new CC_GRC_IsMemberOnline helper), so it costs no extra roster scan. The column header ("ON") is sortable like the other custom columns (online-first by default, click to reverse) via the existing CC_CustomSortButton path and a new online branch in ApplyCustomSort; it's wired into both the view and create/edit invite lists. The dot is anchored to the Status column's left edge so it tracks the right side on resize. Location: ClassicCalendarTemplates.xml, ClassicCalendar.lua, GuildRankConfirm.lua.

Bug Fixes

  • Fixed ClassicCalendar.lua being executed twice on every load. ClassicCalendar.xml opened with <Script file="ClassicCalendar.lua"/> while ClassicCalendar.toc already loaded ClassicCalendar.lua (before GuildRankConfirm.lua, so the latter could hook it). The XML's <Script> re-ran the entire file when the XML loaded — after GuildRankConfirm.lua had installed its hooks — redefining every global function (CalendarFrame_ShowEventFrame, the create/edit frame handlers, etc.) to fresh copies with no hooks attached. It also duplicated every RegisterEvent, the LibDBIcon setup, the world-buff sync init, the 30-minute heartbeat ticker, and VersionCheck registration, and raced two copies of every saved-variable write. Removed the redundant <Script> line; the TOC remains the sole loader, preserving the lua→GuildRankConfirm→xml order. Location: ClassicCalendar.xml.
    • Concretely fixes the Rank Auto-Confirm control never appearing reliably. With the CalendarFrame_ShowEventFrame hook detached, UpdateConfigButtonVisibility (and thus the control's creation) never ran when an event frame opened. The control only ever showed when a CALENDAR_UPDATE_EVENT happened to fire with the frame open — hence "it was there ten minutes ago, then a guildmate logged on and it vanished." The reliable hook path now survives, so the control is created whenever a guild event's create/edit frame opens. (The control itself is also reworked into a dropdown menu — see Changed.)
  • Fixed CalendarHelper initializing twice. CalendarHelper.lua contained a copy-pasted duplicate of its entire init tail — two CreateFrame frames each registered for ADDON_LOADED/PLAYER_LOGIN, so CalendarHelper:Initialize() and PrintSavedVariableStatus() (and their debug prints) ran twice per login. Removed the duplicate block. Location: CalendarHelper.lua.
  • Fixed two-digit signup numbers rendering as "…" in the event invite list. The signup-order column (SignupNum in CalendarEventInviteListButtonTemplate) was a fixed 14px-wide FontString; a two-digit ordinal (10+) overflowed and ellipsized to a bare "…". Widened it to 20px, which still clears the leader/ready-check icon slot at x=20. The frame's resize grip only redistributes width to the Name/Rank columns, so this column could not be widened by dragging. Location: ClassicCalendarTemplates.xml.
  • Fixed the Rank Auto-Confirm rank list omitting empty guild ranks. BuildRankList derived the selectable ranks from the ranks current roster members happened to hold, so any rank with no currently-loaded member never appeared (reported as "only the highest two and lowest two ranks show"). It now enumerates the guild's rank definitions via GuildControlGetNumRanks() / GuildControlGetRankName(i) (1-based, mapped to the 0-based rankIndex used everywhere else), including empty ranks, then tops up from the roster scan as a permission-safe fallback so a restricted client degrades to the old behavior instead of erroring. Location: GuildRankConfirm.lua.
  • Fixed the world-buff date picker allowing unbounded future years. The month-navigation arrows (ChangeMonth, ChangeDatePickerMonth) rolled the year forward/back with no limit and nothing validated the year on save, so repeated clicks could create entries years out (the "entries dated into 2029" report). Both navigation paths now clamp through a shared ClampSelectedDateToWindow to a rolling last-year / this-year / next-year window (date("%Y") ±1) — enough headroom to navigate across a December/January boundary, but no further. Pre-existing far-future entries are left intact (they live in the synced store). Location: WorldBuff.lua.
  • Fixed the invite-list column headers not lining up over the #, LVL, and ON columns. Those cells aren't left-justified (# is centre-justified, LVL right-justified, ON is a centred dot), but their headers were left-anchored like the Name/Class/Rank headers, so they sat off to one side. In CalendarEventInviteList_AnchorSortButtons the # header is now centred over its cell (x=12), LVL is right-aligned to the cell's right edge (x=207), and ON is centred over the dot (right-75, accounting for the row's ~5px inset). Location: ClassicCalendar.lua.

Changed

  • Rank Auto-Confirm is now a native dropdown menu, not a button + floating popup. The UIPanelButton and the custom CalendarGuildRankConfirmPopup (checkbox panel, Done/Re-process buttons) are replaced by a Blizzard UIDropDownMenuTemplate injected into the create/edit invite-list section. Each guild rank is a checkable menu entry (isNotRadio + keepShownOnClick, so multi-select stays open); a title row heads the menu and, in edit mode, a "Re-process Signups" action closes it. The menu's UIDropDownMenu_Initialize builder re-reads the rank list and per-event settings on every open, so checkmarks always reflect current state. This also resolves the see-through popup background (the report that the panel was too transparent) for free — the native dropdown list uses Blizzard's opaque menu backdrop. /calranks debug now reports configDropDown state and /calranks show toggles the menu. Location: GuildRankConfirm.lua.
  • Removed the officer view-only Rank Auto-Confirm control. The view-event window's invite-list header is fully occupied by Blizzard's RSVP buttons (Sign Up/Tentative/Decline/Remove), so the dropdown collided with them there; its settings also didn't reliably persist from the view frame (they were gated on the create/edit frame's edit-mode). The control now lives only on the create/edit window, where it fits and functions. Officers who can edit an event still configure ranks via the edit window. Location: GuildRankConfirm.lua.

[v1.6.1] (2026-07-11)

New Features

  • World-buff entry timestamps. Each entry now records an immutable createdAt (server time, stamped once on add and preserved across edits) alongside lastModified. The Date Received column appends the entry's added time-of-day so it reads as a full date/time stamp; hovering a player name surfaces the last-edited time (when applicable), the left/right-click actions, and the member-only note. createdAt propagates on the wire and is folded into the leaf hash and content tie-break so it converges across the guild. Location: WorldBuff.lua, WorldBuffDB.lua, WorldBuffSync.lua.

Bug Fixes

  • Fixed login/logout stutter under world-buff sync (large guilds). getMyHashes — which DeltaSync calls on every guildmate's hash-broadcast — was re-hashing the entire world-buff dataset each time, an O(all-entries) main-thread pass that stuttered during pre-raid login flurries. Item hashes are now per-entry leaf hashes rolled up per item, maintained incrementally on write in an in-memory index (WorldBuffDB._hx); the receive path is a pure lookup with no content hashing. Content is hashed only on an actual edit, or once when the index is first built after login. Location: WorldBuffDB.lua, WorldBuffSync.lua.
  • Fixed connected-realm key fragmentation / endless resync. On a connected-realm cluster a bare player name was normalized with the viewer's realm, so the same player fragmented into per-realm and per-case keys (nuksylvshuntm5-atiesh / -oldblanchy / -myzrael / mixed case) that never matched across clients — so peers' item hashes never converged and re-synced forever. NormalizeKey now resolves the canonical Name-HomeRealm via the library roster (short-name → roster lookup), which is identical on every client, and never strips the realm (the fallback is GR:NormalizeName, which adds one). Location: WorldBuffDB.lua.
  • Eliminated the redundant guild-roster refresh churn. GuildRankConfirm kept its own GetGuildRosterInfo scan (memberCache/rankList) rebuilt on every GUILD_ROSTER_UPDATE, and re-requested the roster via C_GuildInfo.GuildRoster() — a self-feeding refresh loop. That parallel cache is deleted; rank/level/online/name now read directly from LibGuildRoster (GR:GetMember, GR:GetRoster, GR:GetOnlineMembers), and the re-requests are gone. WorldBuffSync:IsTrustedSender and the WB add-entry autocomplete are likewise library-backed — our world-buff and rank code now makes zero direct guild-roster API calls (the ported Blizzard calendar frames in ClassicCalendar.lua still use their own, unchanged). Location: GuildRankConfirm.lua, WorldBuffSync.lua, WorldBuff.lua.

Changed

  • World-buff entries are restricted to current guild members. The add/edit dialog now only accepts a name that resolves to a current guild member via the roster (one of the autocomplete suggestions); a free-typed or non-member name is rejected. Every entry therefore keys to a canonical, cross-client-consistent key by construction, closing the last path by which a viewer-realm-keyed entry could fragment across peers. Location: WorldBuff.lua, WorldBuffDB.lua.
  • Dedup migration for legacy fragmented keys. WorldBuffDB:Dedupe re-keys every entry through the canonical NormalizeKey and last-writer-wins merges collisions (with a content tie-break byte-identical to the sync merge, so every client keeps the same survivor), collapsing per-realm/per-case duplicates into one row. Runs once when the roster is ready; /ccwb dedup forces it manually. Received entries are re-keyed on arrival (ApplyEntries) so an un-updated peer can't re-fragment a cleaned store. Location: WorldBuffDB.lua, WorldBuffSync.lua.
  • Wire protocol versioned wb:wb2:, with a one-time data reset. v1.6.1 clients operate in a DeltaSync item space disjoint from v1.6.0, so old-format sync traffic lands on items we don't hold and is ignored rather than merged. Because the v1 data was corrupted beyond repair, the first v1.6.1 load discards the entire world-buff store and starts blank (WorldBuffDB:Init wipes ClassicCalendarWBDB.guilds when the _dataFormat marker is below 2, then stamps it — so it runs exactly once); clean data then syncs back from other v1.6.1 peers. Legacy per-character migration is gated off on the v2 format (Migrate returns early), so the old arrays can't re-seed corruption. Location: WorldBuffSync.lua, WorldBuffDB.lua.
  • World Buff window UI polish. Player names and mains display as their canonical Name-Realm (resolved on render, so pre-existing entries show the realm too); the add-entry autocomplete lists full Name-Realm on an opaque, TOOLTIP-strata dropdown (readable on the dark backdrop, no longer clipped behind the dialog); the Player Name column left-justifies under its header via an explicit child FontString (a Button re-centers its own text, which is why it was indented); rows are zebra-striped (the scroll child is now sized to the viewport each render, so rows span the full width instead of collapsing to the 1px child); and hovering a name shows a tooltip with the click actions and a note that a member who has left the guild can only be deleted, not edited. Location: WorldBuff.lua.

Hardening

  • True FNV-1a (no double-mantissa overflow). The hash multiply is now done in 16-bit halves so every intermediate product stays exact, replacing hash * 16777619 which overflowed the 53-bit double mantissa and silently dropped low bits (degraded collision resistance in the convergence-critical roll-up hash). Applied identically to fnvStep/settingChecksum (WorldBuffDB) and contentChecksum (WorldBuffSync) so DB-side and sync-side tie-breaks stay in lockstep. Mirrors LibGuildRoster's fnv1a32. Location: WorldBuffDB.lua, WorldBuffSync.lua.
  • Clock-skew-safe timestamps. Synced lastModified / setAt / wipe-epoch stamps use GetServerTime() (identical on every client) instead of local time(), so LWW ordering and the wipe epoch don't depend on a member's OS-clock skew. Location: WorldBuffDB.lua.
  • Tombstones kept forever. Deleted entries are never garbage-collected, so a deletion can't resurrect from a peer that GC'd on a different schedule, and peers can't diverge on GC timing. GarbageCollect is now a no-op. Location: WorldBuffDB.lua, WorldBuff.lua.
  • /ccwb diagnostics. Counters (getMyHashes calls / reassembles / memo-hits, one-time hash-index builds, inbound/outbound sync), /ccwb log for a timestamped live trace, /ccwb reset to zero counters, and /ccwb dedup to force the duplicate-collapse. Location: WorldBuffSync.lua.

[v1.6.0] (2026-07-04)

New Features

  • Officer "Clear All" for world buffs (guild-wide start-fresh). An officer-only button in the World Buff window (and /calwbclear guild) wipes all world-buff data for the whole guild after a confirmation prompt. Implemented as a synced wipe epoch (WBWipeAt): the timestamp propagates like a setting (LWW), every member clears entries at/before it, and pre-wipe entries are rejected on sync (and skipped by migration) so cleared data can't resurrect from an offline peer. Location: WorldBuffDB.lua, WorldBuffSync.lua, WorldBuff.lua.
  • Sortable columns in the World Buff window. Click a column header (Player Name, Main Name, Date Received, Dropped) to sort by it; click again to reverse direction. The active column shows a sort-direction arrow (Interface\Calendar\MoreArrow — the same icon Blizzard's calendar and FastGuildInvite use), and each header has a hover tooltip. Headers are fixed above the scroll area rather than scrolling with the rows. Location: WorldBuff.lua.

Changed

  • Rebuilt world buff sync on the DeltaSync-1.0 library stack. Replaced the bespoke hash/session/delta protocol (WorldBuffHash.lua, WorldBuffDelta.lua, WorldBuffSession.lua, the old WorldBuffSync.lua, and the dead DataSync.lua) with a thin DeltaSync bridge routed through AceCommQueue-1.0 (throttled sends) and LibGuildRoster-1.0 (identity/trust). New hard dependencies: DeltaSync, AceCommQueue-1.0, GuildRoster.
    • Each of the 4 buff tables plus a guild-settings record is one DeltaSync "item" (wb:rend|hakkar|onyxia|nefarian, wb:settings); entries reconcile per-entry via last-writer-wins on lastModified. Uses the multi-host DS:NewHost API (DeltaSync MINOR 15+) under an isolated AceAddon shell (ClassicCalendarSync) so it can't clobber other DeltaSync consumers on the same client.
  • World buff storage is now account-wide, keyed by guild (ClassicCalendarWBDB), replacing the four per-character positional arrays. Entries are stored as [normalizedPlayerKey] = entry maps (LibGuildRoster-normalized keys) instead of index arrays, eliminating duplicate rows and index/name drift. A one-time migration folds each character's legacy WorldBuff*Data into the guild store on first login. Location: WorldBuffDB.lua.
  • Ship explicit per-flavor TOCs instead of packager-generated multi-version. ClassicCalendar.toc is now Classic Era only (## Interface: 11508); a new ClassicCalendar_BCC.toc carries BCC (## Interface: 20505). .pkgmeta enable-toc-creation is now no. Multi-## Interface-* single TOCs proved unreliable to load on live installs; matches the per-flavor convention used by GuildRoster / FastGuildInvite. Both TOCs must keep the same file load list.

Bug Fixes

  • Fixed dropped status never propagating. The field was written as the string "Yes"/"No" but hashed as tostring(entry.dropped == true), so it always hashed as "false" — toggling it never changed the sync hash. dropped is now a canonical boolean everywhere. Location: WorldBuff.lua, WorldBuffDB.lua.
  • Fixed guild event creation being blocked while the GM is offline. The RestrictGuildEventsToOfficers gate now fails open — members can create guild events unless an officer has explicitly enabled the restriction. The setting rides the DeltaSync relay, so any guildmate holding it can serve it (previously only the setter could answer a request). Location: ClassicCalendar.lua, WorldBuff.lua.
  • Fixed unthrottled comms. World buff messages now route through AceCommQueue-1.0, preventing ChatThrottleLib chunk interleaving / CRC corruption under guild load.

Hardening

  • Deterministic convergence tie-break. Version vectors now carry a content checksum alongside the timestamp, so two edits to the same entry (or setting) in the same second resolve to the same winner on every peer instead of offering forever. The guild-settings hash also excludes setBy (not reconciled by the LWW merge) to avoid the same no-op-resync trap. Location: WorldBuffSync.lua, WorldBuffDB.lua.
  • Anti-grief wipe epoch. A wipe epoch more than a day in the future is rejected, so a modified client can't clear everyone's data and block new entries indefinitely. Migration and the receive path both honor the epoch, so cleared data can't resurrect from an offline peer. Location: WorldBuffDB.lua.
  • World Buff window: frame pooling, key case-folding, roster-load refresh. Table rows are pooled/reused instead of leaking a frame per row on every render/sort/sync; normalized player keys are case-folded so bob/Bob dedupe to one entry; the window refreshes once the guild roster loads so it isn't stuck empty when opened at login. Location: WorldBuff.lua, WorldBuffDB.lua, WorldBuffSync.lua.
  • Guildless edits are rejected with a message instead of silently dropped (world buffs are guild-scoped). Location: WorldBuff.lua.

Removed

  • DataSync.lua, WorldBuffHash.lua, WorldBuffDelta.lua, WorldBuffSession.lua, and the bespoke WorldBuffSync.lua protocol. The XOR-obfuscated CC-SET guild-settings channel is retired in favour of the wb:settings DeltaSync item.

[v1.5.4] (2026-05-05)

Bug Fixes

  • Fixed ZG (Zul'Gurub) and AQ20 (Ruins of Ahn'Qiraj) 3-day lockout schedule
    • Adjusted first reset from January 1 to January 3, 2026
    • Now correctly displays resets on May 3, 6, 9, 12, 15, etc. (matching official schedule)
    • Previously showed incorrect dates: May 1, 4, 7, 10, 13

[v1.5.2] (2026-05-03)

New Features

  • Added "Hide the calendar minimap button" checkbox to General settings in the Options panel
    • Saves and restores across sessions via CCConfig.HideMinimapButton
    • Uses LibDBIcon:Hide/Show to toggle the icon
    • Calendar remains accessible via /cal or /calendar when hidden

[v1.5.1] (2026-04-13)

Bug Fixes

  • Fixed delete event confirmation popup covering half the screen (BUG-024)
    • Replaced oversized StaticPopupDialogs["CALENDAR_DELETE_EVENT"] with a compact custom frame (320×115 px)
    • Supports Escape to cancel, Enter to confirm, and standard OK/Cancel buttons
    • CalendarFrame_PushModal/PopModal preserved via OnShow/OnHide
  • Fixed SetBackdrop nil error on delete confirmation frame
    • Added "BackdropTemplate" inheritance to CalendarDeleteConfirmFrame
    • Same fix applied pre-emptively to CalendarGuildRankConfirmPopup in GuildRankConfirm.lua

[v1.5.0] (2026-04-13)

New Features

  • Invite list right-click menu now shows RSVP options (Confirmed, Standby) directly in the context menu — previously displayed behind a blank flyout arrow
  • Right-click RSVP menu restricted to event creator/moderator only (EventCanEdit()) — non-creators use the existing top RSVP buttons
  • Removed redundant myInviteIndex player scan from CalendarViewEventInviteListScrollFrame_Update

Bug Fixes

  • Fixed invite list #, Rank, and Level sort buttons firing both their own handler and the inherited template handler on each click — added inherit="false" to <OnClick> in ClassicCalendarTemplates.xml
  • Fixed custom sort columns cycling through a redundant third "clear" state — now toggles between ascending and descending only, matching native sort button behavior
  • Fixed Status column header rendering lower than all other column headers — was anchored to inviteList.ScrollBox instead of inviteList

Internal

  • Fixed undefined globals in GuildRankConfirm.lua: GameTooltip_Hide, DONE, CALENDAR_CREATEEVENTFRAME_DEFAULT_TITLE, CalendarGuildRankConfigButton
  • Added nil guard for popup in PopulateAndShowPopup
  • Fixed tabFocusGroup:OnTabPressed nil safety in ClassicCalendar.lua
  • Used _G[] lookup for CalendarCreateEventDivider to resolve linter undefined global

[v1.4.4] (2026-04-10)

Bug Fixes

  • Fixed art type checkbox labels not showing for non-English locales (BUG-023)
    • checkLocale() now iterates over enUS keys so keys absent from other locale tables correctly fall back to English
    • All 9 newly-added art type checkbox labels now display properly regardless of client language

[v1.4.3] (2026-04-04)

Bug Fixes

  • Removed all leftover debug print statements from click handlers and Today View
    • Cleaned up remaining print() calls that were not gated behind ClassicCalendar.debug

[v1.4.2] (2026-04-04)

Bug Fixes

  • Removed leftover debug print from LibDBIcon OnClick handler

[v1.4.1] (2026-03-30)

New Features

  • Calendar frame position now persists across /reload and sessions
    • CalendarFrame saves and restores its position via CCConfig.calendarFramePos
    • Removed hardcoded XML anchor; default position now set in Lua on first load
    • Frame marked movable with clampedToScreen to keep it on screen
  • Today View frame position now persists across /reload and sessions
    • OnDragStop saves position to CCConfig.todayViewPos; restored on PLAYER_LOGIN

[v1.4.0] (2026-03-30)

New Features

  • Today's Events panel — new Today View window showing all events for the current (or navigated) day
    • Holiday banner art displayed matching the main calendar — BORDER texture for non-ONGOING, ARTWORK banner for ONGOING events
    • Prev/Next day arrow navigation buttons in the title strip to move between days without closing the panel
    • Filter dropdown for event category visibility
    • Right-click an event button to open the full context menu (Create Personal Event, Create Guild Event, and event-specific options)
    • Right-click empty content area to open the day-level create menu
  • Consistent gradient background on every calendar day cell
    • EventBackgroundTexture now always rendered on all cells, including holiday-only and empty cells, eliminating the inconsistent look where some cells lacked the gradient
    • CalendarEventBackground added as a permanent overlay in Today View to match the main calendar aesthetic

[v1.3.1] (2026-03-30)

Bug Fixes

  • Fixed debug messages bleeding through without /caldebug enabled (BUG-021)
    • Wrapped all sync and diagnostic print statements behind ClassicCalendar.debug check
    • Affected files: CalendarHelper.lua, WorldBuffSession.lua, WorldBuffSync.lua, WorldBuffHash.lua, WorldBuffDelta.lua
    • User-facing error messages remain visible by default
  • Fixed calendar day cells remaining highlighted after mouse leaves event buttons (BUG-022)
    • Added missing UnlockHighlight() calls to event button OnLeave handlers
    • Prevents visual clutter from accumulated stuck highlights

[v1.3.0] (2026-03-27)

New Features

  • Officer-controlled guild event creation restriction via Options > Officer Settings
  • General tab now shows "Valid Hash" and "Event Creation" status (Yes / No / Unknown)
  • "Create Guild Event" context menu entry hidden for non-officers when restriction is active
  • Right-click minimap button or calendar button to toggle the Options panel directly to the General tab
  • Left and right clicks on calendar/minimap buttons now both toggle open/closed

Bug Fixes

  • Fixed multi-day holiday banner art only displaying on the final day of an event (BUG-008)
    • ShouldDisplayEventOnCalendar now returns true for ONGOING sequence days when displayBanner=true
  • Fixed Love is in the Air and Winter's Veil textures returning nil due to incorrect texture path casing (BUG-008)
  • Added individual on/off toggles for all 11 holiday banner art types in Options > Art (BUG-008)
    • All checkboxes persist through /reload; Fireworks Spectacular only appears in Season of Discovery
  • Added Winter's Veil 2026–2027 calendar entry (BUG-008)
  • Fixed Fishing Extravaganza starting on Monday instead of Sunday (BUG-008)
  • Removed duplicate Noblegarden entry causing date overlap (BUG-008)
  • Optimized version detection — isClassicEra and isSoD are now cached globally at load time (BUG-008)

[v1.2.2] (2026-03-26)

Bug Fixes

  • Fixed string vs number comparison error in officer rank checking (BUG-005)
    • Added tonumber() conversion before all rank comparisons; GetGuildInfo returns rank as a string, not a number
    • Affected: ClassicCalendar_Options.lua, WorldBuff.lua, WorldBuffSync.lua, ClassicCalendar.lua, DataSync.lua
  • Fixed FontString OnUpdate script error spamming the UI error log (BUG-006)
    • FontStrings do not support OnUpdate; replaced with invisible Frame intermediaries that update the FontStrings
    • Eliminates 21+ repeated errors when opening the Options panel
  • Fixed incorrect GetGuildInfo return index causing all officer checks to fail (BUG-007)
    • Changed select(2, GetGuildInfo(...))select(3, ...) to retrieve the numeric rank index instead of the rank name string
    • Guild Master and officers can now broadcast guild settings correctly

[v1.2.1] (2026-03-16)

Bug Fixes

  • Fixed debug mode status display in /calwbsync
  • Fixed integer overflow in FNV-1a hash computation (BUG-004)
  • Persist debug mode state across /reload
  • Improved debug diagnostics output for WorldBuff sync

[v1.2.0] (2026-03-16)

New Features

  • Added /calwbsync command for manual WorldBuff sync trigger
  • Enabled WorldBuffSync debug messages via /caldebug

Bug Fixes

  • Added nil checks for ClassicCalendar.debug across all WorldBuff modules
  • Fixed function argument count and type issues in sync modules

[v1.1.12] (2026-03-16)

Changes

  • Complete WorldBuff Sync rewrite with delta-sync P2P system (Protocol v4)
  • 96% traffic reduction via hash-based pull protocol
  • Session management: limits concurrent syncs (3 inbound / 3 outbound)
  • Self-healing mesh via periodic heartbeat for eventual consistency
  • Fixed critical DataSync issues and improved sync reliability

New Files

  • WorldBuffHash.lua - FNV-1a hash computation and tracking
  • WorldBuffDelta.lua - Delta computation and application
  • WorldBuffSession.lua - P2P session manager
  • WorldBuffSync.lua - Protocol coordinator and message router

Breaking Changes

  • No backward compatibility with v1.1.x clients (protocol v3)
  • All guild members must upgrade for sync to function

[v1.1.11] (2026-02-26)

Bug Fixes

  • Fixed deletedDate/deletedTime field inconsistency causing garbage collection failure in DataSync
  • Fixed direct table reference bleeding in SendGuildSync() — now creates shallow copies before sending
  • Implemented separate communication prefixes per buff table (CCWB_RH, CCWB_HH, CCWB_OH, CCWB_NH) for complete isolation
  • Added 5-minute cooldown on GUILD_ROSTER_UPDATE to prevent spam (~90% network traffic reduction)
  • Added prefix-to-buffType validation layer
  • Rejected wipe commands when guild roster not yet loaded (closes exploit window)
  • Skipped processing own addon messages to prevent double-processing by officers
  • Bumped sync protocol to v3 (backward compatible with v2)
  • Moved BUG_TRACKER.md, FEATURE_TRACKER.md, developer_log.md to docs/ folder

[v1.1.10] (2026-02-01)

Changes

  • Moved world buff data to per-character SavedVariables to prevent data bleed between characters

[v1.1.9] (2026-01-27)

Changes

  • Added Darkmoon Faire schedule for 2026

[v1.1.8] (2026-01-22)

Changes

  • Guild Leader is now the authoritative source of truth for World Buff scheduler data
  • Prevents data corruption from non-GM characters overwriting GM data

[v1.1.7] (2026-01-22)

Changes

  • Updated .pkgmeta to exclude development documentation (BUG_TRACKER.md, FEATURE_TRACKER.md, developer_log.md) from CurseForge release packages

[v1.1.6] (2026-01-22)

Bug Fixes

  • Fixed BUG-002: World Buff data corruption — deep copy and table separation to prevent cross-contamination

[v1.1.5] (2025-11-20)

Bug Fixes

  • Fixed BUG-001: Intermittent BG event display issue

[v1.1.4] (2026-01-19)

Changes

  • Updated holiday dates

[v1.1.3] (2025-12-04)

Changes

  • Updated .pkgmeta to include calendar-helper dependency

[v1.1.2] (2025-12-03)

Changes

  • WB sync now only accepts data newer than the last wipe timestamp
  • Improved wipe function reliability

[v1.1.1] (2025-11-25)

Changes

  • Added function to wipe corrupted world buff data
  • Split WB sync into 4 separate messages per buff type to stop cross-table data contamination

[v1.1.0] (2025-11-19)

New Features

  • Added CalendarHelper as a dependency for Discord Raid Helper event import

[v1.0.0] (2025-10-01)

New Features

  • Added duplicate event detection to prevent creating duplicate raid events from CalendarHelper data
  • CalendarHelper integration stable

[v0.9.6] (2025-10-30)

Changes

  • Updated world buff event creation logic

[v0.9.5] (2025-10-26)

Changes

  • Updated world buff data table logic

[v0.9.4] (2025-10-25)

Bug Fixes

  • Fixed Lua errors in ClassicCalendar.xml

[v0.9.3] (2025-10-25)

Changes

  • Hid debug print statements behind debug flags

[v0.9.2] (2025-10-25)

Bug Fixes

  • Fixed bug in hide/show filters for world buff events

[v0.9.1] (2025-10-25)

Changes

  • Updated display logic and spacing for player names in the world buff window

[v0.9.0] (2025-10-24)

Changes

  • All world buff window buttons now match the calendar button style

[v0.8.8] (2025-09-28)

Changes

  • Removed Brewfest (not present in Classic Era)

[v0.8.6] (2025-09-18)

Changes

  • Updated December Darkmoon Faire schedule

[v0.8.5] (2025-09-18)

Changes

  • Hard-coded Darkmoon Faire event dates

[v0.8.4] (2025-09-17)

Changes

  • Added /caldebug debug slash command

[v0.8.3] (2025-09-17)

Changes

  • Updated calendar to display a full year of events

[v0.8.2] (2025-09-15)

Changes

  • Removed unused textures
  • Miscellaneous bug fixes

[v0.8.1] (2025-09-14)

Changes

  • Added deployment automation
  • Added minimap button

v0.7.0beta (2024-09-26)

Full Changelog Previous Releases

  • Fix bugs introduced by 1.15.4

This mod has no related projects