From 9eb7481c06daac5546dabcaf23a03ef648c570b9 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Thu, 12 Nov 2020 13:25:08 +0800 Subject: [PATCH] Cleanup CGameItemPtr, add reference count to avoid glitches, kaetemi/ryzomclassic#194 --- .../game_item_manager/game_item.cpp | 907 ++---------------- .../game_item_manager/game_item.h | 444 +++------ .../game_item_manager/game_item_ptr.h | 24 +- 3 files changed, 201 insertions(+), 1174 deletions(-) diff --git a/ryzom/server/src/entities_game_service/game_item_manager/game_item.cpp b/ryzom/server/src/entities_game_service/game_item_manager/game_item.cpp index 251c63d51..245e6e406 100644 --- a/ryzom/server/src/entities_game_service/game_item_manager/game_item.cpp +++ b/ryzom/server/src/entities_game_service/game_item_manager/game_item.cpp @@ -41,13 +41,15 @@ using namespace NLNET; extern CPlayerManager PlayerManager; +#if 0 NL_INSTANCE_COUNTER_IMPL(CGameItem); +#endif //-------------------------------------------------------------------- // singleton data CGameItemVector CGameItem::_Items; -uint32 CGameItem::_FirstFreeItem; +uint32 CGameItem::_FirstFreeItem = 1; // Item 0 is invalid! #if 0 uint32 CGameItem::_BugTestCounter; #endif @@ -732,31 +734,26 @@ void CGameItem::callItemChanged(INVENTORIES::TItemChangeFlags changeFlags) void CGameItemPtr::deleteItem() { - CGameItem *item=**this; + CGameItem *item = **this; - BOMB_IF( item == NULL, "Attempt to delete an item that is not allocated or has been freed", return ); + BOMB_IF(item == NULL, "Attempt to delete an item that is not allocated or has been freed", return); if (item->_Inventory != NULL) item->_Inventory->removeItem(item->getInventorySlot()); - // only unlink if the pointer 'this' is not the same as the inventory ptr for the item - // after the unlink this == NULL -// if (! ( item->_Parent!=NULL && -// item->Loc.Slot_Parent->getChildren().size() && -// &(item->_Parent->getChildren()[item->Loc.Slot])==this ) ) - unlinkFromItem(); - - // call dtor now to unlink all children - item->dtor(); - // check no one else is referencing us -#ifdef GAME_PTR_DEBUG - nlassert(item->_Ptrs.empty()); -#endif + // FIXME: Item delete can occur outside of context... (character log out) + // This does not match with newItem behaviour. + // Function decRef automatically deletes the real item, so deleteItem does not have to be called for automatic deletes! + log_Item_Delete(item->getItemId(), item->getSheetId(), item->getStackSize(), item->quality()); - CGameItem::deleteItem(item); -#if 0 - item->_BugTestUpdate=CGameItem::_BugTestCounter; -#endif + decRef(); + + if (static_cast(item)->PtrRefCount > 0) + { + nlwarning("Game item deleted, but still referenced"); + } + + m_Idx = 0; } //----------------------------------------------- @@ -771,14 +768,10 @@ void CGameItemPtr::deleteItem() //----------------------------------------------- void CGameItem::ctor() { - // if we have children already we need to get rid of them cleanly! -// if (!_Children.empty()) -// dtor(); + clear(); // Generate a new Item id _ItemId = INVENTORIES::TItemId(); - - clear(); }; //----------------------------------------------- @@ -789,6 +782,7 @@ void CGameItem::ctor() void CGameItem::ctor( const CSheetId& sheetId, uint32 recommended, bool destroyable, bool dropable ) { ctor(); + // _ItemId = id; _SheetId = sheetId; _Destroyable = destroyable; @@ -1166,54 +1160,55 @@ void CGameItem::setLockedByOwner(bool value) //----------------------------------------------- CGameItemPtr CGameItem::getItemCopy() { + // used for + // - NPC item sales + // - stack splitting + // - creating named items + // create a new item CGameItemPtr ret; - ret.newItem(true); + ret.newItem(); // backup id and allocation data -// CEntityId itemId(RYZOMID::object, GameItemManager.getFreeItemIndice() ); - sint32 alloc = ret->_AllocatorData; + // CEntityId itemId(RYZOMID::object, GameItemManager.getFreeItemIndice() ); // use the default copy ctor to init it - CGameItem* item = *ret; -#ifdef GAME_PTR_DEBUG - std::vector old; - old= item->_Ptrs; -#endif + CGameItem *item = *ret; *item = *this; -#ifdef GAME_PTR_DEBUG - *(CGameItemPtrArray*)item->_Ptrs=old; -#endif // generate a new item id item->_ItemId = INVENTORIES::TItemId(); - // reset allocator - item->_AllocatorData = alloc; + // reset dynamic elements. ( we do it this way because people who add gameplay data properties will probably forget to update this method. So it is safe this way - item->_StackSize = _StackSize; - item->_Looter = CEntityId::Unknown; -// item->_Id = itemId; - item->_AllocatorData = alloc; -// item->_IsOnTheGround = false; -// item->_Parent = NULL; + item->_Looter = CEntityId::Unknown; item->_Inventory = NULL; item->_InventorySlot = INVENTORIES::INVALID_INVENTORY_SLOT; item->_RefInventory = NULL; item->_RefInventorySlot = INVENTORIES::INVALID_INVENTORY_SLOT; - item->_CreatorId = _CreatorId; item->_LockCount = 0; item->_HP = item->maxDurability(); item->_LostHPremains = 0.0f; + item->_LockedByOwner = false; + item->_Movable = false; + item->_UnMovable = false; + + // item->_StackSize = 1; + // item->_CreatorId = CEntityId::Unknown; // item->_Enchantment.clear(); // item->_SapLoad = 0.0f; + // item->_Id = itemId; + // item->_IsOnTheGround = false; + // item->_Parent = NULL; + item->computeItemWornState(); log_Item_Create(item->getItemId(), item->getSheetId(), item->getStackSize(), item->quality()); return ret; } + //----------------------------------------------- // sendNameId : //----------------------------------------------- @@ -1240,101 +1235,15 @@ uint32 CGameItem::sendNameId(CCharacter * user) return 0; } -//----------------------------------------------- -// ~CGameItem : -//----------------------------------------------- -void CGameItem::dtor() -{ - // detach from parent -// detachFromParent(); -// detachFromInventory(); - - if (getInventory() != NULL) - { - getInventory()->removeItem(getInventorySlot()); - } - - // destroy children. As they call detachFromParent() when destroyed and _Children vector may be resized - // we must make a copy of _children ptrs before - // so we now work on a safe copy of _Children vector -// vector children = _Children; -// const sint size = children.size(); -// for (sint i = size-1 ; i >= 0 ; --i) -// { -// if(children[i] != NULL && children[i] != this) -// { -// // debug level 2 loop -// for(uint j = 0; j < children[i]->_Children.size(); j++) -// if(children[i]->_Children[j] == this) goto failed; -// -// detachChild(i); -// children[i].deleteItem(); -// } -// } -// if( _CraftParameters != NULL ) -// { -// delete _CraftParameters; -// _CraftParameters = 0; -// } -// failed: -// _Children.clear(); -// GameItemManager.removeFromMap( _Id ); - -// CGameItemPtr item(this); -// GameItemManager.removeFromMap(item); -} - -//void CGameItem::copyItem(const CGameItemPtr &model) -//{ -// // Copy all parameter for the item -// // Inventory info, lock state and looter are not copied -// _StackSize = model->_StackSize; -// //_Looter -// _SheetId = model->_SheetId; -// _Destroyable = model->_Destroyable; -// _Dropable = model->_Dropable; -// _Recommended = model->_Recommended; -// _HP = model->_HP; -// _LostHPremains = model->_LostHPremains; -// _CurrentWornState = model->_CurrentWornState; -// _SapLoad = model->_SapLoad; -// _CraftParameters = model->_CraftParameters; -// _CreatorId = model->_CreatorId; -// //_LockCount -// _Enchantment = model->_Enchantment; -// _Form = model->_Form; -// _PhraseId = model->_PhraseId; -// _LatencyEndDate = model->_LatencyEndDate; -// _TotalSaleCycle = model->_TotalSaleCycle; -// -// computeRequirementFromForm(); -// -// _TypeSkillMods = model->_TypeSkillMods; -//} -// - //----------------------------------------------- // clear : // //----------------------------------------------- void CGameItem::clear() { - // remove all of the item's children -// for (uint32 i=0;i<_Children.size();++i) -// if (_Children[i]!=NULL) -// _Children[i].deleteItem(); - - // if the item was a stack then resize the children vector back down to 0 -// if (_SheetId==NLMISC::CSheetId("stack.sitem")) -// { -// // TODO : remove when no more trace of stack.sitem -// nlassert(false); -// _Children.clear(); -// } - // clear the enchantment _Enchantment.clear(); - contReset( _Enchantment ); + contReset(_Enchantment); _CraftParameters = NULL; @@ -1797,8 +1706,9 @@ uint32 CGameItem::getMaxStackSize() const //----------------------------------------------- CGameItem * CGameItem::getItem(uint idx) { - BOMB_IF( idx>=_Items.size(), "Attempt to access an item beyond end of item vector", return 0 ); - BOMB_IF( _Items[idx]._AllocatorData>=0, NLMISC::toString("Attempt to access an item that is not allocated or has been freed (idx: %d)",idx), return 0 ); + BOMB_IF( !idx, "Attempt to access a null item pointer", return &_Items[0] ); + BOMB_IF( idx>=_Items.size(), "Attempt to access an item beyond end of item vector", return &_Items[0] ); + BOMB_IF( _Items[idx].AllocatorNext>=0, NLMISC::toString("Attempt to access an item that is not allocated or has been freed (idx: %d)",idx), return &_Items[0] ); return &_Items[idx]; } @@ -1810,49 +1720,22 @@ CGameItem *CGameItem::newItem() { // NOTE // the following assert is very important as the rest of this algorithm depends on this condition being met - nlassert(_FirstFreeItem<=_Items.size()); + nlassert(_FirstFreeItem <= _Items.size()); // see whether there are any deleted items awaiting re-allocation - if (_FirstFreeItem==_Items.size()) + if (_FirstFreeItem == _Items.size()) { // no unallocated items found so allocate a bit more RAM -// uint sizeIncrement=65536; //16; //65536; // use 16 for testing - likely 64k for exploitation -// egs_giinfo("Increased item vector size to %d items",(_Items.size()+1)*sizeIncrement); -// for (uint i=0;i=0); - // overwrite the _AllocatorData with a unique(ish) negative value - if (--_NextAllocatorDataValue>=0) - _NextAllocatorDataValue=-1; - _Items[idx]._AllocatorData=_NextAllocatorDataValue; - - #ifdef NL_DEBUG - // make sure the linked list of free blocks is intact - uint i,j,k; - for(i=0, j=0; i<_Items.size(); ++i) - if (_Items[i]._AllocatorData>=0) - ++j; - for(i=_FirstFreeItem, k=0; i<_Items.size(); i=_Items[i]._AllocatorData) - ++k; - nlassert(j==k); - #endif - - // TODO: replace this egs_giinfo() with a LOG() -// egs_giinfo("newItem(): %5d (free: %d/%d)",idx,j,_Items.size()); - #endif + uint32 idx = _FirstFreeItem; + CGameItemEntry &item = _Items[idx]; + _FirstFreeItem = item.AllocatorNext; + item.AllocatorNext = 0; - return &_Items[idx]; + return static_cast(&item); } //----------------------------------------------- @@ -1861,695 +1744,23 @@ CGameItem *CGameItem::newItem() //----------------------------------------------- void CGameItem::deleteItem(CGameItem *item) { - uint32 idx=_Items.getUniqueIndex(*item); - BOMB_IF( idx == ~0u, "Delete item failed because getIndex failed", return); + + BOMB_IF( idx == 0, "Delete item failed because getIndex failed", return); BOMB_IF( item->_Inventory != NULL, "Item still in an inventory while deleting", item->_Inventory->removeItem(item->getInventorySlot());); BOMB_IF( item->_RefInventory != NULL, "Item still in a ref inventory while deleting", item->_RefInventory->removeItem(item->getRefInventorySlot());); - log_Item_Delete(item->getItemId(), item->getSheetId(), item->getStackSize(), item->quality()); - // this test would only have value if the implementation of std::vector<> doesn't guarantee a // continuous memory address space for the vector's data // It's not in the #IFDEF DEBUG because it may only be triggered in very obscure conditions - nlassert(&_Items[idx]==item); - - #ifdef ITEM_DEBUG - // make sure idx is within the _Items vector - nlassert(idx<_Items.size()); - // make sure the item hasn't already been liberated - - nlassert(_Items[idx]._AllocatorData<0); - - #ifdef NL_DEBUG - // make sure the linked list of free blocks is intact - uint i,j,k; - for(i=0, j=0; i<_Items.size(); ++i) - if (_Items[i]._AllocatorData>=0) - ++j; - for(i=_FirstFreeItem, k=0; i<_Items.size() && k<_Items.size(); i=_Items[i]._AllocatorData) - ++k; - nlassert(j==k); - #endif - - // TODO: replace this egs_giinfo() with a LOG() -// egs_giinfo("deleteItem(): %5d (free: %d/%d)",idx,j,_Items.size()); - #endif - - _Items[idx]._AllocatorData=_FirstFreeItem; - _FirstFreeItem=idx; + nlassert(&_Items[idx] == item); + CGameItemEntry *entry = static_cast(item); + nlassert(idx == entry->VectorIdx); + nlassert(!entry->AllocatorNext); + entry->AllocatorNext = _FirstFreeItem; + _FirstFreeItem = idx; } -//void CGameItem::save( NLMISC::IStream &f ) -//{ -// //NLMEMORY::CheckHeap (true); -// -// if ( _IsOnTheGround ) -// nlwarning(" saving an object on the ground should never happen sheet: %s, id: %s ",_SheetId.toString().c_str(), _Id.toString().c_str() ); -// // save item infos -// f.serial( _SlotImage ); -// f.serial( _SheetId ); -// f.serial( Owner ); -// if( Owner != CEntityId::Unknown ) -// { -// f.serial(Loc.Slot); -// } -// else -// { -// f.serial( Loc.Pos.X ); -// f.serial( Loc.Pos.Y ); -// f.serial( Loc.Pos.Z ); -// } -// -// //NLMEMORY::CheckHeap (true); -// -// f.serial( TimeOnTheGround ); -// f.serial( SlotCount ); -// f.serial( _CarrionSheetId ); -// f.serial( _Destroyable ); -// f.serial( _Dropable); -// -// f.serial( _CreatorId ); -// -// f.serial( _HP ); -// f.serial( _Recommended ); -// f.serialPtr( _CraftParameters ); -// f.serial( _LostHPremains ); -// -// //NLMEMORY::CheckHeap (true); -// -// // serial rm used for craft item -//// f.serialCont( _RmUsedForCraft ); -// std::vector RmUsedCraft; -// f.serialCont( RmUsedCraft ); -// -// //NLMEMORY::CheckHeap (true); -// -// // serial position in bag inventory -// f.serial(_ClientInventoryPosition); -// -// -// f.serial( _SapLoad ); -// f.serialCont( _Enchantment ); -// -// //NLMEMORY::CheckHeap (true); -// -// // save children count -// uint32 childrenCount = _Children.size(); -// f.serial( childrenCount ); -// -// // save non null children count -// uint32 nonNullChildrenCount = 0; -// uint32 i; -// for( i = 0; i < childrenCount; ++i ) -// { -// if( _Children[i]!=NULL && _Children[i] != this ) -// ++nonNullChildrenCount; -// } -// f.serial( nonNullChildrenCount ); -// -// //NLMEMORY::CheckHeap (true); -// -// string sheetName = _SheetId.toString(); -// -// // for each non null child -// for( i = 0; i < childrenCount; ++i ) -// { -// if( _Children[i]!=NULL && _Children[i] != this ) -// { -// // save child index -// f.serial( i ); -// -// // save child -// (*_Children[i])->save( f ); -// -// if (getSheetId() == CSheetId("stack.sitem")) -// break; -// -// } -// } -// //NLMEMORY::CheckHeap (true); -//} // save // - - -//----------------------------------------------- -// load : -// -//----------------------------------------------- -//void CGameItem::legacyLoad( NLMISC::IStream &f, uint16 characterSerialVersion, CCharacter *ownerPtr ) -//{ -// _LatencyEndDate = 0; -// uint16 slotImage; -// NLMISC::CEntityId owner; -// uint8 slot = 0; -// sint32 coord = 0; -// NLMISC::TGameCycle timeOnGround = 0; -// sint16 slotCount = 0; -// uint32 carrionSheetId = 0; -// -// //NLMEMORY::CheckHeap (true); -//// try -//// { -// if ( characterSerialVersion >= 32 ) -// { -//// f.serial(_SlotImage); -// f.serial(slotImage); -// } -// -// if( characterSerialVersion >= 17 ) -// { -// // load item infos -// f.serial( _SheetId ); -// -// -///***/ string sheetString = _SheetId.toString(); -// -//// f.serial( Owner ); -// f.serial(owner); -//// if( Owner != CEntityId::Unknown ) -// if( owner != CEntityId::Unknown ) -// { -//// f.serial(Loc.Slot); -// f.serial(slot); -// } -// else -// { -//// f.serial( Loc.Pos.X ); -//// f.serial( Loc.Pos.Y ); -//// f.serial( Loc.Pos.Z ); -// f.serial(coord); -// f.serial(coord); -// f.serial(coord); -// } -// -// //NLMEMORY::CheckHeap (true); -// -//// f.serial( TimeOnTheGround ); -// f.serial(timeOnGround); -//// f.serial( SlotCount ); -// f.serial(slotCount); -//// f.serial( _CarrionSheetId ); -// f.serial(carrionSheetId); -// -// f.serial( _Destroyable ); -// if ( characterSerialVersion >= 19 ) -// f.serial(_Dropable); -// -// f.serial( _CreatorId ); -// -// f.serial( _HP ); -// f.serial( _Recommended ); -// -// if (_CraftParameters == NULL) -// _CraftParameters = new CItemCraftParameters(); -// f.serial( *_CraftParameters ); -// -// if ( characterSerialVersion >= 55 ) -// f.serial(_LostHPremains); -// -// //NLMEMORY::CheckHeap (true); -// -// // serial rm used for craft item -//// f.serialCont( _RmUsedForCraft ); -// std::vector RmUsedCraft; -// f.serialCont( RmUsedCraft ); -// -// // ANTIBUG : huge rm vector serialized !!!! -//// if ( f.isReading() && _RmUsedForCraft.size() >= 1000 ) -//// _RmUsedForCraft.clear(); -// -// //NLMEMORY::CheckHeap (true); -// -// f.serial(_ClientInventoryPosition); -// -// if( characterSerialVersion >= 20 ) -// { -// f.serial( _SapLoad ); -// f.serialCont( _Enchantment ); -// } -// -// // load children count -// uint32 childrenCount = 0; -// f.serial( childrenCount ); -//// -//// // load non null children count -// uint32 nonNullChildrenCount = 0; -// f.serial( nonNullChildrenCount ); -//// -//// //NLMEMORY::CheckHeap (true); -//// -// bool isStack = false; -// if ( _SheetId == CSheetId("stack.sitem") ) -// { -// // stack do not have NULL items -// isStack = true; -// if ( nonNullChildrenCount != childrenCount ) -// { -//// nlwarning("char %s a stack contains NULL items! children: '%d' non null children: '%d'", Idc.toString().c_str(),childrenCount,nonNullChildrenCount); -// nlwarning(" A stack contains NULL items! children: '%d' non null children: '%d'", -// childrenCount, -// nonNullChildrenCount); -// } -// } -// else -// { -// nlassertex(childrenCount == 0, ("Can't read old inventory item as item, must be read as inventory")); -//// _Children.resize( childrenCount, NULL ); -// } -//// -//// //NLMEMORY::CheckHeap (true); -//// -// uint32 i; -// for( i = 0; i < nonNullChildrenCount; ++i ) -// { -//// // load child index -//// //NLMEMORY::CheckHeap (true); -//// -// uint32 index; -// f.serial( index ); -//// -//// //NLMEMORY::CheckHeap (true); -//// -//// // load child -// CGameItemPtr item; -// item.newItem(); -//// -//// //NLMEMORY::CheckHeap (true); -//// CEntityId id( RYZOMID::object, GameItemManager.getFreeItemIndice() ); -//// item->_Id = id; -//// //NLMEMORY::CheckHeap (true); -// if( item!=NULL ) -// { -//// //NLMEMORY::CheckHeap (true); -//// (*item)->load(f, Idc, characterSerialVersion); -// item->legacyLoad(f, characterSerialVersion, ownerPtr); -//// //NLMEMORY::CheckHeap (true); -// } -// else -// { -//// nlwarning("char %s Can't allocate child item %d",Idc.toString().c_str(),i); -// nlwarning("Can't allocate child item %d", i); -// return; -// } -// -// if (i == 0) -// { -// // replace the current item with the first stacked item -// copyItem(item); -// } -//// -// // delete this garbage item -// item.deleteItem(); -// -//// //NLMEMORY::CheckHeap (true); -//// -//// // add child in children -//// if (isStack) -//// _Children.push_back(item); -//// else -//// { -//// if( index == ((uint32)-1) || (index >= _Children.size()) ) -//// { -//// nlwarning(" load children item with bad index = %d (item number slots %d ), skip it...", index, _Children.size() ); -//// -//// for( index = 0; index < _Children.size(); ++index ) -//// { -//// if(_Children[index] == 0 ) break; -//// } -//// } -//// if( index < _Children.size() ) -//// { -//// _Children[index] = item; -//// } -//// else -//// { -//// nlwarning(" load children item with bad index = %d (item number slots %d ), skip it...", index, _Children.size() ); -//// } -//// } -//// -//// //NLMEMORY::CheckHeap (true); -//// -//// // set the parent -//// (*item)->setParent( this ); -//// -//// //NLMEMORY::CheckHeap (true); -//// -//// // add item in manager -//// GameItemManager.insertItem( item ); -//// -//// -//// if (getSheetId() == CSheetId("stack.sitem") && characterSerialVersion>=43 ) -//// { -//// for (uint32 j=1;jgetCopy(); -//// if ( copy != NULL ) -//// { -//// //_Children.push_back( copy ); -//// addChild(copy); -//// } -//// } -//// break; -//// } -//// -//// //NLMEMORY::CheckHeap (true); -// } -// -// // Set the stack size -// if (nonNullChildrenCount == 0) -// nonNullChildrenCount = 1; // ANTI-BUG: repair empty stacks... is it a good solution? -// -// setStackSize(nonNullChildrenCount); -// -///* // not sure about version number -// if( characterSerialVersion < 17 && characterSerialVersion > 13 ) -// { -// f.serial(_ClientInventoryPosition); -// } -// //NLMEMORY::CheckHeap (true); -//*/ } -// else // load old item format -// { -// //NLMEMORY::CheckHeap (true); -// -// float dummy_f; -// uint16 dummy_uint16; -// uint32 dummy_uint32; -// bool dummy_bool; -// -// //NLMEMORY::CheckHeap (true); -// -// // load item infos -// f.serial( _SheetId ); -//// f.serial( Owner ); -// f.serial( owner ); -//// if( Owner != CEntityId::Unknown ) -// if( owner != CEntityId::Unknown ) -// { -//// f.serial(Loc.Slot); -// f.serial(slot); -// } -// else -// { -//// f.serial( Loc.Pos.X ); -//// f.serial( Loc.Pos.Y ); -//// f.serial( Loc.Pos.Z ); -// f.serial(coord); -// f.serial(coord); -// f.serial(coord); -// } -// -// //NLMEMORY::CheckHeap (true); -// -// if( characterSerialVersion >= 8 ) -// { -// f.serial( dummy_f ); -// f.serial( dummy_f ); -// f.serial( dummy_f ); -// } -// -// //NLMEMORY::CheckHeap (true); -// -// f.serial( dummy_uint16 ); //uint16 -// _Recommended = dummy_uint16; -// -// f.serial( _HP ); //uint32 -// -// if( characterSerialVersion < 7 ) -// { -// f.serial( dummy_uint16 ); -// } -// else if( characterSerialVersion == 7 ) -// { -// f.serial( dummy_f ); -// } -// -// //NLMEMORY::CheckHeap (true); -// -// if( characterSerialVersion < 8 ) -// { -// f.serial( dummy_f ); -// } -// f.serial( dummy_f ); -// -// //NLMEMORY::CheckHeap (true); -// -// f.serial( dummy_uint16 ); -// f.serial( dummy_uint16 ); -// -// //NLMEMORY::CheckHeap (true); -// -// if( characterSerialVersion < 8 ) -// { -// f.serial( dummy_f ); -// } -// f.serial( dummy_uint16 ); -// -// f.serial( dummy_uint32 ); -// f.serial( dummy_uint16 ); -// f.serial( dummy_uint32 ); -// f.serial( dummy_uint16 ); -// f.serial( dummy_uint16 ); -// f.serial( dummy_bool ); -// -// //NLMEMORY::CheckHeap (true); -// -// vector< SProtection > dummy_protection; -// f.serialCont(dummy_protection); -// -// //NLMEMORY::CheckHeap (true); -// -// f.serial( timeOnGround ); -// f.serial( slotCount ); -// uint8 col; -// f.serial( col ); -// if( _CraftParameters ) -// _CraftParameters->Color = col; -// -// f.serial( carrionSheetId ); -// -// f.serial( _Destroyable ); -// -// f.serial( _CreatorId ); -// -// // load children count -// uint32 childrenCount = 0; -// f.serial( childrenCount ); -// -// // load non null children count -// uint32 nonNullChildrenCount = 0; -// f.serial( nonNullChildrenCount ); -// -// //NLMEMORY::CheckHeap (true); -// -// bool isStack = false; -// if ( _SheetId == CSheetId("stack.sitem") ) -// { -//// // stack do not have NULL items -// isStack = true; -// if ( nonNullChildrenCount != childrenCount ) -// { -//// nlwarning("char %s a stack contains NULL items! children: '%d' non null children: '%d'",Idc.toString().c_str(),childrenCount,nonNullChildrenCount); -// nlwarning(" A stack contains NULL items! children: '%d' non null children: '%d'", -// childrenCount, -// nonNullChildrenCount); -// } -// } -// else -// { -// nlassertex(childrenCount == 0, ("Can't read old inventory item as item, must be read as inventory")); -//// _Children.resize( childrenCount, NULL ); -// } -// -// //NLMEMORY::CheckHeap (true); -// -// uint32 i; -// for( i = 0; i < nonNullChildrenCount; ++i ) -// { -// // load child index -// uint32 index; -// f.serial( index ); -//// -//// //NLMEMORY::CheckHeap (true); -//// -// // load child -// CGameItemPtr item; -//// -//// //NLMEMORY::CheckHeap (true); -//// -// item.newItem(); -//// -//// //NLMEMORY::CheckHeap (true); -//// -//// CEntityId id( RYZOMID::object, GameItemManager.getFreeItemIndice() ); -//// -//// item->_Id = id; -//// -//// //NLMEMORY::CheckHeap (true); -// if( item!=NULL ) -// { -// //NLMEMORY::CheckHeap (true); -//// item->load(f, Idc, characterSerialVersion); -// item->legacyLoad(f, characterSerialVersion, ownerPtr); -//// //NLMEMORY::CheckHeap (true); -// } -// else -// { -//// nlwarning("char %s Can't allocate child item %d",Idc.toString().c_str(),i); -// nlwarning(" Can't allocate child item %d", i); -// return; -// } -//// -//// //NLMEMORY::CheckHeap (true); -//// -// if (i==0) -// { -// // copy first item into current item -// copyItem(item); -// } -// -// item.deleteItem(); -//// // add child in children -//// if (isStack) -//// _Children.push_back(item); -//// else -//// _Children[index] = item; -//// -//// //NLMEMORY::CheckHeap (true); -//// -//// // set the parent -//// (*item)->setParent( this ); -//// -//// //NLMEMORY::CheckHeap (true); -//// -//// // add item in manager -//// GameItemManager.insertItem( item ); -//// -//// if (getSheetId() == CSheetId("stack.sitem") && characterSerialVersion>=43 ) -//// { -//// for (uint32 j=1;jgetCopy(); -//// if ( copy != NULL ) -//// _Children.push_back( copy ); -//// } -//// break; -//// } -//// -//// -//// //NLMEMORY::CheckHeap (true); -// } -// -// if (nonNullChildrenCount == 0) -// nonNullChildrenCount = 1; // ANTI-BUG: repair empty stacks... is it a good solution? -// -// setStackSize(nonNullChildrenCount); -// -// // the client position has been added with Character version 4, for older item, just init it wiht -1 -// // we do this to keep compatibility with previous character backup version -// if (characterSerialVersion >= 4) -// f.serial(_ClientInventoryPosition); -// else -// _ClientInventoryPosition = -1; -// -// //NLMEMORY::CheckHeap (true); -// -// // serialize raw material used for craft item -// if( characterSerialVersion >= 10 ) -// { -//// f.serialCont( _RmUsedForCraft ); -// std::vector RmUsedCraft; -// f.serialCont( RmUsedCraft ); -// -//// if ( f.isReading() && _RmUsedForCraft.size() >= 20 ) -//// _RmUsedForCraft.clear(); -// } -// //NLMEMORY::CheckHeap (true); -// } -//// } -//// catch(const Exception &e) -//// { -//// nlwarning(" %s",e.what()); -//// } -// -// // init form -// _Form = CSheets::getForm( _SheetId ); -// -// // patch tool HP for old saves -// if ( characterSerialVersion < 68 && _Form) -// { -// if ( _Form->Family == ITEMFAMILY::CRAFTING_TOOL || _Form->Family == ITEMFAMILY::HARVEST_TOOL ) -// _HP = maxDurability(); -// } -// -// -// // memory optimization for non craftable items -// if (_Form != NULL) -// { -// switch(_Form->Family) -// { -// //craftable families, do nothing -// case ITEMFAMILY::ARMOR: -// case ITEMFAMILY::MELEE_WEAPON: -// case ITEMFAMILY::RANGE_WEAPON: -// case ITEMFAMILY::AMMO: -// case ITEMFAMILY::SHIELD: -// case ITEMFAMILY::JEWELRY: -// case ITEMFAMILY::CRAFTING_TOOL: -// case ITEMFAMILY::HARVEST_TOOL: -// break; -// // non craftable-> release craft parameters structure -// default: -// if (_CraftParameters != NULL) -// { -// delete _CraftParameters; -// _CraftParameters = NULL; -// } -// } -// } -// -// // compute item worn state -// computeItemWornState(); -// -// // adapt the old slotimage method to new ref method and auto equip item if needed -// if ( f.isReading() && slotImage != 0xFFFF && ownerPtr != NULL) -// { -// INVENTORIES::TInventory refInventoryId; -// if ( slotImage < 2 ) -// { -// refInventoryId = INVENTORIES::handling; -// _RefInventorySlot = slotImage; -// nlinfo("Convert item %s, had slot image %u, is now in HAND, slot %u", _SheetId.toString().c_str(),slotImage,_RefInventorySlot); -// } -// else -// { -// refInventoryId = INVENTORIES::equipment; -// _RefInventorySlot = slotImage - 2; -// nlinfo("Convert item %s, had slot image %u, is now in EQUIPMENT, slot %u", _SheetId.toString().c_str(),slotImage,_RefInventorySlot); -// } -// -// const uint32 slot = _RefInventorySlot; -// _RefInventorySlot = CInventoryBase::INVALID_INVENTORY_SLOT; -// const CInventoryPtr inv = ownerPtr->getInventory(refInventoryId); -// if (inv) -// { -// CGameItemPtr itemPtr(this); -// inv->insertItem(itemPtr, slot); -// } -// else -// _RefInventorySlot = CInventoryBase::INVALID_INVENTORY_SLOT; -// -// //ownerPtr->equipCharacter(refInventoryId, slot, getInventorySlot()); -// } -// else -// _RefInventorySlot = CInventoryBase::INVALID_INVENTORY_SLOT; -// -//// if ( _IsOnTheGround ) -//// nlwarning(" loading an object on the ground should never happen sheet: %s, id: %s ",_SheetId.toString().c_str(), _ItemId.toString().c_str() ); -// -// //NLMEMORY::CheckHeap (true); -//} // load // - //----------------------------------------------- // dumpGameItemStats : diff --git a/ryzom/server/src/entities_game_service/game_item_manager/game_item.h b/ryzom/server/src/entities_game_service/game_item_manager/game_item.h index ad4736c0e..b63af9a70 100644 --- a/ryzom/server/src/entities_game_service/game_item_manager/game_item.h +++ b/ryzom/server/src/entities_game_service/game_item_manager/game_item.h @@ -256,16 +256,12 @@ private: void keepTheThreeBestResistance( const CCraftParameters& p ); }; - - //------------------------------------------------------------------------ // advance declaration of classes with circular references class CGameItem; +class CGameItemEntry; //class CGameItemManager; - - - /** * CGameItemVector * @@ -278,7 +274,7 @@ class CGameItemVector { public: uint32 size() const; - CGameItem& operator[](uint32 idx); + CGameItemEntry& operator[](uint32 idx); void extend(); uint32 getUniqueIndex(const CGameItem& item); virtual ~CGameItemVector(); @@ -289,45 +285,9 @@ private: CGameItemVector(); private: - std::vector< CGameItem* > _Data; -}; - - -#ifdef GAME_PTR_DEBUG -class CGameItemPtrArray -{ -public: - CGameItemPtrArray() - { - } + std::vector m_Data; - CGameItemPtrArray(const CGameItemPtrArray&) - { - // do nothing - } - - CGameItemPtrArray &operator=(const CGameItemPtrArray &) - { - // do nothing - } - -#ifdef NL_CPP14 - CGameItemPtrArray(CGameItemPtrArray &&) - { - // do nothing - } - - CGameItemPtrArray &operator=(CGameItemPtrArray &&) noexcept - { - // do nothing - } -#endif - -protected: - /// keep pointers pointing this item - std::vector _Ptrs; }; -#endif /** * CGameItem @@ -336,17 +296,18 @@ protected: * \author Nevrax France * \date 2002 */ -class CGameItem -#ifdef GAME_PTR_DEBUG - : public CGameItemPtrArray -#endif +class CGameItem { +#if 0 NLMISC_COMMAND_FRIEND(testParanoidItemSystem); +#endif friend class CInventoryBase; friend class CRefInventory; +#if 0 NL_INSTANCE_COUNTER_DECL(CGameItem); +#endif public: /// returns true if the two param items are stackable @@ -752,10 +713,10 @@ protected: /// The inventory that contains this item (NULL if none) CInventoryPtr _Inventory; - /// The slot inside the inventory - uint32 _InventorySlot; /// The inventory that reference this item (NULL if none) CInventoryPtr _RefInventory; + /// The slot inside the inventory + uint32 _InventorySlot; /// The slot inside the reference inventory uint32 _RefInventorySlot; @@ -773,20 +734,12 @@ private: static CGameItemVector _Items; static uint32 _FirstFreeItem; - #ifdef ITEM_DEBUG - static sint32 _NextAllocatorDataValue; - #endif - - //-------------------------------------------------------------------- - // instance data for singleton's allocator algorithms - - sint32 _AllocatorData; - private: //-------------------------------------------------------------------- // singleton interface used by the CGameItemPtr class // make CGameItemPtr a friend to give it decent access + friend class CGameItemEntry; friend class CGameItemPtr; friend class CInventoryProxy; friend class COldGuildInventoryLoader; @@ -807,32 +760,10 @@ private: // return the CWeaponCraftParameters variable corresponding to protection type float getMagicProtectionCraftParateters( PROTECTION_TYPE::TProtectionType protection ) const; -private: -#if 0 - // singleton counter - static uint32 _BugTestCounter; - - // instance debug data - uint32 _BugTestChecksum; - uint32 _BugTestUpdate; -#endif - public: -#if 0 - // run through the items looking for bugs - static void testItemsForBugs(); -// static void testPlayerInventoryForBugs(const std::vector& inventory); -#endif - static std::string showItemsStats(); -#if 0 - // check a single item for bugs... - void checkItemForBugs(); -#endif - -public: // I've had to make these public for now 'cos I can't work out how to make the vector class a friend :o( -//private : +private : //-------------------------------------------------------------------- // ctors and dtors are now private for better control over allocation etc @@ -877,7 +808,7 @@ private: /** * pseudo Destructor */ - void dtor(); + //void dtor(); /// Copy all the item info and parameters from model into this // void copyItem(const CGameItemPtr &model); @@ -921,22 +852,16 @@ public: private: /// Item unique id INVENTORIES::TItemId _ItemId; - /// Item stack size - uint32 _StackSize; - // true if the item is on the ground -// bool _IsOnTheGround; /// item id // NLMISC::CEntityId _ItemId; /// looter id of the character currently looting this item (for items on the ground only) NLMISC::CEntityId _Looter; /// sheet ref NLMISC::CSheetId _SheetId; + /// Item stack size + uint32 _StackSize; /// carrion sheet ref // uint32 _CarrionSheetId; - /// true if the object is destroyable - bool _Destroyable; - /// true if the object is dropable - bool _Dropable; /// children // std::vector _Children; /// pointer on the parent item (NULL if no parent) @@ -954,52 +879,64 @@ private: /// current sap load uint32 _SapLoad; + /// all craft parameters NLMISC::CDeepPtr _CraftParameters; /// entityId of the character who has created the Item via faber (if applicable, for item not created by playres, Creator = CEntityId::Unknown) NLMISC::CEntityId _CreatorId; - /// number of item locked - uint32 _LockCount; /// Position in the client inventory interface if item is owned by a player (sint16 juste because we need an "invalid" position (-1) for version compatibility) - // TODO : a virer - sint16 _ClientInventoryPosition; /// Vector of CSheetId used for craft this item // std::vector< NLMISC::CSheetId > _RmUsedForCraft; /// vector of sheetId of CStaticBrick define spell of enchanted item std::vector< NLMISC::CSheetId > _Enchantment; + /// pointer on the associated static form const CStaticItem* _Form; /// string associated with this item NLMISC::CDeepPtr _PhraseId; + + /// skill modifiers against given ennemy types + std::vector _TypeSkillMods; + + NLMISC::CDeepPtr _CustomText; +#ifdef RYZOM_FORGE_PET_NAME + // FIXME: Reuse _PhraseId string and add a m_Literal flag + ucstring _CustomName; +#endif + /// tick when the proc will be available again NLMISC::TGameCycle _LatencyEndDate; /// image of the item in bag / equipment // uint16 _SlotImage; NLMISC::TGameCycle _TotalSaleCycle; + /// number of item locked + uint32 _LockCount; // required skill - bool _UseNewSystemRequirement; SKILLS::ESkills _RequiredSkill; - uint16 _RequiredSkillLevel; SKILLS::ESkills _RequiredSkill2; + CHARACTERISTICS::TCharacteristics _RequiredCharac; + uint16 _RequiredSkillLevel; uint16 _RequiredSkillLevel2; /// min required stat level and required stat - CHARACTERISTICS::TCharacteristics _RequiredCharac; uint16 _RequiredCharacLevel; /// whether the item has any skill requirements bool _HasPrerequisit; - /// skill modifiers against given ennemy types - std::vector _TypeSkillMods; + bool _UseNewSystemRequirement; - NLMISC::CDeepPtr _CustomText; bool _LockedByOwner; bool _UnMovable; bool _Movable; uint8 _PetIndex; -#ifdef RYZOM_FORGE_PET_NAME - ucstring _CustomName; -#endif + + /// true if the object is destroyable + bool _Destroyable; + /// true if the object is dropable + bool _Dropable; + // true if the item is on the ground + // bool _IsOnTheGround; + }; /** @@ -1029,110 +966,128 @@ private: #define QUANTUM (1<>LOG_QUANTUM][idx&QUANTUM_MASK]; + return m_Data[idx >> LOG_QUANTUM][idx & QUANTUM_MASK]; } inline void CGameItemVector::extend() { - _Data.push_back(new CGameItem[QUANTUM]); - nlassert(_Data.back()!=NULL); - for (uint32 i=0;i(item).VectorIdx; } #undef LOG_QUANTUM #undef QUANTUM #undef QUANTUM_MASK - //------------------------------------------------------------------------ // ptr class added by sadge // inline implementations -// ctor - default -inline CGameItemPtr::CGameItemPtr() +// link ptr to game item +inline void CGameItemPtr::incRef() { - reset(); + if (!m_Idx) + return; + + ++CGameItem::_Items[m_Idx].PtrRefCount; } -inline void CGameItemPtr::reset() +// unlink ptr from item +inline void CGameItemPtr::decRef() { - _idx = ~0u; + // cannot unlink a pointer pointing on nothing + if (!m_Idx) + return; - #ifdef ITEM_DEBUG - _debugPtr= NULL; - _debug=0; - #endif + CGameItemEntry *entry = &CGameItem::_Items[m_Idx]; + sint count = --CGameItem::_Items[m_Idx].PtrRefCount; + if (!count) + { + CGameItem::deleteItem(static_cast(entry)); + } + nlassert(count >= 0); +} + +// ctor - default +inline CGameItemPtr::CGameItemPtr() : m_Idx(0) +{ + } // ctor - copy -inline CGameItemPtr::CGameItemPtr(const CGameItemPtr &other) +inline CGameItemPtr::CGameItemPtr(const CGameItemPtr &other) : m_Idx(other.m_Idx) { - reset(); - *this=other; + incRef(); } // ctor - initialise from a CGameItem* -inline CGameItemPtr::CGameItemPtr(const CGameItem *item) +inline CGameItemPtr::CGameItemPtr(const CGameItem *item) : m_Idx(static_cast(item)->VectorIdx) { - reset(); - *this=item; + incRef(); } // dtor inline CGameItemPtr::~CGameItemPtr() { - unlinkFromItem(); + decRef(); } // equivalent to: new CGameItem inline CGameItem *CGameItemPtr::newItem(bool destroyable,bool dropable) { - CGameItem *item=CGameItem::newItem(); + CGameItem *item = CGameItem::newItem(); item->ctor(); item->_Destroyable=destroyable; item->_Dropable = dropable; *this=item; -#if 0 - item->_BugTestUpdate=CGameItem::_BugTestCounter; -#endif return item; } @@ -1153,93 +1108,17 @@ inline CGameItem *CGameItemPtr::newItem( const NLMISC::CSheetId& sheetId, uint32 // item->ctor(id,sheetId,recommended,slotCount,destroyable,dropable); item->ctor(sheetId, recommended, destroyable, dropable); *this=item; -#if 0 - item->_BugTestUpdate = CGameItem::_BugTestCounter; -#endif return item; } - -// equivalent to: delete (for a CGameItem*) -//inline void CGameItemPtr::deleteItem() -//{ -// CGameItem *item=**this; -// -// BOMB_IF( item == NULL, "Attempt to delete an item that is not allocated or has been freed", return ); -// -// // only unlink if the pointer 'this' is not the same as the inventory ptr for the item -// // after the unlink this == NULL -// if (! ( item->_Parent!=NULL && -// item->Loc.Slot_Parent->getChildren().size() && -// &(item->_Parent->getChildren()[item->Loc.Slot])==this ) ) -// unlinkFromItem(); -// -// // call dtor now to unlink all children -// item->dtor(); -// // check no one else is referencing us -// nlassert(item->_Ptrs.empty()); -// -// CGameItem::deleteItem(item); -// item->_BugTestUpdate=CGameItem::_BugTestCounter; -//} - -// link ptr to game item -inline void CGameItemPtr::linkToItem() -{ -#ifdef GAME_PTR_DEBUG - if (_idx == ~0u) - return; - - CGameItem *item=**this; - - for (uint i = 0 ; i < item->_Ptrs.size() ; ++i) - { - nlassert(item->_Ptrs[i] != this); - } - - item->_Ptrs.push_back(this); -#endif -} - -// unlink ptr from item -inline void CGameItemPtr::unlinkFromItem() -{ - // cannot unlink a pointer pointing on nothing - if (_idx == ~0u) - return; - -#ifdef GAME_PTR_DEBUG - CGameItem *item=**this; - - uint j=~0u; - for (uint i = 0 ; i < item->_Ptrs.size() ; ++i) - { - if (item->_Ptrs[i] == this) - { - nlassert(j==~0u); - j=i; - } - } - nlassert(j!=~0u); - item->_Ptrs.erase(item->_Ptrs.begin()+j); -#endif - - // set the GameItemPtr to NULL - reset(); -} - // = operator - for copying another CGameItemPtr inline const CGameItemPtr &CGameItemPtr::operator=(const CGameItemPtr &other) { - unlinkFromItem(); + decRef(); - _idx=other._idx; - #ifdef ITEM_DEBUG - _debug=other._debug; - _debugPtr=other._debugPtr; - #endif + m_Idx = other.m_Idx; - linkToItem(); + incRef(); return *this; } @@ -1247,135 +1126,76 @@ inline const CGameItemPtr &CGameItemPtr::operator=(const CGameItemPtr &other) // = operator - for assignment of CGameItemPtr directly to a CGameItem inline const CGameItemPtr &CGameItemPtr::operator=(const CGameItem *item) { - unlinkFromItem(); + decRef(); - if (item==NULL) - _idx=~0u; - else + if (!item) { - _idx=CGameItem::_Items.getUniqueIndex(*item); - - // this test would only have value if the implementation of std::vector<> doesn't guarantee a - // continuous memory address space for the vector's data - // It's not in the #IFDEF DEBUG because it may only be triggered in very obscure conditions - if (CGameItem::getItem(_idx)!=item) - { - nlwarning("**** BIG BAD NASTY BUG - BEGINS ****"); - nlwarning("item: %p",item); - nlwarning("_idx: %i",_idx); - nlwarning("**** BIG BAD NASTY BUG - ENDS ****"); - } - // nlassert(&CGameItem::getItem(_idx)==item); + m_Idx = 0; } + else + { + m_Idx = static_cast(item)->VectorIdx; + nlassert(CGameItem::getItem(m_Idx) == item); - #ifdef ITEM_DEBUG - _debugPtr= (CGameItem *)item; - if (item==NULL) - _debug=0; - else - { - CGameItem * item = CGameItem::getItem(_idx); - if( item ) - _debug=item->_AllocatorData; - } - #endif - - linkToItem(); + incRef(); + } return *this; } // * operator - returning the item referenced by this pointer -inline CGameItem * CGameItemPtr::operator*() const +inline CGameItem *CGameItemPtr::operator*() const { - if (_idx == ~0u) - return NULL; - - CGameItem* item= CGameItem::getItem(_idx); - - #ifdef ITEM_DEBUG - BOMB_IF( CGameItem::getItem(_idx) !=_debugPtr, "CGameItemPtr do not reference the good item", return 0 ); - BOMB_IF( _idx == ~0u, "Attempting to derefence a NULL pointer", return 0 ); - if( item ) - BOMB_IF( _debug!=CGameItem::getItem(_idx)->_AllocatorData, "Attempting to access an item that has been re-allocated", return 0 ); - #endif - - BOMB_IF(item==0, "Attempting to access an item an item that is not allocated or has been freed", return 0); - -#if 0 - item->_BugTestUpdate=CGameItem::_BugTestCounter; -#endif - return item; + CGameItemEntry *entry = static_cast(CGameItem::getItem(m_Idx)); + BOMB_IF(!entry->VectorIdx, "Attempting to access an item an item that is not allocated or has been freed", return 0); + return static_cast(entry); } // -> operator - returning the item referenced by this pointer inline CGameItem *CGameItemPtr::operator->() const { - if (_idx == ~0u) - return NULL; - - CGameItem* item= CGameItem::getItem(_idx); - - #ifdef ITEM_DEBUG - BOMB_IF( CGameItem::getItem(_idx) !=_debugPtr, "CGameItemPtr do not reference the good item", return 0 ); - BOMB_IF( _idx == ~0u, "Attempting to derefence a NULL pointer", return 0 ); - if( item ) - BOMB_IF( _debug!=CGameItem::getItem(_idx)->_AllocatorData, "Attempting to access an item that has been re-allocated", return 0 ); - #endif - - BOMB_IF(item==0, "Attempting to access an item an item that is not allocated or has been freed", return 0); - -#if 0 - item->_BugTestUpdate=CGameItem::_BugTestCounter; -#endif - return item; + // this is crash-safe even when m_Idx is wrong, it'll return item 0 + return CGameItem::getItem(m_Idx); } // () operator - returning the item referenced by this pointer inline CGameItem *CGameItemPtr::operator()() const { - return operator->(); + CGameItemEntry *entry = static_cast(CGameItem::getItem(m_Idx)); + BOMB_IF(!entry->VectorIdx, "Attempting to access an item an item that is not allocated or has been freed", return 0); + return static_cast(entry); } // == operator - compare 2 CGameItemPtrs inline bool CGameItemPtr::operator==(const CGameItemPtr &other) const { - #ifdef ITEM_DEBUG - //nlassert(CGameItem::getItem(_idx)==_debugPtr); - if(_idx==other._idx) - nlassert(_debug==other._debug); - #endif - - return (_idx==other._idx); + return (m_Idx == other.m_Idx); } // == operator - compare CGameItemPtrs to CGameItem* inline bool CGameItemPtr::operator==(const CGameItem *item) const { - if (item==NULL) - return operator*()==NULL; + if (!item) + return m_Idx == 0; - return *this==CGameItemPtr(item); + return CGameItem::getItem(m_Idx) == item; } // != operator - compare 2 CGameItemPtrs inline bool CGameItemPtr::operator!=(const CGameItemPtr &other) const { - return !(*this==other); + return !(*this == other); } // != operator - compare CGameItemPtrs to CGameItem* inline bool CGameItemPtr::operator!=(const CGameItem *item) const { - if (item==NULL) - return operator*()!=NULL; - - return !(*this==item); + return !(*this == item); } inline bool CGameItemPtr::operator < (const CGameItemPtr &other) const { - return _idx < other._idx; + return m_Idx < other.m_Idx; } #endif // GAME_ITEM_H diff --git a/ryzom/server/src/entities_game_service/game_item_manager/game_item_ptr.h b/ryzom/server/src/entities_game_service/game_item_manager/game_item_ptr.h index fd8f5b7e2..94d599fb6 100644 --- a/ryzom/server/src/entities_game_service/game_item_manager/game_item_ptr.h +++ b/ryzom/server/src/entities_game_service/game_item_manager/game_item_ptr.h @@ -54,7 +54,7 @@ public: void deleteItem(); // * operator - returning the item referenced by this pointer - CGameItem * operator*() const; + CGameItem *operator*() const; // -> operator - returning the item referenced by this pointer CGameItem *operator->() const; @@ -74,27 +74,23 @@ public: bool operator==(const CGameItem *item) const; bool operator!=(const CGameItem *item) const; - uint32 getUniqueIndex() { return _idx; } + uint32 getUniqueIndex() { return m_Idx; } // For set and map bool operator < (const CGameItemPtr &other) const; + + // operator bool() { return m_Idx; } + // bool operator!() { return !m_Idx; } + private: // link to item - void linkToItem(); + void incRef(); // unlink from item - void unlinkFromItem(); - // init - void reset(); + void decRef(); // index into the CGameItem singleton's _Items vector - uint32 _idx; - - #ifdef ITEM_DEBUG - // used for making sure that referenced items haven't been freed or reallocated - // contains a copy of a CGameItem's allocation index (which changes at every alloaction and free) - sint32 _debug; - CGameItem* _debugPtr; - #endif + uint32 m_Idx; + };