Implement a basic and functional jukebox implementation

This commit is contained in:
Salanto 2021-09-12 22:32:10 +02:00
parent 5115b97721
commit f9dcaa2aa5
7 changed files with 145 additions and 3 deletions

View File

@ -1809,6 +1809,13 @@ class AOClient : public QObject {
*/
void cmdToggleMusic(int argc, QStringList argv);
/**
* @brief cmdToggleJukebox Toggles jukebox status in the current area.
*
* @details No arguments.
*/
void cmdToggleJukebox(int argc, QStringList argv);
///@}
/**
@ -2121,6 +2128,7 @@ class AOClient : public QObject {
{"ignore_bglist", {ACLFlags.value("IGNORE_BGLIST"),0, &AOClient::cmdIgnoreBgList}},
{"notice", {ACLFlags.value("SEND_NOTICE"), 1, &AOClient::cmdNotice}},
{"noticeg", {ACLFlags.value("SEND_NOTICE"), 1, &AOClient::cmdNoticeGlobal}},
{"togglejukebox", {ACLFlags.value("None"), 0, &AOClient::cmdToggleJukebox}},
};
/**

View File

@ -27,6 +27,7 @@
#include <QDebug>
#include <QTimer>
#include <QElapsedTimer>
#include <QRandomGenerator>
class Logger;
@ -295,6 +296,15 @@ class AreaData : public QObject {
*/
LockStatus lockStatus() const;
/**
* @brief Returns the jukebox status of the area.
*
* @return See short description.
*
* @see #m_jukebox
*/
bool isjukeboxEnabled() const;
/**
* @brief Locks the area, setting it to LOCKED.
*/
@ -778,6 +788,30 @@ class AreaData : public QObject {
*/
void toggleIgnoreBgList();
/**
* @brief Toggles wether the jukebox is enabled or not.
*/
void toggleJukebox();
/**
* @brief Adds a song to the Jukeboxs queue.
*/
bool addJukeboxSong(QString f_song);
public slots:
/**
* @brief Plays a random song from the jukebox. Plays the same if only one is left.
*/
void switchJukeboxSong();
signals:
/**
* @brief Changes the song in the current area when the jukebox timer expires.
*/
void playJukeboxSong(AOPacket f_packet, int f_area_index);
private:
/**
* @brief The list of timers available in the area.
@ -966,6 +1000,28 @@ private:
* @brief Whether or not to ignore the server defined background list. If true, any background can be set in an area.
*/
bool m_ignoreBgList;
// Jukebox specific members
/**
* @brief Stores the songs added to the jukebox to be played.
*
* @details This contains the names of each song, noteworthy is that none of the songs are able to be entered twice.
*
*/
QVector<QString> m_jukebox_queue;
/**
* @brief Triggers the playing of the next song once the last song has fully played.
*
* @details While this may be considered bad design, I do not care.
* It triggers a direct broadcast of the MC packet in the area.
*/
QTimer* m_jukebox_timer;
/**
* @brief Wether or not the jukebox is enabled in this area.
*/
bool m_jukebox;
};
#endif // AREA_DATA_H

View File

@ -48,6 +48,7 @@ AreaData::AreaData(QString p_name, int p_index) :
m_toggleMusic = areas_ini->value("toggle_music", "true").toBool();
m_shownameAllowed = areas_ini->value("shownames_allowed", "true").toBool();
m_ignoreBgList = areas_ini->value("ignore_bglist", "false").toBool();
m_jukebox = areas_ini->value("jukebox_enabled", "false").toBool();
areas_ini->endGroup();
QTimer* timer1 = new QTimer();
m_timers.append(timer1);
@ -57,6 +58,9 @@ AreaData::AreaData(QString p_name, int p_index) :
m_timers.append(timer3);
QTimer* timer4 = new QTimer();
m_timers.append(timer4);
m_jukebox_timer = new QTimer();
connect(m_jukebox_timer, &QTimer::timeout,
this, &AreaData::switchJukeboxSong);
}
const QMap<QString, AreaData::Status> AreaData::map_statuses = {
@ -131,6 +135,11 @@ AreaData::LockStatus AreaData::lockStatus() const
return m_locked;
}
bool AreaData::isjukeboxEnabled() const
{
return m_jukebox;
}
void AreaData::lock()
{
m_locked = LockStatus::LOCKED;
@ -504,3 +513,43 @@ void AreaData::toggleIgnoreBgList()
{
m_ignoreBgList = !m_ignoreBgList;
}
void AreaData::toggleJukebox()
{
m_jukebox = !m_jukebox;
}
bool AreaData::addJukeboxSong(QString f_song)
{
if(!m_jukebox_queue.contains(f_song)) {
if (m_jukebox_queue.size() == 0) {
emit playJukeboxSong(AOPacket("MC",{f_song,QString::number(-1)}), index());
m_jukebox_timer->start(ConfigManager::songInformation(f_song) * 1000);
}
m_jukebox_queue.append(f_song);
return true;
}
else {
return false;
}
}
void AreaData::switchJukeboxSong()
{
QString l_song_name;
if(m_jukebox_queue.size() == 1) {
l_song_name = m_jukebox_queue[0];
emit playJukeboxSong(AOPacket("MC",{l_song_name,QString::number(-1)}), m_index);
m_jukebox_timer->start(ConfigManager::songInformation(l_song_name) * 1000);
}
else {
int l_random_index = QRandomGenerator::system()->bounded(m_jukebox_queue.size() -1);
l_song_name = m_jukebox_queue[l_random_index];
emit playJukeboxSong(AOPacket("MC",{l_song_name,QString::number(-1)}), m_index);
m_jukebox_timer->start(ConfigManager::songInformation(m_jukebox_queue[l_random_index]) * 1000);
m_jukebox_queue.remove(l_random_index);
m_jukebox_queue.squeeze();
}
currentMusic() = l_song_name;
musicPlayerBy() = "Jukebox";
}

View File

@ -16,7 +16,6 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. //
//////////////////////////////////////////////////////////////////////////////////////
#include "include/aoclient.h"
// This file is for commands under the music category in aoclient.h
// Be sure to register the command in the header before adding it here!
@ -112,3 +111,19 @@ void AOClient::cmdToggleMusic(int argc, QStringList argv)
QString l_state = l_area->isMusicAllowed() ? "allowed." : "disallowed.";
sendServerMessage("Music in this area is now " + l_state);
}
void AOClient::cmdToggleJukebox(int argc, QStringList argv)
{
Q_UNUSED(argc);
Q_UNUSED(argv);
if (checkAuth(ACLFlags.value("CM")) | m_authenticated) {
AreaData* l_area = server->m_areas.value(m_current_area);
l_area->toggleJukebox();
QString l_state = l_area->isjukeboxEnabled() ? "enabled." : "disabled.";
sendServerMessageArea("The jukebox in this area has been " + l_state);
}
else {
sendServerMessage("You do not have permission to change the jukebox status.");
}
}

