TrinityCore
Loading...
Searching...
No Matches
TicketHandler.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "WorldSession.h"
19#include "Common.h"
20#include "DatabaseEnv.h"
21#include "GameTime.h"
22#include "Language.h"
23#include "Log.h"
24#include "ObjectMgr.h"
25#include "Opcodes.h"
26#include "Player.h"
27#include "Random.h"
28#include "TicketMgr.h"
29#include "TicketPackets.h"
30#include "Util.h"
31#include "World.h"
32#include "WorldPacket.h"
33#include <zlib.h>
34
36{
37 // Don't accept tickets if the ticket queue is disabled. (Ticket UI is greyed out but not fully dependable)
39 return;
40
41 if (GetPlayer()->GetLevel() < sWorld->getIntConfig(CONFIG_TICKET_LEVEL_REQ))
42 {
44 return;
45 }
46
48 GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID());
49
50 if (ticket && ticket->IsCompleted())
51 sTicketMgr->CloseTicket(ticket->GetId(), GetPlayer()->GetGUID());
52
53 // Player must not have ticket
54 if (!ticket || ticket->IsClosed())
55 {
56 uint32 mapId;
57 float x, y, z;
58 std::string message;
59 uint32 needResponse;
60 bool needMoreHelp;
61 uint32 count;
62 std::list<uint32> times;
63 uint32 decompressedSize;
64 std::string chatLog;
65
66 recvData >> mapId;
67 recvData >> x >> y >> z;
68 recvData >> message;
69
71 return;
72
73 recvData >> needResponse;
74 recvData >> needMoreHelp;
75
76 recvData >> count;
77
78 for (uint32 i = 0; i < count; i++)
79 {
80 uint32 time;
81 recvData >> time;
82 times.push_back(time);
83 }
84
85 recvData >> decompressedSize;
86
87 if (count && decompressedSize && decompressedSize < 0xFFFF)
88 {
89 uint32 pos = recvData.rpos();
90 ByteBuffer dest;
91 dest.resize(decompressedSize);
92
93 uLongf realSize = decompressedSize;
94 if (uncompress(dest.contents(), &realSize, recvData.contents() + pos, recvData.size() - pos) == Z_OK)
95 {
96 dest >> chatLog;
97 }
98 else
99 {
100 TC_LOG_ERROR("network", "CMSG_GM_TICKET_CREATE possibly corrupt. Uncompression failed.");
101 recvData.rfinish();
102 return;
103 }
104
105 recvData.rfinish(); // Will still have compressed data in buffer.
106 }
107
108 if (!chatLog.empty() && !ValidateHyperlinksAndMaybeKick(chatLog))
109 return;
110
111 ticket = new GmTicket(GetPlayer());
112 ticket->SetPosition(mapId, x, y, z);
113 ticket->SetMessage(message);
114 ticket->SetGmAction(needResponse, needMoreHelp);
115 if (!chatLog.empty())
116 ticket->SetChatLog(times, chatLog);
117
118 sTicketMgr->AddTicket(ticket);
119 sTicketMgr->UpdateLastChange();
120
121 sWorld->SendGMText(LANG_COMMAND_TICKETNEW, GetPlayer()->GetName().c_str(), ticket->GetId());
122
124 }
125
127 data << uint32(response);
128 SendPacket(&data);
129}
130
132{
133 std::string message;
134 recvData >> message;
135
136 if (!ValidateHyperlinksAndMaybeKick(message))
137 return;
138
140 if (GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID()))
141 {
143 ticket->SetMessage(message);
144 ticket->SaveToDB(trans);
145
146 sWorld->SendGMText(LANG_COMMAND_TICKETUPDATED, GetPlayer()->GetName().c_str(), ticket->GetId());
147
149 }
150
152 data << uint32(response);
153 SendPacket(&data);
154}
155
157{
158 if (GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID()))
159 {
162 SendPacket(&data);
163
164 sWorld->SendGMText(LANG_COMMAND_TICKETPLAYERABANDON, GetPlayer()->GetName().c_str(), ticket->GetId());
165
166 sTicketMgr->CloseTicket(ticket->GetId(), GetPlayer()->GetGUID());
167 sTicketMgr->SendTicket(this, nullptr);
168 }
169}
170
172{
174
175 if (GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID()))
176 {
177 if (ticket->IsCompleted())
178 ticket->SendResponse(this);
179 else
180 sTicketMgr->SendTicket(this, ticket);
181 }
182 else
183 sTicketMgr->SendTicket(this, nullptr);
184}
185
187{
188 // Note: This only disables the ticket UI at client side and is not fully reliable
189 // Note: This disables the whole customer support UI after trying to send a ticket in disabled state (MessageBox: "GM Help Tickets are currently unavaiable."). UI remains disabled until the character relogs.
192 SendPacket(response.Write());
193}
194
196{
197 uint32 nextSurveyID = sTicketMgr->GetNextSurveyID();
198 // just put the survey into the database
199 uint32 mainSurvey; // GMSurveyCurrentSurvey.dbc, column 1 (all 9) ref to GMSurveySurveys.dbc
200 recvData >> mainSurvey;
201
202 std::unordered_set<uint32> surveyIds;
203 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
204 // 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,
205 for (uint8 i = 0; i < 10; i++)
206 {
207 uint32 subSurveyId; // ref to i'th GMSurveySurveys.dbc field (all fields in that dbc point to fields in GMSurveyQuestions.dbc)
208 recvData >> subSurveyId;
209 if (!subSurveyId)
210 break;
211
212 uint8 rank; // probably some sort of ref to GMSurveyAnswers.dbc
213 recvData >> rank;
214 std::string comment; // comment ("Usage: GMSurveyAnswerSubmit(question, rank, comment)")
215 recvData >> comment;
216
217 // make sure the same sub survey is not added to DB twice
218 if (!surveyIds.insert(subSurveyId).second)
219 continue;
220
221 if (!ValidateHyperlinksAndMaybeKick(comment))
222 return;
223
225 stmt->setUInt32(0, nextSurveyID);
226 stmt->setUInt32(1, subSurveyId);
227 stmt->setUInt32(2, rank);
228 stmt->setString(3, comment);
229 trans->Append(stmt);
230 }
231
232 std::string comment; // just a guess
233 recvData >> comment;
234
235 if (!ValidateHyperlinksAndMaybeKick(comment))
236 return;
237
239 stmt->setUInt32(0, GetPlayer()->GetGUID().GetCounter());
240 stmt->setUInt32(1, nextSurveyID);
241 stmt->setUInt32(2, mainSurvey);
242 stmt->setString(3, comment);
243
244 trans->Append(stmt);
245
246 CharacterDatabase.CommitTransaction(trans);
247}
248
250{
251 // just put the lag report into the database...
252 // can't think of anything else to do with it
253 uint32 lagType, mapId;
254 recvData >> lagType;
255 recvData >> mapId;
256 float x, y, z;
257 recvData >> x;
258 recvData >> y;
259 recvData >> z;
260
262 stmt->setUInt32(0, GetPlayer()->GetGUID().GetCounter());
263 stmt->setUInt8 (1, lagType);
264 stmt->setUInt16(2, mapId);
265 stmt->setFloat (3, x);
266 stmt->setFloat (4, y);
267 stmt->setFloat (5, z);
268 stmt->setUInt32(6, GetLatency());
270 CharacterDatabase.Execute(stmt);
271}
272
274{
275 // empty packet
276 if (GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID()))
277 {
278 uint8 getSurvey = 0;
279 if (roll_chance_f(sWorld->getFloatConfig(CONFIG_CHANCE_OF_GM_SURVEY)))
280 getSurvey = 1;
281
283 data << uint8(getSurvey);
284 SendPacket(&data);
285
288 SendPacket(&data2);
289
290 sTicketMgr->CloseTicket(ticket->GetId(), GetPlayer()->GetGUID());
291 sTicketMgr->SendTicket(this, nullptr);
292 }
293}
@ CHAR_INS_GM_SURVEY
@ CHAR_INS_LAG_REPORT
@ CHAR_INS_GM_SUBSURVEY
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
uint8_t uint8
Definition Define.h:135
uint32_t uint32
Definition Define.h:133
@ LANG_TICKET_REQ
Definition Language.h:1165
@ LANG_COMMAND_TICKETPLAYERABANDON
Definition Language.h:1027
@ LANG_COMMAND_TICKETNEW
Definition Language.h:1025
@ LANG_COMMAND_TICKETUPDATED
Definition Language.h:1026
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
bool roll_chance_f(float chance)
Definition Random.h:53
#define sTicketMgr
Definition TicketMgr.h:250
@ GMTICKET_QUEUE_STATUS_ENABLED
Definition TicketMgr.h:34
@ GMTICKET_QUEUE_STATUS_DISABLED
Definition TicketMgr.h:33
GMTicketResponse
Definition TicketMgr.h:44
@ GMTICKET_RESPONSE_CREATE_ERROR
Definition TicketMgr.h:47
@ GMTICKET_RESPONSE_CREATE_SUCCESS
Definition TicketMgr.h:46
@ GMTICKET_RESPONSE_TICKET_DELETED
Definition TicketMgr.h:50
@ GMTICKET_RESPONSE_UPDATE_SUCCESS
Definition TicketMgr.h:48
@ GMTICKET_RESPONSE_UPDATE_ERROR
Definition TicketMgr.h:49
size_t rpos() const
Definition ByteBuffer.h:312
void resize(size_t newsize)
Definition ByteBuffer.h:416
void rfinish()
Definition ByteBuffer.h:320
size_t size() const
Definition ByteBuffer.h:413
uint8 * contents()
Definition ByteBuffer.h:399
bool IsClosed() const
Definition TicketMgr.h:97
void SetPosition(uint32 mapId, float x, float y, float z)
void SetMessage(std::string const &message)
void SetGmAction(uint32 needResponse, bool needMoreHelp)
bool IsCompleted() const
Definition TicketMgr.h:98
uint32 GetId() const
Definition TicketMgr.h:105
void SetChatLog(std::list< uint32 > time, std::string const &log)
void setUInt16(uint8 index, uint16 value)
void setUInt32(uint8 index, uint32 value)
void setFloat(uint8 index, float value)
void setUInt8(uint8 index, uint8 value)
void setString(uint8 index, std::string const &value)
WorldPacket const * Write() override
void HandleGMTicketCreateOpcode(WorldPacket &recvPacket)
char const * GetTrinityString(uint32 entry) const
void SendNotification(char const *format,...) ATTR_PRINTF(2
void HandleGMSurveySubmit(WorldPacket &recvPacket)
void SendPacket(WorldPacket const *packet)
Send a packet to the client.
void HandleGMTicketUpdateOpcode(WorldPacket &recvPacket)
void HandleGMTicketGetTicketOpcode(WorldPackets::Ticket::GMTicketGetTicket &packet)
void HandleGMTicketSystemStatusOpcode(WorldPackets::Ticket::GMTicketGetSystemStatus &packet)
Player * GetPlayer() const
void HandleGMResponseResolve(WorldPacket &recvPacket)
void HandleReportLag(WorldPacket &recvPacket)
uint32 GetLatency() const
void SendQueryTimeResponse()
void HandleGMTicketDeleteOpcode(WorldPacket &recvPacket)
bool ValidateHyperlinksAndMaybeKick(std::string const &str)
@ SMSG_GMRESPONSE_STATUS_UPDATE
Definition Opcodes.h:1294
@ SMSG_GMTICKET_DELETETICKET
Definition Opcodes.h:565
@ SMSG_GMTICKET_UPDATETEXT
Definition Opcodes.h:549
@ SMSG_GMTICKET_CREATE
Definition Opcodes.h:547
#define sWorld
Definition World.h:901
@ CONFIG_TICKET_LEVEL_REQ
Definition World.h:303
@ CONFIG_CHANCE_OF_GM_SURVEY
Definition World.h:196
time_t GetGameTime()
Definition GameTime.cpp:42