ManaPlus
messageout.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2004-2009 The Mana World Development Team
4  * Copyright (C) 2009-2010 The Mana Developers
5  * Copyright (C) 2011-2018 The ManaPlus Developers
6  *
7  * This file is part of The ManaPlus Client.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "net/messageout.h"
24 
25 #include "logger.h"
26 
27 #include "net/net.h"
28 #include "net/packetcounters.h"
29 
30 #include "utils/stringutils.h"
31 
32 PRAGMA48(GCC diagnostic push)
33 PRAGMA48(GCC diagnostic ignored "-Wshadow")
34 #include <SDL_endian.h>
35 PRAGMA48(GCC diagnostic pop)
36 
37 #include "debug.h"
38 
39 #ifndef SDL_BIG_ENDIAN
40 #error missing SDL_endian.h
41 #endif // SDL_BYTEORDER
42 
43 extern int itemIdLen;
44 
45 namespace Net
46 {
47 
48 MessageOut::MessageOut(const int16_t id) :
49  mData(nullptr),
50  mDataSize(0),
51  mPos(0),
52  mId(id),
53  mIgnore(false)
54 {
57  DEBUGLOG2("Send packet", 0, "MessageOut");
58 }
59 
60 void MessageOut::writeInt8(const int8_t value, const char *const str)
61 {
62  expand(1);
63  mData[mPos] = value;
64  DEBUGLOG2("writeInt8: " + toStringPrint(CAST_U32(
65  CAST_U8(value))),
66  mPos, str);
67  mPos += 1;
68 }
69 
70 void MessageOut::writeInt16(const int16_t value, const char *const str)
71 {
72  expand(2);
73 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
74  int16_t swap = SDL_Swap16(value);
75  memcpy(mData + CAST_SIZE(mPos), &swap, sizeof(int16_t));
76 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
77 
78  memcpy(mData + CAST_SIZE(mPos), &value, sizeof(int16_t));
79 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
80 
81  DEBUGLOG2("writeInt16: " + toStringPrint(CAST_U32(
82  CAST_U16(value))),
83  mPos, str);
84  mPos += 2;
85 }
86 
87 void MessageOut::writeInt32(const int32_t value, const char *const str)
88 {
89  DEBUGLOG2("writeInt32: " + toStringPrint(CAST_U32(value)),
90  mPos, str);
91  expand(4);
92 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
93  int32_t swap = SDL_Swap32(value);
94  memcpy(mData + CAST_SIZE(mPos), &swap, sizeof(int32_t));
95 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
96 
97  memcpy(mData + CAST_SIZE(mPos), &value, sizeof(int32_t));
98 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
99 
100  mPos += 4;
101 }
102 
103 void MessageOut::writeItemId(const int32_t value,
104  const char *const str)
105 {
106  if (itemIdLen == 2)
107  writeInt16(CAST_S16(value), str);
108  else
109  writeInt32(value, str);
110 }
111 
112 void MessageOut::writeInt64(const int64_t value, const char *const str)
113 {
114  DEBUGLOG2("writeInt64: " + toStringPrint(CAST_U32(value)),
115  mPos, str);
116  expand(8);
117 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
118  int32_t swap = SDL_Swap64(value);
119  memcpy(mData + CAST_SIZE(mPos), &swap, sizeof(int64_t));
120 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
121 
122  memcpy(mData + CAST_SIZE(mPos), &value, sizeof(int64_t));
123 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
124 
125  mPos += 8;
126 }
127 
128 void MessageOut::writeBeingId(const BeingId value, const char *const str)
129 {
130  writeInt32(toInt(value, int32_t), str);
131 }
132 
133 #define LOBYTE(w) (CAST_U8(w))
134 #define HIBYTE(w) (CAST_U8((CAST_U16(w)) >> 8))
135 
136 void MessageOut::writeCoordinates(const uint16_t x,
137  const uint16_t y,
138  unsigned char direction,
139  const char *const str)
140 {
141  DEBUGLOG2(strprintf("writeCoordinates: %u,%u %u",
142  CAST_U32(x),
143  CAST_U32(y),
144  CAST_U32(direction)), mPos, str);
145  unsigned char *const data = reinterpret_cast<unsigned char*>(mData)
146  + CAST_SIZE(mPos);
147  expand(3);
148  mPos += 3;
149 
150  uint16_t temp = x;
151  temp <<= 6;
152  data[0] = 0;
153  data[1] = 1;
154  data[2] = 2;
155  data[0] = HIBYTE(temp);
156  data[1] = CAST_U8(temp);
157  temp = y;
158  temp <<= 4;
159  data[1] |= HIBYTE(temp);
160  data[2] = LOBYTE(temp);
161  direction = toServerDirection(direction);
162  data[2] |= direction;
163 }
164 
165 void MessageOut::writeString(const std::string &string,
166  int length,
167  const char *const str)
168 {
169  int stringLength = CAST_S32(string.length());
170  if (length < 0)
171  {
172  // Write the length at the start if not fixed
173  writeInt16(CAST_S16(stringLength), "len");
174  length = stringLength;
175  }
176  else if (length < stringLength)
177  {
178  // Make sure the length of the string is no longer than specified
179  stringLength = length;
180  }
181  expand(length);
182 
183  // Write the actual string
184  memcpy(mData + CAST_SIZE(mPos), string.c_str(), stringLength);
185 
186  // Pad remaining space with zeros
187  if (length > stringLength)
188  {
189  memset(mData + CAST_SIZE(mPos + stringLength),
190  '\0',
191  length - stringLength);
192  }
193 
194  DEBUGLOG2("writeString: " + string, mPos, str);
195  mPos += length;
196 }
197 
198 void MessageOut::writeStringNoLog(const std::string &string,
199  int length,
200  const char *const str)
201 {
202  int stringLength = CAST_S32(string.length());
203  if (length < 0)
204  {
205  // Write the length at the start if not fixed
206  writeInt16(CAST_S16(stringLength), "len");
207  length = stringLength;
208  }
209  else if (length < stringLength)
210  {
211  // Make sure the length of the string is no longer than specified
212  stringLength = length;
213  }
214  expand(length);
215 
216  // Write the actual string
217  memcpy(mData + CAST_SIZE(mPos), string.c_str(), stringLength);
218 
219  // Pad remaining space with zeros
220  if (length > stringLength)
221  {
222  memset(mData + CAST_SIZE(mPos + stringLength),
223  '\0',
224  length - stringLength);
225  }
226 
227  DEBUGLOG2("writeString: ***", mPos, str);
228  mPos += length;
229 }
230 
231 const char *MessageOut::getData() const
232 {
233  return mData;
234 }
235 
236 unsigned int MessageOut::getDataSize() const
237 {
238  return mDataSize;
239 }
240 
241 unsigned char MessageOut::toServerDirection(unsigned char direction)
242 {
243  // Translate direction to eAthena format
244  switch (direction)
245  {
246  case 1: // DOWN
247  direction = 0;
248  break;
249  case 3: // DOWN | LEFT
250  direction = 1;
251  break;
252  case 2: // LEFT
253  direction = 2;
254  break;
255  case 6: // LEFT | UP
256  direction = 3;
257  break;
258  case 4: // UP
259  direction = 4;
260  break;
261  case 12: // UP | RIGHT
262  direction = 5;
263  break;
264  case 8: // RIGHT
265  direction = 6;
266  break;
267  case 9: // RIGHT + DOWN
268  direction = 7;
269  break;
270  default:
271  // OOPSIE! Impossible or unknown
272  direction = CAST_U8(-1);
273  break;
274  }
275  return direction;
276 }
277 
278 } // namespace Net
#define HIBYTE(w)
Definition: messageout.cpp:134
#define CAST_U32
Definition: cast.h:30
void writeString(const std::string &string, int length, const char *const str)
Definition: messageout.cpp:165
unsigned int mDataSize
Definition: messageout.h:129
#define CAST_U8
Definition: cast.h:26
void writeStringNoLog(const std::string &string, int length, const char *const str)
Definition: messageout.cpp:198
std::string toStringPrint(const unsigned int val)
static unsigned char toServerDirection(unsigned char direction) A_CONST
Definition: messageout.cpp:241
#define DEBUGLOG2(str, pos, comment)
Definition: logger.h:41
#define LOBYTE(w)
Definition: messageout.cpp:133
int BeingId
Definition: beingid.h:29
void writeItemId(const int32_t value, const char *const str)
Definition: messageout.cpp:103
virtual void expand(size_t size) const =0
unsigned int mPos
Definition: messageout.h:130
void writeInt64(const int64_t value, const char *const str)
Definition: messageout.cpp:112
unsigned int getDataSize() const
Definition: messageout.cpp:236
const char * getData() const
Definition: messageout.cpp:231
#define toInt(val, name)
Definition: intdefines.h:46
#define CAST_U16
Definition: cast.h:28
void writeBeingId(const BeingId value, const char *const str)
Definition: messageout.cpp:128
#define CAST_S32
Definition: cast.h:29
std::string strprintf(const char *const format,...)
Definition: stringutils.cpp:99
static void incOutPackets()
uint32_t data
void writeInt16(const int16_t value, const char *const str)
Definition: messageout.cpp:70
#define IGNOREDEBUGLOG
Definition: logger.h:47
void writeCoordinates(const uint16_t x, const uint16_t y, unsigned char direction, const char *const str)
Definition: messageout.cpp:136
#define nullptr
Definition: localconsts.h:44
PlayerInfoBackend mData
Definition: playerinfo.cpp:54
virtual void writeInt8(const int8_t value, const char *const str)
Definition: messageout.cpp:60
MessageOut(const int16_t id)
Definition: messageout.cpp:48
#define PRAGMA48(str)
Definition: localconsts.h:198
#define CAST_SIZE
Definition: cast.h:33
#define CAST_S16
Definition: cast.h:27
int itemIdLen
Definition: client.cpp:129
void writeInt32(const int32_t value, const char *const str)
Definition: messageout.cpp:87