diff --git a/Content.IntegrationTests/Tests/ClickableTest.cs b/Content.IntegrationTests/Tests/ClickableTest.cs
index 943ee44ae3..670f1313ea 100644
--- a/Content.IntegrationTests/Tests/ClickableTest.cs
+++ b/Content.IntegrationTests/Tests/ClickableTest.cs
@@ -5,7 +5,6 @@ using NUnit.Framework;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.GameObjects;
-using Robust.Shared.Map;
namespace Content.IntegrationTests.Tests
{
diff --git a/Content.Packaging/Content.Packaging.csproj b/Content.Packaging/Content.Packaging.csproj
new file mode 100644
index 0000000000..ac430e4354
--- /dev/null
+++ b/Content.Packaging/Content.Packaging.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/Content.Packaging/ContentPackaging.cs b/Content.Packaging/ContentPackaging.cs
new file mode 100644
index 0000000000..0f8c7c747b
--- /dev/null
+++ b/Content.Packaging/ContentPackaging.cs
@@ -0,0 +1,32 @@
+using Robust.Packaging;
+using Robust.Packaging.AssetProcessing;
+
+namespace Content.Packaging;
+
+public static class ContentPackaging
+{
+ public static async Task WriteResources(
+ string contentDir,
+ AssetPass pass,
+ IPackageLogger logger,
+ CancellationToken cancel)
+ {
+ var graph = new RobustClientAssetGraph();
+ pass.Dependencies.Add(new AssetPassDependency(graph.Output.Name));
+
+ AssetGraph.CalculateGraph(graph.AllPasses.Append(pass).ToArray(), logger);
+
+ var inputPass = graph.Input;
+
+ await RobustClientPackaging.WriteContentAssemblies(
+ inputPass,
+ contentDir,
+ "Content.Client",
+ new[] { "Content.Client", "Content.Shared", "Content.Shared.Database" },
+ cancel);
+
+ await RobustClientPackaging.WriteClientResources(contentDir, inputPass, cancel);
+
+ inputPass.InjectFinished();
+ }
+}
diff --git a/Content.Packaging/Program.cs b/Content.Packaging/Program.cs
new file mode 100644
index 0000000000..f965ec9995
--- /dev/null
+++ b/Content.Packaging/Program.cs
@@ -0,0 +1,68 @@
+using System.Diagnostics;
+using System.IO.Compression;
+using Content.Packaging;
+using Robust.Packaging;
+using Robust.Packaging.AssetProcessing.Passes;
+using Robust.Packaging.Utility;
+using Robust.Shared.Timing;
+
+IPackageLogger logger = new PackageLoggerConsole();
+
+logger.Info("Clearing release/ directory");
+Directory.CreateDirectory("release");
+
+var skipBuild = args.Contains("--skip-build");
+
+if (!skipBuild)
+ WipeBin();
+
+await Build(skipBuild);
+
+async Task Build(bool skipBuild)
+{
+ logger.Info("Building project...");
+
+ if (!skipBuild)
+ {
+ await ProcessHelpers.RunCheck(new ProcessStartInfo
+ {
+ FileName = "dotnet",
+ ArgumentList =
+ {
+ "build",
+ Path.Combine("Content.Client", "Content.Client.csproj"),
+ "-c", "Release",
+ "--nologo",
+ "/v:m",
+ "/t:Rebuild",
+ "/p:FullRelease=true",
+ "/m"
+ }
+ });
+ }
+
+ logger.Info("Packaging client...");
+
+ var sw = RStopwatch.StartNew();
+
+ {
+ using var zipFile =
+ File.Open(Path.Combine("release", "SS14.Client.zip"), FileMode.Create, FileAccess.ReadWrite);
+ using var zip = new ZipArchive(zipFile, ZipArchiveMode.Update);
+ var writer = new AssetPassZipWriter(zip);
+
+ await ContentPackaging.WriteResources("", writer, logger, default);
+
+ await writer.FinishedTask;
+ }
+
+ logger.Info($"Finished packaging in {sw.Elapsed}");
+}
+
+
+void WipeBin()
+{
+ logger.Info("Clearing old build artifacts (if any)...");
+
+ Directory.Delete("bin", recursive: true);
+}
diff --git a/Content.Server/Acz/ContentMagicAczProvider.cs b/Content.Server/Acz/ContentMagicAczProvider.cs
new file mode 100644
index 0000000000..ffd3123c57
--- /dev/null
+++ b/Content.Server/Acz/ContentMagicAczProvider.cs
@@ -0,0 +1,25 @@
+using System.Threading;
+using System.Threading.Tasks;
+using Content.Packaging;
+using Robust.Packaging;
+using Robust.Packaging.AssetProcessing;
+using Robust.Server.ServerStatus;
+
+namespace Content.Server.Acz;
+
+public sealed class ContentMagicAczProvider : IMagicAczProvider
+{
+ private readonly IDependencyCollection _deps;
+
+ public ContentMagicAczProvider(IDependencyCollection deps)
+ {
+ _deps = deps;
+ }
+
+ public async Task Package(AssetPass pass, IPackageLogger logger, CancellationToken cancel)
+ {
+ var contentDir = DefaultMagicAczProvider.FindContentRootPath(_deps);
+
+ await ContentPackaging.WriteResources(contentDir, pass, logger, cancel);
+ }
+}
diff --git a/Content.Server/Content.Server.csproj b/Content.Server/Content.Server.csproj
index 55f18dfc43..669ccf368d 100644
--- a/Content.Server/Content.Server.csproj
+++ b/Content.Server/Content.Server.csproj
@@ -18,6 +18,7 @@
+
diff --git a/Content.Server/Entry/EntryPoint.cs b/Content.Server/Entry/EntryPoint.cs
index e62dd41d07..caf4a722aa 100644
--- a/Content.Server/Entry/EntryPoint.cs
+++ b/Content.Server/Entry/EntryPoint.cs
@@ -1,3 +1,4 @@
+using Content.Server.Acz;
using Content.Server.Administration;
using Content.Server.Administration.Logs;
using Content.Server.Administration.Managers;
@@ -45,8 +46,8 @@ namespace Content.Server.Entry
{
base.Init();
- IoCManager.Resolve().SetAczInfo("Content.Client",
- new[] { "Content.Client", "Content.Shared", "Content.Shared.Database" });
+ var aczProvider = new ContentMagicAczProvider(IoCManager.Resolve());
+ IoCManager.Resolve().SetMagicAczProvider(aczProvider);
var factory = IoCManager.Resolve();
var prototypes = IoCManager.Resolve();
diff --git a/SpaceStation14.sln b/SpaceStation14.sln
index 9bd6959e7c..4c46a5e5bd 100644
--- a/SpaceStation14.sln
+++ b/SpaceStation14.sln
@@ -100,6 +100,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Content.Shared.Database", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Content.MapRenderer", "Content.MapRenderer\Content.MapRenderer.csproj", "{199BBEA1-7627-434B-B6F6-0F52A7C0E1E0}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Robust.Packaging", "RobustToolbox\Robust.Packaging\Robust.Packaging.csproj", "{952AAF2A-DF63-4A7D-8094-3453893EBA80}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Content.Packaging", "Content.Packaging\Content.Packaging.csproj", "{424445D4-F5D9-4CA9-A435-0A36E8AA28F3}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Project Files", "Project Files", "{EC27A16C-9412-4AA6-AE68-CAAB28882802}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
@@ -241,6 +244,14 @@ Global
{199BBEA1-7627-434B-B6F6-0F52A7C0E1E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{199BBEA1-7627-434B-B6F6-0F52A7C0E1E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{199BBEA1-7627-434B-B6F6-0F52A7C0E1E0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {952AAF2A-DF63-4A7D-8094-3453893EBA80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {952AAF2A-DF63-4A7D-8094-3453893EBA80}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {952AAF2A-DF63-4A7D-8094-3453893EBA80}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {952AAF2A-DF63-4A7D-8094-3453893EBA80}.Release|Any CPU.Build.0 = Release|Any CPU
+ {424445D4-F5D9-4CA9-A435-0A36E8AA28F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {424445D4-F5D9-4CA9-A435-0A36E8AA28F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {424445D4-F5D9-4CA9-A435-0A36E8AA28F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {424445D4-F5D9-4CA9-A435-0A36E8AA28F3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -268,6 +279,7 @@ Global
{88B0FC0F-7209-40E2-AF16-EB90AF727C5B} = {83B4CBBA-547A-42F0-A7CD-8A67D93196CE}
{A3C5B00A-D232-4A01-B82E-B0E58BFD5C12} = {83B4CBBA-547A-42F0-A7CD-8A67D93196CE}
{8A21C7CA-2EB8-40E5-8043-33582C06D139} = {83B4CBBA-547A-42F0-A7CD-8A67D93196CE}
+ {952AAF2A-DF63-4A7D-8094-3453893EBA80} = {83B4CBBA-547A-42F0-A7CD-8A67D93196CE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AA37ED9F-F8D6-468E-A101-658AD605B09A}