reckfellENGINE

Dedicated server: launch, ENet and export

Headless startup, server role, UDP port, complete C# example and choosing Strip Visuals, Keep and Remove.

On this page

What server mode changes

A dedicated server runs game logic and networking without rendering. These are separate choices:

ActionEffect
--headlessSelects the headless display driver and Dummy audio. It does not select server game logic by itself.
-- --serverA user argument interpreted by your code. The example below starts an ENet server.
An export with the dedicated_server tagThe engine automatically selects headless and Dummy; the example enables server logic without --server.
Export as dedicated serverAdds the tag and allows unnecessary visual resources to be replaced with placeholders.

Adding only the dedicated_server tag manually does not strip textures or meshes from the pack. Headless also does not mean zero processing cost: physics, scripts, imports and network updates still perform their work.

First run from a project

You need a C# project, a configured main scene and a working project build. Put both files below alongside your other scripts. Attach DedicatedServerHost.cs to one Entity in the main scene. This example owns the tree MultiplayerPeer; do not attach a second host to the same Multiplayer API.

Replace the paths in this command:

PowerShell
& 'C:\Tools\Reckfell\Reckfell Engine.console.exe' --headless --path 'D:\Games\MyGame' -- --server --port=7777 --bind=127.0.0.1

-- separates engine arguments from game arguments. Put --headless before it and --server, --port=... and --bind=... after it. OS.GetCmdlineUserArgs() receives only the latter part.

Expected output: SERVER_READY bind=127.0.0.1 port=7777. The client connects to 127.0.0.1, port 7777. ENet uses UDP. This message confirms local server creation; it does not prove internet reachability or player authentication.

The example listens only on the current computer by default. For a network host, explicitly pass --bind=0.0.0.0 or --bind=*; clients use the actual server address, not 0.0.0.0. The --bind option accepts an IP address or *, not a hostname. Allow the selected UDP port in the firewall. External clients behind NAT may also require router configuration.

Without --server or the dedicated_server tag, the code does not create an ENet server, even under --headless. The same project can therefore run headless checks without unintentionally opening a network port.

Complete startup code

ServerOptions.cs selects the role and validates options. It accepts one --port=<1..65535> and one --bind=...; arguments are case-sensitive. This example deliberately rejects port zero so that the server cannot receive a random port instead of the requested one.

C#
using System;
using System.Globalization;
using System.Linq;
using System.Net;

public sealed record ServerOptions(bool Enabled, int Port, string BindAddress)
{
    public static bool TryRead(string[] args, bool dedicatedBuild,
        out ServerOptions options, out string error)
    {
        options = new(dedicatedBuild || args.Contains("--server"), 7777, "127.0.0.1");
        error = "";
        if (!options.Enabled) return true;
        bool portSeen = false, bindSeen = false;
        foreach (string arg in args)
        {
            if (arg.StartsWith("--port=", StringComparison.Ordinal))
            {
                if (portSeen || !int.TryParse(arg[7..], NumberStyles.None,
                    CultureInfo.InvariantCulture, out int port) || port is < 1 or > 65535)
                { error = "Use one --port=<1..65535>."; return false; }
                portSeen = true;
                options = options with { Port = port };
            }
            else if (arg.StartsWith("--bind=", StringComparison.Ordinal))
            {
                string address = arg[7..];
                if (bindSeen || (address != "*" && !IPAddress.TryParse(address, out _)))
                { error = "Use one --bind=<IP address or *>; hostnames are not accepted."; return false; }
                bindSeen = true;
                options = options with { BindAddress = address };
            }
        }
        return true;
    }
}

DedicatedServerHost.cs opens the port, assigns the transport and releases it when the Entity exits the tree. Repeated StopServer() calls are safe. The example sets a 32-client limit; that is an ENet configuration value, not a measured game capacity.

C#
using Reckfell;

public partial class DedicatedServerHost : Entity
{
    private ENetMultiplayerPeer? _peer;
    public bool Listening { get; private set; }

    public override void _Ready()
    {
        if (!ServerOptions.TryRead(OS.GetCmdlineUserArgs(), OS.HasFeature("dedicated_server"),
            out var options, out string error))
        { ReckfellApi.PrintErr(error); GetTree().Quit(2); return; }
        if (!options.Enabled) return;

        _peer = new ENetMultiplayerPeer();
        _peer.SetBindIP(options.BindAddress);
        Error result = _peer.CreateServer(options.Port, maxClients: 32);
        if (result != Error.Ok)
        {
            ReckfellApi.PrintErr($"SERVER_FAILED {result} bind={options.BindAddress} port={options.Port}");
            _peer.Dispose(); _peer = null;
            GetTree().Quit(3); return;
        }
        Multiplayer.MultiplayerPeer = _peer;
        Listening = true;
        ReckfellApi.Print($"SERVER_READY bind={options.BindAddress} port={options.Port}");
    }

