diff --git a/src/Episode3/Server.cc b/src/Episode3/Server.cc index 84d2b52c..efc02b34 100644 --- a/src/Episode3/Server.cc +++ b/src/Episode3/Server.cc @@ -34,6 +34,9 @@ Server::Server(shared_ptr lobby, Options&& options) last_chosen_map(this->options.tournament ? this->options.tournament->get_map() : nullptr), tournament_match_result_sent(false), override_environment_number(0xFF), + def_dice_value_range_override(0xFF), + atk_dice_value_range_2v1_override(0xFF), + def_dice_value_range_2v1_override(0xFF), battle_finished(false), battle_in_progress(false), round_num(1), @@ -2146,26 +2149,35 @@ void Server::handle_CAx12_end_attack_list(shared_ptr, const string& data } template -void Server::handle_CAx13_update_map_during_setup_t(shared_ptr, const string& data) { +void Server::handle_CAx13_update_map_during_setup_t(shared_ptr c, const string& data) { const auto& in_cmd = check_size_t(data); - this->send_debug_command_received_message( - in_cmd.header.subsubcommand, "UPDATE MAP"); + this->send_debug_command_received_message(in_cmd.header.subsubcommand, "UPDATE MAP"); if (!this->battle_in_progress && (this->setup_phase == SetupPhase::REGISTRATION) && (this->map_and_rules->num_players == 0) && (this->registration_phase != RegistrationPhase::REGISTERED) && (this->registration_phase != RegistrationPhase::BATTLE_STARTED)) { - // newserv's extended rules are stored in unused parts of the Rules struct, - // and clients will probably overwrite them with zeroes if we allow them to. - // So, we preserve the extended rules manually here. - uint8_t def_dice_value_range = this->map_and_rules->rules.def_dice_value_range; - uint8_t atk_dice_value_range_2v1 = this->map_and_rules->rules.atk_dice_value_range_2v1; - uint8_t def_dice_value_range_2v1 = this->map_and_rules->rules.def_dice_value_range_2v1; + if (!this->last_chosen_map) { + throw runtime_error("CAx13 sent with no map chosen"); + } + *this->map_and_rules = in_cmd.map_and_rules_state; - this->map_and_rules->rules.def_dice_value_range = def_dice_value_range; - this->map_and_rules->rules.atk_dice_value_range_2v1 = atk_dice_value_range_2v1; - this->map_and_rules->rules.def_dice_value_range_2v1 = def_dice_value_range_2v1; + // The client will likely send incorrect values for the extended rules (or + // in the case of NTE, no values at all, since the Rules structure is + // smaller). So, use the values from the last chosen map if applicable, or + // the values from the $dicerange command if available. + const auto& map_rules = this->last_chosen_map->version(c->language())->map->default_rules; + auto& server_rules = this->map_and_rules->rules; + server_rules.def_dice_value_range = (map_rules.def_dice_value_range == 0xFF) + ? ((this->def_dice_value_range_override == 0xFF) ? 0 : this->def_dice_value_range_override) + : map_rules.def_dice_value_range; + server_rules.atk_dice_value_range_2v1 = (map_rules.atk_dice_value_range_2v1 == 0xFF) + ? ((this->atk_dice_value_range_2v1_override == 0xFF) ? 0 : this->atk_dice_value_range_2v1_override) + : map_rules.atk_dice_value_range_2v1; + server_rules.def_dice_value_range_2v1 = (map_rules.def_dice_value_range_2v1 == 0xFF) + ? ((this->def_dice_value_range_2v1_override == 0xFF) ? 0 : this->def_dice_value_range_2v1_override) + : map_rules.def_dice_value_range_2v1; // If this match is part of a tournament, ignore the rules sent by the // client and use the tournament rules instead. @@ -2603,30 +2615,10 @@ void Server::send_6xB6x41_to_all_clients() const { } } -void Server::handle_CAx41_map_request(shared_ptr c, const string& data) { +void Server::handle_CAx41_map_request(shared_ptr, const string& data) { const auto& cmd = check_size_t(data); this->send_debug_command_received_message(cmd.header.subsubcommand, "MAP DATA"); - this->last_chosen_map = this->options.map_index->for_number(cmd.map_number); - - // We don't trust the extended rules fields from the client, and the client - // can't modify it anyway, so we always apply the map's extended rules here. - // This allows map creators to use newserv's extended rules in quests. - if (this->setup_phase == SetupPhase::REGISTRATION) { - auto mv = this->last_chosen_map->version(c->language()); - const auto& map_rules = mv->map->default_rules; - auto& server_rules = this->map_and_rules->rules; - if (map_rules.def_dice_value_range != 0xFF) { - server_rules.def_dice_value_range = map_rules.def_dice_value_range; - } - if (map_rules.atk_dice_value_range_2v1 != 0xFF) { - server_rules.atk_dice_value_range_2v1 = map_rules.atk_dice_value_range_2v1; - } - if (map_rules.def_dice_value_range_2v1 != 0xFF) { - server_rules.def_dice_value_range_2v1 = map_rules.def_dice_value_range_2v1; - } - } - this->send_6xB6x41_to_all_clients(); } diff --git a/src/Episode3/Server.hh b/src/Episode3/Server.hh index 41701368..c4bb771a 100644 --- a/src/Episode3/Server.hh +++ b/src/Episode3/Server.hh @@ -278,6 +278,9 @@ public: std::shared_ptr last_chosen_map; bool tournament_match_result_sent; uint8_t override_environment_number; + uint8_t def_dice_value_range_override; + uint8_t atk_dice_value_range_2v1_override; + uint8_t def_dice_value_range_2v1_override; mutable std::deque logger_stack; // These fields were originally contained in the TCardServerBase object