Mana
Loading...
Searching...
No Matches
charserverhandler.cpp
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2004-2009 The Mana World Development Team
4 * Copyright (C) 2009-2012 The Mana Developers
5 *
6 * This file is part of The Mana Client.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
23
24#include "client.h"
25#include "game.h"
26#include "log.h"
27
29#include "gui/okdialog.h"
30
31#include "net/net.h"
32
35#include "net/tmwa/messagein.h"
36#include "net/tmwa/messageout.h"
37#include "net/tmwa/network.h"
38#include "net/tmwa/protocol.h"
39#include "net/tmwa/token.h"
40
42#include "resources/chardb.h"
43#include "resources/hairdb.h"
44
45#include "utils/dtor.h"
46#include "utils/gettext.h"
47#include "utils/stringutils.h"
48
50
51namespace TmwAthena {
52
55
72
74{
75 switch (msg.getId())
76 {
77 case SMSG_CHAR_LOGIN:
78 {
79 msg.skip(2); // Length word
80 msg.skip(20); // Unused
81
83 mCharacters.clear();
84
85 // Derive number of characters from message length
86 const int count = (msg.getLength() - 24) / 106;
87
88 for (int i = 0; i < count; ++i)
89 {
90 auto *character = new Net::Character;
91 readPlayerData(msg, character);
92 mCharacters.push_back(character);
93 Log::info("CharServer: Player: %s (%d)",
94 character->dummy->getName().c_str(), character->slot);
95 }
96
98 }
99 break;
100
102 switch (msg.readInt8())
103 {
104 case 0:
105 errorMessage = _("Access denied. Most likely, there are "
106 "too many players on this server.");
107 break;
108 case 1:
109 errorMessage = _("Cannot use this ID.");
110 break;
111 default:
112 errorMessage = _("Unknown char-server failure.");
113 break;
114 }
116 break;
117
119 {
120 auto *character = new Net::Character;
121 readPlayerData(msg, character);
122 mCharacters.push_back(character);
123
125
126 // Close the character create dialog
128 {
130 mCharCreateDialog = nullptr;
131 }
132 }
133 break;
134
136 new OkDialog(_("Error"), _("Failed to create character. Most "
137 "likely the name is already taken."));
140 break;
141
143 delete mSelectedCharacter;
145 mSelectedCharacter = nullptr;
148 new OkDialog(_("Info"), _("Character deleted."));
149 break;
150
153 new OkDialog(_("Error"), _("Failed to delete character."));
154 break;
155
157 {
158 msg.skip(4); // CharID, must be the same as local_player->charID
159 auto *gh = static_cast<GameHandler*>(Net::getGameHandler());
160 gh->setMap(msg.readString(16));
161
162 const auto ip = msg.readInt32();
163
166 else
168
169 mapServer.port = msg.readInt16();
170
173
174 // Prevent the selected local player from being deleted
175 mSelectedCharacter->dummy = nullptr;
176
178 mCharacters.clear();
180
183 }
184 break;
185
187 {
188 auto *gh = static_cast<GameHandler*>(Net::getGameHandler());
189 gh->setMap(msg.readString(16));
190 int x = msg.readInt16();
191 int y = msg.readInt16();
193 mapServer.port = msg.readInt16();
194
197 Map *map = local_player->getMap();
198 const int tileWidth = map->getTileWidth();
199 const int tileHeight = map->getTileHeight();
200 local_player->setPosition(Vector(x * tileWidth + tileWidth / 2,
201 y * tileHeight + tileHeight / 2));
202 local_player->setMap(nullptr);
203 }
204 break;
205 }
206}
207
209{
210 const int id = msg.readInt32();
211
212 character->data.mAttributes[EXP] = msg.readInt32();
213 character->data.mAttributes[MONEY] = msg.readInt32();
214 character->data.mStats[JOB].exp = msg.readInt32();
215
216 const int temp = msg.readInt32();
217 character->data.mStats[JOB].base = temp;
218 character->data.mStats[JOB].mod = temp;
219
220 const int shoe = msg.readInt16();
221 const int gloves = msg.readInt16();
222 const int cape = msg.readInt16();
223 const int misc1 = msg.readInt16();
224
225 msg.readInt32(); // option
226 msg.readInt32(); // karma
227 msg.readInt32(); // manner
228 msg.readInt16(); // character points left
229
230 character->data.mAttributes[HP] = msg.readInt16();
231 character->data.mAttributes[MAX_HP] = msg.readInt16();
232 character->data.mAttributes[MP] = msg.readInt16();
233 character->data.mAttributes[MAX_MP] = msg.readInt16();
234
235 msg.readInt16(); // speed
236 const uint16_t race = msg.readInt16(); // class (used for race)
237 int hairStyle = msg.readInt8();
238 msg.readInt8(); // look
239 const uint16_t weapon = msg.readInt16();
240
241 auto *tempPlayer = new LocalPlayer(id, race);
242
243 tempPlayer->setSprite(SPRITE_SHOE, shoe);
244 tempPlayer->setSprite(SPRITE_GLOVES, gloves);
245 tempPlayer->setSprite(SPRITE_CAPE, cape);
246 tempPlayer->setSprite(SPRITE_MISC1, misc1);
247 tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", true);
248
249 character->data.mAttributes[LEVEL] = msg.readInt16();
250
251 msg.readInt16(); // skill point
252 tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, msg.readInt16()); // head bottom
253 tempPlayer->setSprite(SPRITE_SHIELD, msg.readInt16());
254 tempPlayer->setSprite(SPRITE_HAT, msg.readInt16()); // head option top
255 tempPlayer->setSprite(SPRITE_TOPCLOTHES, msg.readInt16()); // head option mid
256 tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1,
258 tempPlayer->setSprite(SPRITE_MISC2, msg.readInt16());
259 tempPlayer->setName(msg.readString(24));
260
261 character->dummy = tempPlayer;
262
263 for (int i = 0; i < 6; i++)
264 character->data.mStats[i + STRENGTH].base = msg.readInt8();
265
266 character->slot = msg.readInt8(); // character slot
267 tempPlayer->setGender(sexToGender(static_cast<SEX>(msg.readInt8())));
268}
269
275
277{
278 mCharCreateDialog = window;
279
281 return;
282
283 std::vector<std::string> attributes;
284 attributes.emplace_back(_("Strength:"));
285 attributes.emplace_back(_("Agility:"));
286 attributes.emplace_back(_("Vitality:"));
287 attributes.emplace_back(_("Intelligence:"));
288 attributes.emplace_back(_("Dexterity:"));
289 attributes.emplace_back(_("Luck:"));
290
291 const Token &token =
292 static_cast<LoginHandler*>(Net::getLoginHandler())->getToken();
293
294 unsigned minStat = CharDB::getMinStat();
295 if (minStat == 0)
297 unsigned maxStat = CharDB::getMaxStat();
298 if (maxStat == 0)
300 unsigned sumStat = CharDB::getSumStat();
301 if (sumStat == 0)
303
304 mCharCreateDialog->setAttributes(attributes, sumStat, minStat, maxStat);
305
306 if (token.sex != SEX::UNSPECIFIED)
308}
309
314
316{
317 mSelectedCharacter = character;
318 mCharSelectDialog = nullptr;
319
322}
323
324void CharServerHandler::newCharacter(const std::string &name, int slot,
325 Gender /*gender*/, int hairstyle, int hairColor,
326 const std::vector<int> &stats)
327{
329 outMsg.writeString(name, 24);
330 for (int i = 0; i < 6; i++)
331 {
332 outMsg.writeInt8(stats[i]);
333 }
334 outMsg.writeInt8(slot);
335 outMsg.writeInt16(hairColor);
336 outMsg.writeInt16(hairstyle);
337}
338
340{
341 mSelectedCharacter = character;
342
345 outMsg.writeString("a@a.com", 40);
346}
347
349{
350 // This is really a map-server packet
352 outMsg.writeInt8(1);
353}
354
356{
357 return SPRITE_BASE;
358}
359
361{
362 return SPRITE_HAIR;
363}
364
366{
367 return SPRITE_VECTOREND;
368}
369
374
376{
377 const int max = CharDB::getMaxHairColor();
378 return max ? max : 11; // default maximum
379}
380
382{
383 const int max = CharDB::getMaxHairStyle();
384 return max ? max : 19; // default maximum
385}
386
388{
389 const Token &token =
390 static_cast<LoginHandler*>(Net::getLoginHandler())->getToken();
391
395 outMsg.writeInt32(token.account_ID);
396 outMsg.writeInt32(token.session_ID1);
397 outMsg.writeInt32(token.session_ID2);
398 // [Fate] The next word is unused by the old char server, so we squeeze in
399 // mana client version information
401 outMsg.writeInt8(static_cast<uint8_t>(token.sex));
402
403 // We get 4 useless bytes before the real answer comes in (what are these?)
404 mNetwork->skip(4);
405}
406
407} // namespace TmwAthena
Gender
Definition being.h:58
Net::CharHandler * charHandler
Definition net.cpp:47
int getId() const
Definition actorsprite.h:63
Map * getMap() const
Definition actor.h:109
void setPosition(const Vector &pos) final
Sets the pixel position of this actor.
Definition being.cpp:187
void setMap(Map *map) final
Definition being.cpp:1398
Character creation dialog.
void setAttributes(const std::vector< std::string > &labels, unsigned available, unsigned min, unsigned max)
void setDefaultGender(Gender gender)
void unlock()
Unlocks the dialog, enabling the create character button again.
Character selection dialog.
static void setState(State state)
Definition client.h:169
const std::string & getHairColor(int id) const
Definition hairdb.cpp:79
The local player character.
Definition localplayer.h:75
A tile map.
Definition map.h:147
int getTileHeight() const
Returns the tile height used by this map.
Definition map.h:271
int getTileWidth() const
Returns the tile width of this map.
Definition map.h:265
CharSelectDialog * mCharSelectDialog
Net::Characters mCharacters
The list of available characters.
Net::Character * mSelectedCharacter
The selected character.
void unlockCharSelectDialog()
CharCreateDialog * mCharCreateDialog
void updateCharSelectDialog()
const uint16_t * handledMessages
An 'Ok' button dialog.
Definition okdialog.h:34
std::string hostname
Definition serverinfo.h:42
uint16_t port
Definition serverinfo.h:43
bool persistentIp
Definition serverinfo.h:49
int getCharCreateMaxHairStyleId() const override
Returns the max permitted hair style Id at character creation time, or 0 if no limit should be applie...
void deleteCharacter(Net::Character *character) override
unsigned int baseSprite() const override
static void readPlayerData(MessageIn &msg, Net::Character *character)
void setCharSelectDialog(CharSelectDialog *window) override
void newCharacter(const std::string &name, int slot, Gender gender, int hairstyle, int hairColor, const std::vector< int > &stats) override
int getCharCreateMaxHairColorId() const override
Returns the max permitted hair color Id at character creation time, or 0 if no limit should be applie...
unsigned int hairSprite() const override
void setCharCreateDialog(CharCreateDialog *window) override
Sets the character create dialog.
int getCharCreateMinHairColorId() const override
Returns the min permitted hair color Id at character creation time, or 0 if there is no minimum.
unsigned int maxSprite() const override
void chooseCharacter(Net::Character *character) override
void handleMessage(MessageIn &msg) override
void setMap(const std::string &map)
Used for parsing an incoming message from eAthena.
Definition messagein.h:35
std::string readString(int length=-1)
Reads a string.
void skip(unsigned int length)
Skips a given number of bytes.
uint16_t readInt16()
Reads an unsigned 16-bit integer from the message.
Definition messagein.cpp:57
uint8_t readInt8()
Reads an unsigned 8-bit integer from the message.
Definition messagein.cpp:46
uint16_t getId() const
Returns the message ID.
Definition messagein.h:42
uint32_t readInt32()
Reads an unsigned 32-bit integer from the message.
Definition messagein.cpp:69
unsigned int getLength() const
Returns the message length.
Definition messagein.h:47
Used for building an outgoing message to eAthena.
Definition messageout.h:35
void writeInt32(uint32_t value)
Writes an unsigned 32-bit integer to the message.
void writeInt8(uint8_t value)
Writes an unsigned 8-bit integer to the message.
void writeInt16(uint16_t value)
Writes an unsigned 16-bit integer to the message.
void writeString(const std::string &string, int length=-1)
Writes a string.
bool connect(const ServerInfo &server)
Definition network.cpp:278
void skip(int len)
Definition network.cpp:445
Vector class.
Definition vector.h:33
void scheduleDelete()
Schedule this window for deletion.
Definition window.cpp:299
HairDB hairDB
Hair styles and colors info database.
Definition client.cpp:107
std::string errorMessage
Definition client.cpp:94
@ STATE_CONNECT_GAME
Definition client.h:72
@ STATE_CHANGE_MAP
Definition client.h:74
@ STATE_CHAR_SELECT
Definition client.h:71
@ STATE_ERROR
Definition client.h:60
void delete_all(Container &c)
Definition dtor.h:46
#define _(s)
Definition gettext.h:38
LocalPlayer * local_player
Net::CharHandler * charHandler
Definition net.cpp:47
unsigned int getAttributeMaximum()
Give the maximum attribute point possible at character's creation.
unsigned int getCreationPoints()
Give the attribute points given to a character at its creation.
unsigned int getAttributeMinimum()
Give the minimum attribute point possible at character's creation.
unsigned getSumStat()
Definition chardb.cpp:124
unsigned getMinStat()
Definition chardb.cpp:114
unsigned getMaxHairStyle()
Definition chardb.cpp:109
unsigned getMaxStat()
Definition chardb.cpp:119
unsigned getMaxHairColor()
Definition chardb.cpp:99
unsigned getMinHairColor()
Definition chardb.cpp:94
void info(const char *log_text,...) LOG_PRINTF_ATTR
LoginHandler * getLoginHandler()
Definition net.cpp:95
GameHandler * getGameHandler()
Definition net.cpp:75
void setBackend(const PlayerInfoBackend &backend)
Changes the internal PlayerInfoBackend reference;.
Warning: buffers and other variables are shared, so there can be only one connection active at a time...
ServerInfo mapServer
@ SPRITE_GLOVES
Definition protocol.h:60
@ SPRITE_BASE
Definition protocol.h:51
@ SPRITE_BOTTOMCLOTHES
Definition protocol.h:53
@ SPRITE_WEAPON
Definition protocol.h:61
@ SPRITE_MISC1
Definition protocol.h:55
@ SPRITE_SHOE
Definition protocol.h:52
@ SPRITE_HAT
Definition protocol.h:58
@ SPRITE_VECTOREND
Definition protocol.h:63
@ SPRITE_HAIR
Definition protocol.h:57
@ SPRITE_MISC2
Definition protocol.h:56
@ SPRITE_SHIELD
Definition protocol.h:62
@ SPRITE_CAPE
Definition protocol.h:59
@ SPRITE_TOPCLOTHES
Definition protocol.h:54
ServerInfo charServer
@ CMSG_CHAR_CREATE
Definition protocol.h:148
@ CMSG_CHAR_DELETE
Definition protocol.h:149
@ CMSG_PLAYER_REBOOT
Definition protocol.h:204
@ SMSG_CHAR_DELETE_SUCCEEDED
Definition protocol.h:154
@ CMSG_CHAR_SELECT
Definition protocol.h:147
@ SMSG_CHAR_CREATE_SUCCEEDED
Definition protocol.h:152
@ SMSG_CHAR_DELETE_FAILED
Definition protocol.h:155
@ SMSG_CHAR_LOGIN_ERROR
Definition protocol.h:151
@ SMSG_CHAR_CREATE_FAILED
Definition protocol.h:153
@ SMSG_CHANGE_MAP_SERVER
Definition protocol.h:178
@ SMSG_CHAR_LOGIN
Definition protocol.h:150
@ CMSG_CHAR_SERVER_CONNECT
Definition protocol.h:146
@ SMSG_CHAR_MAP_INFO
Definition protocol.h:156
Gender sexToGender(SEX sex)
Definition protocol.h:106
@ EXP
Definition playerinfo.h:33
@ HP
Definition playerinfo.h:31
@ MAX_HP
Definition playerinfo.h:31
@ LEVEL
Definition playerinfo.h:30
@ MP
Definition playerinfo.h:32
@ MAX_MP
Definition playerinfo.h:32
@ MONEY
Definition playerinfo.h:34
unsigned char uint8_t
Definition sha256.cpp:81
const char * ipToString(int address)
Converts the given IP address to a string.
A structure to hold information about a character.
Definition charhandler.h:38
LocalPlayer * dummy
A dummy representing this character.
Definition charhandler.h:45
PlayerInfoBackend data
Definition charhandler.h:46
int slot
The index in the list of characters.
Definition charhandler.h:44
std::map< int, Stat > mStats
Definition playerinfo.h:57
std::map< int, int > mAttributes
Definition playerinfo.h:56
int session_ID1
Definition token.h:31
int session_ID2
Definition token.h:32
#define CLIENT_PROTOCOL_VERSION
Protocol version, reported to the eAthena char and mapserver who can adjust the protocol accordingly.
Definition network.h:42