CatStation/Content.Packaging/ServerPackaging.cs
Morb0 6fc8c1cd54 Merge remote-tracking branch 'upstream/master' into master-syndicate
# Conflicts:
#	Content.Packaging/ServerPackaging.cs
#	Resources/Prototypes/Accents/word_replacements.yml
#	Resources/Prototypes/Entities/Clothing/Neck/mantles.yml
#	Resources/Prototypes/Entities/Structures/Doors/Airlocks/highsec.yml
#	Resources/Prototypes/Maps/marathon.yml
#	Resources/Prototypes/Maps/packed.yml
#	Resources/Prototypes/Roles/Jobs/Engineering/atmospheric_technician.yml
#	Resources/Prototypes/Roles/Jobs/Security/detective.yml
#	Resources/Textures/Clothing/Head/Hardsuits/cybersun.rsi/meta.json
#	Resources/Textures/Clothing/Head/Hardsuits/spatiohelm.rsi/meta.json
#	Resources/Textures/Clothing/Head/Hardsuits/syndiecommander.rsi/meta.json
#	Resources/Textures/Clothing/Head/Hardsuits/syndieelite.rsi/meta.json
#	Resources/Textures/Clothing/Head/Helmets/atmos_firehelmet.rsi/meta.json
#	Resources/Textures/Clothing/Head/Helmets/paramedhelm.rsi/meta.json
#	Resources/Textures/Clothing/Mask/plaguedoctormask.rsi/meta.json
#	Resources/Textures/Clothing/Neck/Cloaks/capcloakformal.rsi/meta.json
#	Resources/Textures/Clothing/Neck/mantles/capmantle.rsi/meta.json
#	Resources/Textures/Clothing/Neck/mantles/cemantle.rsi/meta.json
#	Resources/Textures/Clothing/Neck/mantles/cmomantle.rsi/meta.json
#	Resources/Textures/Clothing/Neck/mantles/hopmantle.rsi/meta.json
#	Resources/Textures/Clothing/Neck/mantles/hosmantle.rsi/meta.json
#	Resources/Textures/Clothing/Neck/mantles/rdmantle.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Armor/lingarmor.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/equipped-OUTERCLOTHING.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/icon-open.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/icon.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/inhand-left.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/inhand-right.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/open-equipped-OUTERCLOTHING.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/open-inhand-left.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/open-inhand-right.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/equipped-OUTERCLOTHING.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/icon-open.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/icon.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/inhand-left.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/inhand-right.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/open-equipped-OUTERCLOTHING.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/open-inhand-left.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/open-inhand-right.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/equipped-OUTERCLOTHING.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/icon-open.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/icon.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/inhand-left.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/inhand-right.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/open-equipped-OUTERCLOTHING.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_gene.rsi/equipped-OUTERCLOTHING.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_gene.rsi/icon.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_gene.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_robo.rsi/equipped-OUTERCLOTHING.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_robo.rsi/icon.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_robo.rsi/inhand-left.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_robo.rsi/inhand-right.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_robo.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/equipped-OUTERCLOTHING-reptilian.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/open-equipped-OUTERCLOTHING-reptilian.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_viro.rsi/equipped-OUTERCLOTHING.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_viro.rsi/icon.png
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_viro.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/rndcoat.rsi/equipped-OUTERCLOTHING.png
#	Resources/Textures/Clothing/OuterClothing/Coats/rndcoat.rsi/icon.png
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/cybersun.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/paramed.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/spatio.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/syndiecommander.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/syndieelite.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Suits/atmos_firesuit.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coat.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatatmos.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatcap.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatcargo.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatce.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatcentcom.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatchem.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatcmo.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatengi.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatgen.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coathop.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coathos.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coathydro.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatjani.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatmed.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatmime.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatminer.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatparamed.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatqm.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatrd.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatrobo.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatsci.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatsec.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatviro.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatwarden.rsi/meta.json
#	Resources/Textures/Clothing/Shoes/Boots/combatboots.rsi/meta.json
#	Resources/Textures/Clothing/Shoes/Specific/bling.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpskirt/atmosf.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpskirt/capformaldress.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpskirt/operative_s.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/atmos.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/capformal.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_officer.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/centcomformal.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/hosformal.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/journalist.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/operative.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/psychologist.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/reporter.rsi/meta.json
#	Resources/Textures/Mobs/Animals/regalrat.rsi/meta.json
#	Resources/Textures/Objects/Storage/boxes.rsi/meta.json
#	Resources/Textures/Objects/Weapons/Guns/Battery/antiquelasergun.rsi/meta.json
#	Resources/Textures/Structures/Doors/Airlocks/Glass/atmospherics.rsi/meta.json
#	Resources/Textures/Structures/Doors/Airlocks/Standard/atmospherics.rsi/meta.json
#	Resources/Textures/Structures/Doors/Airlocks/highsec/highsec.rsi/meta.json
#	Resources/Textures/Structures/Furniture/chairs.rsi/meta.json
#	Resources/Textures/Structures/Holo/holofan.rsi/meta.json
#	Resources/Textures/Structures/Holo/wetfloor.rsi/meta.json
2024-03-27 01:12:55 +03:00

