Stack and storage enhancements (#16405)
This commit is contained in:
@@ -5,7 +5,9 @@ using Robust.Client.UserInterface.CustomControls;
|
||||
using Content.Client.Items.Components;
|
||||
using Content.Client.Stylesheets;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Client.UserInterface;
|
||||
using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||
using static Content.Shared.Storage.SharedStorageComponent;
|
||||
@@ -28,7 +30,7 @@ namespace Content.Client.Storage.UI
|
||||
public StorageWindow(IEntityManager entityManager)
|
||||
{
|
||||
_entityManager = entityManager;
|
||||
SetSize = (200, 320);
|
||||
SetSize = (240, 320);
|
||||
Title = Loc.GetString("comp-storage-window-title");
|
||||
RectClipContent = true;
|
||||
|
||||
@@ -112,6 +114,9 @@ namespace Content.Client.Storage.UI
|
||||
|
||||
_entityManager.TryGetComponent(entity, out SpriteComponent? sprite);
|
||||
_entityManager.TryGetComponent(entity, out ItemComponent? item);
|
||||
_entityManager.TryGetComponent(entity, out StackComponent? stack);
|
||||
var count = stack?.Count ?? 1;
|
||||
var size = item?.Size;
|
||||
|
||||
button.AddChild(new BoxContainer
|
||||
{
|
||||
@@ -131,12 +136,13 @@ namespace Content.Client.Storage.UI
|
||||
{
|
||||
HorizontalExpand = true,
|
||||
ClipText = true,
|
||||
Text = _entityManager.GetComponent<MetaDataComponent>(entity).EntityName
|
||||
Text = _entityManager.GetComponent<MetaDataComponent>(Identity.Entity(entity, _entityManager)).EntityName +
|
||||
(count > 1 ? $" x {count}" : string.Empty),
|
||||
},
|
||||
new Label
|
||||
{
|
||||
Align = Label.AlignMode.Right,
|
||||
Text = item?.Size.ToString() ?? Loc.GetString("comp-storage-no-item-size"),
|
||||
Text = size.ToString() ?? Loc.GetString("comp-storage-no-item-size"),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using Content.Server.Storage.Components;
|
||||
using Content.Server.Storage.EntitySystems;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Verbs;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
@@ -14,6 +17,8 @@ namespace Content.Server.Stack
|
||||
[UsedImplicitly]
|
||||
public sealed class StackSystem : SharedStackSystem
|
||||
{
|
||||
[Dependency] private readonly ContainerSystem _container = default!;
|
||||
[Dependency] private readonly StorageSystem _storage = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public static readonly int[] DefaultSplitAmounts = { 1, 5, 10, 20, 30, 50 };
|
||||
@@ -160,6 +165,12 @@ namespace Content.Server.Stack
|
||||
if (Split(uid, amount, userTransform.Coordinates, stack) is not {} split)
|
||||
return;
|
||||
|
||||
if (_container.TryGetContainingContainer(uid, out var container) &&
|
||||
TryComp<ServerStorageComponent>(container.Owner, out var storage))
|
||||
{
|
||||
_storage.UpdateStorageUI(container.Owner, storage);
|
||||
}
|
||||
|
||||
HandsSystem.PickupOrDrop(userUid, split);
|
||||
|
||||
PopupSystem.PopupCursor(Loc.GetString("comp-stack-split"), userUid);
|
||||
|
||||
@@ -3,6 +3,7 @@ using Content.Server.Administration.Managers;
|
||||
using Content.Server.Ghost.Components;
|
||||
using Content.Server.Interaction;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Stack;
|
||||
using Content.Server.Storage.Components;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Administration;
|
||||
@@ -37,10 +38,8 @@ using static Content.Shared.Storage.SharedStorageComponent;
|
||||
|
||||
namespace Content.Server.Storage.EntitySystems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed partial class StorageSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly IAdminManager _admin = default!;
|
||||
[Dependency] private readonly ContainerSystem _containerSystem = default!;
|
||||
@@ -57,6 +56,7 @@ namespace Content.Server.Storage.EntitySystems
|
||||
[Dependency] private readonly SharedCombatModeSystem _combatMode = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly StackSystem _stack = default!;
|
||||
[Dependency] private readonly UseDelaySystem _useDelay = default!;
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -423,7 +423,7 @@ namespace Content.Server.Storage.EntitySystems
|
||||
_appearance.SetData(uid, StackVisuals.Hide, !storageComp.IsOpen);
|
||||
}
|
||||
|
||||
private void RecalculateStorageUsed(ServerStorageComponent storageComp)
|
||||
public void RecalculateStorageUsed(ServerStorageComponent storageComp)
|
||||
{
|
||||
storageComp.StorageUsed = 0;
|
||||
storageComp.SizeCache.Clear();
|
||||
@@ -438,11 +438,20 @@ namespace Content.Server.Storage.EntitySystems
|
||||
if (!itemQuery.TryGetComponent(entity, out var itemComp))
|
||||
continue;
|
||||
|
||||
storageComp.StorageUsed += itemComp.Size;
|
||||
storageComp.SizeCache.Add(entity, itemComp.Size);
|
||||
var size = itemComp.Size;
|
||||
storageComp.StorageUsed += size;
|
||||
storageComp.SizeCache.Add(entity, size);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetAvailableSpace(EntityUid uid, ServerStorageComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return 0;
|
||||
|
||||
return component.StorageCapacityMax - component.StorageUsed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move entities from one storage to another.
|
||||
/// </summary>
|
||||
@@ -508,7 +517,7 @@ namespace Content.Server.Storage.EntitySystems
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TryComp(insertEnt, out ItemComponent? itemComp) &&
|
||||
if (!HasComp<StackComponent>(insertEnt) && TryComp(insertEnt, out ItemComponent? itemComp) &&
|
||||
itemComp.Size > storageComp.StorageCapacityMax - storageComp.StorageUsed)
|
||||
{
|
||||
reason = "comp-storage-insufficient-capacity";
|
||||
@@ -525,9 +534,63 @@ namespace Content.Server.Storage.EntitySystems
|
||||
/// <returns>true if the entity was inserted, false otherwise</returns>
|
||||
public bool Insert(EntityUid uid, EntityUid insertEnt, ServerStorageComponent? storageComp = null, bool playSound = true)
|
||||
{
|
||||
if (!Resolve(uid, ref storageComp) || !CanInsert(uid, insertEnt, out _, storageComp) || storageComp.Storage?.Insert(insertEnt) == false)
|
||||
if (!Resolve(uid, ref storageComp) || !CanInsert(uid, insertEnt, out _, storageComp) || storageComp.Storage == null)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* 1. If the inserted thing is stackable then try to stack it to existing stacks
|
||||
* 2. If anything remains insert whatever is possible.
|
||||
* 3. If insertion is not possible then leave the stack as is.
|
||||
* At either rate still play the insertion sound
|
||||
*
|
||||
* For now we just treat items as always being the same size regardless of stack count.
|
||||
*/
|
||||
|
||||
// If it's stackable then prefer to stack it
|
||||
var stackQuery = GetEntityQuery<StackComponent>();
|
||||
|
||||
if (stackQuery.TryGetComponent(insertEnt, out var insertStack))
|
||||
{
|
||||
var toInsertCount = insertStack.Count;
|
||||
|
||||
foreach (var ent in storageComp.Storage.ContainedEntities)
|
||||
{
|
||||
if (!stackQuery.TryGetComponent(ent, out var containedStack) || !insertStack.StackTypeId.Equals(containedStack.StackTypeId))
|
||||
continue;
|
||||
|
||||
if (!_stack.TryAdd(insertEnt, ent, insertStack, containedStack))
|
||||
continue;
|
||||
|
||||
var remaining = insertStack.Count;
|
||||
toInsertCount -= toInsertCount - remaining;
|
||||
|
||||
if (remaining > 0)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Still stackable remaining
|
||||
if (insertStack.Count > 0)
|
||||
{
|
||||
// Try to insert it as a new stack.
|
||||
if (TryComp(insertEnt, out ItemComponent? itemComp) &&
|
||||
itemComp.Size > storageComp.StorageCapacityMax - storageComp.StorageUsed ||
|
||||
!storageComp.Storage.Insert(insertEnt))
|
||||
{
|
||||
// If we also didn't do any stack fills above then just end
|
||||
// otherwise play sound and update UI anyway.
|
||||
if (toInsertCount == insertStack.Count)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Non-stackable but no insertion for reasons.
|
||||
else if (!storageComp.Storage.Insert(insertEnt))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (playSound && storageComp.StorageInsertSound is not null)
|
||||
_audio.PlayPvs(storageComp.StorageInsertSound, uid);
|
||||
|
||||
@@ -643,7 +706,7 @@ namespace Content.Server.Storage.EntitySystems
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateStorageUI(EntityUid uid, ServerStorageComponent storageComp)
|
||||
public void UpdateStorageUI(EntityUid uid, ServerStorageComponent storageComp)
|
||||
{
|
||||
if (storageComp.Storage == null)
|
||||
return;
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace Content.Shared.Stacks
|
||||
if (!Resolve(recipient, ref recipientStack, false) || !Resolve(donor, ref donorStack, false))
|
||||
return false;
|
||||
|
||||
if (recipientStack.StackTypeId == null || !recipientStack.StackTypeId.Equals(donorStack.StackTypeId))
|
||||
if (string.IsNullOrEmpty(recipientStack.StackTypeId) || !recipientStack.StackTypeId.Equals(donorStack.StackTypeId))
|
||||
return false;
|
||||
|
||||
transfered = Math.Min(donorStack.Count, GetAvailableSpace(recipientStack));
|
||||
@@ -270,7 +270,7 @@ namespace Content.Shared.Stacks
|
||||
if (component.MaxCountOverride != null)
|
||||
return component.MaxCountOverride.Value;
|
||||
|
||||
if (component.StackTypeId == null)
|
||||
if (string.IsNullOrEmpty(component.StackTypeId))
|
||||
return 1;
|
||||
|
||||
var stackProto = _prototype.Index<StackPrototype>(component.StackTypeId);
|
||||
@@ -289,6 +289,38 @@ namespace Content.Shared.Stacks
|
||||
return GetMaxCount(component) - component.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to add one stack to another. May have some leftover count in the inserted entity.
|
||||
/// </summary>
|
||||
public bool TryAdd(EntityUid insertEnt, EntityUid targetEnt, StackComponent? insertStack = null, StackComponent? targetStack = null)
|
||||
{
|
||||
if (!Resolve(insertEnt, ref insertStack) || !Resolve(targetEnt, ref targetStack))
|
||||
return false;
|
||||
|
||||
var count = insertStack.Count;
|
||||
return TryAdd(insertEnt, targetEnt, count, insertStack, targetStack);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to add one stack to another. May have some leftover count in the inserted entity.
|
||||
/// </summary>
|
||||
public bool TryAdd(EntityUid insertEnt, EntityUid targetEnt, int count, StackComponent? insertStack = null, StackComponent? targetStack = null)
|
||||
{
|
||||
if (!Resolve(insertEnt, ref insertStack) || !Resolve(targetEnt, ref targetStack))
|
||||
return false;
|
||||
|
||||
var available = GetAvailableSpace(targetStack);
|
||||
|
||||
if (available <= 0)
|
||||
return false;
|
||||
|
||||
var change = Math.Min(available, count);
|
||||
|
||||
SetCount(targetEnt, targetStack.Count + change, targetStack);
|
||||
SetCount(insertEnt, insertStack.Count - change, insertStack);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnStackStarted(EntityUid uid, StackComponent component, ComponentStartup args)
|
||||
{
|
||||
if (!TryComp(uid, out AppearanceComponent? appearance))
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
sprite: Objects/Materials/ore.rsi
|
||||
- type: Item
|
||||
sprite: Objects/Materials/ore.rsi
|
||||
size: 30
|
||||
- type: ItemStatus
|
||||
- type: Tag
|
||||
tags:
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
stackType: Cable
|
||||
- type: Sprite
|
||||
sprite: Objects/Tools/cable-coils.rsi
|
||||
netsync: false
|
||||
- type: Item
|
||||
sprite: Objects/Tools/cable-coils.rsi
|
||||
size: 10
|
||||
- type: CablePlacer
|
||||
- type: Clickable
|
||||
- type: StaticPrice
|
||||
@@ -39,7 +39,6 @@
|
||||
- type: Sprite
|
||||
state: coilhv-30
|
||||
- type: Item
|
||||
size: 10
|
||||
heldPrefix: coilhv
|
||||
- type: CablePlacer
|
||||
cablePrototypeID: CableHV
|
||||
@@ -59,8 +58,6 @@
|
||||
components:
|
||||
- type: Sprite
|
||||
state: coilhv-10
|
||||
- type: Item
|
||||
size: 3
|
||||
- type: Stack
|
||||
count: 1
|
||||
|
||||
@@ -76,7 +73,6 @@
|
||||
- type: Sprite
|
||||
state: coilmv-30
|
||||
- type: Item
|
||||
size: 10
|
||||
heldPrefix: coilmv
|
||||
- type: CablePlacer
|
||||
cablePrototypeID: CableMV
|
||||
@@ -96,8 +92,6 @@
|
||||
components:
|
||||
- type: Sprite
|
||||
state: coilmv-10
|
||||
- type: Item
|
||||
size: 3
|
||||
- type: Stack
|
||||
count: 1
|
||||
|
||||
@@ -111,7 +105,6 @@
|
||||
- type: Sprite
|
||||
state: coillv-30
|
||||
- type: Item
|
||||
size: 10
|
||||
heldPrefix: coillv
|
||||
- type: CablePlacer
|
||||
cablePrototypeID: CableApcExtension
|
||||
@@ -131,7 +124,5 @@
|
||||
components:
|
||||
- type: Sprite
|
||||
state: coillv-10
|
||||
- type: Item
|
||||
size: 3
|
||||
- type: Stack
|
||||
count: 1
|
||||
|
||||
Reference in New Issue
Block a user