diff --git a/Yafc.Model.Tests/Blueprints/BlueprintUtilitiesTests.cs b/Yafc.Model.Tests/Blueprints/BlueprintUtilitiesTests.cs new file mode 100644 index 00000000..939c83e7 --- /dev/null +++ b/Yafc.Model.Tests/Blueprints/BlueprintUtilitiesTests.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; +using System.IO.Compression; +using System.Text; +using System.Text.Json; +using Xunit; +using Yafc.Blueprints; + +namespace Yafc.Model.Tests.Blueprints; + +public class BlueprintUtilitiesTests { + [Fact] + public void ExportConstantCombinators_WithEmptyGoods_ReturnsEmptyBlueprint() { + string blueprintString = BlueprintUtilities.ExportConstantCombinators( + "empty", + Array.Empty<(IObjectWithQuality item, int amount)>()); + + AssertEmptyBlueprint(blueprintString, "empty"); + } + + [Fact] + public void ExportRequesterChests_WithEmptyGoods_ReturnsEmptyBlueprint() { + EntityContainer chest = new() { + logisticSlotsCount = 10, + }; + + string blueprintString = BlueprintUtilities.ExportRequesterChests( + "empty", + Array.Empty<(IObjectWithQuality item, int amount)>(), + chest); + + AssertEmptyBlueprint(blueprintString, "empty"); + } + + private static void AssertEmptyBlueprint(string blueprintString, string name) { + Assert.StartsWith("0", blueprintString); + using JsonDocument document = JsonDocument.Parse(DecodeBlueprintString(blueprintString)); + JsonElement blueprint = document.RootElement.GetProperty("blueprint"); + + Assert.Equal("blueprint", blueprint.GetProperty("item").GetString()); + Assert.Equal(name, blueprint.GetProperty("label").GetString()); + Assert.Empty(blueprint.GetProperty("entities").EnumerateArray()); + } + + private static string DecodeBlueprintString(string blueprintString) { + byte[] compressed = Convert.FromBase64String(blueprintString[1..]); + using MemoryStream input = new MemoryStream(compressed); + using ZLibStream zlib = new ZLibStream(input, CompressionMode.Decompress); + using MemoryStream output = new MemoryStream(); + zlib.CopyTo(output); + return Encoding.UTF8.GetString(output.ToArray()); + } +} diff --git a/Yafc.Model/Blueprints/BlueprintUtilities.cs b/Yafc.Model/Blueprints/BlueprintUtilities.cs index 8d3c45ea..7209104c 100644 --- a/Yafc.Model/Blueprints/BlueprintUtilities.cs +++ b/Yafc.Model/Blueprints/BlueprintUtilities.cs @@ -8,6 +8,10 @@ namespace Yafc.Blueprints; public static class BlueprintUtilities { public static string ExportConstantCombinators(string name, IReadOnlyList<(IObjectWithQuality item, int amount)> goods) { + if (goods.Count == 0) { + return ExportEmptyBlueprint(name); + } + int combinatorCount = ((goods.Count - 1) / Database.constantCombinatorCapacity) + 1; int offset = -combinatorCount / 2; BlueprintString blueprint = new BlueprintString(name); @@ -45,6 +49,10 @@ public static string ExportRequesterChests(string name, IReadOnlyList<(IObjectWi throw new ArgumentException("Chest does not have logistic slots"); } + if (goods.Count == 0) { + return ExportEmptyBlueprint(name); + } + int combinatorCount = ((goods.Count - 1) / chest.logisticSlotsCount) + 1; int offset = -chest.size * combinatorCount / 2; BlueprintString blueprint = new BlueprintString(name); @@ -76,6 +84,9 @@ public static string ExportRequesterChests(string name, IReadOnlyList<(IObjectWi return blueprint.ToBpString(); } + private static string ExportEmptyBlueprint(string name) + => new BlueprintString(name).ToBpString(); + private class PlacedEntity { public RecipeRow Recipe { get; } public int X { get; } // Top-left X coordinate diff --git a/Yafc/Windows/ShoppingListScreen.cs b/Yafc/Windows/ShoppingListScreen.cs index 9cd5e2f0..e7ad5b22 100644 --- a/Yafc/Windows/ShoppingListScreen.cs +++ b/Yafc/Windows/ShoppingListScreen.cs @@ -175,7 +175,7 @@ public override void Build(ImGui gui) { Decompose(); } - if (gui.BuildButton(LSs.ShoppingListExportBlueprint, SchemeColor.Grey)) { + if (gui.BuildButton(LSs.ShoppingListExportBlueprint, SchemeColor.Grey, active: list.data.Count > 0)) { gui.ShowDropDown(ExportBlueprintDropdown); } }