GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/messageout.cpp Lines: 0 92 0.0 %
Date: 2021-03-17 Branches: 0 82 0.0 %

Line Branch Exec Source
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
{
56
    PacketCounters::incOutPackets();
57
    IGNOREDEBUGLOG;
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