biggest gridinv update OF ALL TIME (#25834)

* add SaveItemLocation keybind

* make item direction public to avoid having to change between Angle for no reason

* add item location saving

* show

* Added a better save keybind, made it draw saved positions, and trying to save in a position it has already been saved in removes that position.

* w

* code style

* Make taken spots appear blue

* style

* !

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
Co-authored-by: notquitehadouken <tripwiregamer@gmail.com>
Co-authored-by: I.K <45953835+notquitehadouken@users.noreply.github.com>
This commit is contained in:
deltanedas
2024-03-28 06:31:47 +00:00
committed by GitHub
parent 65fa3ae211
commit 6863a7cc26
10 changed files with 188 additions and 5 deletions

View File

@@ -32,6 +32,7 @@ namespace Content.Client.Input
common.AddFunction(ContentKeyFunctions.ToggleFullscreen); common.AddFunction(ContentKeyFunctions.ToggleFullscreen);
common.AddFunction(ContentKeyFunctions.MoveStoredItem); common.AddFunction(ContentKeyFunctions.MoveStoredItem);
common.AddFunction(ContentKeyFunctions.RotateStoredItem); common.AddFunction(ContentKeyFunctions.RotateStoredItem);
common.AddFunction(ContentKeyFunctions.SaveItemLocation);
common.AddFunction(ContentKeyFunctions.Point); common.AddFunction(ContentKeyFunctions.Point);
common.AddFunction(ContentKeyFunctions.ZoomOut); common.AddFunction(ContentKeyFunctions.ZoomOut);
common.AddFunction(ContentKeyFunctions.ZoomIn); common.AddFunction(ContentKeyFunctions.ZoomIn);

View File

@@ -183,6 +183,7 @@ namespace Content.Client.Options.UI.Tabs
AddButton(ContentKeyFunctions.SwapHands); AddButton(ContentKeyFunctions.SwapHands);
AddButton(ContentKeyFunctions.MoveStoredItem); AddButton(ContentKeyFunctions.MoveStoredItem);
AddButton(ContentKeyFunctions.RotateStoredItem); AddButton(ContentKeyFunctions.RotateStoredItem);
AddButton(ContentKeyFunctions.SaveItemLocation);
AddHeader("ui-options-header-interaction-adv"); AddHeader("ui-options-header-interaction-adv");
AddButton(ContentKeyFunctions.SmartEquipBackpack); AddButton(ContentKeyFunctions.SmartEquipBackpack);

View File

@@ -12,6 +12,7 @@ using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Client.UserInterface.Systems.Storage.Controls; namespace Content.Client.UserInterface.Systems.Storage.Controls;
@@ -355,6 +356,40 @@ public sealed class StorageContainer : BaseWindow
origin, origin,
currentLocation.Rotation); currentLocation.Rotation);
foreach (var locations in storageComponent.SavedLocations)
{
if (!_entity.TryGetComponent<MetaDataComponent>(currentEnt, out var meta) || meta.EntityName != locations.Key)
continue;
float spot = 0;
var marked = new List<Control>();
foreach (var location in locations.Value)
{
var shape = itemSystem.GetAdjustedItemShape(currentEnt, location);
var bound = shape.GetBoundingBox();
var spotFree = storageSystem.ItemFitsInGridLocation(currentEnt, StorageEntity.Value, location);
if (spotFree)
spot++;
for (var y = bound.Bottom; y <= bound.Top; y++)
{
for (var x = bound.Left; x <= bound.Right; x++)
{
if (TryGetBackgroundCell(x, y, out var cell) && shape.Contains(x, y) && !marked.Contains(cell))
{
marked.Add(cell);
cell.ModulateSelfOverride = spotFree
? Color.FromHsv((0.18f, 1 / spot, 0.5f / spot + 0.5f, 1f))
: Color.FromHex("#2222CC");
}
}
}
}
}
var validColor = usingInHand ? Color.Goldenrod : Color.FromHex("#1E8000"); var validColor = usingInHand ? Color.Goldenrod : Color.FromHex("#1E8000");
for (var y = itemBounding.Bottom; y <= itemBounding.Top; y++) for (var y = itemBounding.Bottom; y <= itemBounding.Top; y++)

