Skip to content

Leaderboards

Francisco Dias edited this page Dec 12, 2024 · 19 revisions

Leaderboards

The Steam API supports persistent leaderboards with automatically ordered entries. These leaderboards can be used to display global and friend leaderboards in your game and on the community web page for your game. Each game can have up to 10,000 leaderboards, and each leaderboard can be retrieved immediately after a player's score has been inserted into it, but note that for each leaderboard, a player can have only one entry, although there is no limit on the number of players per leaderboard.

Functions

Each leaderboard entry contains a name, a score and a rank for the leaderboard, and this data will be replaced when a new leaderboard entry is created for the user, and the following functions can be used to add and retrieve this data form the leaderboards for your game:

Structs

The following data types are used by the leaderboard functions:

Constants

The following constants are used by the leaderboard functions:



Back To Top

steam_create_leaderboard

With this function you can create a new leaderboard for your game. The first argument is a string which defines the name of your leaderboard, and this name should be used in any further function calls relating to the leaderboard being created. You can then define the sort order (see LeaderboardSortOrder constants) as well as the way in which the information is displayed (see LeaderboardDisplayType constants).

Note

If you have previously created a leaderboard with the same name (either through code or through your Steam page for the game), then this function will not create a new one.

This function operates asynchronously, which means that it does not immediately return the requested result. Instead, upon completion of the task, it will trigger the Steam Async Event.


Syntax:

steam_create_leaderboard(lb_name, sort_order, display_type)
Argument Type Description
lb_name String The name of the leaderboard that you are creating
sort_order LeaderboardSortOrder The method for sorting the leaderboard entries
display_type LeaderboardDisplayType The way to display the leaderboard to the user



Returns:

Real


Triggers:

Steam Async Event

Key Type Description
id Real The asynchronous request ID
event_type String The string value "create_leaderboard"
status Real The status code, 0 if the leaderboard was created and 1 if it already existed
lb_name String The name of the leaderboard

Example:

steam_create_leaderboard("Game Times", lb_sort_ascending, lb_disp_time_sec);

The above code will create a leaderboard called "Game Times", and set it to display the results in ascending order and with a display in seconds.




Back To Top

steam_upload_score

This function will send a score to the given leaderboard. The score to be uploaded is a real number, and the leaderboard name is a string that was defined when you created the leaderboard using the function steam_create_leaderboard.

Note

If the function call fails for any reason it will return -1 and the Async event will not be triggered.

This function operates asynchronously, which means that it does not immediately return the requested result. Instead, upon completion of the task, it will trigger the Steam Async Event.


Syntax:

steam_upload_score(lb_name, score)
Argument Type Description
lb_name String The name of the leaderboard that you are uploading the scores to
score Real The score to upload



Returns:

Real


Triggers:

Steam Async Event

Key Type Description
post_id Real The asynchronous request ID
event_type String The string value "leaderboard_upload"
lb_name String The name of the leaderboard
num_entries Real The number of returned entries
success Boolean Whether or not the request was successful
updated Boolean Whether or not the leaderboard was updated (i.e.: the new score was better)
score Real The score that was posted to the leaderboard

Example:

In this example, we first upload a score and then parse the async_load map returned if successful. The code below shows a typical example for uploading:

if (hp <= 0)
{
    upload_ID = steam_upload_score("Game Scores", score);
    if (!upload_ID)
    {
        alarm[0] = game_get_speed(gamespeed_fps);
    }
}

Note that we have set an alarm if the call fails. This would be used to try the upload again at a later time and you can add extra code there to retry the upload or to save the score to a text file should it continue to fail, etc. We now add the following into the Steam Async Event for the instance controlling the scores:

var _type = ds_map_find_value(async_load, "event_type");
if (_type == "leaderboard_upload")
{
    var _lb_ID = ds_map_find_value(async_load, "post_id");
    if _lb_ID == upload_ID
    {
        var _lb_name = ds_map_find_value(async_load, "lb_name");
        var _lb_done = ds_map_find_value(async_load, "success");
        var _lb_score = ds_map_find_value(async_load, "score");
        var _lb_updated = ds_map_find_value(async_load, "updated");
        show_debug_message("leaderboard post ID:" + string(_lb_ID) + " to lb:" + string(_lb_name) + " with score:" + string(_lb_score) + " updated=" + string(_lb_updated));
        if (_lb_done)
        {
            show_debug_message("- Succeeded");
        }
        else
        {
            show_debug_message("- Failed");
        }
    }
}

In the example we are simply outputting the return values to the compiler window as debug messages, but you can use this event to deal with the information in any way you choose.




