fix case where map selection is changed during setup

This commit is contained in:
Martin Michelsen
2024-02-13 21:37:15 -08:00
parent 35e2a9d6f4
commit 08ba5d821b
2 changed files with 28 additions and 33 deletions
+25 -33
View File
@@ -34,6 +34,9 @@ Server::Server(shared_ptr<Lobby> lobby, Options&& options)
last_chosen_map(this->options.tournament ? this->options.tournament->get_map() : nullptr), last_chosen_map(this->options.tournament ? this->options.tournament->get_map() : nullptr),
tournament_match_result_sent(false), tournament_match_result_sent(false),
override_environment_number(0xFF), 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_finished(false),
battle_in_progress(false), battle_in_progress(false),
round_num(1), round_num(1),
@@ -2146,26 +2149,35 @@ void Server::handle_CAx12_end_attack_list(shared_ptr<Client>, const string& data
} }
template <typename CmdT> template <typename CmdT>
void Server::handle_CAx13_update_map_during_setup_t(shared_ptr<Client>, const string& data) { void Server::handle_CAx13_update_map_during_setup_t(shared_ptr<Client> c, const string& data) {
const auto& in_cmd = check_size_t<CmdT>(data); const auto& in_cmd = check_size_t<CmdT>(data);
this->send_debug_command_received_message( this->send_debug_command_received_message(in_cmd.header.subsubcommand, "UPDATE MAP");
in_cmd.header.subsubcommand, "UPDATE MAP");
if (!this->battle_in_progress && if (!this->battle_in_progress &&
(this->setup_phase == SetupPhase::REGISTRATION) && (this->setup_phase == SetupPhase::REGISTRATION) &&
(this->map_and_rules->num_players == 0) && (this->map_and_rules->num_players == 0) &&
(this->registration_phase != RegistrationPhase::REGISTERED) && (this->registration_phase != RegistrationPhase::REGISTERED) &&
(this->registration_phase != RegistrationPhase::BATTLE_STARTED)) { (this->registration_phase != RegistrationPhase::BATTLE_STARTED)) {
// newserv's extended rules are stored in unused parts of the Rules struct, if (!this->last_chosen_map) {
// and clients will probably overwrite them with zeroes if we allow them to. throw runtime_error("CAx13 sent with no map chosen");
// 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;
*this->map_and_rules = in_cmd.map_and_rules_state; *this->map_and_rules = in_cmd.map_and_rules_state;
this->map_and_rules->rules.def_dice_value_range = def_dice_value_range; // The client will likely send incorrect values for the extended rules (or
this->map_and_rules->rules.atk_dice_value_range_2v1 = atk_dice_value_range_2v1; // in the case of NTE, no values at all, since the Rules structure is
this->map_and_rules->rules.def_dice_value_range_2v1 = def_dice_value_range_2v1; // 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 // If this match is part of a tournament, ignore the rules sent by the
// client and use the tournament rules instead. // 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<Client> c, const string& data) { void Server::handle_CAx41_map_request(shared_ptr<Client>, const string& data) {
const auto& cmd = check_size_t<G_MapDataRequest_Ep3_CAx41>(data); const auto& cmd = check_size_t<G_MapDataRequest_Ep3_CAx41>(data);
this->send_debug_command_received_message(cmd.header.subsubcommand, "MAP 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); 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(); this->send_6xB6x41_to_all_clients();
} }
+3
View File
@@ -278,6 +278,9 @@ public:
std::shared_ptr<const MapIndex::Map> last_chosen_map; std::shared_ptr<const MapIndex::Map> last_chosen_map;
bool tournament_match_result_sent; bool tournament_match_result_sent;
uint8_t override_environment_number; 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<StackLogger*> logger_stack; mutable std::deque<StackLogger*> logger_stack;
// These fields were originally contained in the TCardServerBase object // These fields were originally contained in the TCardServerBase object