////////////////////////////////////////////////////////////////////////////////////// // 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 "config_manager.h" #include "packet/packet_factory.h" #include "server.h" // This file is for commands under the area category in aoclient.h // Be sure to register the command in the header before adding it here! void AOClient::cmdCM(int argc, QStringList argv) { QString l_sender_name = name(); AreaData *l_area = server->getAreaById(areaId()); if (l_area->isProtected()) { sendServerMessage("This area is protected, you may not become CM."); return; } else if (l_area->owners().isEmpty()) { // no one owns this area, and it's not protected l_area->addOwner(clientId()); sendServerMessageArea(l_sender_name + " is now CM in this area."); arup(ARUPType::CM, true); } else if (!l_area->owners().contains(clientId())) { // there is already a CM, and it isn't us sendServerMessage("You cannot become a CM in this area."); } else if (argc == 1) { // we are CM, and we want to make ID argv[0] also CM bool ok; AOClient *l_owner_candidate = server->getClientByID(argv[0].toInt(&ok)); if (!ok) { sendServerMessage("That doesn't look like a valid ID."); return; } if (l_owner_candidate == nullptr) { sendServerMessage("Unable to find client with ID " + argv[0] + "."); return; } if (l_area->owners().contains(l_owner_candidate->clientId())) { sendServerMessage("User is already a CM in this area."); return; } l_area->addOwner(l_owner_candidate->clientId()); sendServerMessageArea(l_owner_candidate->name() + " is now CM in this area."); arup(ARUPType::CM, true); } else { sendServerMessage("You are already a CM in this area."); } } void AOClient::cmdUnCM(int argc, QStringList argv) { AreaData *l_area = server->getAreaById(areaId()); int l_uid; if (l_area->owners().isEmpty()) { sendServerMessage("There are no CMs in this area."); return; } else if (argc == 0) { l_uid = clientId(); sendServerMessage("You are no longer CM in this area."); } else if (checkPermission(ACLRole::UNCM) && argc >= 1) { bool conv_ok = false; l_uid = argv[0].toInt(&conv_ok); if (!conv_ok) { sendServerMessage("Invalid user ID."); return; } if (!l_area->owners().contains(l_uid)) { sendServerMessage("That user is not CMed."); return; } AOClient *l_target = server->getClientByID(l_uid); if (l_target == nullptr) { sendServerMessage("No client with that ID found."); return; } sendServerMessage(l_target->name() + " was successfully unCMed."); l_target->sendServerMessage("You have been unCMed by a moderator."); } else { sendServerMessage("You do not have permission to unCM others."); return; } if (l_area->removeOwner(l_uid)) { arup(ARUPType::LOCKED, true); } arup(ARUPType::CM, true); } void AOClient::cmdInvite(int argc, QStringList argv) { Q_UNUSED(argc); AreaData *l_area = server->getAreaById(areaId()); bool ok; int l_invited_id = argv[0].toInt(&ok); if (!ok) { sendServerMessage("That does not look like a valid ID."); return; } AOClient *target_client = server->getClientByID(l_invited_id); if (target_client == nullptr) { sendServerMessage("No client with that ID found."); return; } else if (!l_area->invite(l_invited_id)) { sendServerMessage("That ID is already on the invite list."); return; } sendServerMessage("You invited ID " + argv[0]); target_client->sendServerMessage("You were invited and given access to " + l_area->name()); } void AOClient::cmdUnInvite(int argc, QStringList argv) { Q_UNUSED(argc); AreaData *l_area = server->getAreaById(areaId()); bool ok; int l_uninvited_id = argv[0].toInt(&ok); if (!ok) { sendServerMessage("That does not look like a valid ID."); return; } AOClient *target_client = server->getClientByID(l_uninvited_id); if (target_client == nullptr) { sendServerMessage("No client with that ID found."); return; } else if (l_area->owners().contains(l_uninvited_id)) { sendServerMessage("You cannot uninvite a CM!"); return; } else if (!l_area->uninvite(l_uninvited_id)) { sendServerMessage("That ID is not on the invite list."); return; } sendServerMessage("You uninvited ID " + argv[0]); target_client->sendServerMessage("You were uninvited from " + l_area->name()); } void AOClient::cmdLock(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); AreaData *area = server->getAreaById(areaId()); if (area->lockStatus() == AreaData::LockStatus::LOCKED) { sendServerMessage("This area is already locked."); return; } sendServerMessageArea("This area is now locked."); area->lock(); const QVector l_clients = server->getClients(); for (AOClient *l_client : l_clients) { if (l_client->areaId() == areaId() && l_client->hasJoined()) { area->invite(l_client->clientId()); } } arup(ARUPType::LOCKED, true); } void AOClient::cmdSpectatable(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); AreaData *l_area = server->getAreaById(areaId()); if (l_area->lockStatus() == AreaData::LockStatus::SPECTATABLE) { sendServerMessage("This area is already in spectate mode."); return; } sendServerMessageArea("This area is now spectatable."); l_area->spectatable(); const QVector l_clients = server->getClients(); for (AOClient *l_client : l_clients) { if (l_client->areaId() == areaId() && l_client->hasJoined()) { l_area->invite(l_client->clientId()); } } arup(ARUPType::LOCKED, true); } void AOClient::cmdUnLock(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); AreaData *l_area = server->getAreaById(areaId()); if (l_area->lockStatus() == AreaData::LockStatus::FREE) { sendServerMessage("This area is not locked."); return; } sendServerMessageArea("This area is now unlocked."); l_area->unlock(); arup(ARUPType::LOCKED, true); } void AOClient::cmdGetAreas(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); QStringList l_entries; l_entries.append("\n== Currently Online: " + QString::number(server->getPlayerCount()) + " =="); for (int i = 0; i < server->getAreaCount(); i++) { if (server->getAreaById(i)->playerCount() > 0) { QStringList l_cur_area_lines = buildAreaList(i); l_entries.append(l_cur_area_lines); } } sendServerMessage(l_entries.join("\n")); } void AOClient::cmdGetArea(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); QStringList l_entries = buildAreaList(areaId()); sendServerMessage(l_entries.join("\n")); } void AOClient::cmdArea(int argc, QStringList argv) { Q_UNUSED(argc); bool ok; int l_new_area = argv[0].toInt(&ok); if (!ok || l_new_area >= server->getAreaCount() || l_new_area < 0) { sendServerMessage("That does not look like a valid area ID."); return; } changeArea(l_new_area); } void AOClient::cmdAreaKick(int argc, QStringList argv) { Q_UNUSED(argc); AreaData *l_area = server->getAreaById(areaId()); bool ok; int l_idx = argv[0].toInt(&ok); if (!ok) { sendServerMessage("That does not look like a valid ID."); return; } if (server->getAreaById(areaId())->owners().contains(l_idx)) { sendServerMessage("You cannot kick another CM!"); return; } AOClient *l_client_to_kick = server->getClientByID(l_idx); if (l_client_to_kick == nullptr) { sendServerMessage("No client with that ID found."); return; } else if (l_client_to_kick->areaId() != areaId()) { sendServerMessage("That client is not in this area."); return; } l_client_to_kick->changeArea(0); l_area->uninvite(l_client_to_kick->clientId()); sendServerMessage("Client " + argv[0] + " kicked back to area 0."); } void AOClient::cmdSetBackground(int argc, QStringList argv) { Q_UNUSED(argc); QString f_background = argv.join(" "); AreaData *area = server->getAreaById(areaId()); if (m_authenticated || !area->bgLocked()) { if (server->getBackgrounds().contains(f_background, Qt::CaseInsensitive) || area->ignoreBgList() == true) { area->setBackground(f_background); server->broadcast(PacketFactory::createPacket("BN", {f_background}), areaId()); QString ambience_name = ConfigManager::ambience()->value(f_background + "/ambience").toString(); if (ambience_name != "") { server->broadcast(PacketFactory::createPacket("MC", {ambience_name, "-1", characterName(), "1", "1"}), areaId()); } else { server->broadcast(PacketFactory::createPacket("MC", {"~stop.mp3", "-1", characterName(), "1", "1"}), areaId()); } sendServerMessageArea(character() + " changed the background to " + f_background); } else { sendServerMessage("Invalid background name."); } } else { sendServerMessage("This area's background is locked."); } } void AOClient::cmdBgLock(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); AreaData *l_area = server->getAreaById(areaId()); if (l_area->bgLocked() == false) { l_area->toggleBgLock(); }; server->broadcast(PacketFactory::createPacket("CT", {ConfigManager::serverName(), character() + " locked the background.", "1"}), areaId()); } void AOClient::cmdBgUnlock(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); AreaData *l_area = server->getAreaById(areaId()); if (l_area->bgLocked() == true) { l_area->toggleBgLock(); }; server->broadcast(PacketFactory::createPacket("CT", {ConfigManager::serverName(), character() + " unlocked the background.", "1"}), areaId()); } void AOClient::cmdStatus(int argc, QStringList argv) { Q_UNUSED(argc); AreaData *l_area = server->getAreaById(areaId()); QString l_arg = argv[0].toLower(); if (l_area->changeStatus(l_arg)) { arup(ARUPType::STATUS, true); server->broadcast(PacketFactory::createPacket("CT", {ConfigManager::serverName(), character() + " changed status to " + l_arg.toUpper(), "1"}), areaId()); } else { const QStringList keys = AreaData::map_statuses.keys(); sendServerMessage("That does not look like a valid status. Valid statuses are " + keys.join(", ")); } } void AOClient::cmdJudgeLog(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); AreaData *l_area = server->getAreaById(areaId()); if (l_area->judgelog().isEmpty()) { sendServerMessage("There have been no judge actions in this area."); return; } QString l_message = l_area->judgelog().join("\n"); // Judgelog contains an IPID, so we shouldn't send that unless the caller has appropriate permissions if (checkPermission(ACLRole::KICK) || checkPermission(ACLRole::BAN)) { sendServerMessage(l_message); } else { QString filteredmessage = l_message.remove(QRegularExpression("[(].*[)]")); // Filter out anything between two parentheses. This should only ever be the IPID sendServerMessage(filteredmessage); } } void AOClient::cmdIgnoreBgList(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); AreaData *l_area = server->getAreaById(areaId()); l_area->toggleIgnoreBgList(); QString l_state = l_area->ignoreBgList() ? "ignored." : "enforced."; sendServerMessage("BG list in this area is now " + l_state); } void AOClient::cmdAreaMessage(int argc, QStringList argv) { AreaData *l_area = server->getAreaById(areaId()); if (argc == 0) { sendServerMessage(l_area->areaMessage()); return; } if (argc >= 1) { l_area->changeAreaMessage(argv.join(" ")); sendServerMessage("Updated this area's message."); } } void AOClient::cmdToggleAreaMessageOnJoin(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); AreaData *l_area = server->getAreaById(areaId()); l_area->toggleAreaMessageJoin(); QString l_state = l_area->sendAreaMessageOnJoin() ? "enabled." : "disabled."; sendServerMessage("Sending message on area join is now " + l_state); } void AOClient::cmdToggleWtce(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); AreaData *l_area = server->getAreaById(areaId()); l_area->toggleWtceAllowed(); QString l_state = l_area->isWtceAllowed() ? "enabled." : "disabled."; sendServerMessage("Using testimony animations is now " + l_state); } void AOClient::cmdToggleShouts(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); AreaData *l_area = server->getAreaById(areaId()); l_area->toggleShoutAllowed(); QString l_state = l_area->isShoutAllowed() ? "enabled." : "disabled."; sendServerMessage("Using shouts is now " + l_state); } void AOClient::cmdClearAreaMessage(int argc, QStringList argv) { Q_UNUSED(argc); Q_UNUSED(argv); AreaData *l_area = server->getAreaById(areaId()); l_area->clearAreaMessage(); if (l_area->sendAreaMessageOnJoin()) // Turn off the automatic sending. cmdToggleAreaMessageOnJoin(0, QStringList{}); // Dummy values. }