@@ -281,21 +281,34 @@ static class CRD_Inventory_Manager final : public CAutoGameSystem, public CGameE
281281
282282 m_HighOwnedInventoryDefIDs.Purge ();
283283
284+ CUtlMap<SteamItemDef_t, CCopyableUtlVector<SteamItemInstanceID_t>> autoStackDefs ( DefLessFunc ( SteamItemDef_t ) );
284285 for ( uint32 i = 0 ; i < nItems; i++ )
285286 {
286287 ReactiveDropInventory::ItemInstance_t instance{ hResult, i };
287288 m_LocalInventoryCache.AddToTail ( instance );
288289
289- // precache item def + icon
290- ( void )ReactiveDropInventory::GetItemDef ( instance.ItemDefID );
290+ // precache item def + icon and check for auto-stack flag
291+ const ReactiveDropInventory::ItemDef_t *pDef = ReactiveDropInventory::GetItemDef ( instance.ItemDefID );
292+ if ( pDef && pDef->AutoStack )
293+ {
294+ unsigned short index = autoStackDefs.Find ( instance.ItemDefID );
295+ if ( !autoStackDefs.IsValidIndex ( index ) )
296+ {
297+ index = autoStackDefs.Insert ( instance.ItemDefID );
298+ }
299+
300+ autoStackDefs[index].AddToTail ( instance.ItemID );
301+ }
291302
292303 // The Steam inventory API doesn't list item def IDs that are between 1 million and 1 billion unless we ask about them specifically.
293304 // If we own any items with def IDs in this range, remember that and re-write the schema cache to include them.
294305 // These IDs are used for donation receipt medals as well as unique medals.
295306 if ( instance.ItemDefID >= 1000000 )
296307 {
297308 if ( !m_HighOwnedInventoryDefIDs.IsValidIndex ( m_HighOwnedInventoryDefIDs.Find ( instance.ItemDefID ) ) )
309+ {
298310 m_HighOwnedInventoryDefIDs.AddToTail ( instance.ItemDefID );
311+ }
299312 }
300313 }
301314
@@ -320,6 +333,33 @@ static class CRD_Inventory_Manager final : public CAutoGameSystem, public CGameE
320333 }
321334 }
322335
336+ if ( rd_debug_inventory.GetBool () )
337+ {
338+ DevMsg ( 3 , " Verifying %d auto-stack defs...\n " , autoStackDefs.Count () );
339+ }
340+ FOR_EACH_MAP_FAST ( autoStackDefs, i )
341+ {
342+ if ( autoStackDefs[i].Count () == 1 )
343+ {
344+ continue ;
345+ }
346+
347+ Assert ( autoStackDefs[i].Count () != 0 );
348+
349+ if ( rd_debug_inventory.GetBool () )
350+ {
351+ Msg ( " Have %d stacks of auto-stack item %d; merging\n " , autoStackDefs[i].Count (), autoStackDefs.Key ( i ) );
352+ }
353+
354+ pInventory->TransferItemQuantity ( AddCraftItemTask ( CRAFT_AUTO_STACK, autoStackDefs.Key ( i ) ), autoStackDefs[i][1 ], GetLocalItemCache ( autoStackDefs[i][1 ] )->Quantity , autoStackDefs[i][0 ] );
355+ if ( autoStackDefs[i].Count () > 2 )
356+ {
357+ m_CraftingQueue.Tail ()->m_RetryItemList .AddVectorToTail ( autoStackDefs[i] );
358+ m_CraftingQueue.Tail ()->m_RetryItemList .FastRemove ( 1 );
359+ m_CraftingQueue.Tail ()->m_RetryItemList .FastRemove ( 0 );
360+ }
361+ }
362+
323363 ThreadExecute ( WriteInventoryCacheHelper );
324364 }
325365
@@ -1277,6 +1317,7 @@ static class CRD_Inventory_Manager final : public CAutoGameSystem, public CGameE
12771317 case CRAFT_DELETE_SILENT:
12781318 case CRAFT_NOTIFICATION_DYNAMIC_PROPERTY_UPDATE:
12791319 case CRAFT_AUTO_BACKGROUND:
1320+ case CRAFT_AUTO_STACK:
12801321 break ;
12811322 default :
12821323 Assert ( !" unhandled crafting task type" );
@@ -1313,6 +1354,7 @@ static class CRD_Inventory_Manager final : public CAutoGameSystem, public CGameE
13131354 case CRAFT_DELETE_SILENT:
13141355 case CRAFT_NOTIFICATION_DYNAMIC_PROPERTY_UPDATE:
13151356 case CRAFT_AUTO_BACKGROUND:
1357+ case CRAFT_AUTO_STACK:
13161358 break ;
13171359 default :
13181360 Assert ( !" unhandled crafting task type" );
@@ -1457,14 +1499,22 @@ static class CRD_Inventory_Manager final : public CAutoGameSystem, public CGameE
14571499 continue ;
14581500 }
14591501
1502+ char buf[12 ]{};
1503+ uint32 len = sizeof ( buf );
1504+ int32 quantity = 0 ;
1505+ if ( pInventory->GetResultItemProperty ( pTask->m_hResult , i, " quantity" , buf, &len ) )
1506+ {
1507+ quantity = strtol ( buf, NULL , 10 );
1508+ }
1509+
14601510 if ( const ItemInstance_t *pCached = GetLocalItemCache ( diff[i].m_itemId ) )
14611511 {
1462- diff[i]. m_unQuantity = MAX ( 0 , int ( diff[i]. m_unQuantity ) - pCached->Quantity );
1512+ quantity = MAX ( 0 , quantity - pCached->Quantity );
14631513 }
14641514
14651515 if ( diff[i].m_iDefinition == g_RD_Crafting_Material_Info[eMaterialType].m_iItemDef )
14661516 {
1467- added = diff[i]. m_unQuantity ;
1517+ added += quantity ;
14681518 }
14691519 }
14701520
@@ -1527,6 +1577,53 @@ static class CRD_Inventory_Manager final : public CAutoGameSystem, public CGameE
15271577 break ;
15281578 case CRAFT_AUTO_BACKGROUND:
15291579 break ;
1580+ case CRAFT_AUTO_STACK:
1581+ if ( pTask->m_RetryItemList .Count () != 0 )
1582+ {
1583+ uint32 nCount{};
1584+ pInventory->GetResultItems ( pTask->m_hResult , NULL , &nCount );
1585+ CUtlVector<SteamItemDetails_t> items;
1586+ items.AddMultipleToTail ( nCount );
1587+ pInventory->GetResultItems ( pTask->m_hResult , items.Base (), &nCount );
1588+
1589+ SteamItemInstanceID_t iStacked = k_SteamItemInstanceIDInvalid;
1590+ FOR_EACH_VEC ( items, i )
1591+ {
1592+ if ( items[i].m_unFlags & ( k_ESteamItemConsumed | k_ESteamItemRemoved ) )
1593+ {
1594+ continue ;
1595+ }
1596+
1597+ char buf[12 ]{};
1598+ uint32 len = sizeof ( buf );
1599+ int32 quantity = 0 ;
1600+ if ( pInventory->GetResultItemProperty ( pTask->m_hResult , i, " quantity" , buf, &len ) )
1601+ {
1602+ quantity = strtol ( buf, NULL , 10 );
1603+ }
1604+
1605+ if ( quantity > 0 )
1606+ {
1607+ Assert ( items[i].m_iDefinition == pTask->m_iAccessoryDef );
1608+ Assert ( iStacked == k_SteamItemInstanceIDInvalid );
1609+ iStacked = items[i].m_itemId ;
1610+ }
1611+ }
1612+
1613+ Assert ( iStacked != k_SteamItemInstanceIDInvalid );
1614+ if ( iStacked != k_SteamItemInstanceIDInvalid )
1615+ {
1616+ if ( rd_debug_inventory.GetBool () )
1617+ {
1618+ Msg ( " Have %d remaining stacks of auto-stack item %d; merging\n " , pTask->m_RetryItemList .Count () + 1 , pTask->m_iAccessoryDef );
1619+ }
1620+
1621+ pInventory->TransferItemQuantity ( AddCraftItemTask ( CRAFT_AUTO_STACK, pTask->m_iAccessoryDef ), pTask->m_RetryItemList [0 ], GetLocalItemCache ( pTask->m_RetryItemList [0 ] )->Quantity , iStacked );
1622+ m_CraftingQueue.Tail ()->m_RetryItemList .AddVectorToTail ( pTask->m_RetryItemList );
1623+ m_CraftingQueue.Tail ()->m_RetryItemList .FastRemove ( 0 );
1624+ }
1625+ }
1626+ break ;
15301627 default :
15311628 Assert ( !" unhandled crafting task type" );
15321629 break ;
0 commit comments