feat: Implement handshake over ENetMultiplayerPeer to detect closed connections#479
Conversation
…ead of a ENetConnection to allow to return an error if the connection with the host peer is dropped.
PacketHandshake.over_enet() to take an ENetMultiplayerPeer instead of a ENetConnection |
Hey @camperotactico, Thanks for the PR, nice catch! This does make sense, though I moved the logic into a new method instead, to not break backwards compatibility. I couldn't reproduce the issue locally, would you mind checking that the fix still works, e.g. with Forest Brawl? |
|
Hello @elementbound, Thanks for reviewing the changes I submitted. I just tried the new method on the Forest Brawl example and I can confirm the problem does not appear again. What I did was to reproduce the issue first with By default it is not possible to reproduce the bug in Forest Brawl, as it doesn't have a "lobby room" where players can connect and disconnect freely before the game starts. I had to make a couple of changes to simulate the environment on which the error can actually appear (Similar to the project I am working on). In my project, the error appears on the host instance of the game when the host player decides to close a lobby room right after a client peer joins it (At this point, the handshake over enet is taking place, even if both peers have already reached each other). By closing the lobby room I mean something similar to: # close multiplayer menu screen and leave back to main menu
multiplayer.multiplayer_peer.close()
Noray.disconnect_from_host()
multiplayer_menu_screen.hide()
main_menu.show()So, in order to simulate this in Forest Brawl, I simply modified the func _handle_new_peer(id: int):
...
# Once the second player is connected, close the connection.
if multiplayer.is_server():
await get_tree().create_timer(2.0)
multiplayer.multiplayer_peer.close()
Noray.disconnect_from_host()Obviously this example game is not accounting for that to happen, so there are other errors that appear when performing this action. However, only # line 16: add a check to ensure the multiplayer_peer is connected before updating the label values.
if get_tree().get_multiplayer().multiplayer_peer.get_connection_status() == MultiplayerPeer.ConnectionStatus.CONNECTION_CONNECTED and not get_tree().get_multiplayer().is_server():
then the enet errors start popping up as they do on my project. I know this testing process it is a bit dirty, but I wanted to write it down in case we need to test the same issue in the future. |
|
Thanks for the guide and the PR, @camperotactico! |
|
I am glad to hear that. Thanks to you as well for making this amazing asset 🫶🏻 |
Hello, I have been using the Noray add-on for the last couple of days and I noticed a small issue regarding the method
PacketHandshake.over_enet().I have been using this method in a similar matter to the bootstrapper example: The host peer uses it to handshake each client peer anytime a NAT or Relay connection is received by Noray.
In my game, the issue appears when the host peer decides to close the "multiplayer lobby" (and thus disconnect from the Noray orchestrator server and freeing its multiplayer_peer) while a client peer was trying to connect.
The debugger console in Godot then gets full of error messages for the remaining duration of the timeout while loop in
PacketHandshake.over_enet()as the connection is no longer active.At the moment, there is no exposed method to check whether a
ENetConnectionis active or not to prematurely return from the while loop before the timeout.Because of that, I modified
PacketHandshake.over_enet()to take aENetMultiplayerPeerinstead of itsENetConnectionto allow to return an error if the connection with the host peer is dropped.I am new to network stuff, so feel free to let me know if this change is not a good idea.