ManaPlus
playerrecv.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 
23 #include "net/eathena/playerrecv.h"
24 
25 #include "actormanager.h"
26 #include "configuration.h"
27 #include "notifymanager.h"
28 #include "party.h"
29 
30 #include "being/beingflag.h"
31 #include "being/localplayer.h"
32 #include "being/playerinfo.h"
33 
34 #include "const/net/nostat.h"
35 
37 
38 #include "gui/onlineplayer.h"
39 
42 
44 
45 #include "net/eathena/sp.h"
46 #include "net/playerhandler.h"
47 
48 #include "utils/gettext.h"
49 
50 #include "debug.h"
51 
52 namespace EAthena
53 {
54 
56 {
57  // +++ player shortcuts ignored. It also disabled on server side.
58  // may be in future better use it?
59  if (msg.getVersion() >= 20141022)
60  msg.readUInt8("rotate");
61  for (int f = 0; f < 27; f ++)
62  {
63  msg.readUInt8("type 0: item, 1: skill");
64  msg.readInt32("item or skill id");
65  msg.readInt16("skill level");
66  }
67  msg.skip(77, "unused");
68 }
69 
71 {
72  // +++ for now server allow only switch this option but not using it.
73  msg.readUInt8("show equip"); // 1 mean need open "equipment" window
74 }
75 
77 {
78  BLOCK_START("PlayerRecv::processPlayerStatUpdate5")
80  msg.readInt16("char points"),
81  Notify_true);
82 
83  unsigned int val = msg.readUInt8("str");
85  val,
86  Notify_true);
87  if (statusWindow != nullptr)
88  {
90  msg.readUInt8("str cost"));
91  }
92  else
93  {
94  msg.readUInt8("str need");
95  }
96 
97  val = msg.readUInt8("agi");
99  if (statusWindow != nullptr)
100  {
102  msg.readUInt8("agi cost"));
103  }
104  else
105  {
106  msg.readUInt8("agi cost");
107  }
108 
109  val = msg.readUInt8("vit");
111  if (statusWindow != nullptr)
112  {
114  msg.readUInt8("vit cost"));
115  }
116  else
117  {
118  msg.readUInt8("vit cost");
119  }
120 
121  val = msg.readUInt8("int");
123  if (statusWindow != nullptr)
124  {
126  msg.readUInt8("int cost"));
127  }
128  else
129  {
130  msg.readUInt8("int cost");
131  }
132 
133  val = msg.readUInt8("dex");
135  if (statusWindow != nullptr)
136  {
138  msg.readUInt8("dex cost"));
139  }
140  else
141  {
142  msg.readUInt8("dex cost");
143  }
144 
145  val = msg.readUInt8("luk");
147  if (statusWindow != nullptr)
148  {
150  msg.readUInt8("luk cost"));
151  }
152  else
153  {
154  msg.readUInt8("luk cost");
155  }
156 
158  msg.readInt16("left atk"),
159  Notify_false);
161  msg.readInt16("right atk"),
162  Notify_true);
164 
165  val = msg.readInt16("right matk");
167 
168  val = msg.readInt16("left matk");
170  val,
171  Notify_true);
172 
174  msg.readInt16("left def"),
175  Notify_false);
177  msg.readInt16("right def"),
178  Notify_true);
179 
181  msg.readInt16("left mdef"),
182  Notify_false);
184  msg.readInt16("right mdef"),
185  Notify_true);
186 
188  msg.readInt16("hit"),
189  Notify_true);
190 
192  msg.readInt16("flee"),
193  Notify_false);
195  msg.readInt16("flee2/10"),
196  Notify_true);
197 
199  msg.readInt16("crit/10"),
200  Notify_true);
201 
203  msg.readInt16("attack speed"),
204  Notify_true);
205  msg.readInt16("plus speed = 0");
206 
207  BLOCK_END("PlayerRecv::processPlayerStatUpdate5")
208 }
209 
211 {
212  if (localPlayer == nullptr)
213  return;
214  const BeingId id = msg.readBeingId("player id");
215  const int exp = msg.readInt32("exp amount");
216  const int stat = msg.readInt16("exp type");
217  const bool fromQuest = msg.readInt16("is from quest") != 0;
218  if (!fromQuest && id == localPlayer->getId())
219  {
220  if (stat == 1)
222  else if (stat == 2)
224  else
226  }
227  // need show particle depend on isQuest flag, for now ignored
228 }
229 
231 {
232  if (localPlayer == nullptr)
233  return;
234  const BeingId id = msg.readBeingId("player id");
235  const int64_t exp = msg.readInt64("exp amount");
236  const int stat = msg.readInt16("exp type");
237  const bool fromQuest = msg.readInt16("is from quest") != 0;
238  if (!fromQuest && id == localPlayer->getId())
239  {
240  if (stat == 1)
242  else if (stat == 2)
244  else
246  }
247  // need show particle depend on isQuest flag, for now ignored
248 }
249 
251 {
252  BLOCK_START("PlayerRecv::processWalkResponse")
253  /*
254  * This client assumes that all walk messages succeed,
255  * and that the server will send a correction notice
256  * otherwise.
257  */
258  uint16_t srcX, srcY, dstX, dstY;
259  msg.readInt32("tick");
260  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path");
261  msg.readUInt8("(sx<<4) | (sy&0x0f)");
262  if (localPlayer != nullptr)
263  localPlayer->setRealPos(dstX, dstY);
264  BLOCK_END("PlayerRecv::processWalkResponse")
265 }
266 
268 {
269  msg.readInt32("tick");
270  const int x = msg.readInt16("x");
271  const int y = msg.readInt16("y");
272  if (localPlayer != nullptr)
273  localPlayer->failMove(x, y);
274 }
275 
277 {
279  msg.readInt32("char id");
280  msg.readBeingId("account id");
281  msg.readInt32("pvp won");
282  msg.readInt32("pvp lost");
283  msg.readInt32("pvp point");
284 }
285 
287 {
288  if (localPlayer == nullptr)
289  return;
290 
291  const int type = msg.readInt16("var id");
292  int amount;
293  if (msg.getVersion() >= 20150513)
294  amount = msg.readInt32("value");
295  else
296  amount = msg.readInt16("value");
297  if (type == Sp::HP)
298  {
300  amount;
302  base,
303  Notify_true);
304  if (localPlayer->isInParty() && (Party::getParty(1) != nullptr))
305  {
306  PartyMember *const m = Party::getParty(1)
308  if (m != nullptr)
309  {
310  m->setHp(base);
313  }
314  }
315  localPlayer->addHpMessage(amount);
316  }
317  else if (type == Sp::SP)
318  {
319  localPlayer->addSpMessage(amount);
320  }
321 }
322 
324 {
325  const int message = msg.readInt32("type");
326  switch (message)
327  {
328  case 0x15:
330  break;
331  case 0x16:
333  break;
334  case 0x17:
336  break;
337  case 0x18:
339  break;
340  case 0x19:
342  break;
343  case 0x1c:
345  break;
346  case 0x1d:
348  break;
349  case 0x1e:
351  break;
352  case 0x1f:
354  break;
355  case 0x20:
357  break;
358  case 0x28:
360  break;
361  default:
363  break;
364  }
365 }
366 
368 {
370  msg.readInt16("type");
371 }
372 
374 {
376  msg.readInt32("points");
377  msg.readInt32("total points");
378 }
379 
381 {
383  msg.readInt32("points");
384  msg.readInt32("total points");
385 }
386 
388 {
390  msg.readInt32("result");
391  msg.readInt16("item id");
392 }
393 
395 {
397  msg.readInt32("points");
398  msg.readInt32("total points");
399 }
400 
402 {
404  msg.readInt32("book id");
405  msg.readInt32("page");
406 }
407 
409 {
411  msg.readInt32("unused");
412  msg.readInt32("flag");
413 }
414 
416 {
418  const int count = (msg.readInt16("len") - 8) / 2;
419  for (int f = 0; f < count; f ++)
420  msg.readInt16("skill id");
421 }
422 
424 {
426  msg.readInt16("type");
427  msg.readInt32("points");
428  msg.readInt32("fame");
429 }
430 
432 {
433  if (whoIsOnline == nullptr)
434  return;
435 
436  BLOCK_START("PlayerRecv::processOnlineList")
437  const int size = msg.readInt16("len") - 4;
438  STD_VECTOR<OnlinePlayer*> arr;
439 
440  if (size == 0)
441  {
442  if (whoIsOnline != nullptr)
443  whoIsOnline->loadList(arr);
444  BLOCK_END("PlayerRecv::processOnlineList")
445  return;
446  }
447 
448  char *const start = reinterpret_cast<char*>(msg.readBytes(size, "nicks"));
449  if (start == nullptr)
450  {
451  BLOCK_END("PlayerRecv::processOnlineList")
452  return;
453  }
454 
455  const char *buf = start;
456 
457  int addVal = 3;
458 
459  while (buf - start + 1 < size
460  && (*(buf + CAST_SIZE(addVal)) != 0))
461  {
462  const unsigned char status = *buf;
463  buf ++;
464  const unsigned char level = *buf;
465  buf ++;
466  const unsigned char ver = *buf;
467  buf ++;
468 
469  GenderT gender = Gender::UNSPECIFIED;
470  if (config.getBoolValue("showgender"))
471  {
472  if ((status & BeingFlag::GENDER_MALE) != 0)
473  gender = Gender::MALE;
474  else if ((status & BeingFlag::GENDER_HIDDEN) != 0)
475  gender = Gender::HIDDEN;
476  else
477  gender = Gender::FEMALE;
478  }
479  arr.push_back(new OnlinePlayer(static_cast<const char*>(buf),
480  status, level, gender, ver));
481  buf += strlen(buf) + 1;
482  }
483 
484  if (whoIsOnline != nullptr)
485  whoIsOnline->loadList(arr);
486  delete [] start;
487  BLOCK_END("PlayerRecv::processOnlineList")
488 }
489 
491 {
493  msg.readInt16("view");
494 }
495 
497 {
498  if (actorManager == nullptr)
499  return;
500  const BeingId id = msg.readBeingId("killer id");
501  const Being *const dstBeing = actorManager->findBeing(id);
502  if (id == BeingId_zero)
503  {
504  debugMsg(
505  // TRANSLATORS: player killed message
506  _("You were killed by unknown source."));
507  }
508  else
509  {
510  std::string name;
511  if (dstBeing != nullptr)
512  name = dstBeing->getName();
513  else
514  name = strprintf("?%u", CAST_U32(id));
516  // TRANSLATORS: player killed message
517  _("You were killed by %s."),
518  name.c_str()));
519  }
520 }
521 
523 {
524  const int len = msg.readInt16("len");
525  if (len < 8)
526  return;
527 
528  const int groupId = msg.readInt32("group id");
529 
530  if (localPlayer == nullptr)
531  return;
532 
533  localPlayer->setGroupId(groupId);
534 }
535 
537 {
538  BLOCK_START("PlayerRecv::processPlayerStatUpdate7")
539  const int type = msg.readInt16("type");
540  const int64_t value = msg.readInt64("value");
541  playerHandler->setStat(msg, type, value, NoStat, Notify_true);
542  BLOCK_END("PlayerRecv::processPlayerStatUpdate7")
543 }
544 
546 {
548  msg.readUInt8("flag");
549 }
550 
551 } // namespace EAthena
Net::PlayerHandler * playerHandler
Definition: net.cpp:92
#define CAST_U32
Definition: cast.h:30
void processPlayerReadBook(Net::MessageIn &msg)
Definition: playerrecv.cpp:401
unsigned char readUInt8(const char *const str)
Definition: messagein.cpp:98
#define _(s)
Definition: gettext.h:34
void setStatMod(const AttributesT id, const int value, const Notify notify)
Definition: playerinfo.cpp:157
void processWalkError(Net::MessageIn &msg)
Definition: playerrecv.cpp:267
BeingId readBeingId(const char *const str)
Definition: messagein.cpp:211
void processSelectStyleAck(Net::MessageIn &msg)
Definition: playerrecv.cpp:545
void setStatBase(const AttributesT id, const int value, const Notify notify)
Definition: playerinfo.cpp:141
void processDressRoomOpen(Net::MessageIn &msg)
Definition: playerrecv.cpp:490
void processPlayerGetExp2(Net::MessageIn &msg)
Definition: playerrecv.cpp:230
BeingId getId() const
Definition: actorsprite.h:63
void setRealPos(const int x, const int y)
#define BLOCK_START(name)
Definition: perfomance.h:78
Configuration config
int BeingId
Definition: beingid.h:29
StatusWindow * statusWindow
WhoIsOnline * whoIsOnline
Definition: whoisonline.cpp:78
void processPvpInfo(Net::MessageIn &msg)
Definition: playerrecv.cpp:276
#define BLOCK_END(name)
Definition: perfomance.h:79
bool msg(InputEvent &event)
Definition: chat.cpp:38
void notify(const unsigned int message)
void processPlayerGetExp(Net::MessageIn &msg)
Definition: playerrecv.cpp:210
void processWalkResponse(Net::MessageIn &msg)
Definition: playerrecv.cpp:250
void setGroupId(const int id)
void updateAttrs()
Definition: playerinfo.cpp:417
void loadList(const std::vector< OnlinePlayer *> &list)
void addXpMessage(const int64_t change)
int64_t readInt64(const char *const str)
Definition: messagein.cpp:216
void addSpMessage(const int change)
int16_t readInt16(const char *const str)
Definition: messagein.cpp:125
bool getBoolValue(const std::string &key) const
static const int NoStat
Definition: nostat.h:26
std::string strprintf(const char *const format,...)
Definition: stringutils.cpp:99
void processNotifyMapInfo(Net::MessageIn &msg)
Definition: playerrecv.cpp:367
void readCoordinatePair(uint16_t &srcX, uint16_t &srcY, uint16_t &dstX, uint16_t &dstY, const char *const str)
Definition: messagein.cpp:299
void setHp(const int hp)
Definition: avatar.h:92
void processPlayerStatUpdate7(Net::MessageIn &msg)
Definition: playerrecv.cpp:536
static Party * getParty(const int16_t id)
Definition: party.cpp:312
LocalPlayer * localPlayer
void processPlayerFameTaekwon(Net::MessageIn &msg)
Definition: playerrecv.cpp:394
void addJobMessage(const int64_t change)
void skip(const unsigned int length, const char *const str)
Definition: messagein.cpp:337
void processPlayerUpgradeMessage(Net::MessageIn &msg)
Definition: playerrecv.cpp:387
void setAttribute(const AttributesT id, const int64_t value, const Notify notify)
Definition: playerinfo.cpp:108
Being * findBeing(const BeingId id) const
Definition: sp.h:35
PartyMember * getMember(const BeingId id) const
Definition: party.cpp:98
void processPlayerSkillMessage(Net::MessageIn &msg)
Definition: playerrecv.cpp:323
bool isInParty() const
Definition: being.h:320
void failMove(const int x, const int y)
unsigned int getVersion() const
Definition: messagein.h:131
const std::string & getName() const
Definition: being.h:231
void processKilledBy(Net::MessageIn &msg)
Definition: playerrecv.cpp:496
Definition: sp.h:37
Gender ::T GenderT
Definition: gender.h:35
void processPlayerAutoShadowSpellList(Net::MessageIn &msg)
Definition: playerrecv.cpp:415
void processPlayerAttrs(Net::MessageIn &msg)
Definition: playerrecv.cpp:522
void processPlayerShortcuts(Net::MessageIn &msg)
Definition: playerrecv.cpp:55
void processPlayerFameBlacksmith(Net::MessageIn &msg)
Definition: playerrecv.cpp:373
void addHpMessage(const int change)
#define debugMsg(str)
Definition: chattab.h:41
#define UNIMPLEMENTEDPACKET
Definition: logger.h:55
void processPlayerStatUpdate5(Net::MessageIn &msg)
Definition: playerrecv.cpp:76
#define CAST_SIZE
Definition: cast.h:33
const BeingId BeingId_zero
Definition: beingid.h:29
void processPlayerHeal(Net::MessageIn &msg)
Definition: playerrecv.cpp:286
void processOnlineList(Net::MessageIn &msg)
Definition: playerrecv.cpp:431
int32_t readInt32(const char *const str)
Definition: messagein.cpp:169
void setMaxHp(const int maxHp)
Definition: avatar.h:98
int32_t getAttribute(const AttributesT id)
Definition: playerinfo.cpp:100
Definition: being.h:93
void processPlayerRankPoints(Net::MessageIn &msg)
Definition: playerrecv.cpp:423
void processPlayerEquipTickAck(Net::MessageIn &msg)
Definition: playerrecv.cpp:408
virtual void setStat(Net::MessageIn &msg, const int type, const int64_t base, const int mod, const Notify notify) const =0
const bool Notify_false
Definition: notify.h:29
void processPlayerFameAlchemist(Net::MessageIn &msg)
Definition: playerrecv.cpp:380
const bool Notify_true
Definition: notify.h:29
ActorManager * actorManager
void processPlayerShowEquip(Net::MessageIn &msg)
Definition: playerrecv.cpp:70
unsigned char * readBytes(int length, const char *const dstr)
Definition: messagein.cpp:425
#define UNIMPLEMENTEDPACKETFIELD(field)
Definition: logger.h:58
void setPointsNeeded(const AttributesT id, const int needed)