View File

@@ -240,6 +240,16 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
args.Handle(); args.Handle();
} }
else if (args.Function == ContentKeyFunctions.SaveItemLocation)
{
if (_container?.StorageEntity is not {} storage)
return;
_entity.RaisePredictiveEvent(new StorageSaveItemLocationEvent(
_entity.GetNetEntity(control.Entity),
_entity.GetNetEntity(storage)));
args.Handle();
}
else if (args.Function == ContentKeyFunctions.ExamineEntity) else if (args.Function == ContentKeyFunctions.ExamineEntity)
{ {
_entity.System<ExamineSystem>().DoExamine(control.Entity); _entity.System<ExamineSystem>().DoExamine(control.Entity);

View File

@@ -36,6 +36,7 @@ namespace Content.Shared.Input
public static readonly BoundKeyFunction SwapHands = "SwapHands"; public static readonly BoundKeyFunction SwapHands = "SwapHands";
public static readonly BoundKeyFunction MoveStoredItem = "MoveStoredItem"; public static readonly BoundKeyFunction MoveStoredItem = "MoveStoredItem";
public static readonly BoundKeyFunction RotateStoredItem = "RotateStoredItem"; public static readonly BoundKeyFunction RotateStoredItem = "RotateStoredItem";
public static readonly BoundKeyFunction SaveItemLocation = "SaveItemLocation";
public static readonly BoundKeyFunction ThrowItemInHand = "ThrowItemInHand"; public static readonly BoundKeyFunction ThrowItemInHand = "ThrowItemInHand";
public static readonly BoundKeyFunction TryPullObject = "TryPullObject"; public static readonly BoundKeyFunction TryPullObject = "TryPullObject";
public static readonly BoundKeyFunction MovePulledObject = "MovePulledObject"; public static readonly BoundKeyFunction MovePulledObject = "MovePulledObject";

View File

@@ -97,6 +97,7 @@ public abstract class SharedStorageSystem : EntitySystem
SubscribeAllEvent<StorageSetItemLocationEvent>(OnSetItemLocation); SubscribeAllEvent<StorageSetItemLocationEvent>(OnSetItemLocation);
SubscribeAllEvent<StorageInsertItemIntoLocationEvent>(OnInsertItemIntoLocation); SubscribeAllEvent<StorageInsertItemIntoLocationEvent>(OnInsertItemIntoLocation);
SubscribeAllEvent<StorageRemoveItemEvent>(OnRemoveItem); SubscribeAllEvent<StorageRemoveItemEvent>(OnRemoveItem);
SubscribeAllEvent<StorageSaveItemLocationEvent>(OnSaveItemLocation);
SubscribeLocalEvent<StorageComponent, GotReclaimedEvent>(OnReclaimed); SubscribeLocalEvent<StorageComponent, GotReclaimedEvent>(OnReclaimed);
@@ -117,7 +118,8 @@ public abstract class SharedStorageSystem : EntitySystem
Grid = new List<Box2i>(component.Grid), Grid = new List<Box2i>(component.Grid),
IsUiOpen = component.IsUiOpen, IsUiOpen = component.IsUiOpen,
MaxItemSize = component.MaxItemSize, MaxItemSize = component.MaxItemSize,
StoredItems = storedItems StoredItems = storedItems,
SavedLocations = component.SavedLocations
}; };
} }
@@ -138,6 +140,8 @@ public abstract class SharedStorageSystem : EntitySystem
var ent = EnsureEntity<StorageComponent>(nent, uid); var ent = EnsureEntity<StorageComponent>(nent, uid);
component.StoredItems[ent] = location; component.StoredItems[ent] = location;
} }
component.SavedLocations = state.SavedLocations;
} }
public override void Shutdown() public override void Shutdown()
@@ -536,6 +540,35 @@ public abstract class SharedStorageSystem : EntitySystem
InsertAt((storageEnt, storageComp), (itemEnt, null), msg.Location, out _, player, stackAutomatically: false); InsertAt((storageEnt, storageComp), (itemEnt, null), msg.Location, out _, player, stackAutomatically: false);
} }
// TODO: if/when someone cleans up this shitcode please make all these
// handlers use a shared helper for checking that the ui is open etc, thanks
private void OnSaveItemLocation(StorageSaveItemLocationEvent msg, EntitySessionEventArgs args)
{
if (args.SenderSession.AttachedEntity is not {} player)
return;
var storage = GetEntity(msg.Storage);
var item = GetEntity(msg.Item);
if (!TryComp<StorageComponent>(storage, out var storageComp))
return;
if (!_ui.TryGetUi(storage, StorageComponent.StorageUiKey.Key, out var bui) ||
!bui.SubscribedSessions.Contains(args.SenderSession))
return;
if (!Exists(item))
{
Log.Error($"Player {args.SenderSession} saved location of non-existent item {msg.Item} stored in {ToPrettyString(storage)}");
return;
}
if (!ActionBlocker.CanInteract(player, item))
return;
SaveItemLocation(storage, item);
}
private void OnBoundUIOpen(EntityUid uid, StorageComponent storageComp, BoundUIOpenedEvent args) private void OnBoundUIOpen(EntityUid uid, StorageComponent storageComp, BoundUIOpenedEvent args)
{ {
if (!storageComp.IsUiOpen) if (!storageComp.IsUiOpen)
@@ -945,6 +978,10 @@ public abstract class SharedStorageSystem : EntitySystem
if (!Resolve(storageEnt, ref storageEnt.Comp) || !Resolve(itemEnt, ref itemEnt.Comp)) if (!Resolve(storageEnt, ref storageEnt.Comp) || !Resolve(itemEnt, ref itemEnt.Comp))
return false; return false;
// if the item has an available saved location, use that
if (FindSavedLocation(storageEnt, itemEnt, out storageLocation))
return true;
var storageBounding = storageEnt.Comp.Grid.GetBoundingBox(); var storageBounding = storageEnt.Comp.Grid.GetBoundingBox();
Angle startAngle; Angle startAngle;
@@ -987,6 +1024,76 @@ public abstract class SharedStorageSystem : EntitySystem
return false; return false;
} }
/// <summary>
/// Tries to find a saved location for an item from its name.
/// If none are saved or they are all blocked nothing is returned.
/// </summary>
public bool FindSavedLocation(
Entity<StorageComponent?> ent,
Entity<ItemComponent?> item,
[NotNullWhen(true)] out ItemStorageLocation? storageLocation)
{
storageLocation = null;
if (!Resolve(ent, ref ent.Comp))
return false;
var name = Name(item);
if (!ent.Comp.SavedLocations.TryGetValue(name, out var list))
return false;
foreach (var location in list)
{
if (ItemFitsInGridLocation(item, ent, location))
{
storageLocation = location;
return true;
}
}
return false;
}
/// <summary>
/// Saves an item's location in the grid for later insertion to use.
/// </summary>
public void SaveItemLocation(Entity<StorageComponent?> ent, Entity<MetaDataComponent?> item)
{
if (!Resolve(ent, ref ent.Comp))
return;
// needs to actually be stored in it somewhere to save it
if (!ent.Comp.StoredItems.TryGetValue(item, out var location))
return;
var name = Name(item, item.Comp);
if (ent.Comp.SavedLocations.TryGetValue(name, out var list))
{
// iterate to make sure its not already been saved
for (int i = 0; i < list.Count; i++)
{
var saved = list[i];
if (saved == location)
{
list.Remove(location);
return;
}
}
list.Add(location);
}
else
{
list = new List<ItemStorageLocation>()
{
location
};
ent.Comp.SavedLocations[name] = list;
}
Dirty(ent, ent.Comp);
}
/// <summary> /// <summary>
/// Checks if an item fits into a specific spot on a storage grid. /// Checks if an item fits into a specific spot on a storage grid.
/// </summary> /// </summary>
@@ -1165,6 +1272,8 @@ public abstract class SharedStorageSystem : EntitySystem
public Dictionary<NetEntity, ItemStorageLocation> StoredItems = new(); public Dictionary<NetEntity, ItemStorageLocation> StoredItems = new();
public Dictionary<string, List<ItemStorageLocation>> SavedLocations = new();
public List<Box2i> Grid = new(); public List<Box2i> Grid = new();
public ProtoId<ItemSizePrototype>? MaxItemSize; public ProtoId<ItemSizePrototype>? MaxItemSize;

