diff --git a/Content.Client/GameObjects/Components/Disposal/DisposalRouterBoundUserInterface.cs b/Content.Client/GameObjects/Components/Disposal/DisposalRouterBoundUserInterface.cs new file mode 100644 index 0000000000..00f30c02ff --- /dev/null +++ b/Content.Client/GameObjects/Components/Disposal/DisposalRouterBoundUserInterface.cs @@ -0,0 +1,69 @@ +#nullable enable +using JetBrains.Annotations; +using Robust.Client.GameObjects.Components.UserInterface; +using Robust.Shared.GameObjects.Components.UserInterface; +using Robust.Shared.Localization; +using static Content.Shared.GameObjects.Components.Disposal.SharedDisposalRouterComponent; + +namespace Content.Client.GameObjects.Components.Disposal +{ + /// + /// Initializes a and updates it when new server messages are received. + /// + [UsedImplicitly] + public class DisposalRouterBoundUserInterface : BoundUserInterface + { + private DisposalRouterWindow? _window; + + public DisposalRouterBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey) + { + } + + protected override void Open() + { + base.Open(); + + _window = new DisposalRouterWindow + { + Title = Loc.GetString("Disposal Router"), + }; + + _window.OpenCentered(); + _window.OnClose += Close; + + _window.Confirm.OnPressed += _ => ButtonPressed(UiAction.Ok, _window.TagInput.Text); + + } + + private void ButtonPressed(UiAction action, string tag) + { + SendMessage(new UiActionMessage(action, tag)); + _window?.Close(); + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + if (!(state is DisposalRouterUserInterfaceState cast)) + { + return; + } + + _window?.UpdateState(cast); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _window?.Dispose(); + } + } + + + } + +} diff --git a/Content.Client/GameObjects/Components/Disposal/DisposalRouterWindow.cs b/Content.Client/GameObjects/Components/Disposal/DisposalRouterWindow.cs new file mode 100644 index 0000000000..f9f850ae18 --- /dev/null +++ b/Content.Client/GameObjects/Components/Disposal/DisposalRouterWindow.cs @@ -0,0 +1,56 @@ +using System.Runtime.CompilerServices; +using System.Text.RegularExpressions; +using Content.Shared.GameObjects.Components.Disposal; +using Robust.Client.Graphics.Drawing; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.Localization; +using Robust.Shared.Maths; +using static Content.Shared.GameObjects.Components.Disposal.SharedDisposalRouterComponent; + +namespace Content.Client.GameObjects.Components.Disposal +{ + /// + /// Client-side UI used to control a + /// + public class DisposalRouterWindow : SS14Window + { + public readonly LineEdit TagInput; + public readonly Button Confirm; + + protected override Vector2? CustomSize => (400, 80); + + private Regex _tagRegex; + + public DisposalRouterWindow() + { + _tagRegex = new Regex("^[a-zA-Z0-9, ]*$", RegexOptions.Compiled); + + Contents.AddChild(new VBoxContainer + { + Children = + { + new Label {Text = Loc.GetString("Tags:")}, + new Control {CustomMinimumSize = (0, 10)}, + new HBoxContainer + { + Children = + { + (TagInput = new LineEdit {SizeFlagsHorizontal = SizeFlags.Expand, CustomMinimumSize = (320, 0), + ToolTip = Loc.GetString("A comma separated list of tags"), IsValid = tags => _tagRegex.IsMatch(tags)}), + new Control {CustomMinimumSize = (10, 0)}, + (Confirm = new Button {Text = Loc.GetString("Confirm")}) + } + } + } + }); + } + + + public void UpdateState(DisposalRouterUserInterfaceState state) + { + TagInput.Text = state.Tags; + } + } +} diff --git a/Content.Client/GameObjects/Components/Disposal/DisposalTaggerBoundUserInterface.cs b/Content.Client/GameObjects/Components/Disposal/DisposalTaggerBoundUserInterface.cs new file mode 100644 index 0000000000..273b8c06ec --- /dev/null +++ b/Content.Client/GameObjects/Components/Disposal/DisposalTaggerBoundUserInterface.cs @@ -0,0 +1,69 @@ +#nullable enable +using JetBrains.Annotations; +using Robust.Client.GameObjects.Components.UserInterface; +using Robust.Shared.GameObjects.Components.UserInterface; +using Robust.Shared.Localization; +using static Content.Shared.GameObjects.Components.Disposal.SharedDisposalTaggerComponent; + +namespace Content.Client.GameObjects.Components.Disposal +{ + /// + /// Initializes a and updates it when new server messages are received. + /// + [UsedImplicitly] + public class DisposalTaggerBoundUserInterface : BoundUserInterface + { + private DisposalTaggerWindow? _window; + + public DisposalTaggerBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey) + { + } + + protected override void Open() + { + base.Open(); + + _window = new DisposalTaggerWindow + { + Title = Loc.GetString("Disposal Tagger"), + }; + + _window.OpenCentered(); + _window.OnClose += Close; + + _window.Confirm.OnPressed += _ => ButtonPressed(UiAction.Ok, _window.TagInput.Text); + + } + + private void ButtonPressed(UiAction action, string tag) + { + SendMessage(new UiActionMessage(action, tag)); + _window?.Close(); + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + if (!(state is DisposalTaggerUserInterfaceState cast)) + { + return; + } + + _window?.UpdateState(cast); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _window?.Dispose(); + } + } + + + } + +} diff --git a/Content.Client/GameObjects/Components/Disposal/DisposalTaggerWindow.cs b/Content.Client/GameObjects/Components/Disposal/DisposalTaggerWindow.cs new file mode 100644 index 0000000000..7fb6dc6937 --- /dev/null +++ b/Content.Client/GameObjects/Components/Disposal/DisposalTaggerWindow.cs @@ -0,0 +1,56 @@ +using System.Runtime.CompilerServices; +using System.Text.RegularExpressions; +using Content.Shared.GameObjects.Components.Disposal; +using Robust.Client.Graphics.Drawing; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.Localization; +using Robust.Shared.Maths; +using static Content.Shared.GameObjects.Components.Disposal.SharedDisposalTaggerComponent; + +namespace Content.Client.GameObjects.Components.Disposal +{ + /// + /// Client-side UI used to control a + /// + public class DisposalTaggerWindow : SS14Window + { + public readonly LineEdit TagInput; + public readonly Button Confirm; + + protected override Vector2? CustomSize => (400, 80); + + private Regex _tagRegex; + + public DisposalTaggerWindow() + { + _tagRegex = new Regex("^[a-zA-Z0-9 ]*$", RegexOptions.Compiled); + + Contents.AddChild(new VBoxContainer + { + Children = + { + new Label {Text = Loc.GetString("Tag:")}, + new Control {CustomMinimumSize = (0, 10)}, + new HBoxContainer + { + Children = + { + (TagInput = new LineEdit {SizeFlagsHorizontal = SizeFlags.Expand, CustomMinimumSize = (320, 0), + IsValid = tag => _tagRegex.IsMatch(tag)}), + new Control {CustomMinimumSize = (10, 0)}, + (Confirm = new Button {Text = Loc.GetString("Confirm")}) + } + } + } + }); + } + + + public void UpdateState(DisposalTaggerUserInterfaceState state) + { + TagInput.Text = state.Tag; + } + } +} diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index d4588e5c84..6e67d79995 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -142,6 +142,8 @@ "Listening", "Radio", "DisposalHolder", + "DisposalTagger", + "DisposalRouter", "DisposalTransit", "DisposalEntry", "DisposalJunction", diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalHolderComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalHolderComponent.cs index ee39a57d76..44c1a1eab3 100644 --- a/Content.Server/GameObjects/Components/Disposal/DisposalHolderComponent.cs +++ b/Content.Server/GameObjects/Components/Disposal/DisposalHolderComponent.cs @@ -1,4 +1,5 @@ #nullable enable +using System.Collections.Generic; using System.Linq; using Content.Server.GameObjects.Components.Items.Storage; using Content.Shared.GameObjects.Components.Body; @@ -41,6 +42,12 @@ namespace Content.Server.GameObjects.Components.Disposal [ViewVariables] public IDisposalTubeComponent? NextTube { get; set; } + /// + /// A list of tags attached to the content, used for sorting + /// + [ViewVariables] + public HashSet Tags { get; set; } = new HashSet(); + private bool CanInsert(IEntity entity) { if (!_contents.CanInsert(entity)) diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalRouterComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalRouterComponent.cs new file mode 100644 index 0000000000..1abf3a7b2d --- /dev/null +++ b/Content.Server/GameObjects/Components/Disposal/DisposalRouterComponent.cs @@ -0,0 +1,179 @@ +using Content.Server.Interfaces; +using Content.Server.Interfaces.GameObjects.Components.Items; +using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.Interfaces.GameObjects.Components; +using Robust.Server.GameObjects.Components.UserInterface; +using Robust.Server.GameObjects.EntitySystems; +using Robust.Server.Interfaces.GameObjects; +using Robust.Shared.Audio; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Maths; +using Robust.Shared.ViewVariables; +using System; +using System.Collections.Generic; +using static Content.Shared.GameObjects.Components.Disposal.SharedDisposalRouterComponent; + +namespace Content.Server.GameObjects.Components.Disposal +{ + [RegisterComponent] + [ComponentReference(typeof(IActivate))] + [ComponentReference(typeof(IDisposalTubeComponent))] + public class DisposalRouterComponent : DisposalJunctionComponent, IActivate + { +#pragma warning disable 649 + [Dependency] private readonly IServerNotifyManager _notifyManager; +#pragma warning restore 649 + public override string Name => "DisposalRouter"; + + [ViewVariables] + private BoundUserInterface _userInterface; + + [ViewVariables] + private HashSet _tags; + + [ViewVariables] + public bool Anchored => + !Owner.TryGetComponent(out CollidableComponent collidable) || + collidable.Anchored; + + public override Direction NextDirection(DisposalHolderComponent holder) + { + var directions = ConnectableDirections(); + + if (holder.Tags.Overlaps(_tags)) + { + return directions[1]; + } + + return Owner.Transform.LocalRotation.GetDir(); + } + + + public override void Initialize() + { + base.Initialize(); + _userInterface = Owner.GetComponent() + .GetBoundUserInterface(DisposalRouterUiKey.Key); + _userInterface.OnReceiveMessage += OnUiReceiveMessage; + + _tags = new HashSet(); + + UpdateUserInterface(); + } + + /// + /// Handles ui messages from the client. For things such as button presses + /// which interact with the world and require server action. + /// + /// A user interface message from the client. + private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj) + { + var msg = (UiActionMessage) obj.Message; + + if (!PlayerCanUseDisposalTagger(obj.Session.AttachedEntity)) + return; + + if (msg.Action == UiAction.Ok) + { + _tags.Clear(); + foreach (var tag in msg.Tags.Split(',', StringSplitOptions.RemoveEmptyEntries)) + { + _tags.Add(tag.Trim()); + } + } + + ClickSound(); + } + + /// + /// Checks whether the player entity is able to use the configuration interface of the pipe tagger. + /// + /// The player entity. + /// Returns true if the entity can use the configuration interface, and false if it cannot. + private bool PlayerCanUseDisposalTagger(IEntity playerEntity) + { + //Need player entity to check if they are still able to use the configuration interface + if (playerEntity == null) + return false; + if (!Anchored) + return false; + //Check if player can interact in their current state + if (!ActionBlockerSystem.CanInteract(playerEntity) || !ActionBlockerSystem.CanUse(playerEntity)) + return false; + + return true; + } + + /// + /// Gets component data to be used to update the user interface client-side. + /// + /// Returns a + private DisposalRouterUserInterfaceState GetUserInterfaceState() + { + if(_tags == null || _tags.Count <= 0) + { + return new DisposalRouterUserInterfaceState(""); + } + + var taglist = new System.Text.StringBuilder(); + + foreach (var tag in _tags) + { + taglist.Append(tag); + taglist.Append(", "); + } + + taglist.Remove(taglist.Length - 2, 2); + + return new DisposalRouterUserInterfaceState(taglist.ToString()); + } + + private void UpdateUserInterface() + { + var state = GetUserInterfaceState(); + _userInterface.SetState(state); + } + + private void ClickSound() + { + EntitySystem.Get().PlayFromEntity("/Audio/Machines/machine_switch.ogg", Owner, AudioParams.Default.WithVolume(-2f)); + } + + /// + /// Called when you click the owner entity with an empty hand. Opens the UI client-side if possible. + /// + /// Data relevant to the event such as the actor which triggered it. + void IActivate.Activate(ActivateEventArgs args) + { + if (!args.User.TryGetComponent(out IActorComponent actor)) + { + return; + } + + if (!args.User.TryGetComponent(out IHandsComponent hands)) + { + _notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User, + Loc.GetString("You have no hands.")); + return; + } + + var activeHandEntity = hands.GetActiveHand?.Owner; + if (activeHandEntity == null) + { + UpdateUserInterface(); + _userInterface.Open(actor.playerSession); + } + } + + public override void OnRemove() + { + _userInterface.CloseAll(); + base.OnRemove(); + } + } +} diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalTaggerComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalTaggerComponent.cs new file mode 100644 index 0000000000..f949e37090 --- /dev/null +++ b/Content.Server/GameObjects/Components/Disposal/DisposalTaggerComponent.cs @@ -0,0 +1,150 @@ +using Content.Server.Interfaces; +using Content.Server.Interfaces.GameObjects.Components.Items; +using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.Interfaces.GameObjects.Components; +using Robust.Server.GameObjects.Components.UserInterface; +using Robust.Server.GameObjects.EntitySystems; +using Robust.Server.Interfaces.GameObjects; +using Robust.Shared.Audio; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Maths; +using Robust.Shared.ViewVariables; +using static Content.Shared.GameObjects.Components.Disposal.SharedDisposalTaggerComponent; + +namespace Content.Server.GameObjects.Components.Disposal +{ + [RegisterComponent] + [ComponentReference(typeof(IActivate))] + [ComponentReference(typeof(IDisposalTubeComponent))] + public class DisposalTaggerComponent : DisposalTransitComponent, IActivate + { +#pragma warning disable 649 + [Dependency] private readonly IServerNotifyManager _notifyManager; +#pragma warning restore 649 + public override string Name => "DisposalTagger"; + + [ViewVariables] + private BoundUserInterface _userInterface; + + [ViewVariables(VVAccess.ReadWrite)] + private string _tag = ""; + + [ViewVariables] + public bool Anchored => + !Owner.TryGetComponent(out CollidableComponent collidable) || + collidable.Anchored; + + public override Direction NextDirection(DisposalHolderComponent holder) + { + holder.Tags.Add(_tag); + return base.NextDirection(holder); + } + + + public override void Initialize() + { + base.Initialize(); + _userInterface = Owner.GetComponent() + .GetBoundUserInterface(DisposalTaggerUiKey.Key); + _userInterface.OnReceiveMessage += OnUiReceiveMessage; + + UpdateUserInterface(); + } + + /// + /// Handles ui messages from the client. For things such as button presses + /// which interact with the world and require server action. + /// + /// A user interface message from the client. + private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj) + { + var msg = (UiActionMessage) obj.Message; + + if (!PlayerCanUseDisposalTagger(obj.Session.AttachedEntity)) + return; + + if (msg.Action == UiAction.Ok) + { + _tag = msg.Tag; + } + + ClickSound(); + } + + /// + /// Checks whether the player entity is able to use the configuration interface of the pipe tagger. + /// + /// The player entity. + /// Returns true if the entity can use the configuration interface, and false if it cannot. + private bool PlayerCanUseDisposalTagger(IEntity playerEntity) + { + //Need player entity to check if they are still able to use the configuration interface + if (playerEntity == null) + return false; + if (!Anchored) + return false; + //Check if player can interact in their current state + if (!ActionBlockerSystem.CanInteract(playerEntity) || !ActionBlockerSystem.CanUse(playerEntity)) + return false; + + return true; + } + + /// + /// Gets component data to be used to update the user interface client-side. + /// + /// Returns a + private DisposalTaggerUserInterfaceState GetUserInterfaceState() + { + return new DisposalTaggerUserInterfaceState(_tag); + } + + private void UpdateUserInterface() + { + var state = GetUserInterfaceState(); + _userInterface.SetState(state); + } + + private void ClickSound() + { + EntitySystem.Get().PlayFromEntity("/Audio/Machines/machine_switch.ogg", Owner, AudioParams.Default.WithVolume(-2f)); + } + + /// + /// Called when you click the owner entity with an empty hand. Opens the UI client-side if possible. + /// + /// Data relevant to the event such as the actor which triggered it. + void IActivate.Activate(ActivateEventArgs args) + { + if (!args.User.TryGetComponent(out IActorComponent actor)) + { + return; + } + + if (!args.User.TryGetComponent(out IHandsComponent hands)) + { + _notifyManager.PopupMessage(Owner.Transform.GridPosition, args.User, + Loc.GetString("You have no hands.")); + return; + } + + var activeHandEntity = hands.GetActiveHand?.Owner; + if (activeHandEntity == null) + { + UpdateUserInterface(); + _userInterface.Open(actor.playerSession); + } + } + + public override void OnRemove() + { + base.OnRemove(); + _userInterface.CloseAll(); + } + } +} diff --git a/Content.Shared/GameObjects/Components/Disposal/SharedDisposalRouterComponent.cs b/Content.Shared/GameObjects/Components/Disposal/SharedDisposalRouterComponent.cs new file mode 100644 index 0000000000..c0323cbaa1 --- /dev/null +++ b/Content.Shared/GameObjects/Components/Disposal/SharedDisposalRouterComponent.cs @@ -0,0 +1,52 @@ +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.UserInterface; +using Robust.Shared.Serialization; +using System; + +namespace Content.Shared.GameObjects.Components.Disposal +{ + public class SharedDisposalRouterComponent : Component + { + public override string Name => "DisposalRouter"; + + [Serializable, NetSerializable] + public class DisposalRouterUserInterfaceState : BoundUserInterfaceState + { + public readonly string Tags; + + public DisposalRouterUserInterfaceState(string tags) + { + Tags = tags; + } + } + + [Serializable, NetSerializable] + public class UiActionMessage : BoundUserInterfaceMessage + { + public readonly UiAction Action; + public readonly string Tags = ""; + + public UiActionMessage(UiAction action, string tags) + { + Action = action; + + if (Action == UiAction.Ok) + { + Tags = tags.Substring(0, Math.Min(tags.Length, 150)); + } + } + } + + [Serializable, NetSerializable] + public enum UiAction + { + Ok + } + + [Serializable, NetSerializable] + public enum DisposalRouterUiKey + { + Key + } + } +} diff --git a/Content.Shared/GameObjects/Components/Disposal/SharedDisposalTaggerComponent.cs b/Content.Shared/GameObjects/Components/Disposal/SharedDisposalTaggerComponent.cs new file mode 100644 index 0000000000..d12e9060e9 --- /dev/null +++ b/Content.Shared/GameObjects/Components/Disposal/SharedDisposalTaggerComponent.cs @@ -0,0 +1,53 @@ +#nullable enable +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.UserInterface; +using Robust.Shared.Serialization; +using System; + +namespace Content.Shared.GameObjects.Components.Disposal +{ + public class SharedDisposalTaggerComponent : Component + { + public override string Name => "DisposalTagger"; + + [Serializable, NetSerializable] + public class DisposalTaggerUserInterfaceState : BoundUserInterfaceState + { + public readonly string Tag; + + public DisposalTaggerUserInterfaceState(string tag) + { + Tag = tag; + } + } + + [Serializable, NetSerializable] + public class UiActionMessage : BoundUserInterfaceMessage + { + public readonly UiAction Action; + public readonly string Tag = ""; + + public UiActionMessage(UiAction action, string tag) + { + Action = action; + + if (Action == UiAction.Ok) + { + Tag = tag; + } + } + } + + [Serializable, NetSerializable] + public enum UiAction + { + Ok + } + + [Serializable, NetSerializable] + public enum DisposalTaggerUiKey + { + Key + } + } +} diff --git a/Resources/Prototypes/Entities/Constructible/disposal.yml b/Resources/Prototypes/Entities/Constructible/disposal.yml index 5187ce2a88..1d85dd33a6 100644 --- a/Resources/Prototypes/Entities/Constructible/disposal.yml +++ b/Resources/Prototypes/Entities/Constructible/disposal.yml @@ -44,6 +44,31 @@ state_anchored: pipe-s state_broken: pipe-b +- type: entity + id: DisposalTagger + parent: DisposalPipeBase + name: disposal pipe tagger + description: A pipe that tags entities for routing + components: + - type: Sprite + drawdepth: BelowFloor + sprite: Constructible/Power/disposal.rsi + state: conpipe-tagger + - type: Icon + sprite: Constructible/Power/disposal.rsi + state: conpipe-tagger + - type: DisposalTagger + - type: Appearance + visuals: + - type: DisposalVisualizer + state_free: conpipe-tagger + state_anchored: pipe-tagger + state_broken: pipe-b + - type: UserInterface + interfaces: + - key: enum.DisposalTaggerUiKey.Key + type: DisposalTaggerBoundUserInterface + - type: entity id: DisposalTrunk parent: DisposalPipeBase @@ -131,6 +156,63 @@ - key: enum.DisposalUnitUiKey.Key type: DisposalUnitBoundUserInterface +- type: entity + id: DisposalRouter + parent: DisposalPipeBase + name: disposal router + description: A three-way router. Entities with matching tags get routed to the side + components: + - type: Sprite + drawdepth: BelowFloor + sprite: Constructible/Power/disposal.rsi + state: conpipe-j1s + - type: Icon + sprite: Constructible/Power/disposal.rsi + state: conpipe-j1s + - type: DisposalRouter + degrees: + - 0 + - -90 + - 180 + - type: Appearance + visuals: + - type: DisposalVisualizer + state_free: conpipe-j1s + state_anchored: pipe-j1s + state_broken: pipe-b + - type: Flippable + entity: DisposalRouterFlipped + - type: UserInterface + interfaces: + - key: enum.DisposalRouterUiKey.Key + type: DisposalRouterBoundUserInterface + +- type: entity + id: DisposalRouterFlipped + parent: DisposalRouter + name: flipped router junction + components: + - type: Sprite + drawdepth: BelowFloor + sprite: Constructible/Power/disposal.rsi + state: conpipe-j2s + - type: Icon + sprite: Constructible/Power/disposal.rsi + state: conpipe-j2s + - type: DisposalRouter + degrees: + - 0 + - 90 + - 180 + - type: Appearance + visuals: + - type: DisposalVisualizer + state_free: conpipe-j2s + state_anchored: pipe-j2s + state_broken: pipe-b + - type: Flippable + entity: DisposalRouter + - type: entity id: DisposalJunction parent: DisposalPipeBase diff --git a/Resources/Textures/Constructible/Power/disposal.rsi/conpipe-tagger.png b/Resources/Textures/Constructible/Power/disposal.rsi/conpipe-tagger.png new file mode 100644 index 0000000000..e1c4637244 Binary files /dev/null and b/Resources/Textures/Constructible/Power/disposal.rsi/conpipe-tagger.png differ diff --git a/Resources/Textures/Constructible/Power/disposal.rsi/meta.json b/Resources/Textures/Constructible/Power/disposal.rsi/meta.json index 96aadcfa66..f11b589795 100644 --- a/Resources/Textures/Constructible/Power/disposal.rsi/meta.json +++ b/Resources/Textures/Constructible/Power/disposal.rsi/meta.json @@ -1 +1,779 @@ -{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "https://github.com/discordia-space/CEV-Eris/blob/bbe32606902c90f5290b57d905a3f31b84dc6d7d/icons/obj/pipes/disposal.dmi and modified by DrSmugleaf", "states": [{"name": "condisposal", "directions": 1, "delays": [[1.0]]}, {"name": "conpipe-c", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j1", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j1s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j2s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-t", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-y", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "disposal", "directions": 1, "delays": [[1.0]]}, {"name": "disposal-charging", "directions": 1, "delays": [[1.0]]}, {"name": "disposal-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, "delays": [[0.4, 0.4]]}, {"name": "dispover-full", "directions": 1, "delays": [[0.2, 0.2]]}, {"name": "dispover-handle", "directions": 1, "delays": [[1.0]]}, {"name": "dispover-ready", "directions": 1, "delays": [[1.0]]}, {"name": "intake", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "intake-closing", "directions": 4, "delays": [[0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]}, {"name": "outlet", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "outlet-open", "directions": 4, "delays": [[0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1]]}, {"name": "pipe-b", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-bf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-c", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-cf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-d", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1f", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2f", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-t", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tagger", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tagger-partial", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-u", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-y", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-yf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]} \ No newline at end of file +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "https://github.com/discordia-space/CEV-Eris/blob/bbe32606902c90f5290b57d905a3f31b84dc6d7d/icons/obj/pipes/disposal.dmi and modified by DrSmugleaf", + "states": [ + { + "name": "condisposal", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "conpipe-c", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "conpipe-j1", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "conpipe-j1s", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "conpipe-j2", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "conpipe-j2s", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "conpipe-s", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "conpipe-t", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "conpipe-tagger", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "conpipe-y", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "disposal", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "disposal-charging", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "disposal-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, + "delays": [ + [ + 0.4, + 0.4 + ] + ] + }, + { + "name": "dispover-full", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2 + ] + ] + }, + { + "name": "dispover-handle", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "dispover-ready", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "intake", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "intake-closing", + "directions": 4, + "delays": [ + [ + 0.5, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.5, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.5, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.5, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "outlet", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "outlet-open", + "directions": 4, + "delays": [ + [ + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.1, + 1.5, + 0.1 + ], + [ + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.1, + 1.5, + 0.1 + ], + [ + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.1, + 1.5, + 0.1 + ], + [ + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.1, + 1.5, + 0.1 + ] + ] + }, + { + "name": "pipe-b", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-bf", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-c", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-cf", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-d", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-j1", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-j1f", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-j1s", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-j1sf", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-j2", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-j2f", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-j2s", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-j2sf", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-s", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-sf", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-t", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-tagger", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-tagger-partial", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-tf", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-u", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-y", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "pipe-yf", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Constructible/Power/disposal.rsi/pipe-tagger.png b/Resources/Textures/Constructible/Power/disposal.rsi/pipe-tagger.png index a8463fd0c1..ce48830a50 100644 Binary files a/Resources/Textures/Constructible/Power/disposal.rsi/pipe-tagger.png and b/Resources/Textures/Constructible/Power/disposal.rsi/pipe-tagger.png differ