////////////////////////////////////////////////////////////////////////////////////// // akashi - a server for Attorney Online 2 // // Copyright (C) 2020 scatterflower // // // // This program is free software: you can redistribute it and/or modify // // it under the terms of the GNU Affero General Public License as // // published by the Free Software Foundation, either version 3 of the // // License, or (at your option) any later version. // // // // This program is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY; without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU Affero General Public License for more details. // // // // You should have received a copy of the GNU Affero General Public License // // along with this program. If not, see . // ////////////////////////////////////////////////////////////////////////////////////// #include "aoclient.h" #include "area_data.h" #include "music_manager.h" #include "packet/packet_factory.h" #include "server.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! void AOClient::cmdPlay(int argc, QStringList argv) { Q_UNUSED(argc); if (m_is_dj_blocked) { sendServerMessage("You are blocked from changing the music."); return; } AreaData *l_area = server->getAreaById(areaId()); const ACLRole l_role = server->getACLRolesHandler()->getRoleById(m_acl_role_id); if (!l_area->owners().contains(clientId()) && !l_area->isPlayEnabled() && !l_role.checkPermission(ACLRole::CM)) { // Make sure we have permission to play music sendServerMessage("Free music play is disabled in this area."); return; } QString l_song = argv.join(" "); if (characterName().isEmpty()) { l_area->changeMusic(character(), l_song); } else { l_area->changeMusic(characterName(), l_song); } AOPacket *music_change = PacketFactory::createPacket("MC", {l_song, QString::number(server->getCharID(character())), characterName(), "1", "0"}); server->broadcast(music_change, areaId()); } 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(areaId()); if (!l_area->owners().contains(clientId()) && !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", characterName(), "1", "1"}); server->broadcast(music_change, areaId()); } void AOClient::cmdCurrentMusic(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); AreaData *l_area = server->getAreaById(areaId()); if (!l_area->currentMusic().isEmpty() && !l_area->currentMusic().contains("~stop.mp3")) // dummy track for stopping music sendServerMessage("The current song is " + l_area->currentMusic() + " played by " + l_area->musicPlayerBy()); else sendServerMessage("There is no music playing."); } void AOClient::cmdBlockDj(int argc, QStringList argv) { Q_UNUSED(argc); bool conv_ok = false; int l_uid = argv[0].toInt(&conv_ok); if (!conv_ok) { sendServerMessage("Invalid user ID."); return; } AOClient *l_target = server->getClientByID(l_uid); if (l_target == nullptr) { sendServerMessage("No client with that ID found."); return; } if (l_target->m_is_dj_blocked) sendServerMessage("That player is already DJ blocked!"); else { sendServerMessage("DJ blocked player."); l_target->sendServerMessage("You were blocked from changing the music by a moderator. " + getReprimand()); } l_target->m_is_dj_blocked = true; } void AOClient::cmdUnBlockDj(int argc, QStringList argv) { Q_UNUSED(argc); bool conv_ok = false; int l_uid = argv[0].toInt(&conv_ok); if (!conv_ok) { sendServerMessage("Invalid user ID."); return; } AOClient *l_target = server->getClientByID(l_uid); if (l_target == nullptr) { sendServerMessage("No client with that ID found."); return; } if (!l_target->m_is_dj_blocked) sendServerMessage("That player is not DJ blocked!"); else { sendServerMessage("DJ permissions restored to player."); l_target->sendServerMessage("A moderator restored your music permissions. " + getReprimand(true)); } l_target->m_is_dj_blocked = false; } void AOClient::cmdToggleMusic(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); AreaData *l_area = server->getAreaById(areaId()); l_area->toggleMusic(); 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); AreaData *l_area = server->getAreaById(areaId()); l_area->toggleJukebox(); QString l_state = l_area->isjukeboxEnabled() ? "enabled." : "disabled."; sendServerMessageArea("The jukebox in this area has been " + l_state); } void AOClient::cmdAddSong(int argc, QStringList argv) { Q_UNUSED(argc); // This needs some explanation. // Akashi has no concept of argument count,so any space is interpreted as a new element // in the QStringList. This works fine until someone enters something with a space. // Since we can't preencode those elements, we join all as a string and use a delimiter // that does not exist in file and URL paths. I decided on the ol' reliable ','. QString l_argv_string = argv.join(" "); QStringList l_argv = l_argv_string.split(","); bool l_success = false; if (l_argv.size() == 1) { QString l_song_name = l_argv.value(0); l_success = m_music_manager->addCustomSong(l_song_name, l_song_name, 0, areaId()); } if (l_argv.size() == 2) { QString l_song_name = l_argv.value(0); QString l_true_name = l_argv.value(1); l_success = m_music_manager->addCustomSong(l_song_name, l_true_name, 0, areaId()); } if (l_argv.size() == 3) { QString l_song_name = l_argv.value(0); QString l_true_name = l_argv.value(1); bool ok; int l_song_duration = l_argv.value(2).toInt(&ok); if (!ok) l_song_duration = 0; l_success = m_music_manager->addCustomSong(l_song_name, l_true_name, l_song_duration, areaId()); } if (l_argv.size() >= 4) { sendServerMessage("Too many arguments. Addition of song has failed."); return; } QString l_message = l_success ? "succeeded." : "failed."; sendServerMessage("The addition of the song has " + l_message); } void AOClient::cmdAddCategory(int argc, QStringList argv) { Q_UNUSED(argc); bool l_success = m_music_manager->addCustomCategory(argv.join(" "), areaId()); QString l_message = l_success ? "succeeded." : "failed."; sendServerMessage("The addition of the category has " + l_message); } void AOClient::cmdRemoveCategorySong(int argc, QStringList argv) { Q_UNUSED(argc); bool l_success = m_music_manager->removeCategorySong(argv.join(" "), areaId()); QString l_message = l_success ? "succeeded." : "failed."; sendServerMessage("The removal of the entry has " + l_message); } void AOClient::cmdToggleRootlist(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); bool l_status = m_music_manager->toggleRootEnabled(areaId()); QString l_message = (l_status) ? "enabled." : "disabled."; sendServerMessage("Global musiclist has been " + l_message); } void AOClient::cmdClearCustom(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); m_music_manager->clearCustomList(areaId()); sendServerMessage("Custom songs have been cleared."); } void AOClient::cmdJukeboxSkip(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); QString l_name = character(); if (!characterName().isEmpty()) { l_name = characterName(); } AreaData *l_area = server->getAreaById(areaId()); if (l_area->isjukeboxEnabled()) { if (l_area->getJukeboxQueueSize() >= 1) { l_area->switchJukeboxSong(); sendServerMessageArea(l_name + " has forced a skip. Playing the next available song."); return; } sendServerMessage("Unable to skip song. Jukebox is currently empty."); return; } sendServerMessage("Unable to skip song. The jukebox is not running."); }