Adds disposal mailing units (again) (#7630)
This commit is contained in:
@@ -47,9 +47,9 @@ namespace Content.Client.Disposal.Systems
|
||||
|
||||
foreach (var inter in userInterface.Interfaces)
|
||||
{
|
||||
if (inter is DisposalUnitBoundUserInterface disposals)
|
||||
if (inter is DisposalUnitBoundUserInterface boundInterface)
|
||||
{
|
||||
return disposals.Window?.UpdateState(state) != false;
|
||||
return boundInterface.UpdateWindowState(state) != false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using Content.Client.Disposal.Components;
|
||||
using Content.Client.Disposal.Systems;
|
||||
using Content.Shared.Disposal;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using static Content.Shared.Disposal.Components.SharedDisposalUnitComponent;
|
||||
@@ -9,12 +12,13 @@ using static Content.Shared.Disposal.Components.SharedDisposalUnitComponent;
|
||||
namespace Content.Client.Disposal.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a <see cref="DisposalUnitWindow"/> and updates it when new server messages are received.
|
||||
/// Initializes a <see cref="MailingUnitWindow"/> or a <see cref="DisposalUnitWindow"/> and updates it when new server messages are received.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public sealed class DisposalUnitBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
public DisposalUnitWindow? Window;
|
||||
public MailingUnitWindow? MailingUnitWindow;
|
||||
public DisposalUnitWindow? DisposalUnitWindow;
|
||||
|
||||
public DisposalUnitBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
|
||||
{
|
||||
@@ -27,35 +31,66 @@ namespace Content.Client.Disposal.UI
|
||||
// the pressure lerp up.
|
||||
}
|
||||
|
||||
private void TargetSelected(ItemList.ItemListSelectedEventArgs args)
|
||||
{
|
||||
var item = args.ItemList[args.ItemIndex];
|
||||
SendMessage(new TargetSelectedMessage(item.Text));
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
Window = new DisposalUnitWindow();
|
||||
if (UiKey is MailingUnitUiKey)
|
||||
{
|
||||
MailingUnitWindow = new MailingUnitWindow();
|
||||
|
||||
Window.OpenCentered();
|
||||
Window.OnClose += Close;
|
||||
MailingUnitWindow.OpenCenteredRight();
|
||||
MailingUnitWindow.OnClose += Close;
|
||||
|
||||
Window.Eject.OnPressed += _ => ButtonPressed(UiButton.Eject);
|
||||
Window.Engage.OnPressed += _ => ButtonPressed(UiButton.Engage);
|
||||
Window.Power.OnPressed += _ => ButtonPressed(UiButton.Power);
|
||||
MailingUnitWindow.Eject.OnPressed += _ => ButtonPressed(UiButton.Eject);
|
||||
MailingUnitWindow.Engage.OnPressed += _ => ButtonPressed(UiButton.Engage);
|
||||
MailingUnitWindow.Power.OnPressed += _ => ButtonPressed(UiButton.Power);
|
||||
|
||||
MailingUnitWindow.TargetListContainer.OnItemSelected += TargetSelected;
|
||||
}
|
||||
else if(UiKey is DisposalUnitUiKey)
|
||||
{
|
||||
DisposalUnitWindow = new DisposalUnitWindow();
|
||||
|
||||
DisposalUnitWindow.OpenCenteredRight();
|
||||
DisposalUnitWindow.OnClose += Close;
|
||||
|
||||
DisposalUnitWindow.Eject.OnPressed += _ => ButtonPressed(UiButton.Eject);
|
||||
DisposalUnitWindow.Engage.OnPressed += _ => ButtonPressed(UiButton.Engage);
|
||||
DisposalUnitWindow.Power.OnPressed += _ => ButtonPressed(UiButton.Power);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
if (state is not DisposalUnitBoundUserInterfaceState cast)
|
||||
if (state is not MailingUnitBoundUserInterfaceState && state is not DisposalUnitBoundUserInterfaceState)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Window?.UpdateState(cast);
|
||||
|
||||
// Kinda icky but we just want client to handle its own lerping and not flood bandwidth for it.
|
||||
if (!IoCManager.Resolve<IEntityManager>().TryGetComponent(Owner.Owner, out DisposalUnitComponent? component)) return;
|
||||
|
||||
component.UiState = cast;
|
||||
switch (state)
|
||||
{
|
||||
case MailingUnitBoundUserInterfaceState mailingUnitState:
|
||||
MailingUnitWindow?.UpdateState(mailingUnitState);
|
||||
component.UiState = mailingUnitState.DisposalState;
|
||||
break;
|
||||
|
||||
case DisposalUnitBoundUserInterfaceState disposalUnitState:
|
||||
DisposalUnitWindow?.UpdateState(disposalUnitState);
|
||||
component.UiState = disposalUnitState;
|
||||
break;
|
||||
}
|
||||
|
||||
EntitySystem.Get<DisposalUnitSystem>().UpdateActive(component, true);
|
||||
}
|
||||
|
||||
@@ -63,10 +98,17 @@ namespace Content.Client.Disposal.UI
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
if (disposing)
|
||||
if (!disposing) return;
|
||||
|
||||
MailingUnitWindow?.Dispose();
|
||||
DisposalUnitWindow?.Dispose();
|
||||
}
|
||||
|
||||
public bool? UpdateWindowState(DisposalUnitBoundUserInterfaceState state)
|
||||
{
|
||||
Window?.Dispose();
|
||||
}
|
||||
return UiKey is DisposalUnitUiKey
|
||||
? DisposalUnitWindow?.UpdateState(state)
|
||||
: MailingUnitWindow?.UpdatePressure(state.FullPressureTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
xmlns:ui="clr-namespace:Content.Client.Disposal.UI"
|
||||
MinSize="300 140"
|
||||
SetSize="300 140"
|
||||
Resizable="False">
|
||||
@@ -13,7 +14,7 @@
|
||||
<BoxContainer Orientation="Horizontal"
|
||||
SeparationOverride="4">
|
||||
<Label Text="{Loc 'ui-disposal-unit-label-pressure'}" />
|
||||
<ProgressBar Name="PressureBar"
|
||||
<ui:PressureBar Name="PressureBar"
|
||||
MinSize="190 20"
|
||||
HorizontalAlignment="Right"
|
||||
MinValue="0"
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
using System;
|
||||
using Content.Shared.Disposal;
|
||||
using Content.Shared.Disposal.Components;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Timing;
|
||||
using static Content.Shared.Disposal.Components.SharedDisposalUnitComponent;
|
||||
|
||||
namespace Content.Client.Disposal.UI
|
||||
@@ -25,60 +18,18 @@ namespace Content.Client.Disposal.UI
|
||||
RobustXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void UpdatePressureBar(float pressure)
|
||||
{
|
||||
PressureBar.Value = pressure;
|
||||
|
||||
var normalized = pressure / PressureBar.MaxValue;
|
||||
|
||||
const float leftHue = 0.0f; // Red
|
||||
const float middleHue = 0.066f; // Orange
|
||||
const float rightHue = 0.33f; // Green
|
||||
const float saturation = 1.0f; // Uniform saturation
|
||||
const float value = 0.8f; // Uniform value / brightness
|
||||
const float alpha = 1.0f; // Uniform alpha
|
||||
|
||||
// These should add up to 1.0 or your transition won't be smooth
|
||||
const float leftSideSize = 0.5f; // Fraction of _chargeBar lerped from leftHue to middleHue
|
||||
const float rightSideSize = 0.5f; // Fraction of _chargeBar lerped from middleHue to rightHue
|
||||
|
||||
float finalHue;
|
||||
if (normalized <= leftSideSize)
|
||||
{
|
||||
normalized /= leftSideSize; // Adjust range to 0.0 to 1.0
|
||||
finalHue = MathHelper.Lerp(leftHue, middleHue, normalized);
|
||||
}
|
||||
else
|
||||
{
|
||||
normalized = (normalized - leftSideSize) / rightSideSize; // Adjust range to 0.0 to 1.0.
|
||||
finalHue = MathHelper.Lerp(middleHue, rightHue, normalized);
|
||||
}
|
||||
|
||||
// Check if null first to avoid repeatedly creating this.
|
||||
PressureBar.ForegroundStyleBoxOverride ??= new StyleBoxFlat();
|
||||
|
||||
var foregroundStyleBoxOverride = (StyleBoxFlat) PressureBar.ForegroundStyleBoxOverride;
|
||||
foregroundStyleBoxOverride.BackgroundColor =
|
||||
Color.FromHsv(new Vector4(finalHue, saturation, value, alpha));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the interface state for the disposals window.
|
||||
/// </summary>
|
||||
/// <returns>true if we should stop updating every frame.</returns>
|
||||
public bool UpdateState(DisposalUnitBoundUserInterfaceState state)
|
||||
{
|
||||
var currentTime = IoCManager.Resolve<IGameTiming>().CurTime;
|
||||
var fullTime = state.FullPressureTime;
|
||||
var pressure = (float) Math.Min(1.0f, 1.0f - (fullTime.TotalSeconds - currentTime.TotalSeconds) * SharedDisposalUnitSystem.PressurePerSecond);
|
||||
|
||||
Title = state.UnitName;
|
||||
UnitState.Text = state.UnitState;
|
||||
UpdatePressureBar(pressure);
|
||||
Power.Pressed = state.Powered;
|
||||
Engage.Pressed = state.Engaged;
|
||||
|
||||
return !state.Powered || pressure >= 1.0f;
|
||||
return !state.Powered || PressureBar.UpdatePressure(state.FullPressureTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
53
Content.Client/Disposal/UI/MailingUnitWindow.xaml
Normal file
53
Content.Client/Disposal/UI/MailingUnitWindow.xaml
Normal file
@@ -0,0 +1,53 @@
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
xmlns:ui="clr-namespace:Content.Client.Disposal.UI"
|
||||
MinSize="300 400"
|
||||
SetSize="300 400"
|
||||
Resizable="False">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<BoxContainer Orientation="Horizontal" SeparationOverride="8">
|
||||
<Label Text="{Loc 'ui-mailing-unit-target-label'}" />
|
||||
<Label Name="Target"
|
||||
Text="" />
|
||||
</BoxContainer>
|
||||
<ItemList Name="TargetListContainer"
|
||||
Access="Public"
|
||||
SelectMode="Single"
|
||||
VerticalExpand="True"
|
||||
HorizontalExpand="True"
|
||||
Margin="0 0 0 16">
|
||||
</ItemList>
|
||||
<BoxContainer Orientation="Horizontal" SeparationOverride="4">
|
||||
<Label Text="{Loc 'ui-disposal-unit-label-state'}" />
|
||||
<Label Name="UnitState"
|
||||
Text="{Loc 'ui-disposal-unit-label-status'}" />
|
||||
</BoxContainer>
|
||||
<Control MinSize="0 5" />
|
||||
<BoxContainer Orientation="Horizontal"
|
||||
SeparationOverride="4">
|
||||
<Label Text="{Loc 'ui-disposal-unit-label-pressure'}" />
|
||||
<ui:PressureBar Name="PressureBar"
|
||||
MinSize="190 20"
|
||||
HorizontalAlignment="Right"
|
||||
MinValue="0"
|
||||
MaxValue="1"
|
||||
Page="0"
|
||||
Value="0.5" />
|
||||
</BoxContainer>
|
||||
<Control MinSize="0 10" />
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<Button Name="Engage"
|
||||
Access="Public"
|
||||
Text="{Loc 'ui-mailing-unit-button-flush'}"
|
||||
StyleClasses="OpenRight"
|
||||
ToggleMode="True" />
|
||||
<Button Name="Eject"
|
||||
Access="Public"
|
||||
Text="{Loc 'ui-disposal-unit-button-eject'}"
|
||||
StyleClasses="OpenBoth" />
|
||||
<CheckButton Name="Power"
|
||||
Access="Public"
|
||||
Text="{Loc 'ui-disposal-unit-button-power'}"
|
||||
StyleClasses="OpenLeft" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</DefaultWindow>
|
||||
50
Content.Client/Disposal/UI/MailingUnitWindow.xaml.cs
Normal file
50
Content.Client/Disposal/UI/MailingUnitWindow.xaml.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using Content.Shared.Disposal;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Disposal.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Client-side UI used to control a <see cref="MailingUnitComponent"/>
|
||||
/// </summary>
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class MailingUnitWindow : DefaultWindow
|
||||
{
|
||||
public MailingUnitWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the interface state for the disposals window.
|
||||
/// </summary>
|
||||
/// <returns>true if we should stop updating every frame.</returns>
|
||||
public bool UpdateState(MailingUnitBoundUserInterfaceState state)
|
||||
{
|
||||
var disposalState = state.DisposalState;
|
||||
|
||||
Title = Loc.GetString("ui-mailing-unit-window-title", ("tag", state.Tag ?? " "));
|
||||
UnitState.Text = disposalState.UnitState;
|
||||
var pressureReached = PressureBar.UpdatePressure(disposalState.FullPressureTime);
|
||||
Power.Pressed = disposalState.Powered;
|
||||
Engage.Pressed = disposalState.Engaged;
|
||||
|
||||
//UnitTag.Text = state.Tag;
|
||||
Target.Text = state.Target;
|
||||
|
||||
TargetListContainer.Clear();
|
||||
foreach (var target in state.TargetList)
|
||||
{
|
||||
TargetListContainer.AddItem(target);
|
||||
}
|
||||
|
||||
return !disposalState.Powered || pressureReached;
|
||||
}
|
||||
|
||||
public bool UpdatePressure(TimeSpan stateFullPressureTime)
|
||||
{
|
||||
return PressureBar.UpdatePressure(stateFullPressureTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
54
Content.Client/Disposal/UI/PressureBar.cs
Normal file
54
Content.Client/Disposal/UI/PressureBar.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using Content.Shared.Disposal;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Disposal.UI;
|
||||
|
||||
public sealed class PressureBar : ProgressBar
|
||||
{
|
||||
public bool UpdatePressure(TimeSpan fullTime)
|
||||
{
|
||||
var currentTime = IoCManager.Resolve<IGameTiming>().CurTime;
|
||||
var pressure = (float) Math.Min(1.0f, 1.0f - (fullTime.TotalSeconds - currentTime.TotalSeconds) * SharedDisposalUnitSystem.PressurePerSecond);
|
||||
UpdatePressureBar(pressure);
|
||||
return pressure >= 1.0f;
|
||||
}
|
||||
|
||||
private void UpdatePressureBar(float pressure)
|
||||
{
|
||||
Value = pressure;
|
||||
|
||||
var normalized = pressure / MaxValue;
|
||||
|
||||
const float leftHue = 0.0f; // Red
|
||||
const float middleHue = 0.066f; // Orange
|
||||
const float rightHue = 0.33f; // Green
|
||||
const float saturation = 1.0f; // Uniform saturation
|
||||
const float value = 0.8f; // Uniform value / brightness
|
||||
const float alpha = 1.0f; // Uniform alpha
|
||||
|
||||
// These should add up to 1.0 or your transition won't be smooth
|
||||
const float leftSideSize = 0.5f; // Fraction of _chargeBar lerped from leftHue to middleHue
|
||||
const float rightSideSize = 0.5f; // Fraction of _chargeBar lerped from middleHue to rightHue
|
||||
|
||||
float finalHue;
|
||||
if (normalized <= leftSideSize)
|
||||
{
|
||||
normalized /= leftSideSize; // Adjust range to 0.0 to 1.0
|
||||
finalHue = MathHelper.Lerp(leftHue, middleHue, normalized);
|
||||
}
|
||||
else
|
||||
{
|
||||
normalized = (normalized - leftSideSize) / rightSideSize; // Adjust range to 0.0 to 1.0.
|
||||
finalHue = MathHelper.Lerp(middleHue, rightHue, normalized);
|
||||
}
|
||||
|
||||
// Check if null first to avoid repeatedly creating this.
|
||||
ForegroundStyleBoxOverride ??= new StyleBoxFlat();
|
||||
|
||||
var foregroundStyleBoxOverride = (StyleBoxFlat) ForegroundStyleBoxOverride;
|
||||
foregroundStyleBoxOverride.BackgroundColor =
|
||||
Color.FromHsv(new Vector4(finalHue, saturation, value, alpha));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Tools.Components;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Containers;
|
||||
using static Content.Shared.Configurable.SharedConfigurationComponent;
|
||||
|
||||
namespace Content.Server.Configurable;
|
||||
@@ -16,6 +17,7 @@ public sealed class ConfigurationSystem : EntitySystem
|
||||
SubscribeLocalEvent<ConfigurationComponent, ConfigurationUpdatedMessage>(OnUpdate);
|
||||
SubscribeLocalEvent<ConfigurationComponent, ComponentStartup>(OnStartup);
|
||||
SubscribeLocalEvent<ConfigurationComponent, InteractUsingEvent>(OnInteractUsing);
|
||||
SubscribeLocalEvent<ConfigurationComponent, ContainerIsInsertingAttemptEvent>(OnInsert);
|
||||
}
|
||||
|
||||
private void OnInteractUsing(EntityUid uid, ConfigurationComponent component, InteractUsingEvent args)
|
||||
@@ -57,8 +59,31 @@ public sealed class ConfigurationSystem : EntitySystem
|
||||
|
||||
UpdateUi(uid, component);
|
||||
|
||||
// TODO raise event.
|
||||
var updatedEvent = new ConfigurationUpdatedEvent(component);
|
||||
RaiseLocalEvent(uid, updatedEvent, false);
|
||||
|
||||
// TODO support float (spinbox) and enum (drop-down) configurations
|
||||
// TODO support verbs.
|
||||
}
|
||||
|
||||
private void OnInsert(EntityUid uid, ConfigurationComponent component, ContainerIsInsertingAttemptEvent args)
|
||||
{
|
||||
if (!TryComp(args.EntityUid, out ToolComponent? tool) || !tool.Qualities.Contains(component.QualityNeeded))
|
||||
return;
|
||||
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sent when configuration values got changes
|
||||
/// </summary>
|
||||
public sealed class ConfigurationUpdatedEvent : EntityEventArgs
|
||||
{
|
||||
public ConfigurationComponent Configuration;
|
||||
|
||||
public ConfigurationUpdatedEvent(ConfigurationComponent configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
30
Content.Server/Disposal/Mailing/MailingUnitComponent.cs
Normal file
30
Content.Server/Disposal/Mailing/MailingUnitComponent.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Content.Shared.Disposal.Components;
|
||||
|
||||
namespace Content.Server.Disposal.Mailing;
|
||||
|
||||
[Access(typeof(MailingUnitSystem))]
|
||||
[RegisterComponent]
|
||||
public sealed class MailingUnitComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// List of targets the mailing unit can send to.
|
||||
/// Each target is just a disposal routing tag
|
||||
/// </summary>
|
||||
[DataField("targetList")]
|
||||
public readonly List<string> TargetList = new();
|
||||
|
||||
/// <summary>
|
||||
/// The target that gets attached to the disposal holders tag list on flush
|
||||
/// </summary>
|
||||
[DataField("target")]
|
||||
public string? Target;
|
||||
|
||||
/// <summary>
|
||||
/// The tag for this mailing unit
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("tag")]
|
||||
public string? Tag;
|
||||
|
||||
public SharedDisposalUnitComponent.DisposalUnitBoundUserInterfaceState? DisposalUnitInterfaceState;
|
||||
}
|
||||
205
Content.Server/Disposal/Mailing/MailingUnitSystem.cs
Normal file
205
Content.Server/Disposal/Mailing/MailingUnitSystem.cs
Normal file
@@ -0,0 +1,205 @@
|
||||
using Content.Server.Configurable;
|
||||
using Content.Server.DeviceNetwork;
|
||||
using Content.Server.DeviceNetwork.Components;
|
||||
using Content.Server.DeviceNetwork.Systems;
|
||||
using Content.Server.Disposal.Unit.EntitySystems;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.UserInterface;
|
||||
using Content.Shared.Disposal;
|
||||
using Content.Shared.Interaction;
|
||||
using Robust.Server.GameObjects;
|
||||
|
||||
namespace Content.Server.Disposal.Mailing;
|
||||
|
||||
public sealed class MailingUnitSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
||||
|
||||
private const string MailTag = "mail";
|
||||
|
||||
private const string TagConfigurationKey = "tag";
|
||||
|
||||
private const string NetTag = "tag";
|
||||
private const string NetSrc = "src";
|
||||
private const string NetTarget = "target";
|
||||
private const string NetCmdSent = "mail_sent";
|
||||
private const string NetCmdRequest = "get_mailer_tag";
|
||||
private const string NetCmdResponse = "mailer_tag";
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<MailingUnitComponent, ComponentInit>(OnComponentInit);
|
||||
SubscribeLocalEvent<MailingUnitComponent, DeviceNetworkPacketEvent>(OnPacketReceived);
|
||||
SubscribeLocalEvent<MailingUnitComponent, DisposalUnitSystem.BeforeDisposalFlushEvent>(OnBeforeFlush);
|
||||
SubscribeLocalEvent<MailingUnitComponent, ConfigurationSystem.ConfigurationUpdatedEvent>(OnConfigurationUpdated);
|
||||
SubscribeLocalEvent<MailingUnitComponent, ActivateInWorldEvent>(HandleActivate);
|
||||
SubscribeLocalEvent<MailingUnitComponent, DisposalUnitSystem.DisposalUnitUIStateUpdatedEvent>(OnDisposalUnitUIStateChange);
|
||||
SubscribeLocalEvent<MailingUnitComponent, TargetSelectedMessage>(OnTargetSelected);
|
||||
}
|
||||
|
||||
|
||||
private void OnComponentInit(EntityUid uid, MailingUnitComponent component, ComponentInit args)
|
||||
{
|
||||
UpdateTargetList(uid, component);
|
||||
}
|
||||
|
||||
private void OnPacketReceived(EntityUid uid, MailingUnitComponent component, DeviceNetworkPacketEvent args)
|
||||
{
|
||||
if (!args.Data.TryGetValue(DeviceNetworkConstants.Command, out string? command) || !IsPowered(uid))
|
||||
return;
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case NetCmdRequest:
|
||||
SendTagRequestResponse(uid, args, component.Tag);
|
||||
break;
|
||||
case NetCmdResponse when args.Data.TryGetValue(NetTag, out string? tag):
|
||||
//Add the received tag request response to the list of targets
|
||||
component.TargetList.Add(tag!);
|
||||
UpdateUserInterface(component);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the given tag as a response to a <see cref="NetCmdRequest"/> if it's not null
|
||||
/// </summary>
|
||||
private void SendTagRequestResponse(EntityUid uid, DeviceNetworkPacketEvent args, string? tag)
|
||||
{
|
||||
if (tag == null)
|
||||
return;
|
||||
|
||||
var payload = new NetworkPayload
|
||||
{
|
||||
[DeviceNetworkConstants.Command] = NetCmdResponse,
|
||||
[NetTag] = tag
|
||||
};
|
||||
|
||||
_deviceNetworkSystem.QueuePacket(uid, args.Address, payload, args.Frequency);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prevents the unit from flushing if no target is selected
|
||||
/// </summary>
|
||||
private void OnBeforeFlush(EntityUid uid, MailingUnitComponent component, DisposalUnitSystem.BeforeDisposalFlushEvent args)
|
||||
{
|
||||
if (string.IsNullOrEmpty(component.Target))
|
||||
{
|
||||
args.Cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
args.Tags.Add(MailTag);
|
||||
args.Tags.Add(component.Target);
|
||||
|
||||
BroadcastSentMessage(uid, component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcast that a mail was sent including the src and target tags
|
||||
/// </summary>
|
||||
private void BroadcastSentMessage(EntityUid uid, MailingUnitComponent component, DeviceNetworkComponent? device = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(component.Tag) || string.IsNullOrEmpty(component.Target) || !Resolve(uid, ref device))
|
||||
return;
|
||||
|
||||
var payload = new NetworkPayload
|
||||
{
|
||||
[DeviceNetworkConstants.Command] = NetCmdSent,
|
||||
[NetSrc] = component.Tag,
|
||||
[NetTarget] = component.Target
|
||||
};
|
||||
|
||||
_deviceNetworkSystem.QueuePacket(uid, null, payload, null, device);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the units target list and broadcasts a <see cref="NetCmdRequest"/>.
|
||||
/// The target list will then get populated with <see cref="NetCmdResponse"/> responses from all active mailing units on the same grid
|
||||
/// </summary>
|
||||
private void UpdateTargetList(EntityUid uid, MailingUnitComponent component, DeviceNetworkComponent? device = null)
|
||||
{
|
||||
if (!Resolve(uid, ref device, false))
|
||||
return;
|
||||
|
||||
var payload = new NetworkPayload
|
||||
{
|
||||
[DeviceNetworkConstants.Command] = NetCmdRequest
|
||||
};
|
||||
|
||||
component.TargetList.Clear();
|
||||
_deviceNetworkSystem.QueuePacket(uid, null, payload, null, device);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets called when the units tag got updated
|
||||
/// </summary>
|
||||
private void OnConfigurationUpdated(EntityUid uid, MailingUnitComponent component, ConfigurationSystem.ConfigurationUpdatedEvent args)
|
||||
{
|
||||
var configuration = args.Configuration.Config;
|
||||
if (!configuration.ContainsKey(TagConfigurationKey) || configuration[TagConfigurationKey] == string.Empty)
|
||||
{
|
||||
component.Tag = null;
|
||||
return;
|
||||
}
|
||||
|
||||
component.Tag = configuration[TagConfigurationKey];
|
||||
UpdateUserInterface(component);
|
||||
}
|
||||
|
||||
private void HandleActivate(EntityUid uid, MailingUnitComponent component, ActivateInWorldEvent args)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
args.Handled = true;
|
||||
UpdateTargetList(uid, component);
|
||||
_userInterfaceSystem.GetUiOrNull(uid, MailingUnitUiKey.Key)?.Open(actor.PlayerSession);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets called when the disposal unit components ui state changes. This is required because the mailing unit requires a disposal unit component and overrides its ui
|
||||
/// </summary>
|
||||
private void OnDisposalUnitUIStateChange(EntityUid uid, MailingUnitComponent component, DisposalUnitSystem.DisposalUnitUIStateUpdatedEvent args)
|
||||
{
|
||||
component.DisposalUnitInterfaceState = args.State;
|
||||
UpdateUserInterface(component);
|
||||
}
|
||||
|
||||
private void UpdateUserInterface(MailingUnitComponent component)
|
||||
{
|
||||
if (component.DisposalUnitInterfaceState == null)
|
||||
return;
|
||||
|
||||
var state = new MailingUnitBoundUserInterfaceState(component.DisposalUnitInterfaceState, component.Target, component.TargetList, component.Tag);
|
||||
component.Owner.GetUIOrNull(MailingUnitUiKey.Key)?.SetState(state);
|
||||
}
|
||||
|
||||
private void OnTargetSelected(EntityUid uid, MailingUnitComponent component, TargetSelectedMessage args)
|
||||
{
|
||||
if (string.IsNullOrEmpty(args.target))
|
||||
{
|
||||
component.Target = null;
|
||||
}
|
||||
|
||||
component.Target = args.target;
|
||||
UpdateUserInterface(component);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the unit is powered if an <see cref="ApcPowerReceiverComponent"/> is present
|
||||
/// </summary>
|
||||
/// <returns>True if the power receiver component is powered or not present</returns>
|
||||
private bool IsPowered(EntityUid uid, ApcPowerReceiverComponent? powerReceiver = null)
|
||||
{
|
||||
if (Resolve(uid, ref powerReceiver) && !powerReceiver.Powered)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Disposal.Unit.Components;
|
||||
using Content.Server.Disposal.Unit.EntitySystems;
|
||||
@@ -14,7 +14,7 @@ namespace Content.Server.Disposal.Tube.Components
|
||||
|
||||
private const string HolderPrototypeId = "DisposalHolder";
|
||||
|
||||
public bool TryInsert(DisposalUnitComponent from)
|
||||
public bool TryInsert(DisposalUnitComponent from, IEnumerable<string>? tags = default)
|
||||
{
|
||||
var holder = _entMan.SpawnEntity(HolderPrototypeId, _entMan.GetComponent<TransformComponent>(Owner).MapPosition);
|
||||
var holderComponent = _entMan.GetComponent<DisposalHolderComponent>(holder);
|
||||
@@ -27,6 +27,9 @@ namespace Content.Server.Disposal.Tube.Components
|
||||
EntitySystem.Get<AtmosphereSystem>().Merge(holderComponent.Air, from.Air);
|
||||
from.Air.Clear();
|
||||
|
||||
if (tags != default)
|
||||
holderComponent.Tags.UnionWith(tags);
|
||||
|
||||
return EntitySystem.Get<DisposableSystem>().EnterTube((holderComponent).Owner, Owner, holderComponent, null, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,45 +26,11 @@ namespace Content.Server.Disposal.Tube
|
||||
SubscribeLocalEvent<DisposalTubeComponent, PhysicsBodyTypeChangedEvent>(BodyTypeChanged);
|
||||
SubscribeLocalEvent<DisposalTubeComponent, ContainerRelayMovementEntityEvent>(OnRelayMovement);
|
||||
SubscribeLocalEvent<DisposalTubeComponent, BreakageEventArgs>(OnBreak);
|
||||
SubscribeLocalEvent<DisposalTaggerComponent, GetVerbsEvent<InteractionVerb>>(AddOpenUIVerbs);
|
||||
SubscribeLocalEvent<DisposalRouterComponent, GetVerbsEvent<InteractionVerb>>(AddOpenUIVerbs);
|
||||
SubscribeLocalEvent<DisposalRouterComponent, ActivatableUIOpenAttemptEvent>(OnOpenRouterUIAttempt);
|
||||
SubscribeLocalEvent<DisposalTaggerComponent, ActivatableUIOpenAttemptEvent>(OnOpenTaggerUIAttempt);
|
||||
|
||||
}
|
||||
|
||||
private void AddOpenUIVerbs(EntityUid uid, DisposalTaggerComponent component, GetVerbsEvent<InteractionVerb> args)
|
||||
{
|
||||
if (!args.CanAccess || !args.CanInteract)
|
||||
return;
|
||||
|
||||
if (!EntityManager.TryGetComponent<ActorComponent?>(args.User, out var actor))
|
||||
return;
|
||||
var player = actor.PlayerSession;
|
||||
|
||||
InteractionVerb verb = new();
|
||||
verb.Text = Loc.GetString("configure-verb-get-data-text");
|
||||
verb.IconTexture = "/Textures/Interface/VerbIcons/settings.svg.192dpi.png";
|
||||
verb.Act = () => component.OpenUserInterface(actor);
|
||||
args.Verbs.Add(verb);
|
||||
}
|
||||
|
||||
private void AddOpenUIVerbs(EntityUid uid, DisposalRouterComponent component, GetVerbsEvent<InteractionVerb> args)
|
||||
{
|
||||
if (!args.CanAccess || !args.CanInteract)
|
||||
return;
|
||||
|
||||
if (!EntityManager.TryGetComponent<ActorComponent?>(args.User, out var actor))
|
||||
return;
|
||||
var player = actor.PlayerSession;
|
||||
|
||||
InteractionVerb verb = new();
|
||||
verb.Text = Loc.GetString("configure-verb-get-data-text");
|
||||
verb.IconTexture = "/Textures/Interface/VerbIcons/settings.svg.192dpi.png";
|
||||
verb.Act = () => component.OpenUserInterface(actor);
|
||||
args.Verbs.Add(verb);
|
||||
}
|
||||
|
||||
private void OnRelayMovement(EntityUid uid, DisposalTubeComponent component, ref ContainerRelayMovementEntityEvent args)
|
||||
{
|
||||
if (_gameTiming.CurTime < component.LastClang + DisposalTubeComponent.ClangDelay)
|
||||
|
||||
@@ -24,6 +24,10 @@ namespace Content.Server.Disposal.Unit.Components
|
||||
[DataField("pressure")]
|
||||
public float Pressure = 1f;
|
||||
|
||||
[ViewVariables]
|
||||
[DataField("autoEngageEnabled")]
|
||||
public bool AutomaticEngage = true;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("autoEngageTime")]
|
||||
public readonly TimeSpan AutomaticEngageTime = TimeSpan.FromSeconds(30);
|
||||
|
||||
@@ -131,7 +131,8 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
||||
{
|
||||
// This is not an interaction, activation, or alternative verb type because unfortunately most users are
|
||||
// unwilling to accept that this is where they belong and don't want to accidentally climb inside.
|
||||
if (!args.CanAccess ||
|
||||
if (!component.MobsCanEnter ||
|
||||
!args.CanAccess ||
|
||||
!args.CanInteract ||
|
||||
component.Container.ContainedEntities.Contains(args.User) ||
|
||||
!_actionBlockerSystem.CanMove(args.User))
|
||||
@@ -423,6 +424,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
||||
if (oldPressure < 1 && state == SharedDisposalUnitComponent.PressureState.Ready)
|
||||
{
|
||||
UpdateVisualState(component);
|
||||
UpdateInterface(component, component.Powered);
|
||||
|
||||
if (component.Engaged)
|
||||
{
|
||||
@@ -512,6 +514,16 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
||||
return false;
|
||||
}
|
||||
|
||||
//Allows the MailingUnitSystem to add tags or prevent flushing
|
||||
var beforeFlushArgs = new BeforeDisposalFlushEvent();
|
||||
RaiseLocalEvent(component.Owner, beforeFlushArgs, false);
|
||||
|
||||
if (beforeFlushArgs.Cancelled)
|
||||
{
|
||||
Disengage(component);
|
||||
return false;
|
||||
}
|
||||
|
||||
var xform = Transform(component.Owner);
|
||||
if (!TryComp(xform.GridUid, out IMapGridComponent? grid))
|
||||
return false;
|
||||
@@ -536,7 +548,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
||||
component.Air = environment.Remove(transferMoles);
|
||||
}
|
||||
|
||||
entryComponent.TryInsert(component);
|
||||
entryComponent.TryInsert(component, beforeFlushArgs.Tags);
|
||||
|
||||
component.AutomaticEngageToken?.Cancel();
|
||||
component.AutomaticEngageToken = null;
|
||||
@@ -558,6 +570,9 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
||||
var stateString = Loc.GetString($"{component.State}");
|
||||
var state = new SharedDisposalUnitComponent.DisposalUnitBoundUserInterfaceState(EntityManager.GetComponent<MetaDataComponent>(component.Owner).EntityName, stateString, EstimatedFullPressure(component), powered, component.Engaged);
|
||||
component.Owner.GetUIOrNull(SharedDisposalUnitComponent.DisposalUnitUiKey.Key)?.SetState(state);
|
||||
|
||||
var stateUpdatedEvent = new DisposalUnitUIStateUpdatedEvent(state);
|
||||
RaiseLocalEvent(component.Owner, stateUpdatedEvent, false);
|
||||
}
|
||||
|
||||
private TimeSpan EstimatedFullPressure(DisposalUnitComponent component)
|
||||
@@ -686,7 +701,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
||||
/// </summary>
|
||||
public void TryQueueEngage(DisposalUnitComponent component)
|
||||
{
|
||||
if (component.Deleted || !component.Powered && component.Container.ContainedEntities.Count == 0)
|
||||
if (component.Deleted || !component.AutomaticEngage || !component.Powered && component.Container.ContainedEntities.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -713,5 +728,28 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
||||
|
||||
UpdateVisualState(component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sent before the disposal unit flushes it's contents.
|
||||
/// Allows adding tags for sorting and preventing the disposal unit from flushing.
|
||||
/// </summary>
|
||||
public sealed class BeforeDisposalFlushEvent : CancellableEntityEventArgs
|
||||
{
|
||||
public List<string> Tags = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sent before the disposal unit flushes it's contents.
|
||||
/// Allows adding tags for sorting and preventing the disposal unit from flushing.
|
||||
/// </summary>
|
||||
public sealed class DisposalUnitUIStateUpdatedEvent : EntityEventArgs
|
||||
{
|
||||
public SharedDisposalUnitComponent.DisposalUnitBoundUserInterfaceState State;
|
||||
|
||||
public DisposalUnitUIStateUpdatedEvent(SharedDisposalUnitComponent.DisposalUnitBoundUserInterfaceState state)
|
||||
{
|
||||
State = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ namespace Content.Shared.Disposal.Components
|
||||
/// </summary>
|
||||
public List<EntityUid> RecentlyEjected = new();
|
||||
|
||||
|
||||
[DataField("mobsCanEnter")]
|
||||
public bool MobsCanEnter = true;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum Visuals : byte
|
||||
{
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
using Content.Shared.Disposal.Components;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Disposal;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class MailingUnitBoundUserInterfaceState: BoundUserInterfaceState, IEquatable<MailingUnitBoundUserInterfaceState>
|
||||
{
|
||||
public string? Target;
|
||||
public List<string> TargetList;
|
||||
public string? Tag;
|
||||
public SharedDisposalUnitComponent.DisposalUnitBoundUserInterfaceState DisposalState;
|
||||
|
||||
public MailingUnitBoundUserInterfaceState(SharedDisposalUnitComponent.DisposalUnitBoundUserInterfaceState disposalState, string? target, List<string> targetList, string? tag)
|
||||
{
|
||||
DisposalState = disposalState;
|
||||
Target = target;
|
||||
TargetList = targetList;
|
||||
Tag = tag;
|
||||
}
|
||||
|
||||
public bool Equals(MailingUnitBoundUserInterfaceState? other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return DisposalState.Equals(other.DisposalState)
|
||||
&& Target == other.Target
|
||||
&& TargetList.Equals(other.TargetList)
|
||||
&& Tag == other.Tag;
|
||||
}
|
||||
}
|
||||
23
Content.Shared/Disposal/MailingUnitUiMessages.cs
Normal file
23
Content.Shared/Disposal/MailingUnitUiMessages.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Disposal;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum MailingUnitUiKey : byte
|
||||
{
|
||||
Key
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Message data sent from client to server when a disposal unit ui button is pressed.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class TargetSelectedMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly string? target;
|
||||
|
||||
public TargetSelectedMessage(string? target)
|
||||
{
|
||||
this.target = target;
|
||||
}
|
||||
}
|
||||
@@ -66,11 +66,15 @@ namespace Content.Shared.Disposal
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check if the entity is a mob and if mobs can be inserted
|
||||
if (EntityManager.HasComponent<MobStateComponent>(entity) && !component.MobsCanEnter)
|
||||
return false;
|
||||
|
||||
if (!EntityManager.TryGetComponent(entity, out IPhysBody? physics) ||
|
||||
!physics.CanCollide && storable == null)
|
||||
{
|
||||
if (!(EntityManager.TryGetComponent(entity, out MobStateComponent? damageState) && damageState.IsDead()))
|
||||
if (!(EntityManager.TryGetComponent(entity, out MobStateComponent? damageState) &&
|
||||
(!component.MobsCanEnter || damageState.IsDead())))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
device-frequency-prototype-name-atmos = Atmospheric Devices
|
||||
device-frequency-prototype-name-suit-sensors = Suit Sensors
|
||||
device-frequency-prototype-name-lights = Smart Lights
|
||||
device-frequency-prototype-name-mailing-units = Mailing Units
|
||||
|
||||
## camera frequencies
|
||||
device-frequency-prototype-name-surveillance-camera-test = Subnet Test
|
||||
|
||||
@@ -1,25 +1,8 @@
|
||||
## UI
|
||||
|
||||
disposal-mailing-unit-window-state-label = State:
|
||||
disposal-mailing-unit-window-ready-state = Ready
|
||||
disposal-mailing-unit-pressure-label = Pressure:
|
||||
disposal-mailing-unit-handle-label = Handle:
|
||||
disposal-mailing-unit-engage-button = Engage
|
||||
disposal-mailing-unit-eject-label = Eject:
|
||||
disposal-mailing-unit-eject-button = Eject Contents
|
||||
disposal-mailing-unit-power-button = Power
|
||||
disposal-mailing-unit-destination-select-label = Select a destination:
|
||||
disposal-mailing-unit-unit-self-reference = This unit:
|
||||
disposal-mailing-unit-is-valid-interaction-cannot-interact = You can't do that!
|
||||
disposal-mailing-unit-is-valid-interaction-cannot-reach = You can't reach there!
|
||||
disposal-mailing-unit-is-valid-interaction-no-hands = You have no hands.
|
||||
ui-mailing-unit-window-title = {$tag} mailing unit
|
||||
|
||||
## SelfInsertVerb
|
||||
|
||||
disposal-self-insert-verb-get-data-text = Jump inside
|
||||
|
||||
## FlushVerb
|
||||
|
||||
disposal-flush-verb-get-data-text = Flush
|
||||
|
||||
disposal-eject-verb-contents = contents
|
||||
ui-mailing-unit-button-flush = Send
|
||||
ui-mailing-unit-destination-select-label = Select a destination:
|
||||
ui-mailing-unit-self-reference-label = This unit:
|
||||
ui-mailing-unit-target-label = Destination:
|
||||
|
||||
@@ -10,6 +10,11 @@ ui-disposal-unit-button-flush = Flush
|
||||
ui-disposal-unit-button-eject = Eject Contents
|
||||
ui-disposal-unit-button-power = Power
|
||||
|
||||
## No hands
|
||||
## FlushVerb
|
||||
disposal-flush-verb-get-data-text = Flush
|
||||
|
||||
## SelfInsertVerb
|
||||
disposal-self-insert-verb-get-data-text = Jump inside
|
||||
|
||||
## No hands
|
||||
disposal-unit-no-hands = You don't have hands!
|
||||
|
||||
@@ -239,6 +239,7 @@
|
||||
- ComputerTelevisionCircuitboard
|
||||
- AirAlarmElectronics
|
||||
- FireAlarmElectronics
|
||||
- MailingUnitElectronics
|
||||
- HolofanProjector
|
||||
|
||||
- type: technology
|
||||
|
||||
@@ -64,3 +64,8 @@
|
||||
id: SmartLight #used by powered lights.
|
||||
name: device-frequency-prototype-name-lights
|
||||
frequency: 1173
|
||||
|
||||
- type: deviceFrequency
|
||||
id: MailingUnit
|
||||
name: device-frequency-prototype-name-mailing-units
|
||||
frequency: 2300
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
- type: entity
|
||||
id: MailingUnitElectronics
|
||||
parent: BaseItem
|
||||
name: mailing unit electronics
|
||||
description: An electronics board used in mailing units
|
||||
components:
|
||||
- type: Tag
|
||||
tags:
|
||||
- MailingUnitElectronics
|
||||
- DroneUsable
|
||||
- type: Sprite
|
||||
sprite: Objects/Misc/module.rsi
|
||||
state: net_wired
|
||||
@@ -181,6 +181,7 @@
|
||||
- APCElectronics
|
||||
- AirAlarmElectronics
|
||||
- FireAlarmElectronics
|
||||
- MailingUnitElectronics
|
||||
- Bucket
|
||||
- MopItem
|
||||
- SprayBottle
|
||||
|
||||
@@ -85,3 +85,57 @@
|
||||
interfaces:
|
||||
- key: enum.DisposalUnitUiKey.Key
|
||||
type: DisposalUnitBoundUserInterface
|
||||
|
||||
|
||||
- type: entity
|
||||
id: MailingUnit
|
||||
parent: DisposalUnitBase
|
||||
name: mailing unit
|
||||
description: A pneumatic mail delivery unit.
|
||||
components:
|
||||
- type: Sprite
|
||||
netsync: false
|
||||
sprite: Structures/Piping/disposal.rsi
|
||||
layers:
|
||||
- state: conmailing
|
||||
map: [ "enum.DisposalUnitVisualLayers.Base" ]
|
||||
- state: mailover-handle
|
||||
map: [ "enum.DisposalUnitVisualLayers.Handle" ]
|
||||
- state: dispover-ready
|
||||
map: [ "enum.DisposalUnitVisualLayers.Light" ]
|
||||
- type: Construction
|
||||
graph: DisposalMachine
|
||||
node: mailing_unit
|
||||
- type: DisposalUnit
|
||||
flushTime: 2
|
||||
autoEngageEnabled: false
|
||||
mobsCanEnter: false
|
||||
- type: MailingUnit
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wired
|
||||
receiveFrequencyId: MailingUnit
|
||||
transmitFrequencyId: MailingUnit
|
||||
- type: WiredNetworkConnection
|
||||
- type: Configuration
|
||||
config:
|
||||
tag:
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: DisposalUnitVisualizer
|
||||
state_unanchored: conmailing
|
||||
state_anchored: mailing
|
||||
state_charging: mailing-charging
|
||||
overlay_charging: dispover-charge
|
||||
overlay_ready: dispover-ready
|
||||
overlay_full: dispover-full
|
||||
overlay_engaged: mailover-handle
|
||||
state_flush: mailing-flush
|
||||
flush_sound:
|
||||
path: /Audio/Machines/disposalflush.ogg
|
||||
flush_time: 2
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.MailingUnitUiKey.Key
|
||||
type: DisposalUnitBoundUserInterface
|
||||
- key: enum.ConfigurationUiKey.Key
|
||||
type: ConfigurationBoundUserInterface
|
||||
|
||||
@@ -68,12 +68,15 @@
|
||||
steps:
|
||||
- tool: Screwing
|
||||
doAfter: 0.25
|
||||
#- to: frame_mailing
|
||||
# steps:
|
||||
# - ... # 1x mailing unit electronics
|
||||
# amount: 1
|
||||
# - tool: Screwing
|
||||
# doAfter: 0.25
|
||||
- to: frame_mailing
|
||||
steps:
|
||||
- tag: MailingUnitElectronics
|
||||
name: Mailing Unit Electronics
|
||||
icon:
|
||||
sprite: "Objects/Misc/module.rsi"
|
||||
state: "net_wired"
|
||||
- tool: Screwing
|
||||
doAfter: 0.25
|
||||
- node: frame_unit
|
||||
entity: DisposalMachineFrame
|
||||
actions:
|
||||
@@ -105,6 +108,37 @@
|
||||
steps:
|
||||
- tool: Prying
|
||||
doAfter: 1
|
||||
- node: frame_mailing
|
||||
entity: DisposalMachineFrame
|
||||
actions:
|
||||
- !type:SpriteStateChange
|
||||
state: "frame_unit"
|
||||
edges:
|
||||
- to: frame_electronics
|
||||
steps:
|
||||
- tool: Prying
|
||||
doAfter: 0.25
|
||||
- to: mailing_unit
|
||||
conditions:
|
||||
- !type:EntityAnchored
|
||||
steps:
|
||||
- material: Steel
|
||||
amount: 1
|
||||
doAfter: 1
|
||||
- node: mailing_unit
|
||||
entity: MailingUnit
|
||||
edges:
|
||||
- to: frame_mailing
|
||||
completed:
|
||||
- !type:SpawnPrototype
|
||||
prototype: SheetSteel1
|
||||
amount: 1
|
||||
- !type:EmptyAllContainers
|
||||
conditions:
|
||||
- !type:EntityAnchored
|
||||
steps:
|
||||
- tool: Prying
|
||||
doAfter: 1
|
||||
- node: frame_inlet
|
||||
entity: DisposalMachineFrame
|
||||
actions:
|
||||
|
||||
@@ -134,6 +134,19 @@
|
||||
sprite: Structures/Piping/disposal.rsi
|
||||
state: "disposal"
|
||||
|
||||
- type: construction
|
||||
name: mailing unit
|
||||
id: MailingUnit
|
||||
graph: DisposalMachine
|
||||
startNode: start
|
||||
targetNode: mailing_unit
|
||||
category: Utilities
|
||||
placementMode: SnapgridCenter
|
||||
canBuildInImpassable: false
|
||||
icon:
|
||||
sprite: Structures/Piping/disposal.rsi
|
||||
state: "mailing"
|
||||
|
||||
- type: construction
|
||||
name: disposal pipe
|
||||
id: DisposalPipe
|
||||
|
||||
@@ -7,6 +7,15 @@
|
||||
Steel: 50
|
||||
Plastic: 50
|
||||
|
||||
- type: latheRecipe
|
||||
id: MailingUnitElectronics
|
||||
icon: Objects/Misc/module.rsi/net_wired.png
|
||||
result: MailingUnitElectronics
|
||||
completetime: 4
|
||||
materials:
|
||||
Steel: 50
|
||||
Plastic: 50
|
||||
|
||||
- type: latheRecipe
|
||||
id: DoorElectronics
|
||||
icon: Objects/Misc/module.rsi/door_electronics.png
|
||||
|
||||
@@ -305,6 +305,9 @@
|
||||
- type: Tag
|
||||
id: Matchstick
|
||||
|
||||
- type: Tag
|
||||
id: MailingUnitElectronics
|
||||
|
||||
- type: Tag
|
||||
id: Medkit
|
||||
|
||||
|
||||
BIN
Resources/Textures/Structures/Piping/disposal.rsi/conmailing.png
Normal file
BIN
Resources/Textures/Structures/Piping/disposal.rsi/conmailing.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 421 B |
Binary file not shown.
|
After Width: | Height: | Size: 503 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Resources/Textures/Structures/Piping/disposal.rsi/mailing.png
Normal file
BIN
Resources/Textures/Structures/Piping/disposal.rsi/mailing.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 452 B |
Binary file not shown.
|
After Width: | Height: | Size: 184 B |
@@ -16,6 +16,15 @@
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "conmailing",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
1.0
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "conpipe-c",
|
||||
"directions": 4,
|
||||
@@ -187,6 +196,15 @@
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "mailing",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
1.0
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "disposal-charging",
|
||||
"directions": 1,
|
||||
@@ -196,6 +214,15 @@
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "mailing-charging",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
1.0
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "disposal-flush",
|
||||
"directions": 1,
|
||||
@@ -213,6 +240,23 @@
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "mailing-flush",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.5,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dispover-charge",
|
||||
"directions": 1,
|
||||
@@ -242,6 +286,15 @@
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "mailover-handle",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
1.0
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dispover-ready",
|
||||
"directions": 1,
|
||||
|
||||
Reference in New Issue
Block a user