ManaPlus
inventoryrecv.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/tmwa/inventoryrecv.h"
25 
26 #include "notifymanager.h"
27 
28 #include "being/localplayer.h"
29 
30 #include "const/net/inventory.h"
31 
32 #include "enums/equipslot.h"
33 
35 
37 
38 #include "net/inventoryhandler.h"
39 #include "net/messagein.h"
40 
41 #include "net/ea/equipbackend.h"
42 #include "net/ea/inventoryrecv.h"
43 
44 #include "debug.h"
45 
46 namespace TmwAthena
47 {
48 
49 namespace InventoryRecv
50 {
52  {
53  EquipSlot::LEGS_SLOT, // Lower Headgear
54  EquipSlot::FIGHT1_SLOT, // Weapon
55  EquipSlot::GLOVES_SLOT, // Garment
56  EquipSlot::RING2_SLOT, // Accessory 1
57  EquipSlot::RING1_SLOT, // Armor
58  EquipSlot::FIGHT2_SLOT, // Shield
59  EquipSlot::FEET_SLOT, // Footgear
60  EquipSlot::NECK_SLOT, // Accessory 2
61  EquipSlot::HEAD_SLOT, // Upper Headgear
62  EquipSlot::TORSO_SLOT, // Middle Headgear
63  EquipSlot::EVOL_RING1_SLOT, // Costume Top Headgear
64  EquipSlot::EVOL_RING2_SLOT, // Costume Mid Headgear
65  EquipSlot::PROJECTILE_SLOT, // Costume Low Headgear
66  EquipSlot::COSTUME_ROBE_SLOT, // Costume Garment/Robe
67  EquipSlot::MISSING1_SLOT, // Missing slot 1
68  EquipSlot::MISSING2_SLOT, // Missing slot 2
69  EquipSlot::SHADOW_ARMOR_SLOT, // Shadow Armor
70  EquipSlot::SHADOW_WEAPON_SLOT, // Shadow Weapon
71  EquipSlot::SHADOW_SHIELD_SLOT, // Shadow Shield
72  EquipSlot::SHADOW_SHOES_SLOT, // Shadow Shoes
73  EquipSlot::SHADOW_ACCESSORY2_SLOT, // Shadow Accessory 2
74  EquipSlot::SHADOW_ACCESSORY1_SLOT, // Shadow Accessory 1
75  };
76 } // namespace InventoryRecv
77 
79 {
80  BLOCK_START("InventoryRecv::processPlayerEquipment")
81  Inventory *const inventory = localPlayer != nullptr
82  ? PlayerInfo::getInventory() : nullptr;
83 
84  msg.readInt16("len");
85  Equipment *const equipment = PlayerInfo::getEquipment();
86  if ((equipment != nullptr) && (equipment->getBackend() == nullptr))
87  { // look like SMSG_PLAYER_INVENTORY was not received
90  }
91  const int number = (msg.getLength() - 4) / 20;
92 
93  for (int loop = 0; loop < number; loop++)
94  {
95  const int index = msg.readInt16("index") - INVENTORY_OFFSET;
96  const int itemId = msg.readInt16("item id");
97  const ItemTypeT itemType = static_cast<ItemTypeT>(
98  msg.readUInt8("item type"));
99  const uint8_t identified = msg.readUInt8("identify");
100  msg.readInt16("equip type?");
101  const int equipType = msg.readInt16("equip type");
102  msg.readUInt8("attribute");
103  const uint8_t refine = msg.readUInt8("refine");
104  int cards[maxCards];
105  for (int f = 0; f < maxCards; f++)
106  cards[f] = msg.readUInt16("card");
107 
109  {
110  logger->log("Index: %d, ID: %d, Type: %d, Identified: %d",
111  index, itemId, CAST_S32(itemType), identified);
112  }
113 
114  if (inventory != nullptr)
115  {
116  inventory->setItem(index,
117  itemId,
118  itemType,
119  1,
120  refine,
122  fromBool(identified, Identified),
125  Equipm_true,
127  inventory->setCards(index, cards, maxCards);
128  }
129 
130  if (equipType != 0)
131  {
133  InventoryRecv::getSlot(equipType),
134  index);
135  }
136  }
137  BLOCK_END("InventoryRecv::processPlayerEquipment")
138 }
139 
141 {
142  BLOCK_START("InventoryRecv::processPlayerInventoryAdd")
143  Inventory *const inventory = localPlayer != nullptr
144  ? PlayerInfo::getInventory() : nullptr;
145 
146  if ((PlayerInfo::getEquipment() != nullptr)
147  && (PlayerInfo::getEquipment()->getBackend() == nullptr))
148  { // look like SMSG_PLAYER_INVENTORY was not received
151  }
152  const int index = msg.readInt16("index") - INVENTORY_OFFSET;
153  int amount = msg.readInt16("amount");
154  const int itemId = msg.readInt16("item id");
155  const uint8_t identified = msg.readUInt8("identified");
156  msg.readUInt8("attribute");
157  const uint8_t refine = msg.readUInt8("refine");
158  int cards[maxCards];
159  for (int f = 0; f < maxCards; f++)
160  cards[f] = msg.readUInt16("card");
161  const int equipType = msg.readInt16("equip type");
162  const ItemTypeT type = static_cast<ItemTypeT>(msg.readUInt8("item type"));
163  const unsigned char err = msg.readUInt8("status");
164  BeingId floorId;
166  {
167  floorId = BeingId_zero;
168  }
169  else
170  {
171  floorId = Ea::InventoryRecv::mSentPickups.front();
173  }
174 
175  if (err != 0U)
176  {
177  PickupT pickup;
178  switch (err)
179  {
180  case 1:
182  break;
183  case 2:
185  break;
186  case 3:
188  break;
189  case 4:
191  break;
192  case 5:
194  break;
195  case 6:
197  break;
198  default:
201  break;
202  }
203  if (localPlayer != nullptr)
204  {
205  if (itemId == 0)
206  {
208  0,
210  floorId,
211  pickup);
212  }
213  else
214  {
216  0,
218  floorId,
219  pickup);
220  }
221  }
222  }
223  else
224  {
225  if (localPlayer != nullptr)
226  {
227  if (itemId == 0)
228  {
230  amount,
232  floorId,
233  Pickup::OKAY);
234  }
235  else
236  {
238  amount,
240  floorId,
241  Pickup::OKAY);
242  }
243  }
244 
245  if (inventory != nullptr)
246  {
247  const Item *const item = inventory->getItem(index);
248 
249  if ((item != nullptr) && item->getId() == itemId)
250  amount += item->getQuantity();
251 
252  inventory->setItem(index,
253  itemId,
254  type,
255  amount,
256  refine,
258  fromBool(identified, Identified),
261  fromBool(equipType, Equipm),
263  inventory->setCards(index, cards, maxCards);
264  }
266  }
267  BLOCK_END("InventoryRecv::processPlayerInventoryAdd")
268 }
269 
271 {
272  BLOCK_START("InventoryRecv::processPlayerInventory")
273  Inventory *const inventory = localPlayer != nullptr
274  ? PlayerInfo::getInventory() : nullptr;
275 
276  if (PlayerInfo::getEquipment() != nullptr)
277  {
278  // Clear inventory - this will be a complete refresh
281  }
282 
283  if (inventory != nullptr)
284  inventory->clear();
285 
286  msg.readInt16("len");
287  const int number = (msg.getLength() - 4) / 18;
288 
289  for (int loop = 0; loop < number; loop++)
290  {
291  int cards[maxCards];
292  const int index = msg.readInt16("index") - INVENTORY_OFFSET;
293  const int itemId = msg.readInt16("item id");
294  const ItemTypeT itemType = static_cast<ItemTypeT>(
295  msg.readUInt8("item type"));
296  const uint8_t identified = msg.readUInt8("identified");
297  const int amount = msg.readInt16("amount");
298  const int arrow = msg.readInt16("arrow");
299  for (int i = 0; i < maxCards; i++)
300  cards[i] = msg.readUInt16("card");
301 
303  {
304  logger->log("Index: %d, ID: %d, Type: %d, Identified: %d, "
305  "Qty: %d, Cards: %d, %d, %d, %d",
306  index, itemId, CAST_S32(itemType), identified, amount,
307  cards[0], cards[1], cards[2], cards[3]);
308  }
309 
310  // Trick because arrows are not considered equipment
311  const bool isEquipment = (arrow & 0x8000) != 0;
312 
313  if (inventory != nullptr)
314  {
315  inventory->setItem(index,
316  itemId,
317  itemType,
318  amount,
319  0,
321  fromBool(identified, Identified),
324  fromBool(isEquipment, Equipm),
326  inventory->setCards(index, cards, maxCards);
327  }
328  }
329  BLOCK_END("InventoryRecv::processPlayerInventory")
330 }
331 
333 {
334  BLOCK_START("InventoryRecv::processPlayerInventory")
336 
337  msg.readInt16("len");
338  const int number = (msg.getLength() - 4) / 18;
339 
340  for (int loop = 0; loop < number; loop++)
341  {
342  int cards[maxCards];
343  const int index = msg.readInt16("index") - STORAGE_OFFSET;
344  const int itemId = msg.readInt16("item id");
345  const ItemTypeT itemType = static_cast<ItemTypeT>(
346  msg.readUInt8("item type"));
347  const uint8_t identified = msg.readUInt8("identified");
348  const int amount = msg.readInt16("amount");
349  msg.readInt16("arrow");
350  for (int i = 0; i < maxCards; i++)
351  cards[i] = msg.readUInt16("card");
352 
354  {
355  logger->log("Index: %d, ID: %d, Type: %d, Identified: %d, "
356  "Qty: %d, Cards: %d, %d, %d, %d",
357  index, itemId, CAST_S32(itemType), identified, amount,
358  cards[0], cards[1], cards[2], cards[3]);
359  }
360 
362  index,
363  itemId,
364  itemType,
365  cards,
366  nullptr,
367  amount,
368  0,
370  fromBool(identified, Identified),
373  Equipm_false,
374  -1));
375  }
376  BLOCK_END("InventoryRecv::processPlayerInventory")
377 }
378 
380 {
381  BLOCK_START("InventoryRecv::processPlayerEquip")
382  const int index = msg.readInt16("index") - INVENTORY_OFFSET;
383  const int equipType = msg.readInt16("equip type");
384  const uint8_t flag = msg.readUInt8("flag");
385 
386  if (flag == 0U)
387  {
389  }
390  else
391  {
393  InventoryRecv::getSlot(equipType),
394  index);
395  }
396  BLOCK_END("InventoryRecv::processPlayerEquip")
397 }
398 
400 {
401  BLOCK_START("InventoryRecv::processPlayerUnEquip")
402  msg.readInt16("index");
403  const int equipType = msg.readInt16("equip type");
404  const uint8_t flag = msg.readUInt8("flag");
405 
406  if (flag != 0U)
407  {
409  InventoryRecv::getSlot(equipType),
410  -1);
411  }
412  if ((equipType & 0x8000) != 0)
414  BLOCK_END("InventoryRecv::processPlayerUnEquip")
415 }
416 
418 {
419  BLOCK_START("InventoryRecv::processPlayerStorageEquip")
420  msg.readInt16("len");
421  const int number = (msg.getLength() - 4) / 20;
422 
423  for (int loop = 0; loop < number; loop++)
424  {
425  int cards[maxCards];
426  const int index = msg.readInt16("index") - STORAGE_OFFSET;
427  const int itemId = msg.readInt16("item id");
428  const ItemTypeT itemType = static_cast<ItemTypeT>(
429  msg.readUInt8("item type"));
430  const uint8_t identified = msg.readUInt8("identified");
431  const int amount = 1;
432  msg.readInt16("equip point?");
433  msg.readInt16("another equip point?");
434  msg.readUInt8("attribute (broken)");
435  const uint8_t refine = msg.readUInt8("refine");
436  for (int i = 0; i < maxCards; i++)
437  cards[i] = msg.readUInt16("card");
438 
440  {
441  logger->log("Index: %d, ID: %d, Type: %d, Identified: %u, "
442  "Qty: %d, Cards: %d, %d, %d, %d, Refine: %u",
443  index, itemId, CAST_S32(itemType),
444  CAST_U32(identified), amount,
445  cards[0], cards[1], cards[2], cards[3],
446  CAST_U32(refine));
447  }
448 
450  index,
451  itemId,
452  itemType,
453  cards,
454  nullptr,
455  amount,
456  refine,
458  fromBool(identified, Identified),
461  Equipm_false,
462  -1));
463  }
464  BLOCK_END("InventoryRecv::processPlayerStorageEquip")
465 }
466 
468 {
469  BLOCK_START("InventoryRecv::processPlayerStorageAdd")
470  // Move an item into storage
471  const int index = msg.readInt16("index") - STORAGE_OFFSET;
472  const int amount = msg.readInt32("amount");
473  const int itemId = msg.readInt16("item id");
474  const unsigned char identified = msg.readUInt8("identified");
475  msg.readUInt8("attribute");
476  const uint8_t refine = msg.readUInt8("refine");
477  int cards[maxCards];
478  for (int f = 0; f < maxCards; f++)
479  cards[f] = msg.readUInt16("card");
480 
481  if (Item *const item = Ea::InventoryRecv::mStorage->getItem(index))
482  {
483  item->setId(itemId, ItemColor_one);
484  item->increaseQuantity(amount);
485  }
486  else
487  {
488  if (Ea::InventoryRecv::mStorage != nullptr)
489  {
491  itemId,
493  amount,
494  refine,
496  fromBool(identified, Identified),
499  Equipm_false,
502  }
503  }
504  BLOCK_END("InventoryRecv::processPlayerStorageAdd")
505 }
506 
508 {
509  BLOCK_START("InventoryRecv::processPlayerStorageRemove")
510  // Move an item out of storage
511  const int index = msg.readInt16("index") - STORAGE_OFFSET;
512  const int amount = msg.readInt32("amount");
513  if (Ea::InventoryRecv::mStorage != nullptr)
514  {
515  if (Item *const item = Ea::InventoryRecv::mStorage->getItem(index))
516  {
517  item->increaseQuantity(-amount);
518  if (item->getQuantity() == 0)
520  }
521  }
522  BLOCK_END("InventoryRecv::processPlayerStorageRemove")
523 }
524 
526 {
527  BLOCK_START("InventoryRecv::processPlayerInventoryRemove")
528  Inventory *const inventory = localPlayer != nullptr
529  ? PlayerInfo::getInventory() : nullptr;
530 
531  const int index = msg.readInt16("index") - INVENTORY_OFFSET;
532  const int amount = msg.readInt16("amount");
533  if (inventory != nullptr)
534  {
535  if (Item *const item = inventory->getItem(index))
536  {
537  item->increaseQuantity(-amount);
538  if (item->getQuantity() == 0)
539  inventory->removeItemAt(index);
541  }
542  }
543  BLOCK_END("InventoryRecv::processPlayerInventoryRemove")
544 }
545 
546 int InventoryRecv::getSlot(const int eAthenaSlot)
547 {
548  if (eAthenaSlot == 0)
549  return EquipSlot::VECTOREND;
550 
551  if ((eAthenaSlot & 0x8000) != 0)
553 
554  unsigned int mask = 1;
555  int position = 0;
556  while ((eAthenaSlot & mask) == 0U)
557  {
558  mask <<= 1;
559  position++;
560  }
561  if (position >= EquipSlot::VECTOREND)
562  return EquipSlot::VECTOREND;
563  return CAST_S32(EQUIP_POINTS[position]);
564 }
565 
567 {
568  BLOCK_START("InventoryRecv::processPlayerInventoryUse")
569  Inventory *const inventory = localPlayer != nullptr
570  ? PlayerInfo::getInventory() : nullptr;
571 
572  const int index = msg.readInt16("index") - INVENTORY_OFFSET;
573  msg.readItemId("item id");
574  msg.readInt32("id?");
575  const int amount = msg.readInt16("amount");
576  msg.readUInt8("type");
577 
578  if (inventory != nullptr)
579  {
580  if (Item *const item = inventory->getItem(index))
581  {
582  if (amount != 0)
583  item->setQuantity(amount);
584  else
585  inventory->removeItemAt(index);
586  }
587  }
588  BLOCK_END("InventoryRecv::processPlayerInventoryUse")
589 }
590 
591 } // namespace TmwAthena
int BeingId
Definition: beingid.h:30
const BeingId BeingId_zero
Definition: beingid.h:30
#define fromBool(val, name)
Definition: booldefines.h:49
#define maxCards
Definition: cards.h:25
#define CAST_S32
Definition: cast.h:30
#define CAST_U32
Definition: cast.h:31
static void distributeEvent()
void setEquipment(const int index, const int inventoryIndex)
Definition: equipbackend.h:78
const Backend * getBackend() const
Definition: equipment.h:91
void setBackend(Backend *const backend)
Definition: equipment.h:88
void setCards(const int index, const int *const cards, const int size) const
Definition: inventory.cpp:194
void clear()
Definition: inventory.cpp:238
void removeItemAt(const int index)
Definition: inventory.cpp:254
Item * getItem(const int index) const
Definition: inventory.cpp:83
virtual void setItem(const int index, const int id, const ItemTypeT type, const int quantity, const uint8_t refine, const ItemColor color, const Identified identified, const Damaged damaged, const Favorite favorite, const Equipm equipment, const Equipped equipped)
Definition: inventory.cpp:141
Definition: item.h:50
int getQuantity() const
Definition: item.h:105
int getId() const
Definition: item.h:81
void pickedUp(const ItemInfo &itemInfo, const int amount, const ItemColor color, const BeingId floorItemId, const PickupT fail)
void log(const char *const log_text,...)
Definition: logger.cpp:269
virtual int getProjectileSlot() const =0
static const int STORAGE_OFFSET
Definition: inventory.h:28
static const int INVENTORY_OFFSET
Definition: inventory.h:27
const bool Damaged_false
Definition: damaged.h:30
const bool Equipm_false
Definition: equipm.h:30
const bool Equipm_true
Definition: equipm.h:30
bool Equipm
Definition: equipm.h:30
const bool Equipped_false
Definition: equipped.h:30
const bool Favorite_false
Definition: favorite.h:30
bool Identified
Definition: identified.h:30
Net::InventoryHandler * inventoryHandler
Definition: net.cpp:89
const ItemColor ItemColor_one
Definition: itemcolor.h:30
ItemType ::T ItemTypeT
Definition: itemtype.h:43
LocalPlayer * localPlayer
Logger * logger
Definition: logger.cpp:89
#define UNIMPLEMENTEDPACKETFIELD(field)
Definition: logger.h:59
bool msg(InputEvent &event)
Definition: chat.cpp:39
bool pickup(InputEvent &event)
Definition: actions.cpp:49
EquipBackend mEquips
PickupQueue mSentPickups
Inventory * mStorage
InventoryItems mStorageItems
@ FIGHT1_SLOT
Definition: equipslot.h:41
@ EVOL_RING1_SLOT
Definition: equipslot.h:44
@ SHADOW_SHOES_SLOT
Definition: equipslot.h:52
@ MISSING1_SLOT
Definition: equipslot.h:47
@ COSTUME_ROBE_SLOT
Definition: equipslot.h:46
@ HEAD_SLOT
Definition: equipslot.h:35
@ VECTOREND
Definition: equipslot.h:55
@ LEGS_SLOT
Definition: equipslot.h:36
@ RING1_SLOT
Definition: equipslot.h:38
@ MISSING2_SLOT
Definition: equipslot.h:48
@ GLOVES_SLOT
Definition: equipslot.h:34
@ PROJECTILE_SLOT
Definition: equipslot.h:43
@ SHADOW_ACCESSORY2_SLOT
Definition: equipslot.h:54
@ NECK_SLOT
Definition: equipslot.h:40
@ TORSO_SLOT
Definition: equipslot.h:33
@ SHADOW_ACCESSORY1_SLOT
Definition: equipslot.h:53
@ FIGHT2_SLOT
Definition: equipslot.h:42
@ SHADOW_ARMOR_SLOT
Definition: equipslot.h:49
@ RING2_SLOT
Definition: equipslot.h:39
@ EVOL_RING2_SLOT
Definition: equipslot.h:45
@ FEET_SLOT
Definition: equipslot.h:37
@ SHADOW_SHIELD_SLOT
Definition: equipslot.h:51
@ SHADOW_WEAPON_SLOT
Definition: equipslot.h:50
const ItemInfo & getEmpty()
Definition: itemdb.cpp:834
const ItemInfo & get(const int id)
Definition: itemdb.cpp:792
@ Unknown
Definition: itemtype.h:30
void notify(const unsigned int message)
@ INV_FULL
Definition: pickup.h:38
@ BAD_ITEM
Definition: pickup.h:35
@ UNKNOWN
Definition: pickup.h:34
@ OKAY
Definition: pickup.h:33
@ TOO_FAR
Definition: pickup.h:37
@ STACK_FULL
Definition: pickup.h:39
@ TOO_HEAVY
Definition: pickup.h:36
@ DROP_STEAL
Definition: pickup.h:40
Inventory * getInventory()
Definition: playerinfo.cpp:195
Equipment * getEquipment()
Definition: playerinfo.cpp:220
void processPlayerStorageAdd(Net::MessageIn &msg)
int getSlot(const int eAthenaSlot)
void processPlayerInventoryUse(Net::MessageIn &msg)
void processPlayerStorage(Net::MessageIn &msg)
void processPlayerStorageEquip(Net::MessageIn &msg)
void processPlayerUnEquip(Net::MessageIn &msg)
const EquipSlot::Type EQUIP_POINTS[EquipSlot::VECTOREND]
void processPlayerStorageRemove(Net::MessageIn &msg)
void processPlayerEquip(Net::MessageIn &msg)
void processPlayerEquipment(Net::MessageIn &msg)
void processPlayerInventoryAdd(Net::MessageIn &msg)
void processPlayerInventory(Net::MessageIn &msg)
void processPlayerInventoryRemove(Net::MessageIn &msg)
#define BLOCK_END(name)
Definition: perfomance.h:80
#define BLOCK_START(name)
Definition: perfomance.h:79
Pickup ::T PickupT
Definition: pickup.h:44
std::string empty
Definition: podict.cpp:26