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-2019 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 void MessageOut::writeFloat(const float value, const char *const str)
134 {
135 #ifdef ENABLEDEBUGLOG
136  std::string text = strprintf("writeFloat: %f", value);
137  DEBUGLOG2(text, mPos, str);
138 #endif
139  expand(4);
140  memcpy(mData + CAST_SIZE(mPos), &value, sizeof(float));
141  mPos += 4;
142 }
143 
144 #define LOBYTE(w) (CAST_U8(w))
145 #define HIBYTE(w) (CAST_U8((CAST_U16(w)) >> 8))
146 
147 void MessageOut::writeCoordinates(const uint16_t x,
148  const uint16_t y,
149  unsigned char direction,
150  const char *const str)
151 {
152  DEBUGLOG2(strprintf("writeCoordinates: %u,%u %u",
153  CAST_U32(x),
154  CAST_U32(y),
155  CAST_U32(direction)), mPos, str);
156  unsigned char *const data = reinterpret_cast<unsigned char*>(mData)
157  + CAST_SIZE(mPos);
158  expand(3);
159  mPos += 3;
160 
161  uint16_t temp = x;
162  temp <<= 6;
163  data[0] = 0;
164  data[1] = 1;
165  data[2] = 2;
166  data[0] = HIBYTE(temp);
167  data[1] = CAST_U8(temp);
168  temp = y;
169  temp <<= 4;
170  data[1] |= HIBYTE(temp);
171  data[2] = LOBYTE(temp);
172  direction = toServerDirection(direction);
173  data[2] |= direction;
174 }
175 
176 void MessageOut::writeString(const std::string &string,
177  int length,
178  const char *const str)
179 {
180  int stringLength = CAST_S32(string.length());
181  if (length < 0)
182  {
183  // Write the length at the start if not fixed
184  writeInt16(CAST_S16(stringLength), "len");
185  length = stringLength;
186  }
187  else if (length < stringLength)
188  {
189  // Make sure the length of the string is no longer than specified
190  stringLength = length;
191  }
192  expand(length);
193 
194  // Write the actual string
195  memcpy(mData + CAST_SIZE(mPos), string.c_str(), stringLength);
196 
197  // Pad remaining space with zeros
198  if (length > stringLength)
199  {
200  memset(mData + CAST_SIZE(mPos + stringLength),
201  '\0',
202  length - stringLength);
203  }
204 
205  DEBUGLOG2("writeString: " + string, mPos, str);
206  mPos += length;
207 }
208 
209 void MessageOut::writeStringNoLog(const std::string &string,
210  int length,
211  const char *const str)
212 {
213  int stringLength = CAST_S32(string.length());
214  if (length < 0)
215  {
216  // Write the length at the start if not fixed
217  writeInt16(CAST_S16(stringLength), "len");
218  length = stringLength;
219  }
220  else if (length < stringLength)
221  {
222  // Make sure the length of the string is no longer than specified
223  stringLength = length;
224  }
225  expand(length);
226 
227  // Write the actual string
228  memcpy(mData + CAST_SIZE(mPos), string.c_str(), stringLength);
229 
230  // Pad remaining space with zeros
231  if (length > stringLength)
232  {
233  memset(mData + CAST_SIZE(mPos + stringLength),
234  '\0',
235  length - stringLength);
236  }
237 
238  DEBUGLOG2("writeString: ***", mPos, str);
239  mPos += length;
240 }
241 
242 const char *MessageOut::getData() const
243 {
244  return mData;
245 }
246 
247 unsigned int MessageOut::getDataSize() const
248 {
249  return mDataSize;
250 }
251 
252 unsigned char MessageOut::toServerDirection(unsigned char direction)
253 {
254  // Translate direction to eAthena format
255  switch (direction)
256  {
257  case 1: // DOWN
258  direction = 0;
259  break;
260  case 3: // DOWN | LEFT
261  direction = 1;
262  break;
263  case 2: // LEFT
264  direction = 2;
265  break;
266  case 6: // LEFT | UP
267  direction = 3;
268  break;
269  case 4: // UP
270  direction = 4;
271  break;
272  case 12: // UP | RIGHT
273  direction = 5;
274  break;
275  case 8: // RIGHT
276  direction = 6;
277  break;
278  case 9: // RIGHT + DOWN
279  direction = 7;
280  break;
281  default:
282  // OOPSIE! Impossible or unknown
283  direction = CAST_U8(-1);
284  break;
285  }
286  return direction;
287 }
288 
289 } // namespace Net
#define HIBYTE(w)
Definition: messageout.cpp:145
#define CAST_U32
Definition: cast.h:30
void writeString(const std::string &string, int length, const char *const str)
Definition: messageout.cpp:176
unsigned int mDataSize
Definition: messageout.h:132
#define CAST_U8
Definition: cast.h:26
void writeStringNoLog(const std::string &string, int length, const char *const str)
Definition: messageout.cpp:209
std::string toStringPrint(const unsigned int val)
static unsigned char toServerDirection(unsigned char direction) A_CONST
Definition: messageout.cpp:252
#define DEBUGLOG2(str, pos, comment)
Definition: logger.h:41
#define LOBYTE(w)
Definition: messageout.cpp:144
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:133
void writeInt64(const int64_t value, const char *const str)
Definition: messageout.cpp:112
unsigned int getDataSize() const
Definition: messageout.cpp:247
const char * getData() const
Definition: messageout.cpp:242
#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:147
#define nullptr
Definition: localconsts.h:44
PlayerInfoBackend mData
Definition: playerinfo.cpp:55
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
void writeFloat(const float value, const char *const str)
Definition: messageout.cpp:133
#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