Merge branch 'master' into kaleidoscope

This commit is contained in:
TrickyLeifa 2024-05-17 19:19:04 +02:00
commit fefaad5394
6 changed files with 348 additions and 282 deletions

View File

@ -74,7 +74,9 @@ jobs:
rm -rf $ANDROID_HOME/ndk/25.2.9519653 rm -rf $ANDROID_HOME/ndk/25.2.9519653
ln -sf $ANDROID_HOME/ndk/21.4.7075529 $ANDROID_HOME/ndk/25.2.9519653 ln -sf $ANDROID_HOME/ndk/21.4.7075529 $ANDROID_HOME/ndk/25.2.9519653
- uses: jurplel/install-qt-action@v3 - name: Install Qt
if: matrix.os != 'ubuntu-latest'
uses: jurplel/install-qt-action@v3
id: qt id: qt
with: with:
version: ${{matrix.version}} version: ${{matrix.version}}
@ -84,6 +86,13 @@ jobs:
cache: true cache: true
cache-key-prefix: qt cache-key-prefix: qt
- name: Install Qt (Ubuntu)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install qtbase5-dev libqt5websockets5-dev qttools5-dev qt5-image-formats-plugins
- name: Add tools to PATH (MinGW) - name: Add tools to PATH (MinGW)
if: matrix.platform == 'mingw81_32' if: matrix.platform == 'mingw81_32'
shell: bash shell: bash
@ -93,7 +102,7 @@ jobs:
if: contains(matrix.platform, 'msvc') if: contains(matrix.platform, 'msvc')
uses: ilammy/msvc-dev-cmd@v1 uses: ilammy/msvc-dev-cmd@v1
- name: Install QtApng - name: Build QtApng
run: | run: |
git clone https://github.com/Skycoder42/QtApng.git git clone https://github.com/Skycoder42/QtApng.git
cd QtApng cd QtApng
@ -103,7 +112,18 @@ jobs:
cd ../.. cd ../..
qmake CONFIG+=install_ok QMAKE_CXXFLAGS+="-fno-sized-deallocation" QT_PLATFORM=${{matrix.platform}} qmake CONFIG+=install_ok QMAKE_CXXFLAGS+="-fno-sized-deallocation" QT_PLATFORM=${{matrix.platform}}
${{matrix.make}} ${{matrix.make}}
- name: Install QtApng
if: matrix.os != 'ubuntu-latest'
run: |
cd QtApng
${{matrix.make}} INSTALL_ROOT="${Qt5_DIR}" install ${{matrix.make}} INSTALL_ROOT="${Qt5_DIR}" install
- name: Install QtApng (Ubuntu)
if: matrix.os == 'ubuntu-latest'
run: |
cd QtApng
sudo ${{matrix.make}} install
- name: Install Windows Discord RPC - name: Install Windows Discord RPC
if: contains(matrix.os, 'windows') if: contains(matrix.os, 'windows')

View File

