EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Inventory.cpp
Go to the documentation of this file.
1 /*
2  ------------------------------------------------------------------------------------
3  LICENSE:
4  ------------------------------------------------------------------------------------
5  This file is part of EVEmu: EVE Online Server Emulator
6  Copyright 2006 - 2021 The EVEmu Team
7  For the latest information visit https://evemu.dev
8  ------------------------------------------------------------------------------------
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13 
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License along with
19  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20  Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21  http://www.gnu.org/copyleft/lesser.txt.
22  ------------------------------------------------------------------------------------
23  Author: Bloody.Rabbit
24  Rewrite: Allan
25 */
26 
27 #include "eve-server.h"
28 
29 #include "Client.h"
30 #include "ConsoleCommands.h"
31 #include "EVEServerConfig.h"
32 #include "StaticDataMgr.h"
33 #include "PyCallable.h"
34 #include "character/Character.h"
35 #include "inventory/Inventory.h"
36 #include "inventory/ItemDB.h"
37 #include "inventory/ItemFactory.h"
38 #include "pos/Structure.h"
39 #include "ship/Ship.h"
40 #include "station/Station.h"
41 #include "station/StationDB.h"
42 #include "system/Container.h"
43 #include "system/SolarSystem.h"
45 
46 /*
47  * Inventory
48  */
50 {
51  mContentsLoaded = false;
52  m_self = iRef;
53  m_myID = iRef->itemID();
54 }
55 
57 {
58  Unload();
59  LoadContents();
60 }
61 
63 {
64  if (!mContentsLoaded)
65  return;
66 
67  // save contents on the off-chance they have changed, but not on shutdown. (saved in ItemFactory::Close())
68  Inventory* inv(nullptr);
69  if (!sConsole.IsShutdown()) {
70  std::vector<Inv::SaveData> items;
71  items.clear();
72  std::map<uint32, InventoryItemRef>::iterator itr = mContents.begin();
73  while (itr != mContents.end()) {
74  // test for item contents and unload as required
75  inv = itr->second->GetMyInventory();
76  if (inv != nullptr)
77  inv->Unload();
78  if (IsPlayerItem(itr->first)) { // only save player items (except skills - saved in Character::SaveAll())
79  if (itr->second->flag() == flagSkill) {
80  sItemFactory.RemoveItem(itr->first);
81  itr = mContents.erase(itr);
82  continue;
83  }
84 
86  data.itemID = itr->first;
87  data.contraband = itr->second->contraband();
88  data.flag = itr->second->flag();
89  data.locationID = itr->second->locationID();
90  data.ownerID = itr->second->ownerID();
91  data.position = itr->second->position();
92  data.quantity = itr->second->quantity();
93  data.singleton = itr->second->isSingleton();
94  data.typeID = itr->second->typeID();
95  data.customInfo = itr->second->customInfo();
96  items.push_back(data);
97  }
98  sItemFactory.RemoveItem(itr->first);
99  itr = mContents.erase(itr);
100  }
101 
102  ItemDB::SaveItems(items);
103  }
104  mContents.clear();
105  m_contentsByFlag.clear();
106  mContentsLoaded = false;
107 }
108 
109 bool Inventory::GetItems(OwnerData od, std::vector< uint32 >& into ) {
110  return m_db.GetItemContents(od, into);
111 }
112 
114  if (IsAgent(m_myID))
115  return true;
116  double profileStartTime(GetTimeUSeconds());
117  /* rewrote logic, optimized, and fixed "empty inventory" for new chars in existing systems -allan 22.2.16 */
118  Client* pClient(sItemFactory.GetUsingClient());
119 
120  // test for character creation (which throws errors) and station loading
121  if (pClient != nullptr) {
122  if (pClient->IsCharCreation())
123  return true;
124  if (sDataMgr.IsStation(m_myID)) {
125  if (pClient->IsHangarLoaded(m_myID))
126  return true;
127  pClient->AddStationHangar(m_myID);
128  mContentsLoaded = false;
129  }
130  }
131 
132  // check if the contents has already been loaded
133  if (mContentsLoaded) {
134  _log(INV__INFO, "Inventory::LoadContents() - inventory %u(%p) already loaded.", m_myID, this);
135  return true;
136  }
137 
138  OwnerData od = OwnerData();
139  od.ownerID = 1;
140  od.locID = m_myID;
141 
142  std::vector<uint32> items;
143  if (pClient != nullptr) {
144  if (pClient->IsValidSession())
145  od.corpID = pClient->GetCorporationID();
146  if (sDataMgr.IsStation(m_myID)) {
147  if (!StationItemRef::StaticCast(m_self)->IsLoaded())
148  StationDB::LoadOffices(od, items);
149  if (IsPlayerCorp(od.corpID)) {
150  /* this will load all non-NPC corp items in this station */
151  od.ownerID = od.corpID;
152  _log(INV__TRACE, "Inventory::LoadContents()::IsPlayerCorp() - Loading inventory %u(%p) with owner %u", m_myID, this , od.ownerID);
153  GetItems(od, items);
154  }
155  } else if (IsOfficeID(m_myID)) {
156  if (IsPlayerCorp(od.corpID)) {
157  /* this will load corp hangars' inventory for this station */
158  od.ownerID = od.corpID;
159  _log(INV__TRACE, "Inventory::LoadContents() - Loading office inventory %u(%p) for corp %u in station %s",\
160  m_myID, this , od.ownerID, (pClient->IsValidSession() ? itoa(pClient->GetStationID()) : "(invalid)"));
161  GetItems(od, items);
162  } else {
163  // make error for loading office and NOT a PC corp
164  _log(INV__WARNING, "Inventory::LoadContents() - inventory of officeID %u using corpID %u. Continuing...", m_myID, od.corpID);
165  }
166  }
167  if (pClient->IsValidSession()) {
168  od.ownerID = pClient->GetCharacterID();
169  } else {
170  od.ownerID = pClient->GetCharID();
171  }
172  }
173 
174  _log(INV__TRACE, "Inventory::LoadContents() - Loading inventory of %s(%u) with owner %u", m_self->name(), m_myID, od.ownerID);
175  if (!GetItems(od, items)) {
176  _log(INV__ERROR, "Inventory::LoadContents() - Failed to get inventory items for %s(%u)", m_self->name(), m_myID);
177  if ((pClient != nullptr) and sDataMgr.IsStation(m_myID))
178  pClient->RemoveStationHangar(m_myID);
179  return false;
180  }
181 
182  for (auto cur : items) {
183  if ((cur == od.ownerID) or (cur == od.locID) or (cur == m_myID))
184  continue;
185  InventoryItemRef iRef = sItemFactory.GetItem(cur);
186  if (iRef.get() == nullptr) {
187  _log(INV__WARNING, "Inventory::LoadContents() - Failed to load item %u contained in %u. Skipping.", cur, m_myID);
188  continue;
189  } else {
190  AddItem(iRef);
191  Client* pClient(sItemFactory.GetUsingClient());
192  }
193  }
194 
195  if (sConfig.debug.UseProfiling)
196  sProfiler.AddTime(Profile::itemload, GetTimeUSeconds() - profileStartTime);
197 
198  mContentsLoaded = true;
199 
200  return mContentsLoaded;
201 }
202 
204  //segfault check
205  if (iRef.get() == nullptr)
206  return;
207 
208  std::map<uint32, InventoryItemRef>::iterator itr = mContents.find(iRef->itemID());
209  std::pair <std::_Rb_tree_iterator <std::pair <const uint32, InventoryItemRef > >, bool > test;
210  if (itr == mContents.end())
211  test = mContents.emplace(iRef->itemID(), iRef);
212 
213  if (test.second) {
214  _log(INV__TRACE, "Inventory::AddItem() - Updated %s(%u) to contain (%u) %s(%u) in %s.", \
215  m_self->name(), m_myID, iRef->quantity(), iRef->name(), iRef->itemID(), sDataMgr.GetFlagName(iRef->flag()));
216  } else {
217  _log(INV__TRACE, "Inventory::AddItem() - %s(%u) already contains %s(%u) in %s.", \
218  m_self->name(), m_myID, iRef->name(), iRef->itemID(), sDataMgr.GetFlagName(iRef->flag()));
219  }
220 
221  // need to find and remove skill in training flag here for proper skill search
222  if (IsCharacterID(m_myID)) {
223  if (iRef->categoryID() == EVEDB::invCategories::Skill) {
224  m_contentsByFlag.emplace(flagSkill, iRef);
225  } else {
226  m_contentsByFlag.emplace(iRef->flag(), iRef);
227  }
228  } else {
229  m_contentsByFlag.emplace(iRef->flag(), iRef);
230  }
231 
232  // Apply iHub upgrades
233  if (m_self->typeID() == EVEDB::invTypes::InfrastructureHub) {
234  _log(SOV__DEBUG, "Applying system upgrade %s to system %s...", iRef->name(), m_self->locationID());
235 
236  // For now, all we need to do is mark the upgrade active,
237  // but in the future upgrades for military and resource harvesting
238  // will need to be 'activated' here
239  iRef->SetFlag(EVEItemFlags::flagStructureActive, true);
240  }
241 }
242 
244  //segfault check
245  if (iRef.get() == nullptr)
246  return;
247 
248  std::map<uint32, InventoryItemRef>::iterator itr = mContents.find(iRef->itemID());
249  if (itr != mContents.end()) {
250  mContents.erase(itr);
251  _log(INV__TRACE, "Inventory::RemoveItem(1) - Updated %s(%u) to no longer contain %s(%u) in %s.", \
252  m_self->name(), m_myID, iRef->name(), iRef->itemID(), sDataMgr.GetFlagName(iRef->flag()));
253  } else {
254  _log(INV__WARNING,"Inventory::RemoveItem(1) - %s(%u) contents does not contain %s(%u) in %s.", \
255  m_self->name(), m_myID, iRef->name(), iRef->itemID(), sDataMgr.GetFlagName(iRef->flag()));
256  }
257 
259  auto range = m_contentsByFlag.equal_range(iRef->flag());
260  for (auto cur = range.first; cur != range.second; ++cur) {
261  if (cur->second == iRef) {
262  m_contentsByFlag.erase(cur);
263  _log(INV__TRACE, "Inventory::RemoveItem(2) - %s(%u) removed from %s(%u) flagMap at %s.", \
264  iRef->name(), iRef->itemID(), m_self->name(), m_myID, sDataMgr.GetFlagName(iRef->flag()));
265  return;
266  }
267  }
268 
269  _log(INV__WARNING,"Inventory::RemoveItem(2) - %s(%u) flagMap does not contain %s(%u) in %s.", \
270  m_self->name(), m_myID, iRef->name(), iRef->itemID(), sDataMgr.GetFlagName(iRef->flag()));
271 }
272 
274 {
275  if (!mContentsLoaded)
276  return;
277  InventoryItemRef iRef(nullptr);
278  std::map<uint32, InventoryItemRef>::iterator cur = mContents.begin();
279  while (cur != mContents.end()) {
280  iRef = cur->second;
281  ++cur;
282  iRef->Delete();
283  }
284 
285  mContents.clear();
286  m_contentsByFlag.clear();
287  mContentsLoaded = false;
288 }
289 
290 CRowSet* Inventory::List(EVEItemFlags flag, uint32 ownerID/*0*/) const
291 {
292  DBRowDescriptor* header = sDataMgr.CreateHeader();
293  CRowSet* rowset = new CRowSet(&header);
294  List(rowset, flag, ownerID);
295 
296  if (is_log_enabled(INV__LIST))
297  rowset->Dump(INV__LIST, " ");
298  return rowset;
299 }
300 
301 void Inventory::List(CRowSet* into, EVEItemFlags flag, uint32 ownerID) const {
302  //there has to be a better way to build this...
303  PyPackedRow* row(nullptr);
304  // office hangars list ALL items. client separates by division flag
306  for (auto cur : mContents) {
307  row = into->NewRow();
308  cur.second->GetItemRow(row);
309  }
310  } else if (m_self->categoryID() == EVEDB::invCategories::Ship) {
311  bool space = sDataMgr.IsSolarSystem(m_self->locationID());
312  for (auto cur : mContents) {
313  // this also fills module/charges in fit window when docked.
314  // charges not sent like this in space (uses subLocation sent via shipInfo())
315  if (space and IsFittingSlot(cur.second->flag()))
316  if (cur.second->categoryID() == EVEDB::invCategories::Charge)
317  continue;
318  row = into->NewRow();
319  cur.second->GetItemRow(row);
320  }
321  } else {
322  for (auto cur : mContents) {
323  if (((ownerID == 0) or (cur.second->ownerID() == ownerID))
324  and ((flag == flagNone) or (cur.second->flag() == flag))) {
325  row = into->NewRow();
326  cur.second->GetItemRow(row);
327  }
328  }
329  }
330 }
331 
332 void Inventory::GetCargoList(std::multimap< uint8, InventoryItemRef >& cargoMap) {
333  for (auto cur : mContents)
334  cargoMap.emplace(cur.second->flag(), cur.second);
335 }
336 
338  float totalVolume(0.0f);
339  for (auto cur : mContents)
340  if (IsHangarFlag(cur.second->flag()))
341  totalVolume += cur.second->quantity() * cur.second->GetAttribute(AttrVolume).get_float();
342  return totalVolume;
343 }
344 
345 void Inventory::GetInventoryVec(std::vector<InventoryItemRef> &itemVec) {
346  std::vector<InventoryItemRef> itemVecTmp;
347  itemVecTmp.clear();
348  for (auto cur : mContents)
349  itemVecTmp.push_back(cur.second);
350  /* sorting method to put modules first, charges second, and cargo last
351  * this is needed to correctly fit modules BEFORE trying to load charges
352  */
353  itemVec = SortVector(itemVecTmp);
354 }
355 
356 std::vector<InventoryItemRef> Inventory::SortVector(std::vector<InventoryItemRef> &itemVec)
357 {
358  // my sort
359  //15:53:09 [ItemTrace] Inventory::SortVector: 41 items sorted in 0.177us with 480 loops. <<-- dunno when/where this was run
360  //15:40:20 [ItemTrace] Inventory::SortVector() - 30 items sorted in 28.250us with 87 loops.i
361  //22:09:28 [InvTrace] Inventory::SortVector() - 47 items sorted in 129.250us with 644 loops.
362 
363 
364  // std::swap
365  //12:57:36 [ItemTrace] Inventory::SortVector() - 21 items sorted in 16.000us with 60 loops.
366  //13:00:55 [ItemTrace] Inventory::SortVector() - 15 items sorted in 20.750us with 28 loops.
367  //13:01:20 [ItemTrace] Inventory::SortVector() - 19 items sorted in 46.000us with 90 loops.
368  /* sorts a vector of items by category, with loaded modules first (in slot order), then loaded charges (in slot order), then cargo
369  * if there is only one item, no sorting required...
370  * this should only be called by ships
371  * -allan
372  */
373  if (itemVec.size() < 2)
374  return itemVec;
375 
376  uint16 count(0);
377  double start(GetTimeUSeconds());
378 
379  //begin basic sort
380  bool done(false);
381  InventoryItemRef tmp(nullptr);
382 
383  while (!done) { //check if sorted
384  done = true; //assume sorted
385  //iterate though list
386  for (int i = 0, i2 = 1; (i < itemVec.size()) && (i2 < itemVec.size()); ++i, ++i2) {
387  if ((IsModuleSlot(itemVec[i]->flag())) && (IsModuleSlot(itemVec[i2]->flag()))) {
388  //check if each pair is sorted by category. subsystems > charges > modules
389  if (itemVec[i]->categoryID() > itemVec[i2]->categoryID()) {
390  //it's not, so flip the values
391  //std::swap(itemVec[i],itemVec[i2]); // this is ~100x slower on dev server
392  tmp = itemVec[i];
393  itemVec[i] = itemVec[i2];
394  itemVec[i2] = tmp;
395  done = false; //we weren't sorted, so now go back and check if we are
396  }
397  //check if each pair is sorted by flag. cargo > module
398  } else if ((IsCargoHoldFlag(itemVec[i]->flag())) && (IsModuleSlot(itemVec[i2]->flag()))) {
399  //it's not, so flip the values
400  tmp = itemVec[i];
401  itemVec[i] = itemVec[i2];
402  itemVec[i2] = tmp;
403  done = false; //we weren't sorted, so now go back and check if we are
404  }
405  ++count;
406  }
407  }
408 
409  if (sConfig.debug.IsTestServer)
410  _log(INV__TRACE, "Inventory::SortVector() - %u items sorted in %.3fus with %u loops.", itemVec.size(), (GetTimeUSeconds() - start), count);
411 
412  return itemVec; //returns sorted list
413 }
414 
416  std::map<uint32, InventoryItemRef>::const_iterator res = mContents.find(id);
417  if (res != mContents.end())
418  return res->second;
419 
420  return InventoryItemRef(nullptr);
421 }
422 
423 // for stations only...can get expensive for stations that have many players loaded
424 // maybe create an inventory map by owner in station?
425 void Inventory::GetInvForOwner(uint32 ownerID, std::vector< InventoryItemRef >& items)
426 {
427  if (!IsOfficeID(m_myID) and !sDataMgr.IsStation(m_myID)) {
428  _log(INV__ERROR, "GetInvForOwner called on non-station item %s(%u)", m_self->name(), m_myID);
429  EvE::traceStack();
430  }
431  for (auto cur : mContents)
432  if (cur.second->ownerID() == ownerID)
433  items.push_back(cur.second);
434 }
435 
437  for (auto cur : mContents)
438  if (cur.second->flag() == flag)
439  return cur.second;
440 
441  return InventoryItemRef(nullptr);
442 }
443 
445  auto range = m_contentsByFlag.equal_range(flag);
446  for ( auto itr = range.first; itr != range.second; ++itr )
447  if (itr->second->typeID() == typeID)
448  return itr->second;
449 
450  return InventoryItemRef(nullptr);
451 }
452 
453 void Inventory::GetInventoryMap( std::map< uint32, InventoryItemRef >& invMap ) {
454  for (auto cur : mContents)
455  invMap.emplace(cur.first, cur.second);
456 }
457 
458 uint32 Inventory::GetItemsByFlag(EVEItemFlags flag, std::vector<InventoryItemRef> &items) const {
459  auto range = m_contentsByFlag.equal_range(flag);
460  for ( auto itr = range.first; itr != range.second; ++itr )
461  items.push_back(itr->second);
462  return items.size();
463 }
464 
465 bool Inventory::GetTypesByFlag(EVEItemFlags flag, std::map< uint16, InventoryItemRef >& items)
466 {
467  auto range = m_contentsByFlag.equal_range(flag);
468  for ( auto itr = range.first; itr != range.second; ++itr )
469  items.emplace(itr->second->typeID(), itr->second);
470 
471  if (items.size() > 0)
472  return true;
473  return false;
474 }
475 
477 {
478  std::vector<InventoryItemRef> items;
479  if (GetItemsByFlag(flag, items) < 1)
480  return InventoryItemRef(nullptr);
481 
482  for (auto cur : items)
483  if (cur->typeID() == typeID )
484  return cur;
485 
486  return InventoryItemRef(nullptr);
487 }
488 
490  auto range = m_contentsByFlag.equal_range(flag);
491  for ( auto itr = range.first; itr != range.second; ++itr ) {
492  iRef = itr->second;
493  return true;
494  }
495  return false;
496 }
497 
499  return (m_contentsByFlag.find(flag) == m_contentsByFlag.end());
500 }
501 
502 uint32 Inventory::GetItemsByFlagRange(EVEItemFlags lowflag, EVEItemFlags highflag, std::vector<InventoryItemRef> &items) const
503 {
504  // i dont yet see a better way to do this one...
505  uint32 count = 0;
506  for (auto cur : mContents)
507  if (cur.second->flag() >= lowflag && cur.second->flag() <= highflag) {
508  items.push_back(cur.second);
509  ++count;
510  }
511  return count;
512 }
513 
514 uint32 Inventory::GetItemsByFlagSet(std::set<EVEItemFlags> flags, std::vector<InventoryItemRef> &items) const
515 {
516  // i dont yet see a better way to do this one...
517  uint32 count = 0;
518  for (auto cur : mContents)
519  if (flags.find(cur.second->flag()) != flags.end()) {
520  items.push_back(cur.second);
521  ++count;
522  }
523  return count;
524 }
525 
526 bool Inventory::ContainsTypeQty(uint16 typeID, uint32 qty/*0*/) const
527 {
528  uint32 count(0);
529  for (auto cur : mContents) {
530  if (cur.second->typeID() == typeID ) {
531  if (cur.second->quantity() >= qty) {
532  return true;
533  } else {
534  count += cur.second->quantity();
535  }
536  }
537  }
538 
539  return (count >= qty);
540 }
541 
543 {
544  uint32 count(0);
545  std::vector<InventoryItemRef> itemVec;
546  if (GetItemsByFlag(flag, itemVec) < 1)
547  return false;
548 
549  for (auto cur : itemVec) {
550  if (cur->quantity() >= qty) {
551  return true;
552  } else {
553  count += cur->quantity();
554  }
555  }
556 
557  return (count >= qty);
558 }
559 
560 
562 {
563  std::vector<InventoryItemRef> itemVec;
564  if (GetItemsByFlag(flag, itemVec) < 1)
565  return false;
566 
567  for (auto cur : itemVec)
568  if (cur->typeID() == typeID)
569  return true;
570 
571  return false;
572 }
573 
574 
575 void Inventory::StackAll(EVEItemFlags locFlag, uint32 ownerID/*0*/)
576 {
577  InventoryItemRef iRef(nullptr);
578  std::vector<InventoryItemRef> delVec;
579  std::map<uint16, InventoryItemRef> types;
580  std::map<uint16, InventoryItemRef>::iterator tItr = types.end();
581 
582  auto range = m_contentsByFlag.equal_range(locFlag);
583  for (auto itr = range.first; itr != range.second; ++itr) {
584  iRef = itr->second;
585  // check to avoid removing modules (and their charges) from ship
586  if (IsModuleSlot(iRef->flag()))
587  continue;
588  // singletons dont stack
589  if (iRef->isSingleton())
590  continue;
591  if ((ownerID == 0) or (ownerID == iRef->ownerID())) {
592  tItr = types.find(iRef->typeID());
593  if (tItr == types.end()) {
594  // insert type into map for later comparison (existing stack to merge into)
595  types.emplace(iRef->typeID(), iRef);
596  } else {
597  // found another stack of this type.
598  delVec.push_back(iRef);
599  // fake merge as calling II::Merge() will invalidate iterator
600  tItr->second->SetQuantity(tItr->second->quantity() + iRef->quantity(), true, false);
601  }
602  }
603  }
604 
605  for (auto cur : delVec)
606  cur->Delete();
607 }
608 
609 float Inventory::GetStoredVolume(EVEItemFlags flag, bool combined/*true*/) const
610 {
611  float totalVolume(0.0f);
612  if (IsHangarFlag(flag) and combined) {
613  for (auto cur : mContents)
614  if (IsHangarFlag(cur.second->flag()))
615  totalVolume += cur.second->quantity() * cur.second->GetAttribute(AttrVolume).get_float();
616  } else {
617  auto range = m_contentsByFlag.equal_range(flag);
618  for ( auto itr = range.first; itr != range.second; ++itr )
619  totalVolume += itr->second->quantity() * itr->second->GetAttribute(AttrVolume).get_float();
620  // This formula is a hybrid of both old and new ones...and it works \o/
621  }
622  return totalVolume;
623 }
624 
626 
627  float capacity(GetRemainingCapacity(flag));
628  float volume(iRef->quantity() * iRef->GetAttribute(AttrVolume).get_float());
629 
630  if (is_log_enabled(INV__CAPY))
631  _log(INV__CAPY, "Inventory::HasAvailableSpace() - Testing %s's %s available capy of %.2f to add %u %s at %.2f (%.3f each)", \
632  m_self->name(), sDataMgr.GetFlagName(flag), capacity, iRef->quantity(), iRef->name(), \
633  volume, iRef->GetAttribute(AttrVolume).get_float());
634 
635  // check capy for all units
636  if (volume > capacity)
637  return false;
638 
639  return true;
640 }
641 
643  // added hangar capy for all hangar types
644  // are we missing any hangar types here? POS types? yes...see next line
646  // IsFlagCapacityLocationWide item.groupID in (const.groupCorporateHangarArray, const.groupAssemblyArray, const.groupMobileLaboratory):
647 
648  switch( flag ) {
649  case flagOffice:
650  case flagProperty:
651  //case flagDelivery:
652  case flagImpounded:
653  case flagCorpMarket: return maxHangarCapy;
654  case flagNone:
655  case flagCargoHold: return m_self->GetAttribute(AttrCapacity).get_float();
656  case flagDroneBay: return m_self->GetAttribute(AttrDroneCapacity).get_float();
657  case flagShipHangar: return m_self->GetAttribute(AttrShipMaintenanceBayCapacity).get_float();
658  case flagSecondaryStorage: return m_self->GetAttribute(AttrSecondaryCapacity).get_float();
659  case flagFuelBay: return m_self->GetAttribute(AttrFuelBayCapacity).get_float();
660  case flagOreHold: return m_self->GetAttribute(AttrOreHoldCapacity).get_float();
661  case flagGasHold: return m_self->GetAttribute(AttrGasHoldCapacity).get_float();
662  case flagAmmoHold: return m_self->GetAttribute(AttrAmmoHoldCapacity).get_float();
663  case flagShipHold: return m_self->GetAttribute(AttrShipHoldCapacity).get_float();
664  case flagMineralHold: return m_self->GetAttribute(AttrMineralHoldCapacity).get_float();
665  case flagSalvageHold: return m_self->GetAttribute(AttrSalvageHoldCapacity).get_float();
666  case flagSmallShipHold: return m_self->GetAttribute(AttrSmallShipHoldCapacity).get_float();
667  case flagMediumShipHold: return m_self->GetAttribute(AttrMediumShipHoldCapacity).get_float();
668  case flagLargeShipHold: return m_self->GetAttribute(AttrLargeShipHoldCapacity).get_float();
669  case flagIndustrialShipHold: return m_self->GetAttribute(AttrIndustrialShipHoldCapacity).get_float();
670  // for PI
671  case flagCommandCenterHold: return m_self->GetAttribute(AttrCommandCenterHoldCapacity).get_float();
672  case flagPlanetaryCommoditiesHold: return m_self->GetAttribute(AttrPlanetaryCommoditiesHoldCapacity).get_float();
673  // for pos battery/array
674  case flagHiSlot0: return m_self->GetAttribute(AttrAmmoCapacity).get_float();
675  // still not sure where/why this is used....
676  case flagQuafeBay: return m_self->GetAttribute(AttrQuafeHoldCapacity).get_float();
677  // these can be in station OR on ship....
678  case flagCorpHangar2:
679  case flagCorpHangar3:
680  case flagCorpHangar4:
681  case flagCorpHangar5:
682  case flagCorpHangar6:
683  case flagCorpHangar7: {
684  if (sDataMgr.IsStation(m_myID))
685  return maxHangarCapy;
686  //for ship, this is TOTAL capy for all corp hangars (they share capy)
687  if (m_self->HasAttribute(AttrHasCorporateHangars))
688  return m_self->GetAttribute(AttrCorporateHangarCapacity).get_float();
689  }
690  case flagHangar: {
691  if (sDataMgr.IsStation(m_myID))
692  return maxHangarCapy;
693  if (m_self->HasAttribute(AttrHasCorporateHangars))
694  return m_self->GetAttribute(AttrCorporateHangarCapacity).get_float();
695  //for cargo container, this is 27k5m3.
696  return m_self->GetAttribute(AttrCapacity).get_float();
697  }
698  }
699 
700  _log(INV__WARNING, "Inventory::GetCapacity() - Unsupported flag %s(%u) called for %s(%u)", \
701  sDataMgr.GetFlagName(flag), flag, m_self->name(), m_myID);
702  return 0.0f;
703 }
704 
705 // Validate an IHub Upgrade and trigger it's activation
707  // Get days since claim for strategic development index
708  SovereigntyData sovData = svDataMgr.GetSovereigntyData(m_self->locationID());
709  double daysSinceClaim = (GetFileTimeNow() - sovData.claimTime) / Win32Time_Day;
710 
711  // Get client who currently owns the item
712  Client* pClient(sItemFactory.GetUsingClient());
713  //Client* pClient = sEntityList.FindClientByCharID(iRef->ownerID());
714 
715  switch (iRef->typeID()) {
717  if (daysSinceClaim > 2.0f) {
718  break;
719  } else {
720  _log(INV__WARNING, "Inventory::ValidateIHubUpgrade() - Upgrade %s requires a higher development index.", iRef->name());
721  throw CustomError("%s requires a development index of 2", iRef->name());
722  }
723  break;
726  if (daysSinceClaim > 3.0f) {
727  break;
728  } else {
729  _log(INV__WARNING, "Inventory::ValidateIHubUpgrade() - Upgrade %s requires a higher development index.", iRef->name());
730  throw CustomError("%s requires a development index of 3", iRef->name());
731  }
732  break;
733  default:
734  _log(INV__WARNING, "Inventory::ValidateIHubUpgrade() - Upgrade %s is not supported currently.", iRef->name());
735  throw CustomError("%s is not currently supported.", iRef->name());
736  }
737  if (m_self->GetMyInventory()->ContainsItem(iRef->itemID())) {
738  _log(INV__WARNING, "Inventory::ValidateIHubUpgrade() - Upgrade %s is already installed.", iRef->name());
739  throw CustomError("%s is already installed.", iRef->name());
740  }
741 
742  // If we didn't hit anything above, it must be okay to insert item
743  return true;
744 
745 }
746 
748 {
750  if (iRef->categoryID() == EVEDB::invCategories::StructureUpgrade)
751  return ValidateIHubUpgrade(iRef);
752 
753  // i dont think we need to check shit in stations...yet
754  if (m_self->categoryID() == EVEDB::invCategories::Station)
755  return true;
756 
757  Client* pClient(sItemFactory.GetUsingClient());
758 
759  // check that we're close enough if a container in space
760  if (m_self->groupID() == EVEDB::invGroups::Cargo_Container && sDataMgr.IsSolarSystem(m_self->locationID())) {
761  GVector direction (m_self->position(), pClient->GetShip()->position());
762  float maxDistance = 2500.0f;
763 
764  if (m_self->HasAttribute (AttrMaxOperationalDistance) == true)
765  maxDistance = m_self->GetAttribute (AttrMaxOperationalDistance).get_float ();
766 
767  if (direction.length() > maxDistance)
768  throw UserError ("NotCloseEnoughToAdd")
769  .AddAmount ("maxdist", maxDistance);
770  }
771 
772  // check if where the item is coming from was a cargo container
773  InventoryItemRef cRef = sItemFactory.GetItem(iRef->locationID());
774  if (cRef->groupID() == EVEDB::invGroups::Cargo_Container && sDataMgr.IsSolarSystem(cRef->locationID())) {
775  GVector direction (cRef->position(), pClient->GetShip()->position());
776  float maxDistance(2500.0f);
777  if (cRef->HasAttribute (AttrMaxOperationalDistance) == true)
778  maxDistance = cRef->GetAttribute(AttrMaxOperationalDistance).get_float ();
779 
780  if (direction.length() > maxDistance)
781  throw UserError("NotCloseEnoughToLoot")
782  .AddAmount("maxdist", maxDistance);
783  }
784  // can this be coded to check weapon capy? im sure it can. just a flag, right?
785 
786  float capacity = GetRemainingCapacity(flag);
787  float volume = iRef->GetAttribute(AttrVolume).get_float();
788  float totalVolume = iRef->quantity() * volume;
789 
790  _log(INV__CAPY, "Inventory::ValidateAddItem() - Testing %s's %s available capy of %.2f to add %i %s at %.2f (%.3f each)",
791  m_self->name(), sDataMgr.GetFlagName(flag), capacity, iRef->quantity(), iRef->name(), totalVolume, volume);
792 
798  if (m_self->itemID() == iRef->locationID())
799  if ((flag == iRef->flag())
800  or (IsHangarFlag(flag) and IsHangarFlag(iRef->flag()))) {
801  // possible item split. will have to molest the shit outta this one to verify nullablity of exploits
802  capacity += totalVolume;
803  _log(INV__CAPY, "Inventory::ValidateAddItem() - flag() %s (%u) == iRef->flag() %s (%u) - test capacity changed to %.2f",
804  sDataMgr.GetFlagName(flag), flag, sDataMgr.GetFlagName(iRef->flag()), iRef->flag(), capacity);
805  }
806 
807  // check capy for single unit
808  if (capacity < volume) { // smallest volume is 0.0025
809  if (pClient != nullptr) {
810  std::map<std::string, PyRep *> args;
811  args["volume"] = new PyFloat(volume);
812  sItemFactory.UnsetUsingClient();
813  if (IsCargoHoldFlag(flag))
814  throw UserError ("NotEnoughCargoSpace")
815  .AddAmount ("volume", volume)
816  .AddAmount ("available", capacity);
817  else if (flag == flagShipHangar)
818  throw UserError ("NotEnoughCargoSpaceFor1Unit")
819  .AddAmount ("volume", volume)
820  .AddFormatValue ("type", new PyInt (iRef->itemID ()))
821  .AddAmount ("required", volume)
822  .AddAmount ("free", capacity);
823  else if (IsSpecialHoldFlag(flag))
824  throw UserError ("NotEnoughSpecialBaySpaceOverload")
825  .AddAmount ("volume", volume)
826  .AddFormatValue ("item", new PyInt (iRef->itemID ()))
827  .AddAmount ("maximum", GetCapacity (flag))
828  .AddAmount ("user", GetStoredVolume (flag));
829  else if (IsModuleSlot(flag))
830  throw UserError ("NotEnoughChargeSpace")
831  .AddAmount ("volume", volume)
832  .AddAmount ("capacity", GetCapacity (flag));
833  else if (IsHangarFlag(flag))
834  throw UserError ("NotEnoughSpaceOverload")
835  .AddAmount ("volume", volume)
836  .AddLocationName ("item", iRef->itemID ())
837  .AddAmount ("maximum", GetCapacity (flag))
838  .AddAmount ("user", GetStoredVolume (flag));
839  else if (flag == flagDroneBay)
840  throw UserError ("NotEnoughDroneBaySpaceOverload")
841  .AddAmount ("volume", volume)
842  .AddLocationName ("item", iRef->itemID ())
843  .AddAmount ("maximum", GetCapacity (flag))
844  .AddAmount ("used", GetStoredVolume (flag));
845  else
846  throw UserError ("NoSpaceForThatOverload")
847  .AddAmount ("volume", volume)
848  .AddFormatValue ("item", new PyInt (iRef->itemID ()))
849  .AddAmount ("maximum", GetCapacity (flag))
850  .AddAmount ("used", GetStoredVolume (flag));
851  }
852  return false;
853  }
854 
855  // check capy for all units
856  if (totalVolume > capacity) {
857  if (IsSpecialHoldFlag(flag))
858  throw UserError ("NotEnoughSpecialBaySpace")
859  .AddAmount ("volume", totalVolume)
860  .AddAmount ("available", capacity);
861  else if (flag == flagDroneBay)
862  throw UserError ("NotEnoughDroneBaySpace")
863  .AddAmount ("volume", totalVolume)
864  .AddAmount ("available", capacity);
865  else if (IsHangarFlag(flag))
866  throw UserError ("NotEnoughCargoSpaceOverload")
867  .AddAmount ("volume", totalVolume)
868  .AddLocationName ("item", iRef->itemID ())
869  .AddAmount ("maximum", GetCapacity (flag))
870  .AddAmount ("used", GetStoredVolume (flag));
871  else if (IsCargoHoldFlag(flag))
872  throw UserError ("NotEnoughCargoSpace")
873  .AddAmount ("volume", totalVolume)
874  .AddAmount ("available", capacity);
875  else
876  throw UserError ("NoSpaceForThat")
877  .AddAmount ("volume", totalVolume)
878  .AddFormatValue ("itemTypeName", new PyInt (iRef->itemID ()))
879  .AddAmount ("itemVolume", totalVolume)
880  .AddAmount ("volumeAvailable", capacity);
881  return false;
882  }
883 
884  return true;
885 }
886 
887 // multimerge - NotEnoughCargoSpace', 'NotEnoughCargoSpaceOverload', 'NotEnoughDroneBaySpace', 'NotEnoughDroneBaySpaceOverload',
888 // 'NoSpaceForThat', 'NoSpaceForThatOverload', 'NotEnoughChargeSpace'):
889 
890 // add - NotEnoughCargoSpace', 'NotEnoughCargoSpaceOverload', 'NotEnoughDroneBaySpace', 'NotEnoughDroneBaySpaceOverload',
891 // 'NoSpaceForThat', 'NoSpaceForThatOverload', 'NotEnoughChargeSpace', 'NotEnoughSpecialBaySpace', 'NotEnoughSpecialBaySpaceOverload',
892 // 'NotEnoughSpace'):
893 
894 //{'FullPath': u'UI/Messages', 'messageID': 259240, 'label': u'NotEnoughSpaceBody'}(u'{[numeric]volume} {[numeric]volume -> "unit", "units"} of space would be required to complete this operation. Destination container only has {[numeric]available} {[numeric]available-> "unit", "units"} available.', None, {u'{[numeric]volume}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'volume'}, u'{[numeric]volume -> "unit", "units"}': {'conditionalValues': [u'unit', u'units'], 'variableType': 9, 'propertyName': None, 'args': 320, 'kwargs': {}, 'variableName': 'volume'}, u'{[numeric]available-> "unit", "units"}': {'conditionalValues': [u'unit', u'units'], 'variableType': 9, 'propertyName': None, 'args': 320, 'kwargs': {}, 'variableName': 'available'}, u'{[numeric]available}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'available'}})
895 
896 //{'FullPath': u'UI/Messages', 'messageID': 259447, 'label': u'ItemMoveGoesThroughFullCargoHoldBody'}(u'You fail to move the {[item]itemType.name} as it gets invisibly moved to your cargo hold before it gets moved elsewhere and your cargo hold is full.', None, {u'{[item]itemType.name}': {'conditionalValues': [], 'variableType': 2, 'propertyName': 'name', 'args': 0, 'kwargs': {}, 'variableName': 'itemType'}})
897 
898 //{'FullPath': u'UI/Messages', 'messageID': 259195, 'label': u'NotPermittedToAddCharBody'}(u'You cannot put items into that container because it belongs to {[character]owner.name} and you are not in their fleet, their corporation or held in the highest personal standing by them.', None, {u'{[character]owner.name}': {'conditionalValues': [], 'variableType': 0, 'propertyName': 'name', 'args': 0, 'kwargs': {}, 'variableName': 'owner'}})
899 
900 //{'FullPath': u'UI/Messages', 'messageID': 259161, 'label': u'NotEnoughCargoSpaceBody'}(u'{[numeric]volume} {[numeric]volume -> "cargo unit", "cargo units"} would be required to complete this operation. Destination container only has {[numeric]available} {[numeric]available -> "unit", "units"} available.', None, {u'{[numeric]volume}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'volume'}, u'{[numeric]volume -> "cargo unit", "cargo units"}': {'conditionalValues': [u'cargo unit', u'cargo units'], 'variableType': 9, 'propertyName': None, 'args': 320, 'kwargs': {}, 'variableName': 'volume'}, u'{[numeric]available}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'available'}, u'{[numeric]available -> "unit", "units"}': {'conditionalValues': [u'unit', u'units'], 'variableType': 9, 'propertyName': None, 'args': 320, 'kwargs': {}, 'variableName': 'available'}})
901 
902 //{'FullPath': u'UI/Messages', 'messageID': 257335, 'label': u'NotEnoughSpecialBaySpaceBody'}(u'{volume} units would be required to complete this operation. Destination bay only has {available} units available.', None, {u'{available}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'available'}, u'{volume}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'volume'}})
903 //{'FullPath': u'UI/Messages', 'messageID': 257337, 'label': u'NotEnoughSpecialBaySpaceOverloadBody'}(u'That cargo bay is overloaded and cannot be made to fit {item}. It is currently only capable of fitting {maximum} units and it is currently jammed full with {used}units.', None, {u'{maximum}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'maximum'}, u'{item}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'item'}, u'{used}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'used'}})
904 //{'FullPath': u'UI/Messages', 'messageID': 257338, 'label': u'CannotStoreDestinationRestrictedBody'}(u'You cannot place a {item} into that location in your {[item]ship.name}. The bay you are trying to access is specialized and can only handle certain types of items.', None, {u'{item}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'item'}, u'{[item]ship.name}': {'conditionalValues': [], 'variableType': 2, 'propertyName': 'name', 'args': 0, 'kwargs': {}, 'variableName': 'ship'}})
905 //{'FullPath': u'UI/Messages', 'messageID': 259154, 'label': u'NoSpaceForThatBody'}(u"You can't add the {[item]itemTypeName.name} as there simply isn't enough room for it to fit. It takes up {[numeric]itemVolume, decimalPlaces=2} units of volume, and there are only {[numeric]volumeAvailable} left.", None, {u'{[item]itemTypeName.name}': {'conditionalValues': [], 'variableType': 2, 'propertyName': 'name', 'args': 0, 'kwargs': {}, 'variableName': 'itemTypeName'}, u'{[numeric]volumeAvailable}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'volumeAvailable'}, u'{[numeric]itemVolume, decimalPlaces=2}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 512, 'kwargs': {'decimalPlaces': 2}, 'variableName': 'itemVolume'}})
906 //{'FullPath': u'UI/Messages', 'messageID': 259141, 'label': u'NotEnoughCargoSpaceFor1UnitBody'}(u'One unit of {[item]type.name} would take {[numeric]required, decimalPlaces=2} units of space. This container only has {[numeric]free, decimalPlaces=2} units free.', None, {u'{[numeric]free, decimalPlaces=2}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 512, 'kwargs': {'decimalPlaces': 2}, 'variableName': 'free'}, u'{[item]type.name}': {'conditionalValues': [], 'variableType': 2, 'propertyName': 'name', 'args': 0, 'kwargs': {}, 'variableName': 'type'}, u'{[numeric]required, decimalPlaces=2}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 512, 'kwargs': {'decimalPlaces': 2}, 'variableName': 'required'}})
907 //{'FullPath': u'UI/Messages', 'messageID': 259208, 'label': u'NotEnoughCargoSpaceOverloadBody'}(u'The cargo bay is overloaded and cannot be made to fit {item}. It is currently only capable of fitting {maximum} units and it is currently jammed full with {used} units.', None, {u'{maximum}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'maximum'}, u'{item}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'item'}, u'{used}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'used'}})
908 //{'FullPath': u'UI/Messages', 'messageID': 259191, 'label': u'NotEnoughDroneBaySpaceBody'}(u'{[numeric]volume} units would be required to complete this operation. Destination container only has {[numeric]available} units available.', None, {u'{[numeric]volume}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'volume'}, u'{[numeric]available}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'available'}})
909 //{'FullPath': u'UI/Messages', 'messageID': 259210, 'label': u'NotEnoughDroneBaySpaceOverloadBody'}(u'The drone bay is overloaded and cannot be made to fit {item}. It is currently only capable of fitting {maximum} units and it is currently jammed full with {used} units.', None, {u'{maximum}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'maximum'}, u'{item}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'item'}, u'{used}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'used'}})
910 //{'FullPath': u'UI/Messages', 'messageID': 259213, 'label': u'NotEnoughSpaceOverloadBody'}(u'The storage area is overloaded and cannot be made to fit any {item}. It is currently only capable of fitting {maximum} units and it is currently jammed full with {used} units.', None, {u'{maximum}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'maximum'}, u'{item}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'item'}, u'{used}': {'conditionalValues': [], 'variableType': 10, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'used'}})
911 //{'FullPath': u'UI/Messages', 'messageID': 259183, 'label': u'NoSpaceForThatOverloadBody'}(u"You can't add the {[item]item.name} as there simply isn't enough room for it to fit. The container is currently only capable of fitting {[numeric]maximum} units and it is currently jammed full with {[numeric]used} units.", None, {u'{[numeric]used}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'used'}, u'{[item]item.name}': {'conditionalValues': [], 'variableType': 2, 'propertyName': 'name', 'args': 0, 'kwargs': {}, 'variableName': 'item'}, u'{[numeric]maximum}': {'conditionalValues': [], 'variableType': 9, 'propertyName': None, 'args': 0, 'kwargs': {}, 'variableName': 'maximum'}})
void GetInvForOwner(uint32 ownerID, std::vector< InventoryItemRef > &items)
Definition: Inventory.cpp:425
float GetRemainingCapacity(EVEItemFlags flag) const
Definition: Inventory.h:72
#define sConfig
A macro for easier access to the singleton.
void GetInventoryVec(std::vector< InventoryItemRef > &itemVec)
Definition: Inventory.cpp:345
float GetCapacity(EVEItemFlags flag) const
Definition: Inventory.cpp:642
uint32 locID
bool GetTypesByFlag(EVEItemFlags flag, std::map< uint16, InventoryItemRef > &items)
Definition: Inventory.cpp:465
#define _log(type, fmt,...)
Definition: logsys.h:124
#define sConsole
void StackAll(EVEItemFlags flag, uint32 ownerID=0)
Definition: Inventory.cpp:575
InventoryItemRef FindFirstByFlag(EVEItemFlags flag) const
Definition: Inventory.cpp:436
bool ContainsTypeByFlag(uint16 typeID, EVEItemFlags flag=flagNone) const
Definition: Inventory.cpp:561
bool HasAvailableSpace(EVEItemFlags flag, InventoryItemRef iRef) const
Definition: Inventory.cpp:625
#define IsAgent(itemID)
Definition: EVE_Defines.h:247
void AddItem(InventoryItemRef iRef)
Definition: Inventory.cpp:203
static void SaveItems(std::vector< Inv::SaveData > &data)
Definition: ItemDB.cpp:264
EVEItemFlags
Definition: EVE_Flags.h:13
std::multimap< uint8, InventoryItemRef > m_contentsByFlag
Definition: Inventory.h:115
#define sProfiler
Definition: dbcore.cpp:39
float GetCorpHangerCapyUsed() const
Definition: Inventory.cpp:337
Python floating point number.
Definition: PyRep.h:292
void DeleteContents()
Definition: Inventory.cpp:273
void RemoveItem(InventoryItemRef iRef)
Definition: Inventory.cpp:243
UserError & AddFormatValue(const char *name, PyRep *value)
Fluent version of the protected AddKeyword, allows for adding a keyword to the exception.
bool IsEmptyByFlag(EVEItemFlags flag) const
Definition: Inventory.cpp:498
Advanced version of UserError that allows to send a full custom message.
Definition: PyExceptions.h:453
void Dump(FILE *into, const char *pfx) const
Dumps object to file.
Definition: PyRep.cpp:84
* args
uint32 GetItemsByFlag(EVEItemFlags flag, std::vector< InventoryItemRef > &items) const
Definition: Inventory.cpp:458
bool GetItems(OwnerData od, std::vector< uint32 > &into)
Definition: Inventory.cpp:109
void Unload()
Definition: Inventory.cpp:62
#define is_log_enabled(type)
Definition: logsys.h:78
const int64 Win32Time_Day
Definition: utils_time.cpp:41
UserError & AddAmount(const char *name, int quantity)
Shorthand method for adding a quantity value.
double GetTimeUSeconds()
Definition: utils_time.cpp:116
uint32 corpID
std::string customInfo
bool GetItemContents(OwnerData &od, std::vector< uint32 > &into)
#define IsPlayerItem(itemID)
Definition: EVE_Defines.h:256
EVEItemFlags flag
Definition: EVE_Inventory.h:97
Python object "blue.DBRowDescriptor".
Definition: PyDatabase.h:41
Inventory(InventoryItemRef iRef)
Definition: Inventory.cpp:49
std::map< uint32, InventoryItemRef > mContents
Definition: Inventory.h:114
Python object "dbutil.CRowset".
Definition: PyDatabase.h:124
Python integer.
Definition: PyRep.h:231
#define IsSpecialHoldFlag(flag)
Definition: EVE_Defines.h:340
void GetCargoList(std::multimap< uint8, InventoryItemRef > &cargoMap)
Definition: Inventory.cpp:332
static void LoadOffices(OwnerData &od, std::vector< uint32 > &into)
Definition: StationDB.cpp:180
X * get() const
Definition: RefPtr.h:213
#define IsFittingSlot(flag)
Definition: EVE_Defines.h:355
uint32 ownerID
#define IsPlayerCorp(itemID)
Definition: EVE_Defines.h:241
#define IsCharacterID(itemID)
Definition: EVE_Defines.h:206
Python object "ccp_exceptions.UserError".
Definition: PyExceptions.h:121
Definition: Client.h:66
static RefPtr StaticCast(const RefPtr< Y > &oth)
Acts as static_cast from one RefPtr to another.
Definition: RefPtr.h:238
bool ValidateIHubUpgrade(InventoryItemRef iRef) const
Definition: Inventory.cpp:706
unsigned __int32 uint32
Definition: eve-compat.h:50
uint32 GetItemsByFlagSet(std::set< EVEItemFlags > flags, std::vector< InventoryItemRef > &items) const
Definition: Inventory.cpp:514
void GetInventoryMap(std::map< uint32, InventoryItemRef > &invMap)
Definition: Inventory.cpp:453
RefPtr< InventoryItem > InventoryItemRef
Definition: ItemRef.h:52
double GetFileTimeNow()
Definition: utils_time.cpp:84
#define IsOfficeID(itemID)
Definition: EVE_Defines.h:253
#define IsModuleSlot(flag)
Definition: EVE_Defines.h:350
#define IsCargoHoldFlag(flag)
Definition: EVE_Defines.h:336
bool LoadContents()
Definition: Inventory.cpp:113
InventoryItemRef GetItemByTypeFlag(uint16 typeID, EVEItemFlags flag=flagNone)
Definition: Inventory.cpp:476
void Reset()
Definition: Inventory.cpp:56
PyPackedRow * NewRow()
Definition: PyDatabase.cpp:132
#define IsHangarFlag(flag)
Definition: EVE_Defines.h:344
void traceStack(void)
Definition: misc.cpp:169
#define sItemFactory
Definition: ItemFactory.h:165
Packed row.
Definition: PyRep.h:961
Definition: gpoint.h:70
#define svDataMgr
std::vector< InventoryItemRef > SortVector(std::vector< InventoryItemRef > &itemVec)
Definition: Inventory.cpp:356
bool ContainsTypeQtyByFlag(uint16 typeID, EVEItemFlags flag=flagNone, uint32 qty=0) const
Definition: Inventory.cpp:542
#define maxHangarCapy
Definition: EVE_Defines.h:168
bool mContentsLoaded
Definition: Inventory.h:107
unsigned __int16 uint16
Definition: eve-compat.h:48
entityID heal the character with the entityID note giving you detailed ship status information gives a list of all dynamic entities and players and their destinyState in this bubble shows some current destiny variables save all items
InventoryDB m_db
Definition: Inventory.h:103
InventoryItemRef GetByTypeFlag(uint32 typeID, EVEItemFlags flag) const
Definition: Inventory.cpp:444
CRowSet * List(EVEItemFlags flag, uint32 ownerID=0) const
Definition: Inventory.cpp:290
uint32 m_myID
Definition: Inventory.h:109
uint32 GetItemsByFlagRange(EVEItemFlags low_flag, EVEItemFlags high_flag, std::vector< InventoryItemRef > &items) const
Definition: Inventory.cpp:502
bool ValidateAddItem(EVEItemFlags flag, InventoryItemRef iRef) const
Definition: Inventory.cpp:747
bool ContainsTypeQty(uint16 typeID, uint32 qty=0) const
Definition: Inventory.cpp:526
InventoryItemRef GetByID(uint32 id) const
Definition: Inventory.cpp:415
const char * itoa(int64 num)
Convers num to string.
float GetStoredVolume(EVEItemFlags flag, bool combined=true) const
Definition: Inventory.cpp:609
void AddStationHangar(uint32 stationID)
Definition: Client.cpp:1652
bool GetSingleItemByFlag(EVEItemFlags flag, InventoryItemRef &iRef) const
Definition: Inventory.cpp:489
UserError & AddLocationName(const char *name, uint32 locationID)
Shorthand method for adding a location's name.
Reference-counting-based smart pointer.
Definition: RefPtr.h:133
#define sDataMgr
InventoryItemRef m_self
Definition: Inventory.h:104