Unstable v0.19.3.0
This commit is contained in:
22
Deploy/DeployAll/DeployAll.csproj
Normal file
22
Deploy/DeployAll/DeployAll.csproj
Normal file
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AsmResolver.PE" Version="4.11.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
111
Deploy/DeployAll/Deployables.cs
Normal file
111
Deploy/DeployAll/Deployables.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace DeployAll;
|
||||
|
||||
public static class Deployables
|
||||
{
|
||||
public const string ResultPath = "Deploy/bin/content";
|
||||
|
||||
private const string clientProjFmt = "Barotrauma/BarotraumaClient/{0}Client.csproj";
|
||||
private const string serverProjFmt = "Barotrauma/BarotraumaServer/{0}Server.csproj";
|
||||
|
||||
private static readonly ImmutableArray<(string Project, string Runtime)> platforms = new[]
|
||||
{
|
||||
("Windows", "win-x64"),
|
||||
("Mac", "osx-x64"),
|
||||
("Linux", "linux-x64")
|
||||
}.ToImmutableArray();
|
||||
|
||||
public static void Generate(string configuration, Version version, string gitBranch, string gitRevision)
|
||||
{
|
||||
Util.RecreateDirectory(ResultPath);
|
||||
|
||||
File.WriteAllText(
|
||||
Path.Combine(ResultPath, "readme.txt"),
|
||||
$"This is Barotrauma {configuration} v{version} ({gitBranch}, {gitRevision}) built on {DateTime.Now}");
|
||||
|
||||
foreach (var (project, runtime) in platforms)
|
||||
{
|
||||
string serverPath = Path.Combine(ResultPath, project, "Server");
|
||||
|
||||
void checkVersion(string projPath)
|
||||
{
|
||||
Version projVersion = Version.Parse(
|
||||
XDocument.Load(projPath).Root?
|
||||
.Element("PropertyGroup")?
|
||||
.Element("Version")?
|
||||
.Value ?? throw new Exception($"Version not found in {projPath}"));
|
||||
if (projVersion != version)
|
||||
{
|
||||
throw new Exception($"Version mismatch in {projPath}: {projVersion} != {version}");
|
||||
}
|
||||
}
|
||||
|
||||
string serverProj = string.Format(serverProjFmt, project);
|
||||
string clientProj = string.Format(clientProjFmt, project);
|
||||
|
||||
checkVersion(serverProj);
|
||||
checkVersion(clientProj);
|
||||
|
||||
Console.WriteLine(
|
||||
$"*** Building Barotrauma {configuration}{project} v{version} ({gitBranch}, {gitRevision}) to \"{Path.Combine(ResultPath, project)}\" ***");
|
||||
|
||||
DotnetCmd.Publish(
|
||||
projPath: serverProj,
|
||||
configuration: configuration,
|
||||
runtime: runtime,
|
||||
resultPath: serverPath);
|
||||
Util.DeleteFiles(serverPath,
|
||||
"*.png", "*.ogg", "*.webm",
|
||||
"*.mp4", "*.otf", "*.ttf");
|
||||
|
||||
string clientPath = Path.Combine(ResultPath, project, "Client");
|
||||
string clientBundlePath = clientPath;
|
||||
|
||||
if (project == "Mac")
|
||||
{
|
||||
clientPath = Path.Combine(clientPath, "Barotrauma.app", "Contents", "MacOS");
|
||||
Util.CopyDirectory("Deploy/DeployAll/macSkeleton", clientBundlePath);
|
||||
|
||||
string infoPlistPath = Path.Combine(clientBundlePath, "Barotrauma.app", "Contents", "info.plist");
|
||||
string infoPlist = File.ReadAllText(infoPlistPath, Encoding.UTF8)
|
||||
.Replace("{short_version_string}", $"{version.Major}.{version.Minor}.{version.Build}")
|
||||
.Replace("{version}", version.ToString())
|
||||
.Replace("{current_year}", DateTime.Now.Year.ToString());
|
||||
File.WriteAllText(infoPlistPath, infoPlist, Encoding.UTF8);
|
||||
}
|
||||
|
||||
DotnetCmd.Publish(
|
||||
projPath: serverProj,
|
||||
configuration: configuration,
|
||||
runtime: runtime,
|
||||
resultPath: clientPath);
|
||||
DotnetCmd.Publish(
|
||||
projPath: clientProj,
|
||||
configuration: configuration,
|
||||
runtime: runtime,
|
||||
resultPath: clientPath);
|
||||
|
||||
if (!File.Exists(Path.Combine(clientPath, "GameAnalytics.NetStandard.dll")))
|
||||
{
|
||||
throw new Exception($"GameAnalytics was not found in \"{clientPath}\"");
|
||||
}
|
||||
|
||||
if (project == "Mac")
|
||||
{
|
||||
Util.CopyDirectory(Path.Combine(clientPath, "Content", "Effects"),
|
||||
Path.Combine(
|
||||
clientBundlePath, "Barotrauma.app", "Contents", "Resources", "Content", "Effects"));
|
||||
Util.CopyDirectory(Path.Combine(clientPath, "Content", "Lights"),
|
||||
Path.Combine(
|
||||
clientBundlePath, "Barotrauma.app", "Contents", "Resources", "Content", "Lights"));
|
||||
}
|
||||
|
||||
Console.WriteLine("");
|
||||
}
|
||||
}
|
||||
}
|
||||
123
Deploy/DeployAll/DotnetCmd.cs
Normal file
123
Deploy/DeployAll/DotnetCmd.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Xml.Linq;
|
||||
using AsmResolver.PE;
|
||||
using AsmResolver.PE.File;
|
||||
using AsmResolver.PE.File.Headers;
|
||||
using AsmResolver.PE.Win32Resources.Builder;
|
||||
|
||||
namespace DeployAll;
|
||||
|
||||
public static class DotnetCmd
|
||||
{
|
||||
private const string DotnetAppName = "dotnet";
|
||||
|
||||
private const string desiredRuntimeVersion = "6.0.8";
|
||||
|
||||
public static void Publish(string projPath, string configuration, string runtime, string resultPath)
|
||||
{
|
||||
ProcessStartInfo psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = DotnetAppName,
|
||||
ArgumentList =
|
||||
{
|
||||
"publish",
|
||||
projPath,
|
||||
"-c",
|
||||
configuration,
|
||||
"-clp:ErrorsOnly;Summary",
|
||||
"--self-contained",
|
||||
"-r",
|
||||
runtime,
|
||||
"/p:Platform=x64",
|
||||
"/p:ErrorOnDuplicatePublishOutputFiles=false", //TODO: fix our duplicate files
|
||||
"/p:RollForward=Disable",
|
||||
$"/p:RuntimeFrameworkVersion={desiredRuntimeVersion}",
|
||||
"-o",
|
||||
resultPath
|
||||
},
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
};
|
||||
var process = Util.StartProcess(psi);
|
||||
process.WaitForExit();
|
||||
string stdout = process.StandardOutput.ReadToEnd();
|
||||
string stderr = process.StandardError.ReadToEnd();
|
||||
|
||||
string errorLine = $"{stdout}\n{stderr}".Split('\n')
|
||||
.First(ln => ln.Contains("Error(s)", StringComparison.OrdinalIgnoreCase))
|
||||
.Trim();
|
||||
|
||||
if (!errorLine.StartsWith("0 ", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new Exception($"Failed to build {projPath}, {errorLine}");
|
||||
}
|
||||
|
||||
Console.WriteLine($" - Published \"{projPath}\" to \"{resultPath}\", {errorLine}");
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || !runtime.StartsWith("win")) { return; }
|
||||
|
||||
// You may be wondering, what is this crap?
|
||||
// Cross-compiling is something that should work perfectly, because it's super convenient.
|
||||
// However, thanks to the way .NET works, cross-compiling to Windows from *nix platforms
|
||||
// results in an executable with basically no metadata, and the wrong subsystem!
|
||||
// (see https://github.com/dotnet/sdk/blob/375955d3a9de213a01d70eb6180298000dee30ee/src/Tasks/Microsoft.NET.Build.Tasks/GenerateShims.cs#L127-L132)
|
||||
// Does it look like we're about to modify the SDK itself to solve this problem? Yeah right.
|
||||
// Instead let's just take the shim generated by the SDK and fix it ourselves.
|
||||
|
||||
XElement firstPropertyGroup = XDocument.Load(projPath)
|
||||
.Root?
|
||||
.Element("PropertyGroup")
|
||||
?? throw new Exception("PropertyGroup not found");
|
||||
|
||||
string assemblyName = firstPropertyGroup.Element("AssemblyName")?.Value
|
||||
?? throw new Exception("AssemblyName not found");
|
||||
|
||||
// This is the shim that doesn't have the stuff we want.
|
||||
var fileToChange = PEFile.FromFile(Path.Combine(resultPath, $"{assemblyName}.exe"));
|
||||
// Luckily, the SDK does embed all of that data in the assembly with all of the IL!
|
||||
// We can just yoink it from here.
|
||||
var managedAssembly = PEImage.FromFile(Path.Combine(resultPath, $"{assemblyName}.dll"));
|
||||
|
||||
// Here's a whole lot of magic to set up the resources section of the executable
|
||||
var resourceSection = new PESection(".rsrc", SectionFlags.ContentInitializedData | SectionFlags.MemoryRead);
|
||||
var resourceDirectoryBuffer = new ResourceDirectoryBuffer();
|
||||
resourceDirectoryBuffer.AddDirectory(managedAssembly.Resources ?? throw new Exception($"{assemblyName}.dll has no resources"));
|
||||
resourceSection.Contents = resourceDirectoryBuffer;
|
||||
fileToChange.Sections.Add(resourceSection);
|
||||
fileToChange.AlignSections();
|
||||
var dataDirectories = fileToChange.OptionalHeader.DataDirectories;
|
||||
dataDirectories[2] = new DataDirectory(resourceDirectoryBuffer.Rva, resourceDirectoryBuffer.GetPhysicalSize());
|
||||
|
||||
// And here's something a little less magical that fixes the subsystem
|
||||
fileToChange.OptionalHeader.SubSystem = firstPropertyGroup.Element("OutputType")?.Value == "WinExe"
|
||||
? SubSystem.WindowsGui
|
||||
: SubSystem.WindowsCui;
|
||||
|
||||
using var writeStream = File.Open(Path.Combine(resultPath, $"{assemblyName}.exe"), FileMode.Create);
|
||||
fileToChange.Write(writeStream);
|
||||
}
|
||||
|
||||
public static Version GetSdkVersion()
|
||||
{
|
||||
ProcessStartInfo psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = DotnetAppName,
|
||||
ArgumentList =
|
||||
{
|
||||
"--version"
|
||||
},
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
};
|
||||
var process = Util.StartProcess(psi);
|
||||
process.WaitForExit();
|
||||
string stdout = process.StandardOutput.ReadToEnd();
|
||||
|
||||
return Version.Parse(stdout.Trim());
|
||||
}
|
||||
}
|
||||
86
Deploy/DeployAll/GitCmd.cs
Normal file
86
Deploy/DeployAll/GitCmd.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace DeployAll;
|
||||
|
||||
public static class GitCmd
|
||||
{
|
||||
private const string gitCmdName = "git";
|
||||
|
||||
private static ProcessStartInfo MakePsi(params string[] args)
|
||||
{
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = gitCmdName,
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardOutput = true
|
||||
};
|
||||
foreach (var arg in args)
|
||||
{
|
||||
psi.ArgumentList.Add(arg);
|
||||
}
|
||||
|
||||
return psi;
|
||||
}
|
||||
|
||||
private static void ExecCmd(out string stdOut, out string stdErr, params string[] args)
|
||||
{
|
||||
var process = Util.StartProcess(MakePsi(args));
|
||||
process.WaitForExit();
|
||||
stdOut = process.StandardOutput.ReadToEnd();
|
||||
stdErr = process.StandardError.ReadToEnd();
|
||||
}
|
||||
|
||||
public static string GetRevision()
|
||||
{
|
||||
ExecCmd(out string stdOut, out _,
|
||||
"rev-parse",
|
||||
"--short",
|
||||
"HEAD");
|
||||
|
||||
return stdOut.Trim();
|
||||
}
|
||||
|
||||
public static string GetBranch()
|
||||
{
|
||||
ExecCmd(out string stdOut, out _,
|
||||
"branch",
|
||||
"--show-current");
|
||||
|
||||
return stdOut.Trim();
|
||||
}
|
||||
|
||||
public static bool HasUncommittedChanges()
|
||||
{
|
||||
ExecCmd(out string stdOut, out _,
|
||||
"status",
|
||||
"--porcelain=1");
|
||||
|
||||
return !string.IsNullOrWhiteSpace(stdOut);
|
||||
}
|
||||
|
||||
public static bool IsRepoOutOfSync()
|
||||
{
|
||||
ExecCmd(out _, out _,
|
||||
"fetch");
|
||||
|
||||
ExecCmd(out string remoteBranch, out _,
|
||||
"status",
|
||||
"-sb");
|
||||
|
||||
if (!remoteBranch.StartsWith("##")) { return true; }
|
||||
if (!remoteBranch.Contains("...")) { return true; }
|
||||
|
||||
remoteBranch = remoteBranch[(remoteBranch.IndexOf("...", StringComparison.InvariantCulture) + 3)..];
|
||||
remoteBranch = remoteBranch[..remoteBranch.IndexOf("\n", StringComparison.InvariantCulture)];
|
||||
|
||||
string localRevision = GetRevision();
|
||||
ExecCmd(out string remoteRevision, out _,
|
||||
"rev-parse",
|
||||
"--short",
|
||||
remoteBranch);
|
||||
remoteRevision = remoteRevision.Trim();
|
||||
|
||||
return localRevision != remoteRevision;
|
||||
}
|
||||
}
|
||||
58
Deploy/DeployAll/Program.cs
Normal file
58
Deploy/DeployAll/Program.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using DeployAll;
|
||||
|
||||
while (!Directory.GetFiles(".").Any(f => f.EndsWith(".sln")))
|
||||
{
|
||||
Directory.SetCurrentDirectory("..");
|
||||
}
|
||||
|
||||
const string windowsClientProj = "Barotrauma/BarotraumaClient/WindowsClient.csproj";
|
||||
|
||||
Version gameVersion = Version.Parse(
|
||||
XDocument.Load(windowsClientProj).Root?
|
||||
.Element("PropertyGroup")?
|
||||
.Element("Version")?
|
||||
.Value ?? throw new Exception($"Version not found in {windowsClientProj}"));
|
||||
|
||||
string gitRevision = GitCmd.GetRevision();
|
||||
string gitBranch = GitCmd.GetBranch();
|
||||
|
||||
Console.WriteLine($"DEPLOYALL - Barotrauma v{gameVersion}, branch {gitBranch}, revision {gitRevision}");
|
||||
|
||||
if (GitCmd.HasUncommittedChanges())
|
||||
{
|
||||
if (Util.AskQuestion("The repo currently has some uncommitted changes. Do you still wish to proceed? [y/n]")
|
||||
.AnsweredNo()) { return; }
|
||||
}
|
||||
else if (GitCmd.IsRepoOutOfSync())
|
||||
{
|
||||
if (Util.AskQuestion("The repo is currently out of sync. Do you still wish to proceed? [y/n]")
|
||||
.AnsweredNo()) { return; }
|
||||
}
|
||||
|
||||
var sdkVersion = DotnetCmd.GetSdkVersion();
|
||||
Console.WriteLine($"Using .NET SDK {sdkVersion}");
|
||||
|
||||
string configuration = Util.AskQuestion("Type 1 for Release, 2 for Unstable, enter nothing to cancel") switch
|
||||
{
|
||||
"1" => "Release",
|
||||
"2" => "Unstable",
|
||||
_ => ""
|
||||
};
|
||||
if (string.IsNullOrWhiteSpace(configuration)) { return; }
|
||||
|
||||
Deployables.Generate(configuration, gameVersion, gitBranch, gitRevision);
|
||||
|
||||
if (Util.AskQuestion("Would you like to upload the generated builds to Steam? [y/n]")
|
||||
.AnsweredNo()) { return; }
|
||||
|
||||
SteamPipeAssistant.PrepareSteamCmd();
|
||||
SteamPipeAssistant.PrepareScripts(configuration, gameVersion, gitBranch, gitRevision);
|
||||
|
||||
string userName = Util.AskQuestion("Type your Steam username to upload to Steamworks, enter nothing to skip uploading");
|
||||
if (string.IsNullOrWhiteSpace(userName)) { return; }
|
||||
|
||||
SteamPipeAssistant.Upload(userName, configuration);
|
||||
248
Deploy/DeployAll/SteamPipeAssistant.cs
Normal file
248
Deploy/DeployAll/SteamPipeAssistant.cs
Normal file
@@ -0,0 +1,248 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DeployAll;
|
||||
|
||||
public static class SteamPipeAssistant
|
||||
{
|
||||
private abstract record ScriptItem(string Name)
|
||||
{
|
||||
public abstract override string ToString();
|
||||
}
|
||||
|
||||
private record SingleItem(string Name, string Value) : ScriptItem(Name)
|
||||
{
|
||||
public override string ToString() => $"\"{Name}\" \"{Value}\"";
|
||||
}
|
||||
|
||||
private record AggregateItem(string Name, params ScriptItem[] SubItems) : ScriptItem(Name)
|
||||
{
|
||||
public override string ToString()
|
||||
{
|
||||
return $"\"{Name}\"\n"
|
||||
+ "{\n"
|
||||
+ string.Join("\n",
|
||||
SubItems.Select(it => it.ToString())
|
||||
.SelectMany(s => s.Split("\n"))
|
||||
.Select(s => $"\t{s}"))
|
||||
+ "\n}";
|
||||
}
|
||||
}
|
||||
|
||||
private static string steamCmdUrl
|
||||
=> true switch
|
||||
{
|
||||
_ when RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||
=> "https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip",
|
||||
_ when RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
|
||||
=> "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz",
|
||||
_ when RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
|
||||
=> "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_osx.tar.gz",
|
||||
_ => throw new Exception($"Unsupported host platform: {RuntimeInformation.OSDescription}")
|
||||
};
|
||||
|
||||
private static string[] steamCmdFilenames
|
||||
=> true switch
|
||||
{
|
||||
_ when RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||
=> new[] { "steamcmd.exe" },
|
||||
_ when RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
|
||||
=> new[] { "steamcmd.sh", "linux32/steamcmd", "linux32/steamerrorreporter" },
|
||||
_ when RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
|
||||
=> new[] { "steamcmd.sh", "steamcmd" },
|
||||
_ => throw new Exception($"Unsupported host platform: {RuntimeInformation.OSDescription}")
|
||||
};
|
||||
|
||||
private const string SteamCmdPath = "Deploy/bin/steamcmd";
|
||||
|
||||
public static void PrepareSteamCmd()
|
||||
{
|
||||
if (Directory.Exists(SteamCmdPath))
|
||||
{
|
||||
Console.WriteLine($"SteamCMD found at {SteamCmdPath}, skipping download");
|
||||
return;
|
||||
}
|
||||
Console.WriteLine($"Downloading SteamCMD to {SteamCmdPath}");
|
||||
|
||||
Util.RecreateDirectory(SteamCmdPath);
|
||||
|
||||
var steamCmdPkg = Util.DownloadFile(steamCmdUrl).ToArray();
|
||||
|
||||
if (Path.GetExtension(steamCmdUrl) == ".zip")
|
||||
{
|
||||
using var memStream = new MemoryStream(steamCmdPkg);
|
||||
using ZipArchive archive = new ZipArchive(memStream, ZipArchiveMode.Read);
|
||||
archive.ExtractToDirectory(SteamCmdPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
string downloadResultPath = Path.Combine(SteamCmdPath, Path.GetFileName(steamCmdUrl));
|
||||
File.WriteAllBytes(downloadResultPath, steamCmdPkg);
|
||||
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = "tar",
|
||||
ArgumentList =
|
||||
{
|
||||
"-xf",
|
||||
downloadResultPath,
|
||||
"-C",
|
||||
SteamCmdPath
|
||||
},
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardOutput = true
|
||||
};
|
||||
var process = Util.StartProcess(psi);
|
||||
process.WaitForExit();
|
||||
|
||||
File.Delete(downloadResultPath);
|
||||
|
||||
foreach (var filename in steamCmdFilenames)
|
||||
{
|
||||
psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = "chmod",
|
||||
ArgumentList =
|
||||
{
|
||||
"+x",
|
||||
Path.Combine(SteamCmdPath, filename)
|
||||
},
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardOutput = true
|
||||
};
|
||||
process = Util.StartProcess(psi);
|
||||
process.WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("SteamCMD downloaded and extracted");
|
||||
}
|
||||
|
||||
private const string ScriptPath = "Deploy/bin/scripts";
|
||||
private const string BuildOutput = "Deploy/bin/output";
|
||||
|
||||
private const string appIdScriptFileFmt = "app_{0}.vdf";
|
||||
|
||||
private const ulong ClientAppId = 602960;
|
||||
private const ulong ClientWindowsDepotId = 602961;
|
||||
private const ulong ClientLinuxDepotId = 602962;
|
||||
private const ulong ClientMacDepotId = 602963;
|
||||
|
||||
private const ulong ServerAppId = 1026340;
|
||||
private const ulong ServerWindowsDepotId = 1026341;
|
||||
private const ulong ServerLinuxDepotId = 1026342;
|
||||
|
||||
private static ScriptItem PrepareDepotScript(ulong depotId, string contentPath)
|
||||
{
|
||||
var childItems = new List<ScriptItem>
|
||||
{
|
||||
new SingleItem("DepotID", depotId.ToString()),
|
||||
new SingleItem("contentroot", contentPath),
|
||||
new AggregateItem("FileMapping",
|
||||
new SingleItem("LocalPath", "*"),
|
||||
new SingleItem("DepotPath", "."),
|
||||
new SingleItem("recursive", "1")),
|
||||
new SingleItem("FileExclusion", "config_player.xml"),
|
||||
new SingleItem("FileExclusion", "Thumbs.db"),
|
||||
new SingleItem("FileExclusion", ".DS_Store"),
|
||||
new SingleItem("FileExclusion", "__MACOSX"),
|
||||
};
|
||||
|
||||
if (depotId == ClientMacDepotId)
|
||||
{
|
||||
childItems.Add(new SingleItem("InstallScript", "Barotrauma.app/installscript.vdf"));
|
||||
}
|
||||
|
||||
var script = new AggregateItem("DepotBuildConfig", childItems.ToArray());
|
||||
var scriptFileName = Path.Combine(ScriptPath, $"depot_{depotId}.vdf");
|
||||
File.WriteAllText(scriptFileName, script.ToString());
|
||||
return new SingleItem(depotId.ToString(), Path.GetFullPath(scriptFileName));
|
||||
}
|
||||
|
||||
private static void PrepareAppScript(ulong appId, string configuration, Version version, string gitBranch, string gitRevision)
|
||||
{
|
||||
var depotScripts = new AggregateItem("depots", appId switch
|
||||
{
|
||||
ClientAppId => new[]
|
||||
{
|
||||
PrepareDepotScript(ClientWindowsDepotId,
|
||||
Path.Combine("Windows", "Client")),
|
||||
PrepareDepotScript(ClientMacDepotId,
|
||||
Path.Combine("Mac", "Client")),
|
||||
PrepareDepotScript(ClientLinuxDepotId,
|
||||
Path.Combine("Linux", "Client"))
|
||||
},
|
||||
ServerAppId => new[]
|
||||
{
|
||||
PrepareDepotScript(ServerWindowsDepotId,
|
||||
Path.Combine("Windows", "Server")),
|
||||
PrepareDepotScript(ServerLinuxDepotId,
|
||||
Path.Combine("Linux", "Server"))
|
||||
},
|
||||
_ => throw new InvalidOperationException()
|
||||
});
|
||||
|
||||
var script = new AggregateItem("appbuild",
|
||||
new SingleItem("appid", appId.ToString()),
|
||||
new SingleItem("desc", $"{configuration} v{version} ({gitBranch}, {gitRevision})"),
|
||||
new SingleItem("buildoutput", Path.GetFullPath(BuildOutput)),
|
||||
new SingleItem("contentroot", Path.GetFullPath(Deployables.ResultPath)),
|
||||
new SingleItem("setlive", appId switch
|
||||
{
|
||||
ClientAppId => "experimental",
|
||||
ServerAppId => "development",
|
||||
_ => throw new InvalidOperationException()
|
||||
}),
|
||||
new SingleItem("preview", "0"),
|
||||
depotScripts);
|
||||
|
||||
var scriptFileName = Path.Combine(ScriptPath, string.Format(appIdScriptFileFmt, appId));
|
||||
File.WriteAllText(scriptFileName, script.ToString());
|
||||
}
|
||||
|
||||
public static void PrepareScripts(string configuration, Version version, string gitBranch, string gitRevision)
|
||||
{
|
||||
Console.WriteLine($"Preparing SteamPipe scripts for {configuration} v{version} ({gitBranch}, {gitRevision})");
|
||||
|
||||
Util.RecreateDirectory(ScriptPath);
|
||||
|
||||
PrepareAppScript(ClientAppId, configuration, version, gitBranch, gitRevision);
|
||||
PrepareAppScript(ServerAppId, configuration, version, gitBranch, gitRevision);
|
||||
|
||||
Console.WriteLine("");
|
||||
}
|
||||
|
||||
public static void Upload(string userName, string configuration)
|
||||
{
|
||||
Util.RecreateDirectory(BuildOutput);
|
||||
|
||||
ProcessStartInfo psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = Path.Combine(SteamCmdPath, steamCmdFilenames.First()),
|
||||
ArgumentList =
|
||||
{
|
||||
"+login",
|
||||
userName
|
||||
},
|
||||
RedirectStandardOutput = false,
|
||||
RedirectStandardError = false
|
||||
};
|
||||
|
||||
void addScriptCmd(ulong appId)
|
||||
{
|
||||
psi.ArgumentList.Add("+run_app_build");
|
||||
psi.ArgumentList.Add(Path.GetFullPath(Path.Combine(ScriptPath, string.Format(appIdScriptFileFmt, appId))));
|
||||
}
|
||||
addScriptCmd(ClientAppId);
|
||||
if (configuration == "Release") { addScriptCmd(ServerAppId); }
|
||||
|
||||
psi.ArgumentList.Add("+quit");
|
||||
var process = Util.StartProcess(psi);
|
||||
process.WaitForExit();
|
||||
}
|
||||
}
|
||||
106
Deploy/DeployAll/Util.cs
Normal file
106
Deploy/DeployAll/Util.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace DeployAll;
|
||||
|
||||
public static class Util
|
||||
{
|
||||
public static void DeleteFiles(string path, params string[] patterns)
|
||||
{
|
||||
foreach (var file in patterns.SelectMany(p => Directory.GetFiles(path, p, SearchOption.AllDirectories)))
|
||||
{
|
||||
File.Delete(file);
|
||||
string dir = file;
|
||||
do
|
||||
{
|
||||
dir = Path.GetDirectoryName(dir) ?? "";
|
||||
if (Directory.GetFiles(dir, "*", SearchOption.AllDirectories).Length == 0)
|
||||
{
|
||||
Directory.Delete(dir, recursive: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (dir.LastIndexOf('/') > 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static void CopyDirectory(string sourceDir, string destinationDir)
|
||||
{
|
||||
var dir = new DirectoryInfo(sourceDir);
|
||||
|
||||
DirectoryInfo[] dirs = dir.GetDirectories();
|
||||
|
||||
Directory.CreateDirectory(destinationDir);
|
||||
|
||||
foreach (FileInfo file in dir.GetFiles())
|
||||
{
|
||||
string targetFilePath = Path.Combine(destinationDir, file.Name);
|
||||
file.CopyTo(targetFilePath);
|
||||
}
|
||||
|
||||
foreach (DirectoryInfo subDir in dirs)
|
||||
{
|
||||
string newDestinationDir = Path.Combine(destinationDir, subDir.Name);
|
||||
CopyDirectory(subDir.FullName, newDestinationDir);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DeleteDirectory(string path)
|
||||
{
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
Directory.Delete(path, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RecreateDirectory(string path)
|
||||
{
|
||||
DeleteDirectory(path);
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
public static IReadOnlyList<byte> DownloadFile(string url)
|
||||
{
|
||||
var httpClient = new HttpClient();
|
||||
var response = httpClient.Send(new HttpRequestMessage(
|
||||
HttpMethod.Get,
|
||||
new Uri(url)));
|
||||
using var stream = response.Content.ReadAsStream();
|
||||
|
||||
using var reader = new BinaryReader(stream);
|
||||
var contents = new List<byte>();
|
||||
while (true)
|
||||
{
|
||||
byte[] bytesRead = reader.ReadBytes(1024);
|
||||
if (bytesRead.Length == 0) { break; }
|
||||
contents.AddRange(bytesRead);
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
public static string AskQuestion(string question)
|
||||
{
|
||||
Console.WriteLine(question);
|
||||
Console.Write("> ");
|
||||
string answer = Console.ReadLine() ?? "";
|
||||
Console.WriteLine("");
|
||||
return answer;
|
||||
}
|
||||
|
||||
public static bool AnsweredYes(this string answer)
|
||||
=> answer.Equals("y", StringComparison.InvariantCulture);
|
||||
|
||||
public static bool AnsweredNo(this string answer)
|
||||
=> !answer.AnsweredYes();
|
||||
|
||||
public static Process StartProcess(ProcessStartInfo info)
|
||||
=> Process.Start(info)
|
||||
?? throw new Exception($"Failed to start process \"{info.FileName}\"");
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Barotrauma</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>barotrauma</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.FakeFish.Barotrauma</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Barotrauma</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>{short_version_string}</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>FONV</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>{version}</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.games</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.13</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Needs microphone access for in-game communications</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2017-{current_year} FakeFish. All rights reserved.</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,31 @@
|
||||
"InstallScript"
|
||||
{
|
||||
"version" "2"
|
||||
"chmod"
|
||||
{
|
||||
"0"
|
||||
{
|
||||
"file" "Barotrauma.app/Contents/MacOS/Barotrauma"
|
||||
"mode" "755"
|
||||
}
|
||||
"1"
|
||||
{
|
||||
"file" "Barotrauma.app/Contents/MacOS/Barotrauma.bin.osx"
|
||||
"mode" "755"
|
||||
}
|
||||
"2"
|
||||
{
|
||||
"file" "Barotrauma.app/Contents/MacOS/DedicatedServer"
|
||||
"mode" "755"
|
||||
}
|
||||
"3"
|
||||
{
|
||||
"file" "Barotrauma.app/Contents/MacOS/DedicatedServer.bin.osx"
|
||||
"mode" "755"
|
||||
}
|
||||
}
|
||||
}
|
||||
"kvsignatures"
|
||||
{
|
||||
"InstallScript" "2d0e72227a48d72bfda9810a7f5478af6670d8653f25a92974ceaa4d2e1009e0f5e8a5312a092a64790635d574b0adb84a265ee89df71470d7e8e15c915420da429eb4a15d4ee68840d19c8928a970ab25b8bbfb13f22ce3a061bbb604a94f92299d6e94d7543f3f7bd51170a4c31b3f9808f2f98e85ffd4bd074e88da44491e"
|
||||
}
|
||||
Reference in New Issue
Block a user