mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-09-21 04:56:01 +08:00
Update from SDK 2013
This commit is contained in:

committed by
Nicholas Hastings

parent
6d5c024820
commit
94b660e16e
415
game/shared/workshop/ugc_utils.cpp
Normal file
415
game/shared/workshop/ugc_utils.cpp
Normal file
@ -0,0 +1,415 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Utility helper functions for dealing with UGC files
|
||||
//
|
||||
//==========================================================================//
|
||||
#include "cbase.h"
|
||||
|
||||
#include "steam/steam_api.h"
|
||||
#include "ugc_utils.h"
|
||||
#include "fmtstr.h"
|
||||
|
||||
// utime() and stat()
|
||||
#if defined( _WIN32 )
|
||||
#include <sys/utime.h>
|
||||
#elif defined(OSX)
|
||||
#include <utime.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <utime.h>
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
ISteamUGC *GetSteamUGC()
|
||||
{
|
||||
#ifdef GAME_DLL
|
||||
// Use steamgameserver context if this isn't a client/listenserver.
|
||||
// While we can use steamgameserver in listenservers, we want to always use client-side UGC there currently.
|
||||
if ( engine->IsDedicatedServer() )
|
||||
{
|
||||
return steamgameserverapicontext ? steamgameserverapicontext->SteamUGC() : NULL;
|
||||
}
|
||||
#endif
|
||||
return steamapicontext ? steamapicontext->SteamUGC() : NULL;
|
||||
}
|
||||
|
||||
ISteamRemoteStorage *GetSteamRemoteStorage()
|
||||
{
|
||||
return steamapicontext ? steamapicontext->SteamRemoteStorage() : NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// File request helper class for older ISteamRemoteStorage UGC files.
|
||||
// Prefer ISteamUGC when possible.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CUGCFileRequest::CUGCFileRequest( void ) :
|
||||
m_hCloudID(k_UGCHandleInvalid),
|
||||
m_UGCStatus(UGCFILEREQUEST_READY),
|
||||
m_AsyncControl(NULL)
|
||||
{
|
||||
// Start with these disabled
|
||||
m_szFileName[0] = '\0';
|
||||
m_szTargetDirectory[0] = '\0';
|
||||
m_szTargetFilename[0] = '\0';
|
||||
m_szErrorText[0] = '\0';
|
||||
|
||||
#ifdef FILEREQUEST_IO_STALL
|
||||
m_nIOStallType = FILEREQUEST_STALL_DOWNLOAD;
|
||||
m_flIOStallDuration = FILEREQUEST_IO_STALL_DELAY; // seconds
|
||||
#endif // FILEREQUEST_IO_STALL
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CUGCFileRequest::~CUGCFileRequest( void )
|
||||
{
|
||||
// Finish the file i/o
|
||||
if ( m_AsyncControl != NULL )
|
||||
{
|
||||
g_pFullFileSystem->AsyncFinish( m_AsyncControl );
|
||||
g_pFullFileSystem->AsyncRelease( m_AsyncControl );
|
||||
m_AsyncControl = NULL;
|
||||
}
|
||||
|
||||
// Clear our internal buffer
|
||||
m_bufContents.Clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Start a download by handle
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
UGCFileRequestStatus_t CUGCFileRequest::StartDownload( UGCHandle_t hFileHandle, const char *lpszTargetDirectory /*= NULL*/, const char *lpszTargetFilename /*= NULL*/ )
|
||||
{
|
||||
// Start with the assumption of failure
|
||||
m_UGCStatus = UGCFILEREQUEST_ERROR;
|
||||
|
||||
// Start the download request
|
||||
SteamAPICall_t hSteamAPICall = GetSteamRemoteStorage()->UGCDownload( hFileHandle, 0 );
|
||||
m_callbackUGCDownload.Set( hSteamAPICall, this, &CUGCFileRequest::Steam_OnUGCDownload );
|
||||
|
||||
if ( hSteamAPICall != k_uAPICallInvalid )
|
||||
{
|
||||
#ifdef LOG_FILEREQUEST_PROGRESS
|
||||
Msg( "Started download of cloud file %s/%s (%08X%08X)\n", lpszTargetDirectory, lpszTargetFilename, (uint32)(hFileHandle>>32), (uint32)hFileHandle );
|
||||
#endif // LOG_FILEREQUEST_PROGRESS
|
||||
|
||||
// Mark download as in progress
|
||||
m_UGCStatus = UGCFILEREQUEST_DOWNLOADING;
|
||||
m_hCloudID = hFileHandle;
|
||||
|
||||
// Take a target directory for the file
|
||||
if ( lpszTargetDirectory != NULL )
|
||||
{
|
||||
V_strncpy( m_szTargetDirectory, lpszTargetDirectory, MAX_PATH );
|
||||
}
|
||||
|
||||
// Take a target filename for the file
|
||||
if ( lpszTargetFilename != NULL )
|
||||
{
|
||||
V_strncpy( m_szTargetFilename, lpszTargetFilename, MAX_PATH );
|
||||
}
|
||||
|
||||
#ifdef FILEREQUEST_IO_STALL
|
||||
m_flIOStallStart = gpGlobals->curtime;
|
||||
#endif // FILEREQUEST_IO_STALL
|
||||
|
||||
// Done!
|
||||
return m_UGCStatus;
|
||||
}
|
||||
|
||||
// We were unable to start our download through the Steam API
|
||||
return ThrowError( "Failed to initiate download of file from cloud\n" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Start an upload of a buffer by filename
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
UGCFileRequestStatus_t CUGCFileRequest::StartUpload( CUtlBuffer &buffer, const char *lpszFilename )
|
||||
{
|
||||
// Start with the assumption of failure
|
||||
m_UGCStatus = UGCFILEREQUEST_ERROR;
|
||||
|
||||
// Write the local copy of the file
|
||||
#ifdef LOG_FILEREQUEST_PROGRESS
|
||||
Msg( "Saving %s to user cloud...\n", lpszFilename );
|
||||
#endif // LOG_FILEREQUEST_PROGRESS
|
||||
|
||||
ISteamRemoteStorage *pRemoteStorage = GetSteamRemoteStorage();
|
||||
if ( !pRemoteStorage || !pRemoteStorage->FileWrite( lpszFilename, buffer.Base(), buffer.TellPut() ) )
|
||||
return ThrowError( "Failed to write file to cloud\n" );
|
||||
|
||||
// Now share the file (uploads it to the cloud)
|
||||
SteamAPICall_t hSteamAPICall = pRemoteStorage->FileShare( lpszFilename );
|
||||
m_callbackFileShare.Set( hSteamAPICall, this, &CUGCFileRequest::Steam_OnFileShare);
|
||||
|
||||
#ifdef FILEREQUEST_IO_STALL
|
||||
m_flIOStallStart = gpGlobals->curtime;
|
||||
#endif // FILEREQUEST_IO_STALL
|
||||
|
||||
m_UGCStatus = UGCFILEREQUEST_UPLOADING;
|
||||
return m_UGCStatus;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: FileShare complete for a file request
|
||||
//-----------------------------------------------------------------------------
|
||||
void CUGCFileRequest::Steam_OnFileShare( RemoteStorageFileShareResult_t *pResult, bool bError )
|
||||
{
|
||||
if ( bError )
|
||||
{
|
||||
ThrowError( "Upload of file to Steam cloud failed\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef LOG_FILEREQUEST_PROGRESS
|
||||
Msg( "Custom map uploaded to cloud completed OK, assigned UGC ID %08X%08X\n", (uint32)(pResult->m_hFile >> 32), (uint32)(pResult->m_hFile) );
|
||||
#endif // LOG_FILEREQUEST_PROGRESS
|
||||
|
||||
// Save the return handle
|
||||
m_hCloudID = pResult->m_hFile;
|
||||
|
||||
MarkCompleteAndFree();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: UGDownload complete for a file request
|
||||
//-----------------------------------------------------------------------------
|
||||
void CUGCFileRequest::Steam_OnUGCDownload( RemoteStorageDownloadUGCResult_t *pResult, bool bError )
|
||||
{
|
||||
// Completed. Did we succeed?
|
||||
if ( bError || pResult->m_eResult != k_EResultOK )
|
||||
{
|
||||
ThrowError( "Download of file from cloud failed!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we got back the file we were expecting
|
||||
Assert( pResult->m_hFile == m_hCloudID );
|
||||
|
||||
// Fetch file details
|
||||
AppId_t nAppID;
|
||||
char *pchName;
|
||||
int32 nFileSizeInBytes = -1;
|
||||
CSteamID steamIDOwner;
|
||||
ISteamRemoteStorage *pRemoteStorage = GetSteamRemoteStorage();
|
||||
|
||||
if ( !pRemoteStorage->GetUGCDetails( m_hCloudID, &nAppID, &pchName, &nFileSizeInBytes, &steamIDOwner ) || nFileSizeInBytes <= 0 )
|
||||
{
|
||||
ThrowError( "Unable to retrieve cloud file info from Steam\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate a temporary buffer
|
||||
m_bufContents.Clear();
|
||||
m_bufContents.SeekPut( CUtlBuffer::SEEK_HEAD, nFileSizeInBytes );
|
||||
|
||||
// Read in the data
|
||||
if ( pRemoteStorage->UGCRead( m_hCloudID, m_bufContents.Base( ), nFileSizeInBytes, 0, k_EUGCRead_ContinueReadingUntilFinished ) != nFileSizeInBytes )
|
||||
{
|
||||
ThrowError( "Failed call to UGCRead on cloud file\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Save our name
|
||||
V_strncpy( m_szFileName, pchName, sizeof(m_szFileName) );
|
||||
|
||||
// Take this as our target if we haven't specified one
|
||||
if ( m_szTargetFilename[0] == '\0' )
|
||||
{
|
||||
V_strncpy( m_szTargetFilename, pchName, sizeof(m_szTargetFilename) );
|
||||
}
|
||||
|
||||
#ifdef LOG_FILEREQUEST_PROGRESS
|
||||
Msg( "Read file %s/%s (%08X%08X)\n", m_szTargetDirectory, m_szTargetFilename, (uint32)(m_hCloudID>>32), (uint32)m_hCloudID );
|
||||
#endif // LOG_FILEREQUEST_PROGRESS
|
||||
|
||||
// FIXME: Is this already in scope?
|
||||
// Done downloading, so commit it to the local disc
|
||||
const char *lpszFilename = V_UnqualifiedFileName( GetFileName() );
|
||||
|
||||
char szLocalFilename[MAX_PATH];
|
||||
|
||||
// Make sure the directory exists if we're creating one
|
||||
if ( m_szTargetDirectory[0] != '\0' )
|
||||
{
|
||||
V_snprintf( szLocalFilename, sizeof(szLocalFilename), "%s/%s", m_szTargetDirectory, lpszFilename );
|
||||
g_pFullFileSystem->CreateDirHierarchy( m_szTargetDirectory, "DEFAULT_WRITE_PATH" );
|
||||
}
|
||||
else
|
||||
{
|
||||
V_snprintf( szLocalFilename, sizeof(szLocalFilename), "%s", lpszFilename );
|
||||
|
||||
/*
|
||||
char szDirectory[MAX_PATH];
|
||||
Q_FileBase( GetFileName(), szDirectory, sizeof(szDirectory) );
|
||||
g_pFullFileSystem->CreateDirHierarchy( szDirectory, "DEFAULT_WRITE_PATH" );
|
||||
*/
|
||||
}
|
||||
|
||||
// Async write this to disc with monitoring
|
||||
if ( g_pFullFileSystem->AsyncWrite( szLocalFilename, m_bufContents.Base(), m_bufContents.TellPut(), false, false, &m_AsyncControl ) < 0 )
|
||||
{
|
||||
// Async write failed immediately!
|
||||
ThrowError( CFmtStr( "Async write of downloaded file %s failed\n", szLocalFilename ) );
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef LOG_FILEREQUEST_PROGRESS
|
||||
Msg( "Async write started for %s (%08X%08X)\n", szLocalFilename, (uint32)(m_hCloudID>>32), (uint32)m_hCloudID );
|
||||
#endif // LOG_FILEREQUEST_PROGRESS
|
||||
|
||||
// Mark us as having started out download
|
||||
m_UGCStatus = UGCFILEREQUEST_DOWNLOAD_WRITING;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Poll for status and drive the process forward
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
UGCFileRequestStatus_t CUGCFileRequest::Update( void )
|
||||
{
|
||||
switch ( m_UGCStatus )
|
||||
{
|
||||
// Handle the async write of the file to disc
|
||||
case UGCFILEREQUEST_DOWNLOAD_WRITING:
|
||||
{
|
||||
#ifdef FILEREQUEST_IO_STALL
|
||||
if ( m_nIOStallType == FILEREQUEST_STALL_WRITE )
|
||||
{
|
||||
if ( ( gpGlobals->curtime - m_flIOStallStart ) < m_flIOStallDuration )
|
||||
return UGCFILEREQUEST_DOWNLOAD_WRITING;
|
||||
}
|
||||
#endif // FILEREQUEST_IO_STALL
|
||||
|
||||
// Monitor the async write progress and clean up after we're done
|
||||
if ( m_AsyncControl )
|
||||
{
|
||||
FSAsyncStatus_t status = g_pFullFileSystem->AsyncStatus( m_AsyncControl );
|
||||
switch ( status )
|
||||
{
|
||||
case FSASYNC_STATUS_PENDING:
|
||||
case FSASYNC_STATUS_INPROGRESS:
|
||||
case FSASYNC_STATUS_UNSERVICED:
|
||||
return UGCFILEREQUEST_DOWNLOAD_WRITING;
|
||||
|
||||
case FSASYNC_ERR_FILEOPEN:
|
||||
return ThrowError( "Unable to write file to disc!\n" );
|
||||
}
|
||||
|
||||
// Finish the read
|
||||
g_pFullFileSystem->AsyncFinish( m_AsyncControl );
|
||||
g_pFullFileSystem->AsyncRelease( m_AsyncControl );
|
||||
m_AsyncControl = NULL;
|
||||
|
||||
#ifdef LOG_FILEREQUEST_PROGRESS
|
||||
Msg( "Async write completed for %s/%s (%08X%08X)\n", m_szTargetDirectory, m_szTargetFilename, (uint32)(m_hCloudID>>32), (uint32)m_hCloudID );
|
||||
#endif // LOG_FILEREQUEST_PROGRESS
|
||||
|
||||
MarkCompleteAndFree();
|
||||
return m_UGCStatus;
|
||||
}
|
||||
|
||||
// Somehow we lost the handle to our async status or got a spurious call in here!
|
||||
return ThrowError( "Lost handle to async handle for downloaded file write!" );
|
||||
}
|
||||
break;
|
||||
|
||||
// Handle starting up a download
|
||||
case UGCFILEREQUEST_READY:
|
||||
case UGCFILEREQUEST_DOWNLOADING:
|
||||
case UGCFILEREQUEST_UPLOADING:
|
||||
case UGCFILEREQUEST_FINISHED:
|
||||
return m_UGCStatus;
|
||||
break;
|
||||
|
||||
// An error has occurred while trying to handle the user's request
|
||||
default:
|
||||
case UGCFILEREQUEST_ERROR:
|
||||
return UGCFILEREQUEST_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Get the local file name on disk, accounting for target directories and filenames
|
||||
//-----------------------------------------------------------------------------
|
||||
void CUGCFileRequest::GetLocalFileName( char *pDest, size_t strSize )
|
||||
{
|
||||
if ( m_szTargetDirectory[0] == '\0' )
|
||||
{
|
||||
V_strncpy( pDest, GetFileName(), strSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
V_snprintf( pDest, strSize, "%s/%s", m_szTargetDirectory, GetFileName() );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Get the local directory on disk, accounting for target directories
|
||||
//-----------------------------------------------------------------------------
|
||||
void CUGCFileRequest::GetLocalDirectory( char *pDest, size_t strSize )
|
||||
{
|
||||
if ( m_szTargetDirectory[0] == '\0' )
|
||||
{
|
||||
V_strncpy( pDest, "\0", strSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
V_strncpy( pDest, m_szTargetDirectory, strSize );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets the modified/access times of a file, taking care to avoid a win32 CRT bug.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool UGC_SetFileTime( const char *pFileRelativePath, RTime32 uTimestamp )
|
||||
{
|
||||
char chFullFilePathForTimestamp[ MAX_PATH ] = {0};
|
||||
char const *pchFullPath = g_pFullFileSystem->RelativePathToFullPath( pFileRelativePath,
|
||||
UGC_PATHID,
|
||||
chFullFilePathForTimestamp,
|
||||
sizeof( chFullFilePathForTimestamp ) );
|
||||
if ( pchFullPath )
|
||||
{
|
||||
struct utimbuf tbuffer;
|
||||
tbuffer.modtime = tbuffer.actime = uTimestamp;
|
||||
int iResultCode = utime( pchFullPath, &tbuffer );
|
||||
|
||||
#if defined ( _WIN32 )
|
||||
// In MSVC2013 and earlier, utime() incorrectly factors in daylight savings.
|
||||
// Prior to MSVC2013 stat() also has this bug.
|
||||
// This means for MSVC2013's CRT specifically, stat() stops canceling out the error and returns something
|
||||
// different from what utime() sets.
|
||||
// Seriously.
|
||||
// https://connect.microsoft.com/VisualStudio/feedback/details/811534/utime-sometimes-fails-to-set-the-correct-file-times-in-visual-c-2013
|
||||
|
||||
// Check if what we wrote is being offset, then re-set the time canceling out this offset.
|
||||
RTime32 unFileTimeFromStat = (RTime32)g_pFullFileSystem->GetFileTime( pFileRelativePath, "MOD" );
|
||||
if ( unFileTimeFromStat != uTimestamp )
|
||||
{
|
||||
int32 nDLSOffset = unFileTimeFromStat - uTimestamp;
|
||||
tbuffer.modtime = tbuffer.actime = uTimestamp - nDLSOffset;
|
||||
iResultCode = utime( pchFullPath, &tbuffer );
|
||||
#if defined ( DEBUG )
|
||||
unFileTimeFromStat = (RTime32)g_pFullFileSystem->GetFileTime( pFileRelativePath, "MOD" );
|
||||
Assert( unFileTimeFromStat == uTimestamp );
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return ( iResultCode == 0 );
|
||||
}
|
||||
return false;
|
||||
}
|
138
game/shared/workshop/ugc_utils.h
Normal file
138
game/shared/workshop/ugc_utils.h
Normal file
@ -0,0 +1,138 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Utility helper functions for dealing with UGC files
|
||||
//
|
||||
//==========================================================================//
|
||||
|
||||
#ifndef UGC_UTILS_H
|
||||
#define UGC_UTILS_H
|
||||
|
||||
#include "utlbuffer.h"
|
||||
#include "filesystem.h"
|
||||
#include "steam/steam_api.h"
|
||||
|
||||
#include "dbg.h"
|
||||
|
||||
// All UGC files are assumed to be on this path by default
|
||||
#define UGC_PATHID "DEFAULT_WRITE_PATH"
|
||||
|
||||
// This will log the UGC file requests as they're serviced
|
||||
// #define LOG_FILEREQUEST_PROGRESS
|
||||
|
||||
// Enable verbose debug spew to DevMsg
|
||||
// #define UGC_DEBUG
|
||||
|
||||
#define UGCMsg(...) Msg("[UGC] " __VA_ARGS__)
|
||||
#define UGCWarning(...) Warning("[UGC] " __VA_ARGS__)
|
||||
|
||||
#ifdef UGC_DEBUG
|
||||
#define UGCDebug(...) DevMsg("[UGC Debug] " __VA_ARGS__)
|
||||
#else // UGC_DEBUG
|
||||
#define UGCDebug(...)
|
||||
#endif // UGC_DEBUG
|
||||
|
||||
ISteamUGC *GetSteamUGC();
|
||||
ISteamRemoteStorage *GetSteamRemoteStorage();
|
||||
|
||||
// Consistently set/get modified/access timestamps for UGC files.
|
||||
bool UGC_SetFileTime( const char *pFileRelativePath, RTime32 uTimestamp );
|
||||
|
||||
// Simulates stalling of the file IO for testing
|
||||
// #define FILEREQUEST_IO_STALL
|
||||
#define FILEREQUEST_IO_STALL_DELAY 1.0f // Seconds
|
||||
|
||||
enum UGCFileRequestStatus_t
|
||||
{
|
||||
UGCFILEREQUEST_ERROR = -1, // An error occurred while processing the file operation
|
||||
UGCFILEREQUEST_READY, // File request is ready to do work
|
||||
UGCFILEREQUEST_DOWNLOADING, // Currently downloading a file
|
||||
UGCFILEREQUEST_DOWNLOAD_WRITING, // Async write of the downloaded file to the disc
|
||||
UGCFILEREQUEST_UPLOADING, // Currently uploading a file
|
||||
UGCFILEREQUEST_FINISHED // Operation complete, no work waiting
|
||||
};
|
||||
|
||||
#ifdef FILEREQUEST_IO_STALL
|
||||
enum
|
||||
{
|
||||
FILEREQUEST_STALL_NONE,
|
||||
FILEREQUEST_STALL_DOWNLOAD, // Download from UGC server
|
||||
FILEREQUEST_STALL_WRITE, // Write to disc
|
||||
};
|
||||
#endif // FILEREQUEST_IO_STALL
|
||||
|
||||
|
||||
// FIXME(johns): This is superseded by the newer CUGCSyncedFile. Once the
|
||||
// remaining users of this are migrated it should be nuked.
|
||||
class CUGCFileRequest
|
||||
{
|
||||
public:
|
||||
CUGCFileRequest( void );
|
||||
~CUGCFileRequest( void );
|
||||
|
||||
UGCFileRequestStatus_t StartDownload( UGCHandle_t hFileHandle, const char *lpszTargetDirectory = NULL, const char *lpszTargetFilename = NULL );
|
||||
UGCFileRequestStatus_t StartUpload( CUtlBuffer &buffer, const char *lpszFilename );
|
||||
UGCFileRequestStatus_t Update( void );
|
||||
UGCFileRequestStatus_t GetStatus( void ) const { return m_UGCStatus; }
|
||||
|
||||
// Accessors
|
||||
const char *GetFileName( void ) { return ( m_szTargetFilename[0] == '\0' ) ? m_szFileName : m_szTargetFilename; }
|
||||
const char *GetLastError( void ) const { return m_szErrorText; }
|
||||
UGCHandle_t GetCloudHandle( void ) const { return m_hCloudID; }
|
||||
|
||||
void GetLocalFileName( char *pDest, size_t strSize );
|
||||
void GetLocalDirectory( char *pDest, size_t strSize );
|
||||
|
||||
private:
|
||||
|
||||
CCallResult<CUGCFileRequest, RemoteStorageDownloadUGCResult_t> m_callbackUGCDownload;
|
||||
void Steam_OnUGCDownload( RemoteStorageDownloadUGCResult_t *pResult, bool bError );
|
||||
|
||||
CCallResult<CUGCFileRequest, RemoteStorageFileShareResult_t> m_callbackFileShare;
|
||||
void Steam_OnFileShare( RemoteStorageFileShareResult_t *pResult, bool bError );
|
||||
|
||||
//
|
||||
// Marks the file request as complete and frees its internal buffers
|
||||
//
|
||||
|
||||
void MarkCompleteAndFree( void )
|
||||
{
|
||||
m_bufContents.Clear();
|
||||
m_UGCStatus = UGCFILEREQUEST_FINISHED;
|
||||
}
|
||||
|
||||
//
|
||||
// Sets the file request into an error state
|
||||
//
|
||||
|
||||
UGCFileRequestStatus_t ThrowError( const char *lpszDesc )
|
||||
{
|
||||
V_strncpy( m_szErrorText, lpszDesc, ARRAYSIZE(m_szErrorText) );
|
||||
Warning( "%s", m_szErrorText );
|
||||
Assert(0);
|
||||
m_UGCStatus = UGCFILEREQUEST_ERROR;
|
||||
|
||||
return m_UGCStatus;
|
||||
}
|
||||
|
||||
private:
|
||||
char m_szTargetDirectory[MAX_PATH]; // If specified, the directory the file will be placed in
|
||||
char m_szTargetFilename[MAX_PATH]; // If specified, this name overrides the UGC filename
|
||||
char m_szFileName[MAX_PATH]; // Filename of in the cloud structure
|
||||
|
||||
SteamAPICall_t m_hSteamAPICall; // Used to track Steam API calls which are non-blocking
|
||||
CUtlBuffer m_bufContents; // Contents of the file once read from the cloud
|
||||
UGCHandle_t m_hCloudID; // Cloud handle of this request
|
||||
FSAsyncControl_t m_AsyncControl; // Handle for the async requests this class can initiate
|
||||
|
||||
UGCFileRequestStatus_t m_UGCStatus; // The current status of this request
|
||||
char m_szErrorText[512]; // Holds information if an error occurred
|
||||
|
||||
#ifdef FILEREQUEST_IO_STALL
|
||||
// Debug data
|
||||
float m_flIOStallDuration; // Amount of time (in seconds) to stall all IO operations
|
||||
int m_nIOStallType; // Type of stall (0 - none, 1 - download, 2 - write )
|
||||
float m_flIOStallStart;
|
||||
#endif // FILEREQUEST_IO_STALL
|
||||
};
|
||||
|
||||
#endif //UGC_UTILS_H
|
Reference in New Issue
Block a user