diff --git a/server/NeonSprawl.Server/Game/Crafting/CraftOperations.cs b/server/NeonSprawl.Server/Game/Crafting/CraftOperations.cs index 903eecd..ad7e117 100644 --- a/server/NeonSprawl.Server/Game/Crafting/CraftOperations.cs +++ b/server/NeonSprawl.Server/Game/Crafting/CraftOperations.cs @@ -56,7 +56,7 @@ public static class CraftOperations } } - var simulated = CloneSnapshot(snapshot); + var simulated = snapshot.Clone(); foreach (var input in scaledInputs) { if (!PlayerInventoryOperations.TrySimulateRemoveStack(ref simulated, input.ItemId, input.Quantity, itemRegistry)) @@ -176,13 +176,6 @@ public static class CraftOperations return scaled; } - private static PlayerInventorySnapshot CloneSnapshot(PlayerInventorySnapshot snapshot) => - new() - { - BagSlots = PlayerInventorySnapshot.CloneSlots(snapshot.BagSlots), - EquipmentSlots = PlayerInventorySnapshot.CloneSlots(snapshot.EquipmentSlots), - }; - private static void CompensatingRestoreInputs( string playerId, IReadOnlyList inputs, diff --git a/server/NeonSprawl.Server/Game/Encounters/EncounterCompletionOperations.cs b/server/NeonSprawl.Server/Game/Encounters/EncounterCompletionOperations.cs index ba8bf72..692b085 100644 --- a/server/NeonSprawl.Server/Game/Encounters/EncounterCompletionOperations.cs +++ b/server/NeonSprawl.Server/Game/Encounters/EncounterCompletionOperations.cs @@ -62,7 +62,7 @@ public static class EncounterCompletionOperations return Deny(EncounterCompletionReasonCodes.InventoryStoreMissing); } - var simulated = CloneSnapshot(snapshot); + var simulated = snapshot.Clone(); foreach (var grant in grants) { if (!PlayerInventoryOperations.TrySimulateAddStack( @@ -139,13 +139,6 @@ public static class EncounterCompletionOperations private static string MakeIdempotencyKey(string normalizedPlayerId, string normalizedEncounterId) => $"{normalizedPlayerId}:{normalizedEncounterId}"; - private static PlayerInventorySnapshot CloneSnapshot(PlayerInventorySnapshot snapshot) => - new() - { - BagSlots = PlayerInventorySnapshot.CloneSlots(snapshot.BagSlots), - EquipmentSlots = PlayerInventorySnapshot.CloneSlots(snapshot.EquipmentSlots), - }; - private static void CompensatingRemoveGrants( string playerId, IReadOnlyList grants, diff --git a/server/NeonSprawl.Server/Game/Items/PlayerInventorySnapshot.cs b/server/NeonSprawl.Server/Game/Items/PlayerInventorySnapshot.cs index 089c9e3..8b16dfb 100644 --- a/server/NeonSprawl.Server/Game/Items/PlayerInventorySnapshot.cs +++ b/server/NeonSprawl.Server/Game/Items/PlayerInventorySnapshot.cs @@ -41,6 +41,14 @@ public sealed class PlayerInventorySnapshot return copy; } + /// Deep-copies bag and equipment slot arrays (NEO-69 craft pre-flight, NEO-105 encounter grant pre-flight). + public PlayerInventorySnapshot Clone() => + new() + { + BagSlots = CloneSlots(BagSlots), + EquipmentSlots = CloneSlots(EquipmentSlots), + }; + public InventorySlotState[] GetSlots(InventoryContainerKind container) => container == InventoryContainerKind.Equipment ? EquipmentSlots : BagSlots;