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:
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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++)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user