View File

@ -142,6 +142,7 @@ QStringList ConfigManager::musiclist()
QJsonArray l_Json_root_array = l_music_list_json.array();
QJsonObject l_child_obj;
QJsonArray l_child_array;
QStringList l_musiclist;
for (int i = 0; i <= l_Json_root_array.size() -1; i++){ //Iterate trough entire JSON file to assemble musiclist
l_child_obj = l_Json_root_array.at(i).toObject();
@ -149,6 +150,7 @@ QStringList ConfigManager::musiclist()
QString l_category_name = l_child_obj["category"].toString();
if (!l_category_name.isEmpty()) {
m_musicList->insert(l_category_name,0);
l_musiclist.append(l_category_name);
}
else {
qWarning() << "Category name not set. This may cause the musiclist to be displayed incorrectly.";
@ -160,11 +162,11 @@ QStringList ConfigManager::musiclist()
QString l_song_name = l_song_obj["name"].toString();
int l_song_duration = l_song_obj["length"].toVariant().toFloat();
m_musicList->insert(l_song_name,l_song_duration);
l_musiclist.append(l_song_name);
}
}
l_music_json.close();
QStringList l_musiclist = m_musicList->keys();
if(!l_musiclist[0].contains("==")) // Add a default category if none exists
l_musiclist.insert(0,"==Music==");

View File

@ -319,6 +319,15 @@ void AOClient::pktChangeMusic(AreaData* area, int argc, QStringList argv, AOPack
l_final_song = "~stop.mp3";
else
l_final_song = l_argument;
if (area->isjukeboxEnabled()) {
if (area->addJukeboxSong(l_final_song))
sendServerMessage("Your song has been added to the Jukebox queue.");
else
sendServerMessage("Your song could not be added to the jukebox queue. It already exists");
return;
}
AOPacket l_music_change("MC", {l_final_song, argv[1], m_showname, "1", "0", l_effects});
area->currentMusic() = l_final_song;
area->musicPlayerBy() = m_showname;

View File

@ -91,7 +91,10 @@ void Server::start()
QStringList raw_area_names = ConfigManager::rawAreaNames();
for (int i = 0; i < raw_area_names.length(); i++) {
QString area_name = raw_area_names[i];
m_areas.insert(i, new AreaData(area_name, i));
AreaData* l_area = new AreaData(area_name, i);
m_areas.insert(i, l_area);
connect(l_area, &AreaData::playJukeboxSong,
this, QOverload<AOPacket,int>::of(&Server::broadcast));
}
//Rate-Limiter for IC-Chat