View File

@@ -8,16 +8,16 @@ public partial record struct ItemStorageLocation
/// <summary> /// <summary>
/// The rotation, stored a cardinal direction in order to reduce rounding errors. /// The rotation, stored a cardinal direction in order to reduce rounding errors.
/// </summary> /// </summary>
[DataField] [DataField("_rotation")]
private Direction _rotation; public Direction Direction;
/// <summary> /// <summary>
/// The rotation of the piece in storage. /// The rotation of the piece in storage.
/// </summary> /// </summary>
public Angle Rotation public Angle Rotation
{ {
get => _rotation.ToAngle(); get => Direction.ToAngle();
set => _rotation = value.GetCardinalDir(); set => Direction = value.GetCardinalDir();
} }
/// <summary> /// <summary>

View File

@@ -32,6 +32,14 @@ namespace Content.Shared.Storage
[DataField, ViewVariables(VVAccess.ReadWrite)] [DataField, ViewVariables(VVAccess.ReadWrite)]
public Dictionary<EntityUid, ItemStorageLocation> StoredItems = new(); public Dictionary<EntityUid, ItemStorageLocation> StoredItems = new();
/// <summary>
/// A dictionary storing each saved item to its location in the grid.
/// When trying to quick insert an item, if there is an empty location with the same name it will be placed there.
/// Multiple items with the same name can be saved, they will be checked individually.
/// </summary>
[DataField]
public Dictionary<string, List<ItemStorageLocation>> SavedLocations = new();
/// <summary> /// <summary>
/// A list of boxes that comprise a combined grid that determines the location that items can be stored. /// A list of boxes that comprise a combined grid that determines the location that items can be stored.
/// </summary> /// </summary>
@@ -171,6 +179,20 @@ namespace Content.Shared.Storage
} }
} }
[Serializable, NetSerializable]
public sealed class StorageSaveItemLocationEvent : EntityEventArgs
{
public readonly NetEntity Item;
public readonly NetEntity Storage;
public StorageSaveItemLocationEvent(NetEntity item, NetEntity storage)
{
Item = item;
Storage = storage;
}
}
/// <summary> /// <summary>
/// Network event for displaying an animation of entities flying into a storage entity /// Network event for displaying an animation of entities flying into a storage entity

View File

@@ -135,6 +135,7 @@ ui-options-function-examine-entity = Examine
ui-options-function-swap-hands = Swap hands ui-options-function-swap-hands = Swap hands
ui-options-function-move-stored-item = Move stored item ui-options-function-move-stored-item = Move stored item
ui-options-function-rotate-stored-item = Rotate stored item ui-options-function-rotate-stored-item = Rotate stored item
ui-options-function-save-item-location = Save item location
ui-options-static-storage-ui = Lock storage window to hotbar ui-options-static-storage-ui = Lock storage window to hotbar
ui-options-function-smart-equip-backpack = Smart-equip to backpack ui-options-function-smart-equip-backpack = Smart-equip to backpack

View File

@@ -171,6 +171,9 @@ binds:
- function: RotateStoredItem - function: RotateStoredItem
type: State type: State
key: MouseRight key: MouseRight
- function: SaveItemLocation
type: State
key: MouseMiddle
- function: Drop - function: Drop
type: State type: State
key: Q key: Q