Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 7 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,23 +85,18 @@ Things to be aware of when running this on a live server:
`Interval`, the next automatic pass is pushed back each time and may never
fire — use `.bgevents run` to trigger one on demand, or avoid reloading
right before a pass is due.
- **Opt-out is stored per character via the core PlayerSettings system**
(`source = "mod-bg-auto-queue"`, index 0; `1` = opted out). The core loads it
on login, saves it on logout, and deletes it when the character is deleted —
the module keeps no table of its own. **This requires the core config
`EnablePlayerSettings = 1` for the opt-out to persist across logins.** With it
`0` (the core default), `.bgevents off` still works but only for the current
session, and a warning is logged at startup.
- **Opt-out is stored account-wide in a custom database table**
(`mod_bg_auto_queue_account_settings`). The setting applies to all characters
on the same account and persists across logins.

## Installation

1. Clone this folder into `modules/mod-bg-auto-queue/` of your AzerothCore source.
2. Re-run CMake and rebuild the worldserver.
3. Copy `mod-bg-auto-queue.conf.dist` to `mod-bg-auto-queue.conf` in your
worldserver's configuration directory and adjust as needed.
4. For per-character opt-out to persist across logins, set the core config
`EnablePlayerSettings = 1` (see the dependency note in the conf). The module
creates no database tables of its own.
4. Run the SQL file in `data/sql/db-characters/base/mod_bg_auto_queue_account_settings.sql`
against your characters database to create the required table.

## Configuration

Expand All @@ -121,8 +116,8 @@ All options are documented in `conf/mod-bg-auto-queue.conf.dist`:

## Commands

- `.bgevents on` — opt the current character back into battleground events.
- `.bgevents off` — opt the current character out (future passes only; does not dequeue an existing queue).
- `.bgevents on` — opt the current account back into battleground events.
- `.bgevents off` — opt the current account out (future passes only; does not dequeue an existing queue).
- `.bgevents` — *(no argument)* show the opt-in state and the time until the next scheduled pass.
- `.bgevents run` — *(GM, console-capable)* run a queue pass immediately, even when the automatic schedule is disabled. Does not reset the periodic timer.

