Class ServerViewModel
- Namespace
- McServerLauncher.ViewModels
- Assembly
- McServerLauncher.dll
The crossplay half of ServerViewModel: Geyser, the Bedrock tunnel and the address.
public class ServerViewModel : ObservableObject, INotifyPropertyChanged, INotifyPropertyChanging
- Inheritance
-
ServerViewModel
- Implements
- Inherited Members
Remarks
Split out because the file had reached two thousand lines carrying the process, the console, the players, the ports, the tunnels, crossplay, the backups, Java and the notifications. This is the part that has grown most and is likeliest to grow again, and it is a closed subject: everything here is about one question, and nothing outside it needs any of these members.
A move, not a rewrite. The class was already partial, so not one instruction changed — which is what makes it safe to do at all, and why the whole test suite must give the identical result.
Constructors
ServerViewModel(ServerConfig)
public ServerViewModel(ServerConfig config)
Parameters
configServerConfig
Properties
AddToWhitelistCommand
Gets an IAsyncRelayCommand instance wrapping McServerLauncher.ViewModels.ServerViewModel.AddToWhitelist().
[ExcludeFromCodeCoverage]
public IAsyncRelayCommand AddToWhitelistCommand { get; }
Property Value
Backups
public ServerBackupsViewModel Backups { get; }
Property Value
BanPlayerCommand
Gets an IAsyncRelayCommand<T> instance wrapping BanPlayer(string).
[ExcludeFromCodeCoverage]
public IAsyncRelayCommand<string?> BanPlayerCommand { get; }
Property Value
BannedPlayers
Banned players (banned-players.json).
public ObservableCollection<string> BannedPlayers { get; }
Property Value
BedrockHost
The Bedrock host and port, shown separately. Null when there is no Bedrock tunnel.
[ExcludeFromCodeCoverage]
public string? BedrockHost { get; set; }
Property Value
BedrockLocalPortText
The local UDP port Geyser listens on. Known from the moment crossplay is set up.
public string BedrockLocalPortText { get; }
Property Value
BedrockPortText
[ExcludeFromCodeCoverage]
public string? BedrockPortText { get; set; }
Property Value
BedrockPortsInUse
The Bedrock ports the other servers have already been given.
public Func<IEnumerable<int>>? BedrockPortsInUse { get; set; }
Property Value
Remarks
Supplied by MainViewModel, which is the only thing that knows the other servers exist.
It matters because the free-port search asks the operating system which UDP ports are
bound right now: set crossplay up on two stopped servers and both are handed 19132,
and the collision only shows up later as the second Geyser failing to bind.
BedrockState
How far along the Bedrock address is. Drives the explanation under the panel.
[ExcludeFromCodeCoverage]
public BedrockAddressState BedrockState { get; set; }
Property Value
BedrockStateText
One line saying what is happening, so the panel is never blank without a reason.
public string BedrockStateText { get; }
Property Value
CanStart
public bool CanStart { get; }
Property Value
CanStop
public bool CanStop { get; }
Property Value
ClearConsoleCommand
Gets an IRelayCommand instance wrapping McServerLauncher.ViewModels.ServerViewModel.ClearConsole().
[ExcludeFromCodeCoverage]
public IRelayCommand ClearConsoleCommand { get; }
Property Value
CommandHelp
Common commands with their explanation (for the console help).
public IReadOnlyList<CommandHelp> CommandHelp { get; }
Property Value
CommandText
[ExcludeFromCodeCoverage]
public string CommandText { get; set; }
Property Value
Config
public ServerConfig Config { get; }
Property Value
ConnectedPlayers
Players connected right now (live, read from the console).
public ObservableCollection<string> ConnectedPlayers { get; }
Property Value
ConsoleFilter
[ExcludeFromCodeCoverage]
public string ConsoleFilter { get; set; }
Property Value
ConsoleKinds
One switch per kind of line, in the order they appear along the top of the console.
public IReadOnlyList<ConsoleKindFilter> ConsoleKinds { get; }
Property Value
Remarks
Ordered by how much they matter rather than by the enum, so the two that make somebody open the console at all come first and are never the ones that wrap out of sight.
ConsoleLines
Lines of the embedded console (server stdout/stderr + the launcher's own).
public BulkObservableCollection<ConsoleLine> ConsoleLines { get; }
Property Value
CopyBedrockAddressCommand
Gets an IAsyncRelayCommand instance wrapping McServerLauncher.ViewModels.ServerViewModel.CopyBedrockAddress().
[ExcludeFromCodeCoverage]
public IAsyncRelayCommand CopyBedrockAddressCommand { get; }
Property Value
CopyTunnelAddressCommand
Gets an IAsyncRelayCommand instance wrapping McServerLauncher.ViewModels.ServerViewModel.CopyTunnelAddress().
[ExcludeFromCodeCoverage]
public IAsyncRelayCommand CopyTunnelAddressCommand { get; }
Property Value
CpuSeries
[ExcludeFromCodeCoverage]
public IReadOnlyList<double>? CpuSeries { get; set; }
Property Value
CpuText
[ExcludeFromCodeCoverage]
public string CpuText { get; set; }
Property Value
DeopPlayerCommand
Gets an IAsyncRelayCommand<T> instance wrapping DeopPlayer(string).
[ExcludeFromCodeCoverage]
public IAsyncRelayCommand<string?> DeopPlayerCommand { get; }
Property Value
GameVersionText
Minecraft version (empty until known).
public string GameVersionText { get; }
Property Value
HasBedrockAddress
True once there is a public Bedrock address worth showing.
public bool HasBedrockAddress { get; }
Property Value
HasIcon
public bool HasIcon { get; }
Property Value
HasIdleCountdown
True while there is a countdown to show.
public bool HasIdleCountdown { get; }
Property Value
IdleCountdownText
How long until the empty server stops itself, or null when nothing is counting.
[ExcludeFromCodeCoverage]
public string? IdleCountdownText { get; set; }
Property Value
Remarks
Only set while the clock is actually running, so the UI can bind its visibility straight to this: an idle countdown showing "0:00" on a server nobody configured to stop would be a lie.
IsCommandHelpOpen
[ExcludeFromCodeCoverage]
public bool IsCommandHelpOpen { get; set; }
Property Value
IsConsoleFiltered
True while anything at all is being hidden, so the UI can offer to undo it.
public bool IsConsoleFiltered { get; }
Property Value
IsCrossplayOn
Whether to show the Bedrock panel at all: the user asked for crossplay.
public bool IsCrossplayOn { get; }
Property Value
Remarks
Deliberately not "we successfully looked a tunnel up", which is what the panel used to be tied to. Everything the user needs in the first minute — the local port, and the fact that the app is still waiting on playit — is knowable before any lookup succeeds, and hiding the whole block until one did is what made a working server look like a broken one.
IsModded
public bool IsModded { get; }
Property Value
IsRunning
public bool IsRunning { get; }
Property Value
KickPlayerCommand
Gets an IAsyncRelayCommand<T> instance wrapping KickPlayer(string).
[ExcludeFromCodeCoverage]
public IAsyncRelayCommand<string?> KickPlayerCommand { get; }
Property Value
KnownPlayers
Players who have ever joined (usercache.json).
public ObservableCollection<string> KnownPlayers { get; }
Property Value
Mods
public ServerModsViewModel Mods { get; }
Property Value
MotdText
[ExcludeFromCodeCoverage]
public string MotdText { get; set; }
Property Value
Name
[ExcludeFromCodeCoverage]
public string Name { get; set; }
Property Value
NewWhitelistName
[ExcludeFromCodeCoverage]
public string NewWhitelistName { get; set; }
Property Value
OpPlayerCommand
Gets an IAsyncRelayCommand<T> instance wrapping OpPlayer(string).
[ExcludeFromCodeCoverage]
public IAsyncRelayCommand<string?> OpPlayerCommand { get; }
Property Value
OpPlayers
Operators (ops.json).
public ObservableCollection<string> OpPlayers { get; }
Property Value
OpenPlayitDashboardCommand
Gets an IRelayCommand instance wrapping McServerLauncher.ViewModels.ServerViewModel.OpenPlayitDashboard().
[ExcludeFromCodeCoverage]
public IRelayCommand OpenPlayitDashboardCommand { get; }
Property Value
PardonPlayerCommand
Gets an IAsyncRelayCommand<T> instance wrapping PardonPlayer(string).
[ExcludeFromCodeCoverage]
public IAsyncRelayCommand<string?> PardonPlayerCommand { get; }
Property Value
PlayerCountText
[ExcludeFromCodeCoverage]
public string PlayerCountText { get; set; }
Property Value
PlayitState
[ExcludeFromCodeCoverage]
public PlayitState PlayitState { get; set; }
Property Value
PlayitStatusText
[ExcludeFromCodeCoverage]
public string PlayitStatusText { get; set; }
Property Value
PortText
[ExcludeFromCodeCoverage]
public string PortText { get; set; }
Property Value
RamSeries
[ExcludeFromCodeCoverage]
public IReadOnlyList<double>? RamSeries { get; set; }
Property Value
RamText
[ExcludeFromCodeCoverage]
public string RamText { get; set; }
Property Value
RefreshPlayersCommand
Gets an IRelayCommand instance wrapping McServerLauncher.ViewModels.ServerViewModel.RefreshPlayers().
[ExcludeFromCodeCoverage]
public IRelayCommand RefreshPlayersCommand { get; }
Property Value
RemoveFromWhitelistCommand
Gets an IAsyncRelayCommand<T> instance wrapping RemoveFromWhitelist(string).
[ExcludeFromCodeCoverage]
public IAsyncRelayCommand<string?> RemoveFromWhitelistCommand { get; }
Property Value
RestartCommand
Gets an IAsyncRelayCommand instance wrapping McServerLauncher.ViewModels.ServerViewModel.Restart().
[ExcludeFromCodeCoverage]
public IAsyncRelayCommand RestartCommand { get; }
Property Value
SendCommandCommand
Gets an IRelayCommand instance wrapping McServerLauncher.ViewModels.ServerViewModel.SendCommand().
[ExcludeFromCodeCoverage]
public IRelayCommand SendCommandCommand { get; }
Property Value
ServerIcon
[ExcludeFromCodeCoverage]
public Bitmap? ServerIcon { get; set; }
Property Value
- Bitmap
ServerTypeBrush
Badge color per type (shared palette; unknown/future types fall back to gray).
public IBrush ServerTypeBrush { get; }
Property Value
- IBrush
ServerTypeText
Server type shown as a badge (Vanilla/Fabric/Forge, and any future type).
public string ServerTypeText { get; }
Property Value
ShowAllConsoleKindsCommand
Gets an IRelayCommand instance wrapping McServerLauncher.ViewModels.ServerViewModel.ShowAllConsoleKinds().
[ExcludeFromCodeCoverage]
public IRelayCommand ShowAllConsoleKindsCommand { get; }
Property Value
ShowTunnelWarning
[ExcludeFromCodeCoverage]
public bool ShowTunnelWarning { get; set; }
Property Value
SignalBrush
[ExcludeFromCodeCoverage]
public IBrush SignalBrush { get; set; }
Property Value
- IBrush
SignalHint
[ExcludeFromCodeCoverage]
public string SignalHint { get; set; }
Property Value
StartCommand
Gets an IAsyncRelayCommand instance wrapping McServerLauncher.ViewModels.ServerViewModel.Start().
[ExcludeFromCodeCoverage]
public IAsyncRelayCommand StartCommand { get; }
Property Value
State
[ExcludeFromCodeCoverage]
public ServerState State { get; set; }
Property Value
StatusBrush
[ExcludeFromCodeCoverage]
public IBrush StatusBrush { get; set; }
Property Value
- IBrush
StatusText
[ExcludeFromCodeCoverage]
public string StatusText { get; set; }
Property Value
StopCommand
Gets an IAsyncRelayCommand instance wrapping McServerLauncher.ViewModels.ServerViewModel.Stop().
[ExcludeFromCodeCoverage]
public IAsyncRelayCommand StopCommand { get; }
Property Value
TogglePlayitCommand
Gets an IAsyncRelayCommand instance wrapping McServerLauncher.ViewModels.ServerViewModel.TogglePlayit().
[ExcludeFromCodeCoverage]
public IAsyncRelayCommand TogglePlayitCommand { get; }
Property Value
TunnelAddress
[ExcludeFromCodeCoverage]
public string? TunnelAddress { get; set; }
Property Value
UptimeText
[ExcludeFromCodeCoverage]
public string UptimeText { get; set; }
Property Value
UseCommandCommand
Gets an IRelayCommand<T> instance wrapping UseCommand(CommandHelp).
[ExcludeFromCodeCoverage]
public IRelayCommand<CommandHelp?> UseCommandCommand { get; }
Property Value
VisibleConsoleLines
The lines currently shown in the console UI: all of ConsoleLines when nothing is filtered, or the matching subset (kept in order, updated incrementally as new lines arrive) while a search is typed or a category is switched off.
public BulkObservableCollection<ConsoleLine> VisibleConsoleLines { get; }
Property Value
WhitelistEnabled
[ExcludeFromCodeCoverage]
public bool WhitelistEnabled { get; set; }
Property Value
WhitelistPlayers
Players currently in the whitelist (names).
public ObservableCollection<string> WhitelistPlayers { get; }
Property Value
Methods
CreateTunnelAsync(string)
Creates (if it doesn't exist) the Playit tunnel for this server's port, using the write key. Messages are shown in the server's console.
public Task CreateTunnelAsync(string writeKey)
Parameters
writeKeystring
Returns
RefreshConsoleColours()
Repaints the console and its switches after the colours change in the settings.
public void RefreshConsoleColours()
Remarks
The lines themselves get their colour through a converter, so nothing here has to hold a brush per line. Rebuilding the visible list is what makes them ask again: it is a single Reset, the items are re-created, and the converter runs with the new settings.
RefreshFromDisk()
Re-reads data from disk (after editing server.properties).
public void RefreshFromDisk()
SetUpBedrockModContentAsync()
Installs Hydraulic and Fabric API, so Bedrock players see what the mods add.
public Task SetUpBedrockModContentAsync()
Returns
Remarks
The flag is only set once the install has actually succeeded. A server remembering it has this when the download failed would leave Bedrock players staring at invisible blocks with the app insisting it was handled.
SetUpCrossplayAsync(string?)
Installs Geyser and Floodgate, creates the Bedrock tunnel and points Geyser at it.
public Task SetUpCrossplayAsync(string? playitKey)
Parameters
playitKeystring
Returns
Remarks
The order matters. The tunnel has to exist before the config is written, because the one value Geyser cannot work out for itself is the tunnel's public port — and writing the config first would leave it advertising the wrong one until something happened to rewrite it.
SetUpMultiVersionAsync()
Installs ViaVersion and ViaBackwards, so other Minecraft versions can join.
public Task SetUpMultiVersionAsync()
Returns
Remarks
Nothing to configure and no tunnel involved: both plugins work as installed. The flag is only set once the install has actually succeeded — a server remembering it has them when the download failed would turn players away and show no reason for it.
ShutdownAsync()
Stops the server when the app closes. Does NOT touch the Playit service (keeps running in the background).
public Task ShutdownAsync()
Returns
Events
ConfigChanged
Raised when something persistable about the server changes (to save).
public event Action? ConfigChanged