@ -4,6 +4,7 @@
#include "datatypes.h" #include "datatypes.h"
#include "demoserver.h" #include "demoserver.h"
#include "discord_rich_presence.h" #include "discord_rich_presence.h"
#include "serverdata.h"
#include "widgets/aooptionsdialog.h" #include "widgets/aooptionsdialog.h"
#include "bass.h" #include "bass.h"
@ -84,48 +85,31 @@ public:
qint64 latency = 0; qint64 latency = 0;
QString window_title; QString window_title;
/////////////////server metadata////////////////// /// Stores everything related to the server the client is connected to, if
/// any.
bool yellow_text_supported = false; server::ServerData m_serverdata;
bool prezoom_supported = false;
bool flipping_supported = false;
bool custom_objection_supported = false;
bool desk_mod_supported = false;
bool evidence_supported = false;
bool cccc_ic_supported = false;
bool arup_supported = false;
bool casing_alerts_supported = false;
bool modcall_reason_supported = false;
bool looping_sfx_supported = false;
bool additive_supported = false;
bool effects_supported = false;
bool y_offset_supported = false;
bool expanded_desk_mods_supported = false;
bool auth_packet_supported = false;
bool custom_blips_supported = false;
///////////////loading info/////////////////// ///////////////loading info///////////////////
// client ID. Not useful, to be removed eventually // client ID. Not useful, to be removed eventually
int client_id = 0; int client_id = 0;
QString server_software; /// Used for a fancy loading bar upon joining a server.
int char_list_size = 0;
int loaded_chars = 0;
int generated_chars = 0; int generated_chars = 0;
int evidence_list_size = 0;
int loaded_evidence = 0;
int music_list_size = 0;
int loaded_music = 0;
bool courtroom_loaded = false; bool courtroom_loaded = false;
//////////////////versioning/////////////// /**
* @brief Returns the version string of the software.
*
* @return The string "X.Y.Z", where X is the release of the software (usually
* '2'), Y is the major version, and Z is the minor version.
*/
static QString get_version_string();
QString get_version_string(); static const int RELEASE = 2;
static const int MAJOR_VERSION = 10;
/////////////////////////////////////////// static const int MINOR_VERSION = 1;
void set_server_list(QVector<ServerInfo> &servers) { server_list = servers; } void set_server_list(QVector<ServerInfo> &servers) { server_list = servers; }
QVector<ServerInfo> &get_server_list() { return server_list; } QVector<ServerInfo> &get_server_list() { return server_list; }
@ -335,16 +319,6 @@ public:
// The file name of the log file in base/logs. // The file name of the log file in base/logs.
QString log_filename; QString log_filename;
/**
* @brief A QString of an URL that defines the content repository
* send by the server.
*
* @details Introduced in Version 2.9.2.
* Addresses the issue of contenturl devlivery for WebAO
* without relying on someone adding the link manually.
*/
QString asset_url;
void initBASS(); void initBASS();
static void load_bass_plugins(); static void load_bass_plugins();
static void CALLBACK BASSreset(HSTREAM handle, DWORD channel, DWORD data, void *user); static void CALLBACK BASSreset(HSTREAM handle, DWORD channel, DWORD data, void *user);
@ -354,10 +328,6 @@ public:
DemoServer *demo_server = nullptr; DemoServer *demo_server = nullptr;
private: private:
const int RELEASE = 2;
const int MAJOR_VERSION = 11;
const int MINOR_VERSION = 0;
QVector<ServerInfo> server_list; QVector<ServerInfo> server_list;
QHash<uint, QString> asset_lookup_cache; QHash<uint, QString> asset_lookup_cache;
QHash<uint, QString> dir_listing_cache; QHash<uint, QString> dir_listing_cache;

View File

