From 2aae90e65a11cbc30fb5c5999c7369c30725572b Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Sat, 9 Mar 2024 09:45:20 -0800 Subject: [PATCH] add option to use game creator section ID --- src/ItemCreator.cc | 18 ++++++++++-------- src/ItemCreator.hh | 3 +++ src/Lobby.cc | 14 ++++++++++---- src/Lobby.hh | 30 ++++++++++++++++-------------- src/ReceiveCommands.cc | 4 ++++ src/ServerState.cc | 1 + src/ServerState.hh | 1 + system/config.example.json | 12 +++++++++++- tests/config.json | 2 ++ 9 files changed, 58 insertions(+), 27 deletions(-) diff --git a/src/ItemCreator.cc b/src/ItemCreator.cc index 54fc4f52..e3cadf59 100644 --- a/src/ItemCreator.cc +++ b/src/ItemCreator.cc @@ -50,14 +50,16 @@ void ItemCreator::set_random_crypt(shared_ptr new_random_crypt } void ItemCreator::set_section_id(uint8_t new_section_id) { - this->section_id = new_section_id; - this->log.prefix = string_printf("[ItemCreator:%s/%s/%s/%c/%hhu] ", - name_for_enum(stack_limits->version), - abbreviation_for_episode(episode), - abbreviation_for_mode(mode), - abbreviation_for_difficulty(difficulty), - this->section_id); - this->pt = common_item_set->get_table(this->episode, this->mode, this->difficulty, this->section_id); + if (this->section_id != new_section_id) { + this->section_id = new_section_id; + this->log.prefix = string_printf("[ItemCreator:%s/%s/%s/%c/%hhu] ", + name_for_enum(stack_limits->version), + abbreviation_for_episode(episode), + abbreviation_for_mode(mode), + abbreviation_for_difficulty(difficulty), + this->section_id); + this->pt = common_item_set->get_table(this->episode, this->mode, this->difficulty, this->section_id); + } } bool ItemCreator::are_rare_drops_allowed() const { diff --git a/src/ItemCreator.hh b/src/ItemCreator.hh index 7c6c3533..18f56944 100644 --- a/src/ItemCreator.hh +++ b/src/ItemCreator.hh @@ -52,6 +52,9 @@ public: inline void set_restrictions(std::shared_ptr restrictions) { this->restrictions = restrictions; } + inline uint8_t get_section_id() const { + return this->section_id; + } void set_section_id(uint8_t new_section_id); private: diff --git a/src/Lobby.cc b/src/Lobby.cc index f1af79b6..b4c79e82 100644 --- a/src/Lobby.cc +++ b/src/Lobby.cc @@ -264,10 +264,13 @@ void Lobby::create_item_creator() { void Lobby::change_section_id() { if (this->item_creator) { uint8_t new_section_id = this->effective_section_id(); - this->item_creator->set_section_id(new_section_id); - for (const auto& c : this->clients) { - if (c && c->config.check_flag(Client::Flag::DEBUG_ENABLED)) { - send_text_message_printf(c, "$C5Section ID changed\nto %s (%hhu)", name_for_section_id(new_section_id), new_section_id); + if (this->item_creator->get_section_id() != new_section_id) { + this->log.info("Changing section ID to %s", name_for_section_id(new_section_id)); + this->item_creator->set_section_id(new_section_id); + for (const auto& c : this->clients) { + if (c && c->config.check_flag(Client::Flag::DEBUG_ENABLED)) { + send_text_message_printf(c, "$C5Section ID changed\nto %s (%hhu)", name_for_section_id(new_section_id), new_section_id); + } } } } @@ -277,6 +280,9 @@ uint8_t Lobby::effective_section_id() const { if (this->override_section_id != 0xFF) { return this->override_section_id; } + if (this->check_flag(Lobby::Flag::USE_CREATOR_SECTION_ID)) { + return this->creator_section_id; + } auto leader = this->clients.at(this->leader_id); if (leader) { return leader->character()->disp.visual.section_id; diff --git a/src/Lobby.hh b/src/Lobby.hh index 62bc65ee..0142e4b3 100644 --- a/src/Lobby.hh +++ b/src/Lobby.hh @@ -56,23 +56,24 @@ struct Lobby : public std::enable_shared_from_this { uint32_t reassign_all_item_ids(uint32_t next_item_id); }; enum class Flag { - GAME = 0x00000001, - PERSISTENT = 0x00000002, - + // clang-format off + GAME = 0x00000001, + PERSISTENT = 0x00000002, // Flags used only for games - CHEATS_ENABLED = 0x00000100, - QUEST_IN_PROGRESS = 0x00000200, - BATTLE_IN_PROGRESS = 0x00000400, - JOINABLE_QUEST_IN_PROGRESS = 0x00000800, - IS_SPECTATOR_TEAM = 0x00002000, // episode must be EP3 also - SPECTATORS_FORBIDDEN = 0x00004000, + CHEATS_ENABLED = 0x00000100, + QUEST_IN_PROGRESS = 0x00000200, + BATTLE_IN_PROGRESS = 0x00000400, + JOINABLE_QUEST_IN_PROGRESS = 0x00000800, + IS_SPECTATOR_TEAM = 0x00002000, // episode must be EP3 also + SPECTATORS_FORBIDDEN = 0x00004000, START_BATTLE_PLAYER_IMMEDIATELY = 0x00008000, - CANNOT_CHANGE_CHEAT_MODE = 0x00010000, - + CANNOT_CHANGE_CHEAT_MODE = 0x00010000, + USE_CREATOR_SECTION_ID = 0x00020000, // Flags used only for lobbies - PUBLIC = 0x01000000, - DEFAULT = 0x02000000, - IS_OVERFLOW = 0x08000000, + PUBLIC = 0x01000000, + DEFAULT = 0x02000000, + IS_OVERFLOW = 0x08000000, + // clang-format on }; enum class DropMode { DISABLED = 0, @@ -107,6 +108,7 @@ struct Lobby : public std::enable_shared_from_this { // bits are indexed as (1 << version), where version is a value from the // Version enum. uint16_t allowed_versions; + uint8_t creator_section_id; uint8_t override_section_id; Episode episode; GameMode mode; diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index 77634745..6095acd8 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -4178,11 +4178,15 @@ shared_ptr create_game_generic( if (!s->behavior_can_be_overridden(s->cheat_mode_behavior)) { game->set_flag(Lobby::Flag::CANNOT_CHANGE_CHEAT_MODE); } + if (s->use_game_creator_section_id) { + game->set_flag(Lobby::Flag::USE_CREATOR_SECTION_ID); + } if (watched_lobby || battle_player) { game->set_flag(Lobby::Flag::IS_SPECTATOR_TEAM); } game->password = password; + game->creator_section_id = p->disp.visual.section_id; game->override_section_id = c->config.override_section_id; game->episode = episode; game->mode = mode; diff --git a/src/ServerState.cc b/src/ServerState.cc index 5f60f38c..14aaa79c 100644 --- a/src/ServerState.cc +++ b/src/ServerState.cc @@ -728,6 +728,7 @@ void ServerState::load_config_early() { this->persistent_game_idle_timeout_usecs = this->config_json->get_int("PersistentGameIdleTimeout", 0); this->cheat_mode_behavior = parse_behavior_switch("CheatModeBehavior", BehaviorSwitch::OFF_BY_DEFAULT); + this->use_game_creator_section_id = this->config_json->get_bool("UseGameCreatorSectionID", false); this->default_rare_notifs_enabled_v1_v2 = this->config_json->get_bool("RareNotificationsEnabledByDefault", false); this->default_rare_notifs_enabled_v3_v4 = this->default_rare_notifs_enabled_v1_v2; this->default_rare_notifs_enabled_v1_v2 = this->config_json->get_bool("RareNotificationsEnabledByDefaultV1V2", this->default_rare_notifs_enabled_v1_v2); diff --git a/src/ServerState.hh b/src/ServerState.hh index 0c1657af..52227c67 100644 --- a/src/ServerState.hh +++ b/src/ServerState.hh @@ -123,6 +123,7 @@ struct ServerState : public std::enable_shared_from_this { bool hide_download_commands = true; RunShellBehavior run_shell_behavior = RunShellBehavior::DEFAULT; BehaviorSwitch cheat_mode_behavior = BehaviorSwitch::OFF_BY_DEFAULT; + bool use_game_creator_section_id = false; bool default_rare_notifs_enabled_v1_v2 = false; bool default_rare_notifs_enabled_v3_v4 = false; std::vector> bb_private_keys; diff --git a/system/config.example.json b/system/config.example.json index 6329f794..48cab806 100644 --- a/system/config.example.json +++ b/system/config.example.json @@ -814,7 +814,17 @@ // drop modes in all game versions. If you want to scale the drop rates for // only some versions, use the --multiply option to the convert-rare-item-set // action instead. - "ServerGlobalDropRateMultiplier": 1, + "ServerGlobalDropRateMultiplier": 1.0, + + // Whether to retain server drop tables when game leaders change. The client + // reloads its drop tables when the leader joins a game or returns to Pioneer + // 2; this leads to some edge cases that could be confusing for players, so + // newserv instead switches its server tables instantly to the new leader's + // section ID when the leader leaves the game. This option, if enabled, causes + // the server to instead use the game creator's section ID for the entire + // duration of the game. On versions other than BB, this only has an effect in + // server drop modes. + "UseGameCreatorSectionID": false, // BB team reward definitions. Team rewards have the following fields: // Key: Internal name of the reward. Must be unique across all rewards. diff --git a/tests/config.json b/tests/config.json index fd53ba0b..ffa90e28 100644 --- a/tests/config.json +++ b/tests/config.json @@ -297,6 +297,8 @@ "031000", ], "BBGlobalEXPMultiplier": 1, + "ServerGlobalDropRateMultiplier": 1.0, + "UseGameCreatorSectionID": false, "TeamRewards": [ {