Back To Top

steam_upload_score_ext

This function will send a score to the given leaderboard. It is similar to the function steam_upload_score but has an extra argument that will allow you to force the update of the score, as by default Steam only updates the score if it is better than the previous one.

Note

If the function call fails for any reason it will return -1 and the Async event will not be triggered.

This function operates asynchronously, which means that it does not immediately return the requested result. Instead, upon completion of the task, it will trigger the Steam Async Event.


Syntax:

steam_upload_score_ext(lb_name, score, force_update)
Argument Type Description
lb_name String The name of the leaderboard that you are uploading the scores to
score Real The score to upload
force_update Boolean Whether or not the value should be replaced



Returns:

Real


Triggers:

Steam Async Event

Key Type Description
post_id Real The asynchronous request ID
event_type String The string value "leaderboard_upload"
lb_name String The name of the leaderboard
num_entries Real The number of returned entries
success Boolean Whether or not the request was successful
updated Boolean Whether or not the leaderboard was updated (i.e.: the new score was better or forceUpdate was set to true)
score Real The score that was posted to the leaderboard

Example:

In this example, we first upload a score and then parse the async_load map returned if successful. The code below shows a typical example for uploading:

if (hp <= 0)
{
    upload_ID = steam_upload_score_ext("Game Scores", score, true);
    if (!upload_ID)
    {
        alarm[0] = game_get_speed(gamespeed_fps);
    }
}

Note that we have set an alarm if the call fails. This would be used to try the upload again at a later time and you can add extra code there to retry the upload or to save the score to a text file should it continue to fail, etc. We now add the following into the Steam Async Event for the instance controlling the scores:

var _type = ds_map_find_value(async_load, "event_type");
if (_type == "leaderboard_upload")
{
    var _lb_ID = ds_map_find_value(async_load, "post_id");
    if _lb_ID == upload_ID
    {
        var _lb_name = ds_map_find_value(async_load, "lb_name");
        var _lb_done = ds_map_find_value(async_load, "success");
        var _lb_score = ds_map_find_value(async_load, "score");
        var _lb_updated = ds_map_find_value(async_load, "updated");
        show_debug_message("leaderboard post id:" + string(_lb_ID) + " to lb:" + string(_lb_name) + " with score:" + string(_lb_score) + " updated=" + string(_lb_updated));
        if (_lb_done)
        {
            show_debug_message("- Succeeded");
        }
        else
        {
            show_debug_message("- Failed");
        }
    }
}

In the example we are simply outputting the return values to the compiler window as debug messages, but you can use this event to deal with the information in any way you choose.




Back To Top

steam_upload_score_buffer

This function will send a score to the given leaderboard along with a data package created from a buffer. The buffer should be no more than 256 bytes in size - anything beyond that will be chopped off - and can contain any data you require. The score to be uploaded should be a real number, and the leaderboard name is a string that was defined when you created the leaderboard using the function steam_create_leaderboard.

Note

If the function call fails for any reason it will return -1 and the Async event will not be triggered.

This function operates asynchronously, which means that it does not immediately return the requested result. Instead, upon completion of the task, it will trigger the Steam Async Event.


Syntax:

steam_upload_score_buffer(lb_name, score, buffer)
Argument Type Description
lb_name String The name of the leaderboard that you are uploading the scores to
score Real The score to upload
buffer Buffer The ID of the buffer to attach



Returns:

Real


Triggers:

Steam Async Event

Key Type Description
post_id Real The asynchronous request ID
event_type String The string value "leaderboard_upload"
lb_name String The name of the leaderboard
num_entries Real The number of returned entries
success Boolean Whether or not the request was successful
updated Boolean Whether or not the leaderboard was updated (i.e.: the new score was better). Note that if you score was not updated neither will the data buffer.
score Real The score that was posted to the leaderboard

Example:

In this example, we first upload a score and then parse the async_load map returned if successful. The code below shows a typical example for uploading, with a buffer being created to hold a string telling us which level the score was uploaded from:

if (hp <= 0)
{
    var _buff = buffer_create(256, buffer_fixed, 1);
    buffer_write(_buff, buffer_string, "Uploaded on level " + string(global.Level));
    upload_ID = steam_upload_score("Game Scores", score, _buff);

    if (!upload_ID)
    {
        alarm[0] = game_get_speed(gamespeed_fps);
    }

    buffer_delete(_buff);
}

