diff --git a/Assets/Scripts/ServerShared/Zone.cs b/Assets/Scripts/ServerShared/Zone.cs index 0d729d2be..74d1486c3 100644 --- a/Assets/Scripts/ServerShared/Zone.cs +++ b/Assets/Scripts/ServerShared/Zone.cs @@ -443,12 +443,15 @@ public class Zone { var floating = FloatingItems.FirstOrDefault(f => f.Id.Equals(id)); if (floating == null || (floating.Holder != null && !ReferenceEquals(floating.Holder, taker))) return false; + // The quantity is read before the store: a store that merges into a part-filled stack and spills the rest into a + // new cell rewrites the item's Quantity. + var stored = floating.Item is SimpleCommodity stack ? stack.Quantity : 1; if (!taker.CargoBays.Any(bay => bay.TryStore(floating.Item))) return false; FloatingItems.Remove(floating); CargoGained.OnNext(new CargoGain { Taker = taker, Design = floating.Item.Data, Lot = floating.Item.Lot, Kind = GainKind.Collected, - Stored = floating.Item is SimpleCommodity stack ? stack.Quantity : 1 + Stored = stored }); return true; } diff --git a/tests/Aetheria.Shared.Tests/HaulFeedTests.cs b/tests/Aetheria.Shared.Tests/HaulFeedTests.cs index 7157020b7..34eb8a3db 100644 --- a/tests/Aetheria.Shared.Tests/HaulFeedTests.cs +++ b/tests/Aetheria.Shared.Tests/HaulFeedTests.cs @@ -143,6 +143,23 @@ public sealed class HaulFeedTests : IDisposable Assert.Same(taker, gain.Taker); } + [Fact] + public void APickupThatMergesAndSpillsReportsTheWholeStack() + { + var grit = MiningCut5aTests.Commodity("Grit", maxStack: 4); + var (rig, _, gains) = Mining(1, 1, (grit, 1f)); + var taker = new Ship(rig.Scene.Items, rig.Zone, MiningCut3Tests.Mint(rig.Scene, rig.Scene.Hull), new EntitySettings()); + rig.Zone.Admit(taker, piloted: false); + var bay = MiningCut5aTests.Bay(rig.Scene, taker, 2, 1, "Taker"); + var design = rig.Scene.Cache.RefOf(grit); + Assert.True(bay.TryStore(new SimpleCommodity { Data = design, Lot = 7, Quantity = 3 })); + gains.Clear(); + var floating = rig.Zone.Release(new SimpleCommodity { Data = design, Lot = 7, Quantity = 4 }, new float2(0, 0), new float2(0, 0)); + Assert.True(rig.Zone.TryPickUp(taker, floating.Id)); + Assert.Equal(7, MiningCut5aTests.Units(bay, "Grit", rig.Scene)); + Assert.Equal((GainKind.Collected, 4, 0), (Assert.Single(gains).Kind, gains[0].Stored, gains[0].Adrift)); + } + [Fact] public void TheLineNamesWhatWasTakenAndWhatFloated() { @@ -161,7 +178,10 @@ public sealed class HaulFeedTests : IDisposable var spill = HaulFeed.Line(new CargoGain { Taker = rig.Shooter, Design = design, Stored = 1, Adrift = 2, Kind = GainKind.Mined }, items); Assert.Contains("2 adrift", spill); Assert.Contains("Rock", spill); - Assert.DoesNotContain("adrift", HaulFeed.Line(new CargoGain { Taker = rig.Shooter, Design = design, Stored = 2, Kind = GainKind.Collected }, items)); + var collected = HaulFeed.Line(new CargoGain { Taker = rig.Shooter, Design = design, Stored = 2, Kind = GainKind.Collected }, items); + Assert.DoesNotContain("adrift", collected); + Assert.Contains("Collected 2", collected); + Assert.Contains(hold, collected); } [Fact] diff --git a/tests/Aetheria.Shared.Tests/StationServicesTests.cs b/tests/Aetheria.Shared.Tests/StationServicesTests.cs index b255ad71b..3821a22b4 100644 --- a/tests/Aetheria.Shared.Tests/StationServicesTests.cs +++ b/tests/Aetheria.Shared.Tests/StationServicesTests.cs @@ -536,6 +536,23 @@ public sealed class StationServicesTests : IDisposable Assert.Contains(gun, bay.Cargo.Keys); } + [Fact] + public void SellOreLeavesALottedCommodityThatWasNotExtracted() + { + var ship = Ship(); + var bay = ship.CargoBays.Single(); + var data = _cache.GetByName("Ore"); + var lot = _items.Lots.Add(new Lot { Design = _cache.RefOf(data), Origin = new Attributed(), Quality = 1 }); + Assert.NotEqual(0, lot); + var traded = new SimpleCommodity { Data = _cache.RefOf(data), Quantity = 6, Lot = lot }; + Assert.True(bay.TryStore(traded)); + var credits = 100; + Assert.Equal(0, StationServices.OreValue(_items, ship.CargoBays)); + Assert.Equal(0, StationServices.TrySellOre(ship.CargoBays, Station(), ref credits)); + Assert.Equal(100, credits); + Assert.Contains(traded, bay.Cargo.Keys); + } + [Fact] public void SellOreAcrossBaysAndShips() {