How to achieve a connection between an ENetMultiplayerPeer client (Godot) and another ENet implementation server (ASP.NET Core)?

Godot Version

Godot 4.2.1

Question

Hi all,

I’m currently trying to establish an ENet connection between a Godot Client and a Custom Server written in ASP NET Core (C#) in .NET 8 which does not use any Godot stuff at all.

To do so, I’m using the ENetMultiplayerPeer on the client side and the ENet-CSharp library on the server side.

If I’m not wrong the ENetMultiplayerPeer is just a simple implementation of the ENet library, so, any other implementation of that library whatever programming language it is should do the job ?

However, the client can’t connect to the server for some reason and I can not figure out why.

Here is the client code:

extends Node

# Private fields
var _peer = ENetMultiplayerPeer.new();
var _playerId = -1;

# Settings
var SERVER_IP = ProjectSettings.get_setting("GAME_SERVER_IP", "127.0.0.1");
var SERVER_PORT = ProjectSettings.get_setting("GAME_SERVER_PORT", 8881);

# Called when the node enters the scene tree for the first time.
func _ready():
	multiplayer.connected_to_server.connect(_OnConnectedToServer);
	multiplayer.connection_failed.connect(_OnConnectionFailed);
	multiplayer.server_disconnected.connect(_OnServerDisconnected)
	
	var err = _peer.create_client(SERVER_IP, SERVER_PORT);
	if err:
		printerr("[CLIENT][%d] An error occured while creating the client. (%d)" % [_playerId, err]);
		return;
		
	_playerId = _peer.get_unique_id();
	multiplayer.multiplayer_peer = _peer;

func _OnConnectedToServer():
	print("[CLIENT][%d] Successfully connected to the server." % [_playerId])

func _OnConnectionFailed():
	printerr("[CLIENT][%d] Failed to connect to the server." % [_playerId])
	
func _OnServerDisconnected():
	printerr("[CLIENT][%d] Disconnected from the server." % [_playerId])

Here is the server code:

using ENet;
using Host = ENet.Host;

namespace GameServer.Core;

public class ENetServerService(ILogger logger) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {

        using PeriodicTimer timer = new PeriodicTimer(TimeSpan.FromSeconds(1));
        using Host server = new Host();
        
        Address address = new Address
        {
            Port = 8881
        };

        server.Create(address, 32);

        while (!stoppingToken.IsCancellationRequested && await timer.WaitForNextTickAsync(stoppingToken))
        {
            if (server.CheckEvents(out Event netEvent) <= 0 && server.Service(15, out netEvent) <= 0)
            {
                logger.LogInformation("[ENetServerService] No events to process.");
                continue;
            }

            switch (netEvent.Type)
            {
                case EventType.Connect:
                    logger.LogInformation("[ENetServerService] New peer connected to the server.");
                    break;
                case EventType.Disconnect:
                    logger.LogInformation("[ENetServerService] Peer disconnected from server.");
                    break;
            }
        }
    }
}

Basically the client calls the _OnConnectionFailed() method and nothing is observed on the server side.

Does any one have an idea ?
Is it even possible to do such thing ?

Thanks in advance,
Tuskk

Update: I also tested with the ENetConnection, and still does not work at all.

I think what you are trying to do is actually to extend the Godot’s built-in multiplayer Peer and you can see how to do that by looking up into the documentation about the MultiplayerPeerExtension. I am currently implementing a Nakama .NET peer and I am piping it through the godot MultiplayerAPIExtension and MultiplayerPeerExtension, where I would override the behaviour of the peer and how it is to be used. Everything else should be working as usual in Godot after that.

Unfortunately there are not many (if not none) articles or tutorials on how to do it properly. I will be documenting the process once I get it done and working and I will share it in the forum as a tutorial article.

Before trying to extend anything, I just want to achieve a working ENet connection, which I can not, and that’s the issue actually. Here, my client can not connect to the server nor my server is receiving any data from any client.

Edit: I probably misunderstood your answer, but to be sure, AS IS, it’s not possible to connect to any ENet server using the “default” Godot ENet implementation, right ?

You are trying to connect two different implementations for the server and the client respectively in your case. You want the Godot ENetMultiplayerPeer to connect to an ENetServer, but probably the naming here is a bit confusing… The implementation that Godot has is different than the one in the library you are referring to. This is the reason it does not and it will not work “as is”. That is why I pointed you to the Extension classes. This is the only way you can accomplish a dedicated server architecture where the server is not a Godot executable build of your game in a server mode.

1 Like

On the other hand, thinking about it I don’t see a reason why you would want to use a custom server, when the Godot’s built-in already implements this specific library, is tested and has additional functionalities. Why do you want to have a dedicated server architecture in this case? What is the benefit of it? Why don’t you just skip the hassle of implementing server-side logic in a different IDE and service than your game executable? You can then build the game in dedicated server mode which removes all graphics and stuff and leaves only physics. It will also be easier to do server authoritative rpcs this way. Synchronisation would be a whole another wormhole if you want to use other server implementation.

I’ll answer quickly, but I do not think this is the place to debate about why do I want to do such thing or another, but here are the few points:

  • Scalability
  • Maintainability
  • Architecture Choices (Event Driven Microservices & MQTT)
  • Data persistence (Database & Caching layers)
  • Full usage of .NET features (Dependency Injection, Services Lifetime, GC Management…)
  • Better ALM
1 Like

I see. Well this is certainly doable, but as it is in every other engine - you would need to implement the networking bare bones for the engine to work with it. You would also need a lot of competence and more than a solo developer to achieve this, just keep in mind.

That’s kind of the purpose of this post actually :sweat_smile:. As long as Godot is new to me, but not the Game development generally speaking, I just wanted to know what could be keep “as is” within the Godot engine on the networking part, but looks like some work will be needed :joy:

You can most definitely implement all the stuff you mentioned in a Godot project. It is at the end a C# solution. So you can basically just extend the already existing multiplayer API with whatever you like to - add a database: install nuget client snd connect, add authentication/authorization: use microsoft auth for ex, etc. You don’t have to extract your server code from the game project as i said. You could have different project building profiles for the server and the client, each having its own separate files. As I said you are aiming to implement a library which was already adapted to Godot and was tested in production and it is the Godot’s default multiplayer API. I still cannot understand what you would be gaining if you just swap the underlying UDP connection workflow and strip the game physics on the server :slightly_frowning_face: Everything else you can just implement in your godot solution project.