diff --git a/src/aoapplication.cpp b/src/aoapplication.cpp index bcc1ad598..07b7c04f2 100644 --- a/src/aoapplication.cpp +++ b/src/aoapplication.cpp @@ -122,6 +122,11 @@ QString AOApplication::get_version_string() return QString::number(RELEASE) + "." + QString::number(MAJOR_VERSION) + "." + QString::number(MINOR_VERSION); } +QString AOApplication::get_protocol_version_string() +{ + return QString::number(PROTOCOL_MAJOR_VERSION) + "." + QString::number(PROTOCOL_MINOR_VERSION) + "." + QString::number(PROTOCOL_PATCH_VERSION); +} + QString AOApplication::find_image(QStringList p_list) { QString image_path; @@ -147,6 +152,7 @@ void AOApplication::server_disconnected() construct_lobby(); destruct_courtroom(); } + w_lobby->set_connection_state(tr("Offline")); Options::getInstance().setServerSubTheme(QString()); } diff --git a/src/aoapplication.h b/src/aoapplication.h index d040408d5..c591cabf9 100644 --- a/src/aoapplication.h +++ b/src/aoapplication.h @@ -103,8 +103,14 @@ class AOApplication : public QObject static QString get_version_string(); static const int RELEASE = 2; - static const int MAJOR_VERSION = 10; - static const int MINOR_VERSION = 1; + static const int MAJOR_VERSION = 11; + static const int MINOR_VERSION = 0; + + static QString get_protocol_version_string(); + + static const int PROTOCOL_MAJOR_VERSION = 1; + static const int PROTOCOL_MINOR_VERSION = 0; + static const int PROTOCOL_PATCH_VERSION = 0; void set_server_list(QVector &servers) { server_list = servers; } QVector &get_server_list() { return server_list; } diff --git a/src/courtroom.cpp b/src/courtroom.cpp index cea7ba071..b7c253af9 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -741,25 +741,11 @@ void Courtroom::set_widgets() set_fonts(); set_size_and_pos(ui_viewport, "viewport"); - // If there is a point to it, show all CCCC features. - // We also do this this soon so that set_size_and_pos can hide them all later, - // if needed. - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::CCCC_IC_SUPPORT)) - { - ui_pair_button->show(); - ui_immediate->show(); - ui_showname_enable->show(); - ui_ic_chat_name->show(); - ui_ic_chat_name->setEnabled(true); - } - else - { - ui_pair_button->hide(); - ui_immediate->hide(); - ui_showname_enable->hide(); - ui_ic_chat_name->hide(); - ui_ic_chat_name->setEnabled(false); - } + ui_pair_button->show(); + ui_immediate->show(); + ui_showname_enable->show(); + ui_ic_chat_name->show(); + ui_ic_chat_name->setEnabled(true); // We also show the non-server-dependent client additions. // Once again, if the theme can't display it, set_move_and_pos will catch @@ -1562,59 +1548,56 @@ void Courtroom::update_character(int p_cid, QString char_name, bool reset_emote) } ui_custom_objection->hide(); - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::CUSTOMOBJECTIONS)) // if setting is enabled + custom_obj_menu->clear(); + custom_objections_list.clear(); + if (file_exists(ao_app->get_image_suffix(ao_app->get_character_path(current_char, "custom")))) + { + ui_custom_objection->show(); + QString custom_name = ao_app->read_char_ini(f_char, "custom_name", "Shouts"); + QAction *action; + if (custom_name != "") + { + action = custom_obj_menu->addAction(custom_name); + } + else + { + action = custom_obj_menu->addAction("Default"); + } + custom_obj_menu->setDefaultAction(action); + objection_custom = ""; + } + QString custom_objection_dir = ao_app->get_real_path(ao_app->get_character_path(current_char, "custom_objections")); + if (dir_exists(custom_objection_dir)) { - custom_obj_menu->clear(); - custom_objections_list.clear(); - if (file_exists(ao_app->get_image_suffix(ao_app->get_character_path(current_char, "custom")))) + ui_custom_objection->show(); + QDir directory(custom_objection_dir); + QStringList custom_obj = directory.entryList(QStringList() << "*.png" + << "*.gif" + << "*.apng" + << "*.webp", + QDir::Files); + for (const QString &filename : custom_obj) { - ui_custom_objection->show(); - QString custom_name = ao_app->read_char_ini(f_char, "custom_name", "Shouts"); + CustomObjection custom_objection; + custom_objection.filename = filename; + QString custom_name = ao_app->read_char_ini(f_char, filename.left(filename.lastIndexOf(".")) + "_name", "Shouts"); QAction *action; if (custom_name != "") { + custom_objection.name = custom_name; action = custom_obj_menu->addAction(custom_name); } else { - action = custom_obj_menu->addAction("Default"); + custom_objection.name = filename.left(filename.lastIndexOf(".")); + action = custom_obj_menu->addAction(custom_objection.name); } - custom_obj_menu->setDefaultAction(action); - objection_custom = ""; - } - QString custom_objection_dir = ao_app->get_real_path(ao_app->get_character_path(current_char, "custom_objections")); - if (dir_exists(custom_objection_dir)) - { - ui_custom_objection->show(); - QDir directory(custom_objection_dir); - QStringList custom_obj = directory.entryList(QStringList() << "*.png" - << "*.gif" - << "*.apng" - << "*.webp", - QDir::Files); - for (const QString &filename : custom_obj) + if (custom_obj_menu->defaultAction() == nullptr) { - CustomObjection custom_objection; - custom_objection.filename = filename; - QString custom_name = ao_app->read_char_ini(f_char, filename.left(filename.lastIndexOf(".")) + "_name", "Shouts"); - QAction *action; - if (custom_name != "") - { - custom_objection.name = custom_name; - action = custom_obj_menu->addAction(custom_name); - } - else - { - custom_objection.name = filename.left(filename.lastIndexOf(".")); - action = custom_obj_menu->addAction(custom_objection.name); - } - if (custom_obj_menu->defaultAction() == nullptr) - { - custom_obj_menu->setDefaultAction(action); - objection_custom = custom_objection.filename; - } - custom_objections_list.append(custom_objection); + custom_obj_menu->setDefaultAction(action); + objection_custom = custom_objection.filename; } + custom_objections_list.append(custom_objection); } } @@ -1636,23 +1619,8 @@ void Courtroom::enter_courtroom() { set_evidence_page(); - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::FLIPPING)) - { - ui_flip->show(); - } - else - { - ui_flip->hide(); - } - - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::ADDITIVE)) - { - ui_additive->show(); - } - else - { - ui_additive->hide(); - } + ui_flip->show(); + ui_additive->show(); list_music(); list_areas(); @@ -1764,29 +1732,26 @@ void Courtroom::list_areas() QString i_area; i_area.append(area_list.at(n_area)); - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::ARUP)) - { - i_area.append("\n "); - - i_area.append(arup_statuses.at(n_area)); + i_area.append("\n "); - if (arup_cms.at(n_area) != "FREE") - { - i_area.append(" | CM: "); - i_area.append(arup_cms.at(n_area)); - } + i_area.append(arup_statuses.at(n_area)); - i_area.append("\n "); + if (arup_cms.at(n_area) != "FREE") + { + i_area.append(" | CM: "); + i_area.append(arup_cms.at(n_area)); + } - if (arup_players.at(n_area) != -1) - { - i_area.append(QString::number(arup_players.at(n_area))); - i_area.append(" users | "); - } + i_area.append("\n "); - i_area.append(arup_locks.at(n_area)); + if (arup_players.at(n_area) != -1) + { + i_area.append(QString::number(arup_players.at(n_area))); + i_area.append(" users | "); } + i_area.append(arup_locks.at(n_area)); + QTreeWidgetItem *treeItem = ui_area_list->topLevelItem(n_area); if (treeItem == nullptr) { @@ -1795,41 +1760,34 @@ void Courtroom::list_areas() treeItem->setText(0, area_list.at(n_area)); treeItem->setText(1, i_area); - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::ARUP)) + // Coloring logic here. + treeItem->setBackground(1, free_brush); + if (arup_locks.at(n_area) == "LOCKED") { - // Coloring logic here. - treeItem->setBackground(1, free_brush); - if (arup_locks.at(n_area) == "LOCKED") + treeItem->setBackground(1, locked_brush); + } + else + { + if (arup_statuses.at(n_area) == "LOOKING-FOR-PLAYERS") { - treeItem->setBackground(1, locked_brush); + treeItem->setBackground(1, lfp_brush); } - else + else if (arup_statuses.at(n_area) == "CASING") { - if (arup_statuses.at(n_area) == "LOOKING-FOR-PLAYERS") - { - treeItem->setBackground(1, lfp_brush); - } - else if (arup_statuses.at(n_area) == "CASING") - { - treeItem->setBackground(1, casing_brush); - } - else if (arup_statuses.at(n_area) == "RECESS") - { - treeItem->setBackground(1, recess_brush); - } - else if (arup_statuses.at(n_area) == "RP") - { - treeItem->setBackground(1, rp_brush); - } - else if (arup_statuses.at(n_area) == "GAMING") - { - treeItem->setBackground(1, gaming_brush); - } + treeItem->setBackground(1, casing_brush); + } + else if (arup_statuses.at(n_area) == "RECESS") + { + treeItem->setBackground(1, recess_brush); + } + else if (arup_statuses.at(n_area) == "RP") + { + treeItem->setBackground(1, rp_brush); + } + else if (arup_statuses.at(n_area) == "GAMING") + { + treeItem->setBackground(1, gaming_brush); } - } - else - { - treeItem->setBackground(1, free_brush); } ++n_listed_areas; @@ -1869,11 +1827,6 @@ void Courtroom::append_server_chatmessage(QString p_name, QString p_message, QSt { color = ao_app->get_color("server_chatlog_sender_color", "courtroom_fonts.ini").name(); } - if (!ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::AUTH_PACKET) && p_message == "Logged in as a moderator.") - { - // Emulate successful authentication - on_authentication_state_received(1); - } ui_server_chatlog->addMessage(p_name, p_message, color); @@ -1962,31 +1915,14 @@ void Courtroom::on_chat_return_pressed() // have to fetch this early for a workaround. i hate this system, but i am stuck with it for now int f_emote_mod = ao_app->get_emote_mod(current_char, current_emote); - int f_desk_mod = DESK_SHOW; - - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::DESKMOD)) + int f_desk_mod = ao_app->get_desk_mod(current_char, current_emote); + if (f_desk_mod == -1 && (f_emote_mod == 5 || f_emote_mod == 6)) // workaround for inis that broke after deprecating "chat" { - f_desk_mod = ao_app->get_desk_mod(current_char, current_emote); - {} - if (!ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::EXPANDED_DESK_MODS)) - { - if (f_desk_mod == DESK_PRE_ONLY_EX || f_desk_mod == DESK_PRE_ONLY) - { - f_desk_mod = DESK_HIDE; - } - else if (f_desk_mod == DESK_EMOTE_ONLY_EX || f_desk_mod == DESK_EMOTE_ONLY) - { - f_desk_mod = DESK_SHOW; - } - } - if (f_desk_mod == -1 && (f_emote_mod == 5 || f_emote_mod == 6)) // workaround for inis that broke after deprecating "chat" - { - f_desk_mod = DESK_HIDE; - } - else if (f_desk_mod == -1) - { - f_desk_mod = DESK_SHOW; - } + f_desk_mod = DESK_HIDE; + } + else if (f_desk_mod == -1) + { + f_desk_mod = DESK_SHOW; } packet_contents.append(QString::number(f_desk_mod)); @@ -2020,7 +1956,7 @@ void Courtroom::on_chat_return_pressed() f_emote_mod = PREANIM; } // Turn zoom into preanim zoom - else if (f_emote_mod == ZOOM && ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::PREZOOM)) + else if (f_emote_mod == ZOOM) { f_emote_mod = PREANIM_ZOOM; } @@ -2083,7 +2019,7 @@ void Courtroom::on_chat_return_pressed() QString f_obj_state; - if ((objection_state == 4 && !ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::CUSTOMOBJECTIONS)) || (objection_state < 0)) + if (objection_state < 0) { f_obj_state = "0"; } @@ -2117,23 +2053,14 @@ void Courtroom::on_chat_return_pressed() } QString f_flip; - - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::FLIPPING)) + if (ui_flip->isChecked()) { - if (ui_flip->isChecked()) - { - f_flip = "1"; - } - else - { - f_flip = "0"; - } + f_flip = "1"; } else { - f_flip = QString::number(m_cid); + f_flip = "0"; } - packet_contents.append(f_flip); packet_contents.append(QString::number(realization_state)); @@ -2155,122 +2082,91 @@ void Courtroom::on_chat_return_pressed() packet_contents.append(f_text_color); - // If the server we're on supports CCCC stuff, we should use it! - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::CCCC_IC_SUPPORT)) + // If there is a showname entered, use that -- else, just send an empty + // packet-part. + if (!ui_ic_chat_name->text().isEmpty()) { - // If there is a showname entered, use that -- else, just send an empty - // packet-part. - if (!ui_ic_chat_name->text().isEmpty()) - { - packet_contents.append(ui_ic_chat_name->text()); - } - else - { - packet_contents.append(ao_app->get_showname(current_char, current_emote)); - } - - // Similarly, we send over whom we're paired with, unless we have chosen - // ourselves. Or a charid of -1 or lower, through some means. - if (other_charid > -1 && other_charid != m_cid) - { - QString packet = QString::number(other_charid); - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::EFFECTS)) // Only servers with effects - // enabled will support pair - // reordering - { - packet += "^" + QString::number(pair_order); - } - packet_contents.append(packet); - } - else - { - packet_contents.append("-1"); - } - // Send the offset as it's gonna be used regardless - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::Y_OFFSET)) - { - packet_contents.append(QString::number(char_offset) + "&" + QString::number(char_vert_offset)); - } - else - { - packet_contents.append(QString::number(char_offset)); - } + packet_contents.append(ui_ic_chat_name->text()); + } + else + { + packet_contents.append(ao_app->get_showname(current_char, current_emote)); + } - // Finally, we send over if we want our pres to not interrupt. - if (ui_immediate->isChecked() && ui_pre->isChecked()) - { - packet_contents.append("1"); - } - else - { - packet_contents.append("0"); - } + // Similarly, we send over whom we're paired with, unless we have chosen + // ourselves. Or a charid of -1 or lower, through some means. + if (other_charid > -1 && other_charid != m_cid) + { + QString packet = QString::number(other_charid) + "^" + QString::number(pair_order); + packet_contents.append(packet); + } + else + { + packet_contents.append("-1"); } - // If the server we're on supports Looping SFX and Screenshake, use it if the - // emote uses it. - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::LOOPING_SFX)) + packet_contents.append(QString::number(char_offset) + "&" + QString::number(char_vert_offset)); + + // Finally, we send over if we want our pres to not interrupt. + if (ui_immediate->isChecked() && ui_pre->isChecked()) + { + packet_contents.append("1"); + } + else { - packet_contents.append(ao_app->get_sfx_looping(current_char, current_emote)); - packet_contents.append(QString::number(screenshake_state)); + packet_contents.append("0"); + } + + packet_contents.append(ao_app->get_sfx_looping(current_char, current_emote)); + packet_contents.append(QString::number(screenshake_state)); - QString pre_emote = ao_app->get_pre_emote(current_char, current_emote); - QString emote = ao_app->get_emote(current_char, current_emote); - QStringList emotes_to_check = {pre_emote, "(b)" + emote, "(a)" + emote}; - QStringList effects_to_check = {"_FrameScreenshake", "_FrameRealization", "_FrameSFX"}; + QString pre_emote = ao_app->get_pre_emote(current_char, current_emote); + QString emote = ao_app->get_emote(current_char, current_emote); + QStringList emotes_to_check = {pre_emote, "(b)" + emote, "(a)" + emote}; + QStringList effects_to_check = {"_FrameScreenshake", "_FrameRealization", "_FrameSFX"}; - foreach (QString f_effect, effects_to_check) + foreach (QString f_effect, effects_to_check) + { + QString packet; + foreach (QString f_emote, emotes_to_check) { - QString packet; - foreach (QString f_emote, emotes_to_check) + packet += f_emote; + if (Options::getInstance().networkedFrameSfxEnabled()) { - packet += f_emote; - if (Options::getInstance().networkedFrameSfxEnabled()) + QString sfx_frames = ao_app->read_ini_tags(ao_app->get_character_path(current_char, "char.ini"), f_emote.append(f_effect)).join("|"); + if (sfx_frames != "") { - QString sfx_frames = ao_app->read_ini_tags(ao_app->get_character_path(current_char, "char.ini"), f_emote.append(f_effect)).join("|"); - if (sfx_frames != "") - { - packet += "|" + sfx_frames; - } + packet += "|" + sfx_frames; } - packet += "^"; } - packet_contents.append(packet); + packet += "^"; } + packet_contents.append(packet); } - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::ADDITIVE)) - { - packet_contents.append(ui_additive->isChecked() ? "1" : "0"); - } - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::EFFECTS)) - { - QString p_effect_folder = ao_app->read_char_ini(current_char, "effects", "Options"); - QString fx_sound = ao_app->get_effect_property(effect, current_char, p_effect_folder, "sound"); + packet_contents.append(ui_additive->isChecked() ? "1" : "0"); - // Don't overlap the two sfx - if (!ui_pre->isChecked() && (!custom_sfx.isEmpty() || ui_sfx_dropdown->currentIndex() == 1)) - { - fx_sound = "0"; - } + QString p_effect_folder = ao_app->read_char_ini(current_char, "effects", "Options"); + QString fx_sound = ao_app->get_effect_property(effect, current_char, p_effect_folder, "sound"); - packet_contents.append(effect + "|" + p_effect_folder + "|" + fx_sound); - if (!Options::getInstance().clearEffectsDropdownOnPlayEnabled() && !ao_app->get_effect_property(effect, current_char, p_effect_folder, "sticky").startsWith("true")) - { - ui_effects_dropdown->blockSignals(true); - ui_effects_dropdown->setCurrentIndex(0); - ui_effects_dropdown->blockSignals(false); - effect = ""; - } + // Don't overlap the two sfx + if (!ui_pre->isChecked() && (!custom_sfx.isEmpty() || ui_sfx_dropdown->currentIndex() == 1)) + { + fx_sound = "0"; } - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::CUSTOM_BLIPS)) + packet_contents.append(effect + "|" + p_effect_folder + "|" + fx_sound); + if (!Options::getInstance().clearEffectsDropdownOnPlayEnabled() && !ao_app->get_effect_property(effect, current_char, p_effect_folder, "sticky").startsWith("true")) { - packet_contents.append(ao_app->get_blipname(current_char, current_emote)); - - packet_contents.append(ui_slide_enable->isChecked() ? "1" : "0"); // just let the server figure out what to do with this + ui_effects_dropdown->blockSignals(true); + ui_effects_dropdown->setCurrentIndex(0); + ui_effects_dropdown->blockSignals(false); + effect = ""; } + packet_contents.append(ao_app->get_blipname(current_char, current_emote)); + packet_contents.append(ui_slide_enable->isChecked() ? "1" : "0"); // just let the server figure out what to do with this + ao_app->send_server_packet(AOPacket("MS", packet_contents)); } @@ -2314,14 +2210,6 @@ void Courtroom::reset_ui() void Courtroom::chatmessage_enqueue(QStringList p_contents) { - // Instead of checking for whether a message has at least chatmessage_size - // amount of packages, we'll check if it has at least 15. - // That was the original chatmessage_size. - if (p_contents.size() < MS_MINIMUM) - { - return; - } - // Check the validity of the character ID we got int f_char_id = p_contents[CHAR_ID].toInt(); if (f_char_id < -1 || f_char_id >= char_list.size()) @@ -2430,20 +2318,7 @@ void Courtroom::unpack_chatmessage(QStringList p_contents) for (int n_string = 0; n_string < MS_MAXIMUM; ++n_string) { m_previous_chatmessage[n_string] = m_chatmessage[n_string]; - - // Note that we have added stuff that vanilla clients and servers simply - // won't send. So now, we have to check if the thing we want even exists - // amongst the packet's content. We also have to check if the server even - // supports CCCC's IC features, or if it's just japing us. Also, don't - // forget! A size 15 message will have indices from 0 to 14. - if (n_string < p_contents.size() && (n_string < MS_MINIMUM || ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::CCCC_IC_SUPPORT))) - { - m_chatmessage[n_string] = p_contents.at(n_string); - } - else - { - m_chatmessage[n_string] = ""; - } + m_chatmessage[n_string] = p_contents.at(n_string); } // if the char ID matches our client's char ID (most likely, this is our message coming back to us) @@ -2799,7 +2674,7 @@ void Courtroom::display_pair_character(QString other_charid, QString other_offse ui_vp_sideplayer_char->setPlayOnce(false); // Flip the pair character - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::FLIPPING) && m_chatmessage[OTHER_FLIP].toInt() == 1) + if (m_chatmessage[OTHER_FLIP].toInt() == 1) { ui_vp_sideplayer_char->setFlipped(true); } @@ -4161,7 +4036,7 @@ void Courtroom::start_chat_ticking() QString f_blips = ao_app->get_blipname(m_chatmessage[CHAR_NAME]); f_blips = ao_app->get_blips(f_blips); - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::CUSTOM_BLIPS) && !m_chatmessage[BLIPNAME].isEmpty()) + if (!m_chatmessage[BLIPNAME].isEmpty()) { f_blips = ao_app->get_blips(m_chatmessage[BLIPNAME]); } @@ -4918,7 +4793,7 @@ void Courtroom::on_ooc_return_pressed() // We ignore it when the server is compatible with 2.8 // Using an arbitrary 2.8 feature flag certainly won't cause issues someday. - if (ooc_message.startsWith("/pos") && ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::EFFECTS)) + if (ooc_message.startsWith("/pos")) { if (ooc_message == "/pos jud") { @@ -5718,14 +5593,8 @@ void Courtroom::on_music_list_double_clicked(QTreeWidgetItem *p_item, int column QStringList packet_contents; packet_contents.append(p_song); packet_contents.append(QString::number(m_cid)); - if ((!ui_ic_chat_name->text().isEmpty() && ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::CCCC_IC_SUPPORT)) || ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::EFFECTS)) - { - packet_contents.append(ui_ic_chat_name->text()); - } - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::EFFECTS)) - { - packet_contents.append(QString::number(music_flags)); - } + packet_contents.append(ui_ic_chat_name->text()); + packet_contents.append(QString::number(music_flags)); ao_app->send_server_packet(AOPacket("MC", packet_contents)); } @@ -5869,25 +5738,18 @@ void Courtroom::music_stop(bool no_effects) QStringList packet_contents; // its music list packet_contents.append(fake_song); // this is our fake song, playing it triggers special code packet_contents.append(QString::number(m_cid)); + packet_contents.append(ui_ic_chat_name->text()); - if ((!ui_ic_chat_name->text().isEmpty() && ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::CCCC_IC_SUPPORT)) || ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::EFFECTS)) + if (no_effects) { - packet_contents.append(ui_ic_chat_name->text()); + packet_contents.append("0"); } - - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::EFFECTS)) + else { - if (no_effects) - { - packet_contents.append("0"); - } - else - { - packet_contents.append(QString::number(music_flags)); - } - - ao_app->send_server_packet(AOPacket("MC", packet_contents)); + packet_contents.append(QString::number(music_flags)); } + + ao_app->send_server_packet(AOPacket("MC", packet_contents)); } void Courtroom::on_area_list_double_clicked(QTreeWidgetItem *p_item, int column) @@ -6076,10 +5938,7 @@ void Courtroom::on_pair_clicked() { ui_pair_list->show(); ui_pair_offset_spinbox->show(); - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::Y_OFFSET)) - { - ui_pair_vert_offset_spinbox->show(); - } + ui_pair_vert_offset_spinbox->show(); ui_pair_order_dropdown->show(); ui_mute_list->hide(); ui_mute->setImage("mute"); @@ -6305,7 +6164,7 @@ void Courtroom::on_witness_testimony_clicked() return; } - ao_app->send_server_packet(AOPacket("RT", {"testimony1"})); + ao_app->send_server_packet(AOPacket("RT", {"testimony1", "0"})); focus_ic_input(); } @@ -6317,7 +6176,7 @@ void Courtroom::on_cross_examination_clicked() return; } - ao_app->send_server_packet(AOPacket("RT", {"testimony2"})); + ao_app->send_server_packet(AOPacket("RT", {"testimony2", "0"})); focus_ic_input(); } @@ -6396,17 +6255,10 @@ void Courtroom::on_spectator_clicked() void Courtroom::on_call_mod_clicked() { - if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::MODCALL_REASON)) - { - auto maybe_reason = call_moderator_support(); - if (maybe_reason) - { - ao_app->send_server_packet(AOPacket("ZZ", {maybe_reason.value(), "-1"})); - } - } - else + auto maybe_reason = call_moderator_support(); + if (maybe_reason) { - ao_app->send_server_packet(AOPacket("ZZ")); + ao_app->send_server_packet(AOPacket("ZZ", {maybe_reason.value(), "-1"})); } focus_ic_input(); diff --git a/src/courtroom.h b/src/courtroom.h index 6cae0ff48..00d4f6434 100644 --- a/src/courtroom.h +++ b/src/courtroom.h @@ -73,6 +73,8 @@ class Courtroom : public QMainWindow Q_OBJECT public: + static const int MS_MAXIMUM = 32; + explicit Courtroom(AOApplication *p_ao_app); ~Courtroom(); @@ -451,8 +453,6 @@ class Courtroom : public QMainWindow int ghost_blocks = 0; // Minumum and maximum number of parameters in the MS packet - static const int MS_MINIMUM = 15; - static const int MS_MAXIMUM = 32; QString m_chatmessage[MS_MAXIMUM]; QString m_previous_chatmessage[MS_MAXIMUM]; diff --git a/src/demoserver.cpp b/src/demoserver.cpp index 93eaad567..138e374d6 100644 --- a/src/demoserver.cpp +++ b/src/demoserver.cpp @@ -143,13 +143,11 @@ void DemoServer::handle_packet(AOPacket p_packet) if (header == "HI") { - client_sock->sendTextMessage("ID#0#DEMOINTERNAL#0#%"); + client_sock->sendTextMessage("PN#0#1#%"); } else if (header == "ID") { - QStringList feature_list = {"noencryption", "yellowtext", "prezoom", "flipping", "customobjections", "fastloading", "deskmod", "evidence", "cccc_ic_support", "arup", "casing_alerts", "modcall_reason", "looping_sfx", "additive", "effects", "y_offset", "expanded_desk_mods"}; - client_sock->sendTextMessage("PN#0#1#%"); - client_sock->sendTextMessage("FL#" + feature_list.join('#') + "#%"); + client_sock->sendTextMessage("ID#0#DEMOINTERNAL#0#%"); } else if (header == "askchaa") { diff --git a/src/lobby.cpp b/src/lobby.cpp index 46bb504a1..2cf107d2a 100644 --- a/src/lobby.cpp +++ b/src/lobby.cpp @@ -567,10 +567,14 @@ void Lobby::check_for_updates() }); } +void Lobby::set_connection_state(const QString &state) +{ + ui_server_player_count_lbl->setText(state); +} + void Lobby::set_player_count(int players_online, int max_players) { - QString f_string = tr("Online: %1/%2").arg(QString::number(players_online), QString::number(max_players)); - ui_server_player_count_lbl->setText(f_string); + set_connection_state(tr("Online: %1/%2").arg(QString::number(players_online), QString::number(max_players))); } void Lobby::set_server_description(const QString &server_description) diff --git a/src/lobby.h b/src/lobby.h index 8b894f4c1..06a968aa8 100644 --- a/src/lobby.h +++ b/src/lobby.h @@ -25,6 +25,7 @@ class Lobby : public QMainWindow Lobby(AOApplication *p_ao_app, NetworkManager *p_net_man = nullptr); ~Lobby(); + void set_connection_state(const QString &state); void set_player_count(int players_online, int max_players); void set_server_description(const QString &server_description); void list_servers(); diff --git a/src/network/websocketconnection.h b/src/network/websocketconnection.h index 9df9a49bd..250884611 100644 --- a/src/network/websocketconnection.h +++ b/src/network/websocketconnection.h @@ -19,10 +19,12 @@ class WebSocketConnection : public QObject bool isConnected(); void connectToServer(const ServerInfo &server); - void disconnectFromServer(); void sendPacket(AOPacket packet); +public Q_SLOTS: + void disconnectFromServer(); + Q_SIGNALS: void connectedToServer(); void disconnectedFromServer(); diff --git a/src/networkmanager.cpp b/src/networkmanager.cpp index 500b2c832..ee261ee01 100644 --- a/src/networkmanager.cpp +++ b/src/networkmanager.cpp @@ -17,8 +17,11 @@ NetworkManager::NetworkManager(AOApplication *parent) ao_app = parent; http = new QNetworkAccessManager(this); + handshake_timer = new QTimer(this); heartbeat_timer = new QTimer(this); + handshake_timer->setSingleShot(true); + QString master_config = Options::getInstance().alternativeMasterserver(); if (!master_config.isEmpty() && QUrl(master_config).scheme().startsWith("http")) { @@ -26,7 +29,9 @@ NetworkManager::NetworkManager(AOApplication *parent) ms_baseurl = master_config; } + connect(handshake_timer, &QTimer::timeout, this, &NetworkManager::on_handshake_timeout); connect(heartbeat_timer, &QTimer::timeout, this, &NetworkManager::send_heartbeat); + heartbeat_timer->start(heartbeat_interval); } @@ -84,11 +89,27 @@ void NetworkManager::ms_request_finished(QNetworkReply *reply) reply->deleteLater(); } +void NetworkManager::on_handshake_timeout() +{ + disconnect_from_server(); + call_error(tr("Failed to connect to server: handshake was not completed in time.\n\nExpected protocol version: %1 (got none)\n\nThe server may not support the current protocol. Contact the administrator of the server you are trying to connect.").arg(ao_app->get_protocol_version_string())); +} + QString NetworkManager::get_user_agent() const { return QStringLiteral("AttorneyOnline/%1 (Desktop)").arg(ao_app->get_version_string()); } +bool NetworkManager::is_handshake_finished() const +{ + return !handshake_timer->isActive(); +} + +void NetworkManager::finish_handshake() +{ + handshake_timer->stop(); +} + void NetworkManager::send_heartbeat() { // Ping the server periodically to tell the MS that you've been playing @@ -155,10 +176,12 @@ void NetworkManager::connect_to_server(ServerInfo server) connect(m_connection, &WebSocketConnection::receivedPacket, this, &NetworkManager::handle_server_packet); m_connection->connectToServer(server); + handshake_timer->start(10000); } void NetworkManager::disconnect_from_server() { + handshake_timer->stop(); if (m_connection) { m_connection->disconnectFromServer(); diff --git a/src/networkmanager.h b/src/networkmanager.h index 8f2d8d426..e0ff65c07 100644 --- a/src/networkmanager.h +++ b/src/networkmanager.h @@ -27,11 +27,15 @@ class NetworkManager : public QObject explicit NetworkManager(AOApplication *parent); void connect_to_server(ServerInfo p_server); - void disconnect_from_server(); QString get_user_agent() const; + bool is_handshake_finished() const; + void finish_handshake(); + public Q_SLOTS: + void disconnect_from_server(); + void get_server_list(); void ship_server_packet(AOPacket packet); void join_to_server(); @@ -52,6 +56,7 @@ private Q_SLOTS: WebSocketConnection *m_connection = nullptr; + QTimer *handshake_timer; QTimer *heartbeat_timer; const QString DEFAULT_MS_BASEURL = "http://servers.aceattorneyonline.com"; @@ -60,4 +65,7 @@ private Q_SLOTS: const int heartbeat_interval = 60 * 5 * 1000; unsigned int s_decryptor = 5; + +private Q_SLOTS: + void on_handshake_timeout(); }; diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp index 9ec6fd013..f34cc7cab 100644 --- a/src/packet_distribution.cpp +++ b/src/packet_distribution.cpp @@ -28,89 +28,78 @@ void AOApplication::server_packet_received(AOPacket packet) { QString header = packet.header(); QStringList content = packet.content(); + int packet_size = packet.content().size(); bool log_to_demo = true; #ifdef DEBUG_NETWORK if (header != "checkconnection") { - qDebug() << "R:" << f_packet; + qDebug() << "R:" << packet; } #endif if (header == "decryptor") { - if (content.size() == 0) + log_to_demo = false; + if (packet_size < 1) { return; } + net_manager->server_connected(true); - // default(legacy) values - m_serverdata.set_features(QStringList()); - - QString f_hdid; - f_hdid = get_hdid(); - - QStringList f_contents = {f_hdid}; - AOPacket hi_packet("HI", f_contents); - send_server_packet(hi_packet); - log_to_demo = false; + QStringList f_contents = {get_protocol_version_string(), "AO2", get_version_string()}; + send_server_packet(AOPacket("ID", f_contents)); } else if (header == "ID") { - if (content.size() < 2) + log_to_demo = false; + if (packet_size < 3) + { + return; + } + + if (net_manager->is_handshake_finished()) { + QMessageBox::warning(nullptr, tr("Handshake Error"), tr("Handshake already completed.")); + net_manager->disconnect_from_server(); return; } + net_manager->finish_handshake(); client_id = content.at(0).toInt(); - m_serverdata.set_server_software(content.at(1)); - net_manager->server_connected(true); + QString f_hdid; + f_hdid = get_hdid(); - QStringList f_contents = {"AO2", get_version_string()}; - send_server_packet(AOPacket("ID", f_contents)); + QStringList f_contents = {f_hdid}; + AOPacket hi_packet("HI", f_contents); + send_server_packet(hi_packet); } else if (header == "CT") { - if (!is_courtroom_constructed() || content.size() < 2) + if (packet_size < 2 || !is_courtroom_constructed()) { return; } - if (content.size() == 3) - { - w_courtroom->append_server_chatmessage(content.at(0), content.at(1), content.at(2)); - } - else - { - w_courtroom->append_server_chatmessage(content.at(0), content.at(1), "0"); - } - } - else if (header == "FL") - { - m_serverdata.set_features(content); - log_to_demo = false; + w_courtroom->append_server_chatmessage(content.at(0), content.at(1), packet_size < 3 ? "0" : content.at(2)); } else if (header == "PN") { - if (!is_lobby_constructed() || content.size() < 2) + log_to_demo = false; + if (packet_size < 3 || !is_lobby_constructed()) { return; } w_lobby->set_player_count(content.at(0).toInt(), content.at(1).toInt()); - - if (content.size() >= 3) - { - w_lobby->set_server_description(content.at(2)); - } - - log_to_demo = false; + w_lobby->set_server_description(content.at(2)); } else if (header == "SI") { - if (!is_lobby_constructed() || content.size() != 3) + log_to_demo = false; + if (packet_size < 3 || !is_lobby_constructed()) { return; } @@ -176,16 +165,16 @@ void AOApplication::server_packet_received(AOPacket packet) { discord->state_server(server_name.toStdString(), hash.result().toBase64().toStdString()); } - log_to_demo = false; } else if (header == "CharsCheck") { + log_to_demo = false; if (!is_courtroom_constructed()) { return; } - for (int n_char = 0; n_char < content.size(); ++n_char) + for (int n_char = 0; n_char < packet_size; ++n_char) { if (content.at(n_char) == "-1") { @@ -196,7 +185,6 @@ void AOApplication::server_packet_received(AOPacket packet) w_courtroom->set_taken(n_char, false); } } - log_to_demo = false; } else if (header == "SC") @@ -205,8 +193,9 @@ void AOApplication::server_packet_received(AOPacket packet) { return; } + w_courtroom->clear_chars(); - for (int n_element = 0; n_element < content.size(); ++n_element) + for (int n_element = 0; n_element < packet_size; ++n_element) { QStringList sub_elements = content.at(n_element).split("&"); for (QString &sub_element : sub_elements) @@ -238,6 +227,7 @@ void AOApplication::server_packet_received(AOPacket packet) } else if (header == "SM") { + log_to_demo = false; if (!is_courtroom_constructed() || courtroom_loaded) { return; @@ -246,7 +236,7 @@ void AOApplication::server_packet_received(AOPacket packet) bool musics_time = false; int areas = 0; - for (int n_element = 0; n_element < content.size(); ++n_element) + for (int n_element = 0; n_element < packet_size; ++n_element) { if (musics_time) { @@ -275,27 +265,26 @@ void AOApplication::server_packet_received(AOPacket packet) } send_server_packet(AOPacket("RD")); - log_to_demo = false; } else if (header == "FM") // Fetch music ONLY { + log_to_demo = false; if (!is_courtroom_constructed()) { return; } w_courtroom->clear_music(); - - for (int n_element = 0; n_element < content.size(); ++n_element) + for (int n_element = 0; n_element < packet_size; ++n_element) { w_courtroom->append_music(content.at(n_element)); } w_courtroom->list_music(); - log_to_demo = false; } else if (header == "FA") // Fetch areas ONLY { + log_to_demo = false; if (!is_courtroom_constructed()) { return; @@ -304,17 +293,17 @@ void AOApplication::server_packet_received(AOPacket packet) w_courtroom->clear_areas(); w_courtroom->arup_clear(); - for (int n_element = 0; n_element < content.size(); ++n_element) + for (int n_element = 0; n_element < packet_size; ++n_element) { w_courtroom->append_area(content.at(n_element)); w_courtroom->arup_append(0, "Unknown", "Unknown", "Unknown"); } w_courtroom->list_areas(); - log_to_demo = false; } else if (header == "DONE") { + log_to_demo = false; if (!is_courtroom_constructed()) { return; @@ -326,29 +315,24 @@ void AOApplication::server_packet_received(AOPacket packet) courtroom_loaded = true; destruct_lobby(); - log_to_demo = false; } else if (header == "BN") { - if (!is_courtroom_constructed() || content.isEmpty()) + if (packet_size < 1 || !is_courtroom_constructed()) { return; } - if (content.size() >= 2) + bool has_side = packet_size == 2 && !content.at(1).isEmpty(); + if (has_side) { - // We have a pos included in the background packet! - if (!content.at(1).isEmpty()) - { - // Not touching it when its empty. - w_courtroom->set_side(content.at(1)); - } + w_courtroom->set_side(content.at(1)); } - w_courtroom->set_background(content.at(0), content.size() >= 2); + w_courtroom->set_background(content.at(0), has_side); } else if (header == "SP") { - if (!is_courtroom_constructed() || content.isEmpty()) + if (packet_size < 1 || !is_courtroom_constructed()) { return; } @@ -358,7 +342,7 @@ void AOApplication::server_packet_received(AOPacket packet) } else if (header == "SD") // Send pos dropdown { - if (!is_courtroom_constructed() || content.isEmpty()) + if (packet_size < 1 || !is_courtroom_constructed()) { return; } @@ -368,10 +352,11 @@ void AOApplication::server_packet_received(AOPacket packet) // server accepting char request(CC) packet else if (header == "PV") { - if (!is_courtroom_constructed() || content.size() < 3) + if (packet_size < 3 || !is_courtroom_constructed()) { return; } + // For some reason, args 0 and 1 are not used (from tsu3 they're client ID and a string "CID") w_courtroom->enter_courtroom(); w_courtroom->set_courtroom_size(); @@ -379,164 +364,175 @@ void AOApplication::server_packet_received(AOPacket packet) } else if (header == "MS") { - if (is_courtroom_constructed() && courtroom_loaded) + if (packet_size < Courtroom::MS_MAXIMUM || !is_courtroom_constructed() || !courtroom_loaded) { - w_courtroom->chatmessage_enqueue(packet.content()); + return; } + + w_courtroom->chatmessage_enqueue(packet.content()); } else if (header == "MC") { - if (is_courtroom_constructed() && courtroom_loaded) + if (packet_size < 2 || !is_courtroom_constructed() || !courtroom_loaded) { - w_courtroom->handle_song(&packet.content()); + return; } + + w_courtroom->handle_song(&packet.content()); } else if (header == "RT") { - if (content.isEmpty()) + if (packet_size < 2 || !is_courtroom_constructed()) { return; } - if (is_courtroom_constructed()) - { - if (content.size() == 1) - { - w_courtroom->handle_wtce(content.at(0), 0); - } - else if (content.size() >= 2) - { - w_courtroom->handle_wtce(content.at(0), content.at(1).toInt()); - } - } + + w_courtroom->handle_wtce(content.at(0), content.at(1).toInt()); } else if (header == "HP") { - if (is_courtroom_constructed() && content.size() >= 2) + if (packet_size < 2 || !is_courtroom_constructed()) { - w_courtroom->set_hp_bar(content.at(0).toInt(), content.at(1).toInt()); + return; } + + w_courtroom->set_hp_bar(content.at(0).toInt(), content.at(1).toInt()); } else if (header == "LE") { - if (is_courtroom_constructed()) + if (!is_courtroom_constructed()) { - QVector f_evi_list; - - for (QString f_string : packet.content()) - { - QStringList sub_contents = f_string.split("&"); - if (sub_contents.size() < 3) - { - continue; - } + return; + } - // decoding has to be done here instead of on reception - // because this packet uses & as a delimiter for some reason - for (QString &data : sub_contents) - { - data = AOPacket::decode(data); - } + QVector f_evi_list; - EvidenceItem f_evi; - f_evi.name = sub_contents.at(0); - f_evi.description = sub_contents.at(1); - f_evi.image = sub_contents.at(2); + for (QString f_string : packet.content()) + { + QStringList sub_contents = f_string.split("&"); + if (sub_contents.size() < 3) + { + continue; + } - f_evi_list.append(f_evi); + // decoding has to be done here instead of on reception + // because this packet uses & as a delimiter for some reason + for (QString &data : sub_contents) + { + data = AOPacket::decode(data); } - w_courtroom->set_evidence_list(f_evi_list); + EvidenceItem f_evi; + f_evi.name = sub_contents.at(0); + f_evi.description = sub_contents.at(1); + f_evi.image = sub_contents.at(2); + + f_evi_list.append(f_evi); } + + w_courtroom->set_evidence_list(f_evi_list); } else if (header == "ARUP") { - if (is_courtroom_constructed() && !content.isEmpty()) + log_to_demo = false; + if (packet_size < 1 || !is_courtroom_constructed()) { - int arup_type = content.at(0).toInt(); - for (int n_element = 1; n_element < content.size(); n_element++) - { - w_courtroom->arup_modify(arup_type, n_element - 1, content.at(n_element)); - } - w_courtroom->list_areas(); + return; } - log_to_demo = false; + + int arup_type = content.at(0).toInt(); + for (int n_element = 1; n_element < packet_size; n_element++) + { + w_courtroom->arup_modify(arup_type, n_element - 1, content.at(n_element)); + } + w_courtroom->list_areas(); } else if (header == "IL") { - if (is_courtroom_constructed() && !content.isEmpty()) + log_to_demo = false; + if (packet_size < 1 || !is_courtroom_constructed()) { - w_courtroom->set_ip_list(content.at(0)); + return; } - log_to_demo = false; + + w_courtroom->set_ip_list(content.at(0)); } else if (header == "MU") { - if (is_courtroom_constructed() && !content.isEmpty()) + log_to_demo = false; + if (packet_size < 1 || !is_courtroom_constructed()) { - w_courtroom->set_mute(true, content.at(0).toInt()); + return; } - log_to_demo = false; + + w_courtroom->set_mute(true, content.at(0).toInt()); } else if (header == "UM") { - if (is_courtroom_constructed() && !content.isEmpty()) + log_to_demo = false; + if (packet_size < 1 || !is_courtroom_constructed()) { - w_courtroom->set_mute(false, content.at(0).toInt()); - log_to_demo = false; + return; } + + w_courtroom->set_mute(false, content.at(0).toInt()); } else if (header == "BB") { - if (is_courtroom_constructed() && !content.isEmpty()) + log_to_demo = false; + if (packet_size < 1 || !is_courtroom_constructed()) { - call_notice(content.at(0)); + return; } - log_to_demo = false; + + call_notice(content.at(0)); } else if (header == "KK") { - if (is_courtroom_constructed() && !content.isEmpty()) + log_to_demo = false; + if (packet_size < 1 || !is_courtroom_constructed()) { - call_notice(tr("You have been kicked from the server.\nReason: %1").arg(content.at(0))); - construct_lobby(); - destruct_courtroom(); + return; } - log_to_demo = false; + + call_notice(tr("You have been kicked from the server.\nReason: %1").arg(content.at(0))); + construct_lobby(); + destruct_courtroom(); } else if (header == "KB") { - if (is_courtroom_constructed() && !content.isEmpty()) + log_to_demo = false; + if (packet_size < 1 || !is_courtroom_constructed()) { - call_notice(tr("You have been banned from the server.\nReason: %1").arg(content.at(0))); - construct_lobby(); - destruct_courtroom(); + return; } - log_to_demo = false; + + call_notice(tr("You have been banned from the server.\nReason: %1").arg(content.at(0))); + construct_lobby(); + destruct_courtroom(); } else if (header == "BD") { - if (content.isEmpty()) + log_to_demo = false; + if (packet_size < 1) { return; } + call_notice(tr("You are banned on this server.\nReason: %1").arg(content.at(0))); - log_to_demo = false; } else if (header == "ZZ") { - if (content.size() < 1) + if (packet_size < 1 || !is_courtroom_constructed()) { return; } - if (is_courtroom_constructed() && !content.isEmpty()) - { - w_courtroom->mod_called(content.at(0)); - } + w_courtroom->mod_called(content.at(0)); } else if (header == "TI") - { // Timer packet - if (!is_courtroom_constructed() || content.size() < 2) + { + if (packet_size < 2 || !is_courtroom_constructed()) { return; } @@ -552,7 +548,7 @@ void AOApplication::server_packet_received(AOPacket packet) if (type == 0 || type == 1) { - if (content.size() < 3) + if (packet_size < 3) { return; } @@ -589,6 +585,7 @@ void AOApplication::server_packet_received(AOPacket packet) } else if (header == "CHECK") { + log_to_demo = false; if (!is_courtroom_constructed()) { return; @@ -600,15 +597,15 @@ void AOApplication::server_packet_received(AOPacket packet) { latency = ping_time; } - log_to_demo = false; } // Subtheme packet else if (header == "ST") { - if (!is_courtroom_constructed() || content.isEmpty()) + if (packet_size < 2 || !is_courtroom_constructed()) { return; } + // Subtheme reserved as argument 0 subtheme = content.at(0); @@ -619,8 +616,8 @@ void AOApplication::server_packet_received(AOPacket packet) return; } - // Reload theme request - if (content.size() > 1 && content.at(1) == "1") + // reload theme request + if (content.at(1) == "1") { Options::getInstance().setServerSubTheme(subtheme); w_courtroom->on_reload_theme_clicked(); @@ -629,10 +626,12 @@ void AOApplication::server_packet_received(AOPacket packet) // Auth packet else if (header == "AUTH") { - if (!is_courtroom_constructed() || !m_serverdata.get_feature(server::BASE_FEATURE_SET::AUTH_PACKET) || content.isEmpty()) + log_to_demo = false; + if (packet_size < 1 || !is_courtroom_constructed()) { return; } + bool ok; int authenticated = content.at(0).toInt(&ok); if (!ok) @@ -641,14 +640,14 @@ void AOApplication::server_packet_received(AOPacket packet) } w_courtroom->on_authentication_state_received(authenticated); - log_to_demo = false; } else if (header == "JD") { - if (!is_courtroom_constructed() || content.isEmpty()) + if (packet_size < 1 || !is_courtroom_constructed()) { return; } + bool ok; Courtroom::JudgeState state = static_cast(content.at(0).toInt(&ok)); if (!ok) @@ -669,8 +668,8 @@ void AOApplication::server_packet_received(AOPacket packet) // AssetURL Packet else if (header == "ASS") { - if (content.size() > 1 || content.isEmpty()) - { // This can never be more than one link. + if (packet_size < 1) + { return; } diff --git a/src/serverdata.cpp b/src/serverdata.cpp index 5b3d139db..25b7a9b23 100644 --- a/src/serverdata.cpp +++ b/src/serverdata.cpp @@ -1,30 +1,9 @@ #include #include -#include namespace server { -bool ServerData::get_feature(const BASE_FEATURE_SET &f_feature) const -{ - return get_feature(QVariant::fromValue(f_feature).toString()); -} - -bool ServerData::get_feature(const QString &f_feature) const -{ - return m_features.contains(f_feature, Qt::CaseInsensitive); -} - -void ServerData::set_features(const QStringList &f_feature_list) -{ - m_features = f_feature_list; -} - -void ServerData::set_server_software(const QString &newServer_software) -{ - m_server_software = newServer_software; -} - QString ServerData::get_asset_url() const { return m_asset_url; diff --git a/src/serverdata.h b/src/serverdata.h index 993518529..ccd5382a0 100644 --- a/src/serverdata.h +++ b/src/serverdata.h @@ -7,113 +7,12 @@ namespace server { -Q_NAMESPACE - -/// The base feature set that almost all servers are supposed to support. -enum class BASE_FEATURE_SET -{ - YELLOWTEXT, ///< Yellow text in in-character messages. - ///< @since 2.1.0 - FLIPPING, ///< The ability to mirror a character in-game. - ///< @since 2.1.0 - CUSTOMOBJECTIONS, ///< Enables the use of a single custom objection named - ///< `custom`. - ///< @since 2.1.0 - FASTLOADING, ///< Enables the use of "fast loading" instead of the legacy - ///< loading protocol. - ///< @since 2.1.0 - NOENCRYPTION, ///< Disables "FantaCrypt" for the remainder of the session. - ///< @since 2.1.0 - DESKMOD, ///< Allows forcing the appearance or disappearance of the desk. - ///< @since 2.3 to 2.5 - EVIDENCE, ///< Allows creating and presenting evidence. - ///< @since 2.3 to 2.5 - CCCC_IC_SUPPORT, ///< The ability to pair up with another user's character, - ///< the ability to change one's displayed name - ///< in-character ("showname"), and the ability to perform - ///< "immediate" preanimations (ones that happen alongside - ///< text display). - ///< @since 2.6.0 - ARUP, ///< Areas have more data about them than just their name (including - ///< their status, their "lockedness", and who is the Case Master in - ///< the area), and sets the client up to receive and send ARUP - ///< packets. - ///< @since 2.6.0 - CASING_ALERTS, ///< The client gains a new window to announce cases with, - ///< and the settings to set itself up to receive case alerts - ///< based on casing preferences. No longer used. - ///< @since 2.6.0 - MODCALL_REASON, ///< Enables entering a custom reason for calling - ///< moderators. - ///< @since 2.6.0 - LOOPING_SFX, ///< Enables looping SFX extensions for the in-character - ///< command. - ///< @since 2.8.0 - ADDITIVE, ///< Enables "additive" text that allows in-character messages to - ///< concatenate to the previous one sent by the same character. - ///< @since 2.8.0 - EFFECTS, ///< Enables effect overlays. - ///< @since 2.8.0 - Y_OFFSET, ///< Enables support for vertical offsets. - ///< @since 2.9.0 - EXPANDED_DESK_MODS, ///< Enables desk modifiers 2 through 5. - ///< @since 2.9.0 - AUTH_PACKET, ///< Enables the use of the AUTH packet. - ///< @since 2.9.1 - PREZOOM, ///< Preanim zoom. - CUSTOM_BLIPS ///< Allows the in-character messages to contain data about - ///< what blips to use for the character's current message. -}; -Q_ENUM_NS(BASE_FEATURE_SET) - /** * @brief Arranges data about the server the client is connected to. */ class ServerData { public: - /** - * @brief Returns true if one of the standard features exists on the server. - * - * @details Internally, this calls get_feature(const QString &f_feature) - * with the enum's value converted to string. - * - * @param f_feature The feature to check for. - * - * @return True if the feature exists on the server. - */ - bool get_feature(const BASE_FEATURE_SET &f_feature) const; - - /** - * @brief Returns true if the feature exists on the server. - * - * @param f_feature The feature to check for. Case insensitive. - * - * @return True if the feature exists on the server. - */ - bool get_feature(const QString &f_feature) const; - - /** - * @brief Sets the feature list, overwriting the existing one. - * - * @param f_feature_list The new feature list of the server. - */ - void set_features(const QStringList &f_feature_list); - - /** - * @brief Self-explanatory: gets the software the server is running on. - * - * @return As brief description. - */ - QString get_server_software() const; - - /** - * @brief Self-explanatory: setter for server software. - * - * @param f_software The new server software. - */ - void set_server_software(const QString &f_software); - /** * @brief Getter for the server's asset URL. * @@ -135,12 +34,6 @@ class ServerData void set_asset_url(const QString &f_asset_url); private: - /// The features available on the server. Determines what - QStringList m_features; - - /// The software the server is running. - QString m_server_software; - /** * @brief A QString of an URL that defines the content repository * send by the server.