Table of Contents

Class ServerConfig

Namespace
McServerLauncher.Models
Assembly
McServerLauncher.dll

Persisted data of a Minecraft server registered in the application. Stored in %APPDATA%\McServerLauncher\servers.json.

public class ServerConfig : ObservableObject, INotifyPropertyChanged, INotifyPropertyChanging
Inheritance
ServerConfig
Implements
Inherited Members

Remarks

It announces its own changes, which is the whole reason it is not a plain object. The view models and the edit dialog share one instance: the dialog writes into the very config the cards are showing. While this was a POCO, nothing derived from it ever recomputed, so converting a server or moving it to another Minecraft version changed the disk and left the app describing what the folder used to be until it was restarted. Every attempted fix was a method somebody had to remember to call.

Being observable does not change what is written: reflection-based System.Text.Json serializes public instance properties, the generated properties keep the exact names the old auto-properties had, and ObservableObject contributes only events. The one thing that is not promised is the order of the keys in the file, which nothing reads positionally. See ServerConfigFormatTests, which holds all of that down.

Never give this class a Clone built on MemberwiseClone: it would copy the PropertyChanged delegate too, and the copy would raise changes at the original's subscribers. Clone() is field-by-field for the same reason.

Properties

AutoBackupEnabled

Whether backups are also made at intervals while the server is running.

[ExcludeFromCodeCoverage]
public bool AutoBackupEnabled { get; set; }

Property Value

bool

BackupIntervalMinutes

Minutes between automatic backups while the server is running. Clamped when it is read (see BackupSchedule), so a hand-edited zero cannot mean "on every tick".

[ExcludeFromCodeCoverage]
public int BackupIntervalMinutes { get; set; }

Property Value

int

BackupRetention

How many automatic backups to keep — the ones made on starting, on stopping, and by the clock. Older ones are deleted after each new one.

[ExcludeFromCodeCoverage]
public int BackupRetention { get; set; }

Property Value

int

BackupsEnabled

Whether a zip backup of the world is made before starting and after an explicit stop.

[ExcludeFromCodeCoverage]
public bool BackupsEnabled { get; set; }

Property Value

bool

BedrockModContentEnabled

Whether Hydraulic is installed, so Bedrock players see what the mods add.

[ExcludeFromCodeCoverage]
public bool BedrockModContentEnabled { get; set; }

Property Value

bool

Remarks

Separate from CrossplayEnabled because it answers a different question. Geyser gets Bedrock players in; without this they arrive to a world whose modded blocks and items they cannot see. Fabric only — see HydraulicService.

BedrockPort

The local UDP port Geyser listens on. 0 until crossplay is set up.

[ExcludeFromCodeCoverage]
public int BedrockPort { get; set; }

Property Value

int

Remarks

UDP, and a different namespace from the Java port: this one can be 19132 while some other program holds TCP 19132, and vice versa.

CrossplayEnabled

Whether Bedrock players (phone, console, Windows 10/11) can join this server too.

[ExcludeFromCodeCoverage]
public bool CrossplayEnabled { get; set; }

Property Value

bool

Remarks

Remembered rather than set up once and forgotten, because it is not a one-off action: it needs a second tunnel to keep existing, and Geyser has to keep advertising that tunnel's public port. Both can drift, and only something that knows the server is meant to be crossplay can put them back.

ExtraJvmArgs

Extra JVM arguments (optional, e.g. GC flags).

[ExcludeFromCodeCoverage]
public string ExtraJvmArgs { get; set; }

Property Value

string

FolderPath

Server root folder (where the .jar and server.properties live).

[ExcludeFromCodeCoverage]
public string FolderPath { get; set; }

Property Value

string

ForgeArgs

Modern Forge (1.17+) and every NeoForge build have no runnable jar; they are launched via an args file under libraries/<loader-root>/<id>/{win,unix}_args.txt. When this holds that id — "1.20.1-47.2.0" for Forge, "21.1.248" for NeoForge — the launcher uses the args file instead of "-jar". Empty means the classic "-jar JarFile" launch (Vanilla, Fabric, old Forge ≤1.16.5).

The name stays ForgeArgs even though it now covers both: it is the key in every existing servers.json, and renaming it would leave installed Forge servers unable to start.

[ExcludeFromCodeCoverage]
public string ForgeArgs { get; set; }

Property Value

string

GameVersion

Minecraft game version (e.g. 1.20.1).

[ExcludeFromCodeCoverage]
public string GameVersion { get; set; }

Property Value

string

Id

