From a43c20248224074d6f5b08267c5e515c673cfdb3 Mon Sep 17 00:00:00 2001 From: GT610 Date: Thu, 16 Jul 2026 16:48:42 +0800 Subject: [PATCH 1/2] Fix storage unit naming Handle the client's zero-id built-in casket naming path, initialize storage metadata, and avoid sending empty tool removal messages. --- csgo_gc/gc_client.cpp | 5 ++- csgo_gc/inventory.cpp | 89 +++++++++++++++++++++++++++++++++---------- 2 files changed, 72 insertions(+), 22 deletions(-) diff --git a/csgo_gc/gc_client.cpp b/csgo_gc/gc_client.cpp index ad80733..182515b 100644 --- a/csgo_gc/gc_client.cpp +++ b/csgo_gc/gc_client.cpp @@ -1694,7 +1694,10 @@ void ClientGC::NameItem(GCMessageRead &messageRead) if (m_inventory.NameItem(nameTagId, itemId, name, update, destroy, notification)) { SendMessageToGame(true, k_ESOMsg_Update, update); - SendMessageToGame(true, k_ESOMsg_Destroy, destroy); + if (destroy.has_type_id()) + { + SendMessageToGame(true, k_ESOMsg_Destroy, destroy); + } SendMessageToGame(false, k_EMsgGCItemCustomizationNotification, notification); } diff --git a/csgo_gc/inventory.cpp b/csgo_gc/inventory.cpp index d05a64a..3cb9ca0 100644 --- a/csgo_gc/inventory.cpp +++ b/csgo_gc/inventory.cpp @@ -39,7 +39,7 @@ inline bool IsDefaultItemId(uint64_t itemId, uint32_t &defIndex, uint32_t &paint return false; } -CSOEconItemAttribute *FindOrAddAttribute(CSOEconItem &item, uint32_t defIndex) +static CSOEconItemAttribute *FindAttribute(CSOEconItem &item, uint32_t defIndex) { for (int i = 0; i < item.attribute_size(); i++) { @@ -50,6 +50,16 @@ CSOEconItemAttribute *FindOrAddAttribute(CSOEconItem &item, uint32_t defIndex) } } + return nullptr; +} + +static CSOEconItemAttribute *FindOrAddAttribute(CSOEconItem &item, uint32_t defIndex) +{ + if (CSOEconItemAttribute *attribute = FindAttribute(item, defIndex)) + { + return attribute; + } + CSOEconItemAttribute *attribute = item.add_attribute(); attribute->set_def_index(defIndex); return attribute; @@ -1210,6 +1220,25 @@ uint32_t Inventory::EquippedMusicKitMVPCount(bool incrementForLocalMVP) const return 0; } +static bool PrepareCasketForNaming(ItemSchema &schema, CSOEconItem &casket) +{ + assert(casket.def_index() == ItemSchema::ItemCasket); + + if (!FindAttribute(casket, ItemSchema::AttributeCasketItemsCount)) + { + CSOEconItemAttribute *countAttribute = + FindOrAddAttribute(casket, ItemSchema::AttributeCasketItemsCount); + if (!schema.SetAttributeUint32(countAttribute, 0)) + { + return false; + } + } + + CSOEconItemAttribute *dateAttribute = + FindOrAddAttribute(casket, ItemSchema::AttributeCasketModificationDate); + return schema.SetAttributeUint32(dateAttribute, static_cast(time(nullptr))); +} + bool Inventory::NameItem(uint64_t nameTagId, uint64_t itemId, std::string_view name, @@ -1217,40 +1246,58 @@ bool Inventory::NameItem(uint64_t nameTagId, CMsgSOSingleObject &destroy, CMsgGCItemCustomizationNotification ¬ification) { - auto tag = m_items.find(nameTagId); - if (tag == m_items.end()) + auto it = m_items.find(itemId); + if (it == m_items.end()) { - Platform::Print("NameItem: name tag item %llu not found for target %llu\n", - nameTagId, itemId); + Platform::Print("NameItem: target item %llu not found\n", itemId); return false; } - if (!m_itemSchema.IsNameTagToolDefIndex(tag->second.def_index())) - { - Platform::Print("NameItem: item %llu def %u is not a name tag for target %llu\n", - nameTagId, tag->second.def_index(), itemId); - return false; - } + // The client sends the casket's built-in naming action as NameItem with a + // zero tool id. It does not use an inventory Name Tag or the ordinary + // item-schema nameable capability. + const bool isCasketNaming = + nameTagId == 0 && it->second.def_index() == ItemSchema::ItemCasket; - auto it = m_items.find(itemId); - if (it == m_items.end()) + auto tag = m_items.end(); + if (isCasketNaming) { - assert(false); - return false; + if (!PrepareCasketForNaming(m_itemSchema, it->second)) + { + Platform::Print("NameItem: failed to initialize casket %llu\n", itemId); + return false; + } } - - if (!m_itemSchema.CanNameDefIndex(it->second.def_index())) + else { - Platform::Print("NameItem: target %llu def %u is not nameable by name tag %llu\n", - itemId, it->second.def_index(), nameTagId); - return false; + if (!m_itemSchema.CanNameDefIndex(it->second.def_index())) + { + Platform::Print("NameItem: target %llu def %u is not nameable by name tag %llu\n", + itemId, it->second.def_index(), nameTagId); + return false; + } + + tag = m_items.find(nameTagId); + if (tag == m_items.end()) + { + Platform::Print("NameItem: name tag item %llu not found for target %llu\n", + nameTagId, itemId); + return false; + } + + if (!m_itemSchema.IsNameTagToolDefIndex(tag->second.def_index())) + { + Platform::Print("NameItem: item %llu def %u is not a name tag for target %llu\n", + nameTagId, tag->second.def_index(), itemId); + return false; + } } it->second.mutable_custom_name()->assign(name); ToSingleObject(update, it->second); - if (GetConfig().DestroyUsedItems()) + if (GetConfig().DestroyUsedItems() && tag != m_items.end()) { DestroyItem(tag, destroy); } From 4cfd9c2c2481fba12bc15c8b577963ec678a72fe Mon Sep 17 00:00:00 2001 From: GT610 Date: Thu, 16 Jul 2026 17:33:11 +0800 Subject: [PATCH 2/2] Polish item naming handling Avoid dispatching empty base-item removal messages and eliminate a redundant casket attribute lookup. --- csgo_gc/gc_client.cpp | 5 ++++- csgo_gc/inventory.cpp | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/csgo_gc/gc_client.cpp b/csgo_gc/gc_client.cpp index 182515b..033030f 100644 --- a/csgo_gc/gc_client.cpp +++ b/csgo_gc/gc_client.cpp @@ -1725,7 +1725,10 @@ void ClientGC::NameBaseItem(GCMessageRead &messageRead) if (m_inventory.NameBaseItem(nameTagId, defIndex, name, create, destroy, notification)) { SendMessageToGame(true, k_ESOMsg_Create, create); - SendMessageToGame(true, k_ESOMsg_Destroy, destroy); + if (destroy.has_type_id()) + { + SendMessageToGame(true, k_ESOMsg_Destroy, destroy); + } SendMessageToGame(false, k_EMsgGCItemCustomizationNotification, notification); } diff --git a/csgo_gc/inventory.cpp b/csgo_gc/inventory.cpp index 3cb9ca0..4814536 100644 --- a/csgo_gc/inventory.cpp +++ b/csgo_gc/inventory.cpp @@ -1226,8 +1226,8 @@ static bool PrepareCasketForNaming(ItemSchema &schema, CSOEconItem &casket) if (!FindAttribute(casket, ItemSchema::AttributeCasketItemsCount)) { - CSOEconItemAttribute *countAttribute = - FindOrAddAttribute(casket, ItemSchema::AttributeCasketItemsCount); + CSOEconItemAttribute *countAttribute = casket.add_attribute(); + countAttribute->set_def_index(ItemSchema::AttributeCasketItemsCount); if (!schema.SetAttributeUint32(countAttribute, 0)) { return false;