Client LuaCsForBarotrauma
BarotraumaShared/SharedSource/Items/Components/Signal/ButtonTerminal.cs
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using System.Xml.Linq;
7 
9 {
10  partial class ButtonTerminal : ItemComponent
11  {
12  [Editable, Serialize(new string[0], IsPropertySaveable.Yes, description: "Signals sent when the corresponding buttons are pressed.", alwaysUseInstanceValues: true)]
13  public string[] Signals { get; set; }
14  [Editable, Serialize("", IsPropertySaveable.Yes, description: "Identifiers or tags of items that, when contained, allow the terminal buttons to be used. Multiple ones should be separated by commas.", alwaysUseInstanceValues: true)]
15  public string ActivatingItems { get; set; }
16 
17  private int RequiredSignalCount { get; set; }
18  private ItemContainer Container { get; set; }
19  private HashSet<ItemPrefab> ActivatingItemPrefabs { get; set; } = new HashSet<ItemPrefab>();
20 
21 
22  private bool AllowUsingButtons => ActivatingItemPrefabs.None() || (Container != null && Container.Inventory.AllItems.Any(i => i != null && ActivatingItemPrefabs.Any(p => p == i.Prefab)));
23 
24  public ButtonTerminal(Item item, ContentXElement element) : base(item, element)
25  {
26  RequiredSignalCount = element.GetChildElements("TerminalButton").Count(c => c.GetAttribute("style") != null);
27  if (RequiredSignalCount < 1)
28  {
29  DebugConsole.ThrowError($"Error in item \"{item.Name}\": no TerminalButton elements defined for the ButtonTerminal component!",
30  contentPackage: element.ContentPackage);
31  }
32  InitProjSpecific(element);
33  }
34 
35  partial void InitProjSpecific(ContentXElement element);
36 
37  public override void OnItemLoaded()
38  {
39  base.OnItemLoaded();
40 
41  if (Signals == null)
42  {
43  Signals = new string[RequiredSignalCount];
44  for (int i = 0; i < RequiredSignalCount; i++)
45  {
46  Signals[i] = string.Empty;
47  }
48  }
49  else if (Signals.Length != RequiredSignalCount)
50  {
51  string[] newSignals = new string[RequiredSignalCount];
52  if (Signals.Length < RequiredSignalCount)
53  {
54  Signals.CopyTo(newSignals, 0);
55  for (int i = Signals.Length; i < RequiredSignalCount; i++)
56  {
57  newSignals[i] = string.Empty;
58  }
59  }
60  else
61  {
62  for (int i = 0; i < RequiredSignalCount; i++)
63  {
64  newSignals[i] = Signals[i];
65  }
66  }
67  Signals = newSignals;
68  }
69 
70  ActivatingItemPrefabs.Clear();
71  if (!string.IsNullOrEmpty(ActivatingItems))
72  {
73  foreach (var activatingItem in ActivatingItems.Split(','))
74  {
75  if (MapEntityPrefab.Find(null, identifier: activatingItem, showErrorMessages: false) is ItemPrefab prefab)
76  {
77  ActivatingItemPrefabs.Add(prefab);
78  }
79  else
80  {
81  ItemPrefab.Prefabs.Where(p => p.Tags.Any(t => t == activatingItem))
82  .ForEach(p => ActivatingItemPrefabs.Add(p));
83  }
84  }
85  if (ActivatingItemPrefabs.None())
86  {
87  DebugConsole.ThrowError($"Error in item \"{item.Name}\": no activating item prefabs found with identifiers or tags \"{ActivatingItems}\"");
88  }
89  }
90 
91  var containers = item.GetComponents<ItemContainer>();
92  if (containers.Count() != 1)
93  {
94  DebugConsole.ThrowError($"Error in item \"{item.Name}\": the ButtonTerminal component requires exactly one ItemContainer component!");
95  return;
96  }
97  Container = containers.FirstOrDefault();
98 
99  OnItemLoadedProjSpecific();
100  }
101 
102  partial void OnItemLoadedProjSpecific();
103 
104  private bool SendSignal(int signalIndex, Character sender, bool isServerMessage = false)
105  {
106  if (!isServerMessage && !AllowUsingButtons) { return false; }
107  string signal = Signals[signalIndex];
108  string connectionName = $"signal_out{signalIndex + 1}";
109  item.SendSignal(new Signal(signal, sender: sender), connectionName);
110  return true;
111  }
112 
113  private readonly struct EventData : IEventData
114  {
115  public readonly int SignalIndex;
116 
117  public EventData(int signalIndex)
118  {
119  SignalIndex = signalIndex;
120  }
121  }
122 
123  public override bool ValidateEventData(NetEntityEvent.IData data)
124  => TryExtractEventData<EventData>(data, out _);
125 
126  private void Write(IWriteMessage msg, NetEntityEvent.IData extraData)
127  {
128  var eventData = ExtractEventData<EventData>(extraData);
129  msg.WriteRangedInteger(eventData.SignalIndex, 0, Signals.Length - 1);
130  }
131  }
132 }
ContentPackage? ContentPackage
IEnumerable< ContentXElement > GetChildElements(string name)
void SendSignal(string signal, string connectionName)
static readonly PrefabCollection< ItemPrefab > Prefabs
override bool ValidateEventData(NetEntityEvent.IData data)
override void OnItemLoaded()
Called when all the components of the item have been loaded. Use to initialize connections between co...
The base class for components holding the different functionalities of the item
static MapEntityPrefab Find(string name, string identifier=null, bool showErrorMessages=true)
Find a matching map entity prefab
void WriteRangedInteger(int val, int min, int max)