add ability to disable rare announcements per account; closes #576

This commit is contained in:
Martin Michelsen
2024-10-20 16:05:29 -07:00
parent c61a13f62e
commit 086b2d411a
6 changed files with 90 additions and 12 deletions
+26 -10
View File
@@ -136,6 +136,7 @@ phosg::JSON BBLicense::json() const {
Account::Account(const phosg::JSON& json)
: account_id(0),
flags(0),
user_flags(0),
ban_end_time(0),
ep3_current_meseta(0),
ep3_total_meseta_earned(0),
@@ -222,6 +223,7 @@ Account::Account(const phosg::JSON& json)
}
this->flags = json.get_int("Flags", 0);
this->user_flags = json.get_int("UserFlags", 0);
this->ban_end_time = json.get_int("BanEndTime", 0);
this->last_player_name = json.get_string("LastPlayerName", "");
this->auto_reply_message = json.get_string("AutoReplyMessage", "");
@@ -278,6 +280,7 @@ phosg::JSON Account::json() const {
{"XBLicenses", std::move(xb_json)},
{"BBLicenses", std::move(bb_json)},
{"Flags", this->flags},
{"UserFlags", this->user_flags},
{"BanEndTime", this->ban_end_time},
{"LastPlayerName", this->last_player_name},
{"AutoReplyMessage", this->auto_reply_message},
@@ -300,34 +303,34 @@ void Account::print(FILE* stream) const {
} else if (this->flags == static_cast<uint32_t>(Flag::MODERATOR)) {
flags_str = "MODERATOR";
} else {
if (this->flags & static_cast<uint32_t>(Flag::KICK_USER)) {
if (this->check_flag(Flag::KICK_USER)) {
flags_str += "KICK_USER,";
}
if (this->flags & static_cast<uint32_t>(Flag::BAN_USER)) {
if (this->check_flag(Flag::BAN_USER)) {
flags_str += "BAN_USER,";
}
if (this->flags & static_cast<uint32_t>(Flag::SILENCE_USER)) {
if (this->check_flag(Flag::SILENCE_USER)) {
flags_str += "SILENCE_USER,";
}
if (this->flags & static_cast<uint32_t>(Flag::CHANGE_EVENT)) {
if (this->check_flag(Flag::CHANGE_EVENT)) {
flags_str += "CHANGE_EVENT,";
}
if (this->flags & static_cast<uint32_t>(Flag::ANNOUNCE)) {
if (this->check_flag(Flag::ANNOUNCE)) {
flags_str += "ANNOUNCE,";
}
if (this->flags & static_cast<uint32_t>(Flag::FREE_JOIN_GAMES)) {
if (this->check_flag(Flag::FREE_JOIN_GAMES)) {
flags_str += "FREE_JOIN_GAMES,";
}
if (this->flags & static_cast<uint32_t>(Flag::DEBUG)) {
if (this->check_flag(Flag::DEBUG)) {
flags_str += "DEBUG,";
}
if (this->flags & static_cast<uint32_t>(Flag::CHEAT_ANYWHERE)) {
if (this->check_flag(Flag::CHEAT_ANYWHERE)) {
flags_str += "CHEAT_ANYWHERE,";
}
if (this->flags & static_cast<uint32_t>(Flag::DISABLE_QUEST_REQUIREMENTS)) {
if (this->check_flag(Flag::DISABLE_QUEST_REQUIREMENTS)) {
flags_str += "ALWAYS_ENABLE_CHAT_COMMANDS,";
}
if (this->flags & static_cast<uint32_t>(Flag::IS_SHARED_ACCOUNT)) {
if (this->check_flag(Flag::IS_SHARED_ACCOUNT)) {
flags_str += "IS_SHARED_ACCOUNT,";
}
}
@@ -339,6 +342,19 @@ void Account::print(FILE* stream) const {
fprintf(stream, " Flags: %08" PRIX32 " (%s)\n", this->flags, flags_str.c_str());
}
if (this->user_flags) {
string user_flags_str = "";
if (this->check_user_flag(UserFlag::DISABLE_DROP_NOTIFICATION_BROADCAST)) {
user_flags_str += "DISABLE_DROP_NOTIFICATION_BROADCAST,";
}
if (user_flags_str.empty()) {
user_flags_str = "none";
} else if (phosg::ends_with(user_flags_str, ",")) {
user_flags_str.pop_back();
}
fprintf(stream, " User flags: %08" PRIX32 " (%s)\n", this->user_flags, user_flags_str.c_str());
}
if (this->ban_end_time) {
string time_str = phosg::format_time(this->ban_end_time);
fprintf(stream, " Banned until: %" PRIu64 " (%s)\n", this->ban_end_time, time_str.c_str());
+17
View File
@@ -76,11 +76,15 @@ struct Account {
UNUSED_BITS = 0x70FFFF00,
// clang-format on
};
enum class UserFlag : uint32_t {
DISABLE_DROP_NOTIFICATION_BROADCAST = 0x00000001,
};
// account_id is also the account's guild card number
uint32_t account_id = 0;
uint32_t flags = 0;
uint32_t user_flags = 0;
uint64_t ban_end_time = 0; // 0 = not banned
std::string last_player_name;
std::string auto_reply_message;
@@ -124,6 +128,19 @@ struct Account {
this->flags = static_cast<uint32_t>(mask);
}
[[nodiscard]] inline bool check_user_flag(UserFlag flag) const {
return !!(this->user_flags & static_cast<uint32_t>(flag));
}
inline void set_user_flag(UserFlag flag) {
this->user_flags |= static_cast<uint32_t>(flag);
}
inline void clear_user_flag(UserFlag flag) {
this->user_flags &= (~static_cast<uint32_t>(flag));
}
inline void toggle_user_flag(UserFlag flag) {
this->user_flags ^= static_cast<uint32_t>(flag);
}
void print(FILE* stream) const;
};
+8
View File
@@ -2088,6 +2088,13 @@ static void proxy_command_switch_assist(shared_ptr<ProxyServer::LinkedSession> s
ses->config.check_flag(Client::Flag::SWITCH_ASSIST_ENABLED) ? "enabled" : "disabled");
}
static void server_command_toggle_rare_announce(shared_ptr<Client> c, const std::string&) {
c->login->account->toggle_user_flag(Account::UserFlag::DISABLE_DROP_NOTIFICATION_BROADCAST);
c->login->account->save();
send_text_message_printf(c, "$C6Rare announcements\n%s for your\nitems",
c->login->account->check_user_flag(Account::UserFlag::DISABLE_DROP_NOTIFICATION_BROADCAST) ? "disabled" : "enabled");
}
static void server_command_dropmode(shared_ptr<Client> c, const std::string& args) {
auto l = c->require_lobby();
check_is_game(l, true);
@@ -2580,6 +2587,7 @@ static const unordered_map<string, ChatCommandDefinition> chat_commands({
{"$allevent", {server_command_lobby_event_all, nullptr}},
{"$ann", {server_command_announce, nullptr}},
{"$ann!", {server_command_announce_mail, nullptr}},
{"$announcerares", {server_command_toggle_rare_announce, nullptr}},
{"$arrow", {server_command_arrow, proxy_command_arrow}},
{"$auction", {server_command_auction, proxy_command_auction}},
{"$ax", {server_command_ax, nullptr}},
+2 -1
View File
@@ -2071,7 +2071,8 @@ static void on_pick_up_item_generic(
}
}
if (fi->flags & 0x1000) {
if (!c->login->account->check_user_flag(Account::UserFlag::DISABLE_DROP_NOTIFICATION_BROADCAST) &&
(fi->flags & 0x1000)) {
uint32_t pi = fi->data.primary_identifier();
bool should_send_game_notif, should_send_global_notif;
if (is_v1_or_v2(c->version()) && (c->version() != Version::GC_NTE)) {
+36 -1
View File
@@ -362,11 +362,37 @@ uint32_t parse_account_flags(const string& flags_str) {
return ret;
}
uint32_t parse_account_user_flags(const string& user_flags_str) {
try {
size_t end_pos = 0;
uint32_t ret = stoul(user_flags_str, &end_pos, 16);
if (end_pos == user_flags_str.size()) {
return ret;
}
} catch (const exception&) {
}
uint32_t ret = 0;
auto tokens = phosg::split(user_flags_str, ',');
for (const auto& token : tokens) {
string token_upper = phosg::toupper(token);
if (token_upper == "NONE") {
// Nothing to do
} else if (token_upper == "DISABLE_DROP_NOTIFICATION_BROADCAST") {
ret |= static_cast<uint32_t>(Account::UserFlag::DISABLE_DROP_NOTIFICATION_BROADCAST);
} else {
throw runtime_error("invalid user flag name: " + token_upper);
}
}
return ret;
}
CommandDefinition c_add_account(
"add-account", "add-account [PARAMETERS...]\n\
Add an account to the server. <parameters> is some subset of:\n\
id=ACCOUNT-ID: preferred account ID in hex (optional)\n\
flags=FLAGS: behaviors and permissions for the account (see below)\n\
user-flags=FLAGS: user-set behaviors for the account\n\
ep3-current-meseta=MESETA: Episode 3 Meseta value\n\
ep3-total-meseta=MESETA: Episode 3 total Meseta ever earned\n\
temporary: marks the account as temporary; it is not saved to disk and\n\
@@ -405,6 +431,8 @@ CommandDefinition c_add_account(
account->is_temporary = true;
} else if (phosg::starts_with(token, "flags=")) {
account->flags = parse_account_flags(token.substr(6));
} else if (phosg::starts_with(token, "user-flags=")) {
account->user_flags = parse_account_user_flags(token.substr(11));
} else {
throw invalid_argument("invalid account field: " + token);
}
@@ -418,7 +446,8 @@ CommandDefinition c_update_account(
Update an existing license. ACCOUNT-ID (8 hex digits) specifies which\n\
account to update. The options are similar to the add-account command:\n\
flags=FLAGS: sets behaviors and permissions for the account (same as\n\
with add-account)\n\
add-account)\n\
user-flags=FLAGS: sets behaviors for the account (same as add-account)\n\
ban-duration=DURATION: bans this account for the specified duration; the\n\
duration should be of the form 3d, 2w, 1mo, or 1y\n\
unban: clears any existing ban from this account\n\
@@ -441,6 +470,7 @@ CommandDefinition c_update_account(
int64_t new_ep3_current_meseta = -1;
int64_t new_ep3_total_meseta = -1;
int64_t new_flags = -1;
int64_t new_user_flags = -1;
uint8_t new_is_temporary = 0xFF;
int64_t new_ban_duration = -1;
for (const string& token : tokens) {
@@ -454,6 +484,8 @@ CommandDefinition c_update_account(
new_is_temporary = 0;
} else if (phosg::starts_with(token, "flags=")) {
new_flags = parse_account_flags(token.substr(6));
} else if (phosg::starts_with(token, "user-flags=")) {
new_user_flags = parse_account_user_flags(token.substr(11));
} else if (token == "unban") {
new_ban_duration = 0;
} else if (phosg::starts_with(token, "ban-duration=")) {
@@ -492,6 +524,9 @@ CommandDefinition c_update_account(
if (new_flags >= 0) {
account->flags = new_flags;
}
if (new_user_flags >= 0) {
account->user_flags = new_user_flags;
}
if (new_is_temporary != 0xFF) {
account->is_temporary = new_is_temporary;
}