Note that we have set an alarm if the call fails. This would be used to try the upload again at a later time and you can add extra code there to retry the upload or to save the score to a text file should it continue to fail, etc. Also note that we immediately delete the buffer, since it is no longer required for the function. We now add the following into the Steam Async Event for the instance controlling the scores:

var _type = ds_map_find_value(async_load, "event_type");
if (_type == "leaderboard_upload")
{
    var _lb_ID = ds_map_find_value(async_load, "post_id");
    if _lb_ID == upload_ID
    {
        var _lb_name = ds_map_find_value(async_load, "lb_name");
        var _lb_done = ds_map_find_value(async_load, "success");
        var _lb_score = ds_map_find_value(async_load, "score");
        var _lb_updated = ds_map_find_value(async_load, "updated");
        show_debug_message("leaderboard post ID:" + string(_lb_ID) + " to lb:" + string(_lb_name) + " with score:" + string(_lb_score) + " updated=" + string(_lb_updated));
        if (_lb_done)
        {
            show_debug_message("- Succeeded");
        }
        else
        {
            show_debug_message("- Failed");
        }
    }
}

In the example we are simply outputting the return values to the compiler window as debug messages, but you can use this event to deal with the information in any way you choose.




Back To Top

steam_upload_score_buffer_ext

This function will send a score to the given leaderboard along with a data package created from a buffer. The buffer should be no more than 256 bytes in size - anything beyond that will be chopped off - and can contain any data you require. This function is similar to steam_upload_score_buffer but has an extra argument that will allow you to force the update of the score, as by default Steam only updates the score if it is better than the previous one.

Note

If the function call fails for any reason it will return -1 and the Async event will not be triggered.

This function operates asynchronously, which means that it does not immediately return the requested result. Instead, upon completion of the task, it will trigger the Steam Async Event.


Syntax:

steam_upload_score_buffer_ext(lb_name, score, buffer, force_update)
Argument Type Description
lb_name String The name of the leaderboard that you are uploading the scores to
score Real The score to upload
buffer Buffer The ID of the buffer to attach
force_update Boolean Whether or not the value should be replaced



Returns:

Real


Triggers:

Steam Async Event

Key Type Description
post_id Real The asynchronous request ID
event_type String The string value "leaderboard_upload"
lb_name String The name of the leaderboard
num_entries Real The number of returned entries
success Boolean Whether or not the request was successful
updated Boolean Whether or not the leaderboard was updated (i.e.: the new score was better or forceUpdate was set to true). Note that if you score was not updated neither will be the data buffer.
score Real The score that was posted to the leaderboard

Example:

In this example, we first upload a score and then parse the async_load map returned if successful. The code below shows a typical example for uploading, with a buffer being created to hold a string telling us which level the score was uploaded from:

if (hp <= 0)
{
    var _buff = buffer_create(256, buffer_fixed, 1 );
    buffer_write(_buff, buffer_string, "Uploaded on level " + string(global.Level));
    upload_ID = steam_upload_score_buffer_ext("Game Scores", score, _buff, true);

    if (!upload_ID)
    {
        alarm[0] = game_get_speed(gamespeed_fps);
    }

    buffer_delete(_buff);
}

Note that we have set an alarm if the call fails. This would be used to try the upload again at a later time and you can add extra code there to retry the upload or to save the score to a text file should it continue to fail, etc. Also note that we immediately delete the buffer, since it is no longer required for the function. We now add the following into the Steam Async Event for the instance controlling the scores:

var _type = ds_map_find_value(async_load, "event_type");
if (_type == "leaderboard_upload")
{
    var _lb_ID = ds_map_find_value(async_load, "post_id");
    if _lb_ID == upload_ID
    {
        var _lb_name = ds_map_find_value(async_load, "lb_name");
        var _lb_done = ds_map_find_value(async_load, "success");
        var _lb_score = ds_map_find_value(async_load, "score");
        var _lb_updated = ds_map_find_value(async_load, "updated");
        show_debug_message("leaderboard post ID:" + string(_lb_ID) + " to lb:" + string(_lb_name) + " with score:" + string(_lb_score) + " updated=" + string(_lb_updated));
        if (_lb_done)
        {
            show_debug_message("- Succeeded");
        }
        else
        {
            show_debug_message("- Failed");
        }
    }
}

In the example we are simply outputting the return values to the compiler window as debug messages, but you can use this event to deal with the information in any way you choose.




Back To Top

steam_download_scores

This function is used to retrieve a sequential range of leaderboard entries by leaderboard ranking. The start_idx and end_idx parameters control the requested range of ranks, for example, you can display the top 10 on a leaderboard for your game by setting the start value to 1 and the end value to 10. The leaderboard name is a string that was defined when you created the leaderboard using the function steam_create_leaderboard.

