Predict StorageComponent (#19682)
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
using Content.Client.Animations;
|
||||
using Content.Shared.DragDrop;
|
||||
using Content.Shared.Storage;
|
||||
|
||||
namespace Content.Client.Storage
|
||||
{
|
||||
/// <summary>
|
||||
/// Client version of item storage containers, contains a UI which displays stored entities and their size
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedStorageComponent))]
|
||||
public sealed partial class ClientStorageComponent : SharedStorageComponent
|
||||
{
|
||||
private List<EntityUid> _storedEntities = new();
|
||||
public override IReadOnlyList<EntityUid> StoredEntities => _storedEntities;
|
||||
|
||||
public override bool Remove(EntityUid entity)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,13 @@ using Content.Client.UserInterface.Controls;
|
||||
using Content.Client.Verbs.UI;
|
||||
using Content.Shared.Input;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Storage;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Input;
|
||||
using static Content.Shared.Storage.SharedStorageComponent;
|
||||
using static Content.Shared.Storage.StorageComponent;
|
||||
|
||||
namespace Content.Client.Storage
|
||||
{
|
||||
@@ -19,8 +20,11 @@ namespace Content.Client.Storage
|
||||
[ViewVariables]
|
||||
private StorageWindow? _window;
|
||||
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
|
||||
public StorageBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
@@ -29,17 +33,22 @@ namespace Content.Client.Storage
|
||||
|
||||
if (_window == null)
|
||||
{
|
||||
_window = new StorageWindow(EntMan)
|
||||
{
|
||||
Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName
|
||||
};
|
||||
// TODO: This is a bit of a mess but storagecomponent got moved to shared and cleaned up a bit.
|
||||
var controller = IoCManager.Resolve<IUserInterfaceManager>().GetUIController<StorageUIController>();
|
||||
_window = controller.EnsureStorageWindow(Owner);
|
||||
_window.Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName;
|
||||
|
||||
_window.EntityList.GenerateItem += _window.GenerateButton;
|
||||
_window.EntityList.ItemPressed += InteractWithItem;
|
||||
_window.StorageContainerButton.OnPressed += TouchedContainerButton;
|
||||
|
||||
_window.OnClose += Close;
|
||||
_window.OpenCenteredLeft();
|
||||
|
||||
if (EntMan.TryGetComponent<StorageComponent>(Owner, out var storageComp))
|
||||
{
|
||||
BuildEntityList(Owner, storageComp);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -47,6 +56,11 @@ namespace Content.Client.Storage
|
||||
}
|
||||
}
|
||||
|
||||
public void BuildEntityList(EntityUid uid, StorageComponent component)
|
||||
{
|
||||
_window?.BuildEntityList(uid, component);
|
||||
}
|
||||
|
||||
public void InteractWithItem(BaseButton.ButtonEventArgs args, ListData cData)
|
||||
{
|
||||
if (cData is not EntityListData { Uid: var entity })
|
||||
@@ -54,7 +68,7 @@ namespace Content.Client.Storage
|
||||
|
||||
if (args.Event.Function == EngineKeyFunctions.UIClick)
|
||||
{
|
||||
SendMessage(new StorageInteractWithItemEvent(EntMan.GetNetEntity(entity)));
|
||||
SendPredictedMessage(new StorageInteractWithItemEvent(_entManager.GetNetEntity(entity)));
|
||||
}
|
||||
else if (EntMan.EntityExists(entity))
|
||||
{
|
||||
@@ -92,17 +106,7 @@ namespace Content.Client.Storage
|
||||
|
||||
public void TouchedContainerButton(BaseButton.ButtonEventArgs args)
|
||||
{
|
||||
SendMessage(new StorageInsertItemMessage());
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
if (_window == null || state is not StorageBoundUserInterfaceState cast)
|
||||
return;
|
||||
|
||||
_window?.BuildEntityList(cast);
|
||||
SendPredictedMessage(new StorageInsertItemMessage());
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
@@ -113,14 +117,13 @@ namespace Content.Client.Storage
|
||||
|
||||
if (_window != null)
|
||||
{
|
||||
_window.Orphan();
|
||||
_window.EntityList.GenerateItem -= _window.GenerateButton;
|
||||
_window.EntityList.ItemPressed -= InteractWithItem;
|
||||
_window.StorageContainerButton.OnPressed -= TouchedContainerButton;
|
||||
_window.OnClose -= Close;
|
||||
_window = null;
|
||||
}
|
||||
|
||||
_window?.Dispose();
|
||||
_window = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
using Content.Client.Animations;
|
||||
using Content.Shared.Storage;
|
||||
using Content.Shared.Storage.EntitySystems;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Storage.Systems;
|
||||
|
||||
// TODO kill this is all horrid.
|
||||
public sealed class StorageSystem : EntitySystem
|
||||
public sealed class StorageSystem : SharedStorageSystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
|
||||
public event Action<EntityUid, StorageComponent>? StorageUpdated;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -13,22 +19,24 @@ public sealed class StorageSystem : EntitySystem
|
||||
SubscribeNetworkEvent<AnimateInsertingEntitiesEvent>(HandleAnimatingInsertingEntities);
|
||||
}
|
||||
|
||||
public override void UpdateUI(EntityUid uid, StorageComponent component)
|
||||
{
|
||||
// Should we wrap this in some prediction call maybe?
|
||||
StorageUpdated?.Invoke(uid, component);
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
var store = GetEntity(msg.Storage);
|
||||
|
||||
if (!HasComp<ClientStorageComponent>(store))
|
||||
return;
|
||||
|
||||
TryComp(store, out TransformComponent? transformComp);
|
||||
TryComp(GetEntity(msg.Storage), out TransformComponent? transformComp);
|
||||
|
||||
for (var i = 0; msg.StoredEntities.Count > i; i++)
|
||||
{
|
||||
var entity = GetEntity(msg.StoredEntities[i]);
|
||||
|
||||
var initialPosition = msg.EntityPositions[i];
|
||||
if (EntityManager.EntityExists(entity) && transformComp != null)
|
||||
{
|
||||
|
||||
60
Content.Client/Storage/UI/StorageUIController.cs
Normal file
60
Content.Client/Storage/UI/StorageUIController.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using Content.Client.Storage.Systems;
|
||||
using Content.Shared.Storage;
|
||||
using Robust.Client.UserInterface.Controllers;
|
||||
|
||||
namespace Content.Client.Storage.UI;
|
||||
|
||||
public sealed class StorageUIController : UIController, IOnSystemChanged<StorageSystem>
|
||||
{
|
||||
// This is mainly to keep legacy functionality for now.
|
||||
private readonly Dictionary<EntityUid, StorageWindow> _storageWindows = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
EntityManager.EventBus.SubscribeLocalEvent<StorageComponent, ComponentShutdown>(OnStorageShutdown);
|
||||
}
|
||||
public StorageWindow EnsureStorageWindow(EntityUid uid)
|
||||
{
|
||||
if (_storageWindows.TryGetValue(uid, out var window))
|
||||
{
|
||||
UIManager.WindowRoot.AddChild(window);
|
||||
return window;
|
||||
}
|
||||
|
||||
window = new StorageWindow(EntityManager);
|
||||
_storageWindows[uid] = window;
|
||||
window.OpenCenteredLeft();
|
||||
return window;
|
||||
}
|
||||
|
||||
private void OnStorageShutdown(EntityUid uid, StorageComponent component, ComponentShutdown args)
|
||||
{
|
||||
if (!_storageWindows.TryGetValue(uid, out var window))
|
||||
return;
|
||||
|
||||
_storageWindows.Remove(uid);
|
||||
window.Dispose();
|
||||
}
|
||||
|
||||
private void OnStorageUpdate(EntityUid uid, StorageComponent component)
|
||||
{
|
||||
if (EntityManager.TryGetComponent<UserInterfaceComponent>(uid, out var uiComp) &&
|
||||
uiComp.OpenInterfaces.TryGetValue(StorageComponent.StorageUiKey.Key, out var bui))
|
||||
{
|
||||
var storageBui = (StorageBoundUserInterface) bui;
|
||||
|
||||
storageBui.BuildEntityList(uid, component);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSystemLoaded(StorageSystem system)
|
||||
{
|
||||
system.StorageUpdated += OnStorageUpdate;
|
||||
}
|
||||
|
||||
public void OnSystemUnloaded(StorageSystem system)
|
||||
{
|
||||
system.StorageUpdated -= OnStorageUpdate;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,9 @@ using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Storage;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.Containers;
|
||||
using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||
using static Content.Shared.Storage.SharedStorageComponent;
|
||||
using Direction = Robust.Shared.Maths.Direction;
|
||||
@@ -18,9 +20,9 @@ namespace Content.Client.Storage.UI
|
||||
/// <summary>
|
||||
/// GUI class for client storage component
|
||||
/// </summary>
|
||||
public sealed class StorageWindow : DefaultWindow
|
||||
public sealed class StorageWindow : FancyWindow
|
||||
{
|
||||
private IEntityManager _entityManager;
|
||||
private readonly IEntityManager _entityManager;
|
||||
|
||||
private readonly Label _information;
|
||||
public readonly ContainerButton StorageContainerButton;
|
||||
@@ -41,7 +43,7 @@ namespace Content.Client.Storage.UI
|
||||
MouseFilter = MouseFilterMode.Pass,
|
||||
};
|
||||
|
||||
Contents.AddChild(StorageContainerButton);
|
||||
ContentsContainer.AddChild(StorageContainerButton);
|
||||
|
||||
var innerContainerButton = new PanelContainer
|
||||
{
|
||||
@@ -54,6 +56,7 @@ namespace Content.Client.Storage.UI
|
||||
{
|
||||
Orientation = LayoutOrientation.Vertical,
|
||||
MouseFilter = MouseFilterMode.Ignore,
|
||||
Margin = new Thickness(5),
|
||||
};
|
||||
|
||||
StorageContainerButton.AddChild(vBox);
|
||||
@@ -87,20 +90,27 @@ namespace Content.Client.Storage.UI
|
||||
/// <summary>
|
||||
/// Loops through stored entities creating buttons for each, updates information labels
|
||||
/// </summary>
|
||||
public void BuildEntityList(StorageBoundUserInterfaceState state)
|
||||
public void BuildEntityList(EntityUid entity, StorageComponent component)
|
||||
{
|
||||
var list = state.StoredEntities.ConvertAll(nent => new EntityListData(_entityManager.GetEntity(nent)));
|
||||
var storedCount = component.Container.ContainedEntities.Count;
|
||||
var list = new List<EntityListData>(storedCount);
|
||||
|
||||
foreach (var uid in component.Container.ContainedEntities)
|
||||
{
|
||||
list.Add(new EntityListData(uid));
|
||||
}
|
||||
|
||||
EntityList.PopulateList(list);
|
||||
|
||||
//Sets information about entire storage container current capacity
|
||||
if (state.StorageCapacityMax != 0)
|
||||
// Sets information about entire storage container current capacity
|
||||
if (component.StorageCapacityMax != 0)
|
||||
{
|
||||
_information.Text = Loc.GetString("comp-storage-window-volume", ("itemCount", state.StoredEntities.Count),
|
||||
("usedVolume", state.StorageSizeUsed), ("maxVolume", state.StorageCapacityMax));
|
||||
_information.Text = Loc.GetString("comp-storage-window-volume", ("itemCount", storedCount),
|
||||
("usedVolume", component.StorageUsed), ("maxVolume", component.StorageCapacityMax));
|
||||
}
|
||||
else
|
||||
{
|
||||
_information.Text = Loc.GetString("comp-storage-window-volume-unlimited", ("itemCount", state.StoredEntities.Count));
|
||||
_information.Text = Loc.GetString("comp-storage-window-volume-unlimited", ("itemCount", storedCount));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user