Mana
Loading...
Searching...
No Matches
charhandler.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-2013 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 "localplayer.h"
26#include "log.h"
27
29#include "gui/okdialog.h"
30
32#include "net/loginhandler.h"
33#include "net/net.h"
34
41
43#include "resources/hairdb.h"
44
45#include "utils/dtor.h"
46#include "utils/gettext.h"
47#include "utils/stringutils.h"
48
51
52namespace ManaServ {
53
54extern Connection *accountServerConnection;
57extern std::string netToken;
60
62{
63 static const Uint16 _messages[] = {
68 0
69 };
70 handledMessages = _messages;
71 charHandler = this;
72}
73
78
80{
81 switch (msg.getId())
82 {
85 break;
86
89 break;
90
91 case APMSG_CHAR_INFO:
93 break;
94
97 break;
98 }
99}
100
102{
103 while (msg.getUnreadLength() > 0)
104 {
105 CachedCharacterInfo &info = mCachedCharacterInfos.emplace_back();
106
107 info.slot = msg.readInt8();
108 info.name = msg.readString();
109 info.gender = getGender(msg.readInt8());
110 info.hairStyle = msg.readInt8();
111 info.hairColor = msg.readInt8();
112 info.characterPoints = msg.readInt16();
113 info.correctionPoints = msg.readInt16();
114
115 int equipmentCount = msg.readInt8();
116 while (equipmentCount--)
117 {
118 auto &slot = info.equipment.emplace_back();
119 slot.id = msg.readInt16();
120 slot.itemId = msg.readInt16();
121 }
122
123 int attributeCount = msg.readInt8();
124 while (attributeCount--)
125 {
126 CachedAttribute &attr = info.attributes[msg.readInt32()];
127 attr.base = msg.readInt32() / 256.0;
128 attr.mod = msg.readInt32() / 256.0;
129 }
130 }
131
133}
134
136{
137 const int errMsg = msg.readInt8();
138
139 if (errMsg != ERRMSG_OK)
140 {
141 // Character creation failed
142 std::string errorMessage;
143 switch (errMsg)
144 {
145 case ERRMSG_NO_LOGIN:
146 errorMessage = _("Not logged in.");
147 break;
149 errorMessage = _("No empty slot.");
150 break;
152 errorMessage = _("Invalid name.");
153 break;
155 errorMessage = _("Character's name already exists.");
156 break;
158 errorMessage = _("Invalid hairstyle.");
159 break;
161 errorMessage = _("Invalid hair color.");
162 break;
164 errorMessage = _("Invalid gender.");
165 break;
167 errorMessage = _("Character's stats are too high.");
168 break;
170 errorMessage = _("Character's stats are too low.");
171 break;
173 errorMessage = strprintf( _("At least one stat "
174 "is out of the permitted range: (%u - %u)."),
177 break;
179 errorMessage = _("Invalid slot number.");
180 break;
181 default:
182 errorMessage = _("Unknown error.");
183 break;
184 }
185 new OkDialog(_("Error"), errorMessage);
186
189 }
190 else
191 {
193
194 // Close the character create dialog
196 {
198 mCharCreateDialog = nullptr;
199 }
200 }
201}
202
204{
205 int errMsg = msg.readInt8();
206 if (errMsg == ERRMSG_OK)
207 {
208 // Character deletion successful
209 for (unsigned i = 0; i < mCachedCharacterInfos.size(); ++i)
210 {
212 {
214 break;
215 }
216 }
217 delete mSelectedCharacter;
220 new OkDialog(_("Info"), _("Player deleted."));
221 }
222 else
223 {
224 // Character deletion failed
225 std::string errorMessage;
226 switch (errMsg)
227 {
228 case ERRMSG_NO_LOGIN:
229 errorMessage = _("Not logged in.");
230 break;
232 errorMessage = _("Selection out of range.");
233 break;
234 default:
235 errorMessage = strprintf(_("Unknown error (%d)."), errMsg);
236 }
237 new OkDialog(_("Error"), errorMessage);
238 }
239 mSelectedCharacter = nullptr;
241}
242
244{
245 int errMsg = msg.readInt8();
246
247 if (errMsg == ERRMSG_OK)
248 {
249 netToken = msg.readString(32);
250
251 gameServer.hostname.assign(msg.readString());
252 gameServer.port = msg.readInt16();
253
254 chatServer.hostname.assign(msg.readString());
255 chatServer.port = msg.readInt16();
256
257 Log::info("Game server: %s:%d", gameServer.hostname.c_str(),
259 Log::info("Chat server: %s:%d", chatServer.hostname.c_str(),
261
262 // Prevent the selected local player from being deleted
265 mSelectedCharacter->dummy = nullptr;
266
268 }
269 else
270 {
271 switch (errMsg)
272 {
273 case ERRMSG_FAILURE:
274 errorMessage = _("No gameservers are available.");
275 break;
277 errorMessage = _("Invalid character slot selected.");
278 break;
279 default:
280 errorMessage = strprintf(_("Unhandled character select "
281 "error message %i."), errMsg);
282 }
284 mCharacters.clear();
286 }
287}
288
294
307
309{
311 {
313 }
314 else
315 {
316 // The characters are already there, continue to character selection
318 }
319}
320
329
330void CharHandler::newCharacter(const std::string &name,
331 int slot,
332 Gender gender,
333 int hairstyle,
334 int hairColor,
335 const std::vector<int> &stats)
336{
338
339 msg.writeString(name);
340 msg.writeInt8(hairstyle);
341 msg.writeInt8(hairColor);
342 msg.writeInt8(gender == Gender::Female);
343 msg.writeInt8(slot);
344
345 for (int stat : stats)
346 msg.writeInt16(stat);
347
349}
350
359
361{
362 gameHandler->quit(true);
363}
364
365unsigned int CharHandler::baseSprite() const
366{
367 return SPRITE_LAYER_BASE;
368}
369
370unsigned int CharHandler::hairSprite() const
371{
372 return SPRITE_LAYER_HAIR;
373}
374
375unsigned int CharHandler::maxSprite() const
376{
377 static unsigned int visibleSlots = FIXED_SPRITE_LAYER_SIZE
379 return visibleSlots;
380}
381
383{
384 // Delete previous characters
386 mCharacters.clear();
387
389 return;
390
391 // Create new characters and initialize them from the cached infos
392 for (const auto &info : mCachedCharacterInfos)
393 {
394 auto *character = new Net::Character;
395 character->slot = info.slot;
396 LocalPlayer *player = character->dummy = new LocalPlayer;
397 player->setName(info.name);
398 player->setGender(info.gender);
399 player->setSprite(SPRITE_LAYER_HAIR, info.hairStyle * -1,
400 hairDB.getHairColor(info.hairColor));
401
402 for (auto &slot : info.equipment)
403 {
404 player->setSprite(slot.id + FIXED_SPRITE_LAYER_SIZE,
405 slot.itemId,
406 std::string(),
408 }
409
410 character->data.mAttributes[CHAR_POINTS] = info.characterPoints;
411 character->data.mAttributes[CORR_POINTS] = info.correctionPoints;
412
413 for (const auto &[id, attr] : info.attributes)
414 {
415 int playerInfoId = Attributes::getPlayerInfoIdFromAttrId(id);
416 if (playerInfoId > -1)
417 {
418 character->data.mAttributes[playerInfoId] = attr.mod;
419 }
420 else
421 {
422 character->data.mStats[id].base = attr.base;
423 character->data.mStats[id].mod = attr.mod;
424 }
425 }
426
427 mCharacters.push_back(character);
428 }
429
431}
432
434{
435 setCharCreateDialog(nullptr);
436 setCharSelectDialog(nullptr);
437
438 mCachedCharacterInfos.clear();
440}
441
442} // namespace ManaServ
Gender
Definition being.h:58
void setSprite(unsigned slot, int id, const std::string &color=std::string(), bool isWeapon=false)
Sets visible equipments for this being.
Definition being.cpp:1254
void setName(const std::string &name)
Sets the name for the being.
Definition being.cpp:463
void setGender(Gender gender)
Sets the gender of this being.
Definition being.cpp:1313
Character creation dialog.
void setAttributes(const std::vector< std::string > &labels, unsigned available, unsigned min, unsigned max)
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
unsigned int hairSprite() const override
void newCharacter(const std::string &name, int slot, Gender gender, int hairstyle, int hairColor, const std::vector< int > &stats) override
void deleteCharacter(Net::Character *character) override
void handleCharacterCreateResponse(MessageIn &msg)
unsigned int baseSprite() const override
unsigned int maxSprite() const override
void requestCharacters() override
void handleMessage(MessageIn &msg) override
void handleCharacterInfo(MessageIn &msg)
void switchCharacter() override
void setCharSelectDialog(CharSelectDialog *window) override
void handleCharacterDeleteResponse(MessageIn &msg)
void setCharCreateDialog(CharCreateDialog *window) override
Sets the character create dialog.
void handleCharacterSelectResponse(MessageIn &msg)
void chooseCharacter(Net::Character *character) override
std::vector< CachedCharacterInfo > mCachedCharacterInfos
Cached character information.
bool isConnected()
Returns whether the server is connected.
void send(const ManaServ::MessageOut &msg)
Sends a message.
void quit(bool reconnectAccount)
Used for parsing an incoming message from manaserv.
Definition messagein.h:37
uint16_t readInt16()
Reads an unsigned 16-bit integer from the message.
Definition messagein.cpp:58
unsigned int getUnreadLength() const
Returns the length of unread data.
Definition messagein.h:54
std::string readString(int length=-1)
Reads a string.
Definition messagein.cpp:92
uint16_t getId() const
Returns the message ID.
Definition messagein.h:44
uint32_t readInt32()
Reads an unsigned 32-bit integer from the message.
Definition messagein.cpp:75
uint8_t readInt8()
Reads an unsigned 8-bit integer from the message.
Definition messagein.cpp:43
Used for building an outgoing message to manaserv.
Definition messageout.h:37
void writeInt16(uint16_t value)
Writes an unsigned 16-bit integer to the message.
void writeInt8(uint8_t value)
Writes an unsigned 8-bit integer to the message.
void writeString(const std::string &string, int length=-1)
Writes a string.
CharSelectDialog * mCharSelectDialog
Net::Characters mCharacters
The list of available characters.
Net::Character * mSelectedCharacter
The selected character.
void unlockCharSelectDialog()
CharCreateDialog * mCharCreateDialog
void updateCharSelectDialog()
virtual unsigned int getVisibleSlotsNumber() const
virtual bool isWeaponSlot(unsigned int slotTypeId) const =0
virtual void connect()=0
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
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_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
ManaServ::GameHandler * gameHandler
Definition net.cpp:52
unsigned int getAttributeMaximum()
Give the maximum attribute point possible at character's creation.
std::vector< std::string > & getLabels()
Returns the list of base attribute labels.
unsigned int getCreationPoints()
Give the attribute points given to a character at its creation.
int getPlayerInfoIdFromAttrId(int attrId)
Give back the corresponding playerinfo Id from the attribute id defined in the xml file.
unsigned int getAttributeMinimum()
Give the minimum attribute point possible at character's creation.
void info(const char *log_text,...) LOG_PRINTF_ATTR
ServerInfo gameServer
@ SPRITE_LAYER_HAIR
@ SPRITE_LAYER_BASE
@ FIXED_SPRITE_LAYER_SIZE
@ CREATE_ATTRIBUTES_OUT_OF_RANGE
Connection * gameServerConnection
std::string netToken
Connection * chatServerConnection
Connection * accountServerConnection
Gender getGender(int gender)
Helper function for getting gender by int.
ServerInfo chatServer
@ APMSG_CHAR_CREATE_RESPONSE
@ APMSG_CHAR_SELECT_RESPONSE
@ APMSG_CHAR_DELETE_RESPONSE
LoginHandler * getLoginHandler()
Definition net.cpp:95
InventoryHandler * getInventoryHandler()
Definition net.cpp:90
void setBackend(const PlayerInfoBackend &backend)
Changes the internal PlayerInfoBackend reference;.
@ CORR_POINTS
Definition playerinfo.h:37
@ CHAR_POINTS
Definition playerinfo.h:37
std::string strprintf(char const *format,...)
A safe version of sprintf that returns a std::string of the result.
Character information needs to be cached since we receive it before we have loaded the dynamic data,...
Definition charhandler.h:91
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