Note

If the function call fails for any reason it will return -1 and the async event will not be triggered.

This function operates asynchronously, which means that it does not immediately return the requested result. Instead, upon completion of the task, it will trigger the Steam Async Event.


Syntax:

steam_download_scores(lb_name, start_idx, end_idx)
Argument Type Description
lb_name String The name of the leaderboard that you are downloading the scores from
start_idx Real The start position within the leaderboard
end_idx Real The end position within the leaderboard



Returns:

Real


Triggers:

Steam Async Event

Key Type Description
id Real The asynchronous request ID
event_type String The string value "leaderboard_download"
status Boolean The status code if download fails
lb_name String The name of the leaderboard
num_entries Real The number of entries returned
entries String A JSON-formatted string with all the downloaded entries (see LeaderboardEntry for details)

Example:

In this extended example we will request the top ten ranking entries for the given leaderboard and parse its results in the Steam Async Event. To start with we need to request the scores with the following code:

/// Create Event
leaderboard = [];

scores_request_id = steam_download_scores("Game Scores", 1, 10);

This code initialises an array variable in leaderboard and then sends off a request to the Steam Server to download the scores from the leaderboard named "Game Scores". The function returns the async ID of the request, which is stored in an instance variable scores_request_id. This will then be handled in the Steam Async Event in the following way:

/// Async Steam Event
var _async_id = ds_map_find_value(async_load, "id");
if (_async_id != scores_request_id)
{
    // This isn't a response to our request, ignore it.
    exit;
}

if (async_load[? "status"] == 0)
{
    // This is a response to the request we made, but something seems to have gone wrong.
    // Handle this, then exit the event.
    exit;
}

// Get the entries
var _entries_json = ds_map_find_value(async_load, "entries");
var _entries = json_parse(_entries_json);
leaderboard = _entries.entries;

// Get any custom data if it's present and assign to a struct variable named "message"
var _data_base64, _buffer, _message;
array_foreach(leaderboard, function(_element, _index)
{
    _element.message = "";
    if (struct_exists(_element, "data"))
    {
        _data_base64 = _element.data;
        _buffer = buffer_base64_decode(_data_base64);
        _element.message = buffer_read(_buffer, buffer_string);
        buffer_delete(_buffer);
    }
});

First we check the "id" key of the async_load DSMap. If this value is the same as the value returned by the original call to the function (stored in the scores_request_id variable) we continue to process the data. After checking the async ID, we can be sure that the async event is of the right "event_type", so a check on that isn't strictly necessary here. The request status is checked next by checking async_load's "status" key. If anything went wrong, it can be handled and we exit the event. The first thing we do after the above checks is get the value of the async_load map's "entries" key which will contain a JSON-formatted string containing the leaderboard data. This JSON object is then parsed using json_parse and the returned struct stored in a local variable _entries. The actual leaderboard data is in an array under the struct's entries variable, which can be directly assigned to the instance's leaderboard variable. In an optional next step we check every item using array_foreach for the presence of a "data" key. If this key exists, the data is decoded into a Buffer and the contents read as a String. The message is then assigned as an additional variable "message" to the current score struct to avoid reading from the buffer again when drawing this info in a Draw event.

/// Draw GUI Event
array_foreach(leaderboard, function(_element, _index)
{
    var _msg = (_element.message == "") ? "No Message" : _element.message;
    draw_text(5, 5 + _index * 20, $"{_element.rank}. {_element.score} ({_element.user}) - (_msg)");
});

The code above draws the leaderboard in the Draw GUI event. If the message turns out to be an empty string for whatever reason, the text "No Message" is shown instead.




Back To Top

steam_download_scores_around_user

This function is used to retrieve leaderboard entries relative to the current user's entry. The range_start parameter is the number of entries to retrieve before the current user's entry, and the range_end parameter is the number of entries after the current user's entry, and the current user's entry is always included in the results. For example, if the current user is number 5 on a given leaderboard, then setting the start range to -2 and the end range to 2 will return 5 entries: 3 through 7. If there are not enough entries in the leaderboard before or after the user's entry, Steam will adjust the range start and end points trying to maintained the range size. For example, if the user is #1 on the leaderboard, start is set to -2, and end is set to 2, Steam will return the first 5 entries in the leaderboard.

Note

If the function call fails for any reason it will return -1 and the async event will not be triggered.

This function operates asynchronously, which means that it does not immediately return the requested result. Instead, upon completion of the task, it will trigger the Steam Async Event.