Stable identifier (so we don't depend on the name, which may change).

[ExcludeFromCodeCoverage]
public string Id { get; set; }

Property Value

string

IdleShutdownMinutes

Minutes with nobody connected before the server stops itself. 0 means never.

[ExcludeFromCodeCoverage]
public int IdleShutdownMinutes { get; set; }

Property Value

int

Remarks

Zero is the default so no existing server changes behaviour on update: a server that used to stay up forever keeps doing exactly that until its owner asks for something else.

JarFile

Server .jar file name (relative to the folder). Defaults to server.jar.

[ExcludeFromCodeCoverage]
public string JarFile { get; set; }

Property Value

string

JarFullPath

Full path to the .jar combining folder + jar name.

[JsonIgnore]
public string JarFullPath { get; }

Property Value

string

JavaPath

Path to the Java executable. "java" uses the one on the PATH.

[ExcludeFromCodeCoverage]
public string JavaPath { get; set; }

Property Value

string

LastKnownSeed

The seed the server last printed when asked with seed. Null until it has been asked.

[ExcludeFromCodeCoverage]
public long? LastKnownSeed { get; set; }

Property Value

long?

Remarks

A fallback, not the source: the seed is read from the world's own files. It is kept because Minecraft has already moved it once (26.1 took it out of level.dat), and the answer the server gives to seed is the one thing that cannot go stale that way.

ManualBackupRetention

How many of the backups the user asked for to keep, counted separately.

[ExcludeFromCodeCoverage]
public int ManualBackupRetention { get; set; }

Property Value

int

Remarks

With a backup every hour, a single shared count would be full of automatic ones by the morning, and the copy somebody took by hand before trying something would be gone — which is the one backup they were sure they still had.

MaxRamGb

Maximum memory in GB (-Xmx), used in Manual mode. Same default the create dialog suggests.

[ExcludeFromCodeCoverage]
public int MaxRamGb { get; set; }

Property Value

int

MemoryMode

Whether the app sizes the memory (Automatic) or uses MinRamGb and MaxRamGb as typed.

[ExcludeFromCodeCoverage]
public MemoryMode? MemoryMode { get; set; }

Property Value

MemoryMode?

Remarks

Null on every server saved before the choice existed, and kept null rather than filled in: that is how the app tells "never chose" from "chose Automatic". Such a server runs as Automatic and shows a one-line notice that offers going back to its old numbers, which are still in MinRamGb and MaxRamGb because Automatic never writes them.

The extra JVM arguments outrank it: a server whose ExtraJvmArgs already size the heap or pick a collector runs as Manual whatever this says (MemoryProfile.Effective).

MinRamGb

Minimum memory in GB (-Xms), used in Manual mode. Same default the create dialog suggests.

[ExcludeFromCodeCoverage]
public int MinRamGb { get; set; }

Property Value

int

ModLoaderVersion

Version of the mod loader (e.g. 0.16.2 for Fabric).

[ExcludeFromCodeCoverage]
public string ModLoaderVersion { get; set; }

Property Value

string

MultiVersionEnabled

Whether ViaVersion and ViaBackwards are installed, for joining from other versions.

[ExcludeFromCodeCoverage]
public bool MultiVersionEnabled { get; set; }

Property Value

bool

Remarks

Separate from CrossplayEnabled on purpose. Geyser does not need these to work, and a Java-only server benefits from them just as much: they are about which Minecraft versions may connect, not which edition.

Name

Display name of the server (e.g. "Survival", "Modded").

[ExcludeFromCodeCoverage]
public string Name { get; set; }

Property Value

string

Notifications

Per-server notification override, used only when UseCustomNotifications.

[ExcludeFromCodeCoverage]
public NotificationSettings? Notifications { get; set; }

Property Value

NotificationSettings

PlayitEnabled

Whether the Playit.gg integration is enabled for this server.

[ExcludeFromCodeCoverage]
public bool PlayitEnabled { get; set; }

Property Value

bool

PropertiesPath

Path to server.properties inside the server folder.

[JsonIgnore]
public string PropertiesPath { get; }

Property Value

string

TunnelAddress

Public tunnel address for this server. It is detected automatically when running playit, but it can also be typed/pasted by hand and is kept saved.

[ExcludeFromCodeCoverage]
public string? TunnelAddress { get; set; }

Property Value

string

Type

Type of the server (Vanilla, Fabric, Forge, Paper, NeoForge).

[ExcludeFromCodeCoverage]
public ServerType Type { get; set; }

Property Value

ServerType

UseCustomNotifications

When true, this server uses its own Notifications instead of the global notification settings. When false (default), the global settings apply.

[ExcludeFromCodeCoverage]
public bool UseCustomNotifications { get; set; }

Property Value

bool

WakeOnDemand

While stopped, answer on the server's port so that someone trying to join starts it.

[ExcludeFromCodeCoverage]
public bool WakeOnDemand { get; set; }

Property Value

bool

Remarks

Off by default: it opens a listening socket, and nobody should end up with one without having asked. Pairs with IdleShutdownMinutes — sleep when empty, wake on demand — but each half works on its own.

WakeOnlyForWhitelist

When the server's whitelist is on, only somebody on it (or an operator) can wake it.

[ExcludeFromCodeCoverage]
public bool WakeOnlyForWhitelist { get; set; }

Property Value

bool

Remarks

On by default. Behind a Playit tunnel the sleeping port is on the internet, and scanners that look for Minecraft servers try to log in as a matter of routine: without this, each of them started the server — and a pre-start backup with it. A server with a whitelist has already said who it is for, so that is who gets to wake it. Without a whitelist this changes nothing, and the owner can switch it off to let anyone wake it regardless.