@ -727,8 +727,8 @@ void Courtroom::set_widgets()
// If there is a point to it, show all CCCC features. // 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, // We also do this this soon so that set_size_and_pos can hide them all later,
// if needed. // if needed.
if (ao_app->cccc_ic_supported) if (ao_app->m_serverdata.get_feature(
{ server::BASE_FEATURE_SET::CCCC_IC_SUPPORT)) {
ui_pair_button->show(); ui_pair_button->show();
ui_immediate->show(); ui_immediate->show();
ui_showname_enable->show(); ui_showname_enable->show();
@ -1574,7 +1574,8 @@ void Courtroom::update_character(int p_cid, QString char_name, bool reset_emote)
} }
ui_custom_objection->hide(); ui_custom_objection->hide();
if (ao_app->custom_objection_supported) // if setting is enabled if (ao_app->m_serverdata.get_feature(
server::BASE_FEATURE_SET::CUSTOMOBJECTIONS)) // if setting is enabled
{ {
custom_obj_menu->clear(); custom_obj_menu->clear();
custom_objections_list.clear(); custom_objections_list.clear();
@ -1648,8 +1649,7 @@ void Courtroom::enter_courtroom()
{ {
set_evidence_page(); set_evidence_page();
if (ao_app->flipping_supported) if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::FLIPPING))
{
ui_flip->show(); ui_flip->show();
} }
else else
@ -1657,8 +1657,7 @@ void Courtroom::enter_courtroom()
ui_flip->hide(); ui_flip->hide();
} }
if (ao_app->additive_supported) if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::ADDITIVE))
{
ui_additive->show(); ui_additive->show();
} }
else else
@ -1711,8 +1710,6 @@ void Courtroom::list_music()
QBrush found_brush(ao_app->get_color("found_song_color", f_file)); QBrush found_brush(ao_app->get_color("found_song_color", f_file));
QBrush missing_brush(ao_app->get_color("missing_song_color", f_file)); QBrush missing_brush(ao_app->get_color("missing_song_color", f_file));
int n_listed_songs = 0;
QTreeWidgetItem *parent = nullptr; QTreeWidgetItem *parent = nullptr;
for (int n_song = 0; n_song < music_list.size(); ++n_song) for (int n_song = 0; n_song < music_list.size(); ++n_song)
{ {
@ -1779,8 +1776,7 @@ void Courtroom::list_areas()
QString i_area; QString i_area;
i_area.append(area_list.at(n_area)); i_area.append(area_list.at(n_area));
if (ao_app->arup_supported) if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::ARUP)) {
{
i_area.append("\n "); i_area.append("\n ");
i_area.append(arup_statuses.at(n_area)); i_area.append(arup_statuses.at(n_area));
@ -1810,8 +1806,7 @@ void Courtroom::list_areas()
treeItem->setText(0, area_list.at(n_area)); treeItem->setText(0, area_list.at(n_area));
treeItem->setText(1, i_area); treeItem->setText(1, i_area);
if (ao_app->arup_supported) if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::ARUP)) {
{
// Coloring logic here. // Coloring logic here.
treeItem->setBackground(1, free_brush); treeItem->setBackground(1, free_brush);
if (arup_locks.at(n_area) == "LOCKED") if (arup_locks.at(n_area) == "LOCKED")
@ -1878,11 +1873,12 @@ void Courtroom::append_server_chatmessage(QString p_name, QString p_message, QSt
color = ao_app->get_color("ms_chatlog_sender_color", "courtroom_fonts.ini").name(); color = ao_app->get_color("ms_chatlog_sender_color", "courtroom_fonts.ini").name();
} }
if (p_color == "1") if (p_color == "1")
{ {color =
color = ao_app->get_color("server_chatlog_sender_color", "courtroom_fonts.ini").name(); ao_app->get_color("server_chatlog_sender_color", "courtroom_fonts.ini")
} .name();}
if (!ao_app->auth_packet_supported && p_message == "Logged in as a moderator.") if (!ao_app->m_serverdata.get_feature(
{ server::BASE_FEATURE_SET::AUTH_PACKET) &&
p_message == "Logged in as a moderator.") {
// Emulate successful authentication // Emulate successful authentication
on_authentication_state_received(1); on_authentication_state_received(1);
} }
@ -1978,11 +1974,10 @@ void Courtroom::on_chat_return_pressed()
int f_desk_mod = DESK_SHOW; int f_desk_mod = DESK_SHOW;
if (ao_app->desk_mod_supported) if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::DESKMOD)) {
{ f_desk_mod = ao_app->get_desk_mod(current_char, current_emote);{}
f_desk_mod = ao_app->get_desk_mod(current_char, current_emote); if (!ao_app->m_serverdata.get_feature(
if (!ao_app->expanded_desk_mods_supported) server::BASE_FEATURE_SET::EXPANDED_DESK_MODS)) {
{
if (f_desk_mod == DESK_PRE_ONLY_EX || f_desk_mod == DESK_PRE_ONLY) if (f_desk_mod == DESK_PRE_ONLY_EX || f_desk_mod == DESK_PRE_ONLY)
{ {
f_desk_mod = DESK_HIDE; f_desk_mod = DESK_HIDE;
@ -2033,8 +2028,8 @@ void Courtroom::on_chat_return_pressed()
f_emote_mod = PREANIM; f_emote_mod = PREANIM;
} }
// Turn zoom into preanim zoom // Turn zoom into preanim zoom
else if (f_emote_mod == ZOOM && ao_app->prezoom_supported) else if (f_emote_mod == ZOOM && ao_app->m_serverdata.get_feature(
{ server::BASE_FEATURE_SET::PREZOOM)) {
f_emote_mod = PREANIM_ZOOM; f_emote_mod = PREANIM_ZOOM;
} }
// Play the sfx // Play the sfx
@ -2096,8 +2091,10 @@ void Courtroom::on_chat_return_pressed()
QString f_obj_state; QString f_obj_state;
if ((objection_state == 4 && !ao_app->custom_objection_supported) || (objection_state < 0)) if ((objection_state == 4 &&
{ !ao_app->m_serverdata.get_feature(
server::BASE_FEATURE_SET::CUSTOMOBJECTIONS)) ||
(objection_state < 0)) {
f_obj_state = "0"; f_obj_state = "0";
} }
else if (objection_custom != "" && objection_state == 4) else if (objection_custom != "" && objection_state == 4)
@ -2131,8 +2128,7 @@ void Courtroom::on_chat_return_pressed()
QString f_flip; QString f_flip;
if (ao_app->flipping_supported) if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::FLIPPING)) {
{
if (ui_flip->isChecked()) if (ui_flip->isChecked())
{ {
f_flip = "1"; f_flip = "1";
@ -2169,12 +2165,11 @@ void Courtroom::on_chat_return_pressed()
packet_contents.append(f_text_color); packet_contents.append(f_text_color);
// If the server we're on supports CCCC stuff, we should use it! // If the server we're on supports CCCC stuff, we should use it!
if (ao_app->cccc_ic_supported) 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 // If there is a showname entered, use that -- else, just send an empty
// packet-part. // packet-part.
if (!ui_ic_chat_name->text().isEmpty()) if (!ui_ic_chat_name->text().isEmpty()) {
{
packet_contents.append(ui_ic_chat_name->text()); packet_contents.append(ui_ic_chat_name->text());
} }
else else
@ -2187,9 +2182,11 @@ void Courtroom::on_chat_return_pressed()
if (other_charid > -1 && other_charid != m_cid) if (other_charid > -1 && other_charid != m_cid)
{ {
QString packet = QString::number(other_charid); QString packet = QString::number(other_charid);
if (ao_app->effects_supported) // Only servers with effects enabled will if (ao_app->m_serverdata.get_feature(
// support pair reordering server::BASE_FEATURE_SET::EFFECTS)) // Only servers with effects
{ // enabled will support pair
// reordering
{
packet += "^" + QString::number(pair_order); packet += "^" + QString::number(pair_order);
} }
packet_contents.append(packet); packet_contents.append(packet);
@ -2199,10 +2196,9 @@ void Courtroom::on_chat_return_pressed()
packet_contents.append("-1"); packet_contents.append("-1");
} }
// Send the offset as it's gonna be used regardless // Send the offset as it's gonna be used regardless
if (ao_app->y_offset_supported) if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::Y_OFFSET)){
{ packet_contents.append(QString::number(char_offset) + "&" +
packet_contents.append(QString::number(char_offset) + "&" + QString::number(char_vert_offset)); QString::number(char_vert_offset));}
}
else else
{ {
packet_contents.append(QString::number(char_offset)); packet_contents.append(QString::number(char_offset));
@ -2221,9 +2217,9 @@ void Courtroom::on_chat_return_pressed()
// If the server we're on supports Looping SFX and Screenshake, use it if the // If the server we're on supports Looping SFX and Screenshake, use it if the
// emote uses it. // emote uses it.
if (ao_app->looping_sfx_supported) if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::LOOPING_SFX)) {
{ packet_contents.append(
packet_contents.append(ao_app->get_sfx_looping(current_char, current_emote)); ao_app->get_sfx_looping(current_char, current_emote));
packet_contents.append(QString::number(screenshake_state)); packet_contents.append(QString::number(screenshake_state));
QString pre_emote = ao_app->get_pre_emote(current_char, current_emote); QString pre_emote = ao_app->get_pre_emote(current_char, current_emote);
@ -2251,14 +2247,14 @@ void Courtroom::on_chat_return_pressed()
} }
} }
if (ao_app->additive_supported) if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::ADDITIVE)) {
{
packet_contents.append(ui_additive->isChecked() ? "1" : "0"); packet_contents.append(ui_additive->isChecked() ? "1" : "0");
} }
if (ao_app->effects_supported) if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::EFFECTS)) {
{ QString p_effect_folder =
QString p_effect_folder = ao_app->read_char_ini(current_char, "effects", "Options"); ao_app->read_char_ini(current_char, "effects", "Options");
QString fx_sound = ao_app->get_effect_property(effect, current_char, p_effect_folder, "sound"); QString fx_sound =
ao_app->get_effect_property(effect, current_char, p_effect_folder, "sound");
// Don't overlap the two sfx // Don't overlap the two sfx
if (!ui_pre->isChecked() && (!custom_sfx.isEmpty() || ui_sfx_dropdown->currentIndex() == 1)) if (!ui_pre->isChecked() && (!custom_sfx.isEmpty() || ui_sfx_dropdown->currentIndex() == 1))
@ -2438,8 +2434,10 @@ void Courtroom::unpack_chatmessage(QStringList p_contents)
// amongst the packet's content. We also have to check if the server even // 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 // 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. // forget! A size 15 message will have indices from 0 to 14.
if (n_string < p_contents.size() && (n_string < MS_MINIMUM || ao_app->cccc_ic_supported)) 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); m_chatmessage[n_string] = p_contents.at(n_string);
} }
else else
@ -2796,8 +2794,9 @@ void Courtroom::display_pair_character(QString other_charid, QString other_offse
} }
} }
// Flip the pair character // Flip the pair character
if (ao_app->flipping_supported && m_chatmessage[OTHER_FLIP].toInt() == 1) if (ao_app->m_serverdata.get_feature(
{ server::BASE_FEATURE_SET::FLIPPING) &&
m_chatmessage[OTHER_FLIP].toInt() == 1){
ui_vp_sideplayer_char->set_flipped(true); ui_vp_sideplayer_char->set_flipped(true);
} }
else else
@ -4005,8 +4004,9 @@ void Courtroom::start_chat_ticking()
QString f_blips = ao_app->get_blipname(m_chatmessage[CHAR_NAME]); QString f_blips = ao_app->get_blipname(m_chatmessage[CHAR_NAME]);
f_blips = ao_app->get_blips(f_blips); f_blips = ao_app->get_blips(f_blips);
if (ao_app->custom_blips_supported && !m_chatmessage[BLIPNAME].isEmpty()) if (ao_app->m_serverdata.get_feature(
{ server::BASE_FEATURE_SET::CUSTOM_BLIPS) &&
!m_chatmessage[BLIPNAME].isEmpty()) {
f_blips = ao_app->get_blips(m_chatmessage[BLIPNAME]); f_blips = ao_app->get_blips(m_chatmessage[BLIPNAME]);
} }
blip_player->setBlip(f_blips); blip_player->setBlip(f_blips);
@ -4463,9 +4463,11 @@ void Courtroom::handle_song(QStringList *p_contents)
} }
} }
if (!file_exists(ao_app->get_sfx_suffix(ao_app->get_music_path(f_song))) && !f_song.startsWith("http") && f_song != "~stop.mp3" && !ao_app->asset_url.isEmpty()) if (!file_exists(ao_app->get_sfx_suffix(ao_app->get_music_path(f_song))) &&
{ !f_song.startsWith("http") && f_song != "~stop.mp3" &&
f_song = (ao_app->asset_url + "sounds/music/" + f_song).toLower(); !ao_app->m_serverdata.get_asset_url().isEmpty()) {
f_song = (ao_app->m_serverdata.get_asset_url() + "sounds/music/" + f_song)
.toLower();
} }
bool is_stop = (f_song == "~stop.mp3"); bool is_stop = (f_song == "~stop.mp3");
@ -4684,12 +4686,11 @@ void Courtroom::on_ooc_return_pressed()
{ {
QString ooc_message = ui_ooc_chat_message->text(); QString ooc_message = ui_ooc_chat_message->text();
// We ignore it when the server is compatible with 2.8 //We ignore it when the server is compatible with 2.8
// Using an arbitrary 2.8 feature flag certainly won't cause issues someday. //Using an arbitrary 2.8 feature flag certainly won't cause issues someday.
if (ooc_message.startsWith("/pos") & !ao_app->effects_supported) if (ooc_message.startsWith("/pos") &&
{ ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::EFFECTS)) {
if (ooc_message == "/pos jud") if (ooc_message == "/pos jud") {
{
show_judge_controls(true); show_judge_controls(true);
} }
else else
@ -5513,12 +5514,12 @@ void Courtroom::on_music_list_double_clicked(QTreeWidgetItem *p_item, int column
QStringList packet_contents; QStringList packet_contents;
packet_contents.append(p_song); packet_contents.append(p_song);
packet_contents.append(QString::number(m_cid)); packet_contents.append(QString::number(m_cid));
if ((!ui_ic_chat_name->text().isEmpty() && ao_app->cccc_ic_supported) || ao_app->effects_supported) 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()); packet_contents.append(ui_ic_chat_name->text());
} if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::EFFECTS)){
if (ao_app->effects_supported)
{
packet_contents.append(QString::number(music_flags)); packet_contents.append(QString::number(music_flags));
} }
ao_app->send_server_packet(AOPacket("MC", packet_contents)); ao_app->send_server_packet(AOPacket("MC", packet_contents));
@ -5664,21 +5665,17 @@ void Courtroom::music_stop(bool no_effects)
QStringList packet_contents; // its music list QStringList packet_contents; // its music list
packet_contents.append(fake_song); // this is our fake song, playing it triggers special code 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(QString::number(m_cid));
if ((!ui_ic_chat_name->text().isEmpty() && ao_app->cccc_ic_supported) || ao_app->effects_supported) 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()); packet_contents.append(ui_ic_chat_name->text());
} if (ao_app->m_serverdata.get_feature(server::BASE_FEATURE_SET::EFFECTS)) {
if (ao_app->effects_supported)
{
if (no_effects) if (no_effects)
{
packet_contents.append("0"); packet_contents.append("0");
}
else else
{
packet_contents.append(QString::number(music_flags)); packet_contents.append(QString::number(music_flags));
}
}
ao_app->send_server_packet(AOPacket("MC", packet_contents)); ao_app->send_server_packet(AOPacket("MC", packet_contents));
} }
@ -5868,10 +5865,8 @@ void Courtroom::on_pair_clicked()
{ {
ui_pair_list->show(); ui_pair_list->show();
ui_pair_offset_spinbox->show(); ui_pair_offset_spinbox->show();
if (ao_app->y_offset_supported) 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_pair_order_dropdown->show();
ui_mute_list->hide(); ui_mute_list->hide();
ui_mute->setImage("mute"); ui_mute->setImage("mute");
@ -6184,8 +6179,8 @@ void Courtroom::on_spectator_clicked()
void Courtroom::on_call_mod_clicked() void Courtroom::on_call_mod_clicked()
{ {
if (ao_app->modcall_reason_supported) if (ao_app->m_serverdata.get_feature(
{ server::BASE_FEATURE_SET::MODCALL_REASON)) {
QMessageBox errorBox; QMessageBox errorBox;
QInputDialog input; QInputDialog input;

View File

@ -46,21 +46,7 @@ void AOApplication::server_packet_received(AOPacket packet)
} }
// default(legacy) values // default(legacy) values
yellow_text_supported = false; m_serverdata.set_features(QStringList());
prezoom_supported = false;
flipping_supported = false;
custom_objection_supported = false;
desk_mod_supported = false;
evidence_supported = false;
cccc_ic_supported = false;
arup_supported = false;
casing_alerts_supported = false;
modcall_reason_supported = false;
looping_sfx_supported = false;
additive_supported = false;
effects_supported = false;
y_offset_supported = false;
custom_blips_supported = false;
QString f_hdid; QString f_hdid;
f_hdid = get_hdid(); f_hdid = get_hdid();
@ -78,7 +64,7 @@ void AOApplication::server_packet_received(AOPacket packet)
} }
client_id = content.at(0).toInt(); client_id = content.at(0).toInt();
server_software = content.at(1); m_serverdata.set_server_software(content.at(1));
net_manager->server_connected(true); net_manager->server_connected(true);
@ -101,94 +87,8 @@ void AOApplication::server_packet_received(AOPacket packet)
w_courtroom->append_server_chatmessage(content.at(0), content.at(1), "0"); w_courtroom->append_server_chatmessage(content.at(0), content.at(1), "0");
} }
} }
else if (header == "FL") else if (header == "FL") {
{ m_serverdata.set_features(content);
yellow_text_supported = false;
prezoom_supported = false;
flipping_supported = false;
custom_objection_supported = false;
desk_mod_supported = false;
evidence_supported = false;
cccc_ic_supported = false;
arup_supported = false;
casing_alerts_supported = false;
modcall_reason_supported = false;
looping_sfx_supported = false;
additive_supported = false;
effects_supported = false;
expanded_desk_mods_supported = false;
auth_packet_supported = false;
custom_blips_supported = false;
log_to_demo = false;
if (content.contains("yellowtext", Qt::CaseInsensitive))
{
yellow_text_supported = true;
}
if (content.contains("prezoom", Qt::CaseInsensitive))
{
prezoom_supported = true;
}
if (content.contains("flipping", Qt::CaseInsensitive))
{
flipping_supported = true;
}
if (content.contains("customobjections", Qt::CaseInsensitive))
{
custom_objection_supported = true;
}
if (content.contains("deskmod", Qt::CaseInsensitive))
{
desk_mod_supported = true;
}
if (content.contains("evidence", Qt::CaseInsensitive))
{
evidence_supported = true;
}
if (content.contains("cccc_ic_support", Qt::CaseInsensitive))
{
cccc_ic_supported = true;
}
if (content.contains("arup", Qt::CaseInsensitive))
{
arup_supported = true;
}
if (content.contains("casing_alerts", Qt::CaseInsensitive))
{
casing_alerts_supported = true;
}
if (content.contains("modcall_reason", Qt::CaseInsensitive))
{
modcall_reason_supported = true;
}
if (content.contains("looping_sfx", Qt::CaseInsensitive))
{
looping_sfx_supported = true;
}
if (content.contains("additive", Qt::CaseInsensitive))
{
additive_supported = true;
}
if (content.contains("effects", Qt::CaseInsensitive))
{
effects_supported = true;
}
if (content.contains("y_offset", Qt::CaseInsensitive))
{
y_offset_supported = true;
}
if (content.contains("expanded_desk_mods", Qt::CaseInsensitive))
{
expanded_desk_mods_supported = true;
}
if (content.contains("auth_packet", Qt::CaseInsensitive))
{
auth_packet_supported = true;
}
if (content.contains("custom_blips", Qt::CaseInsensitive))
{
custom_blips_supported = true;
}
log_to_demo = false; log_to_demo = false;
} }
else if (header == "PN") else if (header == "PN")
@ -223,42 +123,35 @@ void AOApplication::server_packet_received(AOPacket packet)
return; return;
} }
loaded_chars = 0; generated_chars = 0;
loaded_evidence = 0;
loaded_music = 0;
generated_chars = 0;
destruct_courtroom(); destruct_courtroom();
construct_courtroom(); construct_courtroom();
courtroom_loaded = false; courtroom_loaded = false;
int selected_server = w_lobby->get_selected_server(); int selected_server = w_lobby->get_selected_server();
QString server_address; QString server_address ;
QString server_name; QString server_name ;
switch (w_lobby->pageSelected()) switch (w_lobby->pageSelected()) {
{ case 0:
case 0: if (selected_server >= 0 && selected_server < server_list.size()) {
if (selected_server >= 0 && selected_server < server_list.size()) auto info = server_list.at(selected_server);
{ server_name = info.name;
auto info = server_list.at(selected_server); server_address = QString("%1:%2").arg(info.ip, QString::number(info.port));
server_name = info.name; window_title = server_name;
server_address = QString("%1:%2").arg(info.ip, QString::number(info.port)); }
window_title = server_name; break;
}
break; case 1: {
case 1: QVector<ServerInfo> favorite_list = Options::getInstance().favorites();
{ if (selected_server >= 0 && selected_server < favorite_list.size()) {
QVector<ServerInfo> favorite_list = Options::getInstance().favorites(); auto info = favorite_list.at(selected_server);
if (selected_server >= 0 && selected_server < favorite_list.size()) server_name = info.name;
{ server_address = QString("%1:%2").arg(info.ip, QString::number(info.port));
auto info = favorite_list.at(selected_server); window_title = server_name;
server_name = info.name; }
server_address = QString("%1:%2").arg(info.ip, QString::number(info.port)); } break;
window_title = server_name;
}
}
break;
case 2: case 2:
window_title = "Local Demo Recording"; window_title = "Local Demo Recording";
break; break;
@ -361,11 +254,9 @@ void AOApplication::server_packet_received(AOPacket packet)
bool musics_time = false; bool musics_time = false;
int areas = 0; int areas = 0;
for (int n_element = 0; n_element < content.size(); ++n_element) for (int n_element = 0; n_element < content.size(); ++n_element) {
{
++loaded_music; ++loaded_music;
if (musics_time) if (musics_time) {
{
w_courtroom->append_music(content.at(n_element)); w_courtroom->append_music(content.at(n_element));
} }
else else
@ -738,11 +629,11 @@ void AOApplication::server_packet_received(AOPacket packet)
} }
} }
// Auth packet // Auth packet
else if (header == "AUTH") else if (header == "AUTH") {
{ if (!is_courtroom_constructed() ||
if (!is_courtroom_constructed() || !auth_packet_supported || content.isEmpty()) !m_serverdata.get_feature(server::BASE_FEATURE_SET::AUTH_PACKET) ||
{ contents.isEmpty()) {
return; return;
} }
bool ok; bool ok;
int authenticated = content.at(0).toInt(&ok); int authenticated = content.at(0).toInt(&ok);
@ -784,11 +675,8 @@ void AOApplication::server_packet_received(AOPacket packet)
{ // This can never be more than one link. { // This can never be more than one link.
return; return;
} }
QUrl t_asset_url = QUrl::fromPercentEncoding(content.at(0).toUtf8());
if (t_asset_url.isValid()) m_serverdata.set_asset_url(contents.at(0));
{
asset_url = t_asset_url.toString();
}
} }
if (log_to_demo) if (log_to_demo)