Syntax:

steam_download_scores_around_user(lb_name, range_start, range_end)
Argument Type Description
lb_name String The name of the leaderboard that you are downloading the scores from
range_start Real The start position within the leaderboard
range_end Real The end position within the leaderboard



Returns:

Real


Triggers:

Steam Async Event

Key Type Description
id Real The asynchronous request ID
event_type String The string value "leaderboard_download"
status Boolean The status code if download fails
lb_name String The name of the leaderboard
num_entries Real The number of entries returned
entries String A JSON-formatted string with all the downloaded entries (see LeaderboardEntry for details)

Example:

request_id = steam_download_scores_around_user("Game Scores", -4, 5);

This will send off a request to the Steam Server for a range of 10 scores from the leaderboard "Game Scores", centered on the player and will store the async ID of the request in the variable request_id. This will then be handled in the Steam Async Event, as shown in the example for steam_download_scores.




Back To Top

steam_download_friends_scores

With this function you can retrieve only the scores on the leaderboard that belong to those people that are marked as "friends" in the Steam client. So, if your leaderboard has 200 entries, and 50 of them are your friends, this function will retrieve only those 50 results. The leaderboard name is a string that was defined when you created the leaderboard using the function steam_create_leaderboard.

Note

If the function call fails for any reason it will return -1 and the async event will not be triggered.

This function operates asynchronously, which means that it does not immediately return the requested result. Instead, upon completion of the task, it will trigger the Steam Async Event.


Syntax:

steam_download_friends_scores(lb_name)
Argument Type Description
lb_name String The name of the leaderboard that you are downloading the scores from



Returns:

Real


Triggers:

Steam Async Event

Key Type Description
id Real The asynchronous request ID
event_type String The string value "leaderboard_download"
status Int64 The status code if download fails
lb_name String The name of the leaderboard
num_entries Real The number of returned entries
entries String A JSON formatted string with all the downloaded entries (see LeaderboardEntry for details)

Example:

request_id = steam_download_friends_scores("Game Scores");

This will send off a request to the Steam Server for the users friends scores from the given leaderboard and will store the async ID of the request in the variable request_id. This will then be handled in the Steam Async Event, as shown in the example for steam_download_scores.




Back To Top

steam_get_leaderboard_entry_count

This function returns the total number of entries in a leaderboard.

The function returns -1 in case something went wrong.


Syntax:

steam_get_leaderboard_entry_count(lb_name)
Argument Type Description
lb_name String The name of the leaderboard.



Returns:

Real




Back To Top

steam_get_leaderboard_display_type

This function returns the display type of a leaderboard handle.

The function returns -1 in case something went wrong.


Syntax:

steam_get_leaderboard_display_type(lb_name)
Argument Type Description
lb_name String The name of the leaderboard.



Returns:

LeaderboardDisplayType




Back To Top

LeaderboardDisplayType

These constants specify the display type of a leaderboard.

These constants are referenced by the following functions:


Member Description
lb_disp_none Show the leaderboard "as is".
lb_disp_numeric Show the leaderboard as a numeric display.
lb_disp_time_sec Show the leaderboard values as times, with the base value being seconds.
lb_disp_time_ms Show the leaderboard values as times, with the base value being milliseconds


Back To Top

LeaderboardSortOrder

These constants specify the sort order of a leaderboard.

These constants are referenced by the following functions:


Member Description
lb_sort_none No sorting. The information will be displayed "as is".
lb_sort_ascending Sort the leaderboard in ascending order.
lb_sort_descending Sort the leaderboard in descending order.


Back To Top

LeaderboardEntry

A leaderboard entry is represented by a JSON formatted string that can be returned by the async callback event of a couple of functions.

This string can be decoded into a DSMap (see json_decode, needs to be destroyed afterwards) or into a Struct (see json_parse, recommended) and will provide the following members.


Member Type Description
rank Real The rank of the entry on the specified leaderboard
data String The base64 encoded string with the data provided when uploading scores using the steam_upload_score_buffer or steam_upload_score_buffer_ext functions ✴️ OPTIONAL
score Real The score attributed to this entry
name String The display name of the player for this entry
userID Int64 The unique user ID of the player for this entry

> [!NOTE]
>
> If steam_upload_score_buffer or steam_upload_score_buffer_ext were used to upload the score, the decoded entry will now have a "data" key so you can retrieve the data of the uploaded buffer (see the steam_download_scores extended code example for further details). This data will be base64-encoded and so you will need to use the function buffer_base64_decode on the data before reading from the buffer.