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