The host and its settings
ServerHost builds and runs a dedicated server. It sets up dependency
injection, finds your game's code, listens for connections and runs the game loop. A server's
Program is short:
using BSGameLib.Server;
using var host = new ServerHost(new ServerSettings("MyGame"));
host.Run();
Run() blocks until the host is stopped (by Ctrl+C, or by systemd or the Windows service manager),
and then returns. Running the server covers each way of running it. The host needs
exactly one IGameServer to start; see How it finds your code.
Constructors
| Constructor | Settings |
|---|---|
ServerHost() |
The defaults in ServerSettings: application ID BSGameLib.Server, port 55237. |
ServerHost(IServerSettings) |
Yours. |
Settings
ServerSettings is the settings class. Set its properties in code: BSGameLib does not read them from a configuration file.
| Property | Default | What it does |
|---|---|---|
ApplicationId |
The argument to new ServerSettings(...), or BSGameLib.Server |
A name for the server. It appears in the log and in the name of the generated certificate. Clients don't have to match it. |
ListenPort |
55237 |
The UDP port the server listens on. The unreliable traffic uses this port plus 2; see Running the server. |
BindAddress |
null, which means every address |
The IP address the server listens on, for both of those ports. "127.0.0.1" or "::1" listens on that address only. Give an IP address, not a host name: anything else stops the server at startup. |
QuicConfiguration |
null |
The transport configuration, including your certificate. When it is null, the server makes its own certificate. |
CertificateStorePath |
null, which means certs |
Where the generated certificate is kept. Used only when the server makes one. |
ServerSettings has no DataFolder, so the server keeps its files in the executable's folder. To
choose another folder, implement IServerSettings in a class of your own, as here:
using System.Security.Cryptography.X509Certificates;
using BSGameLib.Networking;
using BSGameLib.Server;
public class MySettings : IServerSettings
{
public string ApplicationId { get; set; } = "MyGame";
public int ListenPort { get; set; } = 55237;
public QuicTransportConfiguration QuicConfiguration { get; set; } = new()
{
ServerCertificate = X509CertificateLoader.LoadPkcs12FromFile("server.pfx", "secret"),
};
public string CertificateStorePath { get; set; }
public string DataFolder => Path.Combine(AppContext.BaseDirectory, "data");
}
DataFolder is the folder for the server's own files. When it is null, the executable's folder
is used. A relative CertificateStorePath is taken from the data folder.
The generated certificate
Without a QuicConfiguration, the server makes a self-signed certificate the first time it starts.
It is:
- an elliptic-curve P-256 key, with the subject
CN=<ApplicationId> Dev; - valid for a year from the day it is made;
- stored without a password at
certs/quic-dev-cert.pfxin the data folder.CertificateStorePathreplacescerts.
On later starts the server loads that file, so the certificate stays the same, and clients that remember it keep trusting the server. Nothing renews it: a file that has run out of date is still loaded as it is. To get a new certificate, delete the file. Clients that remember the old one will then refuse the server, so this is a change of identity.
This certificate is for development and a LAN. For a server on the internet, give the server a
certificate of your own through QuicConfiguration; see Server certificates.
A QuicConfiguration without a ServerCertificate stops the server at startup with an
InvalidOperationException.
Changing the host
ServerHost has two methods a subclass can override:
Configure(IServiceCollection)registers your own services. It runs after the registrations the host makes, so a service registered here replaces a scanned one of the same type.ConfigureHost(IHostBuilder)changes the host itself, which is where logging goes. See Logging.
using BSGameLib.Server;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
public class MyServerHost(IServerSettings settings) : ServerHost(settings)
{
protected override void Configure(IServiceCollection services) =>
services.AddSingleton<WorldClock>();
protected override void ConfigureHost(IHostBuilder builder) =>
builder.ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Debug));
}
public class WorldClock
{
public long Now => Environment.TickCount64;
}
Program then runs your host instead:
using BSGameLib.Server;
using var host = new MyServerHost(new ServerSettings("MyGame"));
host.Run();