Files

186 lines
6.2 KiB
C#
Raw Permalink Normal View History

using System.Linq;
using System.Numerics;
using Content.Client.Animations;
2023-09-12 22:34:04 +10:00
using Content.Shared.Hands;
2022-08-08 12:35:57 +10:00
using Content.Shared.Storage;
2023-09-11 21:20:46 +10:00
using Content.Shared.Storage.EntitySystems;
2025-02-08 17:17:55 +11:00
using Robust.Client.Player;
using Robust.Shared.GameStates;
2023-09-12 22:34:04 +10:00
using Robust.Shared.Map;
2023-09-11 21:20:46 +10:00
using Robust.Shared.Timing;
2022-08-08 12:35:57 +10:00
namespace Content.Client.Storage.Systems;
2023-09-11 21:20:46 +10:00
public sealed class StorageSystem : SharedStorageSystem
{
2023-09-11 21:20:46 +10:00
[Dependency] private readonly IGameTiming _timing = default!;
2025-02-08 17:17:55 +11:00
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly EntityPickupAnimationSystem _entityPickupAnimation = default!;
2023-09-11 21:20:46 +10:00
2025-02-08 17:17:55 +11:00
private Dictionary<EntityUid, ItemStorageLocation> _oldStoredItems = new();
2023-09-11 21:20:46 +10:00
private List<(StorageBoundUserInterface Bui, bool Value)> _queuedBuis = new();
public override void Initialize()
{
base.Initialize();
2025-02-08 17:17:55 +11:00
SubscribeLocalEvent<StorageComponent, ComponentHandleState>(OnStorageHandleState);
2023-09-12 22:34:04 +10:00
SubscribeNetworkEvent<PickupAnimationEvent>(HandlePickupAnimation);
SubscribeAllEvent<AnimateInsertingEntitiesEvent>(HandleAnimatingInsertingEntities);
}
2025-02-08 17:17:55 +11:00
private void OnStorageHandleState(EntityUid uid, StorageComponent component, ref ComponentHandleState args)
2023-09-11 21:20:46 +10:00
{
2025-02-08 17:17:55 +11:00
if (args.Current is not StorageComponentState state)
return;
2025-02-08 17:17:55 +11:00
component.Grid.Clear();
component.Grid.AddRange(state.Grid);
component.MaxItemSize = state.MaxItemSize;
component.Whitelist = state.Whitelist;
component.Blacklist = state.Blacklist;
2025-02-08 17:17:55 +11:00
_oldStoredItems.Clear();
2025-02-08 17:17:55 +11:00
foreach (var item in component.StoredItems)
{
_oldStoredItems.Add(item.Key, item.Value);
2025-01-27 21:29:51 +11:00
}
2025-02-08 17:17:55 +11:00
component.StoredItems.Clear();
2025-02-08 17:17:55 +11:00
foreach (var (nent, location) in state.StoredItems)
{
var ent = EnsureEntity<StorageComponent>(nent, uid);
component.StoredItems[ent] = location;
}
2025-02-08 17:17:55 +11:00
component.SavedLocations.Clear();
2025-02-08 17:17:55 +11:00
foreach (var loc in state.SavedLocations)
{
2025-02-08 17:17:55 +11:00
component.SavedLocations[loc.Key] = new(loc.Value);
}
UpdateOccupied((uid, component));
2025-02-08 17:17:55 +11:00
var uiDirty = !component.StoredItems.SequenceEqual(_oldStoredItems);
2025-02-08 17:17:55 +11:00
if (uiDirty && UI.TryGetOpenUi<StorageBoundUserInterface>(uid, StorageComponent.StorageUiKey.Key, out var storageBui))
2025-01-27 21:29:51 +11:00
{
2025-02-08 17:17:55 +11:00
storageBui.Refresh();
// Make sure nesting still updated.
var player = _player.LocalEntity;
2025-02-08 17:17:55 +11:00
if (NestedStorage && player != null && ContainerSystem.TryGetContainingContainer((uid, null, null), out var container) &&
UI.TryGetOpenUi<StorageBoundUserInterface>(container.Owner, StorageComponent.StorageUiKey.Key, out var containerBui))
{
_queuedBuis.Add((containerBui, false));
2025-02-08 17:17:55 +11:00
}
2025-01-27 21:29:51 +11:00
}
}
2025-02-08 17:17:55 +11:00
public override void UpdateUI(Entity<StorageComponent?> entity)
2025-01-27 21:29:51 +11:00
{
2025-02-08 17:17:55 +11:00
if (UI.TryGetOpenUi<StorageBoundUserInterface>(entity.Owner, StorageComponent.StorageUiKey.Key, out var sBui))
{
sBui.Refresh();
}
}
2025-02-08 17:17:55 +11:00
protected override void HideStorageWindow(EntityUid uid, EntityUid actor)
{
if (UI.TryGetOpenUi<StorageBoundUserInterface>(uid, StorageComponent.StorageUiKey.Key, out var storageBui))
{
_queuedBuis.Add((storageBui, false));
2025-02-08 17:17:55 +11:00
}
}
2025-02-08 17:17:55 +11:00
protected override void ShowStorageWindow(EntityUid uid, EntityUid actor)
{
2025-02-08 17:17:55 +11:00
if (UI.TryGetOpenUi<StorageBoundUserInterface>(uid, StorageComponent.StorageUiKey.Key, out var storageBui))
{
_queuedBuis.Add((storageBui, true));
2025-02-08 17:17:55 +11:00
}
2023-09-11 21:20:46 +10:00
}
2023-09-12 22:34:04 +10:00
/// <inheritdoc />
public override void PlayPickupAnimation(EntityUid uid, EntityCoordinates initialCoordinates, EntityCoordinates finalCoordinates,
Angle initialRotation, EntityUid? user = null)
{
if (!_timing.IsFirstTimePredicted)
return;
PickupAnimation(uid, initialCoordinates, finalCoordinates, initialRotation);
}
private void HandlePickupAnimation(PickupAnimationEvent msg)
{
PickupAnimation(GetEntity(msg.ItemUid), GetCoordinates(msg.InitialPosition), GetCoordinates(msg.FinalPosition), msg.InitialAngle);
}
public void PickupAnimation(EntityUid item, EntityCoordinates initialCoords, EntityCoordinates finalCoords, Angle initialAngle)
{
if (!_timing.IsFirstTimePredicted)
return;
2025-02-08 17:17:55 +11:00
if (TransformSystem.InRange(finalCoords, initialCoords, 0.1f) ||
2023-09-12 22:34:04 +10:00
!Exists(initialCoords.EntityId) || !Exists(finalCoords.EntityId))
{
return;
}
var finalMapPos = TransformSystem.ToMapCoordinates(finalCoords).Position;
var finalPos = Vector2.Transform(finalMapPos, TransformSystem.GetInvWorldMatrix(initialCoords.EntityId));
2023-09-12 22:34:04 +10:00
_entityPickupAnimation.AnimateEntityPickup(item, initialCoords, finalPos, initialAngle);
2023-09-12 22:34:04 +10:00
}
/// <summary>
/// Animate the newly stored entities in <paramref name="msg"/> flying towards this storage's position
/// </summary>
/// <param name="msg"></param>
public void HandleAnimatingInsertingEntities(AnimateInsertingEntitiesEvent msg)
{
2023-09-11 21:20:46 +10:00
TryComp(GetEntity(msg.Storage), out TransformComponent? transformComp);
for (var i = 0; msg.StoredEntities.Count > i; i++)
{
var entity = GetEntity(msg.StoredEntities[i]);
2023-09-11 21:20:46 +10:00
var initialPosition = msg.EntityPositions[i];
if (Exists(entity) && transformComp != null)
{
_entityPickupAnimation.AnimateEntityPickup(entity, GetCoordinates(initialPosition), transformComp.LocalPosition, msg.EntityAngles[i]);
}
}
}
public override void Update(float frameTime)
{
base.Update(frameTime);
if (!_timing.IsFirstTimePredicted)
{
return;
}
// This update loop exists just to synchronize with UISystem and avoid 1-tick delays.
// If deferred opens / closes ever get removed you can dump this.
foreach (var (bui, open) in _queuedBuis)
{
if (open)
{
bui.Show();
}
else
{
bui.Hide();
}
}
_queuedBuis.Clear();
}
}