ContainerFillComponent.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. using Content.Shared.Storage;
  2. using Content.Shared.Storage.Components;
  3. using Robust.Shared.Prototypes;
  4. using Robust.Shared.Serialization.Manager;
  5. using Robust.Shared.Serialization.Markdown.Mapping;
  6. using Robust.Shared.Serialization.Markdown.Sequence;
  7. using Robust.Shared.Serialization.Markdown.Validation;
  8. using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
  9. using Robust.Shared.Serialization.TypeSerializers.Interfaces;
  10. namespace Content.Shared.Containers;
  11. /// <summary>
  12. /// Component for spawning entity prototypes into containers on map init.
  13. /// </summary>
  14. /// <remarks>
  15. /// Unlike <see cref="StorageFillComponent"/> this is deterministic and supports arbitrary containers. While this
  16. /// could maybe be merged with that component, it would require significant changes to <see
  17. /// cref="EntitySpawnCollection.GetSpawns"/>, which is also used by several other systems.
  18. /// </remarks>
  19. [RegisterComponent]
  20. public sealed partial class ContainerFillComponent : Component
  21. {
  22. [DataField("containers", customTypeSerializer:typeof(ContainerFillSerializer))]
  23. public Dictionary<string, List<string>> Containers = new();
  24. /// <summary>
  25. /// If true, entities spawned via the construction system will not have entities spawned into containers managed
  26. /// by the construction system.
  27. /// </summary>
  28. [DataField("ignoreConstructionSpawn")]
  29. public bool IgnoreConstructionSpawn = true;
  30. }
  31. // all of this exists just to validate prototype ids.
  32. // it would be nice if you could specify only a type validator and not have to re-implement everything else.
  33. // or a dictionary serializer that accepts a custom type serializer for the dictionary values
  34. public sealed class ContainerFillSerializer : ITypeValidator<Dictionary<string, List<string>>, MappingDataNode>
  35. {
  36. private static PrototypeIdListSerializer<EntityPrototype> ListSerializer => new();
  37. public ValidationNode Validate(
  38. ISerializationManager serializationManager,
  39. MappingDataNode node,
  40. IDependencyCollection dependencies,
  41. ISerializationContext? context = null)
  42. {
  43. var mapping = new Dictionary<ValidationNode, ValidationNode>();
  44. foreach (var (key, val) in node.Children)
  45. {
  46. var keyVal = serializationManager.ValidateNode<string>(key, context);
  47. var listVal = (val is SequenceDataNode seq)
  48. ? ListSerializer.Validate(serializationManager, seq, dependencies, context)
  49. : new ErrorNode(val, "ContainerFillComponent prototypes must be a sequence/list");
  50. mapping.Add(keyVal, listVal);
  51. }
  52. return new ValidatedMappingNode(mapping);
  53. }
  54. }