Content update for UI prediction (#27214)

* Content update for UI refactor

* Big update

* Sharing

* Remaining content updates

* First big update

* Prototype updates

* AUGH

* Fix UI comp ref

* Cleanup

- Fix predicted message, fix item slots, fix interaction range check.

* Fix regressions

* Make this predictive

idk why it wasn't.

* Fix slime merge

* Merge conflict

* Fix merge
This commit is contained in:
metalgearsloth
2024-04-26 18:16:24 +10:00
committed by GitHub
parent 32b81de8c5
commit 5896e68752
279 changed files with 1308 additions and 1582 deletions

View File

@@ -2,9 +2,12 @@ using System.Collections.Frozen;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.ActionBlocker;
using Content.Shared.Administration;
using Content.Shared.Administration.Managers;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Destructible;
using Content.Shared.DoAfter;
using Content.Shared.Ghost;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Implants.Components;
@@ -29,6 +32,7 @@ using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.Storage.EntitySystems;
@@ -36,6 +40,7 @@ public abstract class SharedStorageSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] protected readonly IRobustRandom Random = default!;
[Dependency] private readonly ISharedAdminManager _admin = default!;
[Dependency] protected readonly ActionBlockerSystem ActionBlocker = default!;
[Dependency] private readonly EntityLookupSystem _entityLookupSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
@@ -73,6 +78,7 @@ public abstract class SharedStorageSystem : EntitySystem
private FrozenDictionary<string, ItemSizePrototype> _nextSmallest = FrozenDictionary<string, ItemSizePrototype>.Empty;
private const string QuickInsertUseDelayID = "quickInsert";
private const string OpenUiUseDelayID = "storage";
protected readonly List<string> CantFillReasons = [];
@@ -86,7 +92,13 @@ public abstract class SharedStorageSystem : EntitySystem
_xformQuery = GetEntityQuery<TransformComponent>();
_prototype.PrototypesReloaded += OnPrototypesReloaded;
Subs.BuiEvents<StorageComponent>(StorageComponent.StorageUiKey.Key, subs =>
{
subs.Event<BoundUIClosedEvent>(OnBoundUIClosed);
});
SubscribeLocalEvent<StorageComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<StorageComponent, GetVerbsEvent<ActivationVerb>>(AddUiVerb);
SubscribeLocalEvent<StorageComponent, ComponentGetState>(OnStorageGetState);
SubscribeLocalEvent<StorageComponent, ComponentHandleState>(OnStorageHandleState);
SubscribeLocalEvent<StorageComponent, ComponentInit>(OnComponentInit, before: new[] { typeof(SharedContainerSystem) });
@@ -121,10 +133,13 @@ public abstract class SharedStorageSystem : EntitySystem
UpdatePrototypeCache();
}
protected virtual void OnMapInit(Entity<StorageComponent> entity, ref MapInitEvent args)
private void OnMapInit(Entity<StorageComponent> entity, ref MapInitEvent args)
{
if (TryComp<UseDelayComponent>(entity, out var useDelayComp))
{
UseDelay.SetLength((entity, useDelayComp), entity.Comp.QuickInsertCooldown, QuickInsertUseDelayID);
UseDelay.SetLength((entity, useDelayComp), entity.Comp.OpenUiCooldown, OpenUiUseDelayID);
}
}
private void OnStorageGetState(EntityUid uid, StorageComponent component, ref ComponentGetState args)
@@ -139,7 +154,6 @@ public abstract class SharedStorageSystem : EntitySystem
args.State = new StorageComponentState()
{
Grid = new List<Box2i>(component.Grid),
IsUiOpen = component.IsUiOpen,
MaxItemSize = component.MaxItemSize,
StoredItems = storedItems,
SavedLocations = component.SavedLocations
@@ -153,7 +167,6 @@ public abstract class SharedStorageSystem : EntitySystem
component.Grid.Clear();
component.Grid.AddRange(state.Grid);
component.IsUiOpen = state.IsUiOpen;
component.MaxItemSize = state.MaxItemSize;
component.StoredItems.Clear();
@@ -205,9 +218,108 @@ public abstract class SharedStorageSystem : EntitySystem
UpdateAppearance((uid, storageComp, null));
}
public virtual void UpdateUI(Entity<StorageComponent?> entity) {}
/// <summary>
/// If the user has nested-UIs open (e.g., PDA UI open when pda is in a backpack), close them.
/// </summary>
private void CloseNestedInterfaces(EntityUid uid, EntityUid actor, StorageComponent? storageComp = null)
{
if (!Resolve(uid, ref storageComp))
return;
public virtual void OpenStorageUI(EntityUid uid, EntityUid entity, StorageComponent? storageComp = null, bool silent = false) { }
// for each containing thing
// if it has a storage comp
// ensure unsubscribe from session
// if it has a ui component
// close ui
foreach (var entity in storageComp.Container.ContainedEntities)
{
_ui.CloseUis(entity, actor);
}
}
private void OnBoundUIClosed(EntityUid uid, StorageComponent storageComp, BoundUIClosedEvent args)
{
CloseNestedInterfaces(uid, args.Actor, storageComp);
// If UI is closed for everyone
if (!_ui.IsUiOpen(uid, args.UiKey))
{
UpdateAppearance((uid, storageComp, null));
Audio.PlayPredicted(storageComp.StorageCloseSound, uid, args.Actor);
}
}
private void AddUiVerb(EntityUid uid, StorageComponent component, GetVerbsEvent<ActivationVerb> args)
{
var silent = false;
if (!args.CanAccess || !args.CanInteract || TryComp<LockComponent>(uid, out var lockComponent) && lockComponent.Locked)
{
// we allow admins to open the storage anyways
if (!_admin.HasAdminFlag(args.User, AdminFlags.Admin))
return;
silent = true;
}
silent |= HasComp<GhostComponent>(args.User);
// Does this player currently have the storage UI open?
var uiOpen = _ui.IsUiOpen(uid, StorageComponent.StorageUiKey.Key, args.User);
ActivationVerb verb = new()
{
Act = () =>
{
if (uiOpen)
{
_ui.CloseUi(uid, StorageComponent.StorageUiKey.Key, args.User);
}
else
{
OpenStorageUI(uid, args.User, component, silent);
}
}
};
if (uiOpen)
{
verb.Text = Loc.GetString("comp-storage-verb-close-storage");
verb.Icon = new SpriteSpecifier.Texture(
new("/Textures/Interface/VerbIcons/close.svg.192dpi.png"));
}
else
{
verb.Text = Loc.GetString("comp-storage-verb-open-storage");
verb.Icon = new SpriteSpecifier.Texture(
new("/Textures/Interface/VerbIcons/open.svg.192dpi.png"));
}
args.Verbs.Add(verb);
}
/// <summary>
/// Opens the storage UI for an entity
/// </summary>
/// <param name="entity">The entity to open the UI for</param>
public void OpenStorageUI(EntityUid uid, EntityUid entity, StorageComponent? storageComp = null, bool silent = false)
{
if (!Resolve(uid, ref storageComp, false))
return;
// prevent spamming bag open / honkerton honk sound
silent |= TryComp<UseDelayComponent>(uid, out var useDelay) && UseDelay.IsDelayed((uid, useDelay));
if (!silent)
{
if (!_ui.IsUiOpen(uid, StorageComponent.StorageUiKey.Key))
Audio.PlayPredicted(storageComp.StorageOpenSound, uid, entity);
if (useDelay != null)
UseDelay.TryResetDelay((uid, useDelay));
}
_ui.OpenUi(uid, StorageComponent.StorageUiKey.Key, entity);
}
public virtual void UpdateUI(Entity<StorageComponent?> entity) {}
private void AddTransferVerbs(EntityUid uid, StorageComponent component, GetVerbsEvent<UtilityVerb> args)
{
@@ -261,7 +373,16 @@ public abstract class SharedStorageSystem : EntitySystem
if (args.Handled || TryComp<LockComponent>(uid, out var lockComponent) && lockComponent.Locked)
return;
OpenStorageUI(uid, args.User, storageComp);
// Toggle
if (_ui.IsUiOpen(uid, StorageComponent.StorageUiKey.Key, args.User))
{
_ui.CloseUi(uid, StorageComponent.StorageUiKey.Key, args.User);
}
else
{
OpenStorageUI(uid, args.User, storageComp);
}
args.Handled = true;
}
@@ -460,8 +581,7 @@ public abstract class SharedStorageSystem : EntitySystem
if (!TryComp<StorageComponent>(uid, out var storageComp))
return;
if (!_ui.TryGetUi(uid, StorageComponent.StorageUiKey.Key, out var bui) ||
!bui.SubscribedSessions.Contains(args.SenderSession))
if (!_ui.IsUiOpen(uid, StorageComponent.StorageUiKey.Key, player))
return;
if (!Exists(entity))
@@ -503,8 +623,7 @@ public abstract class SharedStorageSystem : EntitySystem
if (!TryComp<StorageComponent>(storageEnt, out var storageComp))
return;
if (!_ui.TryGetUi(storageEnt, StorageComponent.StorageUiKey.Key, out var bui) ||
!bui.SubscribedSessions.Contains(args.SenderSession))
if (!_ui.IsUiOpen(storageEnt, StorageComponent.StorageUiKey.Key, player))
return;
if (!Exists(itemEnt))
@@ -530,8 +649,7 @@ public abstract class SharedStorageSystem : EntitySystem
if (!TryComp<StorageComponent>(storageEnt, out var storageComp))
return;
if (!_ui.TryGetUi(storageEnt, StorageComponent.StorageUiKey.Key, out var bui) ||
!bui.SubscribedSessions.Contains(args.SenderSession))
if (!_ui.IsUiOpen(storageEnt, StorageComponent.StorageUiKey.Key, player))
return;
if (!Exists(itemEnt))
@@ -558,8 +676,7 @@ public abstract class SharedStorageSystem : EntitySystem
if (!TryComp<StorageComponent>(storageEnt, out var storageComp))
return;
if (!_ui.TryGetUi(storageEnt, StorageComponent.StorageUiKey.Key, out var bui) ||
!bui.SubscribedSessions.Contains(args.SenderSession))
if (!_ui.IsUiOpen(storageEnt, StorageComponent.StorageUiKey.Key, player))
return;
if (!Exists(itemEnt))
@@ -584,11 +701,10 @@ public abstract class SharedStorageSystem : EntitySystem
var storage = GetEntity(msg.Storage);
var item = GetEntity(msg.Item);
if (!TryComp<StorageComponent>(storage, out var storageComp))
if (!HasComp<StorageComponent>(storage))
return;
if (!_ui.TryGetUi(storage, StorageComponent.StorageUiKey.Key, out var bui) ||
!bui.SubscribedSessions.Contains(args.SenderSession))
if (!_ui.IsUiOpen(storage, StorageComponent.StorageUiKey.Key, player))
return;
if (!Exists(item))
@@ -605,11 +721,7 @@ public abstract class SharedStorageSystem : EntitySystem
private void OnBoundUIOpen(EntityUid uid, StorageComponent storageComp, BoundUIOpenedEvent args)
{
if (!storageComp.IsUiOpen)
{
storageComp.IsUiOpen = true;
UpdateAppearance((uid, storageComp, null));
}
UpdateAppearance((uid, storageComp, null));
}
private void OnEntInserted(Entity<StorageComponent> entity, ref EntInsertedIntoContainerMessage args)
@@ -687,11 +799,13 @@ public abstract class SharedStorageSystem : EntitySystem
var capacity = storage.Grid.GetArea();
var used = GetCumulativeItemAreas((uid, storage));
var isOpen = _ui.IsUiOpen(entity.Owner, StorageComponent.StorageUiKey.Key);
_appearance.SetData(uid, StorageVisuals.StorageUsed, used, appearance);
_appearance.SetData(uid, StorageVisuals.Capacity, capacity, appearance);
_appearance.SetData(uid, StorageVisuals.Open, storage.IsUiOpen, appearance);
_appearance.SetData(uid, SharedBagOpenVisuals.BagState, storage.IsUiOpen ? SharedBagState.Open : SharedBagState.Closed, appearance);
_appearance.SetData(uid, StackVisuals.Hide, !storage.IsUiOpen, appearance);
_appearance.SetData(uid, StorageVisuals.Open, isOpen, appearance);
_appearance.SetData(uid, SharedBagOpenVisuals.BagState, isOpen ? SharedBagState.Open : SharedBagState.Closed, appearance);
_appearance.SetData(uid, StackVisuals.Hide, !isOpen, appearance);
}
/// <summary>
@@ -1343,8 +1457,6 @@ public abstract class SharedStorageSystem : EntitySystem
[Serializable, NetSerializable]
protected sealed class StorageComponentState : ComponentState
{
public bool IsUiOpen;
public Dictionary<NetEntity, ItemStorageLocation> StoredItems = new();
public Dictionary<string, List<ItemStorageLocation>> SavedLocations = new();