40
src/serverdata.cpp Normal file
View File

@ -0,0 +1,40 @@
#include <serverdata.h>
#include <QUrl>
#include <QVariant>
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; }
void ServerData::set_asset_url(const QString &f_asset_url)
{
QUrl l_asset_url = QUrl::fromPercentEncoding(f_asset_url.toUtf8());
if (l_asset_url.isValid()) {
m_asset_url = l_asset_url.toString();
}
m_asset_url = f_asset_url;
}
} // namespace server

153
src/serverdata.h Normal file
View File

@ -0,0 +1,153 @@
#ifndef SERVERDATA_H
#define SERVERDATA_H
#include <QObject>
#include <QString>
#include <QStringList>
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.
*
* @return As brief description.
*
* @see m_asset_url
*/
QString get_asset_url() const;
/**
* @brief Attempts to set the new asset URL for the server.
*
* @details The function converts the sole parameter into UTF-8, then
* attempts to percent decode it. The URL is only set if all these steps
* successfully happen.
*
* @param f_asset_url A QString that contains the URL.
*/
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.
*
* @details Introduced in Version 2.9.2.
* Addresses the issue of contenturl devlivery for WebAO
* without relying on someone adding the link manually.
*/
QString m_asset_url;
};
} // namespace server
#endif // SERVERDATA_H