samsface / godot-steam-api

Godot Steam integration using GDNative.
403 stars 16 forks source link

Inconsistent Behavior With Setting Rich Presence #39

Open Gramps opened 1 year ago

Gramps commented 1 year ago

Hey, Sam! Gramps here. I'm opening this issue to get your input on a problem with setting rich presence in Steamworks which seems to affect both your project and mine; though my module and GDExtension are immune to this issue. Perhaps a second set of eyes will help.

I have tested it with Steam's console, their rich presence tester (which isn't super helpful), my GDNative plug-in, my GDExtension plug-in, my module, and your GDNative plug-in; the results are always the same: failure on the GDNative side.

When not using a "special key" specified by Steam, it seems to have an inconsistent behavior when setting keys/values. Since you can pass key/values that will substitute in the rich presence tokens, this kind of needs to work right. If you pass, like Valve's example, the key score then your score as the value, it will sometimes pass the key as the value:

# in GodotSteam
Steam.setRichPresences("score", 40)

# in your system
Steam.friends.set_rich_presence("score", 40)

# both occasionally show as:
06058352 Godot_v3.5.2-stable_win64.exe:3670020 > IClientFriends::SetRichPresence( 480, "score", "score", ) = 1, 
06058534 Godot_v3.5.2-stable_win64.exe:3670020 > IClientFriends::SetRichPresence( 480, "score", "40", ) = 1,

In a test of 100 attempts, it did this 19 times; both with your GDNative plug-in and mine. However, with my module or GDExtension plug-in, this succeeds 100% of the time. Also if you pass one of the "special keys", this will succeed 100% of the time:

# Passing 40 with "steam_display" as key consistently gives
06250305 Godot_v3.5.2-stable_win64.exe:4194309 > IClientFriends::SetRichPresence( 480, "steam_display", "40", ) = 1, 

Printing the currently set rich presence with getRichPresence( steam_id, key ), on the GDNative end, shows that the value is indeed set as "score" or sometimes just blank. While in the module/GDExtension, this prints the expected value of 40 each time.

Given these tests, I assume this is an issue with GDNative. I have another odd behavior with lobby lists that can be solved with the most illogical (to me) solution.

Again, I figured I'd bring it up here first instead of the Godot issues since it affects both of our projects.

samsface commented 1 year ago

@Gramps I've tried a few times now and not able to reproduce this on Linux. I don't have a Windows machine so possibly a Windows only problem.

Gramps commented 1 year ago

Hey @samsface! Hmm, the plot thickens. I'll run my test project through on Linux and OSX to see if I get the same results then report back. Not that it should matter, but what distro were you using?

samsface commented 1 year ago

Ubuntu with clang build chain. And a pretty ancient version of steamsdk (maybe this is a regression in the sdk?).

Gramps commented 1 year ago

How old is old? I'm not sure it is the SDK since this only happens in the GDNative version of your project and mine. This behavior doesn't exist in my module or GDExntension versions. Hopefully today I can do my Linux and OSX test.

Gramps commented 1 year ago

OK, sorry for the late response. I can confirm that your plug-in and mine work fine in Linux but both have this odd behavior in Windows. So, for whatever reason, this is isolated to just GDNative on Windows and nothing else.

Since this is limited to Windows and only GDNative versions, I'm going to guess this isn't a regression with the SDK. Honestly, I doubt this is an issue that can or will be solved. I'm just going to make mention of it in my docs.

samsface commented 1 year ago

@Gramps Just looking at open issues and remembered this one. It sounds like Steam isn't copying the string we pass it and instead just takes the pointer who's address becomes free for Godot's allocator to reuse once the function scope exits. But maybe Steam sends the network call async a while later.

You could test this by copying the string in C++ right before you pass it to a std::string* and then leaking it so it's never freed.

Gramps commented 1 year ago

It's strange that this only affect the GDNative and only the Windows version of GDNative though. Nonetheless, it is on my list of things to explore more when time permits! If I figured it out, I will share it as it also affects your plug-in.