Hello,
I managed to make achievements work, but now I'm struggling with steam leaderboards. I got uploadLeaderboardScore() working and uploaded the score to steam, but I'm failing to retrieve the data. How should I use downloadLeaderboardEntries and downloadLeaderboardEntriesForUsers? Can someone show me an example of how it would look like in the code?
Thanks in advance.
Hey there! Seems I do not have a tutorial for leaderboards yet. I have added it to my list of tutorials for my next update.
As for your issue, it has been somewhat discussed in this closed issue: https://github.com/Gramps/GodotSteam/issues/90
This is the example code from it:
func _ready():
Steam.connect("leaderboard_find_result", self, "_leaderboard_found")
Steam.connect("leaderboard_scores_downloaded", self, "_leaderboard_downloaded")
# Now call your leaderboard
Steam.findLeaderboard(YOUR_LEADERBOARD_NAME)
func _leaderboard_found(leaderboard_handle, found):
# Save this handle somewhere like a global VAR
handle = leaderboard_handle
# If the leaderboard was found
if found == 1:
# If getting this user, use the line below; you can add up to 100 other Steam IDs in the array
Steam.downloadLeaderboardEntriesForUsers([steam_ID])
func _leaderboard_downloaded():
# Get the leaderboard entries as an array
var scores = Steam.getLeaderboardEntries()
That last scores variable will be an array that needs parsed. Let me know if this helps!
Thanks for the fast reply! I tested the code in game and in worked like a charm! I just have two last questions.
1- How can I get the player`s steam username?
2- On the uploadLeaderboardScore I saw that I can send an array with details. How exactly does it work? I tried adding an array with number of deaths and in-game player name, but all I got on steam was something like 0x010000000200000000000000c8000000
Welcome! Glad that worked. To answer your questions:
There is a function called getPersonaName (I think) that will get the local user's Steam username. To get a remote player you need getFriendPersonaName and pass their Steam ID 64 to it.
I'm not totally sure how it works as I've not used it. However, the documentation says:
Details are optional game-defined information which outlines how the user got that score. For example if it's a racing style time based leaderboard you could store the timestamps when the player hits each checkpoint. If you have collectibles along the way you could use bit fields as booleans to store the items the player picked up in the playthrough.
Since it is an array, specifically a PoolIntArray in Godot, you'd have to parse that response you got back into something useful.
uploadLeaderboardScore(int score, bool keepBest, PoolIntArray details) only really needs the score and if you want to keep best or not as a BOOL. The player name is attached to the ID which is assumed by the API as the local player so you don't need to worry about any of that.
getFriendPersonaName worked just fine. Now the leaderboard finally looks like a leaderboard!
Thanks for all the help, you`re a life saver!
Awesome! Glad we got it all sorted out, sir! Cheers!
Sorry for commenting after the post was closed, but I got a pretty serious problem and I have no clue what to do. For some reason I can download and upload the leaderboards with no problems while I`m logged in my account. But after the game was released I noticed that no one outside me was in the leaderboards.
When I tried to test in another account I noticed that the buttons to show the leaderboards did nothing and the score wasn`t being uploaded. The only thing out of the ordinary that I found was when i did a print(scores) on _leaderboard_downloaded() and found that the scores array was empty.
Do you have any idea what might be the cause of this?
Thanks in advance!
I presume the leaderboards are published in Steamworks; pretty sure you couldn't even test them otherwise. As for it only working for your main account and not others, I'm not quite sure. Can't say I've heard of that issue yet.
I'd have to double-check all the leaderboard settings in Steamworks to be sure. So your main account can still set and receive scores but no one else can see them?
After a few tests I somehow managed to upload a score with another account, but when I tested the leaderboards in my main account something strange happened. My rank position went to 2, but the rank 1 position have no name nor score.

