diff --git a/courtroom.cpp b/courtroom.cpp index 15d5025..28540de 100644 --- a/courtroom.cpp +++ b/courtroom.cpp @@ -116,7 +116,8 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_server_chatlog->setOpenExternalLinks(true); ui_mute_list = new QListWidget(this); - //ui_area_list = new QListWidget(this); + ui_area_list = new QListWidget(this); + ui_area_list->hide(); ui_music_list = new QListWidget(this); ui_pair_list = new QListWidget(this); @@ -188,6 +189,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_reload_theme = new AOButton(this, ao_app); ui_call_mod = new AOButton(this, ao_app); ui_settings = new AOButton(this, ao_app); + ui_switch_area_music = new AOButton(this, ao_app); ui_pre = new QCheckBox(this); ui_pre->setText("Pre"); @@ -273,6 +275,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() connect(ui_ooc_chat_message, SIGNAL(returnPressed()), this, SLOT(on_ooc_return_pressed())); connect(ui_music_list, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(on_music_list_double_clicked(QModelIndex))); + connect(ui_area_list, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(on_area_list_double_clicked(QModelIndex))); connect(ui_hold_it, SIGNAL(clicked()), this, SLOT(on_hold_it_clicked())); connect(ui_objection, SIGNAL(clicked()), this, SLOT(on_objection_clicked())); @@ -309,6 +312,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() connect(ui_reload_theme, SIGNAL(clicked()), this, SLOT(on_reload_theme_clicked())); connect(ui_call_mod, SIGNAL(clicked()), this, SLOT(on_call_mod_clicked())); connect(ui_settings, SIGNAL(clicked()), this, SLOT(on_settings_clicked())); + connect(ui_switch_area_music, SIGNAL(clicked()), this, SLOT(on_switch_area_music_clicked())); connect(ui_pre, SIGNAL(clicked()), this, SLOT(on_pre_clicked())); connect(ui_flip, SIGNAL(clicked()), this, SLOT(on_flip_clicked())); @@ -462,8 +466,8 @@ void Courtroom::set_widgets() set_size_and_pos(ui_pair_button, "pair_button"); ui_pair_button->set_image("pair_button.png"); - //set_size_and_pos(ui_area_list, "area_list"); - //ui_area_list->setStyleSheet("background-color: rgba(0, 0, 0, 0);"); + set_size_and_pos(ui_area_list, "music_list"); + ui_area_list->setStyleSheet("background-color: rgba(0, 0, 0, 0);"); set_size_and_pos(ui_music_list, "music_list"); @@ -557,6 +561,9 @@ void Courtroom::set_widgets() set_size_and_pos(ui_settings, "settings"); ui_settings->setText("Settings"); + set_size_and_pos(ui_switch_area_music, "switch_area_music"); + ui_switch_area_music->setText("A/M"); + set_size_and_pos(ui_pre, "pre"); ui_pre->setText("Pre"); @@ -656,6 +663,7 @@ void Courtroom::set_fonts() set_font(ui_ms_chatlog, "ms_chatlog"); set_font(ui_server_chatlog, "server_chatlog"); set_font(ui_music_list, "music_list"); + set_font(ui_area_list, "music_list"); } void Courtroom::set_font(QWidget *widget, QString p_identifier) @@ -839,6 +847,7 @@ void Courtroom::enter_courtroom(int p_cid) ui_flip->hide(); list_music(); + list_areas(); music_player->set_volume(ui_music_slider->value()); sfx_player->set_volume(ui_sfx_slider->value()); @@ -893,6 +902,71 @@ void Courtroom::list_music() } } +void Courtroom::list_areas() +{ + ui_area_list->clear(); + area_row_to_number.clear(); + + QString f_file = "courtroom_design.ini"; + + QBrush free_brush(ao_app->get_color("area_free_color", f_file)); + QBrush lfp_brush(ao_app->get_color("area_lfp_color", f_file)); + QBrush casing_brush(ao_app->get_color("area_casing_color", f_file)); + QBrush recess_brush(ao_app->get_color("area_recess_color", f_file)); + QBrush rp_brush(ao_app->get_color("area_rp_color", f_file)); + QBrush gaming_brush(ao_app->get_color("area_gaming_color", f_file)); + QBrush locked_brush(ao_app->get_color("area_locked_color", f_file)); + + int n_listed_areas = 0; + + for (int n_area = 0 ; n_area < area_list.size() ; ++n_area) + { + QString i_area = area_list.at(n_area); + i_area.append("\n "); + + i_area.append(arup_statuses.at(n_area)); + i_area.append(" | CM: "); + i_area.append(arup_cms.at(n_area)); + + i_area.append("\n "); + + i_area.append(QString::number(arup_players.at(n_area))); + i_area.append(" users | "); + if (arup_locks.at(n_area) == true) + i_area.append("LOCKED"); + else + i_area.append("OPEN"); + + if (i_area.toLower().contains(ui_music_search->text().toLower())) + { + ui_area_list->addItem(i_area); + area_row_to_number.append(n_area); + + // Colouring logic here. + ui_area_list->item(n_listed_areas)->setBackground(free_brush); + if (arup_locks.at(n_area)) + { + ui_area_list->item(n_listed_areas)->setBackground(locked_brush); + } + else + { + if (arup_statuses.at(n_area) == "LOOKING-FOR-PLAYERS") + ui_area_list->item(n_listed_areas)->setBackground(lfp_brush); + else if (arup_statuses.at(n_area) == "CASING") + ui_area_list->item(n_listed_areas)->setBackground(casing_brush); + else if (arup_statuses.at(n_area) == "RECESS") + ui_area_list->item(n_listed_areas)->setBackground(recess_brush); + else if (arup_statuses.at(n_area) == "RP") + ui_area_list->item(n_listed_areas)->setBackground(rp_brush); + else if (arup_statuses.at(n_area) == "GAMING") + ui_area_list->item(n_listed_areas)->setBackground(gaming_brush); + } + + ++n_listed_areas; + } + } +} + void Courtroom::append_ms_chatmessage(QString f_name, QString f_message) { ui_ms_chatlog->append_chatmessage(f_name, f_message); @@ -2535,6 +2609,11 @@ void Courtroom::on_ooc_return_pressed() } return; } + else if (ooc_message.startsWith("/switch_am")) + { + on_switch_area_music_clicked(); + return; + } QStringList packet_contents; packet_contents.append(ui_ooc_chat_name->text()); @@ -2577,6 +2656,7 @@ void Courtroom::on_music_search_edited(QString p_text) //preventing compiler warnings p_text += "a"; list_music(); + list_areas(); } void Courtroom::on_pos_dropdown_changed(int p_index) @@ -2717,6 +2797,12 @@ void Courtroom::on_music_list_double_clicked(QModelIndex p_model) } } +void Courtroom::on_area_list_double_clicked(QModelIndex p_model) +{ + QString p_area = area_list.at(area_row_to_number.at(p_model.row())); + ao_app->send_server_packet(new AOPacket("MC#" + p_area + "#" + QString::number(m_cid) + "#%"), false); +} + void Courtroom::on_hold_it_clicked() { if (objection_state == 1) @@ -3064,6 +3150,20 @@ void Courtroom::on_evidence_button_clicked() } } +void Courtroom::on_switch_area_music_clicked() +{ + if (ui_area_list->isHidden()) + { + ui_area_list->show(); + ui_music_list->hide(); + } + else + { + ui_area_list->hide(); + ui_music_list->show(); + } +} + void Courtroom::ping_server() { ao_app->send_server_packet(new AOPacket("CH#" + QString::number(m_cid) + "#%")); diff --git a/courtroom.h b/courtroom.h index 194298f..90cf21f 100644 --- a/courtroom.h +++ b/courtroom.h @@ -55,6 +55,43 @@ public: void append_char(char_type p_char){char_list.append(p_char);} void append_evidence(evi_type p_evi){evidence_list.append(p_evi);} void append_music(QString f_music){music_list.append(f_music);} + void append_area(QString f_area){area_list.append(f_area);} + + void fix_last_area() + { + QString malplaced = area_list.last(); + area_list.removeLast(); + append_music(malplaced); + } + + void arup_append(int players, QString status, QString cm, bool locked) + { + arup_players.append(players); + arup_statuses.append(status); + arup_cms.append(cm); + arup_locks.append(locked); + } + + void arup_modify(int type, int place, QString value) + { + if (type == 0) + { + arup_players[place] = value.toInt(); + } + else if (type == 1) + { + arup_statuses[place] = value; + } + else if (type == 2) + { + arup_cms[place] = value; + } + else if (type == 3) + { + arup_locks[place] = (value == "True"); + } + list_areas(); + } void character_loading_finished(); @@ -118,6 +155,7 @@ public: //helper function that populates ui_music_list with the contents of music_list void list_music(); + void list_areas(); //these are for OOC chat void append_ms_chatmessage(QString f_name, QString f_message); @@ -206,10 +244,18 @@ private: QVector char_list; QVector evidence_list; QVector music_list; + QVector area_list; + + QVector arup_players; + QVector arup_statuses; + QVector arup_cms; + QVector arup_locks; QSignalMapper *char_button_mapper; + // These map music row items and area row items to their actual IDs. QVector music_row_to_number; + QVector area_row_to_number; //triggers ping_server() every 60 seconds QTimer *keepalive_timer; @@ -396,6 +442,7 @@ private: AOButton *ui_reload_theme; AOButton *ui_call_mod; AOButton *ui_settings; + AOButton *ui_switch_area_music; QCheckBox *ui_pre; QCheckBox *ui_flip; @@ -502,6 +549,7 @@ private slots: void on_music_search_edited(QString p_text); void on_music_list_double_clicked(QModelIndex p_model); + void on_area_list_double_clicked(QModelIndex p_model); void select_emote(int p_id); @@ -584,6 +632,8 @@ private slots: void char_clicked(int n_char); + void on_switch_area_music_clicked(); + void ping_server(); }; diff --git a/packet_distribution.cpp b/packet_distribution.cpp index d2bdcdd..9de0dfe 100644 --- a/packet_distribution.cpp +++ b/packet_distribution.cpp @@ -353,6 +353,9 @@ void AOApplication::server_packet_received(AOPacket *p_packet) if (!courtroom_constructed) goto end; + bool musics_time = false; + int areas = 0; + for (int n_element = 0 ; n_element < f_contents.size() ; n_element += 2) { if (f_contents.at(n_element).toInt() != loaded_music) @@ -367,7 +370,34 @@ void AOApplication::server_packet_received(AOPacket *p_packet) w_lobby->set_loading_text("Loading music:\n" + QString::number(loaded_music) + "/" + QString::number(music_list_size)); - w_courtroom->append_music(f_music); + if (musics_time) + { + w_courtroom->append_music(f_music); + } + else + { + if (f_music.endsWith(".wav") || + f_music.endsWith(".mp3") || + f_music.endsWith(".mp4") || + f_music.endsWith(".ogg") || + f_music.endsWith(".opus")) + { + musics_time = true; + areas--; + w_courtroom->fix_last_area(); + w_courtroom->append_music(f_music); + } + else + { + w_courtroom->append_area(f_music); + areas++; + } + } + + for (int area_n = 0; area_n < areas; area_n++) + { + w_courtroom->arup_append(0, "Unknown", "Unknown", false); + } int total_loading_size = char_list_size * 2 + evidence_list_size + music_list_size; int loading_value = int(((loaded_chars + generated_chars + loaded_music + loaded_evidence) / static_cast(total_loading_size)) * 100); @@ -426,13 +456,43 @@ void AOApplication::server_packet_received(AOPacket *p_packet) if (!courtroom_constructed) goto end; + bool musics_time = false; + int areas = 0; + for (int n_element = 0 ; n_element < f_contents.size() ; ++n_element) { ++loaded_music; w_lobby->set_loading_text("Loading music:\n" + QString::number(loaded_music) + "/" + QString::number(music_list_size)); - w_courtroom->append_music(f_contents.at(n_element)); + if (musics_time) + { + w_courtroom->append_music(f_contents.at(n_element)); + } + else + { + if (f_contents.at(n_element).endsWith(".wav") || + f_contents.at(n_element).endsWith(".mp3") || + f_contents.at(n_element).endsWith(".mp4") || + f_contents.at(n_element).endsWith(".ogg") || + f_contents.at(n_element).endsWith(".opus")) + { + musics_time = true; + w_courtroom->fix_last_area(); + w_courtroom->append_music(f_contents.at(n_element)); + areas--; + } + else + { + w_courtroom->append_area(f_contents.at(n_element)); + areas++; + } + } + + for (int area_n = 0; area_n < areas; area_n++) + { + w_courtroom->arup_append(0, "Unknown", "Unknown", false); + } int total_loading_size = char_list_size * 2 + evidence_list_size + music_list_size; int loading_value = int(((loaded_chars + generated_chars + loaded_music + loaded_evidence) / static_cast(total_loading_size)) * 100); @@ -525,6 +585,17 @@ void AOApplication::server_packet_received(AOPacket *p_packet) w_courtroom->set_evidence_list(f_evi_list); } } + else if (header == "ARUP") + { + if (courtroom_constructed) + { + int arup_type = f_contents.at(0).toInt(); + for (int n_element = 1 ; n_element < f_contents.size() ; n_element++) + { + w_courtroom->arup_modify(arup_type, n_element - 1, f_contents.at(n_element)); + } + } + } else if (header == "IL") { if (courtroom_constructed && f_contents.size() > 0) diff --git a/server/area_manager.py b/server/area_manager.py index ad36362..6e024f6 100644 --- a/server/area_manager.py +++ b/server/area_manager.py @@ -71,12 +71,14 @@ class AreaManager: def new_client(self, client): self.clients.add(client) + self.server.area_manager.send_arup_players() def remove_client(self, client): self.clients.remove(client) if client.is_cm: client.is_cm = False self.owned = False + self.server.area_manager.send_arup_cms() if self.is_locked: self.unlock() @@ -84,6 +86,7 @@ class AreaManager: self.is_locked = False self.blankposting_allowed = True self.invite_list = {} + self.server.area_manager.send_arup_lock() self.send_host_message('This area is open now.') def is_char_available(self, char_id): @@ -240,6 +243,7 @@ class AreaManager: if value.lower() == 'lfp': value = 'looking-for-players' self.status = value.upper() + self.server.area_manager.send_arup_status() def change_doc(self, doc='No document.'): self.doc = doc @@ -333,3 +337,31 @@ class AreaManager: return name[:3].upper() else: return name.upper() + + def send_arup_players(self): + players_list = [0] + for area in self.areas: + players_list.append(len(area.clients)) + self.server.send_arup(players_list) + + def send_arup_status(self): + status_list = [1] + for area in self.areas: + status_list.append(area.status) + self.server.send_arup(status_list) + + def send_arup_cms(self): + cms_list = [2] + for area in self.areas: + cm = 'FREE' + for client in area.clients: + if client.is_cm: + cm = client.get_char_name() + cms_list.append(cm) + self.server.send_arup(cms_list) + + def send_arup_lock(self): + lock_list = [3] + for area in self.areas: + lock_list.append(area.is_locked) + self.server.send_arup(lock_list) diff --git a/server/client_manager.py b/server/client_manager.py index bb2bcd9..b1f8785 100644 --- a/server/client_manager.py +++ b/server/client_manager.py @@ -299,6 +299,12 @@ class ClientManager: self.send_command('BN', self.area.background) self.send_command('LE', *self.area.get_evidence_list(self)) self.send_command('MM', 1) + + self.server.area_manager.send_arup_players() + self.server.area_manager.send_arup_status() + self.server.area_manager.send_arup_cms() + self.server.area_manager.send_arup_lock() + self.send_command('DONE') def char_select(self): diff --git a/server/commands.py b/server/commands.py index 0bd9c55..134b685 100644 --- a/server/commands.py +++ b/server/commands.py @@ -691,6 +691,7 @@ def ooc_cmd_cm(client, arg): client.is_cm = True if client.area.evidence_mod == 'HiddenCM': client.area.broadcast_evidence_list() + client.server.area_manager.send_arup_cms() client.area.send_host_message('{} is CM in this area now.'.format(client.get_char_name())) def ooc_cmd_uncm(client, arg): @@ -700,6 +701,7 @@ def ooc_cmd_uncm(client, arg): client.area.blankposting_allowed = True if client.area.is_locked: client.area.unlock() + client.server.area_manager.send_arup_cms() client.area.send_host_message('{} is no longer CM in this area.'.format(client.get_char_name())) else: raise ClientError('You cannot give up being the CM when you are not one') @@ -718,6 +720,7 @@ def ooc_cmd_area_lock(client, arg): client.send_host_message('Area is already locked.') if client.is_cm: client.area.is_locked = True + client.server.area_manager.send_arup_lock() client.area.send_host_message('Area is locked.') for i in client.area.clients: client.area.invite_list[i.id] = None diff --git a/server/tsuserver.py b/server/tsuserver.py index 97b4b90..8f5bf85 100644 --- a/server/tsuserver.py +++ b/server/tsuserver.py @@ -258,6 +258,40 @@ class TsuServer3: if self.config['use_district']: self.district_client.send_raw_message('NEED#{}#{}#{}#{}'.format(char_name, area_name, area_id, msg)) + def send_arup(self, args): + """ Updates the area properties on the Case Café Custom Client. + + Playercount: + ARUP#0###... + Status: + ARUP#1#####... + CM: + ARUP#2#####... + Lockedness: + ARUP#3#####... + + """ + if len(args) < 2: + # An argument count smaller than 2 means we only got the identifier of ARUP. + return + if args[0] not in (0,1,2,3): + return + + if args[0] in (0, 3): + for part_arg in args[1:]: + try: + sanitised = int(part_arg) + except: + return + elif args[0] in (1, 2): + for part_arg in args[1:]: + try: + sanitised = str(part_arg) + except: + return + + self.send_all_cmd_pred('ARUP', *args, pred=lambda x: True) + def refresh(self): with open('config/config.yaml', 'r') as cfg: self.config['motd'] = yaml.load(cfg)['motd'].replace('\\n', ' \n')