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;
259  uint16_t srcY;
260  uint16_t dstX;
261  uint16_t dstY;
262  msg.readInt32("tick");
263  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path");
264  msg.readUInt8("(sx<<4) | (sy&0x0f)");
265  if (localPlayer != nullptr)
266  localPlayer->setRealPos(dstX, dstY);
267  BLOCK_END("PlayerRecv::processWalkResponse")
268 }
269 
271 {
272  msg.readInt32("tick");
273  const int x = msg.readInt16("x");
274  const int y = msg.readInt16("y");
275  if (localPlayer != nullptr)
276  localPlayer->failMove(x, y);
277 }
278 
280 {
282  msg.readInt32("char id");
283  msg.readBeingId("account id");
284  msg.readInt32("pvp won");
285  msg.readInt32("pvp lost");
286  msg.readInt32("pvp point");
287 }
288 
290 {
291  if (localPlayer == nullptr)
292  return;
293 
294  const int type = msg.readInt16("var id");
295  int amount;
296  if (msg.getVersion() >= 20150513)
297  amount = msg.readInt32("value");
298  else
299  amount = msg.readInt16("value");
300  if (type == Sp::HP)
301  {
303  amount;
305  base,
306  Notify_true);
307  if (localPlayer->isInParty() && (Party::getParty(1) != nullptr))
308  {
309  PartyMember *const m = Party::getParty(1)
311  if (m != nullptr)
312  {
313  m->setHp(base);
316  }
317  }
318  localPlayer->addHpMessage(amount);
319  }
320  else if (type == Sp::SP)
321  {
322  localPlayer->addSpMessage(amount);
323  }
324 }
325 
327 {
328  const int message = msg.readInt32("type");
329  switch (message)
330  {
331  case 0x15:
333  break;
334  case 0x16:
336  break;
337  case 0x17:
339  break;
340  case 0x18:
342  break;
343  case 0x19:
345  break;
346  case 0x1c:
348  break;
349  case 0x1d:
351  break;
352  case 0x1e:
354  break;
355  case 0x1f:
357  break;
358  case 0x20:
360  break;
361  case 0x28:
363  break;
364  default:
366  break;
367  }
368 }
369 
371 {
373  msg.readInt16("type");
374 }
375 
377 {
379  msg.readInt32("points");
380  msg.readInt32("total points");
381 }
382 
384 {
386  msg.readInt32("points");
387  msg.readInt32("total points");
388 }
389 
391 {
393  msg.readInt32("result");
394  msg.readItemId("item id");
395 }
396 
398 {
400  msg.readInt32("points");
401  msg.readInt32("total points");
402 }
403 
405 {
407  msg.readInt32("book id");
408  msg.readInt32("page");
409 }
410 
412 {
413  // +++ actually ZC_CONFIG
415  msg.readInt32("unused");
416  msg.readInt32("flag");
417 }
418 
420 {
422  const int count = (msg.readInt16("len") - 8) / 2;
423  for (int f = 0; f < count; f ++)
424  msg.readInt16("skill id");
425 }
426 
428 {
430  msg.readInt16("type");
431  msg.readInt32("points");
432  msg.readInt32("fame");
433 }
434 
436 {
437  if (whoIsOnline == nullptr)
438  return;
439 
440  BLOCK_START("PlayerRecv::processOnlineList")
441  const int size = msg.readInt16("len") - 4;
442  STD_VECTOR<OnlinePlayer*> arr;
443 
444  if (size == 0)
445  {
446  if (whoIsOnline != nullptr)
447  whoIsOnline->loadList(arr);
448  BLOCK_END("PlayerRecv::processOnlineList")
449  return;
450  }
451 
452  char *const start = reinterpret_cast<char*>(msg.readBytes(size, "nicks"));
453  if (start == nullptr)
454  {
455  BLOCK_END("PlayerRecv::processOnlineList")
456  return;
457  }
458 
459  const char *buf = start;
460 
461  int addVal = 3;
462 
463  while (buf - start + 1 < size
464  && (*(buf + CAST_SIZE(addVal)) != 0))
465  {
466  const unsigned char status = *buf;
467  buf ++;
468  const unsigned char level = *buf;
469  buf ++;
470  const unsigned char ver = *buf;
471  buf ++;
472 
473  GenderT gender = Gender::UNSPECIFIED;
474  if (config.getBoolValue("showgender"))
475  {
476  if ((status & BeingFlag::GENDER_MALE) != 0)
477  gender = Gender::MALE;
478  else if ((status & BeingFlag::GENDER_HIDDEN) != 0)
479  gender = Gender::HIDDEN;
480  else
481  gender = Gender::FEMALE;
482  }
483  arr.push_back(new OnlinePlayer(static_cast<const char*>(buf),
484  status, level, gender, ver));
485  buf += strlen(buf) + 1;
486  }
487 
488  if (whoIsOnline != nullptr)
489  whoIsOnline->loadList(arr);
490  delete [] start;
491  BLOCK_END("PlayerRecv::processOnlineList")
492 }
493 
495 {
497  msg.readInt16("view");
498 }
499 
501 {
502  if (actorManager == nullptr)
503  return;
504  const BeingId id = msg.readBeingId("killer id");
505  const Being *const dstBeing = actorManager->findBeing(id);
506  if (id == BeingId_zero)
507  {
508  debugMsg(
509  // TRANSLATORS: player killed message
510  _("You were killed by unknown source."));
511  }
512  else
513  {
514  std::string name;
515  if (dstBeing != nullptr)
516  name = dstBeing->getName();
517  else
518  name = strprintf("?%u", CAST_U32(id));
520  // TRANSLATORS: player killed message
521  _("You were killed by %s."),
522  name.c_str()));
523  }
524 }
525 
527 {
528  const int len = msg.readInt16("len");
529  if (len < 8)
530  return;
531 
532  const int groupId = msg.readInt32("group id");
533 
534  if (localPlayer == nullptr)
535  return;
536 
537  localPlayer->setGroupId(groupId);
538 }
539 
541 {
542  BLOCK_START("PlayerRecv::processPlayerStatUpdate7")
543  const int type = msg.readInt16("type");
544  const int64_t value = msg.readInt64("value");
545  playerHandler->setStat(msg, type, value, NoStat, Notify_true);
546  BLOCK_END("PlayerRecv::processPlayerStatUpdate7")
547 }
548 
550 {
552  msg.readUInt8("flag");
553 }
554 
556 {
558  msg.readUInt8("fail flag");
559  msg.readInt32("title");
560 }
561 
562 } // namespace EAthena
Net::PlayerHandler * playerHandler
Definition: net.cpp:93
#define CAST_U32
Definition: cast.h:30
void processPlayerReadBook(Net::MessageIn &msg)
Definition: playerrecv.cpp:404
unsigned char readUInt8(const char *const str)
Definition: messagein.cpp:103
#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:270
BeingId readBeingId(const char *const str)
Definition: messagein.cpp:223
void processSelectStyleAck(Net::MessageIn &msg)
Definition: playerrecv.cpp:549
void setStatBase(const AttributesT id, const int value, const Notify notify)
Definition: playerinfo.cpp:141
void processDressRoomOpen(Net::MessageIn &msg)
Definition: playerrecv.cpp:494
void processPlayerGetExp2(Net::MessageIn &msg)
Definition: playerrecv.cpp:230
BeingId getId() const
Definition: actorsprite.h:63
void setRealPos(const int x, const int y)
void processSetTitleAck(Net::MessageIn &msg)
Definition: playerrecv.cpp:555
#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:279
#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:418
void loadList(const std::vector< OnlinePlayer *> &list)
void addXpMessage(const int64_t change)
int64_t readInt64(const char *const str)
Definition: messagein.cpp:228
void addSpMessage(const int change)
int16_t readInt16(const char *const str)
Definition: messagein.cpp:130
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:370
void readCoordinatePair(uint16_t &srcX, uint16_t &srcY, uint16_t &dstX, uint16_t &dstY, const char *const str)
Definition: messagein.cpp:311
void setHp(const int hp)
Definition: avatar.h:92
void processPlayerStatUpdate7(Net::MessageIn &msg)
Definition: playerrecv.cpp:540
static Party * getParty(const int16_t id)
Definition: party.cpp:312
int getVersion() const
Definition: messagein.h:133
LocalPlayer * localPlayer
void processPlayerFameTaekwon(Net::MessageIn &msg)
Definition: playerrecv.cpp:397
void addJobMessage(const int64_t change)
void skip(const unsigned int length, const char *const str)
Definition: messagein.cpp:349
void processPlayerUpgradeMessage(Net::MessageIn &msg)
Definition: playerrecv.cpp:390
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:326
bool isInParty() const
Definition: being.h:320
void failMove(const int x, const int y)
const std::string & getName() const
Definition: being.h:231
void processKilledBy(Net::MessageIn &msg)
Definition: playerrecv.cpp:500
Definition: sp.h:37
Gender ::T GenderT
Definition: gender.h:35
int readItemId(const char *const str)
Definition: messagein.cpp:216
void processPlayerAutoShadowSpellList(Net::MessageIn &msg)
Definition: playerrecv.cpp:419
void processPlayerAttrs(Net::MessageIn &msg)
Definition: playerrecv.cpp:526
void processPlayerShortcuts(Net::MessageIn &msg)
Definition: playerrecv.cpp:55
void processPlayerFameBlacksmith(Net::MessageIn &msg)
Definition: playerrecv.cpp:376
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:289
void processOnlineList(Net::MessageIn &msg)
Definition: playerrecv.cpp:435
int32_t readInt32(const char *const str)
Definition: messagein.cpp:174
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:427
void processPlayerEquipTickAck(Net::MessageIn &msg)
Definition: playerrecv.cpp:411
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:383
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:437
#define UNIMPLEMENTEDPACKETFIELD(field)
Definition: logger.h:58
void setPointsNeeded(const AttributesT id, const int needed)