253 lines
8.5 KiB
C#

using System.Diagnostics;
using System.IO.Compression;
using Robust.Packaging;
using Robust.Packaging.AssetProcessing;
using Robust.Packaging.AssetProcessing.Passes;
using Robust.Packaging.Utility;
using Robust.Shared.Timing;
namespace Content.Packaging;
public static class ServerPackaging
{
private static readonly List<PlatformReg> Platforms = new()
{
new PlatformReg("win-x64", "Windows", true),
new PlatformReg("linux-x64", "Linux", true),
new PlatformReg("linux-arm64", "Linux", true),
new PlatformReg("osx-x64", "MacOS", true),
// Non-default platforms (i.e. for Watchdog Git)
new PlatformReg("win-x86", "Windows", false),
new PlatformReg("linux-x86", "Linux", false),
new PlatformReg("linux-arm", "Linux", false),
};
private static List<string> PlatformRids => Platforms
.Select(o => o.Rid)
.ToList();
private static List<string> PlatformRidsDefault => Platforms
.Where(o => o.BuildByDefault)
.Select(o => o.Rid)
.ToList();
private static readonly List<string> ServerContentAssemblies = new()
{
// Corvax-Secrets-Start
"Content.Corvax.Interfaces.Shared",
"Content.Corvax.Interfaces.Server",
// Corvax-Secrets-End
"Content.Server.Database",
"Content.Server",
"Content.Shared",
"Content.Shared.Database",
};
private static readonly List<string> ServerExtraAssemblies = new()
{
// Python script had Npgsql. though we want Npgsql.dll as well soooo
"Npgsql",
"Microsoft",
};
private static readonly List<string> ServerNotExtraAssemblies = new()
{
"Microsoft.CodeAnalysis",
};
private static readonly HashSet<string> BinSkipFolders = new()
{
// Roslyn localization files, screw em.
"cs",
"de",
"es",
"fr",
"it",
"ja",
"ko",
"pl",
"pt-BR",
"ru",
"tr",
"zh-Hans",
"zh-Hant"
};
private static readonly bool UseSecrets = File.Exists(Path.Combine("Secrets", "CorvaxSecrets.sln")); // Corvax-Secrets
public static async Task PackageServer(bool skipBuild, bool hybridAcz, IPackageLogger logger, string configuration, List<string>? platforms = null)
{
if (platforms == null)
{
platforms ??= PlatformRidsDefault;
}
if (hybridAcz)
{
// Hybrid ACZ involves a file "Content.Client.zip" in the server executable directory.
// Rather than hosting the client ZIP on the watchdog or on a separate server,
// Hybrid ACZ uses the ACZ hosting functionality to host it as part of the status host,
// which means that features such as automatic UPnP forwarding still work properly.
await ClientPackaging.PackageClient(skipBuild, configuration, logger);
}
// Good variable naming right here.
foreach (var platform in Platforms)
{
if (!platforms.Contains(platform.Rid))
continue;
await BuildPlatform(platform, skipBuild, hybridAcz, configuration, logger);
}
}
private static async Task BuildPlatform(PlatformReg platform, bool skipBuild, bool hybridAcz, string configuration, IPackageLogger logger)
{
logger.Info($"Building project for {platform.TargetOs}...");
if (!skipBuild)
{
await ProcessHelpers.RunCheck(new ProcessStartInfo
{
FileName = "dotnet",
ArgumentList =
{
"build",
Path.Combine("Content.Server", "Content.Server.csproj"),
"-c", configuration,
"--nologo",
"/v:m",
$"/p:TargetOs={platform.TargetOs}",
"/t:Rebuild",
"/p:FullRelease=true",
"/m"
}
});
// Corvax-Secrets-Start
if (UseSecrets)
{
logger.Info($"Secrets found. Building secret project for {platform}...");
await ProcessHelpers.RunCheck(new ProcessStartInfo
{
FileName = "dotnet",
ArgumentList =
{
"build",
Path.Combine("Secrets","Content.Corvax.Server", "Content.Corvax.Server.csproj"),
"-c", "Release",
"--nologo",
"/v:m",
$"/p:TargetOs={platform.TargetOs}",
"/t:Rebuild",
"/p:FullRelease=true",
"/m"
}
});
}
// Corvax-Secrets-End
await PublishClientServer(platform.Rid, platform.TargetOs, configuration);
}
logger.Info($"Packaging {platform.Rid} server...");
var sw = RStopwatch.StartNew();
{
await using var zipFile =
File.Open(Path.Combine("release", $"SS14.Server_{platform.Rid}.zip"), FileMode.Create, FileAccess.ReadWrite);
using var zip = new ZipArchive(zipFile, ZipArchiveMode.Update);
var writer = new AssetPassZipWriter(zip);
await WriteServerResources(platform, "", writer, logger, hybridAcz, default);
await writer.FinishedTask;
}
logger.Info($"Finished packaging server in {sw.Elapsed}");
}
private static async Task PublishClientServer(string runtime, string targetOs, string configuration)
{
await ProcessHelpers.RunCheck(new ProcessStartInfo
{
FileName = "dotnet",
ArgumentList =
{
"publish",
"--runtime", runtime,
"--no-self-contained",
"-c", configuration,
$"/p:TargetOs={targetOs}",
"/p:FullRelease=True",
"/m",
"RobustToolbox/Robust.Server/Robust.Server.csproj"
}
});
}
private static async Task WriteServerResources(
PlatformReg platform,
string contentDir,
AssetPass pass,
IPackageLogger logger,
bool hybridAcz,
CancellationToken cancel)
{
var graph = new RobustServerAssetGraph();
var passes = graph.AllPasses.ToList();
pass.Dependencies.Add(new AssetPassDependency(graph.Output.Name));
passes.Add(pass);
AssetGraph.CalculateGraph(passes, logger);
var inputPassCore = graph.InputCore;
var inputPassResources = graph.InputResources;
var contentAssemblies = new List<string>(ServerContentAssemblies);
// Corvax-Secrets-Start
if (UseSecrets)
contentAssemblies.AddRange(new[] { "Content.Corvax.Shared", "Content.Corvax.Server" });
// Corvax-Secrets-End
// Additional assemblies that need to be copied such as EFCore.
var sourcePath = Path.Combine(contentDir, "bin", "Content.Server");
// Should this be an asset pass?
// For future archaeologists I just want audio rework to work and need the audio pass so
// just porting this as is from python.
foreach (var fullPath in Directory.EnumerateFiles(sourcePath, "*.*", SearchOption.AllDirectories))
{
var fileName = Path.GetFileNameWithoutExtension(fullPath);
if (!ServerNotExtraAssemblies.Any(o => fileName.StartsWith(o)) && ServerExtraAssemblies.Any(o => fileName.StartsWith(o)))
{
contentAssemblies.Add(fileName);
}
}
await RobustSharedPackaging.DoResourceCopy(
Path.Combine("RobustToolbox", "bin", "Server",
platform.Rid,
"publish"),
inputPassCore,
BinSkipFolders,
cancel: cancel);
await RobustSharedPackaging.WriteContentAssemblies(
inputPassResources,
contentDir,
"Content.Server",
contentAssemblies,
cancel: cancel);
await RobustServerPackaging.WriteServerResources(contentDir, inputPassResources, cancel);
if (hybridAcz)
{
inputPassCore.InjectFileFromDisk("Content.Client.zip", Path.Combine("release", "SS14.Client.zip"));
}
inputPassCore.InjectFinished();
inputPassResources.InjectFinished();
}
private readonly record struct PlatformReg(string Rid, string TargetOs, bool BuildByDefault);
}