GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/eathena/charserverhandler.cpp Lines: 10 112 8.9 %
Date: 2021-03-17 Branches: 0 150 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/eathena/charserverhandler.h"
25
26
#include "gui/windows/charcreatedialog.h"
27
28
#include "net/character.h"
29
#include "net/serverfeatures.h"
30
31
#include "net/ea/token.h"
32
33
#include "net/eathena/charserverrecv.h"
34
#include "net/eathena/loginhandler.h"
35
#include "net/eathena/messageout.h"
36
#include "net/eathena/network.h"
37
#include "net/eathena/protocolout.h"
38
39
#include "debug.h"
40
41
extern int packetVersion;
42
extern int serverVersion;
43
44
namespace EAthena
45
{
46
47
extern ServerInfo charServer;
48
extern ServerInfo mapServer;
49
50
77
CharServerHandler::CharServerHandler() :
51
77
    Ea::CharServerHandler()
52
{
53
77
    CharServerRecv::mNewName.clear();
54
77
    CharServerRecv::mRenameId = BeingId_zero;
55
56
77
    charServerHandler = this;
57
77
}
58
59
154
CharServerHandler::~CharServerHandler()
60
{
61
77
    charServerHandler = nullptr;
62
77
}
63
64
void CharServerHandler::chooseCharacter(Net::Character *const character) const
65
{
66
    if (character == nullptr)
67
        return;
68
69
    mSelectedCharacter = character;
70
    mCharSelectDialog = nullptr;
71
72
    createOutPacket(CMSG_CHAR_SELECT);
73
    outMsg.writeInt8(CAST_U8(
74
        mSelectedCharacter->slot), "slot");
75
}
76
77
void CharServerHandler::newCharacter(const std::string &name, const int slot,
78
                                     const GenderT gender,
79
                                     const int hairstyle, const int hairColor,
80
                                     const unsigned char race,
81
                                     const uint16_t look,
82
                                     const STD_VECTOR<int> &stats A_UNUSED)
83
                                     const
84
{
85
    createOutPacket(CMSG_CHAR_CREATE);
86
    outMsg.writeString(name, 24, "login");
87
    if (serverVersion > 0)
88
    {
89
        outMsg.writeInt8(CAST_U8(slot), "slot");
90
        outMsg.writeInt16(CAST_S16(hairColor), "hair color");
91
        outMsg.writeInt16(CAST_S16(hairstyle), "hair style");
92
        if (serverFeatures->haveRaceSelection())
93
            outMsg.writeInt16(CAST_S16(race), "race");
94
        if (serverFeatures->haveCreateCharGender())
95
        {
96
            uint8_t sex = 0;
97
            if (gender == Gender::UNSPECIFIED)
98
                sex = 99;
99
            else
100
                sex = Being::genderToInt(gender);
101
            outMsg.writeInt8(sex, "gender");
102
        }
103
        if (serverFeatures->haveLookSelection())
104
            outMsg.writeInt16(CAST_S16(look), "look");
105
    }
106
    else
107
    {
108
        if (packetVersion >= 20151001)
109
        {
110
            outMsg.writeInt8(CAST_U8(slot), "slot");
111
            outMsg.writeInt16(CAST_S16(hairColor), "hair color");
112
            outMsg.writeInt16(CAST_S16(hairstyle), "hair style");
113
            outMsg.writeInt32(CAST_S16(0), "starting job id");
114
            uint8_t sex = 0;
115
            if (gender == Gender::UNSPECIFIED)
116
                sex = 99;
117
            else
118
                sex = Being::genderToInt(gender);
119
            outMsg.writeInt8(sex, "gender");
120
        }
121
        else if (packetVersion >= 20120307)
122
        {
123
            outMsg.writeInt8(CAST_U8(slot), "slot");
124
            outMsg.writeInt16(CAST_S16(hairColor), "hair color");
125
            outMsg.writeInt16(CAST_S16(hairstyle), "hair style");
126
        }
127
        else
128
        {   // < 20120307
129
            // +++ here need send stat points
130
            // sending 5 for each stat for now
131
            for (int i = 0; i < 6; i++)
132
                outMsg.writeInt8(CAST_U8(5), "stat");
133
134
            outMsg.writeInt8(CAST_U8(slot), "slot");
135
            outMsg.writeInt16(CAST_S16(hairColor), "hair color");
136
            outMsg.writeInt16(CAST_S16(hairstyle), "hair style");
137
        }
138
    }
139
}
140
141
void CharServerHandler::deleteCharacter(Net::Character *const character,
142
                                        const std::string &email) const
143
{
144
    if (character == nullptr)
145
        return;
146
147
    mSelectedCharacter = character;
148
149
    createOutPacket(CMSG_CHAR_DELETE);
150
    outMsg.writeBeingId(mSelectedCharacter->dummy->getId(), "id?");
151
    if (email.empty())
152
        outMsg.writeString("[email protected]", 40, "email");
153
    else
154
        outMsg.writeString(email, 40, "email");
155
}
156
157
void CharServerHandler::switchCharacter() const
158
{
159
    // This is really a map-server packet
160
    createOutPacket(CMSG_PLAYER_RESTART);
161
    outMsg.writeInt8(1, "flag");
162
}
163
164
void CharServerHandler::connect() const
165
{
166
    const Token &token =
167
        static_cast<LoginHandler*>(loginHandler)->getToken();
168
169
    if (Network::mInstance == nullptr)
170
        return;
171
172
    Network::mInstance->disconnect();
173
    Network::mInstance->connect(charServer);
174
    createOutPacket(CMSG_CHAR_SERVER_CONNECT);
175
    outMsg.writeBeingId(token.account_ID, "account id");
176
    outMsg.writeInt32(token.session_ID1, "session id1");
177
    outMsg.writeInt32(token.session_ID2, "session id2");
178
    outMsg.writeInt16(CLIENT_PROTOCOL_VERSION, "client protocol version");
179
    outMsg.writeInt8(Being::genderToInt(token.sex), "gender");
180
181
    // We get 4 useless bytes before the real answer comes in (what are these?)
182
    Network::mInstance->skip(4);
183
}
184
185
void CharServerHandler::setCharCreateDialog(CharCreateDialog *const window)
186
                                            const
187
{
188
    mCharCreateDialog = window;
189
190
    if (mCharCreateDialog == nullptr)
191
        return;
192
193
    StringVect attributes;
194
195
    const Token &token = static_cast<LoginHandler*>(loginHandler)->getToken();
196
197
    mCharCreateDialog->setAttributes(attributes, 0, 0, 0);
198
    mCharCreateDialog->setDefaultGender(token.sex);
199
}
200
201
void CharServerHandler::setNewPincode(const BeingId accountId,
202
                                      const std::string &pin) const
203
{
204
    createOutPacket(CMSG_CHAR_CREATE_PIN);
205
    outMsg.writeBeingId(accountId, "account id");
206
    outMsg.writeString(pin, 4, "encrypted pin");
207
}
208
209
void CharServerHandler::sendCheckPincode(const BeingId accountId,
210
                                         const std::string &pin) const
211
{
212
    createOutPacket(CMSG_CHAR_PIN_CHECK);
213
    outMsg.writeBeingId(accountId, "account id");
214
    outMsg.writeString(pin, 4, "encrypted pin");
215
}
216
217
void CharServerHandler::changePincode(const BeingId accountId,
218
                                      const std::string &oldPin,
219
                                      const std::string &newPin) const
220
{
221
    createOutPacket(CMSG_CHAR_PIN_CHANGE);
222
    outMsg.writeBeingId(accountId, "account id");
223
    outMsg.writeString(oldPin, 4, "old encrypted pin");
224
    outMsg.writeString(newPin, 4, "new encrypted pin");
225
}
226
227
void CharServerHandler::renameCharacter(const BeingId id,
228
                                        const std::string &newName) const
229
{
230
    createOutPacket(CMSG_CHAR_CHECK_RENAME);
231
    CharServerRecv::mRenameId = id;
232
    CharServerRecv::mNewName = newName;
233
    outMsg.writeBeingId(id, "char id");
234
    outMsg.writeString(newName, 24, "name");
235
}
236
237
void CharServerHandler::changeSlot(const int oldSlot,
238
                                   const int newSlot) const
239
{
240
    createOutPacket(CMSG_CHAR_CHANGE_SLOT);
241
    outMsg.writeInt16(CAST_S16(oldSlot), "old slot");
242
    outMsg.writeInt16(CAST_S16(newSlot), "new slot");
243
    outMsg.writeInt16(0, "unused");
244
}
245
246
void CharServerHandler::ping() const
247
{
248
    createOutPacket(CMSG_CHAR_PING);
249
    outMsg.writeInt32(0, "unused");
250
}
251
252
unsigned int CharServerHandler::hatSprite() const
253
{
254
    return 7;
255
}
256
257
2
}  // namespace EAthena