Fix OpenDream engine parameter encoding

This commit is contained in:
Jordan Dominion
2023-10-15 15:39:36 -04:00
parent a1f1dbc58b
commit 0fefec9f57
3 changed files with 83 additions and 45 deletions
@@ -1,9 +1,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Api.Models.Internal;
@@ -14,25 +12,25 @@ namespace Tgstation.Server.Host.Components.Engine
/// <summary>
/// Implementation of <see cref="IEngineInstallation"/> for <see cref="EngineType.Byond"/>.
/// </summary>
sealed class ByondInstallation : IEngineInstallation
sealed class ByondInstallation : EngineInstallationBase
{
/// <inheritdoc />
public EngineVersion Version { get; }
public override EngineVersion Version { get; }
/// <inheritdoc />
public string ServerExePath { get; }
public override string ServerExePath { get; }
/// <inheritdoc />
public string CompilerExePath { get; }
public override string CompilerExePath { get; }
/// <inheritdoc />
public bool PromptsForNetworkAccess { get; }
public override bool PromptsForNetworkAccess { get; }
/// <inheritdoc />
public bool HasStandardOutput { get; }
public override bool HasStandardOutput { get; }
/// <inheritdoc />
public Task InstallationTask { get; }
public override Task InstallationTask { get; }
/// <summary>
/// If map threads are supported by the <see cref="Version"/>.
@@ -103,7 +101,7 @@ namespace Tgstation.Server.Host.Components.Engine
}
/// <inheritdoc />
public string FormatServerArguments(
public override string FormatServerArguments(
IDmbProvider dmbProvider,
IReadOnlyDictionary<string, string> parameters,
DreamDaemonLaunchParameters launchParameters,
@@ -113,10 +111,7 @@ namespace Tgstation.Server.Host.Components.Engine
ArgumentNullException.ThrowIfNull(parameters);
ArgumentNullException.ThrowIfNull(launchParameters);
var parametersString = String.Join('&', parameters.Select(kvp => $"{HttpUtility.UrlEncode(kvp.Key)}={HttpUtility.UrlEncode(kvp.Value)}"));
if (!String.IsNullOrEmpty(launchParameters.AdditionalParameters))
parametersString = $"{parametersString}&{launchParameters.AdditionalParameters}";
var parametersString = EncodeParameters(parameters, launchParameters);
var arguments = String.Format(
CultureInfo.InvariantCulture,
@@ -142,7 +137,7 @@ namespace Tgstation.Server.Host.Components.Engine
}
/// <inheritdoc />
public string FormatCompilerArguments(string dmePath)
public override string FormatCompilerArguments(string dmePath)
=> $"-clean \"{dmePath ?? throw new ArgumentNullException(nameof(dmePath))}\"";
}
}
@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.Components.Deployment;
namespace Tgstation.Server.Host.Components.Engine
{
/// <inheritdoc />
abstract class EngineInstallationBase : IEngineInstallation
{
/// <inheritdoc />
public abstract EngineVersion Version { get; }
/// <inheritdoc />
public abstract string ServerExePath { get; }
/// <inheritdoc />
public abstract string CompilerExePath { get; }
/// <inheritdoc />
public abstract bool HasStandardOutput { get; }
/// <inheritdoc />
public abstract bool PromptsForNetworkAccess { get; }
/// <inheritdoc />
public abstract Task InstallationTask { get; }
/// <summary>
/// Encode given parameters for passing as world.params on the command line.
/// </summary>
/// <param name="parameters"><see cref="IReadOnlyDictionary{TKey, TValue}"/> of parameters to encode.</param>
/// <param name="launchParameters">The active <see cref="DreamDaemonLaunchParameters"/>.</param>
/// <returns>The formatted parameters <see cref="string"/>.</returns>
protected static string EncodeParameters(
IReadOnlyDictionary<string, string> parameters,
DreamDaemonLaunchParameters launchParameters)
{
var parametersString = String.Join('&', parameters.Select(kvp => $"{HttpUtility.UrlEncode(kvp.Key)}={HttpUtility.UrlEncode(kvp.Value)}"));
if (!String.IsNullOrEmpty(launchParameters.AdditionalParameters))
parametersString = $"{parametersString}&{launchParameters.AdditionalParameters}";
return parametersString;
}
/// <inheritdoc />
public abstract string FormatCompilerArguments(string dmePath);
/// <inheritdoc />
public abstract string FormatServerArguments(IDmbProvider dmbProvider, IReadOnlyDictionary<string, string> parameters, DreamDaemonLaunchParameters launchParameters, string logFilePath);
}
}
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Api.Models.Internal;
@@ -13,25 +11,25 @@ namespace Tgstation.Server.Host.Components.Engine
/// <summary>
/// Implementation of <see cref="IEngineInstallation"/> for <see cref="EngineType.OpenDream"/>.
/// </summary>
sealed class OpenDreamInstallation : IEngineInstallation
sealed class OpenDreamInstallation : EngineInstallationBase
{
/// <inheritdoc />
public EngineVersion Version { get; }
public override EngineVersion Version { get; }
/// <inheritdoc />
public string ServerExePath { get; }
public override string ServerExePath { get; }
/// <inheritdoc />
public string CompilerExePath { get; }
public override string CompilerExePath { get; }
/// <inheritdoc />
public bool PromptsForNetworkAccess => false;
public override bool PromptsForNetworkAccess => false;
/// <inheritdoc />
public bool HasStandardOutput => true;
public override bool HasStandardOutput => true;
/// <inheritdoc />
public Task InstallationTask { get; }
public override Task InstallationTask { get; }
/// <summary>
/// Initializes a new instance of the <see cref="OpenDreamInstallation"/> class.
@@ -56,39 +54,27 @@ namespace Tgstation.Server.Host.Components.Engine
}
/// <inheritdoc />
public string FormatServerArguments(IDmbProvider dmbProvider, IReadOnlyDictionary<string, string> parameters, DreamDaemonLaunchParameters launchParameters, string logFilePath)
public override string FormatServerArguments(
IDmbProvider dmbProvider,
IReadOnlyDictionary<string, string> parameters,
DreamDaemonLaunchParameters launchParameters,
string logFilePath)
{
ArgumentNullException.ThrowIfNull(dmbProvider);
ArgumentNullException.ThrowIfNull(parameters);
ArgumentNullException.ThrowIfNull(launchParameters);
var parametersString = String.Join(';', parameters.Select(kvp => $"{kvp.Key}={kvp.Value}"));
if (logFilePath != null)
throw new NotSupportedException("OpenDream does not support logging to a file!");
if (!String.IsNullOrEmpty(launchParameters.AdditionalParameters))
{
// TGS and BYOND expect url encoded params, OD takes unencoded
var unencodedAdditionalParams = String.Join(
';',
launchParameters
.AdditionalParameters
.Split('&')
.Select(
singleParam => String.Join(
'=',
singleParam
.Split('=')
.Select(
encodedParam => HttpUtility.UrlDecode(encodedParam)))));
parametersString = $"{parametersString};{unencodedAdditionalParams}";
}
var parametersString = EncodeParameters(parameters, launchParameters);
var arguments = $"--cvar net.port={launchParameters.Port.Value} --cvar opendream.topic_port=0 --cvar opendream.world_params=\"{parametersString}\" \"{dmbProvider.DmbName}\"";
return arguments;
}
/// <inheritdoc />
public string FormatCompilerArguments(string dmePath)
public override string FormatCompilerArguments(string dmePath)
=> $"--suppress-unimplemented --notices-enabled \"{dmePath ?? throw new ArgumentNullException(nameof(dmePath))}\"";
}
}