Core/GM System: rename columns of gm_surveys, gm_subsurveys, gm_tickets and lag_reports tables to lowerCamel, move queries to prepared statements and refactor the code of TicketMgr.

This commit is contained in:
Azazel
2011-04-19 14:04:18 +06:00
parent 890b1f6cc7
commit c36846d78a
15 changed files with 762 additions and 722 deletions
+11
View File
@@ -490,6 +490,17 @@ ChatCommand * ChatHandler::getCommandTable()
return commandTableCache;
}
std::string ChatHandler::PGetParseString(int32 entry, ...) const
{
const char *format = GetTrinityString(entry);
char str[1024];
va_list ap;
va_start(ap, entry);
vsnprintf(str, 1024, format, ap);
va_end(ap);
return std::string(str);
}
const char *ChatHandler::GetTrinityString(int32 entry) const
{
return m_session->GetTrinityString(entry);
+3 -1
View File
@@ -72,7 +72,7 @@ class ChatHandler
void SendSysMessage(int32 entry);
void PSendSysMessage(const char *format, ...) ATTR_PRINTF(2,3);
void PSendSysMessage(int32 entry, ...);
std::string PGetParseString(int32 entry, ...);
std::string PGetParseString(int32 entry, ...) const;
int ParseCommands(const char* text);
@@ -376,6 +376,8 @@ class ChatHandler
uint32 _ReadUInt32(std::istringstream& reader) const;
private:
bool _HandleGMTicketResponseAppendCommand(const char* args, bool newLine);
WorldSession * m_session; // != NULL for chat command call and NULL for CLI command
// common global flag
+188 -322
View File
@@ -25,98 +25,27 @@
#include "Chat.h"
#include "Player.h"
std::string ChatHandler::PGetParseString(int32 entry, ...)
{
const char *format = GetTrinityString(entry);
va_list ap;
char str [1024];
va_start(ap, entry);
vsnprintf(str,1024,format, ap);
va_end(ap);
return (std::string)str;
}
bool ChatHandler::HandleGMTicketListCommand(const char* /*args*/)
{
SendSysMessage(LANG_COMMAND_TICKETSHOWLIST);
for (GmTicketList::iterator itr = sTicketMgr->m_GMTicketList.begin(); itr != sTicketMgr->m_GMTicketList.end(); ++itr)
{
if ((*itr)->closed != 0 || (*itr)->completed)
continue;
std::string gmname;
std::stringstream ss;
ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid);
ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str());
if (sObjectMgr->GetPlayerNameByGUID((*itr)->assignedToGM, gmname))
ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str());
SendSysMessage(ss.str().c_str());
}
sTicketMgr->ShowList(*this, false);
return true;
}
bool ChatHandler::HandleGMTicketListOnlineCommand(const char* /*args*/)
{
SendSysMessage(LANG_COMMAND_TICKETSHOWONLINELIST);
for (GmTicketList::iterator itr = sTicketMgr->m_GMTicketList.begin(); itr != sTicketMgr->m_GMTicketList.end(); ++itr)
{
if ((*itr)->closed != 0 || (*itr)->completed || !sObjectMgr->GetPlayer((*itr)->playerGuid))
continue;
std::string gmname;
std::stringstream ss;
ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid);
ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str());
if (sObjectMgr->GetPlayerNameByGUID((*itr)->assignedToGM, gmname))
ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str());
SendSysMessage(ss.str().c_str());
}
sTicketMgr->ShowList(*this, true);
return true;
}
bool ChatHandler::HandleGMTicketListClosedCommand(const char* /*args*/)
{
SendSysMessage(LANG_COMMAND_TICKETSHOWCLOSEDLIST);
for (GmTicketList::iterator itr = sTicketMgr->m_GMTicketList.begin(); itr != sTicketMgr->m_GMTicketList.end(); ++itr)
{
if ((*itr)->closed == 0)
continue;
std::string gmname;
std::stringstream ss;
ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid);
ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str());
if (sObjectMgr->GetPlayerNameByGUID((*itr)->assignedToGM, gmname))
ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str());
SendSysMessage(ss.str().c_str());
}
sTicketMgr->ShowClosedList(*this);
return true;
}
bool ChatHandler::HandleGMTicketListEscalatedCommand(const char* /*args*/)
{
SendSysMessage(LANG_COMMAND_TICKETSHOWESCALATEDLIST);
for (GmTicketList::iterator itr = sTicketMgr->m_GMTicketList.begin(); itr != sTicketMgr->m_GMTicketList.end(); ++itr)
{
if (!((*itr)->escalated == TICKET_IN_ESCALATION_QUEUE) || (*itr)->closed != 0)
continue;
std::string gmname;
std::stringstream ss;
ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid);
ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str());
SendSysMessage(ss.str().c_str());
}
sTicketMgr->ShowEscalatedList(*this);
return true;
}
@@ -125,31 +54,19 @@ bool ChatHandler::HandleGMTicketGetByIdCommand(const char* args)
if (!*args)
return false;
uint64 tguid = atoi(args);
GM_Ticket *ticket = sTicketMgr->GetGMTicket(tguid);
if (!ticket || ticket->closed != 0 || ticket->completed)
uint32 ticketId = atoi(args);
GmTicket *ticket = sTicketMgr->GetTicket(ticketId);
if (!ticket || ticket->IsClosed() || ticket->IsCompleted())
{
SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
ticket->viewed = true;
std::string gmname;
std::stringstream ss;
ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid);
ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - ticket->createtime, true, false)).c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - ticket->timestamp, true, false)).c_str());
SQLTransaction trans = SQLTransaction(NULL);
ticket->SetViewed();
ticket->SaveToDB(trans);
if (sObjectMgr->GetPlayerNameByGUID(ticket->assignedToGM, gmname))
ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTMESSAGE, ticket->message.c_str());
if (strlen(ticket->comment.c_str()) != 0)
ss << PGetParseString(LANG_COMMAND_TICKETLISTCOMMENT, ticket->comment.c_str());
SendSysMessage(ss.str().c_str());
SendSysMessage(ticket->FormatMessageString(*this, true).c_str());
return true;
}
@@ -158,41 +75,35 @@ bool ChatHandler::HandleGMTicketGetByNameCommand(const char* args)
if (!*args)
return false;
std::string name = (char*)args;
normalizePlayerName(name);
std::string name(args);
if (!normalizePlayerName(name))
return false;
Player *plr = sObjectMgr->GetPlayer(name.c_str());
if (!plr)
// Detect target's GUID
uint64 guid = 0;
if (Player *player = sObjectMgr->GetPlayer(name.c_str()))
guid = player->GetGUID();
else
guid = sObjectMgr->GetPlayerGUIDByName(name);
// Target must exist
if (!guid)
{
SendSysMessage(LANG_NO_PLAYERS_FOUND);
return true;
}
GM_Ticket *ticket = sTicketMgr->GetGMTicketByPlayer(plr->GetGUID());
// Ticket must exist
GmTicket *ticket = sTicketMgr->GetTicketByPlayer(guid);
if (!ticket)
{
SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
ticket->viewed = true;
std::string gmname;
std::stringstream ss;
ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid);
ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - ticket->createtime, true, false)).c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - ticket->timestamp, true, false)).c_str());
if (sObjectMgr->GetPlayerNameByGUID(ticket->assignedToGM, gmname))
ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTMESSAGE, ticket->message.c_str());
if (strlen(ticket->comment.c_str()) != 0)
ss << PGetParseString(LANG_COMMAND_TICKETLISTCOMMENT, ticket->comment.c_str());
SendSysMessage(ss.str().c_str());
SQLTransaction trans = SQLTransaction(NULL);
ticket->SetViewed();
ticket->SaveToDB(trans);
SendSysMessage(ticket->FormatMessageString(*this, true).c_str());
return true;
}
@@ -201,37 +112,34 @@ bool ChatHandler::HandleGMTicketCloseByIdCommand(const char* args)
if (!*args)
return false;
uint64 tguid = atoi(args);
GM_Ticket *ticket = sTicketMgr->GetGMTicket(tguid);
if (!ticket || ticket->closed != 0 || ticket->completed)
uint32 ticketId = atoi(args);
GmTicket* ticket = sTicketMgr->GetTicket(ticketId);
if (!ticket || ticket->IsClosed() || ticket->IsCompleted())
{
SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
if (ticket && ticket->assignedToGM != 0 && ticket->assignedToGM != m_session->GetPlayer()->GetGUID())
// Ticket must be assigned to player, who tries to close it.
uint64 guid = m_session->GetPlayer()->GetGUID();
if (ticket->IsAssignedNotTo(guid))
{
PSendSysMessage(LANG_COMMAND_TICKETCANNOTCLOSE, ticket->guid);
PSendSysMessage(LANG_COMMAND_TICKETCANNOTCLOSE, ticket->GetId());
return true;
}
std::stringstream ss;
ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid);
ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str());
ss << PGetParseString(LANG_COMMAND_TICKETCLOSED, m_session->GetPlayer()->GetName());
SendGlobalGMSysMessage(ss.str().c_str());
Player *plr = sObjectMgr->GetPlayer(ticket->playerGuid);
sTicketMgr->RemoveGMTicket(ticket, m_session->GetPlayer()->GetGUID());
if (!plr || !plr->IsInWorld())
return true;
// send abandon ticket
WorldPacket deleteTicket(SMSG_GMTICKET_DELETETICKET, 4);
deleteTicket << uint32(GMTICKET_RESPONSE_TICKET_DELETED);
plr->GetSession()->SendPacket(&deleteTicket);
sTicketMgr->CloseTicket(ticket->GetId(), guid);
sTicketMgr->UpdateLastChange();
std::string msg = ticket->FormatMessageString(*this, m_session->GetPlayer()->GetName(), NULL, NULL, NULL);
SendGlobalGMSysMessage(msg.c_str());
// Inform player, who submitted this ticket, that it is closed
if (Player *player = ticket->GetPlayer())
if (player->IsInWorld())
{
WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4);
data << uint32(GMTICKET_RESPONSE_TICKET_DELETED);
player->GetSession()->SendPacket(&data);
}
return true;
}
@@ -240,66 +148,55 @@ bool ChatHandler::HandleGMTicketAssignToCommand(const char* args)
if (!*args)
return false;
char* tguid = strtok((char*)args, " ");
uint64 ticketGuid = atoi(tguid);
char* targetgm = strtok(NULL, " ");
char* sTicketId = strtok((char*)args, " ");
uint32 ticketId = atoi(sTicketId);
if (!targetgm)
char* sTarget = strtok(NULL, " ");
if (!sTarget)
return false;
std::string targm = targetgm;
if (!normalizePlayerName(targm))
std::string target(sTarget);
if (!normalizePlayerName(target))
return false;
Player *cplr = m_session->GetPlayer();
GM_Ticket *ticket = sTicketMgr->GetGMTicket(ticketGuid);
if (!ticket || ticket->closed != 0)
GmTicket* ticket = sTicketMgr->GetTicket(ticketId);
if (!ticket || ticket->IsClosed())
{
SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
uint64 tarGUID = sObjectMgr->GetPlayerGUIDByName(targm.c_str());
uint64 accid = sObjectMgr->GetPlayerAccountIdByGUID(tarGUID);
uint32 gmlevel = sAccountMgr->GetSecurity(accid, realmID);
if (!tarGUID || gmlevel == SEC_PLAYER)
// Get target information
uint64 targetGuid = sObjectMgr->GetPlayerGUIDByName(target.c_str());
uint64 targetAccId = sObjectMgr->GetPlayerAccountIdByGUID(targetGuid);
uint32 targetGmLevel = sAccountMgr->GetSecurity(targetAccId, realmID);
// Target must exist and have administrative rights
if (!targetGuid || targetGmLevel == SEC_PLAYER)
{
SendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_A);
return true;
}
if (ticket->assignedToGM == tarGUID)
// If already assigned, leave
if (ticket->IsAssignedTo(targetGuid))
{
PSendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_B, ticket->guid);
PSendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_B, ticket->GetId());
return true;
}
std::string gmname;
sObjectMgr->GetPlayerNameByGUID(tarGUID, gmname);
if (ticket->assignedToGM != 0 && ticket->assignedToGM != cplr->GetGUID())
// If assigned to different player other than current, leave
Player *player = m_session->GetPlayer();
if (ticket->IsAssignedNotTo(player->GetGUID()))
{
PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->guid, gmname.c_str());
PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->GetId(), target.c_str());
return true;
}
ticket->assignedToGM = tarGUID;
if (gmlevel == SEC_ADMINISTRATOR && ticket->escalated == TICKET_IN_ESCALATION_QUEUE)
ticket->escalated = TICKET_ESCALATED_ASSIGNED;
else if (ticket->escalated == TICKET_UNASSIGNED)
ticket->escalated = TICKET_ASSIGNED;
sTicketMgr->AddOrUpdateGMTicket(*ticket);
std::stringstream ss;
ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid);
ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str());
SendGlobalGMSysMessage(ss.str().c_str());
// Assign ticket
SQLTransaction trans = SQLTransaction(NULL);
ticket->SetAssignedTo(targetGuid, targetGmLevel == SEC_ADMINISTRATOR);
ticket->SaveToDB(trans);
sTicketMgr->UpdateLastChange();
std::string msg = ticket->FormatMessageString(*this, NULL, target.c_str(), NULL, NULL);
SendGlobalGMSysMessage(msg.c_str());
return true;
}
@@ -308,41 +205,45 @@ bool ChatHandler::HandleGMTicketUnAssignCommand(const char* args)
if (!*args)
return false;
uint64 ticketGuid = atoi(args);
Player *cplr = m_session->GetPlayer();
GM_Ticket *ticket = sTicketMgr->GetGMTicket(ticketGuid);
if (!ticket|| ticket->closed != 0)
uint32 ticketId = atoi(args);
GmTicket *ticket = sTicketMgr->GetTicket(ticketId);
if (!ticket || ticket->IsClosed())
{
SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
if (ticket->assignedToGM == 0)
// Ticket must be assigned
if (!ticket->IsAssigned())
{
PSendSysMessage(LANG_COMMAND_TICKETNOTASSIGNED, ticket->guid);
PSendSysMessage(LANG_COMMAND_TICKETNOTASSIGNED, ticket->GetId());
return true;
}
std::string gmname;
sObjectMgr->GetPlayerNameByGUID(ticket->assignedToGM, gmname);
Player *plr = sObjectMgr->GetPlayer(ticket->assignedToGM);
if (plr && plr->IsInWorld() && plr->GetSession()->GetSecurity() > cplr->GetSession()->GetSecurity())
// Get security level of player, whom this ticket is assigned to
uint32 security = SEC_PLAYER;
Player* assignedPlayer = ticket->GetAssignedPlayer();
if (assignedPlayer && assignedPlayer->IsInWorld())
security = assignedPlayer->GetSession()->GetSecurity();
else
{
uint64 guid = ticket->GetAssignedToGUID();
uint32 accountId = sObjectMgr->GetPlayerAccountIdByGUID(guid);
security = sAccountMgr->GetSecurity(accountId, realmID);
}
// Check security
Player *player = m_session->GetPlayer();
if (security > uint32(player->GetSession()->GetSecurity()))
{
SendSysMessage(LANG_COMMAND_TICKETUNASSIGNSECURITY);
return true;
}
std::stringstream ss;
ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid);
ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTUNASSIGNED, cplr->GetName());
SendGlobalGMSysMessage(ss.str().c_str());
ticket->assignedToGM = 0;
if (ticket->escalated != TICKET_UNASSIGNED && ticket->escalated != TICKET_IN_ESCALATION_QUEUE)
ticket->escalated--;
sTicketMgr->AddOrUpdateGMTicket(*ticket);
SQLTransaction trans = SQLTransaction(NULL);
ticket->SetUnassigned();
ticket->SaveToDB(trans);
sTicketMgr->UpdateLastChange();
std::string msg = ticket->FormatMessageString(*this, NULL, ticket->GetAssignedToName(), player->GetName(), NULL);
SendGlobalGMSysMessage(msg.c_str());
return true;
}
@@ -352,40 +253,35 @@ bool ChatHandler::HandleGMTicketCommentCommand(const char* args)
return false;
char* tguid = strtok((char*)args, " ");
uint64 ticketGuid = atoi(tguid);
char* comment = strtok(NULL, "\n");
uint32 ticketId = atoi(tguid);
char* comment = strtok(NULL, "\n");
if (!comment)
return false;
Player *cplr = m_session->GetPlayer();
GM_Ticket *ticket = sTicketMgr->GetGMTicket(ticketGuid);
if (!ticket || ticket->closed != 0)
GmTicket *ticket = sTicketMgr->GetTicket(ticketId);
if (!ticket || ticket->IsClosed())
{
PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
if (ticket->assignedToGM != 0 && ticket->assignedToGM != cplr->GetGUID())
// Cannot comment ticket assigned to someone else
Player* player = m_session->GetPlayer();
if (ticket->IsAssignedNotTo(player->GetGUID()))
{
PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->guid);
PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->GetId());
return true;
}
std::string gmname;
sObjectMgr->GetPlayerNameByGUID(ticket->assignedToGM, gmname);
ticket->comment = comment;
sTicketMgr->AddOrUpdateGMTicket(*ticket);
std::stringstream ss;
ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid);
ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str());
if (sObjectMgr->GetPlayerNameByGUID(ticket->assignedToGM, gmname))
ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str());
ss << PGetParseString(LANG_COMMAND_TICKETLISTADDCOMMENT, cplr->GetName(), ticket->comment.c_str());
SendGlobalGMSysMessage(ss.str().c_str());
SQLTransaction trans = SQLTransaction(NULL);
ticket->SetComment(comment);
ticket->SaveToDB(trans);
sTicketMgr->UpdateLastChange();
std::string msg = ticket->FormatMessageString(*this, NULL, ticket->GetAssignedToName(), NULL, NULL);
msg += PGetParseString(LANG_COMMAND_TICKETLISTADDCOMMENT, player->GetName(), comment);
SendGlobalGMSysMessage(msg.c_str());
return true;
}
@@ -393,48 +289,42 @@ bool ChatHandler::HandleGMTicketDeleteByIdCommand(const char* args)
{
if (!*args)
return false;
uint64 ticketGuid = atoi(args);
GM_Ticket *ticket = sTicketMgr->GetGMTicket(ticketGuid);
uint32 ticketId = atoi(args);
GmTicket* ticket = sTicketMgr->GetTicket(ticketId);
if (!ticket)
{
SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
if (ticket->closed == 0)
if (!ticket->IsClosed())
{
SendSysMessage(LANG_COMMAND_TICKETCLOSEFIRST);
return true;
}
std::stringstream ss;
ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid);
ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str());
ss << PGetParseString(LANG_COMMAND_TICKETDELETED, m_session->GetPlayer()->GetName());
SendGlobalGMSysMessage(ss.str().c_str());
Player *plr = sObjectMgr->GetPlayer(ticket->playerGuid);
sTicketMgr->RemoveGMTicket(ticket, -1, true); // we don't need to care about who deleted it...
if (plr && plr->IsInWorld())
{
// Force abandon ticket
WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4);
data << uint32(GMTICKET_RESPONSE_TICKET_DELETED);
plr->GetSession()->SendPacket(&data);
}
std::string msg = ticket->FormatMessageString(*this, NULL, NULL, NULL, m_session->GetPlayer()->GetName());
SendGlobalGMSysMessage(msg.c_str());
ticket = NULL;
sTicketMgr->RemoveTicket(ticket->GetId());
sTicketMgr->UpdateLastChange();
if (Player* player = ticket->GetPlayer())
if (player->IsInWorld())
{
// Force abandon ticket
WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4);
data << uint32(GMTICKET_RESPONSE_TICKET_DELETED);
player->GetSession()->SendPacket(&data);
}
return true;
}
bool ChatHandler::HandleToggleGMTicketSystem(const char* /* args */)
{
sTicketMgr->SetStatus(!sTicketMgr->GetStatus());
if (sTicketMgr->GetStatus())
PSendSysMessage(LANG_ALLOW_TICKETS);
else
PSendSysMessage(LANG_DISALLOW_TICKETS);
bool status = !sTicketMgr->GetStatus();
sTicketMgr->SetStatus(status);
PSendSysMessage(status ? LANG_ALLOW_TICKETS : LANG_DISALLOW_TICKETS);
return true;
}
@@ -443,19 +333,20 @@ bool ChatHandler::HandleGMTicketEscalateCommand(const char *args)
if (!*args)
return false;
uint64 tguid = atoi(args);
GM_Ticket *ticket = sTicketMgr->GetGMTicket(tguid);
if (!ticket || ticket->closed != 0 || ticket->completed || ticket->escalated != TICKET_UNASSIGNED)
uint32 ticketId = atoi(args);
GmTicket* ticket = sTicketMgr->GetTicket(ticketId);
if (!ticket || !ticket->IsClosed() || ticket->IsCompleted() || ticket->GetEscalatedStatus() != TICKET_UNASSIGNED)
{
SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
ticket->escalated = TICKET_IN_ESCALATION_QUEUE;
ticket->SetEscalatedStatus(TICKET_IN_ESCALATION_QUEUE);
if (Player* player = ticket->GetPlayer())
if (player->IsInWorld())
sTicketMgr->SendTicket(player->GetSession(), ticket);
Player *plr = sObjectMgr->GetPlayer(ticket->playerGuid);
if (plr && plr->IsInWorld())
plr->GetSession()->SendGMTicketGetTicket(GMTICKET_STATUS_HASTEXT, ticket->message.c_str(), ticket);
sTicketMgr->UpdateLastChange();
return true;
}
@@ -465,88 +356,63 @@ bool ChatHandler::HandleGMTicketCompleteCommand(const char* args)
if (!*args)
return false;
uint64 tguid = atoi(args);
GM_Ticket *ticket = sTicketMgr->GetGMTicket(tguid);
if (!ticket || ticket->closed != 0 || ticket->completed)
uint32 ticketId = atoi(args);
GmTicket* ticket = sTicketMgr->GetTicket(ticketId);
if (!ticket || !ticket->IsClosed() || ticket->IsCompleted())
{
SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
Player *plr = sObjectMgr->GetPlayer(ticket->playerGuid);
if (plr && plr->IsInWorld())
plr->GetSession()->SendGMTicketResponse(ticket);
if (Player *player = ticket->GetPlayer())
if (player->IsInWorld())
ticket->SendResponse(player->GetSession());
sTicketMgr->UpdateLastChange();
return true;
}
inline bool ChatHandler::_HandleGMTicketResponseAppendCommand(const char* args, bool newLine)
{
if (!*args)
return false;
char* sTicketId = strtok((char*)args, " ");
uint32 ticketId = atoi(sTicketId);
char* response = strtok(NULL, "\n");
if (!response)
return false;
GmTicket* ticket = sTicketMgr->GetTicket(ticketId);
if (!ticket || !ticket->IsClosed())
{
PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
// Cannot add response to ticket, assigned to someone else
Player* player = m_session->GetPlayer();
if (ticket->IsAssignedNotTo(player->GetGUID()))
{
PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->GetId());
return true;
}
SQLTransaction trans = SQLTransaction(NULL);
ticket->AppendResponse(response);
if (newLine)
ticket->AppendResponse("\n");
ticket->SaveToDB(trans);
return true;
}
bool ChatHandler::HandleGMTicketResponseAppendCommand(const char* args)
{
if (!*args)
return false;
char* tguid = strtok((char*)args, " ");
uint64 ticketGuid = atoi(tguid);
char* response = strtok(NULL, "\n");
if (!response)
return false;
GM_Ticket *ticket = sTicketMgr->GetGMTicket(ticketGuid);
Player *cplr = m_session->GetPlayer();
if (!ticket || ticket->closed != 0)
{
PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
if (ticket->assignedToGM != 0 && ticket->assignedToGM != cplr->GetGUID())
{
PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->guid);
return true;
}
std::stringstream ss;
ss << ticket->response;
ss << response;
ticket->response = ss.str();
sTicketMgr->AddOrUpdateGMTicket(*ticket);
return true;
return _HandleGMTicketResponseAppendCommand(args, false);
}
bool ChatHandler::HandleGMTicketResponseAppendLnCommand(const char* args)
{
if (!*args)
return false;
char* tguid = strtok((char*)args, " ");
uint64 ticketGuid = atoi(tguid);
char* response = strtok(NULL, "\n");
if (!response)
return false;
GM_Ticket *ticket = sTicketMgr->GetGMTicket(ticketGuid);
Player *cplr = m_session->GetPlayer();
if (!ticket || ticket->closed != 0)
{
PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
if (ticket->assignedToGM != 0 && ticket->assignedToGM != cplr->GetGUID())
{
PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->guid);
return true;
}
std::stringstream ss;
ss << ticket->response;
ss << response;
ss << "\n";
ticket->response = ss.str();
sTicketMgr->AddOrUpdateGMTicket(*ticket);
return true;
return _HandleGMTicketResponseAppendCommand(args, true);
}
+3 -1
View File
@@ -4870,7 +4870,9 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
trans->PAppend("DELETE FROM character_reputation WHERE guid = '%u'",guid);
trans->PAppend("DELETE FROM character_spell WHERE guid = '%u'",guid);
trans->PAppend("DELETE FROM character_spell_cooldown WHERE guid = '%u'",guid);
trans->PAppend("DELETE FROM gm_tickets WHERE playerGuid = '%u'", guid);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_GM_TICKETS);
stmt->setUInt32(0, guid);
trans->Append(stmt);
trans->PAppend("DELETE FROM item_instance WHERE owner_guid = '%u'",guid);
trans->PAppend("DELETE FROM character_social WHERE guid = '%u' OR friend='%u'",guid,guid);
trans->PAppend("DELETE FROM mail WHERE receiver = '%u'",guid);
@@ -38,54 +38,22 @@ void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recv_data)
return;
}
if (sTicketMgr->GetGMTicketByPlayer(GetPlayer()->GetGUID()))
GMTicketResponse response = GMTICKET_RESPONSE_FAILURE;
// Player must not have ticket
if (!sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID()))
{
WorldPacket data(SMSG_GMTICKET_CREATE, 4);
data << uint32(GMTICKET_RESPONSE_FAILURE); // You already have GM ticket
SendPacket(&data);
return;
GmTicket* ticket = new GmTicket(GetPlayer(), recv_data);
sTicketMgr->AddTicket(ticket);
sTicketMgr->UpdateLastChange();
sWorld->SendGMText(LANG_COMMAND_TICKETNEW, GetPlayer()->GetName(), ticket->GetId());
response = GMTICKET_RESPONSE_SUCCESS;
}
uint32 map, unk1;
uint8 needResponse; // ignored
float x, y, z;
std::string ticketText, ticketText2;
SendQueryTimeResponse();
recv_data >> map;
recv_data >> x;
recv_data >> y;
recv_data >> z;
recv_data >> ticketText;
recv_data >> unk1; // not sure what this is... replyTo?
recv_data >> needResponse; // always 1/0 -- not sure what retail does with this
GM_Ticket *ticket = new GM_Ticket;
ticket->name = GetPlayer()->GetName();
ticket->guid = sTicketMgr->GenerateGMTicketId();
ticket->playerGuid = GetPlayer()->GetGUID();
ticket->message = ticketText;
ticket->createtime = time(NULL);
ticket->map = map;
ticket->pos_x = x;
ticket->pos_y = y;
ticket->pos_z = z;
ticket->timestamp = time(NULL);
ticket->closed = 0;
ticket->assignedToGM = 0;
ticket->comment = "";
ticket->completed = false;
ticket->escalated = TICKET_UNASSIGNED;
ticket->response = "";
sTicketMgr->AddOrUpdateGMTicket(*ticket, true);
WorldPacket data(SMSG_GMTICKET_CREATE, 4);
data << uint32(GMTICKET_RESPONSE_SUCCESS);
data << uint32(response);
SendPacket(&data);
sWorld->SendGMText(LANG_COMMAND_TICKETNEW, GetPlayer()->GetName(), ticket->guid);
}
void WorldSession::HandleGMTicketUpdateOpcode(WorldPacket & recv_data)
@@ -93,40 +61,35 @@ void WorldSession::HandleGMTicketUpdateOpcode(WorldPacket & recv_data)
std::string message;
recv_data >> message;
GM_Ticket *ticket = sTicketMgr->GetGMTicketByPlayer(GetPlayer()->GetGUID());
if (!ticket)
GMTicketResponse response = GMTICKET_RESPONSE_FAILURE;
if (GmTicket *ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID()))
{
WorldPacket data(SMSG_GMTICKET_UPDATETEXT, 4);
data << uint32(GMTICKET_RESPONSE_FAILURE);
SendPacket(&data);
return;
SQLTransaction trans = SQLTransaction(NULL);
ticket->SetMessage(message);
ticket->SaveToDB(trans);
sWorld->SendGMText(LANG_COMMAND_TICKETUPDATED, GetPlayer()->GetName(), ticket->GetId());
response = GMTICKET_RESPONSE_SUCCESS;
}
ticket->message = message;
ticket->timestamp = time(NULL);
sTicketMgr->AddOrUpdateGMTicket(*ticket);
WorldPacket data(SMSG_GMTICKET_UPDATETEXT, 4);
data << uint32(GMTICKET_RESPONSE_SUCCESS);
data << uint32(response);
SendPacket(&data);
sWorld->SendGMText(LANG_COMMAND_TICKETUPDATED, GetPlayer()->GetName(), ticket->guid);
}
void WorldSession::HandleGMTicketDeleteOpcode(WorldPacket & /*recv_data*/)
{
GM_Ticket* ticket = sTicketMgr->GetGMTicketByPlayer(GetPlayer()->GetGUID());
if (ticket)
if (GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID()))
{
WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4);
data << uint32(GMTICKET_RESPONSE_TICKET_DELETED);
SendPacket(&data);
sWorld->SendGMText(LANG_COMMAND_TICKETPLAYERABANDON, GetPlayer()->GetName(), ticket->guid);
sTicketMgr->RemoveGMTicket(ticket, GetPlayer()->GetGUID(), false);
SendGMTicketGetTicket(GMTICKET_STATUS_DEFAULT, NULL);
sWorld->SendGMText(LANG_COMMAND_TICKETPLAYERABANDON, GetPlayer()->GetName(), ticket->GetId());
sTicketMgr->CloseTicket(ticket->GetId(), GetPlayer()->GetGUID());
sTicketMgr->SendTicket(this, NULL);
}
}
@@ -134,139 +97,64 @@ void WorldSession::HandleGMTicketGetTicketOpcode(WorldPacket & /*recv_data*/)
{
SendQueryTimeResponse();
if (GM_Ticket *ticket = sTicketMgr->GetGMTicketByPlayer(GetPlayer()->GetGUID()))
if (GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID()))
{
if (ticket->completed)
SendGMTicketResponse(ticket);
if (ticket->IsCompleted())
ticket->SendResponse(this);
else
SendGMTicketGetTicket(GMTICKET_STATUS_HASTEXT, ticket->message.c_str(), ticket);
sTicketMgr->SendTicket(this, ticket);
}
else
SendGMTicketGetTicket(GMTICKET_STATUS_DEFAULT, NULL);
sTicketMgr->SendTicket(this, NULL);
}
void WorldSession::HandleGMTicketSystemStatusOpcode(WorldPacket & /*recv_data*/)
{
WorldPacket data(SMSG_GMTICKET_SYSTEMSTATUS, 4);
// Note: This only disables the ticket UI at client side and is not fully reliable
// are we sure this is a uint32? Should ask Zor
WorldPacket data(SMSG_GMTICKET_SYSTEMSTATUS, 4);
data << uint32(sTicketMgr->GetStatus() ? GMTICKET_QUEUE_STATUS_ENABLED : GMTICKET_QUEUE_STATUS_DISABLED);
SendPacket(&data);
}
void WorldSession::SendGMTicketGetTicket(uint32 status, char const* text, GM_Ticket *ticket /* = NULL */)
{
int len = text ? strlen(text) : 0;
WorldPacket data(SMSG_GMTICKET_GETTICKET, (4+4+((status == GMTICKET_STATUS_HASTEXT) ? (len+1+4+4+4+1+1) : 0)));
data << uint32(status); // standard 0x0A, 0x06 if text present
data << uint32(1); // g_HasActiveGMTicket -- not a flag
if (status == GMTICKET_STATUS_HASTEXT)
{
data << text; // ticket text
data << uint8(0x7); // ticket category; why is this hardcoded? does it make a diff re: client?
// we've got the easy stuff done by now.
// Now we need to go through the client logic for displaying various levels of ticket load
if (ticket)
{
// get ticketage, but it's stored in seconds so we have to do it in days
float ticketAge = (float)time(NULL) - (float)ticket->timestamp;
ticketAge /= DAY;
data << float(ticketAge); // ticketAge (days)
if (GM_Ticket *oldestTicket = sTicketMgr->GetOldestOpenGMTicket())
{
// get ticketage, but it's stored in seconds so we have to do it in days
float oldestTicketAge = (float)time(NULL) - (float)oldestTicket->timestamp;
oldestTicketAge /= DAY;
data << float(oldestTicketAge);
}
else
data << float(0);
// I am not sure how blizzlike this is, and we don't really have a way to find out
int64 lastChange = int64(sTicketMgr->GetLastChange());
float timeDiff = float(int64(time(NULL)) - lastChange);
timeDiff /= DAY;
data << float(timeDiff);
data << uint8(std::min(ticket->escalated, uint8(TICKET_IN_ESCALATION_QUEUE))); // escalated data
data << uint8(ticket->viewed ? GMTICKET_OPENEDBYGM_STATUS_OPENED : GMTICKET_OPENEDBYGM_STATUS_NOT_OPENED); // whether or not it has been viewed
}
else
{
// we can't actually get any numbers here...
data << float(0);
data << float(0);
data << float(1);
data << uint8(0);
data << uint8(0);
}
}
SendPacket(&data);
}
void WorldSession::SendGMTicketResponse(GM_Ticket *ticket)
{
if (!ticket)
return;
WorldPacket data(SMSG_GMRESPONSE_RECEIVED);
data << uint32(1); // unk? Zor says "hasActiveTicket"
data << uint32(0); // can-edit - always 1 or 0, not flags
data << ticket->message.c_str();
data << ticket->response.c_str();
for (int8 j = 0; j < 3; j++)
data << uint8(0); // 3 null strings
SendPacket(&data);
}
void WorldSession::HandleGMSurveySubmit(WorldPacket& recv_data)
{
uint64 nextSurveyID = sTicketMgr->GetNextSurveyID();
uint32 nextSurveyID = sTicketMgr->GetNextSurveyID();
// just put the survey into the database
std::ostringstream ss;
uint32 mainSurvey; // GMSurveyCurrentSurvey.dbc, column 1 (all 9) ref to GMSurveySurveys.dbc
recv_data >> mainSurvey;
ss << "INSERT INTO gm_surveys (player, surveyid, mainSurvey, overall_comment, timestamp) VALUES (";
ss << GetPlayer()->GetGUID() << ", ";
ss << uint32(nextSurveyID) << ", ";
ss << mainSurvey << ", ";
// sub_survey1, r1, comment1, sub_survey2, r2, comment2, sub_survey3, r3, comment3, sub_survey4, r4, comment4, sub_survey5, r5, comment5, sub_survey6, r6, comment6, sub_survey7, r7, comment7, sub_survey8, r8, comment8, sub_survey9, r9, comment9, sub_survey10, r10, comment10,
for (uint8 i = 0; i < 10; i++)
{
std::ostringstream os;
os << "INSERT INTO gm_subsurveys (surveyid, subsurveyid, rank, comment) VALUES (";
uint32 subSurveyId; // ref to i'th GMSurveySurveys.dbc field (all fields in that dbc point to fields in GMSurveyQuestions.dbc)
recv_data >> subSurveyId;
if(!subSurveyId)
if (!subSurveyId)
break;
uint8 rank; // probably some sort of ref to GMSurveyAnswers.dbc
std::string comment; // comment ("Usage: GMSurveyAnswerSubmit(question, rank, comment)")
recv_data >> rank;
std::string comment; // comment ("Usage: GMSurveyAnswerSubmit(question, rank, comment)")
recv_data >> comment;
os << uint32(nextSurveyID) << " ";
os << subSurveyId << ", ";
os << uint16(rank) << ", '";
CharacterDatabase.escape_string(comment);
os << comment << "');";
CharacterDatabase.PExecute(os.str().c_str());
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_GM_SUBSURVEY);
stmt->setUInt32(0, nextSurveyID);
stmt->setUInt32(1, subSurveyId);
stmt->setUInt32(2, rank);
stmt->setString(3, comment);
CharacterDatabase.Execute(stmt);
}
std::string comment; // just a guess
recv_data >> comment;
CharacterDatabase.escape_string(comment);
ss << "'" << comment << "', ";
ss << int64(time_t(NULL)) << ");";
CharacterDatabase.PExecute(ss.str().c_str());
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_GM_SURVEY);
stmt->setUInt32(0, GUID_LOPART(GetPlayer()->GetGUID()));
stmt->setUInt32(1, nextSurveyID);
stmt->setUInt32(2, mainSurvey);
stmt->setString(3, comment);
CharacterDatabase.Execute(stmt);
}
void WorldSession::HandleReportLag(WorldPacket& recv_data)
@@ -274,35 +162,30 @@ void WorldSession::HandleReportLag(WorldPacket& recv_data)
// just put the lag report into the database...
// can't think of anything else to do with it
uint32 lagType, mapId;
float x, y, z;
recv_data >> lagType;
recv_data >> mapId;
float x, y, z;
recv_data >> x;
recv_data >> y;
recv_data >> z;
// build and execute query
std::ostringstream os;
os << "INSERT INTO lag_reports (player, lag_type, map, posX, posY, posZ) VALUES (";
os << GetPlayer()->GetGUID() << ", ";
os << lagType << ", ";
os << mapId << ", ";
os << x << ", ";
os << y << ", ";
os << z << ");";
CharacterDatabase.Execute(os.str().c_str());
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_LAG_REPORT);
stmt->setUInt32(0, GUID_LOPART(GetPlayer()->GetGUID()));
stmt->setUInt8 (1, lagType);
stmt->setUInt16(2, mapId);
stmt->setFloat (3, x);
stmt->setFloat (4, y);
stmt->setFloat (5, z);
CharacterDatabase.Execute(stmt);
}
void WorldSession::HandleGMResponseResolve(WorldPacket& /*recvPacket*/)
{
// empty packet
GM_Ticket* ticket = sTicketMgr->GetGMTicketByPlayer(GetPlayer()->GetGUID());
if (ticket)
if (GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID()))
{
uint8 getSurvey = 0;
if ((float)rand_chance() < sWorld->getFloatConfig(CONFIG_CHANCE_OF_GM_SURVEY))
if (float(rand_chance()) < sWorld->getFloatConfig(CONFIG_CHANCE_OF_GM_SURVEY))
getSurvey = 1;
WorldPacket data(SMSG_GMRESPONSE_STATUS_UPDATE, 4);
@@ -312,7 +195,8 @@ void WorldSession::HandleGMResponseResolve(WorldPacket& /*recvPacket*/)
WorldPacket data2(SMSG_GMTICKET_DELETETICKET, 4);
data2 << uint32(GMTICKET_RESPONSE_TICKET_DELETED);
SendPacket(&data2);
sTicketMgr->RemoveGMTicket(ticket, GetPlayer()->GetGUID(), true);
SendGMTicketGetTicket(GMTICKET_STATUS_DEFAULT, NULL);
sTicketMgr->CloseTicket(ticket->GetId(), GetPlayer()->GetGUID());
sTicketMgr->SendTicket(this, NULL);
}
}
-3
View File
@@ -47,7 +47,6 @@ class LoginQueryHolder;
class CharacterHandler;
class SpellCastTargets;
struct AreaTableEntry;
struct GM_Ticket;
struct LfgJoinResultData;
struct LfgLockStatus;
struct LfgPlayerBoot;
@@ -425,8 +424,6 @@ class WorldSession
void HandleGMTicketDeleteOpcode(WorldPacket& recvPacket);
void HandleGMTicketGetTicketOpcode(WorldPacket& recvPacket);
void HandleGMTicketSystemStatusOpcode(WorldPacket& recvPacket);
void SendGMTicketGetTicket(uint32 status, char const* text, GM_Ticket *ticket = NULL);
void SendGMTicketResponse(GM_Ticket *ticket);
void HandleGMSurveySubmit(WorldPacket& recvPacket);
void HandleReportLag(WorldPacket& recvPacket);
void HandleGMResponseResolve(WorldPacket& recvPacket);
+278 -120
View File
@@ -24,35 +24,194 @@
#include "WorldPacket.h"
#include "WorldSession.h"
TicketMgr::TicketMgr()
inline float GetAge(uint64 t) { return float(time(NULL) - t) / DAY; }
///////////////////////////////////////////////////////////////////////////////////////////////////
// GM ticket
GmTicket::GmTicket() { }
GmTicket::GmTicket(Player* player, WorldPacket& recv_data) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED)
{
m_GMticketid = 0; // this is initialized in LoadGMTickets() but it's best to be safe
m_GMSurveyID = 0;
m_openTickets = 0;
lastChange = time(NULL);
status = true;
_id = sTicketMgr->GenerateTicketId();
_playerName = player->GetName();
_playerGuid = player->GetGUID();
uint32 mapId;
recv_data >> mapId;
_mapId = mapId;
recv_data >> _posX;
recv_data >> _posY;
recv_data >> _posZ;
recv_data >> _message;
uint32 unk1;
recv_data >> unk1; // not sure what this is... replyTo?
uint8 needResponse;
recv_data >> needResponse; // always 1/0 -- not sure what retail does with this
}
uint64 TicketMgr::GenerateGMTicketId()
GmTicket::~GmTicket() { }
bool GmTicket::LoadFromDB(Field* fields)
{
return ++m_GMticketid;
uint8 index = 0;
_id = fields[ index].GetUInt32();
_playerGuid = MAKE_NEW_GUID(fields[++index].GetUInt32(), 0, HIGHGUID_PLAYER);
_playerName = fields[++index].GetString();
_message = fields[++index].GetString();
_createTime = fields[++index].GetUInt32();
_mapId = fields[++index].GetUInt16();
_posX = fields[++index].GetFloat();
_posY = fields[++index].GetFloat();
_posZ = fields[++index].GetFloat();
_lastModifiedTime = fields[++index].GetUInt32();
_closedBy = fields[++index].GetInt32();
_assignedTo = MAKE_NEW_GUID(fields[++index].GetUInt32(), 0, HIGHGUID_PLAYER);
_comment = fields[++index].GetString();
_completed = fields[++index].GetBool();
_escalatedStatus = GMTicketEscalationStatus(fields[++index].GetUInt8());
_viewed = fields[++index].GetBool();
return true;
}
void TicketMgr::LoadGMTickets()
void GmTicket::SaveToDB(SQLTransaction& trans) const
{
uint8 index = 0;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_GM_TICKET);
stmt->setUInt32( index, _id);
stmt->setUInt32(++index, GUID_LOPART(_playerGuid));
stmt->setString(++index, _playerName);
stmt->setString(++index, _message);
stmt->setUInt32(++index, uint32(_createTime));
stmt->setUInt16(++index, _mapId);
stmt->setFloat (++index, _posX);
stmt->setFloat (++index, _posY);
stmt->setFloat (++index, _posZ);
stmt->setUInt32(++index, uint32(_lastModifiedTime));
stmt->setInt32 (++index, GUID_LOPART(_closedBy));
stmt->setUInt32(++index, GUID_LOPART(_assignedTo));
stmt->setString(++index, _comment);
stmt->setBool (++index, _completed);
stmt->setUInt8 (++index, uint8(_escalatedStatus));
stmt->setBool (++index, _viewed);
CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
void GmTicket::DeleteFromDB(SQLTransaction& trans)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GM_TICKET);
stmt->setUInt32(0, _id);
CharacterDatabase.Execute(stmt);
}
void GmTicket::WritePacket(WorldPacket& data) const
{
data << GetAge(_lastModifiedTime);
if (GmTicket* ticket = sTicketMgr->GetOldestOpenTicket())
data << GetAge(ticket->GetLastModifiedTime());
else
data << float(0);
// I am not sure how blizzlike this is, and we don't really have a way to find out
data << GetAge(sTicketMgr->GetLastChange());
data << uint8(std::min(_escalatedStatus, TICKET_IN_ESCALATION_QUEUE)); // escalated data
data << uint8(_viewed ? GMTICKET_OPENEDBYGM_STATUS_OPENED : GMTICKET_OPENEDBYGM_STATUS_NOT_OPENED); // whether or not it has been viewed
}
void GmTicket::SendResponse(WorldSession* session) const
{
WorldPacket data(SMSG_GMRESPONSE_RECEIVED);
data << uint32(1); // unk? Zor says "hasActiveTicket"
data << uint32(0); // can-edit - always 1 or 0, not flags
data << _message.c_str();
data << _response.c_str();
// 3 null strings
data << uint8(0);
data << uint8(0);
data << uint8(0);
session->SendPacket(&data);
}
std::string GmTicket::FormatMessageString(ChatHandler& handler, bool detailed) const
{
time_t curTime = time(NULL);
std::stringstream ss;
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTGUID, _id);
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTNAME, _playerName.c_str());
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(curTime - _createTime, true, false)).c_str());
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(curTime - _lastModifiedTime, true, false)).c_str());
std::string name;
if (sObjectMgr->GetPlayerNameByGUID(_assignedTo, name))
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, name.c_str());
if (detailed)
{
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTMESSAGE, _message.c_str());
if (!_comment.empty())
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTCOMMENT, _comment.c_str());
}
return ss.str();
}
std::string GmTicket::FormatMessageString(ChatHandler& handler, const char* szClosedName, const char* szAssignedToName, const char* szUnassignedName, const char* szDeletedName) const
{
std::stringstream ss;
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTGUID, _id);
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTNAME, _playerName.c_str());
if (szClosedName)
ss << handler.PGetParseString(LANG_COMMAND_TICKETCLOSED, szClosedName);
if (szAssignedToName)
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, szAssignedToName);
if (szUnassignedName)
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTUNASSIGNED, szUnassignedName);
if (szDeletedName)
ss << handler.PGetParseString(LANG_COMMAND_TICKETDELETED, szDeletedName);
return ss.str();
}
void GmTicket::SetUnassigned()
{
_assignedTo = 0;
switch (_escalatedStatus)
{
case TICKET_ASSIGNED: _escalatedStatus = TICKET_UNASSIGNED; break;
case TICKET_ESCALATED_ASSIGNED: _escalatedStatus = TICKET_IN_ESCALATION_QUEUE; break;
case TICKET_UNASSIGNED:
case TICKET_IN_ESCALATION_QUEUE:
default:
break;
}
}
void GmTicket::TeleportTo(Player* player) const
{
player->TeleportTo(_mapId, _posX, _posY, _posZ, 1, 0);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Ticket manager
TicketMgr::TicketMgr() : _lastTicketId(0), _lastSurveyId(0), _openTicketCount(0), _lastChange(time(NULL)), _status(true) { }
void TicketMgr::LoadTickets()
{
uint32 oldMSTime = getMSTime();
if (!m_GMTicketList.empty())
for (GmTicketList::const_iterator itr = m_GMTicketList.begin(); itr != m_GMTicketList.end(); ++itr)
delete *itr;
if (!_ticketList.empty())
for (GmTicketList::const_iterator itr = _ticketList.begin(); itr != _ticketList.end(); ++itr)
if (itr->second)
delete itr->second;
_ticketList.clear();
m_GMTicketList.clear();
m_GMticketid = 0;
m_openTickets = 0;
QueryResult result = CharacterDatabase.Query("SELECT guid, playerGuid, name, message, createtime, map, posX, posY, posZ, timestamp, closed,"
"assignedto, comment, completed, escalated, viewed FROM gm_tickets");
_lastTicketId = 0;
_openTicketCount = 0;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_GM_TICKETS);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (!result)
{
sLog->outString(">> Loaded 0 GM tickets. DB table `gm_tickets` is empty!");
@@ -61,131 +220,130 @@ void TicketMgr::LoadGMTickets()
}
uint32 count = 0;
do
{
Field *fields = result->Fetch();
GM_Ticket *ticket = new GM_Ticket;
ticket->guid = fields[0].GetUInt32();
ticket->playerGuid = fields[1].GetUInt32();
ticket->name = fields[2].GetString();
ticket->message = fields[3].GetString();
ticket->createtime = fields[4].GetUInt32();
ticket->map = fields[5].GetUInt32();
ticket->pos_x = fields[6].GetFloat();
ticket->pos_y = fields[7].GetFloat();
ticket->pos_z = fields[8].GetFloat();
ticket->timestamp = fields[9].GetUInt32();
ticket->closed = fields[10].GetInt32();
if (ticket->closed == 0)
m_openTickets++;
Field* fields = result->Fetch();
GmTicket* ticket = new GmTicket();
if (!ticket->LoadFromDB(fields))
{
delete ticket;
continue;
}
if (!ticket->IsClosed())
++_openTicketCount;
ticket->assignedToGM = fields[11].GetUInt64();
ticket->comment = fields[12].GetString();
ticket->completed = fields[13].GetBool();
ticket->escalated = fields[14].GetUInt8();
ticket->viewed = fields[15].GetBool();
// Update max ticket id if necessary
uint32 id = ticket->GetId();
if (_lastTicketId < id)
_lastTicketId = id;
_ticketList[id] = ticket;
++count;
m_GMTicketList.push_back(ticket);
} while (result->NextRow());
result = CharacterDatabase.Query("SELECT MAX(guid) from gm_tickets");
if (result)
{
Field *fields = result->Fetch();
m_GMticketid = fields[0].GetUInt64();
}
sLog->outString(">> Loaded %u GM tickets in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
sLog->outString();
}
void TicketMgr::LoadGMSurveys()
void TicketMgr::LoadSurveys()
{
uint32 oldMSTime = getMSTime();
// we don't actually load anything into memory here as there's no reason to
QueryResult result = CharacterDatabase.Query("SELECT MAX(surveyid) FROM gm_surveys");
if (result)
{
Field *fields = result->Fetch();
m_GMSurveyID = fields[0].GetUInt32();
}
else
m_GMSurveyID = 0;
_lastSurveyId = 0;
uint32 oldMSTime = getMSTime();
if (QueryResult result = CharacterDatabase.Query("SELECT MAX(surveyId) FROM gm_surveys"))
_lastSurveyId = (*result)[0].GetUInt32();
sLog->outString(">> Loaded GM Survey count from database in %u ms", GetMSTimeDiffToNow(oldMSTime));
sLog->outString();
}
void TicketMgr::AddOrUpdateGMTicket(GM_Ticket &ticket, bool create)
void TicketMgr::AddTicket(GmTicket* ticket)
{
if (create)
_ticketList[ticket->GetId()] = ticket;
if (!ticket->IsClosed())
++_openTicketCount;
}
void TicketMgr::CloseTicket(uint32 ticketId, int64 source)
{
if (GmTicket* ticket = GetTicket(ticketId))
{
m_GMTicketList.push_back(&ticket);
if (ticket.closed == 0)
m_openTickets++;
SQLTransaction trans = SQLTransaction(NULL);
ticket->SetClosedBy(source);
if (source)
--_openTicketCount;
ticket->SaveToDB(trans);
}
}
void TicketMgr::RemoveTicket(uint32 ticketId)
{
if (GmTicket* ticket = GetTicket(ticketId))
{
SQLTransaction trans = SQLTransaction(NULL);
ticket->DeleteFromDB(trans);
_ticketList.erase(ticketId);
}
}
void TicketMgr::ShowList(ChatHandler& handler, bool onlineOnly) const
{
handler.SendSysMessage(onlineOnly ? LANG_COMMAND_TICKETSHOWONLINELIST : LANG_COMMAND_TICKETSHOWLIST);
for (GmTicketList::const_iterator itr = _ticketList.begin(); itr != _ticketList.end(); ++itr)
if (!itr->second->IsClosed() && !itr->second->IsCompleted())
if (!onlineOnly || itr->second->GetPlayer())
handler.SendSysMessage(itr->second->FormatMessageString(handler).c_str());
}
void TicketMgr::ShowClosedList(ChatHandler& handler) const
{
handler.SendSysMessage(LANG_COMMAND_TICKETSHOWCLOSEDLIST);
for (GmTicketList::const_iterator itr = _ticketList.begin(); itr != _ticketList.end(); ++itr)
if (itr->second->IsClosed())
handler.SendSysMessage(itr->second->FormatMessageString(handler).c_str());
}
void TicketMgr::ShowEscalatedList(ChatHandler& handler) const
{
handler.SendSysMessage(LANG_COMMAND_TICKETSHOWESCALATEDLIST);
for (GmTicketList::const_iterator itr = _ticketList.begin(); itr != _ticketList.end(); ++itr)
if (!itr->second->IsClosed() && itr->second->GetEscalatedStatus() == TICKET_IN_ESCALATION_QUEUE)
handler.SendSysMessage(itr->second->FormatMessageString(handler).c_str());
}
void TicketMgr::SendTicket(WorldSession* session, GmTicket* ticket) const
{
uint32 status = GMTICKET_STATUS_DEFAULT;
std::string message;
if (ticket)
{
message = ticket->GetMessage();
status = GMTICKET_STATUS_HASTEXT;
}
_AddOrUpdateGMTicket(ticket);
}
WorldPacket data(SMSG_GMTICKET_GETTICKET, (4 + 4 + (ticket ? message.length() + 1 + 4 + 4 + 4 + 1 + 1 : 0)));
data << uint32(status); // standard 0x0A, 0x06 if text present
data << uint32(1); // g_HasActiveGMTicket -- not a flag
void TicketMgr::_AddOrUpdateGMTicket(GM_Ticket &ticket)
{
std::string msg(ticket.message), name(ticket.name), comment(ticket.comment);
CharacterDatabase.escape_string(msg);
CharacterDatabase.escape_string(name);
CharacterDatabase.escape_string(comment);
std::ostringstream ss;
ss << "REPLACE INTO gm_tickets (guid, playerGuid, name, message, createtime, map, posX, posY, posZ, timestamp, closed, assignedto, comment, completed, escalated, viewed) VALUES (";
ss << ticket.guid << ", ";
ss << ticket.playerGuid << ", '";
ss << name << "', '";
ss << msg << "', " ;
ss << ticket.createtime << ", ";
ss << ticket.map << ", ";
ss << ticket.pos_x << ", ";
ss << ticket.pos_y << ", ";
ss << ticket.pos_z << ", ";
ss << ticket.timestamp << ", ";
ss << ticket.closed << ", ";
ss << ticket.assignedToGM << ", '";
ss << comment << "', ";
ss << (ticket.completed ? 1 : 0) << ", ";
ss << uint32(ticket.escalated) << ", ";
ss << (ticket.viewed ? 1 : 0) << ");";
if (ticket)
{
data << message.c_str(); // ticket text
data << uint8(0x7); // ticket category; why is this hardcoded? does it make a diff re: client?
SQLTransaction trans = CharacterDatabase.BeginTransaction();
trans->Append(ss.str().c_str());
CharacterDatabase.CommitTransaction(trans);
}
void TicketMgr::RemoveGMTicket(GM_Ticket *ticket, int64 source, bool permanently)
{
for (GmTicketList::iterator i = m_GMTicketList.begin(); i != m_GMTicketList.end(); ++i)
if ((*i)->guid == ticket->guid)
// we've got the easy stuff done by now.
// Now we need to go through the client logic for displaying various levels of ticket load
if (ticket)
ticket->WritePacket(data);
else
{
if (permanently)
{
CharacterDatabase.PExecute("DELETE FROM gm_tickets WHERE guid = '%u'", ticket->guid);
i = m_GMTicketList.erase(i);
ticket = NULL;
return;
}
(*i)->closed = source;
if (source != 0)
m_openTickets--;
_AddOrUpdateGMTicket(*(*i));
// we can't actually get any numbers here...
data << float(0);
data << float(0);
data << float(1);
data << uint8(0);
data << uint8(0);
}
}
void TicketMgr::RemoveGMTicket(uint64 ticketGuid, int64 source, bool permanently)
{
GM_Ticket *ticket = GetGMTicket(ticketGuid);
ASSERT(ticket); // hmm
RemoveGMTicket(ticket, source, permanently);
}
session->SendPacket(&data);
}
+125 -57
View File
@@ -24,6 +24,7 @@
#include "DatabaseEnv.h"
#include "SQLStorage.h"
#include "SQLStorageImpl.h"
#include "Chat.h"
#include "World.h"
// from blizzard lua
@@ -76,27 +77,89 @@ enum LagReportType
LAG_REPORT_TYPE_SPELL = 6
};
struct GM_Ticket
class GmTicket
{
uint64 guid;
uint64 playerGuid;
std::string name;
float pos_x;
float pos_y;
float pos_z;
uint32 map;
std::string message;
uint64 createtime;
uint64 timestamp;
int64 closed; // 0 = Open, -1 = Console, playerGuid = player abandoned ticket, other = GM who closed it.
uint64 assignedToGM;
std::string comment;
bool completed;
uint8 escalated;
bool viewed;
std::string response;
public:
GmTicket();
explicit GmTicket(Player* player, WorldPacket& recv_data);
~GmTicket();
bool IsClosed() const { return _closedBy; }
bool IsCompleted() const { return _completed; }
bool IsFromPlayer(const uint64& guid) { return guid == _playerGuid; }
bool IsAssigned() const { return _assignedTo != 0; }
bool IsAssignedTo(const uint64& guid) const { return guid == _assignedTo; }
bool IsAssignedNotTo(const uint64& guid) const { return IsAssigned() && !IsAssignedTo(guid); }
uint32 GetId() const { return _id; }
Player* GetPlayer() const { return sObjectMgr->GetPlayer(_playerGuid); }
std::string GetPlayerName() const { return _playerName; }
std::string GetMessage() const { return _message; }
Player* GetAssignedPlayer() const { return sObjectMgr->GetPlayer(_assignedTo); }
const uint64& GetAssignedToGUID() const { return _assignedTo; }
const char* GetAssignedToName() const
{
std::string name;
if (_assignedTo)
if (sObjectMgr->GetPlayerNameByGUID(_assignedTo, name))
return name.c_str();
return NULL;
}
const uint64& GetLastModifiedTime() const { return _lastModifiedTime; }
GMTicketEscalationStatus GetEscalatedStatus() const { return _escalatedStatus; }
void SetEscalatedStatus(GMTicketEscalationStatus escalatedStatus) { _escalatedStatus = escalatedStatus; }
void SetAssignedTo(const uint64& guid, bool isAdmin)
{
_assignedTo = guid;
if (isAdmin && _escalatedStatus == TICKET_IN_ESCALATION_QUEUE)
_escalatedStatus = TICKET_ESCALATED_ASSIGNED;
else if (_escalatedStatus == TICKET_UNASSIGNED)
_escalatedStatus = TICKET_ASSIGNED;
}
void SetClosedBy(const int64& value) { _closedBy = value; }
void SetMessage(const std::string& message)
{
_message = message;
_lastModifiedTime = uint64(time(NULL));
}
void SetComment(const std::string& comment) { _comment = comment; }
void SetViewed() { _viewed = true; }
void SetUnassigned();
void AppendResponse(const std::string& response) { _response += response; }
bool LoadFromDB(Field* fields);
void SaveToDB(SQLTransaction& trans) const;
void DeleteFromDB(SQLTransaction& trans);
void WritePacket(WorldPacket& data) const;
void SendResponse(WorldSession* session) const;
void TeleportTo(Player* player) const;
std::string FormatMessageString(ChatHandler& handler, bool detailed = false) const;
std::string FormatMessageString(ChatHandler& handler, const char* szClosedName, const char* szAssignedToName, const char* szUnassignedName, const char* szDeletedName) const;
private:
uint32 _id;
uint64 _playerGuid;
std::string _playerName;
float _posX;
float _posY;
float _posZ;
uint16 _mapId;
std::string _message;
uint64 _createTime;
uint64 _lastModifiedTime;
int64 _closedBy; // 0 = Open, -1 = Console, playerGuid = player abandoned ticket, other = GM who closed it.
uint64 _assignedTo;
std::string _comment;
bool _completed;
GMTicketEscalationStatus _escalatedStatus;
bool _viewed;
std::string _response;
};
typedef std::list<GM_Ticket*> GmTicketList;
typedef std::map<uint32, GmTicket*> GmTicketList;
class TicketMgr
{
@@ -104,63 +167,68 @@ class TicketMgr
friend class ACE_Singleton<TicketMgr, ACE_Null_Mutex>;
public:
void LoadGMTickets();
void LoadGMSurveys();
void LoadTickets();
void LoadSurveys();
GM_Ticket *GetGMTicket(uint64 ticketGuid)
GmTicket* GetTicket(uint32 ticketId)
{
for (GmTicketList::const_iterator i = m_GMTicketList.begin(); i != m_GMTicketList.end(); ++i)
if ((*i) && (*i)->guid == ticketGuid)
return (*i);
GmTicketList::iterator itr = _ticketList.find(ticketId);
if (itr != _ticketList.end())
return itr->second;
return NULL;
}
GM_Ticket *GetGMTicketByPlayer(uint64 playerGuid)
GmTicket* GetTicketByPlayer(const uint64& playerGuid)
{
for (GmTicketList::const_iterator i = m_GMTicketList.begin(); i != m_GMTicketList.end(); ++i)
if ((*i) && (*i)->playerGuid == playerGuid && (*i)->closed == 0)
return (*i);
for (GmTicketList::const_iterator itr = _ticketList.begin(); itr != _ticketList.end(); ++itr)
if (itr->second && itr->second->IsFromPlayer(playerGuid) && !itr->second->IsClosed())
return itr->second;
return NULL;
}
void AddOrUpdateGMTicket(GM_Ticket &ticket, bool create = false);
void _AddOrUpdateGMTicket(GM_Ticket &ticket);
void RemoveGMTicket(uint64 ticketGuid, int64 source = -1, bool permanently = false);
void RemoveGMTicket(GM_Ticket *ticket, int64 source = -1, bool permanently = false);
uint64 GenerateGMTicketId();
bool GetStatus() const { return status; }
void SetStatus(bool newStatus) { status = newStatus; }
uint64 GetOpenTicketCount() const { return m_openTickets; }
uint64 GetNextSurveyID() { return ++m_GMSurveyID; }
void Initialize()
GmTicket* GetOldestOpenTicket()
{
SetStatus(sWorld->getBoolConfig(CONFIG_ALLOW_TICKETS));
}
GM_Ticket *GetOldestOpenGMTicket()
{
for (GmTicketList::const_iterator i = m_GMTicketList.begin(); i != m_GMTicketList.end(); ++i)
if ((*i) && (*i)->closed == 0 && !(*i)->completed)
return (*i);
for (GmTicketList::const_iterator itr = _ticketList.begin(); itr != _ticketList.end(); ++itr)
if (itr->second && !itr->second->IsClosed() && !itr->second->IsCompleted())
return itr->second;
return NULL;
}
time_t GetLastChange() const { return lastChange; }
void UpdateLastChange() { lastChange = time(NULL); }
void AddTicket(GmTicket* ticket);
void CloseTicket(uint32 ticketId, int64 source = -1);
void RemoveTicket(uint32 ticketId);
GmTicketList m_GMTicketList;
bool GetStatus() const { return _status; }
void SetStatus(bool status) { _status = status; }
uint64 GetLastChange() const { return _lastChange; }
void UpdateLastChange() { _lastChange = uint64(time(NULL)); }
uint32 GenerateTicketId() { return ++_lastTicketId; }
uint32 GetOpenTicketCount() const { return _openTicketCount; }
uint32 GetNextSurveyID() { return ++_lastSurveyId; }
void Initialize() { SetStatus(sWorld->getBoolConfig(CONFIG_ALLOW_TICKETS)); }
void ShowList(ChatHandler& handler, bool onlineOnly) const;
void ShowClosedList(ChatHandler& handler) const;
void ShowEscalatedList(ChatHandler& handler) const;
void SendTicket(WorldSession* session, GmTicket* ticket) const;
protected:
uint64 m_GMticketid;
uint64 m_GMSurveyID;
bool status;
uint64 m_openTickets;
uint32 m_gmCount;
time_t lastChange;
void _RemoveTicket(uint32 ticketId, int64 source = -1, bool permanently = false);
GmTicketList _ticketList;
bool _status;
uint32 _lastTicketId;
uint32 _lastSurveyId;
uint32 _openTicketCount;
uint64 _lastChange;
};
#define sTicketMgr ACE_Singleton<TicketMgr, ACE_Null_Mutex>::instance()
+2 -2
View File
@@ -1567,10 +1567,10 @@ void World::SetInitialWorldSettings()
sObjectMgr->LoadFactionChangeReputations();
sLog->outString("Loading GM tickets...");
sTicketMgr->LoadGMTickets();
sTicketMgr->LoadTickets();
sLog->outString("Loading GM surveys...");
sTicketMgr->LoadGMSurveys();
sTicketMgr->LoadSurveys();
sLog->outString("Loading client addons...");
sAddonMgr->LoadFromDB();