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 namespace Net
44 {
45 
46 MessageOut::MessageOut(const int16_t id) :
47  mData(nullptr),
48  mDataSize(0),
49  mPos(0),
50  mId(id),
51  mIgnore(false)
52 {
55  DEBUGLOG2("Send packet", 0, "MessageOut");
56 }
57 
58 void MessageOut::writeInt8(const int8_t value, const char *const str)
59 {
60  expand(1);
61  mData[mPos] = value;
62  DEBUGLOG2("writeInt8: " + toStringPrint(CAST_U32(
63  CAST_U8(value))),
64  mPos, str);
65  mPos += 1;
66 }
67 
68 void MessageOut::writeInt16(const int16_t value, const char *const str)
69 {
70  expand(2);
71 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
72  int16_t swap = SDL_Swap16(value);
73  memcpy(mData + CAST_SIZE(mPos), &swap, sizeof(int16_t));
74 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
75 
76  memcpy(mData + CAST_SIZE(mPos), &value, sizeof(int16_t));
77 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
78 
79  DEBUGLOG2("writeInt16: " + toStringPrint(CAST_U32(
80  CAST_U16(value))),
81  mPos, str);
82  mPos += 2;
83 }
84 
85 void MessageOut::writeInt32(const int32_t value, const char *const str)
86 {
87  DEBUGLOG2("writeInt32: " + toStringPrint(CAST_U32(value)),
88  mPos, str);
89  expand(4);
90 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
91  int32_t swap = SDL_Swap32(value);
92  memcpy(mData + CAST_SIZE(mPos), &swap, sizeof(int32_t));
93 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
94 
95  memcpy(mData + CAST_SIZE(mPos), &value, sizeof(int32_t));
96 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
97 
98  mPos += 4;
99 }
100 
101 void MessageOut::writeInt64(const int64_t value, const char *const str)
102 {
103  DEBUGLOG2("writeInt64: " + toStringPrint(CAST_U32(value)),
104  mPos, str);
105  expand(8);
106 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
107  int32_t swap = SDL_Swap64(value);
108  memcpy(mData + CAST_SIZE(mPos), &swap, sizeof(int64_t));
109 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
110 
111  memcpy(mData + CAST_SIZE(mPos), &value, sizeof(int64_t));
112 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
113 
114  mPos += 8;
115 }
116 
117 void MessageOut::writeBeingId(const BeingId value, const char *const str)
118 {
119  writeInt32(toInt(value, int32_t), str);
120 }
121 
122 #define LOBYTE(w) (CAST_U8(w))
123 #define HIBYTE(w) (CAST_U8((CAST_U16(w)) >> 8))
124 
125 void MessageOut::writeCoordinates(const uint16_t x,
126  const uint16_t y,
127  unsigned char direction,
128  const char *const str)
129 {
130  DEBUGLOG2(strprintf("writeCoordinates: %u,%u %u",
131  CAST_U32(x),
132  CAST_U32(y),
133  CAST_U32(direction)), mPos, str);
134  unsigned char *const data = reinterpret_cast<unsigned char*>(mData)
135  + CAST_SIZE(mPos);
136  expand(3);
137  mPos += 3;
138 
139  uint16_t temp = x;
140  temp <<= 6;
141  data[0] = 0;
142  data[1] = 1;
143  data[2] = 2;
144  data[0] = HIBYTE(temp);
145  data[1] = CAST_U8(temp);
146  temp = y;
147  temp <<= 4;
148  data[1] |= HIBYTE(temp);
149  data[2] = LOBYTE(temp);
150  direction = toServerDirection(direction);
151  data[2] |= direction;
152 }
153 
154 void MessageOut::writeString(const std::string &string,
155  int length,
156  const char *const str)
157 {
158  int stringLength = CAST_S32(string.length());
159  if (length < 0)
160  {
161  // Write the length at the start if not fixed
162  writeInt16(CAST_S16(stringLength), "len");
163  length = stringLength;
164  }
165  else if (length < stringLength)
166  {
167  // Make sure the length of the string is no longer than specified
168  stringLength = length;
169  }
170  expand(length);
171 
172  // Write the actual string
173  memcpy(mData + CAST_SIZE(mPos), string.c_str(), stringLength);
174 
175  // Pad remaining space with zeros
176  if (length > stringLength)
177  {
178  memset(mData + CAST_SIZE(mPos + stringLength),
179  '\0',
180  length - stringLength);
181  }
182 
183  DEBUGLOG2("writeString: " + string, mPos, str);
184  mPos += length;
185 }
186 
187 void MessageOut::writeStringNoLog(const std::string &string,
188  int length,
189  const char *const str)
190 {
191  int stringLength = CAST_S32(string.length());
192  if (length < 0)
193  {
194  // Write the length at the start if not fixed
195  writeInt16(CAST_S16(stringLength), "len");
196  length = stringLength;
197  }
198  else if (length < stringLength)
199  {
200  // Make sure the length of the string is no longer than specified
201  stringLength = length;
202  }
203  expand(length);
204 
205  // Write the actual string
206  memcpy(mData + CAST_SIZE(mPos), string.c_str(), stringLength);
207 
208  // Pad remaining space with zeros
209  if (length > stringLength)
210  {
211  memset(mData + CAST_SIZE(mPos + stringLength),
212  '\0',
213  length - stringLength);
214  }
215 
216  DEBUGLOG2("writeString: ***", mPos, str);
217  mPos += length;
218 }
219 
220 const char *MessageOut::getData() const
221 {
222  return mData;
223 }
224 
225 unsigned int MessageOut::getDataSize() const
226 {
227  return mDataSize;
228 }
229 
230 unsigned char MessageOut::toServerDirection(unsigned char direction)
231 {
232  // Translate direction to eAthena format
233  switch (direction)
234  {
235  case 1: // DOWN
236  direction = 0;
237  break;
238  case 3: // DOWN | LEFT
239  direction = 1;
240  break;
241  case 2: // LEFT
242  direction = 2;
243  break;
244  case 6: // LEFT | UP
245  direction = 3;
246  break;
247  case 4: // UP
248  direction = 4;
249  break;
250  case 12: // UP | RIGHT
251  direction = 5;
252  break;
253  case 8: // RIGHT
254  direction = 6;
255  break;
256  case 9: // RIGHT + DOWN
257  direction = 7;
258  break;
259  default:
260  // OOPSIE! Impossible or unknown
261  direction = CAST_U8(-1);
262  break;
263  }
264  return direction;
265 }
266 
267 } // namespace Net
#define HIBYTE(w)
Definition: messageout.cpp:123
#define CAST_U32
Definition: cast.h:30
void writeString(const std::string &string, int length, const char *const str)
Definition: messageout.cpp:154
unsigned int mDataSize
Definition: messageout.h:126
#define CAST_U8
Definition: cast.h:26
void writeStringNoLog(const std::string &string, int length, const char *const str)
Definition: messageout.cpp:187
std::string toStringPrint(const unsigned int val)
static unsigned char toServerDirection(unsigned char direction) A_CONST
Definition: messageout.cpp:230
#define DEBUGLOG2(str, pos, comment)
Definition: logger.h:41
#define LOBYTE(w)
Definition: messageout.cpp:122
int BeingId
Definition: beingid.h:29
virtual void expand(size_t size) const =0
unsigned int mPos
Definition: messageout.h:127
void writeInt64(const int64_t value, const char *const str)
Definition: messageout.cpp:101
unsigned int getDataSize() const
Definition: messageout.cpp:225
const char * getData() const
Definition: messageout.cpp:220
#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:117
#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:68
#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:125
#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:58
MessageOut(const int16_t id)
Definition: messageout.cpp:46
#define PRAGMA48(str)
Definition: localconsts.h:190
#define CAST_SIZE
Definition: cast.h:33
#define CAST_S16
Definition: cast.h:27
void writeInt32(const int32_t value, const char *const str)
Definition: messageout.cpp:85