Pendahuluan
Berikut ini adalah panduan lengkap untuk mengintegrasikan Statistik Steam yang paling dasar ke aplikasi dalam waktu kurang dari 10 menit dan mengintegrasikan kurang dari 10 baris kode ke kode dasarmu.
SDK Steamworks hadir dengan contoh aplikasi yang sangat bagus, yaitu
Spacewar, yang menunjukkan beragamnya pilihan fitur Steam dan seharusnya menjadi tempat pertamamu untuk melihat kerja seluruh fitur Steam. Tutorial ini merangkum informasi yang ditemukan di Spacewar dan API Statistik dan Pencapaian, sehingga hanya menyajikan informasi yang diperlukan untuk memahami cara kerja Statistik Steam. Harap diingat bahwa ada banyak tumpang tindih antara statistik dan pencapaian, sehingga jika kamu mengintegrasikan keduanya, banyak panggilan yang akan terkonsolidasi.
Langkah 1 - Mendefinisikan Statistik game-mu
Statistik bersifat khusus untuk aplikasi dan diatur di halaman
Konfigurasi Statistik di backend Admin Aplikasi Steamworks. Berikut adalah daftar statistik dari aplikasi Spacewar di Steamworks:

Langkah 2 - Mengenkapsulasi kerja Statistik
Kode berikut bisa diterapkan pada game apa pun dan bisa ditambahkan ke game-mu sesuai kebutuhan. Kelasnya berfungsi penuh tanpa harus diubah, tapi bisa diekstensi untuk memenuhi kebutuhan lebih lanjut. Semua kode ini diambil langsung dari file Spacewar
StatsAndAchievements.cpp/h
.
File Tajuk
Kita mulai dengan mendefinisikan stuktur untuk menyimpan data statistik yang kita terima dari Steam, mendefinisikan jenis statistik menggunakan penghitungan yang praktis, dan kemudian menyediakan makro untuk membuat statistik objek. Data ini memetakan langsung apa yang ditemukan di halaman
Konfigurasi Statistik.
#define _STAT_ID( id,type,name ) { id, type, name, 0, 0, 0, 0 }
enum EStatTypes
{
STAT_INT = 0,
STAT_FLOAT = 1,
STAT_AVGRATE = 2,
};
struct Stat_t
{
int m_ID;
EStatTypes m_eStatType;
const char *m_pchStatName;
int m_iValue;
float m_flValue;
float m_flAvgNumerator;
float m_flAvgDenominator;
};
Kemudian, definisikan kelas helper yang akan membungkus panggilan API Statistik Steam, dan akan membuat semua
callback Steam.
class CSteamStats
{
private:
int64 m_iAppID; // AppID kita saat ini
Stat_t *m_pStats; // Data Statistik
int m_iNumStats; // Jumlah Statistik
bool m_bInitialized; // Sudahkah kita memanggil statistik Permintaan dan menerima callback?
public:
CSteamStats(Stat_t *Stats, int NumStats);
~CSteamStats();
bool RequestStats();
bool StoreStats();
STEAM_CALLBACK( CSteamStats, OnUserStatsReceived, UserStatsReceived_t,
m_CallbackUserStatsReceived );
STEAM_CALLBACK( CSteamStats, OnUserStatsStored, UserStatsStored_t,
m_CallbackUserStatsStored );
};
File Kode
Konstruktor
Parameter - Konstruktor menyertakan penunjuk ke array statistik beserta panjang array. Format array ini tercakup dalam kode utama game di bawah ini.
Hasil - N/A
Fungsi - Konstruktor menginisialisasi sejumlah anggota sambil mengambil AppID yang sedang kita gunakan. Metode callback juga disertakan untuk memproses panggilan asinkron ke Steam. Terakhir, panggilan awal ke
RequestStats()
dilakukan untuk mengambil statistik dan pencapaian pengguna saat ini.
CSteamStats::CSteamStats(Stat_t *Stats, int NumStats) :
m_iAppID( 0 ),
m_bInitialized( false ),
m_CallbackUserStatsReceived( this, &CSteamStats::OnUserStatsReceived ),
m_CallbackUserStatsStored( this, &CSteamStats::OnUserStatsStored )
{
m_iAppID = SteamUtils()->GetAppID();
m_pStats = Stats;
m_iNumStats = NumStats;
RequestStats();
}
RequestStats()
Parameter - Tidak ada
Hasil - nilai boolean menunjukkan apakah panggilan berhasil atau gagal. Jika panggilan gagal, maka kemungkinan besar Steam tidak diinisialisasi. Pastikan Steam Client terbuka ketika melakukan panggilan ini dan bahwa
SteamAPI_Init telah dipanggil sebelumnya.
Fungsi - Metode ini pada dasarnya membungkus panggilan
ISteamUserStats::RequestCurrentStats yang merupakan panggilan asinkron ke Steam untuk meminta statistik dari pemain saat ini. Panggilan ini harus dibuat sebelum kamu mengatur statistik dan pencapaian. Panggilan awal untuk metode ini dibuat di konstruktor. Kamu bisa memanggilnya lagi kapan pun setelahnya jika kamu ingin melihat pembaruan statistik atau pencapaian.
bool CSteamStats::RequestStats()
{
// Apakah Steam dimuat? Kita tidak bisa mendapatkan statistik jika tidak.
if ( NULL == SteamUserStats() || NULL == SteamUser() )
{
return false;
}
// Apakah pengguna login? Kita tidak bisa mendapatkan statistik jika tidak.
if ( !SteamUser()->BLoggedOn() )
{
return false;
}
// Meminta statistik pengguna.
return SteamUserStats()->RequestCurrentStats();
}
StoreStats()
Parameter - Tidak ada
Hasil - nilai boolean menunjukkan apakah panggilan berhasil atau gagal. Jika panggilan gagal, maka kemungkinan besar Steam tidak diinisialisasi. Pastikan Steam Client terbuka ketika melakukan panggilan ini dan bahwa
SteamAPI_Init telah dipanggil sebelumnya.
Fungsi - Metode ini pada dasarnya membungkus panggilan
ISteamUserStats::StoreStats yang merupakan panggilan asinkron ke Steam untuk menyimpan statistik dari pemain saat ini di server. Panggilan ini perlu dilakukan kapan saja kamu ingin memperbarui statistik pengguna.
bool CSteamStats::StoreStats()
{
if ( m_bInitialized )
{
// muat statistik
for ( int iStat = 0; iStat < m_NumStats; ++iStat )
{
Stat_t &stat = m_pStats[iStat];
switch (stat.m_eStatType)
{
case STAT_INT:
SteamUserStats()->SetStat( stat.m_pchStatName, stat.m_iValue );
break;
case STAT_FLOAT:
SteamUserStats()->SetStat( stat.m_pchStatName, stat.m_flValue );
break;
case STAT_AVGRATE:
SteamUserStats()->UpdateAvgRateStat(stat.m_pchStatName, stat.m_flAvgNumerator, stat.m_flAvgDenominator );
// Hasil rata-ratanya sudah dihitung
SteamUserStats()->GetStat(stat.m_pchStatName, &stat.m_flValue );
break;
default:
break;
}
}
return SteamUserStats()->StoreStats();
}
}
OnUserStatsReceived()
Parameter - N/A
Hasil - Tidak ada
Fungsi - Metode ini adalah callback yang dipanggil kapan saja kamu mencoba meminta statistik. Statistik diminta menggunakan
RequestStats()
. Metode ini memperbarui variabel anggota m_Stats untuk mencerminkan data statistik yang paling terkini yang didapatkan dari Steam.
void CSteamStats::OnUserStatsReceived( UserStatsReceived_t *pCallback )
{
// kita mungkin akan mendapatkan callback untuk statistik game lain yang datang, abaikanlah
if ( m_iAppID == pCallback->m_nGameID )
{
if ( k_EResultOK == pCallback->m_eResult )
{
OutputDebugString( "Received stats and achievements from Steam\n" );
// muat statistik
for ( int iStat = 0; iStat < m_iNumStats; ++iStat )
{
Stat_t &stat = m_Stats[iStat];
switch (stat.m_eStatType)
{
case STAT_INT:
SteamUserStats()->GetStat(stat.m_pchStatName, &stat.m_iValue);
break;
case STAT_FLOAT:
case STAT_AVGRATE:
SteamUserStats()->GetStat(stat.m_pchStatName, &stat.m_flValue);
break;
default:
break;
}
}
m_bInitialized = true;
}
else
{
char buffer[128];
_snprintf( buffer, 128, "RequestStats - failed, %d\n", pCallback->m_eResult );
OutputDebugString( buffer );
}
}
}
OnUserStatsStored()
Parameter - N/A
Hasil - Tidak ada
Fungsi - Metode ini adalah callback yang dipanggil kapan saja kamu mencoba untuk menyimpan statistik di Steam. Jika statistik yang telah ditetapkan melanggar batasan, statistik tersebut akan dikembalikan ke nilai lamanya agar nilainya dapat dimulai ulang.
void CSteamStats::OnUserStatsStored( UserStatsStored_t *pCallback )
{
// kita mungkin akan mendapatkan callback untuk statistik game lain yang datang, abaikanlah
if ( m_iAppID == pCallback->m_nGameID )
{
if ( k_EResultOK == pCallback->m_eResult )
{
OutputDebugString( "StoreStats - success\n" );
}
else if ( k_EResultInvalidParam == pCallback->m_eResult )
{
// Satu atau lebih statistik melanggar batasan yang ditetapkan. Aturan telah dikembalikan,
// sekarang, kita harus mengulangi nilai untuk menyinkronkan.
OutputDebugString( "StoreStats - some failed to validate\n" );
// Buat callback palsu sehingga nilai dapat dimulai ulang.
UserStatsReceived_t callback;
callback.m_eResult = k_EResultOK;
callback.m_nGameID = m_iAppID;
OnUserStatsReceived( &callback );
}
else
{
char buffer[128];
_snprintf( buffer, 128, "StoreStats - failed, %d\n", pCallback->m_eResult );
OutputDebugString( buffer );
}
}
}
Langkah 3 - Mengintegrasikan ke game-mu
Berikut adalah daftar lengkap cuplikan kode yang harus kamu integrasikan ke game-mu di lokasi yang sesuai.
Definisi dan Global
Berikut ini adalah daftar pernyataan penyertaan yang dibutuhkan untuk membuat Statistik, penghitungan dari statistik khusus game kita, dan penunjuk global ke objek helper kita. Pastikan bahwa statistiknya sesuai dengan yang ada di halaman Admin di Steamworks.
...
#include "steam_api.h"
#include "isteamuserstats.h"
#include "SteamStats.h"
// Array statistik menyimpan data tentang statistik dan statusnya
Stat_t g_Stats[] =
{
_STAT_ID( 1, STAT_INT, "NumGames"),
_STAT_ID( 2, STAT_INT, "NumWins"),
_STAT_ID( 3, STAT_INT, "NumLosses"),
_STAT_ID( 4, STAT_FLOAT, "FeetTraveled"),
_STAT_ID( 5, STAT_AVGRATE, "AverageSpeed"),
_STAT_ID( 7, STAT_FLOAT, "MaxFeetTraveled"),
};
// Akses global ke Objek Statistik
CSteamStats* g_SteamStats = NULL;
...
Inisialisasi
Panggilan ke
SteamAPI_Init menginisialisasi keseluruhan Steam dan harus dipanggil sebelum yang lainnya. Jika panggilannya berhasil, buat objek helper dengan meneruskan array statistik dan ukuran array.
...
// Menginisialisasi Steam
bool bRet = SteamAPI_Init();
// Buat objek Pencapaian Steam jika Steam berhasil diinisialisasi
if (bRet)
{
g_SteamAchievements = new CSteamAchievements(g_Achievements, 4);
}
...
Memproses Callback
Untuk memastikan bahwa kita sudah memproses semua callback Steam, kita harus mengirimkan pesan baru secara teratur. Ini dicapai dengan menambahkan panggilan ini ke loop game.
...
SteamAPI_RunCallbacks();
...
Menyimpan Statistik
Statistik disimpan dengan melakukan satu panggilan ke
StoreStats()
.
...
if (g_SteamStats)
g_SteamStats->StoreStats();
...
Mematikan
Panggilan ke
SteamAPI_Shutdown adalah sesuatu yang mungkin sudah ada di kodemu. Ini akan menutup Steam dan harus dipanggil sebelum aplikasimu tertutup. Terakhir, hapus objek helper yang kita buat.
...
// Matikan Steam
SteamAPI_Shutdown();
// Hapus objek SteamStats
if (g_SteamStats)
delete g_SteamStats;
...
Langkah 4 - Pengujian dan Troubleshoot
Kode contoh ini mengeluarkan informasi debug ke konsol debug yang dapat membantumu mengidentifikasi panggilan mana yang berhasil dan gagal. Berikut ini adalah beberapa pesan kegagalan umum dan perbaikannya:
Aplikasi ini gagal dijalankan karena steam_api.dll tidak ditemukan. Menginstal ulang aplikasi dapat memperbaiki masalah ini.Pastikan steam_api.dll berada di direktori yang sama dengan executable.
[S_API FAIL] SteamAPI_Init() failed; tidak dapat menemukan Steam yang sedang dijalankan, atau steamclient.dll lokalKemungkinan besar tidak ada Steam Client yang sedang dijalankan. Buka Steam dan login.
[S_API FAIL] SteamAPI_Init() failed; tidak menemukan AppID.Kemungkinan besar file steam_appid.txt tidak ada. Tempatkan file di folder source dan pastikan file tersebut berisi AppID aplikasimu.