    public void StopServer()
    {
        if (_peer is null) return;
        Multiplayer.MultiplayerPeer = null!;
        _peer.Close(); _peer.Dispose(); _peer = null;
        Listening = false;
    }

    public override void _ExitTree() => StopServer();
}

This starts the transport. Entity replication, RPC, authority checks and game rules are separate: see networked gameplay. An established connection does not make client commands trustworthy.

Export without unnecessary resources

  1. Ensure the C# project has both .csproj and .sln. A successful .csproj build alone does not prove export readiness: C# export checks the solution file.
  2. Install matching engine-version export templates with C# support for the target platform and architecture. Run the exported executable for deployment; use the editor for import and export.
  3. Create a separate export preset, such as Windows Server. In its Resources tab, select Export as dedicated server.
  4. Set the project root to Strip Visuals, then override individual files and folders using the table below. Folder settings are inherited until a child has its own mode.
  5. Export the project and copy the whole output directory, including required C# files. Do not arbitrarily copy only the .exe or a single PCK.
  6. Run the export and check for SERVER_READY. The tag selects headless drivers and the example server branch automatically; --port and --bind still belong after --.
ModeResultUse it when
Strip VisualsReplaces supported resources with placeholders. For example, Texture2D retains dimensions, Mesh retains its AABB, and a material becomes a placeholder. Original pixels and geometry are not retained as usable visual data.The server does not need that resource data.
KeepExports the resource with its original data.Height maps, pixels used by game rules, geometry for calculations, or other data actually read by the server.
RemoveExcludes the file from the pack. References are not repaired automatically.The server branch never loads the file and required scenes/resources do not reference it.

Strip Visuals does not universally remove all graphical content: replacement depends on a resource type supporting create_placeholder. A mesh placeholder with an AABB does not retain triangles for your calculations. If collision shapes are stored separately, retain the required shapes; if you build them from a mesh at startup, retain the original mesh with Keep too. Similarly, image analysis requires Keep, not just retained width and height.

Do not make the server branch unconditionally load a client menu, camera or file marked Remove. Use a server main scene or create client Entities only in the client branch. Reckfell text resources use .rdata; levels use .rscene and prefabs use .rprefab.

See feature tags, command line and project export.

Running the export template

A PCK is not an executable. For a manual pack check, use a matching C# export template, not the editor: running the editor does not verify loading exported C# assemblies.

The tested Windows 1.0.0 debug template disables path overrides: --path and --main-pack abort startup. Do not carry these source-project launch arguments into the exported-game command.

For a separate pack, names must match: Server.exe and Server.pck sit beside each other; the console wrapper is Server.console.exe. With a normal export, preserve its generated names and complete output structure. An embedded pack does not require a separate PCK.

Open a terminal in the exported directory and run:

PowerShell
& '.\Server.console.exe' -- --port=7777 --bind=127.0.0.1

Neither --headless nor --server is required here when the exported project has dedicated_server. After SERVER_READY, connect a separate client. The server pack itself does not provide a client menu.

If the server does not work

SymptomCheck
No window, but no SERVER_READY either--headless alone does not select the role. Pass -- --server or check the exported project tag.
Use one --port..., exit code 2Use one integer port from 1 to 65535, without whitespace or a duplicate option.
Use one --bind..., code 2Supply one IP address or *, not a hostname.
SERVER_FAILED, code 3Read the error name, address and port on that line. Check UDP port availability and whether the address belongs to a local interface.
Local clients connect, external clients do notThe default bind address is 127.0.0.1. Check --bind, the client address, the UDP firewall rule and NAT.
Image or mesh data is missing after exportCheck inherited Strip Visuals; select Keep for data the server actually reads.
Resource loading failsCheck Remove, required references and completeness of the exported directory.
C# export reports a missing solutionRestore the correct .sln beside the project; a successful standalone .csproj build does not fix this.

The example was checked on Windows with installed SDK 1.0.0: headless launch, an ENet loopback connection and a debug export template loading a separate PCK. Texture, mesh and material placeholders, Keep and Remove were checked in the pack. This is not Linux deployment, release-template, external-network or load acceptance.

Reckfell Engine documentationBack to top ↑
QUICK LINKSGetting startedEntity hierarchyC# & .NET 10Scenes and prefabs
Reckfell guides and full API K
reckfellENGINE
RECKFELL ACCOUNT

Sign in

Sign in to your Reckfell account.

One account for the entire Reckfell platform.