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-2019 The ManaPlus Developers
6  * Copyright (C) 2019-2021 Andrei Karas
7  *
8  * This file is part of The ManaPlus Client.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #include "net/eathena/playerrecv.h"
25 
26 #include "actormanager.h"
27 #include "configuration.h"
28 #include "notifymanager.h"
29 #include "party.h"
30 
31 #include "being/beingflag.h"
32 #include "being/localplayer.h"
33 #include "being/playerinfo.h"
34 
35 #include "const/net/nostat.h"
36 
38 
39 #include "gui/onlineplayer.h"
40 
43 
45 
46 #include "net/eathena/sp.h"
47 #include "net/playerhandler.h"
48 
49 #include "utils/gettext.h"
50 
51 #include "debug.h"
52 
53 namespace EAthena
54 {
55 
57 {
58  // +++ player shortcuts ignored. It also disabled on server side.
59  // may be in future better use it?
60  for (int f = 0; f < 38; f ++)
61  {
62  msg.readUInt8("type 0: item, 1: skill");
63  msg.readInt32("item or skill id");
64  msg.readInt16("skill level");
65  }
66 }
67 
69 {
70  // +++ player shortcuts ignored. It also disabled on server side.
71  // may be in future better use it?
72  msg.readUInt8("rotate");
73  for (int f = 0; f < 38; f ++)
74  {
75  msg.readUInt8("type 0: item, 1: skill");
76  msg.readInt32("item or skill id");
77  msg.readInt16("skill level");
78  }
79 }
80 
82 {
83  // +++ player shortcuts ignored. It also disabled on server side.
84  // may be in future better use it?
85  msg.readUInt8("rotate");
86  msg.readInt16("tab");
87  for (int f = 0; f < 38; f ++)
88  {
89  msg.readUInt8("type 0: item, 1: skill");
90  msg.readInt32("item or skill id");
91  msg.readInt16("skill level");
92  }
93 }
94 
96 {
97  // +++ for now server allow only switch this option but not using it.
98  msg.readUInt8("show equip"); // 1 mean need open "equipment" window
99 }
100 
102 {
103  BLOCK_START("PlayerRecv::processPlayerStatUpdate5")
105  msg.readInt16("char points"),
106  Notify_true);
107 
108  unsigned int val = msg.readUInt8("str");
110  val,
111  Notify_true);
112  if (statusWindow != nullptr)
113  {
115  msg.readUInt8("str cost"));
116  }
117  else
118  {
119  msg.readUInt8("str need");
120  }
121 
122  val = msg.readUInt8("agi");
124  if (statusWindow != nullptr)
125  {
127  msg.readUInt8("agi cost"));
128  }
129  else
130  {
131  msg.readUInt8("agi cost");
132  }
133 
134  val = msg.readUInt8("vit");
136  if (statusWindow != nullptr)
137  {
139  msg.readUInt8("vit cost"));
140  }
141  else
142  {
143  msg.readUInt8("vit cost");
144  }
145 
146  val = msg.readUInt8("int");
148  if (statusWindow != nullptr)
149  {
151  msg.readUInt8("int cost"));
152  }
153  else
154  {
155  msg.readUInt8("int cost");
156  }
157 
158  val = msg.readUInt8("dex");
160  if (statusWindow != nullptr)
161  {
163  msg.readUInt8("dex cost"));
164  }
165  else
166  {
167  msg.readUInt8("dex cost");
168  }
169 
170  val = msg.readUInt8("luk");
172  if (statusWindow != nullptr)
173  {
175  msg.readUInt8("luk cost"));
176  }
177  else
178  {
179  msg.readUInt8("luk cost");
180  }
181 
183  msg.readInt16("left atk"),
184  Notify_false);
186  msg.readInt16("right atk"),
187  Notify_true);
189 
190  val = msg.readInt16("right matk");
192 
193  val = msg.readInt16("left matk");
195  val,
196  Notify_true);
197 
199  msg.readInt16("left def"),
200  Notify_false);
202  msg.readInt16("right def"),
203  Notify_true);
204 
206  msg.readInt16("left mdef"),
207  Notify_false);
209  msg.readInt16("right mdef"),
210  Notify_true);
211 
213  msg.readInt16("hit"),
214  Notify_true);
215 
217  msg.readInt16("flee"),
218  Notify_false);
220  msg.readInt16("flee2/10"),
221  Notify_true);
222 
224  msg.readInt16("crit/10"),
225  Notify_true);
226 
228  msg.readInt16("attack speed"),
229  Notify_true);
230  msg.readInt16("plus speed = 0");
231 
232  BLOCK_END("PlayerRecv::processPlayerStatUpdate5")
233 }
234 
236 {
237  if (localPlayer == nullptr)
238  return;
239  const BeingId id = msg.readBeingId("player id");
240  const int exp = msg.readInt32("exp amount");
241  const int stat = msg.readInt16("exp type");
242  const bool fromQuest = msg.readInt16("is from quest") != 0;
243  if (!fromQuest && id == localPlayer->getId())
244  {
245  if (stat == 1)
247  else if (stat == 2)
249  else
251  }
252  // need show particle depend on isQuest flag, for now ignored
253 }
254 
256 {
257  if (localPlayer == nullptr)
258  return;
259  const BeingId id = msg.readBeingId("player id");
260  const int64_t exp = msg.readInt64("exp amount");
261  const int stat = msg.readInt16("exp type");
262  const bool fromQuest = msg.readInt16("is from quest") != 0;
263  if (!fromQuest && id == localPlayer->getId())
264  {
265  if (stat == 1)
267  else if (stat == 2)
269  else
271  }
272  // need show particle depend on isQuest flag, for now ignored
273 }
274 
276 {
277  BLOCK_START("PlayerRecv::processWalkResponse")
278  /*
279  * This client assumes that all walk messages succeed,
280  * and that the server will send a correction notice
281  * otherwise.
282  */
283  uint16_t srcX;
284  uint16_t srcY;
285  uint16_t dstX;
286  uint16_t dstY;
287  msg.readInt32("tick");
288  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path");
289  msg.readUInt8("(sx<<4) | (sy&0x0f)");
290  if (localPlayer != nullptr)
291  localPlayer->setRealPos(dstX, dstY);
292  BLOCK_END("PlayerRecv::processWalkResponse")
293 }
294 
296 {
297  msg.readInt32("tick");
298  const int x = msg.readInt16("x");
299  const int y = msg.readInt16("y");
300  if (localPlayer != nullptr)
301  localPlayer->failMove(x, y);
302 }
303 
305 {
307  msg.readInt32("char id");
308  msg.readBeingId("account id");
309  msg.readInt32("pvp won");
310  msg.readInt32("pvp lost");
311  msg.readInt32("pvp point");
312 }
313 
315 {
316  if (localPlayer == nullptr)
317  return;
318 
319  const int type = msg.readInt16("var id");
320  int amount;
321  if (msg.getVersion() >= 20150513)
322  amount = msg.readInt32("value");
323  else
324  amount = msg.readInt16("value");
325  if (type == Sp::HP)
326  {
328  amount;
330  base,
331  Notify_true);
332  if (localPlayer->isInParty() && (Party::getParty(1) != nullptr))
333  {
334  PartyMember *const m = Party::getParty(1)
336  if (m != nullptr)
337  {
338  m->setHp(base);
341  }
342  }
343  localPlayer->addHpMessage(amount);
344  }
345  else if (type == Sp::SP)
346  {
347  localPlayer->addSpMessage(amount);
348  }
349 }
350 
352 {
353  const int message = msg.readInt32("type");
354  switch (message)
355  {
356  case 0x15:
358  break;
359  case 0x16:
361  break;
362  case 0x17:
364  break;
365  case 0x18:
367  break;
368  case 0x19:
370  break;
371  case 0x1c:
373  break;
374  case 0x1d:
376  break;
377  case 0x1e:
379  break;
380  case 0x1f:
382  break;
383  case 0x20:
385  break;
386  case 0x28:
388  break;
389  default:
391  break;
392  }
393 }
394 
396 {
398  msg.readInt16("type");
399 }
400 
402 {
404  msg.readInt32("points");
405  msg.readInt32("total points");
406 }
407 
409 {
411  msg.readInt32("points");
412  msg.readInt32("total points");
413 }
414 
416 {
418  msg.readInt32("result");
419  msg.readItemId("item id");
420 }
421 
423 {
425  msg.readInt32("points");
426  msg.readInt32("total points");
427 }
428 
430 {
432  msg.readInt32("book id");
433  msg.readInt32("page");
434 }
435 
437 {
439  msg.readInt32("type");
440  msg.readInt32("flag");
441 }
442 
444 {
446  const int count = (msg.readInt16("len") - 8) / 2;
447  for (int f = 0; f < count; f ++)
448  msg.readInt16("skill id");
449 }
450 
452 {
454  msg.readInt16("type");
455  msg.readInt32("points");
456  msg.readInt32("fame");
457 }
458 
460 {
461  if (whoIsOnline == nullptr)
462  return;
463 
464  BLOCK_START("PlayerRecv::processOnlineList")
465  const int size = msg.readInt16("len") - 4;
466  STD_VECTOR<OnlinePlayer*> arr;
467 
468  if (size == 0)
469  {
470  if (whoIsOnline != nullptr)
471  whoIsOnline->loadList(arr);
472  BLOCK_END("PlayerRecv::processOnlineList")
473  return;
474  }
475 
476  char *const start = reinterpret_cast<char*>(msg.readBytes(size, "nicks"));
477  if (start == nullptr)
478  {
479  BLOCK_END("PlayerRecv::processOnlineList")
480  return;
481  }
482 
483  const char *buf = start;
484 
485  int addVal = 3;
486 
487  while (buf - start + 1 < size
488  && (*(buf + CAST_SIZE(addVal)) != 0))
489  {
490  const unsigned char status = *buf;
491  buf ++;
492  const unsigned char level = *buf;
493  buf ++;
494  const unsigned char ver = *buf;
495  buf ++;
496 
497  GenderT gender = Gender::UNSPECIFIED;
498  if (config.getBoolValue("showgender"))
499  {
500  if ((status & BeingFlag::GENDER_MALE) != 0)
501  gender = Gender::MALE;
502  else
503  gender = Gender::FEMALE;
504  }
505  arr.push_back(new OnlinePlayer(static_cast<const char*>(buf),
506  status, level, gender, ver, -1));
507  buf += strlen(buf) + 1;
508  }
509 
510  if (whoIsOnline != nullptr)
511  whoIsOnline->loadList(arr);
512  delete [] start;
513  BLOCK_END("PlayerRecv::processOnlineList")
514 }
515 
517 {
519  msg.readInt16("view");
520 }
521 
523 {
524  if (actorManager == nullptr)
525  return;
526  const BeingId id = msg.readBeingId("killer id");
527  const Being *const dstBeing = actorManager->findBeing(id);
528  if (id == BeingId_zero)
529  {
530  debugMsg(
531  // TRANSLATORS: player killed message
532  _("You were killed by unknown source."))
533  }
534  else
535  {
536  std::string name;
537  if (dstBeing != nullptr)
538  name = dstBeing->getName();
539  else
540  name = strprintf("?%u", CAST_U32(id));
542  // TRANSLATORS: player killed message
543  _("You were killed by %s."),
544  name.c_str()))
545  }
546 }
547 
549 {
550  const int len = msg.readInt16("len");
551  if (len < 8)
552  return;
553 
554  const int groupId = msg.readInt32("group id");
555 
556  if (localPlayer == nullptr)
557  return;
558 
559  localPlayer->setGroupId(groupId);
560 }
561 
563 {
564  BLOCK_START("PlayerRecv::processPlayerStatUpdate7")
565  const int type = msg.readInt16("type");
566  const int64_t value = msg.readInt64("value");
567  playerHandler->setStat(msg, type, value, NoStat, Notify_true);
568  BLOCK_END("PlayerRecv::processPlayerStatUpdate7")
569 }
570 
572 {
574  msg.readUInt8("flag");
575 }
576 
578 {
580  msg.readUInt8("fail flag");
581  msg.readInt32("title");
582 }
583 
584 } // namespace EAthena
ActorManager * actorManager
int BeingId
Definition: beingid.h:30
const BeingId BeingId_zero
Definition: beingid.h:30
#define CAST_U32
Definition: cast.h:31
#define CAST_SIZE
Definition: cast.h:34
#define debugMsg(str)
Definition: chattab.h:42
Being * findBeing(const BeingId id) const
BeingId getId() const
Definition: actorsprite.h:64
void setMaxHp(const int maxHp)
Definition: avatar.h:99
void setHp(const int hp)
Definition: avatar.h:93
Definition: being.h:96
const std::string & getName() const
Definition: being.h:232
bool isInParty() const
Definition: being.h:321
bool getBoolValue(const std::string &key) const
void addHpMessage(const int change)
void failMove(const int x, const int y)
void setGroupId(const int id)
void setRealPos(const int x, const int y)
void addJobMessage(const int64_t change)
void addXpMessage(const int64_t change)
void addSpMessage(const int change)
virtual void setStat(Net::MessageIn &msg, const int type, const int64_t base, const int mod, const Notify notify) const =0
PartyMember * getMember(const BeingId id) const
Definition: party.cpp:99
static Party * getParty(const int16_t id)
Definition: party.cpp:313
void setPointsNeeded(const AttributesT id, const int needed)
void loadList(const std::vector< OnlinePlayer * > &list)
Configuration config
Gender ::T GenderT
Definition: gender.h:35
#define _(s)
Definition: gettext.h:35
LocalPlayer * localPlayer
#define UNIMPLEMENTEDPACKETFIELD(field)
Definition: logger.h:59
#define UNIMPLEMENTEDPACKET
Definition: logger.h:56
bool msg(InputEvent &event)
Definition: chat.cpp:39
@ PLAYER_CHAR_POINTS
Definition: attributes.h:49
@ PLAYER_MAX_HP
Definition: attributes.h:33
@ PLAYER_ATTACK_DELAY
Definition: attributes.h:51
@ GENDER_MALE
Definition: beingflag.h:33
void processPlayerReadBook(Net::MessageIn &msg)
Definition: playerrecv.cpp:429
void processWalkResponse(Net::MessageIn &msg)
Definition: playerrecv.cpp:275
void processDressRoomOpen(Net::MessageIn &msg)
Definition: playerrecv.cpp:516
void processWalkError(Net::MessageIn &msg)
Definition: playerrecv.cpp:295
void processPlayerUpgradeMessage(Net::MessageIn &msg)
Definition: playerrecv.cpp:415
void processSetTitleAck(Net::MessageIn &msg)
Definition: playerrecv.cpp:577
void processPlayerStatUpdate7(Net::MessageIn &msg)
Definition: playerrecv.cpp:562
void processSelectStyleAck(Net::MessageIn &msg)
Definition: playerrecv.cpp:571
void processPlayerFameBlacksmith(Net::MessageIn &msg)
Definition: playerrecv.cpp:401
void processPlayerShortcuts2(Net::MessageIn &msg)
Definition: playerrecv.cpp:68
void processPlayerGetExp(Net::MessageIn &msg)
Definition: playerrecv.cpp:235
void processNotifyMapInfo(Net::MessageIn &msg)
Definition: playerrecv.cpp:395
void processPlayerHeal(Net::MessageIn &msg)
Definition: playerrecv.cpp:314
void processPvpInfo(Net::MessageIn &msg)
Definition: playerrecv.cpp:304
void processPlayerZCConfig(Net::MessageIn &msg)
Definition: playerrecv.cpp:436
void processPlayerShowEquip(Net::MessageIn &msg)
Definition: playerrecv.cpp:95
void processPlayerGetExp2(Net::MessageIn &msg)
Definition: playerrecv.cpp:255
void processPlayerAttrs(Net::MessageIn &msg)
Definition: playerrecv.cpp:548
void processOnlineList(Net::MessageIn &msg)
Definition: playerrecv.cpp:459
void processKilledBy(Net::MessageIn &msg)
Definition: playerrecv.cpp:522
void processPlayerFameTaekwon(Net::MessageIn &msg)
Definition: playerrecv.cpp:422
void processPlayerShortcuts1(Net::MessageIn &msg)
Definition: playerrecv.cpp:56
void processPlayerAutoShadowSpellList(Net::MessageIn &msg)
Definition: playerrecv.cpp:443
void processPlayerShortcuts3(Net::MessageIn &msg)
Definition: playerrecv.cpp:81
void processPlayerStatUpdate5(Net::MessageIn &msg)
Definition: playerrecv.cpp:101
void processPlayerSkillMessage(Net::MessageIn &msg)
Definition: playerrecv.cpp:351
void processPlayerFameAlchemist(Net::MessageIn &msg)
Definition: playerrecv.cpp:408
void processPlayerRankPoints(Net::MessageIn &msg)
Definition: playerrecv.cpp:451
int size()
Definition: emotedb.cpp:306
@ UNSPECIFIED
Definition: gender.h:33
@ MALE
Definition: gender.h:31
@ FEMALE
Definition: gender.h:32
void notify(const unsigned int message)
@ SKILL_ENCHANT_ARMOR_HOLY
Definition: notifytypes.h:194
@ SKILL_END_ALL_NEGATIVE_STATUS
Definition: notifytypes.h:188
@ SKILL_ENCHANT_WEAPON_HOLY
Definition: notifytypes.h:193
@ SKILL_FLEE_PLUS_50
Definition: notifytypes.h:197
@ SKILL_FULL_STRIP_FAILED
Definition: notifytypes.h:198
@ SKILL_IMMUNITY_TO_ALL_STATUSES
Definition: notifytypes.h:189
@ SKILL_MESSAGE_UNKNOWN
Definition: notifytypes.h:199
@ SKILL_ATTACK_PLUS_100
Definition: notifytypes.h:196
@ SKILL_ALL_STATUS_PLUS_20
Definition: notifytypes.h:192
void setStatMod(const AttributesT id, const int value, const Notify notify)
Definition: playerinfo.cpp:159
int32_t getAttribute(const AttributesT id)
Definition: playerinfo.cpp:102
void setAttribute(const AttributesT id, const int64_t value, const Notify notify)
Definition: playerinfo.cpp:110
void updateAttrs()
Definition: playerinfo.cpp:420
void setStatBase(const AttributesT id, const int value, const Notify notify)
Definition: playerinfo.cpp:143
@ SP
Definition: sp.h:38
@ HP
Definition: sp.h:36
Net::PlayerHandler * playerHandler
Definition: net.cpp:96
static const int NoStat
Definition: nostat.h:27
const bool Notify_false
Definition: notify.h:30
const bool Notify_true
Definition: notify.h:30
#define BLOCK_END(name)
Definition: perfomance.h:80
#define BLOCK_START(name)
Definition: perfomance.h:79
StatusWindow * statusWindow
std::string strprintf(const char *const format,...)
WhoIsOnline * whoIsOnline
Definition: whoisonline.cpp:82