godotengine / godotengine/godot-cpp

Odd behavior with signal return array and function mixing up values

Open
#1,087 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
2.7k
Forks
809
Avg merge
1d 3h
Merged PRs (30d)
8

Description

I've had some weird, long-standing issues with GDNative that I finally decided to bring up here. [I have also attached this minimum reproduction test.](https://github.com/godotengine/godot-cpp/files/11181428/GDNative.Min.Test.zip) Both issues are related to Steamworks; however, these issues _only_ exist in the GDNative version of my project despite having the exact same code-base as the module or GDExtension versions; thus this behavior is due to something with GDNative.

---

First, there is a function called setRichPresence where the user passes two strings to set internally in Steam. This works as expected in the module and GDExtension; it registers fine in Steam's console and any in-game output. However, in GDNative, it will erratically pass the key as the value instead. There is no rhyme or reason as to why or when this happens; it seems completely random if you pass the same key/value pair over and over. This is a print-out from the Steam console to show that the key becomes the value:
````
00020000 Godot_v3.5.2-stable_win64.exe:3735561 > IClientFriends::SetRichPresence( 480, "score", "score", ) = 1,
00020388 Godot_v3.5.2-stable_win64.exe:3735561 > IClientFriends::SetRichPresence( 480, "score", "50", ) = 1,
00020909 Godot_v3.5.2-stable_win64.exe:3735561 > IClientFriends::SetRichPresence( 480, "score", "50", ) = 1,
````
All three (module, GDExtensions, and GDNative) have the exact same code:
````
bool Steam::setRichPresence(const String& key, const String& value){
if(SteamFriends() == NULL){
return false;
}
return SteamFriends()->SetRichPresence(key.utf8().get_data(), value.utf8().get_data());
}
````
The only difference is how they are bound and what Godot source they use (GDNative using godot-cpp):
````
# GDNative
register_method("setRichPresence", &Steam::setRichPresence);

# Module / GDExtension
ClassDB::bind_method(D_METHOD("setRichPresence", "key", "value"), &Steam::setRichPresence);
````
In my mind, this rules out Steamworks as an issue and the project's code in general since the only inconsistency is with the GDNative version.

---

Second, there is an issue with a signal returning an array. Again, this works fine with the module version and the GDExtension version that share the exact same code as the GDNative version, with the only difference being how it is bound:
````
void Steam::lobby_match_list(LobbyMatchList_t *call_data, bool io_failure){
if(!io_failure){
int lobby_count = call_data->m_nLobbiesMatching;
Array lobbies;
for(int i = 0; i < lobby_count; i++){
CSteamID lobby_id = SteamMatchmaking()->GetLobbyByIndex(i);
uint64_t lobby = lobby_id.ConvertToUint64();
lobbies.append(lobby);
}
emit_signal("lobby_match_list", lobbies);
}
}
````
In the module and GDExtension, this produces a signal that return the lobbies as an array and works as expected. In GDNative, this seems to return all of the lobbies directly without putting them in an array. So we get fifty variables returned instead of one, in the case of app ID 480.

Stranger yet, if I add any other variant to the return like so:
````
void Steam::lobby_match_list(LobbyMatchList_t *call_data, bool io_failure){
if(!io_failure){
int lobby_count = call_data->m_nLobbiesMatching;
Array lobbies;
for(int i = 0; i < lobby_count; i++){
CSteamID lobby_id = SteamMatchmaking()->GetLobbyByIndex(i);
uint64_t lobby = lobby_id.ConvertToUint64();
lobbies.append(lobby);
}
emit_signal("lobby_match_list", lobbies, lobby_count);
}
}
````
It will return the lobbies array correctly as well as the integer for the lobby count. This is an incredibly bizarre behavior that I can't figure out. Again, the only difference between the three versions is how it is bound:
````
# Module / GDExtension
ADD_SIGNAL(MethodInfo("lobby_match_list", PropertyInfo(Variant::ARRAY, "lobbies")));

# GDNative
register_signal("lobby_match_list", "lobbies", GODOT_VARIANT_TYPE_ARRAY);
````
There are other signals that return just arrays and they work fine so this is, again, incredibly strange.

Now, I may be doing something incorrect somewhere but through all of my testing, this seems to point back to some oddities with GDNative that I cannot pinpoint.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.