Expand Down
8 changes: 3 additions & 5 deletions conf/mod-bg-auto-queue.conf.dist
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@
###################################################################################################
# mod-bg-auto-queue
#
# DEPENDENCY: per-character ".bgevents" opt-out is stored via the core
# PlayerSettings system, which only persists across logins when the core
# config "EnablePlayerSettings" is set to 1. With it 0 (the core default),
# ".bgevents off" still works but lasts only for the current session, and a
# warning is logged at startup. This module does not change the core config.
# DEPENDENCY: Account-wide ".bgevents" opt-out is stored in the custom
# `mod_bg_auto_queue_account_settings` database table. Ensure you run the SQL migration on your
# characters database before using the module.
#
# NOTE: when no pool candidate can reach its minimum player count for a
# bracket, the pass still queues the bracket into the smallest battleground
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CREATE TABLE IF NOT EXISTS `mod_bg_auto_queue_account_settings` (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmmh the whole idea behind using playersettings was that we would avoid a new table

`account_id` INT UNSIGNED NOT NULL,
`opted_out` TINYINT UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`account_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2 changes: 1 addition & 1 deletion docs/how-it-works.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ premade party with your group.

## Opting out (and back in)

If you'd rather never be auto-queued, you can turn it off for your character:
If you'd rather never be auto-queued, you can turn it off for your account:

- **`.bgevents off`** — stop being auto-queued (you'll no longer get pop-ups).
- **`.bgevents on`** — opt back in.
Expand Down
46 changes: 35 additions & 11 deletions src/BgAutoQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "Config.h"
#include "Containers.h"
#include "DBCStores.h"
#include "DatabaseEnv.h"
#include "DisableMgr.h"
#include "LFGMgr.h"
#include "Log.h"
Expand Down Expand Up @@ -185,13 +186,7 @@ void BgAutoQueue::LoadConfig()
LOG_INFO("module", "mod-bg-auto-queue: enabled={}, levels=[{}-{}], configured pool size={}, interval={} min, initialDelay={} s, warningLead={} s, crossFaction={}, cfbg={}, evenTeamsStrict={}, skipGM={}, skipAFK={}, skipAuras={}.",
_enabled, _levelMin, _levelMax, _poolRaw.size(), intervalMin, initialDelaySec, warningLeadSec, _crossFaction, _cfbgEnabled, _evenTeamsStrict, _skipGameMasters, _skipAfk, _skipAuras.size());

// Opt-out is stored via the core PlayerSettings system, which only persists
// across logins when EnablePlayerSettings is on. Without it, .bgevents
// opt-out still works but only for the current session.
if (!sWorld->getBoolConfig(CONFIG_PLAYER_SETTINGS_ENABLED))
LOG_WARN("module", "mod-bg-auto-queue: EnablePlayerSettings is 0; "
".bgevents opt-out works only for the current session and will not "
"persist across logins until an administrator sets EnablePlayerSettings = 1.");
LoadAccountSettings();
}

void BgAutoQueue::ResolvePool()
Expand Down Expand Up @@ -248,14 +243,28 @@ void BgAutoQueue::ResolvePool()

bool BgAutoQueue::IsOptedOut(Player* player) const
{
// GetPlayerSetting is non-const (it lazily creates a zero-default entry),
// but the constness here is on BgAutoQueue, not on the Player* argument.
return player->GetPlayerSetting("mod-bg-auto-queue", BG_AUTO_QUEUE_SETTING_OPT_OUT).IsEnabled();
if (!player || !player->GetSession())
return false;

return _optedOutAccounts.find(player->GetSession()->GetAccountId()) != _optedOutAccounts.end();
}

void BgAutoQueue::SetOptOut(Player* player, bool optedOut)
{
player->UpdatePlayerSetting("mod-bg-auto-queue", BG_AUTO_QUEUE_SETTING_OPT_OUT, optedOut ? 1u : 0u);
if (!player || !player->GetSession())
return;

uint32 const accountId = player->GetSession()->GetAccountId();
if (optedOut)
{
_optedOutAccounts.insert(accountId);
CharacterDatabase.Execute(Acore::StringFormat("REPLACE INTO mod_bg_auto_queue_account_settings (account_id, opted_out) VALUES ({}, 1)", accountId));
}
else
{
_optedOutAccounts.erase(accountId);
CharacterDatabase.Execute(Acore::StringFormat("DELETE FROM mod_bg_auto_queue_account_settings WHERE account_id = {}", accountId));
}
}

bool BgAutoQueue::IsLevelEligible(uint8 level) const
Expand Down Expand Up @@ -1096,3 +1105,18 @@ void BgAutoQueue::BroadcastWarning() const

LOG_DEBUG("module", "mod-bg-auto-queue: broadcast warning sent to {} player(s).", sent);
}

void BgAutoQueue::LoadAccountSettings()
{
_optedOutAccounts.clear();
QueryResult result = CharacterDatabase.Query("SELECT account_id FROM mod_bg_auto_queue_account_settings WHERE opted_out = 1");
if (result)
{
do
{
Field* fields = result->Fetch();
uint32 accountId = fields[0].Get<uint32>();
_optedOutAccounts.insert(accountId);
} while (result->NextRow());
}
}
14 changes: 7 additions & 7 deletions src/BgAutoQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,14 @@

#include <array>
#include <string>
#include <unordered_set>
#include <vector>

class Battleground;
class Player;
struct PvPDifficultyEntry;

// PlayerSettings layout for this module. source = "mod-bg-auto-queue".
enum BgAutoQueueSetting
{
BG_AUTO_QUEUE_SETTING_OPT_OUT = 0 // value: 0 = opted in (default), 1 = opted out
};
// Opt-out settings are stored account-wide in a custom database table.

class BgAutoQueue
{
Expand All @@ -33,8 +30,7 @@ class BgAutoQueue

bool IsEnabled() const { return _enabled; }

// Opt-out is stored as a per-character core PlayerSetting; these are thin
// wrappers over Player::GetPlayerSetting/UpdatePlayerSetting.
// Opt-out is stored account-wide.
bool IsOptedOut(Player* player) const;
void SetOptOut(Player* player, bool optedOut);

Expand Down Expand Up @@ -265,6 +261,8 @@ class BgAutoQueue
// at config-load time, and may change on .reload). Cheap: _poolRaw is tiny.
void ResolvePool();

void LoadAccountSettings();

bool _enabled = true;
uint32 _levelMin = 10;
uint32 _levelMax = 79;
Expand All @@ -281,6 +279,8 @@ class BgAutoQueue
std::vector<uint32> _skipAuras; // aura ids that exclude a player from a pass
std::string _broadcastMessage;

std::unordered_set<uint32> _optedOutAccounts;

uint32 _elapsedMs = 0;
bool _warningSent = false;
bool _firstPass = true;
Expand Down
8 changes: 4 additions & 4 deletions src/cs_bg_auto_queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,17 @@ class bg_auto_queue_commandscript : public CommandScript
sBgAutoQueue->SetOptOut(player, !*enable);

if (*enable)
handler->SendSysMessage("Battleground events enabled for your character.");
handler->SendSysMessage("Battleground events enabled for your account.");
else
handler->SendSysMessage("Battleground events disabled for your character. You will not be auto-queued. Use .bgevents on to opt back in.");
handler->SendSysMessage("Battleground events disabled for your account. You will not be auto-queued. Use .bgevents on to opt back in.");

return true;
}

if (sBgAutoQueue->IsOptedOut(player))
handler->SendSysMessage("Battleground events are currently DISABLED for your character.");
handler->SendSysMessage("Battleground events are currently DISABLED for your account.");
else
handler->SendSysMessage("Battleground events are currently ENABLED for your character.");
handler->SendSysMessage("Battleground events are currently ENABLED for your account.");

uint32 msToNext = sBgAutoQueue->GetTimeUntilNextPass();
if (sBgAutoQueue->IsEnabled() && msToNext > 0)
Expand Down
Loading