PartAssemblySystem.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. using Content.Shared.Construction.Components;
  2. using Content.Shared.Interaction;
  3. using Content.Shared.Tag;
  4. using Robust.Shared.Containers;
  5. namespace Content.Shared.Construction;
  6. /// <summary>
  7. /// This handles <see cref="PartAssemblyComponent"/>
  8. /// </summary>
  9. public sealed class PartAssemblySystem : EntitySystem
  10. {
  11. [Dependency] private readonly SharedContainerSystem _container = default!;
  12. [Dependency] private readonly TagSystem _tag = default!;
  13. /// <inheritdoc/>
  14. public override void Initialize()
  15. {
  16. SubscribeLocalEvent<PartAssemblyComponent, ComponentInit>(OnInit);
  17. SubscribeLocalEvent<PartAssemblyComponent, InteractUsingEvent>(OnInteractUsing);
  18. SubscribeLocalEvent<PartAssemblyComponent, EntRemovedFromContainerMessage>(OnEntRemoved);
  19. }
  20. private void OnInit(EntityUid uid, PartAssemblyComponent component, ComponentInit args)
  21. {
  22. component.PartsContainer = _container.EnsureContainer<Container>(uid, component.ContainerId);
  23. }
  24. private void OnInteractUsing(EntityUid uid, PartAssemblyComponent component, InteractUsingEvent args)
  25. {
  26. if (!TryInsertPart(args.Used, uid, component))
  27. return;
  28. args.Handled = true;
  29. }
  30. private void OnEntRemoved(EntityUid uid, PartAssemblyComponent component, EntRemovedFromContainerMessage args)
  31. {
  32. if (args.Container.ID != component.ContainerId)
  33. return;
  34. if (component.PartsContainer.ContainedEntities.Count != 0)
  35. return;
  36. component.CurrentAssembly = null;
  37. }
  38. /// <summary>
  39. /// Attempts to insert a part into the current assembly, starting one if there is none.
  40. /// </summary>
  41. public bool TryInsertPart(EntityUid part, EntityUid uid, PartAssemblyComponent? component = null)
  42. {
  43. if (!Resolve(uid, ref component))
  44. return false;
  45. string? assemblyId = null;
  46. assemblyId ??= component.CurrentAssembly;
  47. if (assemblyId == null)
  48. {
  49. foreach (var (id, tags) in component.Parts)
  50. {
  51. foreach (var tag in tags)
  52. {
  53. if (!_tag.HasTag(part, tag))
  54. continue;
  55. assemblyId = id;
  56. break;
  57. }
  58. if (assemblyId != null)
  59. break;
  60. }
  61. }
  62. if (assemblyId == null)
  63. return false;
  64. if (!IsPartValid(uid, part, assemblyId, component))
  65. return false;
  66. component.CurrentAssembly = assemblyId;
  67. _container.Insert(part, component.PartsContainer);
  68. var ev = new PartAssemblyPartInsertedEvent();
  69. RaiseLocalEvent(uid, ev);
  70. return true;
  71. }
  72. /// <summary>
  73. /// Checks if the given entity is a valid item for the assembly.
  74. /// </summary>
  75. public bool IsPartValid(EntityUid uid, EntityUid part, string assemblyId, PartAssemblyComponent? component = null)
  76. {
  77. if (!Resolve(uid, ref component, false))
  78. return true;
  79. if (!component.Parts.TryGetValue(assemblyId, out var tags))
  80. return false;
  81. var openTags = new List<string>(tags);
  82. var contained = new List<EntityUid>(component.PartsContainer.ContainedEntities);
  83. foreach (var tag in tags)
  84. {
  85. foreach (var ent in component.PartsContainer.ContainedEntities)
  86. {
  87. if (!contained.Contains(ent) || !_tag.HasTag(ent, tag))
  88. continue;
  89. openTags.Remove(tag);
  90. contained.Remove(ent);
  91. break;
  92. }
  93. }
  94. foreach (var tag in openTags)
  95. {
  96. if (_tag.HasTag(part, tag))
  97. return true;
  98. }
  99. return false;
  100. }
  101. public bool IsAssemblyFinished(EntityUid uid, string assemblyId, PartAssemblyComponent? component = null)
  102. {
  103. if (!Resolve(uid, ref component, false))
  104. return true;
  105. if (!component.Parts.TryGetValue(assemblyId, out var parts))
  106. return false;
  107. var contained = new List<EntityUid>(component.PartsContainer.ContainedEntities);
  108. foreach (var tag in parts)
  109. {
  110. var valid = false;
  111. foreach (var ent in new List<EntityUid>(contained))
  112. {
  113. if (!_tag.HasTag(ent, tag))
  114. continue;
  115. valid = true;
  116. contained.Remove(ent);
  117. break;
  118. }
  119. if (!valid)
  120. return false;
  121. }
  122. return true;
  123. }
  124. }