expressobits / steam-multiplayer-peer

Steam Sockets Multiplayer Peer for Godot 4 via GDExtension
MIT License
150 stars 8 forks source link

Nonexistent function 'get_packet_script' in base 'Godot.MultiplayerPeerExtension' #22

Open RoboSkyrat opened 1 month ago

RoboSkyrat commented 1 month ago

Game crashes with

ERROR: Invalid call. Nonexistent function 'get_packet_script' in base 'Godot.MultiplayerPeerExtension'.
   at: void Godot.NativeInterop.ExceptionUtils.DebugCheckCallError(Godot.NativeInterop.godot_string_name, nint, Godot.NativeInterop.godot_variant**, int, Godot.NativeInterop.godot_variant_call_error) (/root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/ExceptionUtils.cs:147)
ERROR: Error getting packet! 2
   at: (modules/multiplayer/scene_multiplayer.cpp:92)
ERROR: Invalid call. Nonexistent function 'get_packet_script' in base 'Godot.MultiplayerPeerExtension'.
   at: void Godot.NativeInterop.ExceptionUtils.DebugCheckCallError(Godot.NativeInterop.godot_string_name, nint, Godot.NativeInterop.godot_variant**, int, Godot.NativeInterop.godot_variant_call_error) (/root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/ExceptionUtils.cs:147)
ERROR: Error getting packet! 2
   at: (modules/multiplayer/scene_multiplayer.cpp:92)
ERROR: FATAL: Condition "!exists" is true.
   at: godot::HashMap<unsigned __int64,class godot::Ref<class SteamConnection>,struct godot::HashMapHasherDefault,struct godot::HashMapComparatorDefault<unsigned __int64>,class godot::DefaultTypedAllocator<struct godot::HashMapElement<unsigned __int64,class godot::Ref<class SteamConnection> > > >::operator [] (godot-cpp\include\godot_cpp/templates/hash_map.hpp:502)

but only after creating a host and having a user join twice.

I am using the C# wrapper (modified slightly to match the latest 0.1.1 create_host and create_client functions) I am on Windows.

I use GodotSteam to create the lobby and when I receive the OnLobbyCreate event I create and set the peer. I have no issues doing that and the engine does not complain. Steam does show that I am in a lobby that is joinable. When connecting with the client nothing happens. Steam properly registers that the client is joining and is calling the code that calls create_client.

if I have the client then close the game and re-join the lobby the engine then crashes with the above error.

At no point is any of the peer or server connection/disconnection signals on MultiplayerApi ever called. in gd or C#.

scriptsengineer commented 1 month ago

get_packet_script

What version of godot? It is trying to access a method that does not exist.

RoboSkyrat commented 1 month ago

Godot 4.2.2

craethke commented 2 weeks ago

Ran into the same problem; the (unmerged) C# bindings map to get_packet_script and put_packet_script, which do not exist in the SteamMuliplayerPeer implementation. Instead, it seems these should be mapped directly to get_packet and put_packet:

public override byte[] _GetPacketScript()
{
    return _classReference.Call(Methods.GetPacket).As<byte[]>();
}

public override Error _PutPacketScript(byte[] pBuffer)
{
    return _classReference.Call(Methods.PutPacket, (Variant) pBuffer).As<Error>(); // cast to variant to avoid varargs expansion
}

private static class Methods
{
    public static readonly StringName GetPacket = new("get_packet");
    public static readonly StringName PutPacket = new("put_packet");
}

This got rid of all the errors for me, but the client is crashing without error a few seconds after calling peer.CreateClient, so I suspect there may be other issues...

craethke commented 1 week ago

Regarding the above issue with the game crashing after calling peer.CreateClient, I switched to calling the GDExtension directly from C# code rather than going through the wrapper, e.g.:

public void ConnectSocket(ulong steamId) {
        var stringName = new StringName("SteamMultiplayerPeer");
        GodotObject _classReference = ClassDB.Instantiate(stringName).AsGodotObject();

        Error error = _classReference.Call("create_client", steamId, 0).As<Error>();
        if (error != Error.Ok) {
            GD.Print("Failed to create client: ", error);
        }

        Multiplayer.MultiplayerPeer = (MultiplayerPeer) _classReference;
    }

and ran the .console.exe via the command line. With that I see that upon creating the client, I get the below error:

Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is co.
    at Godot.GodotObject.Dispose(Boolean)
    at Godot.GodotObject.Finalize()

It seems C# doesn't like something in the GDExtension...


Godot 4.2.2 mono Windows 10 GodotSteam (copied from demo) SteamMultiplayerPeer (copied from demo) GodotSteam C# bindings