godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.55k stars 20.67k forks source link

the multiplayer.send_auth() returns error ERR_INVALID_PARAMETER #97396

Open se8820726 opened 6 days ago

se8820726 commented 6 days ago

Tested versions

reproducible in Godot Engine v4.3.stable.official.77dcf97d8

System information

windows 11 - godot 4.3 - OpenGL API 3.3.0 NVIDIA 560.81 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 3070 Ti Laptop GPU

Issue description

if you see the example code that i provided in line :

var auth_packet :PackedByteArray= "test".to_utf8_buffer()
var error = multiplayer.send_auth(id, auth_packet)

the id is server id and is int 1 and the auth_packet is PackedByteArray and value of error is 31 means ERR_INVALID_PARAMETER

according to documents: the send_auth() input parameters is : int and PackedByteArray and im passing correct values to it. but returns ERR_INVALID_PARAMETER

i think this is a bug

Steps to reproduce

extends Node3D

var port=8083
var ip='127.0.0.1'

func createServer()->void:
    var server_peer := ENetMultiplayerPeer.new()
    server_peer.create_server(port)
    multiplayer.multiplayer_peer = server_peer
    multiplayer.auth_callback = Callable(self, "_auth_request_handler")
    multiplayer.peer_authenticating.connect(_on_peer_authenticating)

func _auth_request_handler(peer_id: int, auth_data: PackedByteArray)->void:
    print('_auth_request_handler: ',peer_id)

func _on_peer_authenticating(peer_id:int)->void:
    print("Peer is authenticating: ", peer_id)

func joinServer()->void:
    var client_peer := ENetMultiplayerPeer.new()
    client_peer.create_client(ip,port)
    multiplayer.multiplayer_peer = client_peer
    multiplayer.peer_connected.connect (inClientSide_clientConnected)

func inClientSide_clientConnected(id:int)->void:

    if id==1:

        var auth_packet :PackedByteArray= "test".to_utf8_buffer()

        # Send the authentication data to the server
        var error = multiplayer.send_auth(id, auth_packet)
        print(id,'  ',error)

Minimal reproduction project (MRP)

test2.zip

AThousandShips commented 6 days ago

I haven't tested but from the code and reading the docs send_auth should be called in peer_authenticating, from the description

se8820726 commented 6 days ago

@AThousandShips no. peer_authenticating emits in server. inClientSide_clientConnected emits in client and in it i want to send authentication data to server by multiplayer.send_auth

so because peer_authenticating emits in server i can not send authentication data in it

AThousandShips commented 6 days ago

The ERR_INVALID_PARAMETER error here is likely from that this peer isn't pending any more from this line: https://github.com/godotengine/godot/blob/4254946de93bab0cc1fb36a7b9039c9ec43be924/modules/multiplayer/scene_multiplayer.cpp#L461

se8820726 commented 6 days ago

sorry @AThousandShips I didn't understand your perspective. Is this issue a bug overall, or do I need to do something?

AThousandShips commented 6 days ago

I'm just saying where the error comes from, I will test the project soon and see if I can identify what is wrong, but I think this is an issue of that the process of doing this isn't clearly documented and that this isn't how this interface is used

AThousandShips commented 6 days ago

You need to do the following, you need to set up the callbacks on both ends, and perform the authentication call on the peer_authenticating signal, minimal example (from your code):

func createServer()->void:
    var server_peer := ENetMultiplayerPeer.new()
    server_peer.create_server(port)
    multiplayer.multiplayer_peer = server_peer
    multiplayer.auth_callback = _auth_request_handler_server
    multiplayer.peer_authenticating.connect(_on_peer_authenticating_server)
    multiplayer.peer_connected.connect(_on_peer_connected_server)

func _auth_request_handler_server(peer_id: int, auth_data: PackedByteArray)->void:
    print('_auth_request_handler_server: ',peer_id, " ", auth_data)
    multiplayer.complete_auth(peer_id)

func _on_peer_authenticating_server(peer_id:int)->void:
    print("Peer is authenticating (server): ", peer_id)
    var auth_packet :PackedByteArray= "test".to_utf8_buffer()
    var error = multiplayer.send_auth(peer_id, auth_packet)
    print(peer_id,'  ',error)

func _on_peer_connected_server(id: int) -> void:
    print("Connected (server): ", id)

func joinServer()->void:
    var client_peer := ENetMultiplayerPeer.new()
    client_peer.create_client(ip,port)
    multiplayer.multiplayer_peer = client_peer
    multiplayer.auth_callback = _auth_request_handler_client
    multiplayer.peer_authenticating.connect(_on_peer_authenticating_client)
    multiplayer.peer_connected.connect(_on_peer_connected_client)

func _auth_request_handler_client(peer_id: int, auth_data: PackedByteArray)->void:
    print('_auth_request_handler_client: ',peer_id, " ", auth_data)
    multiplayer.complete_auth(peer_id)

func _on_peer_authenticating_client(peer_id:int)->void:
    print("Peer is authenticating (client): ", peer_id)
    var auth_packet :PackedByteArray= "test".to_utf8_buffer()
    var error = multiplayer.send_auth(peer_id, auth_packet)
    print(peer_id,'  ',error)

func _on_peer_connected_client(id:int)->void:
    print("Connected (client): ", id)

This should be documented more clearly

se8820726 commented 6 days ago

Your solution worked. Thank you very much for your response.

In the end, I understood that:

1- I don't need to use Callable() for auth_callback, I can just give it the function directly. 2- In the client, I must define auth_callback so that in client peer_authenticating will run, and I should call multiplayer.send_auth in it. 3- And also, in the server's peer_authenticating, I must send a message to the client so that auth_callback runs in the client, and then I definitely need to confirm the server using multiplayer.complete_auth in client auth_callback

Is that correct?

AThousandShips commented 6 days ago

I'm not sure exactly what steps are needed, the example code runs authentication both ways and the auth_callback on the client responds to the send_auth from the server and vice-versa, confirm by changing the message in either one and printing it as a string, in my testing the authentication has to be enabled at both ends or it will get weird error messages about packets being invalid, not sure what is the intended behavior

So this should be documented more clearly, and not sure exactly what is the correct workflow with using these, so someone with multiplayer knowledge should be responsible for that

AThousandShips commented 6 days ago

This should still be clarified in the documentation so lets keep this open