From e068a1f0fa031602d88f315e069c2123d272a5f7 Mon Sep 17 00:00:00 2001 From: Dominion Date: Fri, 31 Mar 2023 10:16:29 -0400 Subject: [PATCH 1/6] Add a missing Dispose call --- tests/Tgstation.Server.Tests/Instance/ByondTest.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/Tgstation.Server.Tests/Instance/ByondTest.cs b/tests/Tgstation.Server.Tests/Instance/ByondTest.cs index 92dca4144d..f2e69aeee4 100644 --- a/tests/Tgstation.Server.Tests/Instance/ByondTest.cs +++ b/tests/Tgstation.Server.Tests/Instance/ByondTest.cs @@ -1,5 +1,4 @@ -using Castle.Core.Logging; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -103,6 +102,8 @@ namespace Tgstation.Server.Tests.Instance new DefaultIOManager(new AssemblyInformationProvider()), Mock.Of>()); + using var windowsByondInstaller = byondInstaller as WindowsByondInstaller; + // get the bytes for stable using var stableBytesMs = await byondInstaller.DownloadVersion(TestVersion, cancellationToken); From e91fda17267aa44414062add12752eecbf65ec1f Mon Sep 17 00:00:00 2001 From: Dominion Date: Fri, 31 Mar 2023 11:05:33 -0400 Subject: [PATCH 2/6] Downgrade WaitForInputIdle errors to trace --- src/Tgstation.Server.Host/System/Process.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tgstation.Server.Host/System/Process.cs b/src/Tgstation.Server.Host/System/Process.cs index 7ef2eeed3f..4a7225df13 100644 --- a/src/Tgstation.Server.Host/System/Process.cs +++ b/src/Tgstation.Server.Host/System/Process.cs @@ -112,7 +112,7 @@ namespace Tgstation.Server.Host.System } catch (Exception ex) { - logger.LogDebug(ex, "Error on WaitForInputIdle()!"); + logger.LogTrace(ex, "WaitForInputIdle() failed, this is normal."); } }, default, // DCT: None available From 824850c35103ca8e23d979a8afb0e576b81018de Mon Sep 17 00:00:00 2001 From: Dominion Date: Fri, 31 Mar 2023 11:35:10 -0400 Subject: [PATCH 3/6] Add dd.exe support --- .../Components/Byond/ByondExecutableLock.cs | 9 ++- .../Components/Byond/ByondInstallerBase.cs | 11 ++-- .../Components/Byond/ByondManager.cs | 15 +++-- .../Components/Byond/IByondExecutableLock.cs | 5 ++ .../Components/Byond/IByondInstaller.cs | 26 ++++++--- .../Components/Byond/PosixByondInstaller.cs | 38 ++++++++++--- .../Components/Byond/WindowsByondInstaller.cs | 56 +++++++++++++++++-- .../Session/SessionControllerFactory.cs | 22 ++++---- .../Byond/TestPosixByondInstaller.cs | 4 +- 9 files changed, 144 insertions(+), 42 deletions(-) diff --git a/src/Tgstation.Server.Host/Components/Byond/ByondExecutableLock.cs b/src/Tgstation.Server.Host/Components/Byond/ByondExecutableLock.cs index 7b83fd5f8d..e6f83363a9 100644 --- a/src/Tgstation.Server.Host/Components/Byond/ByondExecutableLock.cs +++ b/src/Tgstation.Server.Host/Components/Byond/ByondExecutableLock.cs @@ -20,6 +20,9 @@ namespace Tgstation.Server.Host.Components.Byond /// public string DreamMakerPath { get; } + /// + public bool SupportsCli { get; } + /// /// The for the . /// @@ -44,13 +47,15 @@ namespace Tgstation.Server.Host.Components.Byond /// The value of . /// The value of . /// The value of . + /// The value of . public ByondExecutableLock( IIOManager ioManager, SemaphoreSlim trustedFileSemaphore, Version version, string dreamDaemonPath, string dreamMakerPath, - string trustedFilePath) + string trustedFilePath, + bool supportsCli) { this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager)); this.trustedFileSemaphore = trustedFileSemaphore ?? throw new ArgumentNullException(nameof(trustedFileSemaphore)); @@ -58,6 +63,8 @@ namespace Tgstation.Server.Host.Components.Byond DreamDaemonPath = dreamDaemonPath ?? throw new ArgumentNullException(nameof(dreamDaemonPath)); DreamMakerPath = dreamMakerPath ?? throw new ArgumentNullException(nameof(dreamMakerPath)); this.trustedFilePath = trustedFilePath ?? throw new ArgumentNullException(nameof(trustedFilePath)); + + SupportsCli = supportsCli; } // at one point in design, byond versions were to delete themselves if they weren't the active version diff --git a/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs b/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs index cbe76ef1b4..67e80cda1f 100644 --- a/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs +++ b/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs @@ -18,9 +18,6 @@ namespace Tgstation.Server.Host.Components.Byond /// const string CacheDirectoryName = "cache"; - /// - public abstract string DreamDaemonName { get; } - /// public abstract string DreamMakerName { get; } @@ -53,6 +50,9 @@ namespace Tgstation.Server.Host.Components.Byond Logger = logger ?? throw new ArgumentNullException(nameof(logger)); } + /// + public abstract string GetDreamDaemonName(Version version, out bool supportsCli); + /// public async Task CleanCache(CancellationToken cancellationToken) { @@ -77,7 +77,10 @@ namespace Tgstation.Server.Host.Components.Byond } /// - public abstract Task InstallByond(string path, Version version, CancellationToken cancellationToken); + public abstract Task InstallByond(Version version, string path, CancellationToken cancellationToken); + + /// + public abstract Task UpgradeInstallation(Version version, string path, CancellationToken cancellationToken); /// public Task DownloadVersion(Version version, CancellationToken cancellationToken) diff --git a/src/Tgstation.Server.Host/Components/Byond/ByondManager.cs b/src/Tgstation.Server.Host/Components/Byond/ByondManager.cs index 0476292a5f..7aa63f18d2 100644 --- a/src/Tgstation.Server.Host/Components/Byond/ByondManager.cs +++ b/src/Tgstation.Server.Host/Components/Byond/ByondManager.cs @@ -166,7 +166,7 @@ namespace Tgstation.Server.Host.Components.Byond ioManager.ResolvePath( ioManager.ConcatPath( binPathForVersion, - byondInstaller.DreamDaemonName)), + byondInstaller.GetDreamDaemonName(versionToUse, out var supportsCli))), ioManager.ResolvePath( ioManager.ConcatPath( binPathForVersion, @@ -175,7 +175,8 @@ namespace Tgstation.Server.Host.Components.Byond ioManager.ConcatPath( byondInstaller.PathToUserByondFolder, CfgDirectoryName, - TrustedDmbFileName))); + TrustedDmbFileName)), + supportsCli); } /// @@ -211,6 +212,8 @@ namespace Tgstation.Server.Host.Components.Byond await ioManager.CreateDirectory(byondDirectory, cancellationToken); var directories = await ioManager.GetDirectories(byondDirectory, cancellationToken); + var installedVersionPaths = new Dictionary(); + async Task ReadVersion(string path) { var versionFile = ioManager.ConcatPath(path, VersionFileName); @@ -231,6 +234,7 @@ namespace Tgstation.Server.Host.Components.Byond { logger.LogDebug("Adding detected BYOND version {0}...", key); installedVersions.Add(key, Task.CompletedTask); + installedVersionPaths.Add(ioManager.ResolvePath(key), version); return; } } @@ -238,7 +242,10 @@ namespace Tgstation.Server.Host.Components.Byond await ioManager.DeleteDirectory(path, cancellationToken); } - await Task.WhenAll(directories.Select(x => ReadVersion(x))); + await Task.WhenAll(directories.Select(ReadVersion)); + + logger.LogTrace("Upgrading BYOND installations..."); + await Task.WhenAll(installedVersionPaths.Select(kvp => byondInstaller.UpgradeInstallation(kvp.Value, kvp.Key, cancellationToken))); var activeVersionBytes = await activeVersionBytesTask; if (activeVersionBytes != null) @@ -339,7 +346,7 @@ namespace Tgstation.Server.Host.Components.Byond await ioManager.ZipToDirectory(extractPath, versionZipStream, cancellationToken); } - await byondInstaller.InstallByond(extractPath, version, cancellationToken); + await byondInstaller.InstallByond(version, extractPath, cancellationToken); // make sure to do this last because this is what tells us we have a valid version in the future await ioManager.WriteAllBytes( diff --git a/src/Tgstation.Server.Host/Components/Byond/IByondExecutableLock.cs b/src/Tgstation.Server.Host/Components/Byond/IByondExecutableLock.cs index 200aca5a71..ef90080042 100644 --- a/src/Tgstation.Server.Host/Components/Byond/IByondExecutableLock.cs +++ b/src/Tgstation.Server.Host/Components/Byond/IByondExecutableLock.cs @@ -24,6 +24,11 @@ namespace Tgstation.Server.Host.Components.Byond /// string DreamMakerPath { get; } + /// + /// If supports being run as a command-line application. + /// + bool SupportsCli { get; } + /// /// Call if, during a detach, this version should not be deleted. /// diff --git a/src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs b/src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs index ad1edcc08f..87e8468e44 100644 --- a/src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs +++ b/src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs @@ -10,11 +10,6 @@ namespace Tgstation.Server.Host.Components.Byond /// interface IByondInstaller { - /// - /// Get the file name of the DreamDaemon executable. - /// - string DreamDaemonName { get; } - /// /// Get the file name of the DreamMaker executable. /// @@ -25,6 +20,14 @@ namespace Tgstation.Server.Host.Components.Byond /// string PathToUserByondFolder { get; } + /// + /// Get the file name of the DreamDaemon executable. + /// + /// The of BYOND to select the executable name for. + /// Whether or not the returned path supports being run as a command-line application. + /// The file name of the DreamDaemon executable. + public string GetDreamDaemonName(Version version, out bool supportsCli); + /// /// Download a given BYOND . /// @@ -36,11 +39,20 @@ namespace Tgstation.Server.Host.Components.Byond /// /// Does actions necessary to get an extracted BYOND installation working. /// - /// The path to the BYOND installation. /// The of BYOND being installed. + /// The path to the BYOND installation. /// The for the operation. /// A representing the running operation. - Task InstallByond(string path, Version version, CancellationToken cancellationToken); + Task InstallByond(Version version, string path, CancellationToken cancellationToken); + + /// + /// Does actions necessary to get upgrade a BYOND version installed by a previous version of TGS. + /// + /// The of BYOND being installed. + /// The path to the BYOND installation. + /// The for the operation. + /// A representing the running operation. + Task UpgradeInstallation(Version version, string path, CancellationToken cancellationToken); /// /// Attempts to cleans the BYOND cache folder for the system. diff --git a/src/Tgstation.Server.Host/Components/Byond/PosixByondInstaller.cs b/src/Tgstation.Server.Host/Components/Byond/PosixByondInstaller.cs index 00fd577788..876ed37aa7 100644 --- a/src/Tgstation.Server.Host/Components/Byond/PosixByondInstaller.cs +++ b/src/Tgstation.Server.Host/Components/Byond/PosixByondInstaller.cs @@ -30,9 +30,6 @@ namespace Tgstation.Server.Host.Components.Byond /// const string ShellScriptExtension = ".sh"; - /// - public override string DreamDaemonName => DreamDaemonExecutableName + ShellScriptExtension; - /// public override string DreamMakerName => DreamMakerExecutableName + ShellScriptExtension; @@ -66,13 +63,23 @@ namespace Tgstation.Server.Host.Components.Byond } /// - public override Task InstallByond(string path, Version version, CancellationToken cancellationToken) + public override string GetDreamDaemonName(Version version, out bool supportsCli) { - if (path == null) - throw new ArgumentNullException(nameof(path)); if (version == null) throw new ArgumentNullException(nameof(version)); + supportsCli = true; + return DreamDaemonExecutableName + ShellScriptExtension; + } + + /// + public override Task InstallByond(Version version, string path, CancellationToken cancellationToken) + { + if (version == null) + throw new ArgumentNullException(nameof(version)); + if (path == null) + throw new ArgumentNullException(nameof(path)); + // write the scripts for running the ting // need to add $ORIGIN to LD_LIBRARY_PATH const string StandardScript = "#!/bin/sh\nexport LD_LIBRARY_PATH=\"\\$ORIGIN:$LD_LIBRARY_PATH\"\nBASEDIR=$(dirname \"$0\")\nexec \"$BASEDIR/{0}\" \"$@\"\n"; @@ -89,12 +96,29 @@ namespace Tgstation.Server.Host.Components.Byond var basePath = IOManager.ConcatPath(path, ByondManager.BinPath); - var task = Task.WhenAll(WriteAndMakeExecutable(IOManager.ConcatPath(basePath, DreamDaemonName), dreamDaemonScript), WriteAndMakeExecutable(IOManager.ConcatPath(basePath, DreamMakerName), dreamMakerScript)); + var task = Task.WhenAll( + WriteAndMakeExecutable( + IOManager.ConcatPath(basePath, GetDreamDaemonName(version, out var _)), + dreamDaemonScript), + WriteAndMakeExecutable( + IOManager.ConcatPath(basePath, DreamMakerName), + dreamMakerScript)); postWriteHandler.HandleWrite(IOManager.ConcatPath(basePath, DreamDaemonExecutableName)); postWriteHandler.HandleWrite(IOManager.ConcatPath(basePath, DreamMakerExecutableName)); return task; } + + /// + public override Task UpgradeInstallation(Version version, string path, CancellationToken cancellationToken) + { + if (version == null) + throw new ArgumentNullException(nameof(version)); + if (path == null) + throw new ArgumentNullException(nameof(path)); + + return Task.CompletedTask; + } } } diff --git a/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs b/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs index 678e12347f..03d6b9389f 100644 --- a/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs +++ b/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs @@ -41,8 +41,10 @@ namespace Tgstation.Server.Host.Components.Byond /// const string ByondDXDir = "byond/directx"; - /// - public override string DreamDaemonName => "dreamdaemon.exe"; + /// + /// The file TGS uses to determine if dd.exe has been firewalled. + /// + const string TgsFirewalledDDFile = "TGSFirewalledDD"; /// public override string DreamMakerName => "dm.exe"; @@ -96,7 +98,17 @@ namespace Tgstation.Server.Host.Components.Byond public void Dispose() => semaphore.Dispose(); /// - public override Task InstallByond(string path, Version version, CancellationToken cancellationToken) + public override string GetDreamDaemonName(Version version, out bool supportsCli) + { + if (version == null) + throw new ArgumentNullException(nameof(version)); + + supportsCli = version.Major >= 515 && version.Minor >= 1598; + return supportsCli ? "dd.exe" : "dreamdaemon.exe"; + } + + /// + public override Task InstallByond(Version version, string path, CancellationToken cancellationToken) { var tasks = new List { @@ -105,11 +117,33 @@ namespace Tgstation.Server.Host.Components.Byond }; if (!generalConfiguration.SkipAddingByondFirewallException) - tasks.Add(AddDreamDaemonToFirewall(path, cancellationToken)); + tasks.Add(AddDreamDaemonToFirewall(version, path, cancellationToken)); return Task.WhenAll(tasks); } + /// + public override async Task UpgradeInstallation(Version version, string path, CancellationToken cancellationToken) + { + if (version == null) + throw new ArgumentNullException(nameof(version)); + if (path == null) + throw new ArgumentNullException(nameof(path)); + + if (generalConfiguration.SkipAddingByondFirewallException) + return; + + GetDreamDaemonName(version, out var usesDDExe); + if (!usesDDExe) + return; + + if (await IOManager.FileExists(IOManager.ConcatPath(path, TgsFirewalledDDFile), cancellationToken)) + return; + + Logger.LogInformation("BYOND Version {version} needs dd.exe added to firewall", version); + await AddDreamDaemonToFirewall(version, path, cancellationToken); + } + /// /// Creates the BYOND cfg file that prevents the trusted mode dialog from appearing when launching DreamDaemon. /// @@ -177,17 +211,21 @@ namespace Tgstation.Server.Host.Components.Byond /// /// Attempt to add the DreamDaemon executable as an exception to the Windows firewall. /// + /// The BYOND . /// The path to the BYOND installation. /// The for the operation. /// A representing the running operation. - async Task AddDreamDaemonToFirewall(string path, CancellationToken cancellationToken) + async Task AddDreamDaemonToFirewall(Version version, string path, CancellationToken cancellationToken) { + var dreamDaemonName = GetDreamDaemonName(version, out var supportsCli); + var dreamDaemonPath = IOManager.ResolvePath( IOManager.ConcatPath( path, ByondManager.BinPath, - DreamDaemonName)); + dreamDaemonName)); + Logger.LogInformation("Adding Windows Firewall exception for {path}...", dreamDaemonPath); try { using var netshProcess = processExecutor.LaunchProcess( @@ -210,6 +248,12 @@ namespace Tgstation.Server.Host.Components.Byond if (exitCode != 0) throw new JobException(ErrorCode.ByondDreamDaemonFirewallFail, new JobException($"Invalid exit code: {exitCode}")); + + if (supportsCli) + await IOManager.WriteAllBytes( + IOManager.ConcatPath(path, TgsFirewalledDDFile), + Array.Empty(), + cancellationToken); } catch (Exception ex) { diff --git a/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs b/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs index 9117f5eb5d..e938adeb17 100644 --- a/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs +++ b/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs @@ -282,23 +282,22 @@ namespace Tgstation.Server.Host.Components.Session Guid? logFileGuid = null; var arguments = String.Format( CultureInfo.InvariantCulture, - "{0} -port {1} -ports 1-65535 {2}-close -verbose -logself -{3} -{4}{5}{6} -params \"{7}\"", + "{0} -port {1} -ports 1-65535 {2}-close -verbose -{3} -{4}{5}{6} -params \"{7}\"", dmbProvider.DmbName, launchParameters.Port.Value, launchParameters.AllowWebClient.Value ? "-webclient " : String.Empty, SecurityWord(launchParameters.SecurityLevel.Value), VisibilityWord(launchParameters.Visibility.Value), - platformIdentifier.IsWindows - ? $" -log {logFileGuid = Guid.NewGuid()}" - : String.Empty, // Just use stdout on linux + !byondLock.SupportsCli + ? $" -logself -log {logFileGuid = Guid.NewGuid()}" + : !platformIdentifier.IsWindows // Just use stdout on if CLI is supported + ? " -logself" + : String.Empty, // Windows doesn't output anything to dd.exe if -logself is set? launchParameters.StartProfiler.Value ? " -profile" : String.Empty, parameters); - // See https://github.com/tgstation/tgstation-server/issues/719 - var noShellExecute = !platformIdentifier.IsWindows; - if (!apiValidate && dmbProvider.CompileJob.DMApiVersion == null) logger.LogDebug("Session will have no DMAPI support!"); @@ -307,14 +306,15 @@ namespace Tgstation.Server.Host.Components.Session byondLock.DreamDaemonPath, dmbProvider.Directory, arguments, - noShellExecute, - noShellExecute, - noShellExecute: noShellExecute); + byondLock.SupportsCli, + byondLock.SupportsCli, + byondLock.SupportsCli); + var cliSupported = byondLock.SupportsCli; async Task GetDDOutput() { // DCT x2: None available - if (!platformIdentifier.IsWindows) + if (cliSupported) return await process.GetCombinedOutput(default); var logFilePath = ioManager.ConcatPath(dmbProvider.Directory, logFileGuid.ToString()); diff --git a/tests/Tgstation.Server.Host.Tests/Components/Byond/TestPosixByondInstaller.cs b/tests/Tgstation.Server.Host.Tests/Components/Byond/TestPosixByondInstaller.cs index de7d2fc05c..558ccf0faf 100644 --- a/tests/Tgstation.Server.Host.Tests/Components/Byond/TestPosixByondInstaller.cs +++ b/tests/Tgstation.Server.Host.Tests/Components/Byond/TestPosixByondInstaller.cs @@ -65,9 +65,9 @@ namespace Tgstation.Server.Host.Components.Byond.Tests const string FakePath = "fake"; await Assert.ThrowsExceptionAsync(() => installer.InstallByond(null, null, default)); - await Assert.ThrowsExceptionAsync(() => installer.InstallByond(FakePath, null, default)); + await Assert.ThrowsExceptionAsync(() => installer.InstallByond(new Version(123,252345), null, default)); - await installer.InstallByond(FakePath, new Version(511, 1385), default); + await installer.InstallByond(new Version(511, 1385), FakePath, default); mockPostWriteHandler.Verify(x => x.HandleWrite(It.IsAny()), Times.Exactly(4)); } From e40908df1466e11fd156f857597f5545e16e5810 Mon Sep 17 00:00:00 2001 From: Dominion Date: Fri, 31 Mar 2023 11:35:25 -0400 Subject: [PATCH 4/6] Fix chat commands not handling extra spaces well --- src/Tgstation.Server.Host/Components/Chat/ChatManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs b/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs index 019e188cfa..c57099f5a8 100644 --- a/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs +++ b/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs @@ -679,7 +679,7 @@ namespace Tgstation.Server.Host.Components.Chat message.User.Channel.IsAdminChannel = mappingChannelRepresentation.IsAdminChannel; } - var splits = new List(message.Content.Trim().Split(' ')); + var splits = new List(message.Content.Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries)); var address = splits[0]; if (address.Length > 1 && (address.Last() == ':' || address.Last() == ',')) address = address[0..^1]; From 16205b138bd5b69a7982d5aa3609bcb5b60152d0 Mon Sep 17 00:00:00 2001 From: Dominion Date: Fri, 31 Mar 2023 11:36:15 -0400 Subject: [PATCH 5/6] Version bump to 5.6.0 --- build/Version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Version.props b/build/Version.props index fe83ec82ae..75afbdc50b 100644 --- a/build/Version.props +++ b/build/Version.props @@ -3,7 +3,7 @@ - 5.5.0 + 5.6.0 4.4.0 9.8.1 10.2.0 From 556f270b28980838b8230d628ec436205643678b Mon Sep 17 00:00:00 2001 From: Dominion Date: Fri, 31 Mar 2023 11:49:45 -0400 Subject: [PATCH 6/6] `public` is not valid in an interface wth? --- src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs b/src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs index 87e8468e44..cc49610e64 100644 --- a/src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs +++ b/src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs @@ -26,7 +26,7 @@ namespace Tgstation.Server.Host.Components.Byond /// The of BYOND to select the executable name for. /// Whether or not the returned path supports being run as a command-line application. /// The file name of the DreamDaemon executable. - public string GetDreamDaemonName(Version version, out bool supportsCli); + string GetDreamDaemonName(Version version, out bool supportsCli); /// /// Download a given BYOND .