diff options
Diffstat (limited to 'game/shared/econ/econ_storecategory.cpp')
| -rw-r--r-- | game/shared/econ/econ_storecategory.cpp | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/game/shared/econ/econ_storecategory.cpp b/game/shared/econ/econ_storecategory.cpp new file mode 100644 index 0000000..610f2da --- /dev/null +++ b/game/shared/econ/econ_storecategory.cpp @@ -0,0 +1,267 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Base class for generating store meta data. Abstract methods need +// to be overridden on a per-product basis. +// +//------------------------------------------------------------------------------------------------------------------------------- + +#include "cbase.h" +#include "econ_storecategory.h" +#include "econ_store.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//------------------------------------------------------------------------------------------------------------------------------- + +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Invalid = (StoreCategoryID_t)0; +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_New = CEconStoreCategoryManager::GetCategoryID( "New" ); +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Weapons = CEconStoreCategoryManager::GetCategoryID( "Weapons" ); +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Limited = CEconStoreCategoryManager::GetCategoryID( "Limited" ); +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Maps = CEconStoreCategoryManager::GetCategoryID( "Maps" ); +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Cosmetics = CEconStoreCategoryManager::GetCategoryID( "Cosmetics" ); +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Taunts = CEconStoreCategoryManager::GetCategoryID( "Taunts" ); +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Tools = CEconStoreCategoryManager::GetCategoryID( "Tools" ); +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Bundles = CEconStoreCategoryManager::GetCategoryID( "Bundles" ); +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Collections= CEconStoreCategoryManager::GetCategoryID( "Collections" ); +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Popular = CEconStoreCategoryManager::GetCategoryID( "Popular" ); +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_OnSale = CEconStoreCategoryManager::GetCategoryID( "OnSale" ); +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Featured = CEconStoreCategoryManager::GetCategoryID( "Featured" ); +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_ClassBundles = CEconStoreCategoryManager::GetCategoryID( "Class_Bundles" ); +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::k_CategoryID_Highlighted = CEconStoreCategoryManager::GetCategoryID( "Highlighted" ); + + +//------------------------------------------------------------------------------------------------------------------------------- + +CEconStoreCategoryManager::CEconStoreCategoryManager() +{ + m_unHomeCategoryID = k_CategoryID_Invalid; +} + +bool CEconStoreCategoryManager::BInit( CEconStorePriceSheet *pPriceSheet, KeyValues *pStoreMetaDataKV ) +{ + KeyValues *pCategoriesKV = pStoreMetaDataKV->FindKey( "categories" ); + if ( !pCategoriesKV ) + { + AssertMsg( 0, "Could not find 'categories' subkey!" ); + return false; + } + + FOR_EACH_TRUE_SUBKEY( pCategoriesKV, pKVCurCategory ) + { + const int iIndex = m_vecCategories.AddToTail(); + StoreCategory_t &curCategory = m_vecCategories[ iIndex ]; + if ( !BInitCategory( pPriceSheet, &curCategory, pKVCurCategory ) ) + return false; + + // If the current category is the home page, cache off its ID + if ( curCategory.m_bIsHome ) + { + m_unHomeCategoryID = curCategory.m_unID; + } + } + + // Verify that any parents point to valid categories + FOR_EACH_VEC( m_vecCategories, i ) + { + const StoreCategory_t &curCategory = m_vecCategories[i]; + + // Skip current category if it refers to invalid, which is fine + if ( curCategory.m_unParentCategoryID == k_CategoryID_Invalid ) + continue; + + // A category can't be a parent to itself + if ( curCategory.m_unID == curCategory.m_unParentCategoryID ) + { + AssertMsg( 0, "Store category %s is using itself as a parent category!", curCategory.m_pchName ); + } + + // Attempt to find the current section's parent ID + bool bFound = false; + FOR_EACH_VEC( m_vecCategories, j ) + { + // Don't compare against self + if ( i == j ) + continue; + + if ( m_vecCategories[j].m_unID == curCategory.m_unParentCategoryID ) + { + bFound = true; + break; + } + } + + // If we couldn't find the current section's parent ID, assert + if ( !bFound ) + { + AssertMsg( 0, "Category %s refers to an unknown parent category - check your spelling!", curCategory.m_pchName ); + } + } + + // Setup child category lists - looping twice to keep this code clean and easy to read + FOR_EACH_VEC( m_vecCategories, i ) + { + const StoreCategory_t &curCategory = m_vecCategories[i]; + + if ( k_CategoryID_Invalid == curCategory.m_unParentCategoryID ) + continue; + + StoreCategory_t *pParentCategory = GetStoreCategoryFromID( curCategory.m_unParentCategoryID ); + if ( !pParentCategory ) + continue; + + pParentCategory->m_vecSubcategories.AddToTail( &curCategory ); + } + + return true; +} + +//------------------------------------------------------------------------------------------------------------------------------- + +bool CEconStoreCategoryManager::BInitCategory( CEconStorePriceSheet *pPriceSheet, StoreCategory_t *pCategory, KeyValues* pKVTab ) +{ + const char *pDefaultResFile = "Resource/UI/econ/store/v2/StorePage.res"; + + // Get the main category name + const char* pCategoryName = pKVTab->GetName(); + if ( !pCategoryName || !pCategoryName[0] ) + { + AssertMsg( 0, "Invalid category name!" ); + return false; + } + + const bool bIsHome = pKVTab->GetBool( "home", false ); + pCategory->m_bIsHome = bIsHome; + + pCategory->m_pchRawName = pCategoryName; + pCategory->m_unID = GetCategoryID( pCategoryName ); + + pCategory->m_bUseLargeCells = pKVTab->GetBool( "use_large_cells", false ); + pCategory->m_bVisible = pKVTab->GetBool( "visible", true ); + pCategory->m_bInGameOnly = pKVTab->GetBool( "ingame_only", false ); + pCategory->m_bDefaultTab = pKVTab->GetBool( "default", false ); + +#if defined( GC_DLL ) + // Until we replace the in-game store with the web store, we have this hacky override property, so + // that we can call the home page "HOME" in the game client and "TOP SELLERS" on the web. The home page + // will be evolving shortly to include a lot more than just a list of top sellers. + const char *pchLabelTokenWebOverride = pKVTab->GetString( "web_label_token_override", NULL ); +#else + const char *pchLabelTokenWebOverride = NULL; +#endif + pCategory->m_pchName = pchLabelTokenWebOverride ? pchLabelTokenWebOverride : pKVTab->GetString( "label_token", "#Store_Unknown" ); + + pCategory->m_pchPageClass = pKVTab->GetString( "page_class", "CStorePage" ); + pCategory->m_pchPageRes = pKVTab->GetString( "page_res", pDefaultResFile ); + pCategory->m_pchSortType = pKVTab->GetString( "sort_type", "" ); + + // Important for web store but not needed for VGUI store +#if defined( GC_DLL ) + if ( !bIsHome ) + { + const char *pchDropdownPrefabName = pKVTab->GetString( "dropdown_prefab", NULL ); + pCategory->m_pDropdownPrefab = GEconStoreMetaData()->FindDropdownPrefab( pchDropdownPrefabName ); + if ( !pCategory->m_pDropdownPrefab ) + { + AssertMsg( pCategory->m_pDropdownPrefab, CFmtStr( "Invalid dropdown prefab name, '%s'!", pchDropdownPrefabName ).Access() ); + return false; + } + } + else + { + pCategory->m_pDropdownPrefab = NULL; + } +#endif + + // Look for a parent category for non-home categories + if ( !bIsHome ) + { + const char *pParentCategoryName = pKVTab->GetString( "parent", NULL ); + if ( pParentCategoryName ) + { + pCategory->m_unParentCategoryID = GetCategoryID( pParentCategoryName ); + } + else + { + pCategory->m_unParentCategoryID = k_CategoryID_Invalid; + } + } + + return true; +} + +bool CEconStoreCategoryManager::BOnPriceSheetLoaded( CEconStorePriceSheet *pPriceSheet ) +{ + // Go through all categories/subcategories and add a list of items to each. + // If an item belongs to a subcategory, it will also be added to its parent category. For example, + // a hat will be added to both the "hats" subcategory and the "items" parent category. + FOR_EACH_VEC( m_vecCategories, iCategory ) + { + StoreCategory_t &Category = m_vecCategories[iCategory]; + + // find all entries that match + const CEconStorePriceSheet::EconStoreEntryMap_t &mapEntries = pPriceSheet->GetEntries(); + FOR_EACH_MAP_FAST( mapEntries, idx ) + { + const econ_store_entry_t &entry = mapEntries[idx]; + + if ( entry.IsListedInCategoryOrSubcategories( Category ) ) + { + Category.m_vecEntries.InsertNoSort( entry.GetItemDefinitionIndex() ); + } + } + } + + return true; +} + +//------------------------------------------------------------------------------------------------------------------------------- + +/*static*/ StoreCategoryID_t CEconStoreCategoryManager::GetCategoryID( const char *pCategoryName ) +{ + // Make the input lower case + CUtlString strLowerCase = pCategoryName; + strLowerCase.ToLower(); + + return CRC32_ProcessSingleBuffer( (void*)strLowerCase.Get(), strLowerCase.Length() ); +} + +//------------------------------------------------------------------------------------------------------------------------------- + +const CEconStoreCategoryManager::StoreCategory_t *CEconStoreCategoryManager::GetStoreCategoryFromID( StoreCategoryID_t unID ) const +{ + return const_cast< CEconStoreCategoryManager * >( this )->GetStoreCategoryFromID( unID ); +} + +CEconStoreCategoryManager::StoreCategory_t *CEconStoreCategoryManager::GetStoreCategoryFromID( StoreCategoryID_t unID ) +{ + if ( k_CategoryID_Invalid != unID ) + { + FOR_EACH_VEC( m_vecCategories, i ) + { + if ( unID == m_vecCategories[i].m_unID ) + return &m_vecCategories[i]; + } + } + + return NULL; +} + +//------------------------------------------------------------------------------------------------------------------------------- + +static CEconStoreCategoryManager *gs_pEconStoreCategoryManager = NULL; +CEconStoreCategoryManager *GEconStoreCategoryManager() +{ + if ( !gs_pEconStoreCategoryManager ) + { + gs_pEconStoreCategoryManager = new CEconStoreCategoryManager(); + } + + return gs_pEconStoreCategoryManager; +} + +void ClearEconStoreCategoryManager() +{ + delete gs_pEconStoreCategoryManager; + gs_pEconStoreCategoryManager = NULL; +}
\ No newline at end of file |