Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
TicketMgr.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Chat.h"
7#include "Common.h"
8#include "DatabaseEnv.h"
9#include "Language.h"
10#include "Log.h"
11#include "Opcodes.h"
12#include "Player.h"
13#include "TicketMgr.h"
14#include "World.h"
15#include "WorldPacket.h"
16#include "WorldSession.h"
17
18inline float GetAge(uint64 t) { return float(time(NULL) - t) / float(DAY); }
19
23
25{
26 for (GmTicketList::const_iterator itr = _gmTicketList.begin(); itr != _gmTicketList.end(); ++itr)
27 delete itr->second;
28
29 for (BugTicketList::const_iterator itr = _bugTicketList.begin(); itr != _bugTicketList.end(); ++itr)
30 delete itr->second;
31
32 for (SuggestTicketList::const_iterator itr = _suggestTicketList.begin(); itr != _suggestTicketList.end(); ++itr)
33 delete itr->second;
34}
35
41
43{
44 uint32 oldMSTime = getMSTime();
45
46 for (GmTicketList::const_iterator itr = _gmTicketList.begin(); itr != _gmTicketList.end(); ++itr)
47 delete itr->second;
48
49 _gmTicketList.clear();
50
53
54 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GM_TICKETS);
55 PreparedQueryResult result = CharacterDatabase.Query(stmt);
56 if (!result)
57 {
58 SF_LOG_INFO("server.loading", ">> Loaded 0 GM tickets. DB table `gm_ticket` is empty!");
59 return;
60 }
61
62 uint32 count = 0;
63 do
64 {
65 Field* fields = result->Fetch();
66 GmTicket* ticket = new GmTicket();
67 ticket->LoadFromDB(fields);
68
69 if (!ticket->IsClosed())
71
72 uint32 id = ticket->GetTicketId();
73 if (_lastGmTicketId < id)
74 _lastGmTicketId = id;
75
76 _gmTicketList[id] = ticket;
77 ++count;
78 } while (result->NextRow());
79
80 SF_LOG_INFO("server.loading", ">> Loaded %u GM tickets in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
81}
82
84{
85 uint32 oldMSTime = getMSTime();
86
87 for (BugTicketList::const_iterator itr = _bugTicketList.begin(); itr != _bugTicketList.end(); ++itr)
88 delete itr->second;
89
90 _bugTicketList.clear();
91
92 _lastBugId = 0;
94
95 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GM_BUGS);
96 PreparedQueryResult result = CharacterDatabase.Query(stmt);
97 if (!result)
98 {
99 SF_LOG_INFO("server.loading", ">> Loaded 0 ticket bugs. DB table `ticket_bug` is empty!");
100 return;
101 }
102
103 uint32 count = 0;
104 do
105 {
106 Field* fields = result->Fetch();
107 BugTicket* bug = new BugTicket();
108 bug->LoadFromDB(fields);
109
110 if (!bug->IsClosed())
112
113 uint32 id = bug->GetTicketId();
114 if (_lastBugId < id)
115 _lastBugId = id;
116
117 _bugTicketList[id] = bug;
118 ++count;
119 } while (result->NextRow());
120
121 SF_LOG_INFO("server.loading", ">> Loaded %u ticket bugs in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
122}
123
125{
126 uint32 oldMSTime = getMSTime();
127
128 for (SuggestTicketList::const_iterator itr = _suggestTicketList.begin(); itr != _suggestTicketList.end(); ++itr)
129 delete itr->second;
130
131 _suggestTicketList.clear();
132
133 _lastSuggestId = 0;
135
136 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GM_SUGGESTS);
137 PreparedQueryResult result = CharacterDatabase.Query(stmt);
138 if (!result)
139 {
140 SF_LOG_INFO("server.loading", ">> Loaded 0 ticket suggests. DB table `ticket_suggest` is empty!");
141 return;
142 }
143
144 uint32 count = 0;
145 do
146 {
147 Field* fields = result->Fetch();
148 SuggestTicket* suggest = new SuggestTicket();
149 suggest->LoadFromDB(fields);
150
151 if (!suggest->IsClosed())
153
154 uint32 id = suggest->GetTicketId();
155 if (_lastSuggestId < id)
156 _lastSuggestId = id;
157
158 _suggestTicketList[id] = suggest;
159 ++count;
160 } while (result->NextRow());
161
162 SF_LOG_INFO("server.loading", ">> Loaded %u ticket suggests in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
163}
164
166{
167 // we don't actually load anything into memory here as there's no reason to
168 _lastSurveyId = 0;
169
170 uint32 oldMSTime = getMSTime();
171 if (QueryResult result = CharacterDatabase.Query("SELECT MAX(surveyId) FROM gm_surveys"))
172 _lastSurveyId = (*result)[0].GetUInt32();
173
174 SF_LOG_INFO("server.loading", ">> Loaded GM Survey count from database in %u ms", GetMSTimeDiffToNow(oldMSTime));
175
176}
177
179{
180 _gmTicketList[ticket->GetTicketId()] = ticket;
181 if (!ticket->IsClosed())
183
184 SQLTransaction trans = SQLTransaction(NULL);
185 ticket->SaveToDB(trans);
186}
187
189{
190 _bugTicketList[ticket->GetTicketId()] = ticket;
191 if (!ticket->IsClosed())
193
194 SQLTransaction trans = SQLTransaction(NULL);
195 ticket->SaveToDB(trans);
196}
197
199{
200 _suggestTicketList[ticket->GetTicketId()] = ticket;
201 if (!ticket->IsClosed())
203
204 SQLTransaction trans = SQLTransaction(NULL);
205 ticket->SaveToDB(trans);
206}
207
212
217
222
224{
225 GmTicketList::const_iterator itr = _gmTicketList.find(ticketId);
226 if (itr != _gmTicketList.end())
227 return itr->second;
228
229 return NULL;
230}
231
233{
234 BugTicketList::const_iterator itr = _bugTicketList.find(bugId);
235 if (itr != _bugTicketList.end())
236 return itr->second;
237
238 return NULL;
239}
240
242{
243 SuggestTicketList::const_iterator itr = _suggestTicketList.find(ticketId);
244 if (itr != _suggestTicketList.end())
245 return itr->second;
246
247 return NULL;
248}
249
251{
252 if (GmTicket* ticket = GetTicket<GmTicket>(ticketId))
253 {
254 ticket->DeleteFromDB();
255 _gmTicketList.erase(ticketId);
256 delete ticket;
257 }
258}
259
261{
262 if (BugTicket* ticket = GetTicket<BugTicket>(ticketId))
263 {
264 ticket->DeleteFromDB();
265 _bugTicketList.erase(ticketId);
266 delete ticket;
267 }
268}
269
271{
272 if (SuggestTicket* ticket = GetTicket<SuggestTicket>(ticketId))
273 {
274 ticket->DeleteFromDB();
275 _suggestTicketList.erase(ticketId);
276 delete ticket;
277 }
278}
279
280template<> void TicketMgr::CloseTicket<GmTicket>(uint32 ticketId, int64 closedBy)
281{
282 if (GmTicket* ticket = GetTicket<GmTicket>(ticketId))
283 {
284 SQLTransaction trans = SQLTransaction(NULL);
285 ticket->SetClosedBy(closedBy);
286 if (closedBy)
288
289 ticket->SaveToDB(trans);
290 }
291}
292
293template<> void TicketMgr::CloseTicket<BugTicket>(uint32 ticketId, int64 closedBy)
294{
295 if (BugTicket* ticket = GetTicket<BugTicket>(ticketId))
296 {
297 SQLTransaction trans = SQLTransaction(NULL);
298 ticket->SetClosedBy(closedBy);
299 if (closedBy)
301
302 ticket->SaveToDB(trans);
303 }
304}
305
306template<> void TicketMgr::CloseTicket<SuggestTicket>(uint32 ticketId, int64 closedBy)
307{
308 if (SuggestTicket* ticket = GetTicket<SuggestTicket>(ticketId))
309 {
310 SQLTransaction trans = SQLTransaction(NULL);
311 ticket->SetClosedBy(closedBy);
312 if (closedBy)
314
315 ticket->SaveToDB(trans);
316 }
317}
318
320{
321 for (GmTicketList::const_iterator itr = _gmTicketList.begin(); itr != _gmTicketList.end(); ++itr)
322 delete itr->second;
323
324 _gmTicketList.clear();
325
326 _lastGmTicketId = 0;
327
328 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_GM_TICKETS);
329 CharacterDatabase.Execute(stmt);
330}
331
333{
334 for (BugTicketList::const_iterator itr = _bugTicketList.begin(); itr != _bugTicketList.end(); ++itr)
335 delete itr->second;
336
337 _bugTicketList.clear();
338
339 _lastBugId = 0;
340
341 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_GM_BUGS);
342 CharacterDatabase.Execute(stmt);
343}
344
346{
347 for (SuggestTicketList::const_iterator itr = _suggestTicketList.begin(); itr != _suggestTicketList.end(); ++itr)
348 delete itr->second;
349
350 _suggestTicketList.clear();
351
352 _lastSuggestId = 0;
353
355 CharacterDatabase.Execute(stmt);
356}
357
358template<> void TicketMgr::ShowList<GmTicket>(ChatHandler& handler, bool onlineOnly) const
359{
361 for (GmTicketList::const_iterator itr = _gmTicketList.begin(); itr != _gmTicketList.end(); ++itr)
362 if (!itr->second->IsClosed() && !itr->second->IsCompleted())
363 if (!onlineOnly || itr->second->GetPlayer())
364 handler.SendSysMessage(itr->second->FormatMessageString(handler).c_str());
365}
366
367template<> void TicketMgr::ShowList<GmTicket>(ChatHandler& handler) const
368{
370 for (GmTicketList::const_iterator itr = _gmTicketList.begin(); itr != _gmTicketList.end(); ++itr)
371 if (!itr->second->IsClosed() && !itr->second->IsCompleted())
372 handler.SendSysMessage(itr->second->FormatMessageString(handler).c_str());
373}
374
375template<> void TicketMgr::ShowList<BugTicket>(ChatHandler& handler) const
376{
378 for (BugTicketList::const_iterator itr = _bugTicketList.begin(); itr != _bugTicketList.end(); ++itr)
379 if (!itr->second->IsClosed())
380 handler.SendSysMessage(itr->second->FormatMessageString(handler).c_str());
381}
382
383template<> void TicketMgr::ShowList<SuggestTicket>(ChatHandler& handler) const
384{
386 for (SuggestTicketList::const_iterator itr = _suggestTicketList.begin(); itr != _suggestTicketList.end(); ++itr)
387 if (!itr->second->IsClosed())
388 handler.SendSysMessage(itr->second->FormatMessageString(handler).c_str());
389}
390
392{
394 for (GmTicketList::const_iterator itr = _gmTicketList.begin(); itr != _gmTicketList.end(); ++itr)
395 if (itr->second->IsClosed())
396 handler.SendSysMessage(itr->second->FormatMessageString(handler).c_str());
397}
398
400{
402 for (BugTicketList::const_iterator itr = _bugTicketList.begin(); itr != _bugTicketList.end(); ++itr)
403 if (itr->second->IsClosed())
404 handler.SendSysMessage(itr->second->FormatMessageString(handler).c_str());
405}
406
408{
410 for (SuggestTicketList::const_iterator itr = _suggestTicketList.begin(); itr != _suggestTicketList.end(); ++itr)
411 if (itr->second->IsClosed())
412 handler.SendSysMessage(itr->second->FormatMessageString(handler).c_str());
413}
414
416{
418 for (GmTicketList::const_iterator itr = _gmTicketList.begin(); itr != _gmTicketList.end(); ++itr)
419 if (!itr->second->IsClosed() && itr->second->GetEscalatedStatus() == TICKET_IN_ESCALATION_QUEUE)
420 handler.SendSysMessage(itr->second->FormatMessageString(handler).c_str());
421}
422
424
425void TicketMgr::SendGmTicket(WorldSession* session, GmTicket* ticket) const
426{
427 uint32 size = ticket ? (3 + 4 + 1 + 1 + 1 + 4 + ticket->GetMessage().size() + 4 + 4 + 4 + 4) : 1 + 4;
429
430 if (ticket)
431 {
432 GMTicketEscalationStatus escaledstatus = ticket->GetEscalatedStatus();
434 float OldestTicketTime = sTicketMgr->GetOldestOpenTicket() ? GetAge(sTicketMgr->GetOldestOpenTicket()->GetLastModifiedTime()) : 0.0f;
435
436 data.WriteBit(1); // Initilize
437 data.WriteBits(ticket->GetMessage().size(), 11);
438 data.WriteBits(0, 10); // waitTimeOverrideMessage size
439 data.FlushBits();
440 data << uint32(ticket->GetTicketId());
441 data << uint8(std::min(escaledstatus, TICKET_IN_ESCALATION_QUEUE));
442 data << uint8(viewed);
443 data << uint8(1); // Unk
444 data << uint32(ticket->GetMapId());
445 data.WriteString(ticket->GetMessage());
446 data << uint32(0); // Unk
447 data << uint32(OldestTicketTime);
448 data << uint32(GetAge(sTicketMgr->GetLastChange()));
450 }
451 else
452 {
453 data.WriteBit(0);
454 data.FlushBits();
456 }
457
458 session->SendPacket(&data);
459}
460
462{
463 if (ticket)
464 {
465 WorldPacket data(SMSG_GM_TICKET_RESPONSE, 1 + ticket->GetMessage().size() + ticket->GetResponse().size() + 4 + 4);
466 data.WriteBit(0); // Has message ???
467 data.WriteBit(0); // Has response ???
468
469 data.WriteBits(ticket->GetMessage().size(), 11);
470 data.WriteBits(ticket->GetResponse().size(), 14);
471 data.FlushBits();
472
473 data.WriteString(ticket->GetMessage());
474 data.WriteString(ticket->GetResponse());
475
476 data << uint32(ticket->GetTicketId());
477 data << uint32(1); // Response ID
478
479 session->SendPacket(&data);
480 }
481}
482
484{
485 if (player && player->IsInWorld())
486 {
487 WorldPacket data(opcode, 4);
488 data << uint32(response);
489 player->GetSession()->SendPacket(&data);
490 }
491}
@ CHAR_DEL_ALL_GM_SUGGESTS
@ CHAR_DEL_ALL_GM_BUGS
@ CHAR_DEL_ALL_GM_TICKETS
@ CHAR_SEL_GM_BUGS
@ CHAR_SEL_GM_TICKETS
@ CHAR_SEL_GM_SUGGESTS
@ DAY
Definition Common.h:121
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
std::int64_t int64
Definition Define.h:72
@ LANG_COMMAND_TICKETSHOWONLINELIST
Definition Language.h:1045
@ LANG_COMMAND_TICKETSHOWESCALATEDLIST
Definition Language.h:1061
@ LANG_COMMAND_TICKETSHOWLIST
Definition Language.h:1044
@ LANG_COMMAND_TICKETSHOWCLOSEDLIST
Definition Language.h:1046
#define SF_LOG_INFO(filterType__,...)
Definition Log.h:137
Skyfire::AutoPtr< PreparedResultSet, Skyfire::Mutex > PreparedQueryResult
Definition QueryResult.h:94
Skyfire::AutoPtr< ResultSet, Skyfire::Mutex > QueryResult
Definition QueryResult.h:48
GMTicketEscalationStatus
Definition TicketInfo.h:42
@ TICKET_IN_ESCALATION_QUEUE
Definition TicketInfo.h:45
@ GMTICKET_STATUS_DEFAULT
Definition TicketInfo.h:23
@ GMTICKET_STATUS_HASTEXT
Definition TicketInfo.h:22
GMTicketResponse
Definition TicketInfo.h:27
GMTicketOpenedByGMStatus
Definition TicketInfo.h:51
float GetAge(uint64 t)
Definition TicketMgr.cpp:18
#define sTicketMgr
Definition TicketMgr.h:117
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:22
uint32 getMSTime()
Definition Timer.h:12
Skyfire::AutoPtr< Transaction, Skyfire::Mutex > SQLTransaction
Definition Transaction.h:42
void SaveToDB(SQLTransaction &trans) const OVERRIDE
void LoadFromDB(Field *fields) OVERRIDE
bool WriteBit(uint32 bit)
Definition ByteBuffer.h:164
void WriteString(std::string const &str)
Definition ByteBuffer.h:578
void WriteBits(T value, size_t bits)
Definition ByteBuffer.h:192
void FlushBits()
Definition ByteBuffer.h:154
virtual void SendSysMessage(const char *str)
Definition Chat.cpp:153
Definition Field.h:16
std::string const & GetMessage() const
Definition TicketInfo.h:148
bool GetViewed() const
Definition TicketInfo.h:139
std::string const & GetResponse() const
Definition TicketInfo.h:150
void LoadFromDB(Field *fields) OVERRIDE
GMTicketEscalationStatus GetEscalatedStatus() const
Definition TicketInfo.h:153
void SaveToDB(SQLTransaction &trans) const OVERRIDE
bool IsInWorld() const
Definition Object.h:114
WorldSession * GetSession() const
Definition Player.h:2417
void SaveToDB(SQLTransaction &trans) const OVERRIDE
void LoadFromDB(Field *fields) OVERRIDE
uint32 GetTicketId() const
Definition TicketInfo.h:85
uint32 GetMapId() const
Definition TicketInfo.h:86
bool IsClosed() const
Definition TicketInfo.h:75
void SendGmResponsee(WorldSession *session, GmTicket *ticket) const
SuggestTicketList _suggestTicketList
Definition TicketMgr.h:106
GmTicketList _gmTicketList
Definition TicketMgr.h:104
bool _gmTicketSystemStatus
Definition TicketMgr.h:103
uint32 _lastSuggestId
Definition TicketMgr.h:110
void LoadSuggestTickets()
bool _feedbackSystemStatus
Definition TicketMgr.h:102
void SetGmTicketSystemStatus(bool status)
Definition TicketMgr.h:72
void SendGmTicketUpdate(Opcodes opcode, GMTicketResponse response, Player *player) const
void LoadSurveys()
uint32 _openGmTicketCount
Definition TicketMgr.h:112
void LoadBugTickets()
Definition TicketMgr.cpp:83
void ShowClosedList(ChatHandler &handler) const
void AddTicket(GmTicket *ticket)
void CloseTicket(uint32 ticketId, int64 closedBy)
BugTicketList _bugTicketList
Definition TicketMgr.h:105
uint32 GetOpenTicketCount() const
uint32 _lastBugId
Definition TicketMgr.h:109
uint32 _lastSurveyId
Definition TicketMgr.h:108
T * GetTicket(uint32 ticketId)
uint64 _lastChange
Definition TicketMgr.h:111
void ShowGmEscalatedList(ChatHandler &handler) const
void Initialize()
Definition TicketMgr.cpp:36
void SendGmTicket(WorldSession *session, GmTicket *ticket) const
@ response Packets
uint32 _openSuggestTicketCount
Definition TicketMgr.h:114
void SetFeedBackSystemStatus(bool status)
Definition TicketMgr.h:71
uint32 _lastGmTicketId
Definition TicketMgr.h:107
uint32 _openBugTicketCount
Definition TicketMgr.h:113
void LoadGmTickets()
Definition TicketMgr.cpp:42
void ResetTickets()
void RemoveTicket(uint32 ticketId)
void ShowList(ChatHandler &handler) const
Player session in the World.
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
CharacterDatabaseWorkerPool CharacterDatabase
Accessor to the character database.
Definition Main.cpp:41
Opcodes
List of Opcodes.
Definition Opcodes.h:21
@ SMSG_GM_TICKET_RESPONSE
Definition Opcodes.h:665
@ SMSG_GM_TICKET_GET_TICKET
Definition Opcodes.h:663
#define sWorld
Definition World.h:910
@ CONFIG_TICKETS_GM_ENABLED
Definition World.h:167
@ CONFIG_TICKETS_FEEDBACK_SYSTEM_ENABLED
Definition World.h:168