ManaPlus
charserverrecv.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 
24 
25 #include "client.h"
26 #include "configuration.h"
27 #include "settings.h"
28 
31 #include "gui/windows/okdialog.h"
32 
34 
35 #include "net/character.h"
36 #include "net/charserverhandler.h"
37 #include "net/playerhandler.h"
38 
39 #include "net/ea/token.h"
40 
43 #include "net/eathena/messageout.h"
44 #include "net/eathena/network.h"
46 #include "net/eathena/sprite.h"
47 
48 #include "resources/iteminfo.h"
49 
50 #include "resources/db/itemdb.h"
51 
52 #include "utils/dtor.h"
53 #include "utils/gettext.h"
54 
55 #include "debug.h"
56 
57 extern int packetVersion;
58 
59 namespace EAthena
60 {
61 
64 
65 namespace CharServerRecv
66 {
67  std::string mNewName;
68  uint32_t mPinSeed = 0;
71  bool mNeedCreatePin = false;
72 } // namespace CharServerRecv
73 
74 // callers must count each packet size by self
76  Net::Character *const character)
77 {
78  if (character == nullptr)
79  return;
80 
81  const Token &token =
82  static_cast<LoginHandler*>(loginHandler)->getToken();
83 
84  LocalPlayer *const tempPlayer = new LocalPlayer(
85  msg.readBeingId("player id"), BeingTypeId_zero);
86  tempPlayer->setGender(token.sex);
87 
88  PlayerInfoBackend &data = character->data;
89  if (packetVersion >= 20170830)
90  data.mAttributes[Attributes::PLAYER_EXP] = msg.readInt64("exp");
91  else
92  data.mAttributes[Attributes::PLAYER_EXP] = msg.readInt32("exp");
93  data.mAttributes[Attributes::MONEY] = msg.readInt32("money");
94  if (packetVersion >= 20170830)
95  {
97  msg.readInt64("job exp");
98  }
99  else
100  {
102  msg.readInt32("job exp");
103  }
105  msg.readInt32("job level");
106 
107  msg.readInt16("shoes?");
108  const int gloves = msg.readInt16("gloves");
109  const int cape = msg.readInt16("cape");
110  const int misc1 = msg.readInt16("misc1");
111 
112  msg.readInt32("option");
113  tempPlayer->setKarma(msg.readInt32("karma"));
114  tempPlayer->setManner(msg.readInt32("manner"));
115  msg.readInt16("left points");
116 
117  if (packetVersion >= 20081217)
118  {
119  data.mAttributes[Attributes::PLAYER_HP] = msg.readInt32("hp");
120  data.mAttributes[Attributes::PLAYER_MAX_HP] = msg.readInt32("max hp");
121  }
122  else
123  {
124  data.mAttributes[Attributes::PLAYER_HP] = msg.readInt16("hp");
125  data.mAttributes[Attributes::PLAYER_MAX_HP] = msg.readInt16("max hp");
126  }
127  data.mAttributes[Attributes::PLAYER_MP] = msg.readInt16("mp/sp");
128  data.mAttributes[Attributes::PLAYER_MAX_MP] = msg.readInt16("max mp/sp");
129 
130  msg.readInt16("speed");
131  const uint16_t race = msg.readInt16("class");
132 // tempPlayer->setSubtype(race, 0);
133  const int hairStyle = msg.readInt16("hair style");
134  if (packetVersion >= 20141022)
135  msg.readInt16("body");
136  const int option A_UNUSED = (msg.readInt16("weapon") | 1) ^ 1;
137  const int weapon = 0;
138 
139  tempPlayer->setSpriteId(SPRITE_BODY,
140  weapon);
141  tempPlayer->setWeaponId(weapon);
142 
144 
145  msg.readInt16("skill points");
146  const int bottomClothes = msg.readInt16("head bottom");
147  const int shield = msg.readInt16("shild");
148  const int hat = msg.readInt16("head top");
149  const int topClothes = msg.readInt16("head mid");
150 
151  const ItemColor color = fromInt(msg.readInt16("hair color"), ItemColor);
152  tempPlayer->setHairColor(color);
153  if (hairStyle == 0)
154  {
155  tempPlayer->unSetSprite(SPRITE_HAIR_COLOR);
156  }
157  else
158  {
159  tempPlayer->setSpriteColor(SPRITE_HAIR_COLOR,
160  hairStyle * -1,
161  ItemDB::get(-hairStyle).getDyeColorsString(
162  color));
163  }
164 
165  const uint16_t look = msg.readInt16("clothes color");
166  tempPlayer->setSubtype(fromInt(race, BeingTypeId), look);
167  tempPlayer->setName(msg.readString(24, "name"));
168 
169  character->dummy = tempPlayer;
170 
171  character->data.mStats[Attributes::PLAYER_STR].base = msg.readUInt8("str");
172  character->data.mStats[Attributes::PLAYER_AGI].base = msg.readUInt8("agi");
173  character->data.mStats[Attributes::PLAYER_VIT].base = msg.readUInt8("vit");
174  character->data.mStats[Attributes::PLAYER_INT].base = msg.readUInt8("int");
175  character->data.mStats[Attributes::PLAYER_DEX].base = msg.readUInt8("dex");
176  character->data.mStats[Attributes::PLAYER_LUK].base = msg.readUInt8("luk");
177 
178  character->slot = msg.readInt16("character slot id");
179  if (packetVersion >= 20061023)
180  msg.readInt16("rename");
181  if (packetVersion >= 20100803)
182  {
183  msg.readString(16, "map name");
184  msg.readInt32("delete date");
185  }
186  int shoes = 0;
187  if (packetVersion >= 20110111)
188  shoes = msg.readInt32("robe");
189  if (serverVersion == 0)
190  {
191  tempPlayer->setSpriteId(SPRITE_HAIR,
192  shoes);
193  tempPlayer->setSpriteId(SPRITE_SHOES,
194  gloves);
195  tempPlayer->setSpriteId(SPRITE_SHIELD,
196  cape);
197  tempPlayer->setSpriteId(SPRITE_HEAD_TOP,
198  misc1);
199  tempPlayer->setSpriteId(SPRITE_WEAPON,
200  bottomClothes);
201  tempPlayer->setSpriteId(SPRITE_FLOOR,
202  shield);
203  tempPlayer->setSpriteId(SPRITE_CLOTHES_COLOR,
204  hat);
205  tempPlayer->setSpriteId(SPRITE_HEAD_BOTTOM,
206  topClothes);
207 // tempPlayer->setSprite(SPRITE_HEAD_MID, misc2);
208  }
209  if (packetVersion >= 20110928)
210  msg.readInt32("slot change");
211  if (packetVersion >= 20111025)
212  tempPlayer->setRename(msg.readInt32("rename (inverse)") != 0);
213  uint8_t gender = 99U;
214  if (packetVersion >= 20141016)
215  gender = CAST_U8(msg.readUInt8("gender"));
216  if (gender != 99)
217  tempPlayer->setGender(Being::intToGender(gender));
218 }
219 
221 {
222  msg.readInt16("packet len");
223  int slots = 9;
224  int offset = 0;
225  if (packetVersion >= 20100413)
226  {
227  slots = msg.readInt8("MAX_CHARS");
228  msg.readInt8("sd->char_slots");
229  msg.readInt8("MAX_CHARS");
230  offset = 3;
231  }
233 
234  msg.skip(20, "unused 0");
235 
238 
239  // Derive number of characters from message length
240  const int count = (msg.getLength() - 24 - offset)
241  / (106 + 4 + 2 + 16 + 4 + 4 + 4 + 4);
242 
243  for (int i = 0; i < count; ++i)
244  {
245  Net::Character *const character = new Net::Character;
246  readPlayerData(msg, character);
247  Net::CharServerHandler::mCharacters.push_back(character);
248  if (character->dummy != nullptr)
249  {
250  logger->log("CharServer: Player: %s (%d)",
251  character->dummy->getName().c_str(), character->slot);
252  }
253  }
254 
256 }
257 
259 {
260  // ignored
261  msg.readInt16("len");
262  msg.readUInt8("char slots");
263  msg.readUInt8("left slots");
264  msg.readUInt8("left slots");
265  msg.readUInt8("char slots");
266  msg.readUInt8("char slots");
267  msg.skip(20, "unused");
268 }
269 
271 {
272  Network *const network = Network::mInstance;
273  ServerInfo &server = mapServer;
274  BLOCK_START("CharServerRecv::processCharMapInfo")
275  PlayerInfo::setCharId(msg.readInt32("char id"));
276  GameHandler::setMap(msg.readString(16, "map name"));
277  if (config.getBoolValue("usePersistentIP") || settings.persistentIp)
278  {
279  msg.readInt32("map ip address");
280  server.hostname = settings.serverName;
281  }
282  else
283  {
284  server.hostname = ipToString(msg.readInt32("map ip address"));
285  }
286  server.port = msg.readInt16("map ip port");
287  if (msg.getVersion() >= 20170329)
288  {
289  for (int f = 0; f < 32; f ++)
290  msg.readInt32("unused");
291  }
292 
293  // Prevent the selected local player from being deleted
298  Notify_true);
299 
301 
304 
305  if (network != nullptr)
306  network->disconnect();
308  BLOCK_END("CharServerRecv::processCharMapInfo")
309 }
310 
312 {
313  Network *const network = Network::mInstance;
314  ServerInfo &server = mapServer;
315  BLOCK_START("CharServerRecv::processChangeMapServer")
316  if (network == nullptr)
317  {
318  BLOCK_END("CharServerRecv::processChangeMapServer")
319  return;
320  }
321  GameHandler::setMap(msg.readString(16, "map name"));
322  const int x = msg.readInt16("x");
323  const int y = msg.readInt16("y");
324  if (config.getBoolValue("usePersistentIP") || settings.persistentIp)
325  {
326  msg.readInt32("host");
327  server.hostname = settings.serverName;
328  }
329  else
330  {
331  server.hostname = ipToString(msg.readInt32("host"));
332  }
333  server.port = msg.readInt16("port");
334  if (msg.getVersion() >= 20170315)
335  {
336  for (int f = 0; f < 32; f ++)
337  msg.readInt32("unknown");
338  }
339 
340  network->disconnect();
342  if (localPlayer != nullptr)
343  {
344  localPlayer->setTileCoords(x, y);
345  localPlayer->setMap(nullptr);
346  }
347  BLOCK_END("CharServerRecv::processChangeMapServer")
348 }
349 
351 {
352  mPinSeed = msg.readInt32("pincode seed");
353  mPinAccountId = msg.readBeingId("account id");
354  const uint16_t state = CAST_U16(msg.readInt16("state"));
355  switch (state)
356  {
357  case 0: // pin ok
358  break;
359  case 1: // ask for pin
360  break;
361  case 2: // create new pin
362  case 4: // create new pin?
363  {
364  mNeedCreatePin = true;
365  break;
366  }
367  case 3: // pin must be changed
368  break;
369  case 5: // client show error?
370  break;
371  case 6: // Unable to use your KSSN number
372  break;
373  case 7: // char select window shows a button
374  break;
375  case 8: // pincode was incorrect
376  break;
377  default:
379  break;
380  }
381 }
382 
384 {
385  BLOCK_START("CharServerRecv::processCharCreate")
386  Net::Character *const character = new Net::Character;
387  readPlayerData(msg, character);
388  Net::CharServerHandler::mCharacters.push_back(character);
389 
391 
392  // Close the character create dialog
395  BLOCK_END("CharServerRecv::processCharCreate")
396 }
397 
399 {
400  if (msg.readInt16("flag") != 0)
401  {
403  outMsg.writeBeingId(mRenameId, "char id");
404  }
405  else
406  {
408  // TRANSLATORS: error header
409  _("Error"),
410  // TRANSLATORS: error message
411  _("Character rename error."),
412  // TRANSLATORS: ok dialog button
413  _("Error"),
415  Modal_true,
417  nullptr,
418  260);
419  }
420 }
421 
423 {
424  const int flag = msg.readInt16("flag");
425  if (flag == 0)
426  {
428  mRenameId,
429  mNewName);
431  // TRANSLATORS: info header
432  _("Info"),
433  // TRANSLATORS: info message
434  _("Character renamed."),
435  // TRANSLATORS: ok dialog button
436  _("OK"),
438  Modal_true,
440  nullptr,
441  260);
442  }
443  else
444  {
445  std::string message;
446  switch (flag)
447  {
448  case 1:
449  // TRANSLATORS: char rename error
450  message = _("Rename not allowed.");
451  break;
452  case 2:
453  // TRANSLATORS: char rename error
454  message = _("New name is not set.");
455  break;
456  case 3:
457  default:
458  // TRANSLATORS: char rename error
459  message = _("Character rename error.");
460  break;
461  case 4:
462  // TRANSLATORS: char rename error
463  message = _("Character not found.");
464  break;
465  }
467  // TRANSLATORS: info message
468  _("Info"),
469  message,
470  // TRANSLATORS: ok dialog button
471  _("OK"),
473  Modal_true,
475  nullptr,
476  260);
477  }
478 }
479 
481 {
483  msg.readInt16("len");
484  msg.readInt16("flag"); // 0 - ok, 1 - error
485  msg.readInt16("unused");
486 }
487 
489 {
490  BLOCK_START("CharServerRecv::processCharDeleteFailed")
492  msg.readUInt8("error");
494  // TRANSLATORS: error header
495  _("Error"),
496  // TRANSLATORS: error message
497  _("Failed to delete character."),
498  // TRANSLATORS: ok dialog button
499  _("OK"),
501  Modal_true,
503  nullptr,
504  260);
505  BLOCK_END("CharServerRecv::processCharDeleteFailed")
506 }
507 
509 {
511  msg.readInt16("5");
512  msg.readUInt8("1");
513 }
514 
516 {
518  msg.readInt32("char id");
519  msg.readInt32("result");
520  // for packets before 20130000, this is raw time
521  // in other case raw time - time(NULL)
522  msg.readInt32("time");
523 }
524 
526 {
528  msg.readInt32("char id");
529  msg.readInt32("result");
530 }
531 
533 {
535  msg.readInt32("char id");
536  msg.readInt32("result");
537 }
538 
540 {
541  msg.readInt16("packet len");
542 
545 
546  // Derive number of characters from message length
547  const int count = (msg.getLength() - 4)
548  / (106 + 4 + 2 + 16 + 4 + 4 + 4 + 4);
549 
550  for (int i = 0; i < count; ++i)
551  {
552  Net::Character *const character = new Net::Character;
553  readPlayerData(msg, character);
554  Net::CharServerHandler::mCharacters.push_back(character);
555  if (character->dummy != nullptr)
556  {
557  logger->log("CharServer: Player: %s (%d)",
558  character->dummy->getName().c_str(), character->slot);
559  }
560  }
561 
563 }
564 
566 {
568  const int count = (msg.readInt16("len") - 4) / 24;
569  for (int f = 0; f < count; f ++)
570  {
571  msg.readInt32("char id");
572  msg.readString(20, "unbun time");
573  }
574 }
575 
576 } // namespace EAthena
int packetVersion
Definition: client.cpp:120
Net::PlayerHandler * playerHandler
Definition: net.cpp:89
uint16_t characterSlots
Definition: logindata.h:76
void processPincodeStatus(Net::MessageIn &msg)
virtual unsigned char readUInt8(const char *const str)
Definition: messagein.cpp:74
#define _(s)
Definition: gettext.h:34
const ItemInfo & get(const int id)
Definition: itemdb.cpp:814
#define CAST_U8
Definition: cast.h:26
std::string serverName
Definition: settings.h:112
void processChangeMapServer(Net::MessageIn &msg)
void setState(const StateT state)
Definition: client.h:65
void processCharRename(Net::MessageIn &msg)
LoginData loginData
Definition: client.cpp:181
virtual BeingId readBeingId(const char *const str)=0
std::string hostname
Definition: serverinfo.h:44
void setStatBase(const AttributesT id, const int value, const Notify notify)
Definition: playerinfo.cpp:141
void processCharCharacters(Net::MessageIn &msg)
void setTileCoords(const int x, const int y)
Definition: being.cpp:4980
#define fromInt(val, name)
Definition: intdefines.h:45
void setMap(Map *const map)
bool persistentIp
Definition: settings.h:150
static void setMap(const std::string &map)
Definition: gamehandler.cpp:45
int serverVersion
Definition: client.cpp:119
unsigned int getLength() const
Definition: messagein.h:56
#define BLOCK_START(name)
Definition: perfomance.h:78
Configuration config
virtual void setGender(const GenderT gender)
Definition: being.cpp:3554
const BeingTypeId BeingTypeId_zero
Definition: beingtypeid.h:29
int BeingId
Definition: beingid.h:29
virtual int16_t readInt16(const char *const str)=0
#define BLOCK_END(name)
Definition: perfomance.h:79
uint16_t ItemColor
Definition: itemcolor.h:29
bool msg(InputEvent &event)
Definition: chat.cpp:38
void setRename(const bool r)
Definition: localplayer.h:418
Client * client
Definition: client.cpp:113
void processCharCheckRename(Net::MessageIn &msg)
static CharCreateDialog * mCharCreateDialog
void setCharId(const int charId)
Definition: playerinfo.cpp:378
virtual signed char readInt8(const char *const str)
Definition: messagein.cpp:87
static GenderT intToGender(const uint8_t sex) A_CONST
Definition: being.h:936
Definition: token.h:29
virtual void clear() const =0
void setSpriteColor(const unsigned int slot, const int id, const std::string &color)
Definition: being.cpp:2863
void processCharDeleteFailed(Net::MessageIn &msg)
static CharSelectDialog * mCharSelectDialog
Logger * logger
Definition: logger.cpp:95
GenderT sex
Definition: token.h:43
Settings settings
Definition: settings.cpp:31
virtual int64_t readInt64(const char *const str)=0
#define CAST_U16
Definition: cast.h:28
bool getBoolValue(const std::string &key) const
void delete_all(Container &c)
Definition: dtor.h:55
uint16_t slot
Definition: character.h:57
void processCharLogin2(Net::MessageIn &msg)
Net::LoginHandler * loginHandler
Definition: net.cpp:83
void processCharChangeSlot(Net::MessageIn &msg)
void processCharCaptchaNotSupported(Net::MessageIn &msg)
void processCharDelete2AcceptActual(Net::MessageIn &msg)
uint32_t data
LocalPlayer * localPlayer
virtual void skip(const unsigned int length, const char *const str)
Definition: messagein.cpp:201
uint16_t port
Definition: serverinfo.h:57
void disconnect()
Definition: network.cpp:138
AtrIntMap mAttributes
Definition: playerinfo.h:72
const bool ShowCenter_true
Definition: showcenter.h:29
bool hat(InputEvent &event)
Definition: chat.cpp:61
const char * ipToString(const uint32_t address)
Definition: stringutils.cpp:85
void setSpriteId(const unsigned int slot, const int id)
Definition: being.cpp:2762
unsigned int getVersion() const
Definition: messagein.h:127
static Network * mInstance
Definition: network.h:56
void setManner(const int manner)
Definition: being.h:1034
const std::string & getName() const
Definition: being.h:231
#define createOutPacket(name)
Definition: messageout.h:36
ServerInfo mapServer
void processCharMapInfo(Net::MessageIn &msg)
virtual void scheduleDelete()
Definition: window.cpp:826
void setName(const BeingId id, const std::string &newName)
#define A_UNUSED
Definition: localconsts.h:171
void setSubtype(const BeingTypeId subtype, const uint16_t look)
Definition: being.cpp:369
void setKarma(const int karma)
Definition: being.h:1028
#define CREATEWIDGET(type,...)
Definition: createwidget.h:28
void readPlayerData(Net::MessageIn &msg, Net::Character *const character)
static void updateCharSelectDialog()
int CMSG_CHAR_RENAME
Definition: protocolout.cpp:55
void processCharBanCharList(Net::MessageIn &msg)
void setName(const std::string &name)
Definition: being.cpp:1134
void processCharDelete2Ack(Net::MessageIn &msg)
static Net::Characters mCharacters
static Net::Character * mSelectedCharacter
void processCharCreate(Net::MessageIn &msg)
virtual int32_t readInt32(const char *const str)=0
#define restrict
Definition: localconsts.h:176
virtual std::string readString(int length, const char *const dstr)
Definition: messagein.cpp:219
#define UNIMPLEMENTEDPACKET
Definition: logger.h:55
const BeingId BeingId_zero
Definition: beingid.h:29
void setBackend(const PlayerInfoBackend &backend)
Definition: playerinfo.cpp:373
PlayerInfoBackend data
Definition: character.h:56
void setHairColor(const unsigned int slot, const ItemColor color)
Definition: being.cpp:3362
void log(const char *const log_text,...)
Definition: logger.cpp:243
void processCharDelete2CancelAck(Net::MessageIn &msg)
int BeingTypeId
Definition: beingtypeid.h:29
Net::CharServerHandler * charServerHandler
Definition: net.cpp:79
void setWeaponId(const int id)
Definition: being.cpp:3108
void processCharLogin(Net::MessageIn &msg)
ServerInfo charServer
LocalPlayer * dummy
Definition: character.h:55
void unSetSprite(const unsigned int slot)
Definition: being.cpp:2834
static void unlockCharSelectDialog()
const bool Notify_true
Definition: notify.h:29
virtual int getDefaultWalkSpeed() const =0