GodotSteam: A couple of UserStats methods are broken

getAchievementIcon

https://github.com/Gramps/GodotSteam/blob/c8d597f6a325c98ffa541a45c6877070283371bf/godotsteam/godotsteam.cpp#L4077

https://partner.steamgames.com/doc/api/ISteamUserStats#GetAchievementIcon, the return type is just a int, not SteamAPICall_t and it triggers a callback, which means, STEAM_CALLBACK is missing.

requestCurrentStats

_user_stats_received is not being emitted. I found STEAM_CALLBACK is missing.

The way I see it, UserStatsReceived_t should be used as a callback when RequestCurrentStats() gets called, while as a callresult when RequestUserStats() https://partner.steamgames.com/doc/api/ISteamUserStats#RequestCurrentStats https://partner.steamgames.com/doc/api/ISteamUserStats#RequestUserStats

I found these breaking changes were introduced in https://github.com/Gramps/GodotSteam/commit/1ef3a2dab4272d0033a9e04913d2dbdc766b552c

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 1
  • Comments: 17 (11 by maintainers)

Most upvoted comments

Excellent, sir! And welcome!

I also added a tutorial for getting achievement icons; much like how avatars work.

Looks good to me. Thank you 👍

Indeed, I will add this to the next update and test it then make a little addition to my tutorials about it!

Sounds good. I appreciate your effort! I will wait for the next update 😃

OK, so I got a response from a Valve employee:

If the handle returned by GetAchievementIcon is > 0, then the icon has already been loaded and you can retrieve it (using the handle) via a ISteamUtils::GetImageRGBA call. The SteamworksExample project included with the SDK includes a GetAchievementIcon call in the CStatsAndAchievements class which could be helpful.

While it didn’t really tell me anything new, I checked the Steamworks example code and it does not appear that the getAchievementIcon even waits for a callback. It seems to go straight from the call to rendering with the handle. I’m guessing perhaps this has been depreciated without notice or maybe never worked?

That being said, I think I’ll change the function in GodotSteam to just request the handle and use it if one is returned. If one is not, perhaps provide some kind of error message. The callbacks will be left intact in case something changes in the future.

Thank you for the update. I’ll keep my eye on this!

I can confirm that requestUserStats does indeed receive a callback twice. I modified your test code as such:

void Steam::_user_stats_received_callback(UserStatsReceived_t* callData){
	CSteamID gameID = callData->m_nGameID;
	uint64_t game = gameID.ConvertToUint64();
	uint32_t result = callData->m_eResult;
	CSteamID userID = callData->m_steamIDUser;
	uint64_t user = userID.ConvertToUint64();
	emit_signal("user_stats_received_callback", game, result, user);
}

void Steam::_user_stats_received_callresult(UserStatsReceived_t* callData, bool bIOFailure){
	CSteamID gameID = callData->m_nGameID;
	uint64_t game = gameID.ConvertToUint64();
	uint32_t result = callData->m_eResult;
	CSteamID userID = callData->m_steamIDUser;
	uint64_t user = userID.ConvertToUint64();
	emit_signal("user_stats_received", game, result, user);
}

ADD_SIGNAL(MethodInfo("user_stats_received_callback", PropertyInfo(Variant::INT, "gameID"), PropertyInfo(Variant::INT, "result"), PropertyInfo(Variant::INT, "userID")));

That way the callback would not trigger the call result. This confirms that requestUserStats does fire both the callback and the call result. So it seems that requestUserStats also calls requestCurrentStats as you assumed. There is no way to undo this as it is in the Steamworks API.

You could try using ONESHOT on the callback so it doesn’t fire again as it is called when the Steamworks API loads initially. However, that may or may not have some affect on your game depending on if you need to call it again later. In which case it could be substituted for requestUserStats.

I can also confirm that getAchievementIcon never receives the callback. I have no idea why that is but seems to be an issue with Steamworks itself. I’ll try bringing it up in the developer group and see if there is any answer on that.

Quick update here. I rebased on the latest master and now testing https://github.com/Gramps/GodotSteam/compare/master...yeonghoey:fix-stats.

I’m using the following code.

extends Control

func _ready():
	Steam.steamInit()
	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")

func _process(delta):
	Steam.run_callbacks()

func _on_requestCurrentStats_pressed():
	Steam.requestCurrentStats()

func _on_requestUserStats_pressed():
	Steam.requestUserStats(1234)

func _on_user_stats_received(gameID, result, userID):
	printt("user_stats_received", gameID, result, userID)

func _on_getAchievementIcon_pressed():
	Steam.getAchievementIcon("TEST")

func _on_user_achievement_icon_fetched(gameID, achievementName, achieved, width, data):
	printt("ser_achievement_icon_fetched", gameID, achievementName, achieved, width, data)

func _on_setAchievement_pressed():
	Steam.setAchievement("TEST")
	Steam.storeStats()

func _on_user_achievement_stored(game, groupAchieve, name, currentProgress, maxProgress):
	printt("user_achievement_stored", game, groupAchieve, name, currentProgress, maxProgress)


func _on_resetAllStats_pressed():
	Steam.resetAllStats(true)

With

image

I have two problems here.

  1. user_stats_received is now getting emitted when Steam.requestCurrentStats() is called, as expected. However, now when Steam.requestUserStats(1234) is called, user_stats_received is getting emitted twice. I confirmed this were being emitted once before this change. I suspect because the new callback for requestCurrentStats is global and it affected this change, but I’m still bewildered because in the Steamworks document they say:

NOTE: Callbacks and call results are not interchangeable. An event will only come through one or the other, not both. You must make sure that you are registering for the right type of event!

According to this, each APIs should raise events separately but apparently it doesn’t work in the way they documented.

  1. user_achievement_icon_fetched is not being emitted at all. I tested the latest master and even a version prior to the breaking change, but didn’t get any luck. I suspect this issue can be on the Steamworks API itself, like GetAchievementIcon doesn’t triggerUserAchievementIconFetched_t anymore, while it’s documented to do so. image

Can you double check what I tested? I’m still not sure how I can proceed here.

I’m working on features using these two functions and I’ll check if I can fix it and see if it works as expected, then submit a pull request, does it sound okay?