networking
This commit is contained in:
363
external/steamworks/steamworksexample/Inventory.cpp
vendored
Normal file
363
external/steamworks/steamworksexample/Inventory.cpp
vendored
Normal file
@@ -0,0 +1,363 @@
|
||||
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose: Class for tracking inventory
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Inventory.h"
|
||||
#include "SpaceWarClient.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: singleton instance of CSpaceWarLocalInventory
|
||||
//-----------------------------------------------------------------------------
|
||||
CSpaceWarLocalInventory *SpaceWarLocalInventory()
|
||||
{
|
||||
static CSpaceWarLocalInventory inv;
|
||||
return &inv;
|
||||
}
|
||||
|
||||
CSpaceWarLocalInventory::CSpaceWarLocalInventory()
|
||||
: m_SteamInventoryResult( this, &CSpaceWarLocalInventory::OnSteamInventoryResult ),
|
||||
m_SteamInventoryFullUpdate( this, &CSpaceWarLocalInventory::OnSteamInventoryFullUpdate )
|
||||
{
|
||||
m_hPlaytimeRequestResult = k_SteamInventoryResultInvalid;
|
||||
m_hPromoRequestResult = k_SteamInventoryResultInvalid;
|
||||
m_hLastFullUpdate = k_SteamInventoryResultInvalid;
|
||||
m_hExchangeRequestResult = k_SteamInventoryResultInvalid;
|
||||
|
||||
m_LastDropInstanceID = k_SteamItemInstanceIDInvalid;
|
||||
|
||||
// Indicate that this game has a use for item definition properties (we look up "name").
|
||||
// If your game hardcodes the complete set of items, then you can probably skip this call.
|
||||
SteamInventory()->LoadItemDefinitions();
|
||||
|
||||
// If there are any promotional items which your game offers (or may offer in the future)
|
||||
// then this is the call that will grant them. Promotional items are a result of meeting
|
||||
// some external criteria like owning another specific game. These criteria are specified
|
||||
// in your Steamworks item definitions.
|
||||
SteamInventory()->GrantPromoItems( &m_hPromoRequestResult );
|
||||
|
||||
#ifdef _DEBUG
|
||||
GrantTestItems();
|
||||
#endif
|
||||
|
||||
// We could pass a variable to receive the result handle, for
|
||||
// comparison to the handle in SteamInventoryResultReady_t,
|
||||
// but this simple example does not bother to keep track of
|
||||
// multiple in-flight API calls.
|
||||
SteamInventory()->GetAllItems( NULL ); // this will fire off FullUpdate and then ResultReady
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handles notification that GetAllItems has refreshed the local inventory
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpaceWarLocalInventory::OnSteamInventoryFullUpdate( SteamInventoryFullUpdate_t *callback )
|
||||
{
|
||||
// This callback triggers immediately before the ResultReady callback. We shouldn't
|
||||
// free the result handle here, as we wil always free it at the end of ResultReady.
|
||||
|
||||
bool bGotResult = false;
|
||||
std::vector<SteamItemDetails_t> vecDetails;
|
||||
uint32 count = 0;
|
||||
if ( SteamInventory()->GetResultItems( callback->m_handle, NULL, &count ) )
|
||||
{
|
||||
vecDetails.resize( count );
|
||||
bGotResult = SteamInventory()->GetResultItems( callback->m_handle, vecDetails.data(), &count );
|
||||
}
|
||||
|
||||
if ( bGotResult )
|
||||
{
|
||||
// For everything already in the inventory, check for update (exists in result) or removal (does not exist)
|
||||
std::list<CSpaceWarItem *>::iterator iter;
|
||||
for ( iter = m_listPlayerItems.begin(); iter != m_listPlayerItems.end(); /*incr at end of loop*/ )
|
||||
{
|
||||
bool bFound = false;
|
||||
for ( size_t i = 0; i < vecDetails.size(); i++ )
|
||||
{
|
||||
if ( (*iter)->GetItemId() == vecDetails[i].m_itemId )
|
||||
{
|
||||
// Update item with matching item id
|
||||
(*iter)->m_Details = vecDetails[i];
|
||||
|
||||
// Remove elements from the result vector as we process updates (fast swap-and-pop removal)
|
||||
if ( i < vecDetails.size() - 1 )
|
||||
vecDetails[i] = vecDetails.back();
|
||||
vecDetails.pop_back();
|
||||
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !bFound )
|
||||
{
|
||||
// No items in the full update match the existing item. Delete current iterator and advance.
|
||||
delete *iter;
|
||||
iter = m_listPlayerItems.erase( iter );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Increment iterator without deleting.
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
// Anything remaining in the result vector is a new item, since we removed all the updates.
|
||||
for ( size_t i = 0; i < vecDetails.size(); ++i )
|
||||
{
|
||||
CSpaceWarItem *item = new CSpaceWarItem();
|
||||
item->m_Details = vecDetails[i];
|
||||
m_listPlayerItems.push_back( item );
|
||||
}
|
||||
}
|
||||
|
||||
// Remember that we just processed this full update to avoid doing work in ResultReady
|
||||
m_hLastFullUpdate = callback->m_handle;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handles notification that the inventory is updated
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpaceWarLocalInventory::OnSteamInventoryResult( SteamInventoryResultReady_t *callback )
|
||||
{
|
||||
// Ignore results that belong to some other SteamID - this normally won't happen, unless you start
|
||||
// calling SerializeResult/DeserializeResult, but it is better to be safe. Also ignore anything that
|
||||
// we just processed in OnSteamInventoryFullUpdate to avoid duplicate work.
|
||||
if ( callback->m_result == k_EResultOK && m_hLastFullUpdate != callback->m_handle &&
|
||||
SteamInventory()->CheckResultSteamID( callback->m_handle, SpaceWarClient()->GetLocalSteamID() ) )
|
||||
{
|
||||
bool bGotResult = false;
|
||||
std::vector<SteamItemDetails_t> vecDetails;
|
||||
uint32 count = 0;
|
||||
if ( SteamInventory()->GetResultItems( callback->m_handle, NULL, &count ) )
|
||||
{
|
||||
vecDetails.resize( count );
|
||||
bGotResult = SteamInventory()->GetResultItems( callback->m_handle, vecDetails.data(), &count );
|
||||
}
|
||||
|
||||
if ( bGotResult )
|
||||
{
|
||||
// For everything already in the inventory, check for update or removal
|
||||
std::list<CSpaceWarItem *>::iterator iter;
|
||||
for ( iter = m_listPlayerItems.begin(); iter != m_listPlayerItems.end(); /*incr at end of loop*/ )
|
||||
{
|
||||
bool bDestroy = false;
|
||||
for ( size_t i = 0; i < vecDetails.size(); i++ )
|
||||
{
|
||||
if ( (*iter)->GetItemId() == vecDetails[i].m_itemId )
|
||||
{
|
||||
// If flagged for removal by a partial update, remove it
|
||||
if ( vecDetails[i].m_unFlags & k_ESteamItemRemoved )
|
||||
{
|
||||
bDestroy = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*iter)->m_Details = vecDetails[i];
|
||||
}
|
||||
|
||||
// Remove elements from the result vector as we process updates (fast swap-and-pop removal)
|
||||
if ( i < vecDetails.size() - 1 )
|
||||
vecDetails[i] = vecDetails.back();
|
||||
vecDetails.pop_back();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bDestroy )
|
||||
{
|
||||
// Delete list element at current iterator and advance.
|
||||
delete *iter;
|
||||
iter = m_listPlayerItems.erase( iter );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Increment iterator without deleting.
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
// Anything remaining in the result vector is a new item, unless flagged for removal by an operation result.
|
||||
for ( size_t i = 0; i < vecDetails.size(); ++i )
|
||||
{
|
||||
if ( !( vecDetails[i].m_unFlags & k_ESteamItemRemoved ) )
|
||||
{
|
||||
CSpaceWarItem *item = new CSpaceWarItem();
|
||||
item->m_Details = vecDetails[i];
|
||||
m_listPlayerItems.push_back( item );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear out any pending handles.
|
||||
if ( callback->m_handle == m_hPlaytimeRequestResult )
|
||||
m_hPlaytimeRequestResult = -1;
|
||||
if ( callback->m_handle == m_hExchangeRequestResult )
|
||||
m_hExchangeRequestResult = -1;
|
||||
if ( callback->m_handle == m_hPromoRequestResult )
|
||||
m_hPromoRequestResult = -1;
|
||||
if ( callback->m_handle == m_hLastFullUpdate )
|
||||
m_hLastFullUpdate = -1;
|
||||
|
||||
// We're not hanging on the the result after processing it.
|
||||
SteamInventory()->DestroyResult( callback->m_handle );
|
||||
}
|
||||
|
||||
void CSpaceWarLocalInventory::CheckForItemDrops()
|
||||
{
|
||||
SteamInventory()->TriggerItemDrop( &m_hPlaytimeRequestResult, k_SpaceWarItem_TimedDropList );
|
||||
}
|
||||
|
||||
void CSpaceWarLocalInventory::ModifyItemProperties()
|
||||
{
|
||||
const CSpaceWarItem *item100 = GetInstanceOf( k_SpaceWarItem_ShipDecoration1 );
|
||||
if ( item100 )
|
||||
{
|
||||
SteamInventoryUpdateHandle_t updateHandle = SteamInventory()->StartUpdateProperties();
|
||||
SteamInventory()->SetProperty( updateHandle, item100->GetItemId(), "string_value", "blah" );
|
||||
SteamInventory()->SetProperty( updateHandle, item100->GetItemId(), "bool_value", true );
|
||||
SteamInventory()->SetProperty( updateHandle, item100->GetItemId(), "int64_value", (int64)55 );
|
||||
SteamInventory()->SetProperty( updateHandle, item100->GetItemId(), "float_value", 123.456f );
|
||||
SteamInventoryResult_t resultHandle;
|
||||
SteamInventory()->SubmitUpdateProperties( updateHandle, &resultHandle );
|
||||
}
|
||||
}
|
||||
|
||||
void CSpaceWarLocalInventory::DoExchange()
|
||||
{
|
||||
const CSpaceWarItem *item100 = GetInstanceOf( k_SpaceWarItem_ShipDecoration1 );
|
||||
const CSpaceWarItem *item101 = GetInstanceOf( k_SpaceWarItem_ShipDecoration2 );
|
||||
const CSpaceWarItem *item102 = GetInstanceOf( k_SpaceWarItem_ShipDecoration3 );
|
||||
const CSpaceWarItem *item103 = GetInstanceOf( k_SpaceWarItem_ShipDecoration4 );
|
||||
if ( item100 && item101 && item102 && item103 )
|
||||
{
|
||||
SteamItemInstanceID_t inputItems[4];
|
||||
uint32 inputQuantities[4];
|
||||
inputItems[0] = item100->GetItemId();
|
||||
inputQuantities[0] = 1;
|
||||
inputItems[1] = item101->GetItemId();
|
||||
inputQuantities[1] = 1;
|
||||
inputItems[2] = item102->GetItemId();
|
||||
inputQuantities[2] = 1;
|
||||
inputItems[3] = item103->GetItemId();
|
||||
inputQuantities[3] = 1;
|
||||
SteamItemDef_t outputItems[1];
|
||||
outputItems[0] = 110;
|
||||
uint32 outputQuantity[1];
|
||||
outputQuantity[0] = 1;
|
||||
SteamInventory()->ExchangeItems( &m_hExchangeRequestResult, outputItems, outputQuantity, 1, inputItems, inputQuantities, 4 );
|
||||
}
|
||||
}
|
||||
|
||||
void CSpaceWarLocalInventory::GrantTestItems()
|
||||
{
|
||||
std::vector<SteamItemDef_t> newItems;
|
||||
newItems.push_back( k_SpaceWarItem_ShipDecoration1 );
|
||||
newItems.push_back( k_SpaceWarItem_ShipDecoration2 );
|
||||
SteamInventory()->GenerateItems( NULL, newItems.data(), NULL, (uint32) newItems.size() );
|
||||
}
|
||||
|
||||
const CSpaceWarItem * CSpaceWarLocalInventory::GetItem( SteamItemInstanceID_t nItemId ) const
|
||||
{
|
||||
std::list<CSpaceWarItem *>::const_iterator iter;
|
||||
for ( iter = m_listPlayerItems.begin(); iter != m_listPlayerItems.end(); ++iter )
|
||||
{
|
||||
if ( (*iter)->GetItemId() == nItemId )
|
||||
return (*iter);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool CSpaceWarLocalInventory::HasInstanceOf( SteamItemDef_t nDefinition ) const
|
||||
{
|
||||
std::list<CSpaceWarItem *>::const_iterator iter;
|
||||
for ( iter = m_listPlayerItems.begin(); iter != m_listPlayerItems.end(); ++iter )
|
||||
{
|
||||
if ( ( *iter )->GetDefinition() == nDefinition )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 CSpaceWarLocalInventory::GetNumOf( SteamItemDef_t nDefinition ) const
|
||||
{
|
||||
uint32 unQuantity = 0;
|
||||
std::list<CSpaceWarItem *>::const_iterator iter;
|
||||
for ( iter = m_listPlayerItems.begin(); iter != m_listPlayerItems.end(); ++iter )
|
||||
{
|
||||
if ( ( *iter )->GetDefinition() == nDefinition )
|
||||
{
|
||||
unQuantity += (*iter)->GetQuantity();
|
||||
}
|
||||
}
|
||||
return unQuantity;
|
||||
}
|
||||
|
||||
const CSpaceWarItem * CSpaceWarLocalInventory::GetInstanceOf( SteamItemDef_t nDefinition ) const
|
||||
{
|
||||
std::list<CSpaceWarItem *>::const_iterator iter;
|
||||
for ( iter = m_listPlayerItems.begin(); iter != m_listPlayerItems.end(); ++iter )
|
||||
{
|
||||
if ( ( *iter )->GetDefinition() == nDefinition )
|
||||
return (*iter);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CSpaceWarLocalInventory::RefreshFromServer()
|
||||
{
|
||||
// This will trigger the SteamInventoryResultReady_t callback,
|
||||
// and possibly the SteamInventoryFullUpdate_t callback first.
|
||||
|
||||
// We could pass a variable to receive the result handle, for
|
||||
// comparison to the handle in SteamInventoryResultReady_t,
|
||||
// but this simple example does not bother to keep track of
|
||||
// multiple in-flight API calls.
|
||||
SteamInventory()->GetAllItems( NULL );
|
||||
}
|
||||
|
||||
|
||||
std::string CSpaceWarItem::GetLocalizedName() const
|
||||
{
|
||||
std::string ret;
|
||||
char buf[512];
|
||||
uint32 bufSize = sizeof(buf);
|
||||
if ( SteamInventory()->GetItemDefinitionProperty( GetDefinition(), "name", buf, &bufSize ) && bufSize <= sizeof(buf) )
|
||||
{
|
||||
ret = buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = "(unknown)";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string CSpaceWarItem::GetLocalizedDescription() const
|
||||
{
|
||||
std::string ret;
|
||||
char buf[2048];
|
||||
uint32 bufSize = sizeof(buf);
|
||||
if ( SteamInventory()->GetItemDefinitionProperty( GetDefinition(), "description", buf, &bufSize ) && bufSize <= sizeof(buf) )
|
||||
{
|
||||
ret = buf;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string CSpaceWarItem::GetIconURL() const
|
||||
{
|
||||
std::string ret;
|
||||
char buf[512];
|
||||
uint32 bufSize = sizeof(buf);
|
||||
if ( SteamInventory()->GetItemDefinitionProperty( GetDefinition(), "icon_url", buf, &bufSize ) && bufSize <= sizeof(buf) )
|
||||
{
|
||||
ret = buf;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user