This is a function "cheat sheet" for Steamworks.gml extension by YellowAfterlife.
The extension is available on GitHub.
Example files are available via
Donations are accepted via
A most up-to-date version of the manual is always available online.

Click on sections to expand/collapse them.
Quick display controls: Categories · Sections · Everything ·

Setting up Steam

See the official documentation.

Additional note: you can use the test application ID (480) prior to being granted your own application ID, but generally it shouldn't be used for public builds.

Testing games with Steam networking

There are a few things to note about how Steam API works:

  • If multiple instances of the same game are ran at once, Steam does not tell them apart, and will send events to whichever happens to ask for them first.

    Steam client will generally try to prevent you from opening multiples of the same game, but it's possible when running from editor.

  • Steam API uses user IDs as endpoints for connections, meaning that you cannot expect reliable results if trying to send something to yourself.

That said, if you want to test two or more game instances on the same computer, you need to run them through multiple instances of Steam tied to multiple accounts.

Being a single-instance application, Steam will generally not let you open multiple copies of it at once, but that is easily fixed - by using software like Sandboxie (or equivalent), you can run multiple instances of Steam with separate accounts and game libraries (if needed).

To make the process even more straightforward, you can also run multiple game instances straight from the editor. To do so, you would add a small script to return the combined parameter string for the program,

