Fix storagecomp serialization (#23780)

* Fix storagecomp serialization

* Fix state
This commit is contained in:
metalgearsloth
2024-01-09 21:47:51 +11:00
committed by GitHub
parent a01487601e
commit b22c9aa5e2
3 changed files with 87 additions and 38 deletions

View File

@@ -267,16 +267,14 @@ public sealed class StorageContainer : BaseWindow
var currentPosition = new Vector2i(x, y); var currentPosition = new Vector2i(x, y);
foreach (var item in storageComp.StoredItems) foreach (var (itemEnt, itemPos) in storageComp.StoredItems)
{ {
if (item.Value.Position != currentPosition) if (itemPos.Position != currentPosition)
continue; continue;
var itemEnt = _entity.GetEntity(item.Key);
if (_entity.TryGetComponent<ItemComponent>(itemEnt, out var itemEntComponent)) if (_entity.TryGetComponent<ItemComponent>(itemEnt, out var itemEntComponent))
{ {
var gridPiece = new ItemGridPiece((itemEnt, itemEntComponent), item.Value, _entity) var gridPiece = new ItemGridPiece((itemEnt, itemEntComponent), itemPos, _entity)
{ {
MinSize = size, MinSize = size,
Marked = itemEnt == lastEntity Marked = itemEnt == lastEntity

View File

@@ -19,29 +19,31 @@ using Content.Shared.Timing;
using Content.Shared.Verbs; using Content.Shared.Verbs;
using Robust.Shared.Audio.Systems; using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.GameStates;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Serialization;
namespace Content.Shared.Storage.EntitySystems; namespace Content.Shared.Storage.EntitySystems;
public abstract class SharedStorageSystem : EntitySystem public abstract class SharedStorageSystem : EntitySystem
{ {
[Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] protected readonly IRobustRandom Random = default!; [Dependency] protected readonly IRobustRandom Random = default!;
[Dependency] protected readonly ActionBlockerSystem ActionBlocker = default!;
[Dependency] private readonly EntityLookupSystem _entityLookupSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] protected readonly SharedAudioSystem Audio = default!;
[Dependency] private readonly SharedContainerSystem _containerSystem = default!; [Dependency] private readonly SharedContainerSystem _containerSystem = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly EntityLookupSystem _entityLookupSystem = default!;
[Dependency] protected readonly SharedEntityStorageSystem EntityStorage = default!; [Dependency] protected readonly SharedEntityStorageSystem EntityStorage = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
[Dependency] protected readonly SharedItemSystem ItemSystem = default!; [Dependency] protected readonly SharedItemSystem ItemSystem = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly SharedHandsSystem _sharedHandsSystem = default!; [Dependency] private readonly SharedHandsSystem _sharedHandsSystem = default!;
[Dependency] protected readonly ActionBlockerSystem ActionBlocker = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] protected readonly SharedAudioSystem Audio = default!;
[Dependency] protected readonly SharedTransformSystem TransformSystem = default!;
[Dependency] private readonly SharedStackSystem _stack = default!; [Dependency] private readonly SharedStackSystem _stack = default!;
[Dependency] protected readonly SharedTransformSystem TransformSystem = default!;
[Dependency] private readonly SharedUserInterfaceSystem _ui = default!; [Dependency] private readonly SharedUserInterfaceSystem _ui = default!;
[Dependency] protected readonly UseDelaySystem UseDelay = default!; [Dependency] protected readonly UseDelaySystem UseDelay = default!;
@@ -69,6 +71,8 @@ public abstract class SharedStorageSystem : EntitySystem
_xformQuery = GetEntityQuery<TransformComponent>(); _xformQuery = GetEntityQuery<TransformComponent>();
_prototype.PrototypesReloaded += OnPrototypesReloaded; _prototype.PrototypesReloaded += OnPrototypesReloaded;
SubscribeLocalEvent<StorageComponent, ComponentGetState>(OnStorageGetState);
SubscribeLocalEvent<StorageComponent, ComponentHandleState>(OnStorageHandleState);
SubscribeLocalEvent<StorageComponent, ComponentInit>(OnComponentInit, before: new[] { typeof(SharedContainerSystem) }); SubscribeLocalEvent<StorageComponent, ComponentInit>(OnComponentInit, before: new[] { typeof(SharedContainerSystem) });
SubscribeLocalEvent<StorageComponent, GetVerbsEvent<UtilityVerb>>(AddTransferVerbs); SubscribeLocalEvent<StorageComponent, GetVerbsEvent<UtilityVerb>>(AddTransferVerbs);
SubscribeLocalEvent<StorageComponent, InteractUsingEvent>(OnInteractUsing, after: new[] { typeof(ItemSlotsSystem) }); SubscribeLocalEvent<StorageComponent, InteractUsingEvent>(OnInteractUsing, after: new[] { typeof(ItemSlotsSystem) });
@@ -92,6 +96,43 @@ public abstract class SharedStorageSystem : EntitySystem
UpdatePrototypeCache(); UpdatePrototypeCache();
} }
private void OnStorageGetState(EntityUid uid, StorageComponent component, ref ComponentGetState args)
{
var storedItems = new Dictionary<NetEntity, ItemStorageLocation>();
foreach (var (ent, location) in component.StoredItems)
{
storedItems[GetNetEntity(ent)] = location;
}
args.State = new StorageComponentState()
{
Grid = component.Grid,
IsUiOpen = component.IsUiOpen,
MaxItemSize = component.MaxItemSize,
StoredItems = storedItems
};
}
private void OnStorageHandleState(EntityUid uid, StorageComponent component, ref ComponentHandleState args)
{
if (args.Current is not StorageComponentState state)
return;
component.Grid.Clear();
component.Grid.AddRange(state.Grid);
component.IsUiOpen = state.IsUiOpen;
component.MaxItemSize = state.MaxItemSize;
component.StoredItems.Clear();
foreach (var (nent, location) in state.StoredItems)
{
var ent = EnsureEntity<StorageComponent>(nent, uid);
component.StoredItems[ent] = location;
}
}
public override void Shutdown() public override void Shutdown()
{ {
_prototype.PrototypesReloaded -= OnPrototypesReloaded; _prototype.PrototypesReloaded -= OnPrototypesReloaded;
@@ -497,7 +538,7 @@ public abstract class SharedStorageSystem : EntitySystem
if (args.Container.ID != StorageComponent.ContainerId) if (args.Container.ID != StorageComponent.ContainerId)
return; return;
if (!entity.Comp.StoredItems.ContainsKey(GetNetEntity(args.Entity))) if (!entity.Comp.StoredItems.ContainsKey(args.Entity))
{ {
if (!TryGetAvailableGridSpace((entity.Owner, entity.Comp), (args.Entity, null), out var location)) if (!TryGetAvailableGridSpace((entity.Owner, entity.Comp), (args.Entity, null), out var location))
{ {
@@ -505,7 +546,7 @@ public abstract class SharedStorageSystem : EntitySystem
return; return;
} }
entity.Comp.StoredItems[GetNetEntity(args.Entity)] = location.Value; entity.Comp.StoredItems[args.Entity] = location.Value;
Dirty(entity, entity.Comp); Dirty(entity, entity.Comp);
} }
@@ -522,7 +563,7 @@ public abstract class SharedStorageSystem : EntitySystem
if (args.Container.ID != StorageComponent.ContainerId) if (args.Container.ID != StorageComponent.ContainerId)
return; return;
entity.Comp.StoredItems.Remove(GetNetEntity(args.Entity)); entity.Comp.StoredItems.Remove(args.Entity);
Dirty(entity, entity.Comp); Dirty(entity, entity.Comp);
UpdateAppearance((entity, entity.Comp, null)); UpdateAppearance((entity, entity.Comp, null));
@@ -655,7 +696,7 @@ public abstract class SharedStorageSystem : EntitySystem
return false; return false;
} }
if (!ignoreLocation && !storageComp.StoredItems.ContainsKey(GetNetEntity(insertEnt))) if (!ignoreLocation && !storageComp.StoredItems.ContainsKey(insertEnt))
{ {
if (!TryGetAvailableGridSpace((uid, storageComp), (insertEnt, item), out _)) if (!TryGetAvailableGridSpace((uid, storageComp), (insertEnt, item), out _))
{ {
@@ -698,7 +739,7 @@ public abstract class SharedStorageSystem : EntitySystem
if (!ItemFitsInGridLocation(insertEnt, uid, location)) if (!ItemFitsInGridLocation(insertEnt, uid, location))
return false; return false;
uid.Comp.StoredItems[GetNetEntity(insertEnt)] = location; uid.Comp.StoredItems[insertEnt] = location;
Dirty(uid, uid.Comp); Dirty(uid, uid.Comp);
if (Insert(uid, if (Insert(uid,
@@ -713,7 +754,7 @@ public abstract class SharedStorageSystem : EntitySystem
return true; return true;
} }
uid.Comp.StoredItems.Remove(GetNetEntity(insertEnt)); uid.Comp.StoredItems.Remove(insertEnt);
return false; return false;
} }
@@ -869,7 +910,7 @@ public abstract class SharedStorageSystem : EntitySystem
if (!ItemFitsInGridLocation(itemEnt, storageEnt, location.Position, location.Rotation)) if (!ItemFitsInGridLocation(itemEnt, storageEnt, location.Position, location.Rotation))
return false; return false;
storageEnt.Comp.StoredItems[GetNetEntity(itemEnt)] = location; storageEnt.Comp.StoredItems[itemEnt] = location;
Dirty(storageEnt, storageEnt.Comp); Dirty(storageEnt, storageEnt.Comp);
return true; return true;
} }
@@ -997,10 +1038,8 @@ public abstract class SharedStorageSystem : EntitySystem
if (!validGrid) if (!validGrid)
return false; return false;
foreach (var (netEnt, storedItem) in storageEnt.Comp.StoredItems) foreach (var (ent, storedItem) in storageEnt.Comp.StoredItems)
{ {
var ent = GetEntity(netEnt);
if (ent == itemEnt.Owner) if (ent == itemEnt.Owner)
continue; continue;
@@ -1102,4 +1141,16 @@ public abstract class SharedStorageSystem : EntitySystem
/// </summary> /// </summary>
public abstract void PlayPickupAnimation(EntityUid uid, EntityCoordinates initialCoordinates, public abstract void PlayPickupAnimation(EntityUid uid, EntityCoordinates initialCoordinates,
EntityCoordinates finalCoordinates, Angle initialRotation, EntityUid? user = null); EntityCoordinates finalCoordinates, Angle initialRotation, EntityUid? user = null);
[Serializable, NetSerializable]
protected sealed class StorageComponentState : ComponentState
{
public bool IsUiOpen;
public Dictionary<NetEntity, ItemStorageLocation> StoredItems = new();
public List<Box2i> Grid = new();
public ProtoId<ItemSizePrototype>? MaxItemSize;
}
} }

View File

@@ -14,13 +14,13 @@ namespace Content.Shared.Storage
/// <summary> /// <summary>
/// Handles generic storage with window, such as backpacks. /// Handles generic storage with window, such as backpacks.
/// </summary> /// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] [RegisterComponent, NetworkedComponent]
public sealed partial class StorageComponent : Component public sealed partial class StorageComponent : Component
{ {
public static string ContainerId = "storagebase"; public static string ContainerId = "storagebase";
// TODO: This fucking sucks // TODO: This fucking sucks
[ViewVariables(VVAccess.ReadWrite), DataField("isOpen"), AutoNetworkedField] [ViewVariables(VVAccess.ReadWrite), DataField]
public bool IsUiOpen; public bool IsUiOpen;
[ViewVariables] [ViewVariables]
@@ -29,69 +29,69 @@ namespace Content.Shared.Storage
/// <summary> /// <summary>
/// A dictionary storing each entity to its position within the storage grid. /// A dictionary storing each entity to its position within the storage grid.
/// </summary> /// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] [DataField, ViewVariables(VVAccess.ReadWrite)]
public Dictionary<NetEntity, ItemStorageLocation> StoredItems = new(); public Dictionary<EntityUid, ItemStorageLocation> StoredItems = 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>
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] [DataField, ViewVariables(VVAccess.ReadWrite)]
public List<Box2i> Grid = new(); public List<Box2i> Grid = new();
/// <summary> /// <summary>
/// The maximum size item that can be inserted into this storage, /// The maximum size item that can be inserted into this storage,
/// </summary> /// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] [DataField, ViewVariables(VVAccess.ReadWrite)]
[Access(typeof(SharedStorageSystem))] [Access(typeof(SharedStorageSystem))]
public ProtoId<ItemSizePrototype>? MaxItemSize; public ProtoId<ItemSizePrototype>? MaxItemSize;
// TODO: Make area insert its own component. // TODO: Make area insert its own component.
[DataField("quickInsert")] [DataField]
public bool QuickInsert; // Can insert storables by "attacking" them with the storage entity public bool QuickInsert; // Can insert storables by "attacking" them with the storage entity
[DataField("clickInsert")] [DataField]
public bool ClickInsert = true; // Can insert stuff by clicking the storage entity with it public bool ClickInsert = true; // Can insert stuff by clicking the storage entity with it
[DataField("areaInsert")] [DataField]
public bool AreaInsert; // "Attacking" with the storage entity causes it to insert all nearby storables after a delay public bool AreaInsert; // "Attacking" with the storage entity causes it to insert all nearby storables after a delay
[DataField("areaInsertRadius")] [DataField]
public int AreaInsertRadius = 1; public int AreaInsertRadius = 1;
/// <summary> /// <summary>
/// Whitelist for entities that can go into the storage. /// Whitelist for entities that can go into the storage.
/// </summary> /// </summary>
[DataField("whitelist")] [DataField]
public EntityWhitelist? Whitelist; public EntityWhitelist? Whitelist;
/// <summary> /// <summary>
/// Blacklist for entities that can go into storage. /// Blacklist for entities that can go into storage.
/// </summary> /// </summary>
[DataField("blacklist")] [DataField]
public EntityWhitelist? Blacklist; public EntityWhitelist? Blacklist;
/// <summary> /// <summary>
/// Sound played whenever an entity is inserted into storage. /// Sound played whenever an entity is inserted into storage.
/// </summary> /// </summary>
[DataField("storageInsertSound")] [DataField]
public SoundSpecifier? StorageInsertSound = new SoundCollectionSpecifier("storageRustle"); public SoundSpecifier? StorageInsertSound = new SoundCollectionSpecifier("storageRustle");
/// <summary> /// <summary>
/// Sound played whenever an entity is removed from storage. /// Sound played whenever an entity is removed from storage.
/// </summary> /// </summary>
[DataField("storageRemoveSound")] [DataField]
public SoundSpecifier? StorageRemoveSound; public SoundSpecifier? StorageRemoveSound;
/// <summary> /// <summary>
/// Sound played whenever the storage window is opened. /// Sound played whenever the storage window is opened.
/// </summary> /// </summary>
[DataField("storageOpenSound")] [DataField]
public SoundSpecifier? StorageOpenSound = new SoundCollectionSpecifier("storageRustle"); public SoundSpecifier? StorageOpenSound = new SoundCollectionSpecifier("storageRustle");
/// <summary> /// <summary>
/// Sound played whenever the storage window is closed. /// Sound played whenever the storage window is closed.
/// </summary> /// </summary>
[DataField("storageCloseSound")] [DataField]
public SoundSpecifier? StorageCloseSound; public SoundSpecifier? StorageCloseSound;
/// <summary> /// <summary>
@@ -103,7 +103,7 @@ namespace Content.Shared.Storage
public StorageDefaultOrientation? DefaultStorageOrientation; public StorageDefaultOrientation? DefaultStorageOrientation;
[Serializable, NetSerializable] [Serializable, NetSerializable]
public enum StorageUiKey public enum StorageUiKey : byte
{ {
Key, Key,
} }