aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/characters_database.sql44
-rw-r--r--sql/updates/auth_char/2011_04_19_00_characters.sql41
-rwxr-xr-xsrc/server/game/Chat/Chat.cpp11
-rwxr-xr-xsrc/server/game/Chat/Chat.h4
-rwxr-xr-xsrc/server/game/Chat/Commands/TicketCommands.cpp478
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp4
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/TicketHandler.cpp236
-rwxr-xr-xsrc/server/game/Server/WorldSession.h3
-rwxr-xr-xsrc/server/game/Tickets/TicketMgr.cpp402
-rwxr-xr-xsrc/server/game/Tickets/TicketMgr.h182
-rwxr-xr-xsrc/server/game/World/World.cpp4
-rw-r--r--src/server/scripts/Commands/cs_go.cpp21
-rw-r--r--src/server/scripts/Commands/cs_reload.cpp2
-rwxr-xr-xsrc/server/shared/Database/Implementation/CharacterDatabase.cpp11
-rwxr-xr-xsrc/server/shared/Database/Implementation/CharacterDatabase.h9
15 files changed, 746 insertions, 706 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index 29fa888ed78..c9d1bd435c1 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -1335,11 +1335,11 @@ DROP TABLE IF EXISTS `gm_subsurveys`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `gm_subsurveys` (
- `surveyid` int(10) unsigned NOT NULL AUTO_INCREMENT,
- `subsurveyid` int(10) unsigned NOT NULL DEFAULT '0',
+ `surveyId` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `subsurveyId` int(10) unsigned NOT NULL DEFAULT '0',
`rank` int(10) unsigned NOT NULL DEFAULT '0',
`comment` text NOT NULL,
- PRIMARY KEY (`surveyid`,`subsurveyid`)
+ PRIMARY KEY (`surveyId`,`subsurveyId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System';
/*!40101 SET character_set_client = @saved_cs_client */;
@@ -1360,12 +1360,12 @@ DROP TABLE IF EXISTS `gm_surveys`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `gm_surveys` (
- `surveyid` int(10) unsigned NOT NULL AUTO_INCREMENT,
- `player` int(10) unsigned NOT NULL DEFAULT '0',
+ `surveyId` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `guid` int(10) unsigned NOT NULL DEFAULT '0',
`mainSurvey` int(10) unsigned NOT NULL DEFAULT '0',
- `overall_comment` longtext NOT NULL,
- `timestamp` int(10) unsigned NOT NULL DEFAULT '0',
- PRIMARY KEY (`surveyid`)
+ `overallComment` longtext NOT NULL,
+ `createTime` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`surveyId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System';
/*!40101 SET character_set_client = @saved_cs_client */;
@@ -1386,23 +1386,23 @@ DROP TABLE IF EXISTS `gm_tickets`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `gm_tickets` (
- `guid` int(10) unsigned NOT NULL AUTO_INCREMENT,
- `playerGuid` int(10) unsigned NOT NULL DEFAULT '0',
- `name` varchar(12) NOT NULL,
+ `ticketId` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `guid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier of ticket creator',
+ `name` varchar(12) NOT NULL COMMENT 'Name of ticket creator',
`message` text NOT NULL,
- `createtime` int(10) unsigned NOT NULL DEFAULT '0',
- `map` smallint(5) unsigned NOT NULL DEFAULT '0',
+ `createTime` int(10) unsigned NOT NULL DEFAULT '0',
+ `mapId` smallint(5) unsigned NOT NULL DEFAULT '0',
`posX` float NOT NULL DEFAULT '0',
`posY` float NOT NULL DEFAULT '0',
`posZ` float NOT NULL DEFAULT '0',
- `timestamp` int(10) unsigned NOT NULL DEFAULT '0',
- `closed` int(11) NOT NULL DEFAULT '0',
- `assignedto` int(10) unsigned NOT NULL DEFAULT '0',
+ `lastModifiedTime` int(10) unsigned NOT NULL DEFAULT '0',
+ `closedBy` int(10) NOT NULL DEFAULT '0',
+ `assignedTo` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'GUID of admin to whom ticket is assigned',
`comment` text NOT NULL,
`completed` tinyint(3) unsigned NOT NULL DEFAULT '0',
`escalated` tinyint(3) unsigned NOT NULL DEFAULT '0',
`viewed` tinyint(3) unsigned NOT NULL DEFAULT '0',
- PRIMARY KEY (`guid`)
+ PRIMARY KEY (`ticketId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System';
/*!40101 SET character_set_client = @saved_cs_client */;
@@ -1898,14 +1898,14 @@ DROP TABLE IF EXISTS `lag_reports`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `lag_reports` (
- `report_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
- `player` int(10) unsigned NOT NULL DEFAULT '0',
- `lag_type` tinyint(3) unsigned NOT NULL DEFAULT '0',
- `map` smallint(5) unsigned NOT NULL DEFAULT '0',
+ `reportId` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `guid` int(10) unsigned NOT NULL DEFAULT '0',
+ `lagType` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `mapId` smallint(5) unsigned NOT NULL DEFAULT '0',
`posX` float NOT NULL DEFAULT '0',
`posY` float NOT NULL DEFAULT '0',
`posZ` float NOT NULL DEFAULT '0',
- PRIMARY KEY (`report_id`)
+ PRIMARY KEY (`reportId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System';
/*!40101 SET character_set_client = @saved_cs_client */;
diff --git a/sql/updates/auth_char/2011_04_19_00_characters.sql b/sql/updates/auth_char/2011_04_19_00_characters.sql
new file mode 100644
index 00000000000..96536d67a03
--- /dev/null
+++ b/sql/updates/auth_char/2011_04_19_00_characters.sql
@@ -0,0 +1,41 @@
+ALTER TABLE gm_subsurveys
+ CHANGE `surveyid` `surveyId` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ CHANGE `subsurveyid` `subsurveyId` int(10) unsigned NOT NULL DEFAULT '0';
+
+ALTER TABLE gm_subsurveys
+ DROP PRIMARY KEY,
+ ADD PRIMARY KEY(`surveyId`,`subsurveyId`);
+
+ALTER TABLE gm_surveys
+ CHANGE `surveyid` `surveyId` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ CHANGE `player` `guid` int(10) unsigned NOT NULL DEFAULT '0',
+ CHANGE `overall_comment` `overallComment` longtext NOT NULL,
+ CHANGE `timestamp` `createTime` int(10) unsigned NOT NULL DEFAULT '0';
+
+ALTER TABLE gm_surveys
+ DROP PRIMARY KEY,
+ ADD PRIMARY KEY (`surveyId`);
+
+ALTER TABLE gm_tickets
+ CHANGE `guid` `ticketId` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ CHANGE `playerGuid` `guid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier of ticket creator',
+ CHANGE `name` `name` varchar(12) NOT NULL COMMENT 'Name of ticket creator',
+ CHANGE `createtime` `createTime` int(10) unsigned NOT NULL DEFAULT '0',
+ CHANGE `map` `mapId` smallint(5) unsigned NOT NULL DEFAULT '0',
+ CHANGE `timestamp` `lastModifiedTime` int(10) unsigned NOT NULL DEFAULT '0',
+ CHANGE `closed` `closedBy` int(10) NOT NULL DEFAULT '0',
+ CHANGE `assignedto` `assignedTo` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'GUID of admin to whom ticket is assigned';
+
+ALTER TABLE gm_tickets
+ DROP PRIMARY KEY,
+ ADD PRIMARY KEY (`ticketId`);
+
+ALTER TABLE lag_reports
+ CHANGE `report_id` `reportId` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ CHANGE `player` `guid` int(10) unsigned NOT NULL DEFAULT '0',
+ CHANGE `lag_type` `lagType` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ CHANGE `map` `mapId` smallint(5) unsigned NOT NULL DEFAULT '0';
+
+ALTER TABLE lag_reports
+ DROP PRIMARY KEY,
+ ADD PRIMARY KEY (`reportId`);
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index b22e27a7693..21b32c0a24c 100755
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -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);
diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h
index a75d1af9cc1..18b3fa2efbc 100755
--- a/src/server/game/Chat/Chat.h
+++ b/src/server/game/Chat/Chat.h
@@ -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
diff --git a/src/server/game/Chat/Commands/TicketCommands.cpp b/src/server/game/Chat/Commands/TicketCommands.cpp
index d85a3f2763e..88396349a20 100755
--- a/src/server/game/Chat/Commands/TicketCommands.cpp
+++ b/src/server/game/Chat/Commands/TicketCommands.cpp
@@ -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());
+ SQLTransaction trans = SQLTransaction(NULL);
+ ticket->SetComment(comment);
+ ticket->SaveToDB(trans);
+ sTicketMgr->UpdateLastChange();
- if (sObjectMgr->GetPlayerNameByGUID(ticket->assignedToGM, gmname))
- ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str());
+ std::string msg = ticket->FormatMessageString(*this, NULL, ticket->GetAssignedToName(), NULL, NULL);
+ msg += PGetParseString(LANG_COMMAND_TICKETLISTADDCOMMENT, player->GetName(), comment);
+ SendGlobalGMSysMessage(msg.c_str());
- ss << PGetParseString(LANG_COMMAND_TICKETLISTADDCOMMENT, cplr->GetName(), ticket->comment.c_str());
- SendGlobalGMSysMessage(ss.str().c_str());
- sTicketMgr->UpdateLastChange();
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;
}
-bool ChatHandler::HandleGMTicketResponseAppendCommand(const char* args)
+inline bool ChatHandler::_HandleGMTicketResponseAppendCommand(const char* args, bool newLine)
{
if (!*args)
return false;
- char* tguid = strtok((char*)args, " ");
- uint64 ticketGuid = atoi(tguid);
- char* response = strtok(NULL, "\n");
+ char* sTicketId = strtok((char*)args, " ");
+ uint32 ticketId = atoi(sTicketId);
+ 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)
+ GmTicket* ticket = sTicketMgr->GetTicket(ticketId);
+ if (!ticket || !ticket->IsClosed())
{
PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
-
- if (ticket->assignedToGM != 0 && ticket->assignedToGM != cplr->GetGUID())
+ // Cannot add response to 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::stringstream ss;
- ss << ticket->response;
- ss << response;
- ticket->response = ss.str();
- sTicketMgr->AddOrUpdateGMTicket(*ticket);
+ SQLTransaction trans = SQLTransaction(NULL);
+ ticket->AppendResponse(response);
+ if (newLine)
+ ticket->AppendResponse("\n");
+ ticket->SaveToDB(trans);
+
return true;
}
-bool ChatHandler::HandleGMTicketResponseAppendLnCommand(const char* args)
+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;
- }
+ return _HandleGMTicketResponseAppendCommand(args, false);
+}
- std::stringstream ss;
- ss << ticket->response;
- ss << response;
- ss << "\n";
- ticket->response = ss.str();
- sTicketMgr->AddOrUpdateGMTicket(*ticket);
- return true;
+bool ChatHandler::HandleGMTicketResponseAppendLnCommand(const char* args)
+{
+ return _HandleGMTicketResponseAppendCommand(args, true);
}
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 37b3fffe916..e130a570359 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -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);
diff --git a/src/server/game/Server/Protocol/Handlers/TicketHandler.cpp b/src/server/game/Server/Protocol/Handlers/TicketHandler.cpp
index e96cfa2dbbd..ad883394270 100755
--- a/src/server/game/Server/Protocol/Handlers/TicketHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/TicketHandler.cpp
@@ -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();
- uint32 map, unk1;
- uint8 needResponse; // ignored
- float x, y, z;
- std::string ticketText, ticketText2;
+ sWorld->SendGMText(LANG_COMMAND_TICKETNEW, GetPlayer()->GetName(), ticket->GetId());
- 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);
+ response = GMTICKET_RESPONSE_SUCCESS;
+ }
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);
- ticket->message = message;
- ticket->timestamp = time(NULL);
+ sWorld->SendGMText(LANG_COMMAND_TICKETUPDATED, GetPlayer()->GetName(), ticket->GetId());
- sTicketMgr->AddOrUpdateGMTicket(*ticket);
+ response = GMTICKET_RESPONSE_SUCCESS;
+ }
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);
}
}
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 82e8aa20919..9cf9f4f3d37 100755
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -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);
diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp
index 9452c920c3e..ecd9f7c6caf 100755
--- a/src/server/game/Tickets/TicketMgr.cpp
+++ b/src/server/game/Tickets/TicketMgr.cpp
@@ -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
{
- uint32 oldMSTime = getMSTime();
+ 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;
+ }
+}
- if (!m_GMTicketList.empty())
- for (GmTicketList::const_iterator itr = m_GMTicketList.begin(); itr != m_GMTicketList.end(); ++itr)
- delete *itr;
+void GmTicket::TeleportTo(Player* player) const
+{
+ player->TeleportTo(_mapId, _posX, _posY, _posZ, 1, 0);
+}
- m_GMTicketList.clear();
- m_GMticketid = 0;
- m_openTickets = 0;
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Ticket manager
+TicketMgr::TicketMgr() : _lastTicketId(0), _lastSurveyId(0), _openTicketCount(0), _lastChange(time(NULL)), _status(true) { }
- QueryResult result = CharacterDatabase.Query("SELECT guid, playerGuid, name, message, createtime, map, posX, posY, posZ, timestamp, closed,"
- "assignedto, comment, completed, escalated, viewed FROM gm_tickets");
+void TicketMgr::LoadTickets()
+{
+ uint32 oldMSTime = getMSTime();
+
+ if (!_ticketList.empty())
+ for (GmTicketList::const_iterator itr = _ticketList.begin(); itr != _ticketList.end(); ++itr)
+ if (itr->second)
+ delete itr->second;
+ _ticketList.clear();
+ _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++;
-
- 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();
- ++count;
-
- m_GMTicketList.push_back(ticket);
- } while (result->NextRow());
+ Field* fields = result->Fetch();
+ GmTicket* ticket = new GmTicket();
+ if (!ticket->LoadFromDB(fields))
+ {
+ delete ticket;
+ continue;
+ }
+ if (!ticket->IsClosed())
+ ++_openTicketCount;
- result = CharacterDatabase.Query("SELECT MAX(guid) from gm_tickets");
+ // Update max ticket id if necessary
+ uint32 id = ticket->GetId();
+ if (_lastTicketId < id)
+ _lastTicketId = id;
- if (result)
- {
- Field *fields = result->Fetch();
- m_GMticketid = fields[0].GetUInt64();
- }
+ _ticketList[id] = ticket;
+ ++count;
+ } while (result->NextRow());
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);
}
+}
- _AddOrUpdateGMTicket(ticket);
-}
-
-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) << ");";
-
- 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)
- {
- 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));
- }
+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::RemoveGMTicket(uint64 ticketGuid, int64 source, bool permanently)
+void TicketMgr::ShowClosedList(ChatHandler& handler) const
{
- GM_Ticket *ticket = GetGMTicket(ticketGuid);
- ASSERT(ticket); // hmm
- RemoveGMTicket(ticket, source, permanently);
+ 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;
+ }
+
+ 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
+
+ if (ticket)
+ {
+ data << message.c_str(); // 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)
+ ticket->WritePacket(data);
+ else
+ {
+ // we can't actually get any numbers here...
+ data << float(0);
+ data << float(0);
+ data << float(1);
+ data << uint8(0);
+ data << uint8(0);
+ }
+ }
+ session->SendPacket(&data);
}
diff --git a/src/server/game/Tickets/TicketMgr.h b/src/server/game/Tickets/TicketMgr.h
index 69bfcd86844..9f222727510 100755
--- a/src/server/game/Tickets/TicketMgr.h
+++ b/src/server/game/Tickets/TicketMgr.h
@@ -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);
+
+ 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; }
- GmTicketList m_GMTicketList;
+ 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()
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index f0e10b8bd74..c5a9b63b423 100755
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -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();
diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp
index 3b38e1b07e4..b4ca8af6d92 100644
--- a/src/server/scripts/Commands/cs_go.cpp
+++ b/src/server/scripts/Commands/cs_go.cpp
@@ -564,30 +564,21 @@ public:
if (!*args)
return false;
- char *cstrticket_id = strtok((char*)args, " ");
-
- if (!cstrticket_id)
+ char *sTicketId = strtok((char*)args, " ");
+ if (!sTicketId)
return false;
- uint64 ticket_id = atoi(cstrticket_id);
- if (!ticket_id)
+ uint32 ticketId = atoi(sTicketId);
+ if (!ticketId)
return false;
- GM_Ticket *ticket = sTicketMgr->GetGMTicket(ticket_id);
+ GmTicket* ticket = sTicketMgr->GetTicket(ticketId);
if (!ticket)
{
handler->SendSysMessage(LANG_COMMAND_TICKETNOTEXIST);
return true;
}
- float x, y, z;
- int mapid;
-
- x = ticket->pos_x;
- y = ticket->pos_y;
- z = ticket->pos_z;
- mapid = ticket->map;
-
Player* _player = handler->GetSession()->GetPlayer();
if (_player->isInFlight())
{
@@ -597,7 +588,7 @@ public:
else
_player->SaveRecallPosition();
- _player->TeleportTo(mapid, x, y, z, 1, 0);
+ ticket->TeleportTo(_player);
return true;
}
};
diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp
index 9bd6de9f6be..a08befe24ba 100644
--- a/src/server/scripts/Commands/cs_reload.cpp
+++ b/src/server/scripts/Commands/cs_reload.cpp
@@ -166,7 +166,7 @@ public:
//reload commands
static bool HandleReloadGMTicketsCommand(ChatHandler* /*handler*/, const char* /*args*/)
{
- sTicketMgr->LoadGMTickets();
+ sTicketMgr->LoadTickets();
return true;
}
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index 78cc2a2ea9a..f2e9b431f7d 100755
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -323,4 +323,15 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_DEL_GO_RESPAWN_BY_INSTANCE, "DELETE FROM gameobject_respawn WHERE instanceId = ?", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_DEL_EXPIRED_GO_RESPAWNS, "DELETE FROM gameobject_respawn WHERE respawnTime <= UNIX_TIMESTAMP(NOW())", CONNECTION_SYNCH)
PREPARE_STATEMENT(CHAR_DEL_NONEXISTENT_INSTANCE_GO_RESPAWNS, "DELETE FROM gameobject_respawn WHERE instanceId > 0 AND instanceId NOT IN (SELECT instanceId FROM instance)", CONNECTION_SYNCH)
+
+ // GM Tickets
+ PREPARE_STATEMENT(CHAR_LOAD_GM_TICKETS, "SELECT ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed FROM gm_tickets", CONNECTION_SYNCH)
+ PREPARE_STATEMENT(CHAR_ADD_GM_TICKET, "REPLACE INTO gm_tickets (ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC)
+ PREPARE_STATEMENT(CHAR_DEL_GM_TICKET, "DELETE FROM gm_tickets WHERE ticketId = ?", CONNECTION_ASYNC)
+ PREPARE_STATEMENT(CHAR_DEL_PLAYER_GM_TICKETS, "DELETE FROM gm_tickets WHERE guid = ?", CONNECTION_ASYNC)
+
+ // GM Survey/subsurvey/lag report
+ PREPARE_STATEMENT(CHAR_ADD_GM_SURVEY, "INSERT INTO gm_surveys (guid, surveyId, mainSurvey, overallComment, createTime) VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(NOW()))", CONNECTION_ASYNC)
+ PREPARE_STATEMENT(CHAR_ADD_GM_SUBSURVEY, "INSERT INTO gm_subsurveys (surveyId, subsurveyId, rank, comment) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC)
+ PREPARE_STATEMENT(CHAR_ADD_LAG_REPORT, "INSERT INTO lag_reports (guid, lagType, mapId, posX, posY, posZ) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC)
}
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index fec9791e701..91290bbd4a0 100755
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -274,6 +274,15 @@ enum CharacterDatabaseStatements
CHAR_DEL_EXPIRED_GO_RESPAWNS,
CHAR_DEL_NONEXISTENT_INSTANCE_GO_RESPAWNS,
+ CHAR_LOAD_GM_TICKETS,
+ CHAR_ADD_GM_TICKET,
+ CHAR_DEL_GM_TICKET,
+ CHAR_DEL_PLAYER_GM_TICKETS,
+
+ CHAR_ADD_GM_SURVEY,
+ CHAR_ADD_GM_SUBSURVEY,
+ CHAR_ADD_LAG_REPORT,
+
MAX_CHARACTERDATABASE_STATEMENTS,
};