When i used print(scores) i noticed that the only thing in the array was [(global_rank:2), (score:100), (steamID:76561198055174788)]
Can you share the code you are using to upload the scores and retrieve the scores? You don't have to show anything but those functions specifically.
I'll dig into the Steamworks settings stuff too. Wonder if maybe it's just not sending the data correctly...
OK, so in Steamworks you can view all the scores for each leaderboard. Also there is a writes and reads drop down, what are those set as?
func _ready():
var INIT = Steam.steamInit()
ONLINE = Steam.loggedOn()
STEAM_ID = Steam.getSteamID()
OWNED = Steam.isSubscribed()
Steam.requestCurrentStats()
Steam.connect("user_stats_received", self, "_on_user_stats_received")
Steam.connect("user_achievement_icon_fetched", self, "_on_user_achievement_icon_fetched")
Steam.connect("user_achievement_stored", self, "_on_user_achievement_stored")
Steam.connect("leaderboard_find_result", self, "_leaderboard_found")
Steam.connect("leaderboard_scores_downloaded", self, "_leaderboard_downloaded")
Steam.connect("remote_play_session_connected",self,"_on_remote_play_session_connected")
print("Did Steam initialize?: "+str(INIT))
if INIT['status'] != 0:
print("Failed to initialize Steam. "+str(INIT['verbal'])+" Shutting down...")
get_tree().quit()
if(Steam.steamInit()):
print("Steam API start")
set_process(true)
Steam.findLeaderboard("StoryMode_P1")
Steam.findLeaderboard("StoryMode_P2")
Steam.findLeaderboard("TimeAttack_P1")
Steam.findLeaderboard("TimeAttack_P2")
Steam.getFileCount()
print("cloud: ", Steam.getFileCount())
Steam.isCloudEnabledForApp()
print("cloud is enabled: ", Steam.isCloudEnabledForApp())
# Check if account owns the game
if OWNED == false:
printt("User does not own this game")
get_tree().quit()
func _process(delta):
Steam.run_callbacks()
func _leaderboard_found(leaderboard_handle, found):
# Save this handle somewhere like a global VAR
GlobalVar.handle = leaderboard_handle
# If the leaderboard was found
if found == 1:
# If getting this user, use the line below; you can add up to 100 other Steam IDs in the array
Steam.downloadLeaderboardEntriesForUsers([STEAM_ID])
func _leaderboard_downloaded():
# Get the leaderboard entries as an array
var scores = []
scores = Steam.getLeaderboardEntries()
GlobalVar.scores = scores
print(scores)
all writes and reads are set to false on the 4 leaderboards i created. I can see my score in all of them, but that`s all
Hmm, well, we can make a few fixes here.
if found == 1:
# If getting this user, use the line below; you can add up to 100 other Steam IDs in the array
Steam.downloadLeaderboardEntriesForUsers([STEAM_ID])
This will only pull leaderboards for the current user and no one else. Which is probably why you only see your own and no one else sees yours. You'll probably want to use downloadLeaderboardEntries instead.
Do you get entries for all leaderboards? I don't know if the process has to complete fully before calling the next leaderboard or not. Since the handle will change each time it is called and found. The way Steamworks functions is it seems to only deal with one at a time then basically drops all data afterward.
Do you have an example of how the scores are uploaded?
You might also want to pop in a check for them being uploaded:
Steam.connect("leaderboard_uploaded", self, "_on_leaderboard_uploaded")
func _on_leaderboard_uploaded(failure, score, score_changed, global_rank_new, global_rank_previous):
print("Score was uploaded, result = " + str(failure))
Also with this:
if INIT['status'] != 0:
print("Failed to initialize Steam. "+str(INIT['verbal'])+" Shutting down...")
get_tree().quit()
if(Steam.steamInit()):
print("Steam API start")
set_process(true)
I would take out the second Steam.steamInit() as you are just re-initializing again. Doesn't hurt anything but is redundant as you do it right at the beginning of the ready() function.
You could do this instead:
if INIT['status'] != 0:
print("Failed to initialize Steam. "+str(INIT['verbal'])+" Shutting down...")
get_tree().quit()
else:
print("Steam API start")
set_process(true)
changing to downloadLeaderboardEntries fixed the problem. And I believe that Steam.connect("leaderboard_uploaded", self, "_on_leaderboard_uploaded") also helped. So far I managed to upload the score with my other account and download the results without any problems. I`ll keep an eye to see if everything is okay, but so far so good!
Cool! Glad we got it sorted out, sir!