/// parameter_string_all()
var r = "";
var n = parameter_count();
for (var i = 0; i < n; i++) {
    if (i > 0) r += " ";
    var s = parameter_string(i);
    if (string_pos(" ", s)) {
        r += '"' + s + '"';
    } else r += s;
return r;

and then copy that string to clipboard,


on game start (or when other debug condition is met).

Then you would be able to use the copied parameter string to start up additional copies of the game in sandboxed environment(s).

Brief summary on Steam networking

There is a number of things to note about Steam networking compared to regular:

  • System is P2P; user IDs are used as endpoints instead of IP+port.

    If you need to port existing code utilizing IP+port combinations, you can use bit math to assume lower 32 bits to be the IP and higher 32 bits to be the port, for example.

  • Steam handles sending/receiving and async events by itself, queuing the results.

    This means that you generally should call the extension's update-function (steam_net_update) every step while in lobby and at least once per second while not in lobby, or you may later deal with an avalanche of (outdated) events once finally calling it again.

    This schema also introduces an interesting thing where if your game crashed without handling the remaining events/packets, you may receive them after restarting the game.

  • Steam handles port forwarding by itself, meaning that it'll generally find any open port if there is one, and use a wide variety of workarounds to connect when there isn't one.

    In worst case scenario Steam reverts to tunneling (using a Steam server as an intermediate node for connection), but this usually results in fairly high latency.

  • Related to above, it may take up to 10 seconds to establish connection.

    Afterwards, the connection is kept active for as long as anything is sent at least once every 30 seconds or so.

Notes on structs

Some of the extension's functions take and/or return structures.

When using GameMaker Studio 2.3 with steam_gml_use_structs enabled, these will be represented with GML structs.

Otherwise, they will be represented with arrays where fields are written sequentially.

General functions

Returns whether the native extension loaded at all.


Returns whether the native extension had been loaded and initialized.

NB! in GMS2.3, "global" code in scripts runs before extension init does.


Returns whether the native extension is loaded correctly and has it's version matching the one that the game had been built with.

Can be used to timely inform the player that their copy might be broken instead of having them wonder why things are not working.

if (!steam_gml_check_version()) {
    show_message("oh no");

Polls Steam API and dispatches any new events since the last call to the function.

As outlined above, you generally want to call this function every now and then.


Located in: steam_id.gml

Default: true

Indicates whether the extension should use 64-bit integers for Steam IDs.

If disabled, the extension will instead represent IDs as two-element array with higher/lower 32-bit halves.

Exists only for backwards compatibility and will be removed at some point.


Located in: steam_core.gml

Default: true

Indicates whether the extension should use GMS2.3 structs (as opposed to arrays) to represent multi-value arguments and return types in some cases.

Can be disabled to avoid changing code when migrating from GMS2.2 to GMS2.3+.

Async events

As result of a number of function calls, the extension dispatches asynchronous events.

All of these events have async_load[?"success"] indicating whether the async action succeeded (true or false) and async_load[?"result"] containing the status code (descriptions can be found in Steam API documentation);

These can be caught by adding a Async - Steam event, and checking whether async_load[?"event_type"] is one of following names (as strings):


Triggers after requesting a list of public lobbies via steam_lobby_list_request.

It is not required to do anything in response to this event.

async_load[?"lobby_count"] contains the number of matching lobbies (0 in case of network failure).

Use matchmaking functions to retrieve other information.


Triggers after requesting to join a lobby. This can fail if:

  • There's no connection to Steam
  • Lobby is full (no available player slots left)
  • Lobby was destroyed before you requested to join it

When successful, this is a good place to establish connection to lobby's members.


Fires after requesting to create a lobby. This can fail if:

  • There's no connection to Steam
  • You are trying to create a public lobby for a game that does not have matchmaking API enabled (is off by default for free games - request permissions via support forum).

When successful, this is a good place to set up lobby data.


Triggers when the local player accepts an invitation via Steam overlay.

This event has several fields:

  • async_load[?"lobby_id_high"], async_load[?"lobby_id_low"] (combine via steam_id_create) indicate the ID of the lobby to join (via steam_lobby_join_id).
  • async_load[?"friend_id_high"], async_load[?"friend_id_low"] (combine via steam_id_create) indicate the ID of the user that the invitation was from (in case you want to display "joining X's lobby" while loading).

Is commonly used as following:

if (async_load[?"event_type"] == "lobby_join_requested") {

If you have opted to handle P2P sessions yourself (by calling steam_net_set_auto_accept_p2p_sessions(false)), you will want to handle this event for anyone to be able to connect to you.

if (async_load[?"event_type"] == "lobby_join_requested") {
Networking functions
Packet I/O

Attempts to get the next packet from Steam API and returns whether successfully done so.

Other steam_net_ functions can then be used to get packet information/contents.

At most times you would utilize this as following:

while (steam_net_packet_receive()) {
    // process the received packet

(every step while in lobby, less frequently otherwise)


Returns Steam ID of the user that sent the last received packet.

Can be used in conjunction with steam_net_packet_send to send something back and for just telling the senders apart.


Returns the size of last received packet, in bytes.

So, for instance, if you wanted to just display the size of each incoming packet, you could use a snippet of code like the following:

while (steam_net_packet_receive()) {
    show_debug_message("Received " + string(steam_net_packet_size()) + " bytes.");

Copies the contents of last received packet to the given buffer.

Data is copied to the start of the buffer (position remains unaffected), meaning that if you reuse the same buffer, you should "rewind" it prior to reading.

If the buffer is not big enough to fit data, it will be resized automatically.

while (steam_net_packet_receive()) {
    buffer_seek(inbuf, buffer_seek_start, 0);
    switch (buffer_read(inbuf, buffer_u8)) {
        case 1: show_debug_message("packet ID 1"); break;
        case 2: show_debug_message("packet ID 2"); break;
        default: show_debug_message("unknown packet"); break;

Whether inbuf is a "fixed" or "growing" buffer created on game start for the controller object.

steam_net_packet_send(steam_id, buffer, size, type)

Sends a packet to the given endpoint, returns whether successful (as opposed to incorrect arguments/invalid ID).

Much as with the built-in network_send_ functions, this function takes data from the start of the buffer and until the point identified by size parameter.

type parameter can be one of the following:

  • steam_net_packet_type_unreliable: roughly equivalent to UDP. May or may not be delivered, will not be resent automatically.
  • steam_net_packet_type_unreliable_nodelay: much like the regular "unreliable" type, but always sent instantly (as soon as function is called). Intended for things like streaming voice data, where you want lowest latency possible and only care about the current data.
  • steam_net_packet_type_reliable: roughly equivalent to TCP. Warranted to be delivered in order and intact.
  • steam_net_packet_type_reliable_buffer: much like the regular "reliable" type, but utilizes Nagle's algorithm to reduce the number of packets at cost of potential delay while the data accumulates until the sending threshold.

So you could use it like so:

var b = buffer_create(16, buffer_grow, 1);
buffer_write(b, buffer_string, "Hello!");
steam_net_packet_send(steam_id, b, buffer_tell(b), steam_net_packet_type_reliable);

Where steam_id would hold the user ID to send the packet to.

P2P sessions

Sets whether to auto-accept session requests coming from players in the same lobby.

This is enabled by default for convenience.

If you disable it, you will need to handle p2p_session_request async event.


Accepts a P2P session request from the specified user.

Returns whether successful.


Closes a P2P session with the specified user.

Steam will automatically close sessions after a period of inactivity, but you could also do it manually if you so desired.

Returns whether successful.

Lobby functions

The following functions deal with the current lobby.


Starts joining a lobby with the given ID.

The operation is carried out asynchronously;

A lobby_joined event is dispatched on completion.

See lobby_join_requested for a code example.

steam_lobby_create(type, max_members)

Starts creating a lobby.

The operation is carried out asynchronously;

A lobby_created event is dispatched on completion.

max_members indicates the maximum allowed number of users in the lobby (including the lobby's creator).

type can be one of the following:

  • steam_lobby_type_private: Can only be joined by invitation.

    You would usually change the lobby type to this on match start.

  • steam_lobby_type_friends_only: Can be joined by invitation or via friends-list (by opening the user's menu and picking "Join game").
  • steam_lobby_type_public: Can be joined by invitation, via friends-list, and shows up in the public lobby list (see matchmaking functions).

Can be used as following:

steam_lobby_create(steam_lobby_type_public, 4);

(which would create a 4-player public lobby)


Leaves the current lobby (if any).

Does not raise any errors if currently not in a lobby.

Note that if you are the lobby owner and leave the lobby, Steam transfers lobby ownership to any other available user, so you may need to detect lobby owner changes if any particular logic is handled by them.


Changes the lobby's type. You must be the lobby's owner to do this.

Types are the same as per steam_lobby_create.

So, for example, if you don't allow mid-session joining, you could have the game make lobbies private on session start:



Returns a lobby field value, as set by steam_lobby_set_data.

var title = steam_lobby_get_data("title");
steam_lobby_set_data(key:string, value:string)

Changes a lobby's field. You must be the lobby's owner to do this.

Fields can then be used to filter lobbies via matchmaking functions.

Note: if your value is numeric, convert it to string prior to passing it to the function.

Otherwise GM will assume your numeric value to be a pointer to a string, which can hard crash your game and/or Steam client.


Returns whether the local player is the lobby's owner.

If the lobby is not valid, returns false.


Returns the lobby's owner's Steam ID.

If the lobby is not valid, returns ID 0.


If you are a lobby owner, transfers the lobby ownership to the specified player, which must be in this same lobby.

Returns whether successful.

See remarks in SetLobbyOwner


Returns the number of users in the current lobby (including you).

If the lobby is not valid, returns 0.


Returns the user ID of the member at the given index in the current lobby.

Index should be between 0 (incl.) and result of steam_lobby_get_member_count (excl.). Results will include the local user.

If the index (or lobby) is not valid, returns ID 0.


Returns the Steam ID of the current lobby.


Displays an invitation overlay if currently in a lobby.

The invitation overlay is much akin to friends-list overlay, but only shows online friends, and spots "invite" buttons on each row.

Matchmaking functions

The following functions allow retrieving lists of public lobbies.


Starts loading the list of lobbies matching the current filters.

Filters are reset afterwards and have to be set again for subsequent request(s).

Existing results are kept up until the event is dispatched.

The operation is carried out asynchronously;

A lobby_list event is dispatched on completion.


Returns whether a lobby list request is currently underway.

Is a convenience function - you may as well set a global variable prior to calling steam_lobby_list_request and reset in the lobby_list event.

Lobby list functions

These can be used after receiving a lobby_list async event.


Returns the number of lobbies received in the last lobby list request.

For subsequent functions in this section, list_index should be between 0 (incl.) and the number returned by this function (excl.)


Starts joining the lobby at the given index in the list.

See steam_lobby_join_id for more information on the process.

steam_lobby_list_get_data(list_index, key:string)​string

Returns the value of the given field of a lobby at the given index in the current list.

Fields can be set via steam_lobby_set_data.

NB! Value is always returned as a string.

Returns "" if the lobby does not have the given field set.


Returns the Steam ID of the lobby at the given index in the list.

Returns 0 if the index is out of bounds.


Returns the Steam ID of the owner of the lobby at the given index in the list.

Returns 0 if the index is out of bounds.


Returns the number of users in the lobby at the given index in the list.

Returns 0 if the index is out of bounds.


steam_lobby_list_add_string_filter(key, value, comparison_type)

Sets up a string filter for the next lobby list request.

That is, lobbies not matching the condition will be excluded from results.

Lobbies without the given field (key) will be assumed to have it as "".

The following values can be passed as comparison_type:

  • steam_lobby_list_filter_eq: Equal (==).
  • steam_lobby_list_filter_ne: Not-equal (!=).
steam_lobby_list_add_numerical_filter(key, value, comparison_type)

Sets up a numeric filter for the next lobby list request.

That is, lobbies not matching the condition will be excluded from results.

Lobbies without the given field (key) will be excluded.

The following values can be passed as comparison_type:

  • steam_lobby_list_filter_eq: Equal (==).
  • steam_lobby_list_filter_ne: Not-equal (!=).
  • steam_lobby_list_filter_lt: Less-than (<).
  • steam_lobby_list_filter_gt: Greater-than (>).
  • steam_lobby_list_filter_le: Less-than-or-equal (<=).
  • steam_lobby_list_filter_ge: Greater-than-or-equal (>=).
steam_lobby_list_add_near_filter(key, value:number)

Sorts the results based on how close their field's (key)'s value is to the provided one.

If multiple near-filters are specified, the earlier-set ones take precedence.


Restricts results by region and sorts them based on geographical proximity.

The following values can be passed as mode:

  • steam_lobby_list_distance_filter_close: Only allows lobbies in same immediate region.
  • steam_lobby_list_distance_filter_default: Allows lobbies in same or nearby regions (same continent)
  • steam_lobby_list_distance_filter_far: Allows lobbies from up to half-way around the globe (nearby continents).
  • steam_lobby_list_distance_filter_worldwide: Allows any lobbies. May result in very high latencies, so use with care.
Steam Controller/Input functions

These have been since renamed to Steam Input in SDK documentation to avoid confusion with Steam Controller device.

Controller functions

Returns an array of IDs for the connected Steam Controllers.

Such IDs are used for the rest of the functions.

Note: You can also use all (-3) in most controller functions to apply to any/all of the connected controllers.


The above function can also be called with an existing array as an argument, in which case it will store the IDs in the provided array and return how many it had filled out.


Returns Steam-reported type for the given controller.

Values can be:

  • steam_controller_unknown
  • steam_controller_steam_controller
  • steam_controller_xbox360
  • steam_controller_xboxone
  • steam_controller_generic_xinput
  • steam_controller_ps4
  • steam_controller_apple_mfi
  • steam_controller_android
  • steam_controller_switch_joycon_pair
  • steam_controller_switch_joycon_single
  • steam_controller_switch_pro
  • steam_controller_mobile_touch
  • steam_controller_ps3

Note that GMS1 / Steamworks1.35a does not support getting controller types and will always return steam_controller_unknown.


Returns how many Steam Input devices can be detected at most.

This is constant per SDK version;

As of writing this in 2021, this is 16.

Action sets

See documentation;


Finds an action set ID with given name.

Returns a negative number if such an action set does not exist!

steam_controller_set_actionset(controller_id, actionset_id)​success

Returns the current action set id for a controller, or -1 if it fails (e.g. wrong controller ID).

In-game actions

See documentation;

Digital actions:


Finds a Digital Action ID by its name.

Returns a >=0 action ID on success, or a negative value on failure.

steam_controller_get_digital_value(controller_id, digital_id)​bool

Retrieves the current state of a digital action for a controller.

Returns false if controller is missing or action ID is invalid.

steam_controller_get_digital_status(controller_id, digital_id)​bool

Returns whether the given digital action is currently active.

Similarly, returns false if controller is missing or action ID is invalid.

steam_controller_get_digital_origins(controller_id, actionset_id, digital_id, ?out:array<origin>)​array<origin>

Fetches the origins for the specified digital action of an action set for a controller.

The result is an array of origin IDs (see values here) that can then be used to display the correct input prompt.

See GetDigitalActionOrigins

Analog actions:


Find an Analog Action ID by its name.

Returns a >=0 action ID on success, or a negative value on failure.

NB! Digital and analog action names and IDs can overlap. Don't mix them up!

steam_controller_get_analog_status(controller_id, analog_id)​bool

Returns whether the given analog action is currently active.

Returns false if controller is missing or action ID is invalid.

steam_controller_get_analog_mode(controller_id, analog_id)​mode_id

Returns the virtual input mode used by an analog action.

See the returned values here.

Returns -1 if controller is missing or action ID is invalid.

steam_controller_get_analog_x(controller_id, analog_id)​number

Returns the state of an action's horizontal axis.

As per documentation, values depend on configuration - e.g. traditional actions return normalized values in -1..+1 range while mouse-like actions provide updates in pixels since the last frame.

Returns 0 if controller is missing or action ID is invalid.

steam_controller_get_analog_y(controller_id, analog_id)​number

Same as above, but for vertical axis.

Returns 0 if controller is missing or action ID is invalid.

steam_controller_get_analog_origins(controller_id, actionset_id, analog_id, ?out:array<origin>)​array<origin>

Fetches the origins for the specified analog action of an action set for a controller.

The result is an array of origin IDs (see values here) that can then be used to display the correct input prompt.

See GetAnalogActionOrigins



Returns the maximum number of input origins that can be attached to a single action.

This value is constant per SDK version and is set to 8 as of writing this in 2021.

User/friend functions

Adds the given user to the "recently played with" list (accessed via "Players" - "Recent games") menu in Steam overlay.

This is usually something to do on session start for all remote users.


Returns an array of information about what the current user's Steam friends are playing, roughly equivalent to what can be seen in Steam Friends UI.

The array contains nested 3-element arrays with the following fields:

  • Steam User ID
  • Steam Game ID
  • Steam Lobby ID
    (if hosting a lobby that is open for friends to join - otherwise 0)

This can be used to display an in-game join dialog.

var info_arr = steam_get_friends_game_info();
var info_num = array_length(info_arr);
var _steam_app_id = steam_get_app_id();
for (var i = 0; i < info_num; i++) {
    var info = info_arr[i];
    if (info[1] == _steam_app_id) { // same game!
        var lobby_id = info[2];
        if (lobby_id != 0) { // has an open lobby!
            var user_id = info[0];
            // use steam_get_user_persona_name(user_id) to grab the name,
            // store and use steam_lobby_join_id(lobby_id) to join the lobby when asked

steam_get_user_avatar(user_id, avatar_size)​steam_image_id

Fetches an avatar for the specified user ID.

avatar_size can be:

Returns positive IDs (for use with function below) if the avatar is ready;
Returns 0 if no avatar is set for the user;
Returns -1 if the request is pending, in which case an async event will be dispatched with:

  • async_load[?"event_type"]: "avatar_image_loaded"
  • async_load[?"user_id_high"]: first half of associated user's ID
  • async_load[?"user_id_low"]: second half of associated user's ID
  • async_load[?"user_id_string"]: associated user ID as a string
  • async_load[?"image"]: image ID that would otherwise be returned by the function.
  • async_load[?"width"]: image width, in pixels
  • async_load[?"height"]: image height, in pixels

A wrapper for GetImageSize.

Fetches dimensions for the said Steam image ID.

If the call succeeds, the return value is a two-element array containing width and height in pixels.

If the call fails, returns undefined.

steam_image_get_rgba(steam_image_id, buffer)​bool

A wrapper for GetImageRGBA.

Grabs RGBA data of the specified Steam image ID into a GameMaker buffer.

The buffer should be appropriately sized in accordance with steam_image_get_size (width * height * 4).

Returns whether successful.

steam_image_get_bgra(steam_image_id, buffer)​bool

Like steam_image_get_rgba, but converts the pixels to BGRA format (primarily for use with GMS1.4).


A convenience function that grabs the size of the given Steam image ID, creates a buffer for it, copies the pixels to the buffer, copies the pixels to a surface, and creates a sprite out of it.

Returns the newly made sprite ID (which you'll want to sprite_delete once you're done with it) or -1 if the operation fails.

Steam Overlay

Like GameMaker's steam_activate_overlay, but allows to specify any raw names from Steamworks documentation that may not be covered by ov_ constants.


Changes the corner in which overlay notifications will appear.

Position can be:

  • steam_overlay_notification_position_top_left
  • steam_overlay_notification_position_top_right
  • steam_overlay_notification_position_bottom_left
  • steam_overlay_notification_position_bottom_right

This position is per-game and is reset each launch.

steam_set_overlay_notification_inset(hor_inset, vert_inset)

Sets the inset of the overlay notification from the corner specified by steam_set_overlay_notification_position.

A value of (0, 0) resets the position into the corner.

This position is per-game and is reset each launch.

Rich Presence
Steam Inventory

The following functions allow to use Steam Inventory Service.



Represents an item type ("item definition number").

Valid definition numbers are between 1 and 999999999;
Numbers less than or equal to zero are invalid;
Numbers greater than or equal to one billion (1x10^9) are reserved for internal Steam use.


Every individual instance of an item has a globally-unique instance ID.

This ID is unique to the combination of a player and specific item instance, and will not be transferred to another player or re-used for another item.


Many of the functions in this section return a steam_inventory_result async result ID.

Invalid results are represented by -1, also available as steam_inventory_result_invalid constant.

When a result is ready, an async event will be dispatched with:

  • async_load[?"event_type"]: "inventory_result_ready"
  • async_load[?"result"]: status code as per steam_inventory_result_get_status.
  • async_load[?"handle"]: the associated async result ID, which can be used to tell apart what result this event is for.

The ID can later be found in async_load[?"handle"] in inventory-related async events and can be polled to retrieve status or returned items.

Async results must be destroyed when you are done using them via steam_inventory_result_destroy.


A wrapper for GetResultStatus.

Returns status code of a result.

You may opt to use this instead of async events.

Possible values are:

  • steam_inventory_result_status_pending
  • steam_inventory_result_status_ok
  • steam_inventory_result_status_expired
  • steam_inventory_result_status_invalid
  • steam_inventory_result_status_fail
  • steam_inventory_result_status_invalid_param
  • steam_inventory_result_status_service_unavailable
  • steam_inventory_result_status_limit_exceeded

(see Steam documentation for status code explanations)


A wrapper for DestroyResult.

Destroys a result handle and frees all associated memory.


A wrapper for GetResultTimestamp.

Returns a Unix timestamp for the server time at which the result was generated.

steam_inventory_result_get_item_property(inv_result, item_index:int, prop_name:int)​int

A wrapper for GetResultItemProperty.

Gets the dynamic properties from an item in an inventory result set.

Property names are always composed of ASCII letters, numbers, and/or underscores.


steam_inventory_consume_item(item_id, quantity)​steam_inventory_result
steam_inventory_exchange_items(create_arr, destroy_arr)​steam_inventory_result

A wrapper for ExchangeItems.

Grants one item in exchange for a set of other items.

create_arr is an array of structs representing items to be created:

destroy_arr is an array of structs representing items to be consumed:

  • item_id: a steam_inventory_item_id of an item to be consumed
  • quantity: how much of the said item is to be consumed

As of writing this, Steam only supports creating one item per call.

See Steam documentation for specifics.

NOTE: You must call steam_inventory_result_destroy on the returned async result ID when you are done with it.


A wrapper for GenerateItems.

Generates specific items for the current user.

This is only usable by Steam accounts that belong to the publisher group for your game.

create_arr is an array of structs representing items to be created:

NOTE: You must call steam_inventory_result_destroy on the returned async result ID when you are done with it.


A wrapper for RequestEligiblePromoItemDefinitionsIDs.

Requests the list of "eligible" promo items that can be manually granted to the given user.

If user_id is omitted, the items will be checked for the current user.

Once ready, dispatches an async event with:

  • async_load[?"event_type"]: "inventory_request_eligible_promo_item_defs"
  • async_load[?"user_id_high"]: First half of the user ID (to be passed to steam_id_create)
  • async_load[?"user_id_low"]: Second half of the user ID (same as above)
  • async_load[?"item_def_count"]: Number of items returned
  • async_load[?"item_def_json"]: A JSON string with an array of steam_inventory_item_defs
  • async_load[?"is_cached_data"]: indicates whether the data was retrieved from the cache and not from the server

NOTE: This is only available for GMS2/SDK1.42+.


A wrapper for LoadItemDefinitions.

Triggers an asynchronous load and refresh of item definitions.

Dispatches an async event with async_load[?"event_type"] == "inventory_definition_update" when done.

Item prices
steam_inventory_transfer_item_quantity(source_item_id, quantity, dest_item_id)​steam_inventory_result
Item property updates

NOTE: The following are only available for GMS2/SDK1.42+.


A wrapper for StartUpdateProperties.

Starts a transaction request to update dynamic properties on items for the current user.

Returns a steam_inventory_update_handle that is used in other functions in this section.

steam_inventory_set_property_bool(handle, item_id, prop_name, bool_val)​bool
steam_inventory_set_property_float(handle, item_id, prop_name, f32_val)​bool

Same as above, but for 32-bit floats.

steam_inventory_set_property_int(handle, item_id, prop_name, int_val)​bool

Same as above, but for 64-bit integers.

steam_inventory_set_property_string(handle, item_id, prop_name, str_val)​bool

Same as above, but for strings.

steam_inventory_remove_property(handle, item_id, prop_name)​bool

A wrapper for RemoveProperty.

Removes a dynamic property for the given item.

Steam ID functions

Functions for handling 64-bit Steam IDs


This macro can be flipped to false on the steam_id.gml file, which will cause Steamworks.gml to store Steam IDs as two 32-bit integers in a tiny array instead.

This was only useful in REALLY old (1.4.1757 and earlier) versions of GameMaker: Studio where 64-bit integer support was occasionally buggy.

steam_id_create(high, low)​steam_id

Creates a 64-bit ID from two 32-bit halves.

You can see it occasionally used in async events since GameMaker lacks support for dispatching async events with 64-bit integer fields in them.


Returns the higher 32-bit half of a Steam ID.


Returns the lower 32-bit half of a Steam ID.

steam_id_equals(steam_id1, steam_id2)​bool

Returns whether the two Steam IDs are identical.

(with steam_id_use_int64 enabled, this is just steam_id1 == steam_id2)

Uncommon functions

Anything not fitting into the above categories.


Attempts deletion of a previously published UGC item.

This will dispatch an async event with:

  • "event_type": "ugc_delete_item"
  • "success": whether deletion succeeded
  • "result": can offer a more detailed status code if deletion fails
  • "published_file_id_high"
  • "published_file_id_low"
if (async_load[?"event_type"] == "ugc_delete_item") {
    var file_id = steam_id_create(async_load[?"published_file_id_high"], async_load[?"published_file_id_low"]);
    if (async_load[?"success"]) {
        show_debug_message("Deleted " + string(file_id));
    } else {
        show_debug_message("Failed to delete " + string(file_id)
            + " - EResult " + string(async_load[?"result"]));

steam_get_app_ownership_ticket_data(buffer, ?app_id)

Takes a buffer and fills it up with a reasonable "future proof" view of an app ownership ticket for a given app ID.

buffer is a buffer to fill up. Documentation is not very specific, but it seems like it should be at least 256 bytes long.

app_id is the Steam App ID to retrieve ownership data for. If not specified, this defaults to steam_get_app_id().

Returns a 5-element array:

  • 0: Total number of bytes retrieved (0 if the buffer wasn't large enough).
  • 1: Byte offset for App ID in the buffer.
  • 2: Byte offset for Steam User ID in the buffer.
  • 3: Byte offset for signature in the buffer.
  • 4: Byte length for signature in the buffer.

For example,

var b = buffer_create(256, buffer_fixed, 1);
var d = steam_get_app_ownership_ticket_data(b);
if (d[0] > 0) {
    show_debug_message("App ID: " + string(buffer_peek(b, d[1], buffer_u32)));
    show_debug_message("User ID: " + string(buffer_peek(b, d[2], buffer_u64)));
    show_debug_message("Signature: " + string(d[4]) + "B at ofs:" + string(d[3]));
} else {
    show_debug_message("Failed to retrieve app ownership data.");

See: ISteamAppTicket

steam_user_request_encrypted_app_ticket(?data, ?data_size)

data (optional) is a string or a buffer to include in the resulting buffer.
If not specified, defaults to NULL and includes no additional data.

data_size (optional) is the number of bytes in data.
If not specified, this will be set to byte count in a string (not including the final NUL), or buffer size.

This function is async.
Once ready, it will dispatch the following Async - Steam event:

  • "event_type": will be "user_encrypted_app_ticket_response_received".
  • "success": will be true or false depending on whether the operation succeeded.
  • "result": will hold the extended EResult ID if you need that.
  • "ticket_data": will hold base64 of returned binary data.
    You'll probably want to buffer_base64_decode it.

For example:


and in Async - Steam:

if (async_load[?"event_type"] == "user_encrypted_app_ticket_response_received") {
    if (async_load[?"success"]) {
        var buf = buffer_base64_decode(async_load[?"ticket_data"]);
        // ... do something with buf
    } else {
        show_debug_message("Failed to retrieve app ticket - "
            + string(async_load[?"result"]));

See: RequestEncryptedAppTicket

Not to be confused with steam_get_app_ownership_ticket_data!