From 67eb25a988efe8a26be4740c47fa4dfea9fa2a2c Mon Sep 17 00:00:00 2001 From: in1tiate <32779090+in1tiate@users.noreply.github.com> Date: Wed, 15 May 2024 11:06:46 -0500 Subject: [PATCH] Add support for background ambience (#353) * add support for background ambience * add sample ambience config file * Send ambience BEFORE music when possible --- bin/config_sample/ambience.ini | 2 ++ bin/config_sample/command_extensions.ini | 5 ++++- bin/config_sample/text/commandhelp.json | 7 +++++++ core/include/aoclient.h | 13 +++++++++++++ core/include/area_data.h | 24 ++++++++++++++++++++++++ core/include/config_manager.h | 12 ++++++++++++ core/src/aoclient.cpp | 3 ++- core/src/area_data.cpp | 20 ++++++++++++++++++++ core/src/commands/area.cpp | 7 +++++++ core/src/commands/music.cpp | 19 +++++++++++++++++++ core/src/config_manager.cpp | 6 ++++++ 11 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 bin/config_sample/ambience.ini diff --git a/bin/config_sample/ambience.ini b/bin/config_sample/ambience.ini new file mode 100644 index 0000000..6a87d03 --- /dev/null +++ b/bin/config_sample/ambience.ini @@ -0,0 +1,2 @@ +[CourtGreatWitchVS] +ambience = ambient/greatwitchtrial.opus \ No newline at end of file diff --git a/bin/config_sample/command_extensions.ini b/bin/config_sample/command_extensions.ini index ae68c0c..1691578 100644 --- a/bin/config_sample/command_extensions.ini +++ b/bin/config_sample/command_extensions.ini @@ -86,4 +86,7 @@ aliases = toggleshouts aliases = kickother [jukebox_skip] -aliases = jukeboxskip \ No newline at end of file +aliases = jukeboxskip + +[play_ambience] +aliases = playambience playa \ No newline at end of file diff --git a/bin/config_sample/text/commandhelp.json b/bin/config_sample/text/commandhelp.json index 7fd8352..dffddfb 100644 --- a/bin/config_sample/text/commandhelp.json +++ b/bin/config_sample/text/commandhelp.json @@ -872,5 +872,12 @@ ], "usage":"/jukebox_skip", "text":"Skips the current song in the Jukebox and plays the next available one." + }, + { + "names": [ + "play_ambience" + ], + "usage":"/play_ambience", + "text":"Plays the requested track in the ambience channel." } ] diff --git a/core/include/aoclient.h b/core/include/aoclient.h index 88cf447..e8763ef 100644 --- a/core/include/aoclient.h +++ b/core/include/aoclient.h @@ -1843,6 +1843,19 @@ class AOClient : public QObject */ void cmdPlay(int argc, QStringList argv); + /** + * @brief Plays ambience in the area. + * + * @details The arguments are **the song's filepath** originating from `base/sounds/music/`, + * or **the song's URL** if it's a stream. + * + * As described above, this command can be used to play ambience by URL (for clients at and above version 2.9), + * but it can also be used to play ambience locally available for the clients. + * + * @iscommand + */ + void cmdPlayAmbience(int argc, QStringList argv); + /** * @brief DJ-blocks a client. * diff --git a/core/include/area_data.h b/core/include/area_data.h index b5102ba..3632432 100644 --- a/core/include/area_data.h +++ b/core/include/area_data.h @@ -638,6 +638,15 @@ class AreaData : public QObject */ QString currentMusic() const; + /** + * @brief Returns the ambient audio currently being played in the area. + * + * @return See short description. + * + * @see #m_currentAmbience + */ + QString currentAmbience() const; + /** * @brief Sets the music currently being played in the area. * @@ -673,6 +682,13 @@ class AreaData : public QObject */ void changeMusic(const QString &f_source_r, const QString &f_newSong_r); + /** + * @brief Changes the ambience audio being played in the area. + * + * @param f_newSong_r The name of the new audio that is going to be played in the area. + */ + void changeAmbience(const QString &f_newSong_r); + /** * @brief Returns the evidence mod in the area. * @@ -1097,6 +1113,14 @@ class AreaData : public QObject */ QString m_currentMusic; + /** + * @brief See m_currentMusic, but for ambience. + * + * @details Title is a path to the music file, with the starting point on + * `base/sounds/music/` clientside, with file extension. + */ + QString m_currentAmbience; + /** * @brief The name of the client (or client's character) that started the currently playing music. */ diff --git a/core/include/config_manager.h b/core/include/config_manager.h index 434eda9..3ac98bd 100644 --- a/core/include/config_manager.h +++ b/core/include/config_manager.h @@ -101,6 +101,13 @@ class ConfigManager */ static QSettings *areaData(); + /** + * @brief Returns a pointer to the QSettings object which contains the ambience configuration. + * + * @return See short description. + */ + static QSettings *ambience(); + /** * @brief Returns a sanitized QStringList of the areas. * @@ -552,6 +559,11 @@ class ConfigManager */ static QSettings *m_logtext; + /** + * @brief Stores all adjustable logstrings. + */ + static QSettings *m_ambience; + /** * @brief Pointer to QElapsedTimer to track the uptime of the server. */ diff --git a/core/src/aoclient.cpp b/core/src/aoclient.cpp index 340405c..d3c705c 100644 --- a/core/src/aoclient.cpp +++ b/core/src/aoclient.cpp @@ -147,7 +147,8 @@ const QMap AOClient::COMMANDS{ {"toggle_wtce", {{ACLRole::CM}, 0, &AOClient::cmdToggleWtce}}, {"toggle_shouts", {{ACLRole::CM}, 0, &AOClient::cmdToggleShouts}}, {"kick_other", {{ACLRole::NONE}, 0, &AOClient::cmdKickOther}}, - {"jukebox_skip", {{ACLRole::CM}, 0, &AOClient::cmdJukeboxSkip}}}; + {"jukebox_skip", {{ACLRole::CM}, 0, &AOClient::cmdJukeboxSkip}}, + {"play_ambience", {{ACLRole::NONE}, 1, &AOClient::cmdPlayAmbience}}}; void AOClient::clientDisconnected() { diff --git a/core/src/area_data.cpp b/core/src/area_data.cpp index a0d9c73..3af70d3 100644 --- a/core/src/area_data.cpp +++ b/core/src/area_data.cpp @@ -108,6 +108,8 @@ void AreaData::clientJoinedArea(int f_charId, int f_userId) } m_joined_ids.append(f_userId); emit userJoinedArea(m_index, f_userId); + // Send out ambience as well. Use channel 1 for that + emit sendAreaPacketClient(PacketFactory::createPacket("MC", {m_currentAmbience, QString::number(-1), ConfigManager::serverName(), QString::number(1), QString::number(1)}), f_userId); // The name will never be shown as we are using a spectator ID. Still nice for people who network sniff. // We auto-loop this so you'll never sit in silence unless wanted. emit sendAreaPacketClient(PacketFactory::createPacket("MC", {m_currentMusic, QString::number(-1), ConfigManager::serverName(), QString::number(1)}), f_userId); @@ -494,11 +496,21 @@ void AreaData::changeMusic(const QString &f_source_r, const QString &f_newSong_r m_musicPlayedBy = f_source_r; } +void AreaData::changeAmbience(const QString &f_newSong_r) +{ + m_currentAmbience = f_newSong_r; +} + QString AreaData::currentMusic() const { return m_currentMusic; } +QString AreaData::currentAmbience() const +{ + return m_currentAmbience; +} + void AreaData::setCurrentMusic(QString f_current_song) { m_currentMusic = f_current_song; @@ -587,6 +599,14 @@ QString AreaData::background() const void AreaData::setBackground(const QString f_background) { m_background = f_background; + QSettings *ambience_data = ConfigManager::ambience(); + QString new_ambience = ambience_data->value(f_background + "/ambience").toString(); + if (new_ambience != "") { + changeAmbience(new_ambience); + } + else { + changeAmbience(""); // DON'T use ~stop.mp3 it overrides some code we don't want overridden + } } bool AreaData::ignoreBgList() diff --git a/core/src/commands/area.cpp b/core/src/commands/area.cpp index c751561..51a790f 100644 --- a/core/src/commands/area.cpp +++ b/core/src/commands/area.cpp @@ -299,6 +299,13 @@ void AOClient::cmdSetBackground(int argc, QStringList argv) if (server->getBackgrounds().contains(f_background, Qt::CaseInsensitive) || area->ignoreBgList() == true) { area->setBackground(f_background); server->broadcast(PacketFactory::createPacket("BN", {f_background}), m_current_area); + QString ambience_name = ConfigManager::ambience()->value(f_background + "/ambience").toString(); + if (ambience_name != "") { + server->broadcast(PacketFactory::createPacket("MC", {ambience_name, "-1", m_showname, "1", "1"}), m_current_area); + } + else { + server->broadcast(PacketFactory::createPacket("MC", {"~stop.mp3", "-1", m_showname, "1", "1"}), m_current_area); + } sendServerMessageArea(m_current_char + " changed the background to " + f_background); } else { diff --git a/core/src/commands/music.cpp b/core/src/commands/music.cpp index 9ac56c2..96eebb7 100644 --- a/core/src/commands/music.cpp +++ b/core/src/commands/music.cpp @@ -49,6 +49,25 @@ void AOClient::cmdPlay(int argc, QStringList argv) server->broadcast(music_change, m_current_area); } +void AOClient::cmdPlayAmbience(int argc, QStringList argv) +{ + Q_UNUSED(argc); + + if (m_is_dj_blocked) { + sendServerMessage("You are blocked from changing the ambience."); + return; + } + AreaData *l_area = server->getAreaById(m_current_area); + if (!l_area->owners().contains(m_id) && !l_area->isPlayEnabled()) { // Make sure we have permission to play music + sendServerMessage("Free ambience play is disabled in this area."); + return; + } + QString l_song = argv.join(" "); + l_area->changeAmbience(l_song); + AOPacket *music_change = PacketFactory::createPacket("MC", {l_song, "-1", m_showname, "1", "1"}); + server->broadcast(music_change, m_current_area); +} + void AOClient::cmdCurrentMusic(int argc, QStringList argv) { Q_UNUSED(argc); diff --git a/core/src/config_manager.cpp b/core/src/config_manager.cpp index f88a2df..81b9649 100644 --- a/core/src/config_manager.cpp +++ b/core/src/config_manager.cpp @@ -23,6 +23,7 @@ QSettings *ConfigManager::m_settings = new QSettings("config/config.ini", QSetti QSettings *ConfigManager::m_discord = new QSettings("config/discord.ini", QSettings::IniFormat); QSettings *ConfigManager::m_areas = new QSettings("config/areas.ini", QSettings::IniFormat); QSettings *ConfigManager::m_logtext = new QSettings("config/text/logtext.ini", QSettings::IniFormat); +QSettings *ConfigManager::m_ambience = new QSettings("config/ambience.ini", QSettings::IniFormat); ConfigManager::CommandSettings *ConfigManager::m_commands = new CommandSettings(); QElapsedTimer *ConfigManager::m_uptimeTimer = new QElapsedTimer; MusicList *ConfigManager::m_musicList = new MusicList; @@ -231,6 +232,11 @@ QSettings *ConfigManager::areaData() return m_areas; } +QSettings *ConfigManager::ambience() +{ + return m_ambience; +} + QStringList ConfigManager::sanitizedAreaNames() { QStringList l_area_names = m_areas->childGroups(); // invisibly does a lexicographical sort, because Qt is great like that