/
white.sheikh
/
mangoszero-server
Обзор
Документация
Войти
/
white.sheikh
/
mangoszero-server
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/game/Object/GMTicketMgr.cpp
239 строк
8 KB
sanctum32
Replaced SIZEFMTD macro with "%zu" format parameter
04 июн 2024, 15:11
04 июн 2024, 15:11
8dec2c0
Код
Авторство
О чём код?
/** * MaNGOS is a full featured server for World of Warcraft, supporting * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 * * Copyright (C) 2005-2023 MaNGOS <https://getmangos.eu> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * World of Warcraft, and all World of Warcraft or Warcraft art, images, * and lore are copyrighted by Blizzard Entertainment, Inc. */ #include "Common.h" #include "Database/DatabaseEnv.h" #include "SQLStorages.h" #include "GMTicketMgr.h" #include "ObjectMgr.h" #include "ObjectGuid.h" #include "ProgressBar.h" #include "Policies/Singleton.h" #include "Player.h" INSTANTIATE_SINGLETON_1(GMTicketMgr); void GMTicket::SaveSurveyData(WorldPacket& recvData) const { uint32 x; recvData >> x; // answer range? (6 = 0-5?) DEBUG_LOG("SURVEY: X = %u", x); uint8 result[10]; memset(result, 0, sizeof(result)); for (int i = 0; i < 10; ++i) { uint32 questionID; recvData >> questionID; // GMSurveyQuestions.dbc if (!questionID) { break; } uint8 value; std::string unk_text; recvData >> value; // answer recvData >> unk_text; // always empty? result[i] = value; DEBUG_LOG("SURVEY: ID %u, value %u, text %s", questionID, value, unk_text.c_str()); } std::string comment; recvData >> comment; // addional comment DEBUG_LOG("SURVEY: comment %s", comment.c_str()); // TODO: chart this data in some way in DB } void GMTicket::Init(ObjectGuid guid, const std::string& text, const std::string& responseText, time_t update, uint32 ticketId) { m_guid = guid; m_ticketId = ticketId; m_text = text; m_responseText = responseText; m_lastUpdate = update; } void GMTicket::SetText(const char* text) { m_text = text ? text : ""; m_lastUpdate = time(NULL); std::string escapedString = m_text; CharacterDatabase.escape_string(escapedString); CharacterDatabase.PExecute("UPDATE `character_ticket` SET `ticket_text` = '%s' " "WHERE `guid` = '%u' AND `ticket_id` = %u", escapedString.c_str(), m_guid.GetCounter(), m_ticketId); } void GMTicket::SetResponseText(const char* text) { m_responseText = text ? text : ""; // Perform action in DB only if text is not empty if (m_responseText != "") { m_lastUpdate = time(NULL); std::string escapedString = m_responseText; CharacterDatabase.escape_string(escapedString); CharacterDatabase.PExecute("UPDATE `character_ticket` SET `response_text` = '%s' " "WHERE `guid` = '%u' and `ticket_id` = %u", escapedString.c_str(), m_guid.GetCounter(), m_ticketId); } } void GMTicket::CloseWithSurvey() const { _Close(GM_TICKET_STATUS_SURVEY); } void GMTicket::CloseByClient() const { _Close(GM_TICKET_STATUS_DO_NOTHING); } void GMTicket::Close() const { _Close(GM_TICKET_STATUS_CLOSE); } void GMTicket::_Close(GMTicketStatus statusCode) const { Player* pPlayer = sObjectMgr.GetPlayer(m_guid); CharacterDatabase.PExecute("UPDATE `character_ticket` " "SET `resolved` = 1 " "WHERE `guid` = %u AND `resolved` = 0", m_guid.GetCounter()); if (pPlayer && statusCode != GM_TICKET_STATUS_DO_NOTHING) { pPlayer->GetSession()->SendGMTicketStatusUpdate(statusCode); } } void GMTicketMgr::LoadGMTickets() { m_GMTicketMap.clear(); // For reload case QueryResult* result = CharacterDatabase.Query( // 0 1 2 3 4 "SELECT `guid`, `ticket_text`, `response_text`, UNIX_TIMESTAMP(`ticket_lastchange`), `ticket_id` " "FROM `character_ticket` " "WHERE `resolved` = 0 " "ORDER BY `ticket_id` ASC"); if (!result) { BarGoLink bar(1); bar.step(); sLog.outString(">> Loaded `character_ticket`, table is empty."); sLog.outString(); return; } BarGoLink bar(result->GetRowCount()); do { bar.step(); Field* fields = result->Fetch(); uint32 guidlow = fields[0].GetUInt32(); if (!guidlow) { continue; } ObjectGuid guid = ObjectGuid(HIGHGUID_PLAYER, guidlow); GMTicket& ticket = m_GMTicketMap[guid]; ticket.Init(guid, fields[1].GetCppString(), fields[2].GetCppString(), time_t(fields[3].GetUInt64()), fields[4].GetUInt32()); m_GMTicketIdMap[ticket.GetId()] = &ticket; } while (result->NextRow()); delete result; sLog.outString(">> Loaded %zu GM tickets", GetTicketCount()); sLog.outString(); } void GMTicketMgr::Create(ObjectGuid guid, const char* text) { std::string escapedText = text; CharacterDatabase.escape_string(escapedText); CharacterDatabase.BeginTransaction(); //This needs to be Direct (not placed in queue) as we need the id of it soon afterwards CharacterDatabase.DirectPExecute("INSERT INTO `character_ticket` " "(`guid`, `ticket_text`) " "VALUES " "(%u, '%s')", guid.GetCounter(), escapedText.c_str()); // Get the id of the ticket, needed for logging whispers // Limiting to the the most recent ticket of the player and avoid potential multiple returns // if there is inconsistent data in table (e.g : more than 1 ticket unsolved for the same player (should never happen but..who knows..) QueryResult* result = CharacterDatabase.PQuery("SELECT `ticket_id`, `guid`, `resolved` " "FROM `character_ticket` " "WHERE `guid` = %u AND `resolved` = 0 ORDER BY `ticket_id` DESC LIMIT 1;", guid.GetCounter()); CharacterDatabase.CommitTransaction(); if (!result) { return; } Field* fields = result->Fetch(); uint32 ticketId = fields[0].GetUInt32(); //This implicitly creates a new instance since we're using operator[] GMTicket& ticket = m_GMTicketMap[guid]; if (ticket.GetPlayerGuid()) { m_GMTicketIdMap.erase(ticketId); } //Lets reinitialize with new data ticket.Init(guid, text, "", time(NULL), ticketId); m_GMTicketIdMap[ticketId] = &ticket; } void GMTicketMgr::DeleteAll() { for (GMTicketMap::const_iterator itr = m_GMTicketMap.begin(); itr != m_GMTicketMap.end(); ++itr) { if (Player* owner = sObjectMgr.GetPlayer(itr->first)) { owner->GetSession()->SendGMTicketGetTicket(0x0A); } } CharacterDatabase.Execute("DELETE FROM `character_ticket`"); m_GMTicketIdMap.clear(); m_GMTicketMap.clear(); }