TDX VotePlus
Changelog
Version history and release notes for TDX VotePlus.
All notable changes to TDX VotePlus are documented here. Versions are listed newest-first.
v1.2.16 (Latest)
- Fixed vote parties only firing on one server in a shared-DB cluster. The original v1.2.6 design used an atomic compare-and-subtract so exactly one server wins the threshold-crossing race, but never wired the cross-server propagation that was supposed to follow — peer servers' refresh task only synced the counter value, never fired
trigger()locally. Result: only the winning server's online players got the broadcast + rewards. If MySQL latency was asymmetric, one backend could lose the race every time (matches the "kiwi never triggers" report) total_partiesis now the cross-server fire signal. When any server's refresh task detects the counter going up since its last local fire, it runstrigger()so its players see the broadcast + get rewards too- Per-server CAS dedup via
lastFiredTotalPartiesAtomicLong so the winning server doesn't double-fire (once fromincrement, once from its own refresh) - Startup snapshot — first refresh after enable seeds
lastFiredTotalPartieswithout replaying historical parties as fresh celebrations - Lag-collapse — if multiple parties happened between refreshes, players see one celebration rather than a flurry; the underlying
total_partiescounter is still accurate for placeholders / leaderboards
v1.2.15
- Fixed
/voteplus archive <period> confirmrefusing to run whenmonthly-rewards.enabled: false. Archive (writing history + bulk-resetting the leaderboard) is independent of reward distribution — a tracking-only server should still be able to close out past periods cleanly. The check is now decoupled: archive + bulk reset always run; rewards distribution + winner broadcast only fire when rewards are enabled - The auto-rollover hourly check still respects
enabled: false(so users who deliberately disabled the system don't get surprise side effects)
v1.2.14
- Fixed the Vote Leaderboard not rolling over to the new month. The per-vote rollover in
VoteService.applyCounterUpdateonly resets a single player'smonthly_voteson their first vote of the new period, so the leaderboard kept showing last-month's standings for any player who hadn't voted yet - New
DataManager.resetAllMonthlyVotes(newMonthKey)runs once per period change and bulk-resets every row'smonthly_votesto 0 + stampslast_monthly_keywith the new period - True past-period standings are now reconstructed from the append-only
votestable viaaggregateMonthlyTopFromVotes, not the liveplayers.monthly_votescolumn. So archive + rewards work correctly even days after rollover, when fast voters have already triggered their per-row reset - Per-period idempotency markers (
monthly.archived_<period>,monthly.rewards_distributed_<period>) prevent double-distribution if the rollover is re-run after a crash or a duplicate/voteplus archiveinvocation - New
/voteplus archive <period> confirmadmin command for catch-up. Reconstructs the period's top-N from votes, archives to history, distributes rewards (online + offline-queued), bulk-resets monthly counters - Offline winners are no longer skipped. Each command-type reward is queued in the new
pending_rewardstable and replayed on the winner's next join. Non-command rewards (items, messages, fireworks) are still skipped for offline winners — they need a live Player at apply time - New
pending_rewardstable with a uuid index. SQLite serialises drains through its lock; MySQL usesSELECT … FOR UPDATEso two backends sharing one DB can't both claim the same queue when a player joins both at once
v1.2.13
- Renamed the "Next Monthly Rewards" card in the Vote Leaderboard GUI to "Top Monthly Voters" with shorter "Reset in" lore
v1.2.12
- Fixed repeating milestones (
one-time: false) firing on every vote past the threshold instead of once per period - Daily / weekly / monthly key changes and streak breaks now clear the matching claims so repeating milestones fire again on the next period
one-time: truemilestones still stay claimed across rollovers as configured
v1.2.11
- Cleaned up
vote-rewards.ymlcomment text (configs-only, no code change)
v1.2.10
- Suppressed the public
vote.broadcastfor replayed offline votes by default, so a multi-day offline voter rejoining no longer dumps a wall of "Player just voted!" lines into chat - New
offline-queue.broadcast-on-claimkey invote-rewards.yml(defaultfalse; settrueto broadcast every replayed vote like real-time votes) - Real-time votes still honour the top-level
broadcastswitch - Personal reward messages, counters, streaks, milestones, and vote-party progress on replayed votes are unaffected
v1.2.9
- New
/voteplus offline [player]admin subcommand for diagnosing missing votes; permissiontdxvoteplus.admin.debug - Always-on
[VotifierHook] Received vote:log line on every incoming vote - Debug-gated
[VoteService]pipeline trace covering UUID resolution, online vs offline path, and the target table on queue insert - "Queued offline vote for …" log line no longer requires debug mode
- New
DatabaseProviderdiagnostics:dumpOfflineQueue,countAllOfflineVotes,offlineQueueTableName
v1.2.8
- Fixed offline votes silently lost when a player's name had fallen out of the server's
usercache.json VoteService.resolveUuidnow consults theplayerstable by name first, so new rows store under the player's real Mojang UUIDPlayerJoinListenerandClaimMenurepair existing orphaned rows on next login via a two-pronged UUID/name lookupstorage.ymlnow documents the per-server-id vs Votifier-forwarding interaction
v1.2.7
- New optional
mysql.server-idfield for per-server player data isolation when multiple servers share one MySQL database - Scoped tables:
players,votes,offline_queue,monthly_history - Shared table:
metadata, so the vote-party counter stays global across the cluster - Startup banner shows
(shared tables)or(server-id 'survival')so the mode is visible at a glance - Config-version bumped 7 to 8, auto-merged into existing installs
v1.2.6
- Fixed the main menu "Next Milestone" card showing a streak milestone while the Milestones GUI showed a non-streak one
- Fixed vote-party counter drift across servers sharing one MySQL DB; the counter now uses DB-side atomic increment with compare-and-subtract for threshold crossing
- 5-second background refresh task so peer servers see the shared counter move between votes
v1.2.5
- Fixed
IncompatibleClassChangeErroron Paper 1.20.4 caused byInventoryViewbeing a class in 1.20.x but an interface in 1.21+; routed click handling throughevent.getInventory()instead ofevent.getView().getTopInventory()
v1.2.4
- Filtered streak rewards out of the Milestones GUI
- Made milestone item lore configurable via
lore:field on each milestone entry - Fixed duplicate-clock bug in Streaks GUI
- Hidden enchant glints and attribute modifiers via
ItemFlag.values() - Renamed
gui_menus/toguis/(with one-time folder migration)
v1.2.3
- Leaderboard hopper filter
- Merged Milestones and Milestone Rewards GUIs into one screen
- Dropped
material/slotfromvote-sites.yml - Fixed 1.20.x prefix shadow tags