From 501156f84c401cc1b6174e4408edef49e5c4b130 Mon Sep 17 00:00:00 2001 From: Paul Ritter Date: Wed, 18 Nov 2020 14:53:46 +0100 Subject: [PATCH] makes conveyors to use machine linking & refactors machine linking a bit (#2464) * makes conveyors to use machine linking & refactors machine linking a bit * nullable errors * temp commit, starting work on construction * working recipies & graphs * fixes crash * makes items gravitate towards the center when on a conveyor * makes conveyors take bool signal too * ignores components clientside * default arm entitymanager maxtransmitters unsubscribe methods * twowayLEVER * _ * componentreference struct * yaml run leverDefinitelyNotCopiedFromGirderNoNoNo dies today :( * nullable * no divide by 0 * making sloth happy * space gone - happy? * final fix * yes * adds item to lathe * conveyor item -> conveyor assembly * technology * reviews ADRESSED * Update Content.Shared/GameObjects/Verbs/VerbUtility.cs Co-authored-by: Paul Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: Metal Gear Sloth --- .../Components/Conveyor/ConveyorVisualizer.cs | 3 - ...Visualizer.cs => TwoWayLeverVisualizer.cs} | 16 +- Content.Client/IgnoredComponents.cs | 3 +- .../Components/Conveyor/ConveyorComponent.cs | 112 ++------- .../Conveyor/ConveyorItemComponent.cs | 13 ++ .../Conveyor/ConveyorSwitchComponent.cs | 219 ------------------ .../MachineLinking/SignalButtonComponent.cs | 6 +- .../MachineLinking/SignalReceiverComponent.cs | 46 +++- .../MachineLinking/SignalSwitchComponent.cs | 6 +- .../SignalTransmitterComponent.cs | 8 +- .../SignalTwoWayLeverComponent.cs | 68 ++++++ .../Components/Recycling/RecyclerComponent.cs | 2 +- .../EntitySystems/ConveyorSystem.cs | 74 ------ .../Conveyor/SharedConveyorComponent.cs | 5 +- .../MachineLinking/TwoWayLeverSignal.cs | 19 ++ Content.Shared/Physics/ConveyedController.cs | 32 ++- Resources/Maps/saltern.yml | 5 +- .../Prototypes/Catalog/LatheRecipes/cargo.yml | 10 + .../Catalog/Research/technologies.yml | 2 + .../Entities/Constructible/Power/lathe.yml | 1 + .../Specific/Conveyor/constructionGraphs.yml | 57 +++++ .../Specific/Conveyor/constructionRecipes.yml | 26 +++ .../Specific/{ => Conveyor}/conveyor.yml | 38 ++- .../Specific/Conveyor/twoWayLever.yml | 21 ++ 24 files changed, 345 insertions(+), 447 deletions(-) rename Content.Client/GameObjects/Components/Conveyor/{ConveyorSwitchVisualizer.cs => TwoWayLeverVisualizer.cs} (75%) create mode 100644 Content.Server/GameObjects/Components/Conveyor/ConveyorItemComponent.cs delete mode 100644 Content.Server/GameObjects/Components/Conveyor/ConveyorSwitchComponent.cs create mode 100644 Content.Server/GameObjects/Components/MachineLinking/SignalTwoWayLeverComponent.cs create mode 100644 Content.Shared/GameObjects/Components/MachineLinking/TwoWayLeverSignal.cs create mode 100644 Resources/Prototypes/Catalog/LatheRecipes/cargo.yml create mode 100644 Resources/Prototypes/Entities/Constructible/Specific/Conveyor/constructionGraphs.yml create mode 100644 Resources/Prototypes/Entities/Constructible/Specific/Conveyor/constructionRecipes.yml rename Resources/Prototypes/Entities/Constructible/Specific/{ => Conveyor}/conveyor.yml (65%) create mode 100644 Resources/Prototypes/Entities/Constructible/Specific/Conveyor/twoWayLever.yml diff --git a/Content.Client/GameObjects/Components/Conveyor/ConveyorVisualizer.cs b/Content.Client/GameObjects/Components/Conveyor/ConveyorVisualizer.cs index 35c4b3368f..8dbbca9ed4 100644 --- a/Content.Client/GameObjects/Components/Conveyor/ConveyorVisualizer.cs +++ b/Content.Client/GameObjects/Components/Conveyor/ConveyorVisualizer.cs @@ -16,7 +16,6 @@ namespace Content.Client.GameObjects.Components.Conveyor private string _stateRunning; private string _stateStopped; private string _stateReversed; - private string _stateLoose; private void ChangeState(AppearanceComponent appearance) { @@ -32,7 +31,6 @@ namespace Content.Client.GameObjects.Components.Conveyor ConveyorState.Off => _stateStopped, ConveyorState.Forward => _stateRunning, ConveyorState.Reversed => _stateReversed, - ConveyorState.Loose => _stateLoose, _ => throw new ArgumentOutOfRangeException() }; @@ -46,7 +44,6 @@ namespace Content.Client.GameObjects.Components.Conveyor _stateRunning = node.GetNode("state_running").AsString(); _stateStopped = node.GetNode("state_stopped").AsString(); _stateReversed = node.GetNode("state_reversed").AsString(); - _stateLoose = node.GetNode("state_loose").AsString(); } public override void InitializeEntity(IEntity entity) diff --git a/Content.Client/GameObjects/Components/Conveyor/ConveyorSwitchVisualizer.cs b/Content.Client/GameObjects/Components/Conveyor/TwoWayLeverVisualizer.cs similarity index 75% rename from Content.Client/GameObjects/Components/Conveyor/ConveyorSwitchVisualizer.cs rename to Content.Client/GameObjects/Components/Conveyor/TwoWayLeverVisualizer.cs index cec0e8947b..0ed1ec4f72 100644 --- a/Content.Client/GameObjects/Components/Conveyor/ConveyorSwitchVisualizer.cs +++ b/Content.Client/GameObjects/Components/Conveyor/TwoWayLeverVisualizer.cs @@ -1,5 +1,6 @@ using System; using Content.Shared.GameObjects.Components.Conveyor; +using Content.Shared.GameObjects.Components.MachineLinking; using JetBrains.Annotations; using Robust.Client.GameObjects; using Robust.Client.Interfaces.GameObjects.Components; @@ -11,12 +12,11 @@ using YamlDotNet.RepresentationModel; namespace Content.Client.GameObjects.Components.Conveyor { [UsedImplicitly] - public class ConveyorSwitchVisualizer : AppearanceVisualizer + public class TwoWayLeverVisualizer : AppearanceVisualizer { private string _stateForward; private string _stateOff; private string _stateReversed; - private string _stateLoose; private void ChangeState(AppearanceComponent appearance) { @@ -25,15 +25,14 @@ namespace Content.Client.GameObjects.Components.Conveyor return; } - appearance.TryGetData(ConveyorVisuals.State, out ConveyorState state); + appearance.TryGetData(TwoWayLeverVisuals.State, out TwoWayLeverSignal state); var texture = state switch { - ConveyorState.Off => _stateOff, - ConveyorState.Forward => _stateForward, - ConveyorState.Reversed => _stateReversed, - ConveyorState.Loose => _stateLoose, - _ => throw new ArgumentOutOfRangeException() + TwoWayLeverSignal.Middle => _stateOff, + TwoWayLeverSignal.Right => _stateForward, + TwoWayLeverSignal.Left => _stateReversed, + _ => _stateOff }; sprite.LayerSetState(0, texture); @@ -46,7 +45,6 @@ namespace Content.Client.GameObjects.Components.Conveyor _stateForward = node.GetNode("state_forward").AsString(); _stateOff = node.GetNode("state_off").AsString(); _stateReversed = node.GetNode("state_reversed").AsString(); - _stateLoose = node.GetNode("state_loose").AsString(); } public override void InitializeEntity(IEntity entity) diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index 38483522c7..1959d0ebad 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -135,7 +135,6 @@ "DisposalBend", "Recycler", "Conveyor", - "ConveyorSwitch", "Flippable", "Airtight", "MovedByPressure", @@ -211,6 +210,8 @@ "CrematoriumEntityStorage", "RandomArcade", "RandomSpriteState", + "ConveyorAssembly", + "TwoWayLever" }; } } diff --git a/Content.Server/GameObjects/Components/Conveyor/ConveyorComponent.cs b/Content.Server/GameObjects/Components/Conveyor/ConveyorComponent.cs index 2b3d3c74e8..2d50e5c052 100644 --- a/Content.Server/GameObjects/Components/Conveyor/ConveyorComponent.cs +++ b/Content.Server/GameObjects/Components/Conveyor/ConveyorComponent.cs @@ -1,13 +1,12 @@ #nullable enable -using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Content.Server.GameObjects.Components.Interactable; using Content.Server.GameObjects.Components.Items.Storage; +using Content.Server.GameObjects.Components.MachineLinking; using Content.Server.GameObjects.Components.Power.ApcNetComponents; -using Content.Server.GameObjects.EntitySystems; using Content.Shared.GameObjects.Components.Conveyor; using Content.Shared.GameObjects.Components.Interactable; +using Content.Shared.GameObjects.Components.MachineLinking; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Physics; using Content.Shared.Utility; @@ -17,7 +16,6 @@ using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components; using Robust.Shared.GameObjects.Components.Map; using Robust.Shared.Interfaces.GameObjects; -using Robust.Shared.Interfaces.Random; using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Serialization; @@ -26,16 +24,14 @@ using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Conveyor { [RegisterComponent] - public class ConveyorComponent : Component, IInteractUsing + public class ConveyorComponent : Component, ISignalReceiver, ISignalReceiver { - [Dependency] private readonly IEntityManager _entityManager = default!; - public override string Name => "Conveyor"; /// /// The angle to move entities by in relation to the owner's rotation. /// - [ViewVariables] + [ViewVariables(VVAccess.ReadWrite)] private Angle _angle; /// @@ -66,8 +62,6 @@ namespace Content.Server.GameObjects.Components.Conveyor } } - private ConveyorGroup? _group = new ConveyorGroup(); - /// /// Calculates the angle in which entities on top of this conveyor /// belt are pushed in @@ -142,7 +136,7 @@ namespace Content.Server.GameObjects.Components.Conveyor return; } - var intersecting = _entityManager.GetEntitiesIntersecting(Owner, true); + var intersecting = Owner.EntityManager.GetEntitiesIntersecting(Owner, true); var direction = GetAngle().ToVec(); foreach (var entity in intersecting) @@ -155,107 +149,33 @@ namespace Content.Server.GameObjects.Components.Conveyor if (entity.TryGetComponent(out IPhysicsComponent? physics)) { var controller = physics.EnsureController(); - controller.Move(direction, _speed); + controller.Move(direction, _speed, entity.Transform.WorldPosition - Owner.Transform.WorldPosition); } } } - private async Task ToolUsed(IEntity user, ToolComponent tool) - { - if (!Owner.HasComponent() && - await tool.UseTool(user, Owner, 0.5f, ToolQuality.Prying)) - { - State = ConveyorState.Loose; - - Owner.AddComponent(); - _group?.RemoveConveyor(this); - Owner.RandomOffset(0.2f); - - return true; - } - - return false; - } - - public void Sync(ConveyorGroup group) - { - _group = group; - - if (State == ConveyorState.Loose) - { - return; - } - - State = group.State == ConveyorState.Loose - ? ConveyorState.Off - : group.State; - } - - /// - /// Disconnects this conveyor from any switch. - /// - private void Disconnect() - { - _group?.RemoveConveyor(this); - _group = null; - State = ConveyorState.Off; - } - public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); - serializer.DataReadWriteFunction( - "switches", - new List(), - ids => - { - if (ids == null) - { - return; - } - - foreach (var id in ids) - { - if (!Owner.EntityManager.TryGetEntity(id, out var @switch)) - { - continue; - } - - if (!@switch.TryGetComponent(out ConveyorSwitchComponent? component)) - { - continue; - } - - component.Connect(this); - } - }, - () => _group?.Switches.Select(@switch => @switch.Owner.Uid).ToList()); - serializer.DataField(ref _angle, "angle", 0); serializer.DataField(ref _speed, "speed", 2); } - public override void OnRemove() + public void TriggerSignal(TwoWayLeverSignal signal) { - base.OnRemove(); - Disconnect(); + State = signal switch + { + TwoWayLeverSignal.Left => ConveyorState.Reversed, + TwoWayLeverSignal.Middle => ConveyorState.Off, + TwoWayLeverSignal.Right => ConveyorState.Forward, + _ => ConveyorState.Off + }; } - async Task IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs) + public void TriggerSignal(bool signal) { - if (eventArgs.Using.TryGetComponent(out ConveyorSwitchComponent? conveyorSwitch)) - { - conveyorSwitch.Connect(this, eventArgs.User); - return true; - } - - if (eventArgs.Using.TryGetComponent(out ToolComponent? tool)) - { - return await ToolUsed(eventArgs.User, tool); - } - - return false; + State = signal ? ConveyorState.Forward : ConveyorState.Off; } } } diff --git a/Content.Server/GameObjects/Components/Conveyor/ConveyorItemComponent.cs b/Content.Server/GameObjects/Components/Conveyor/ConveyorItemComponent.cs new file mode 100644 index 0000000000..89764b5422 --- /dev/null +++ b/Content.Server/GameObjects/Components/Conveyor/ConveyorItemComponent.cs @@ -0,0 +1,13 @@ +using Robust.Shared.GameObjects; + +namespace Content.Server.GameObjects.Components.Conveyor +{ + /// + /// Dummy component for construction graph + /// + [RegisterComponent] + public class ConveyorAssemblyComponent : Component + { + public override string Name => "ConveyorAssembly"; + } +} diff --git a/Content.Server/GameObjects/Components/Conveyor/ConveyorSwitchComponent.cs b/Content.Server/GameObjects/Components/Conveyor/ConveyorSwitchComponent.cs deleted file mode 100644 index 48edea9ccd..0000000000 --- a/Content.Server/GameObjects/Components/Conveyor/ConveyorSwitchComponent.cs +++ /dev/null @@ -1,219 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Content.Server.GameObjects.EntitySystems; -using Content.Shared.GameObjects.Components.Conveyor; -using Content.Shared.Interfaces; -using Content.Shared.Interfaces.GameObjects.Components; -using Robust.Server.GameObjects; -using Robust.Shared.GameObjects; -using Robust.Shared.Interfaces.GameObjects; -using Robust.Shared.Localization; -using Robust.Shared.Serialization; -using Robust.Shared.ViewVariables; - -namespace Content.Server.GameObjects.Components.Conveyor -{ - [RegisterComponent] - public class ConveyorSwitchComponent : Component, IInteractHand, IInteractUsing, IActivate - { - public override string Name => "ConveyorSwitch"; - - private ConveyorState _state; - - /// - /// The current state of this switch - /// - [ViewVariables] - public ConveyorState State - { - get => _state; - private set - { - _state = value; - - if (Owner.TryGetComponent(out AppearanceComponent? appearance)) - { - appearance.SetData(ConveyorVisuals.State, value); - } - } - } - - private ConveyorGroup? _group; - - public void Sync(ConveyorGroup group) - { - _group = group; - - if (State == ConveyorState.Loose) - { - return; - } - - State = group.State == ConveyorState.Loose - ? ConveyorState.Off - : group.State; - } - - /// - /// Disconnects this switch from any conveyors and other switches. - /// - private void Disconnect() - { - _group?.RemoveSwitch(this); - _group = null; - State = ConveyorState.Off; - } - - /// - /// Connects a conveyor to this switch. - /// - /// The conveyor to be connected. - /// The user doing the connecting, if any. - public void Connect(ConveyorComponent conveyor, IEntity? user = null) - { - if (_group == null) - { - _group = new ConveyorGroup(); - _group.AddSwitch(this); - } - - _group.AddConveyor(conveyor); - user?.PopupMessage(Loc.GetString("Conveyor linked.")); - } - - /// - /// Cycles this conveyor switch to its next valid state - /// - /// - /// true if the switch can be operated and the state could be cycled, - /// false otherwise - /// - private bool NextState() - { - State = State switch - { - ConveyorState.Off => ConveyorState.Forward, - ConveyorState.Forward => ConveyorState.Reversed, - ConveyorState.Reversed => ConveyorState.Off, - ConveyorState.Loose => ConveyorState.Off, - _ => throw new ArgumentOutOfRangeException() - }; - - _group?.SetState(this); - - return true; - } - - /// - /// Moves this switch to the group of another. - /// - /// The conveyor switch to synchronize with. - /// The user doing the syncing, if any. - private void SyncWith(ConveyorSwitchComponent other, IEntity? user = null) - { - other._group?.AddSwitch(this); - - if (user == null) - { - return; - } - - Owner.PopupMessage(user, Loc.GetString("Switches synchronized.")); - } - - public override void ExposeData(ObjectSerializer serializer) - { - base.ExposeData(serializer); - - serializer.DataReadWriteFunction( - "conveyors", - new List(), - ids => - { - if (ids == null) - { - return; - } - - foreach (var id in ids) - { - if (!Owner.EntityManager.TryGetEntity(id, out var conveyor)) - { - continue; - } - - if (!conveyor.TryGetComponent(out ConveyorComponent? component)) - { - continue; - } - - Connect(component); - } - }, - () => _group?.Conveyors.Select(conveyor => conveyor.Owner.Uid).ToList()); - - serializer.DataReadWriteFunction( - "switches", - new List(), - ids => - { - if (ids == null) - { - return; - } - - foreach (var id in ids) - { - if (!Owner.EntityManager.TryGetEntity(id, out var @switch)) - { - continue; - } - - if (!@switch.TryGetComponent(out ConveyorSwitchComponent? component)) - { - continue; - } - - component.SyncWith(this); - } - }, - () => _group?.Switches.Select(@switch => @switch.Owner.Uid).ToList()); - } - - public override void OnRemove() - { - base.OnRemove(); - Disconnect(); - } - - bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs) - { - return NextState(); - } - - async Task IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs) - { - if (eventArgs.Using.TryGetComponent(out ConveyorComponent? conveyor)) - { - Connect(conveyor, eventArgs.User); - return true; - } - - if (eventArgs.Using.TryGetComponent(out ConveyorSwitchComponent? otherSwitch)) - { - SyncWith(otherSwitch, eventArgs.User); - return true; - } - - return true; - } - - void IActivate.Activate(ActivateEventArgs eventArgs) - { - NextState(); - } - } -} diff --git a/Content.Server/GameObjects/Components/MachineLinking/SignalButtonComponent.cs b/Content.Server/GameObjects/Components/MachineLinking/SignalButtonComponent.cs index 928f774281..ec586b2d26 100644 --- a/Content.Server/GameObjects/Components/MachineLinking/SignalButtonComponent.cs +++ b/Content.Server/GameObjects/Components/MachineLinking/SignalButtonComponent.cs @@ -30,11 +30,15 @@ namespace Content.Server.GameObjects.Components.MachineLinking return; } - if (transmitter.TransmitSignal(user, new ToggleSignal())) + if (transmitter.TransmitSignal(new ToggleSignal())) { // Since the button doesn't have an animation, I'm going to use a popup message Owner.PopupMessage(user, Loc.GetString("Click.")); } + else + { + Owner.PopupMessage(user, Loc.GetString("No receivers connected.")); + } } } diff --git a/Content.Server/GameObjects/Components/MachineLinking/SignalReceiverComponent.cs b/Content.Server/GameObjects/Components/MachineLinking/SignalReceiverComponent.cs index 0ae94e641c..f7635f4f76 100644 --- a/Content.Server/GameObjects/Components/MachineLinking/SignalReceiverComponent.cs +++ b/Content.Server/GameObjects/Components/MachineLinking/SignalReceiverComponent.cs @@ -7,8 +7,11 @@ using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Map; +using Robust.Shared.Interfaces.Serialization; using Robust.Shared.IoC; using Robust.Shared.Localization; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; namespace Content.Server.GameObjects.Components.MachineLinking { @@ -19,6 +22,8 @@ namespace Content.Server.GameObjects.Components.MachineLinking private List _transmitters; + private int? _maxTransmitters = default; + public override void Initialize() { base.Initialize(); @@ -26,6 +31,11 @@ namespace Content.Server.GameObjects.Components.MachineLinking _transmitters = new List(); } + public override void ExposeData(ObjectSerializer serializer) + { + serializer.DataField(this, x=> x._maxTransmitters, "maxTransmitters", null); + } + public void DistributeSignal(T state) { foreach (var comp in Owner.GetAllComponents>()) @@ -34,15 +44,18 @@ namespace Content.Server.GameObjects.Components.MachineLinking } } - public void Subscribe(SignalTransmitterComponent transmitter) + public bool Subscribe(SignalTransmitterComponent transmitter) { if (_transmitters.Contains(transmitter)) { - return; + return true; } + if (_transmitters.Count >= _maxTransmitters) return false; + transmitter.Subscribe(this); _transmitters.Add(transmitter); + return true; } public void Unsubscribe(SignalTransmitterComponent transmitter) @@ -51,6 +64,20 @@ namespace Content.Server.GameObjects.Components.MachineLinking _transmitters.Remove(transmitter); } + public void UnsubscribeAll() + { + for (var i = _transmitters.Count-1; i >= 0; i--) + { + var transmitter = _transmitters[i]; + if (transmitter.Deleted) + { + continue; + } + + transmitter.Unsubscribe(this); + } + } + /// /// Subscribes/Unsubscribes a transmitter to this component. Returns whether it was successful. /// @@ -78,7 +105,11 @@ namespace Content.Server.GameObjects.Components.MachineLinking return false; } - Subscribe(transmitter); + if (!Subscribe(transmitter)) + { + Owner.PopupMessage(user, Loc.GetString("Max Transmitters reached!")); + return false; + } Owner.PopupMessage(user, Loc.GetString("Linked!")); return true; } @@ -101,15 +132,8 @@ namespace Content.Server.GameObjects.Components.MachineLinking { base.Shutdown(); - foreach (var transmitter in _transmitters) - { - if (transmitter.Deleted) - { - continue; - } + UnsubscribeAll(); - transmitter.Unsubscribe(this); - } _transmitters.Clear(); } } diff --git a/Content.Server/GameObjects/Components/MachineLinking/SignalSwitchComponent.cs b/Content.Server/GameObjects/Components/MachineLinking/SignalSwitchComponent.cs index 26e694f4e9..a73bc74e89 100644 --- a/Content.Server/GameObjects/Components/MachineLinking/SignalSwitchComponent.cs +++ b/Content.Server/GameObjects/Components/MachineLinking/SignalSwitchComponent.cs @@ -1,5 +1,6 @@ using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.Verbs; +using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects; using Robust.Shared.GameObjects; @@ -52,7 +53,10 @@ namespace Content.Server.GameObjects.Components.MachineLinking return; } - transmitter.TransmitSignal(user, _on); + if (!transmitter.TransmitSignal(_on)) + { + Owner.PopupMessage(user, Loc.GetString("No receivers connected.")); + } } private void UpdateSprite() diff --git a/Content.Server/GameObjects/Components/MachineLinking/SignalTransmitterComponent.cs b/Content.Server/GameObjects/Components/MachineLinking/SignalTransmitterComponent.cs index 081494309f..0018e82017 100644 --- a/Content.Server/GameObjects/Components/MachineLinking/SignalTransmitterComponent.cs +++ b/Content.Server/GameObjects/Components/MachineLinking/SignalTransmitterComponent.cs @@ -10,6 +10,7 @@ using Robust.Shared.Interfaces.Map; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Serialization; +using Robust.Shared.Utility; using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.MachineLinking @@ -87,11 +88,10 @@ namespace Content.Server.GameObjects.Components.MachineLinking } } - public bool TransmitSignal(IEntity user, T signal) + public bool TransmitSignal(T signal) { if (_receivers.Count == 0) { - Owner.PopupMessage(user, Loc.GetString("No receivers connected.")); return false; } @@ -150,8 +150,9 @@ namespace Content.Server.GameObjects.Components.MachineLinking { base.Shutdown(); - foreach (var receiver in _receivers) + for (var i = _receivers.Count-1; i >= 0; i++) { + var receiver = _receivers[i]; if (receiver.Deleted) { continue; @@ -159,6 +160,7 @@ namespace Content.Server.GameObjects.Components.MachineLinking receiver.Unsubscribe(this); } + _receivers.Clear(); } } diff --git a/Content.Server/GameObjects/Components/MachineLinking/SignalTwoWayLeverComponent.cs b/Content.Server/GameObjects/Components/MachineLinking/SignalTwoWayLeverComponent.cs new file mode 100644 index 0000000000..b85c37f29d --- /dev/null +++ b/Content.Server/GameObjects/Components/MachineLinking/SignalTwoWayLeverComponent.cs @@ -0,0 +1,68 @@ +#nullable enable +using System; +using Content.Server.GameObjects.Components.MachineLinking.Signals; +using Content.Shared.GameObjects.Components.Conveyor; +using Content.Shared.GameObjects.Components.MachineLinking; +using Content.Shared.Interfaces; +using Content.Shared.Interfaces.GameObjects.Components; +using Robust.Server.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Localization; + +namespace Content.Server.GameObjects.Components.MachineLinking +{ + [RegisterComponent] + [ComponentReference(typeof(IActivate))] + public class SignalTwoWayLeverComponent : SignalTransmitterComponent, IInteractHand, IActivate + { + public override string Name => "TwoWayLever"; + + private TwoWayLeverSignal _state = TwoWayLeverSignal.Middle; + + private bool _nextForward = true; + + public TwoWayLeverSignal State + { + get => _state; + private set + { + _state = value; + + if (Owner.TryGetComponent(out AppearanceComponent? appearance)) + { + appearance.SetData(TwoWayLeverVisuals.State, value); + } + } + } + + private void NextState(IEntity user) + { + State = State switch + { + TwoWayLeverSignal.Left => TwoWayLeverSignal.Middle, + TwoWayLeverSignal.Middle => _nextForward ? TwoWayLeverSignal.Right : TwoWayLeverSignal.Left, + TwoWayLeverSignal.Right => TwoWayLeverSignal.Middle, + _ => TwoWayLeverSignal.Middle + }; + + if (State == TwoWayLeverSignal.Left || State == TwoWayLeverSignal.Right) _nextForward = !_nextForward; + + if (!TransmitSignal(State)) + { + Owner.PopupMessage(user, Loc.GetString("No receivers connected.")); + } + } + + bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs) + { + NextState(eventArgs.User); + return true; + } + + void IActivate.Activate(ActivateEventArgs eventArgs) + { + NextState(eventArgs.User); + } + } +} diff --git a/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs b/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs index a671569135..482ab4da30 100644 --- a/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs +++ b/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs @@ -173,7 +173,7 @@ namespace Content.Server.GameObjects.Components.Recycling if (entity.TryGetComponent(out IPhysicsComponent physics)) { var controller = physics.EnsureController(); - controller.Move(direction, frameTime); + controller.Move(direction, frameTime, entity.Transform.WorldPosition - Owner.Transform.WorldPosition); } } } diff --git a/Content.Server/GameObjects/EntitySystems/ConveyorSystem.cs b/Content.Server/GameObjects/EntitySystems/ConveyorSystem.cs index d65b266d1f..b692bdd1bd 100644 --- a/Content.Server/GameObjects/EntitySystems/ConveyorSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/ConveyorSystem.cs @@ -17,78 +17,4 @@ namespace Content.Server.GameObjects.EntitySystems } } } - - public class ConveyorGroup - { - private readonly HashSet _conveyors; - private readonly HashSet _switches; - - public ConveyorGroup() - { - _conveyors = new HashSet(0); - _switches = new HashSet(0); - State = ConveyorState.Off; - } - - public IReadOnlyCollection Conveyors => _conveyors; - - public IReadOnlyCollection Switches => _switches; - - public ConveyorState State { get; private set; } - - public void AddConveyor(ConveyorComponent conveyor) - { - _conveyors.Add(conveyor); - conveyor.Sync(this); - } - - public void RemoveConveyor(ConveyorComponent conveyor) - { - _conveyors.Remove(conveyor); - } - - public void AddSwitch(ConveyorSwitchComponent conveyorSwitch) - { - _switches.Add(conveyorSwitch); - - if (_switches.Count == 1) - { - SetState(conveyorSwitch); - } - - conveyorSwitch.Sync(this); - } - - public void RemoveSwitch(ConveyorSwitchComponent conveyorSwitch) - { - _switches.Remove(conveyorSwitch); - } - - public void SetState(ConveyorSwitchComponent conveyorSwitch) - { - var state = conveyorSwitch.State; - - if (state == ConveyorState.Loose) - { - if (_switches.Count > 0) - { - return; - } - - state = ConveyorState.Off; - } - - State = state; - - foreach (var conveyor in Conveyors) - { - conveyor.Sync(this); - } - - foreach (var connectedSwitch in _switches) - { - connectedSwitch.Sync(this); - } - } - } } diff --git a/Content.Shared/GameObjects/Components/Conveyor/SharedConveyorComponent.cs b/Content.Shared/GameObjects/Components/Conveyor/SharedConveyorComponent.cs index bdc9167757..56f1ee383c 100644 --- a/Content.Shared/GameObjects/Components/Conveyor/SharedConveyorComponent.cs +++ b/Content.Shared/GameObjects/Components/Conveyor/SharedConveyorComponent.cs @@ -12,9 +12,8 @@ namespace Content.Shared.GameObjects.Components.Conveyor [Serializable, NetSerializable] public enum ConveyorState { - Off = 0, + Off, Forward, - Reversed, - Loose + Reversed } } diff --git a/Content.Shared/GameObjects/Components/MachineLinking/TwoWayLeverSignal.cs b/Content.Shared/GameObjects/Components/MachineLinking/TwoWayLeverSignal.cs new file mode 100644 index 0000000000..86c9704d02 --- /dev/null +++ b/Content.Shared/GameObjects/Components/MachineLinking/TwoWayLeverSignal.cs @@ -0,0 +1,19 @@ +using System; +using Robust.Shared.Serialization; + +namespace Content.Shared.GameObjects.Components.MachineLinking +{ + [Serializable, NetSerializable] + public enum TwoWayLeverVisuals : byte + { + State + } + + [Serializable, NetSerializable] + public enum TwoWayLeverSignal : byte + { + Middle, + Left, + Right + } +} diff --git a/Content.Shared/Physics/ConveyedController.cs b/Content.Shared/Physics/ConveyedController.cs index 7665100dd9..6232710b87 100644 --- a/Content.Shared/Physics/ConveyedController.cs +++ b/Content.Shared/Physics/ConveyedController.cs @@ -1,8 +1,11 @@ #nullable enable using Content.Shared.GameObjects.Components.Movement; using Robust.Shared.GameObjects.Components; +using Robust.Shared.Interfaces.Random; +using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Physics; +using Robust.Shared.Random; namespace Content.Shared.Physics { @@ -10,7 +13,7 @@ namespace Content.Shared.Physics { public override IPhysicsComponent? ControlledComponent { protected get; set; } - public void Move(Vector2 velocityDirection, float speed) + public void Move(Vector2 velocityDirection, float speed, Vector2 itemRelativeToConveyor) { if (ControlledComponent?.Owner.IsWeightless() ?? false) { @@ -23,6 +26,33 @@ namespace Content.Shared.Physics } LinearVelocity = velocityDirection * speed; + + //gravitating item towards center + //http://csharphelper.com/blog/2016/09/find-the-shortest-distance-between-a-point-and-a-line-segment-in-c/ + Vector2 centerPoint; + + var t = 0f; + if (velocityDirection.Length > 0) //if velocitydirection is 0, this calculation will divide by 0 + { + t = Vector2.Dot(itemRelativeToConveyor, velocityDirection) / + Vector2.Dot(velocityDirection, velocityDirection); + } + + if (t < 0) + { + centerPoint = new Vector2(); + } + else if(t > 1) + { + centerPoint = velocityDirection; + } + else + { + centerPoint = velocityDirection * t; + } + + var delta = centerPoint - itemRelativeToConveyor; + LinearVelocity += delta * (4 * delta.Length); } public override void UpdateAfterProcessing() diff --git a/Resources/Maps/saltern.yml b/Resources/Maps/saltern.yml index eca5ac4f8b..ab4aa3775f 100644 --- a/Resources/Maps/saltern.yml +++ b/Resources/Maps/saltern.yml @@ -1388,15 +1388,12 @@ entities: type: Robust.Server.GameObjects.Components.Container.Container type: ContainerContainer - uid: 163 - type: ConveyorSwitch + type: TwoWayLever components: - parent: 855 pos: -23.467268,-14.347846 rot: 3.141592653589793 rad type: Transform - - conveyors: [] - switches: [] - type: ConveyorSwitch - uid: 164 type: DisposalJunctionFlipped components: diff --git a/Resources/Prototypes/Catalog/LatheRecipes/cargo.yml b/Resources/Prototypes/Catalog/LatheRecipes/cargo.yml new file mode 100644 index 0000000000..bdf99f14d3 --- /dev/null +++ b/Resources/Prototypes/Catalog/LatheRecipes/cargo.yml @@ -0,0 +1,10 @@ +- type: latheRecipe + id: ConveyorAssembly + icon: + sprite: Constructible/Power/conveyor.rsi + state: conveyor_loose + result: ConveyorBeltAssembly + completetime: 1000 + materials: + steel: 1000 + glass: 50 diff --git a/Resources/Prototypes/Catalog/Research/technologies.yml b/Resources/Prototypes/Catalog/Research/technologies.yml index 776649dc4e..b5f1e674d4 100644 --- a/Resources/Prototypes/Catalog/Research/technologies.yml +++ b/Resources/Prototypes/Catalog/Research/technologies.yml @@ -42,6 +42,8 @@ requiredPoints: 1000 requiredTechnologies: - BasicResearch + unlockedRecipes: + - ConveyorAssembly - type: technology name: material sheet printing diff --git a/Resources/Prototypes/Entities/Constructible/Power/lathe.yml b/Resources/Prototypes/Entities/Constructible/Power/lathe.yml index 74aa03019b..4c06f7a770 100644 --- a/Resources/Prototypes/Entities/Constructible/Power/lathe.yml +++ b/Resources/Prototypes/Entities/Constructible/Power/lathe.yml @@ -102,6 +102,7 @@ - CableStack - Crowbar - Multitool + - ConveyorAssembly - type: UserInterface interfaces: - key: enum.LatheUiKey.Key diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/constructionGraphs.yml b/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/constructionGraphs.yml new file mode 100644 index 0000000000..4a66bb7d3c --- /dev/null +++ b/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/constructionGraphs.yml @@ -0,0 +1,57 @@ +- type: constructionGraph + id: ConveyorGraph + start: start + graph: + - node: start + edges: + - to: entity + steps: + - component: ConveyorAssembly + icon: + sprite: Constructible/Power/conveyor.rsi + state: conveyor_loose + name: conveyor belt assembly + doAfter: 2 + - node: item + entity: ConveyorBeltAssembly + actions: + - !type:SetAnchor + value: false + - node: entity + entity: ConveyorBelt + actions: + - !type:SetAnchor + value: true + - !type:SnapToGrid + offset: Center + edges: + - to: item + steps: + - tool: Prying + doAfter: 3 + +- type: constructionGraph + id: leverGraph + start: start + graph: + - node: start + actions: + - !type:SpawnPrototype + prototype: SteelSheet1 + amount: 2 + - !type:DeleteEntity {} + edges: + - to: lever + completed: + - !type:SnapToGrid {} + steps: + - material: Metal + amount: 2 + doAfter: 1 + - node: lever + entity: TwoWayLever + edges: + - to: start + steps: + - tool: Anchoring + doAfter: 1 diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/constructionRecipes.yml b/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/constructionRecipes.yml new file mode 100644 index 0000000000..30d3a84d58 --- /dev/null +++ b/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/constructionRecipes.yml @@ -0,0 +1,26 @@ +- type: construction + name: conveyor belt + id: conveyorbelt + graph: ConveyorGraph + startNode: start + targetNode: entity + category: Structures + description: A conveyor belt, commonly used to transport large numbers of items elsewhere quite quickly. + objectType: Structure + placementMode: SnapgridCenter + icon: + sprite: Constructible/Power/conveyor.rsi + state: conveyor_stopped_cw + +- type: construction + name: two-way lever + id: twowaylever + graph: leverGraph + startNode: start + targetNode: lever + category: Structures + description: A lever to control machines. It has 3 modes. + objectType: Structure + icon: + sprite: Constructible/Power/conveyor.rsi + state: switch-off diff --git a/Resources/Prototypes/Entities/Constructible/Specific/conveyor.yml b/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/conveyor.yml similarity index 65% rename from Resources/Prototypes/Entities/Constructible/Specific/conveyor.yml rename to Resources/Prototypes/Entities/Constructible/Specific/Conveyor/conveyor.yml index af06c06b62..3a6e2f43bc 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/conveyor.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/conveyor.yml @@ -25,7 +25,8 @@ sprite: Constructible/Power/conveyor.rsi state: conveyor_started_cw drawdepth: FloorObjects - + - type: SignalReceiver + maxTransmitters: 1 - type: Conveyor - type: Appearance visuals: @@ -33,26 +34,23 @@ state_running: conveyor_started_cw state_stopped: conveyor_stopped_cw state_reversed: conveyor_started_cw_r - state_loose: conveyor_loose - type: PowerReceiver + - type: Construction + graph: ConveyorGraph + node: entity - type: entity - id: ConveyorSwitch - name: conveyor switch - description: A conveyor control switch. + id: ConveyorBeltAssembly + parent: BaseItem + name: conveyor belt + suffix: assembly + description: A conveyor belt assembly. Used to construct a conveyor belt. components: - - type: Clickable - - type: InteractionOutline - - type: Sprite - netsync: false - sprite: Constructible/Power/conveyor.rsi - state: switch-off - - - type: ConveyorSwitch - - type: Appearance - visuals: - - type: ConveyorSwitchVisualizer - state_forward: switch-fwd - state_off: switch-off - state_reversed: switch-rev - state_loose: switch + - type: Sprite + netsync: false + sprite: Constructible/Power/conveyor.rsi + state: conveyor_loose + - type: ConveyorAssembly + - type: Construction + graph: ConveyorGraph + node: item diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/twoWayLever.yml b/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/twoWayLever.yml new file mode 100644 index 0000000000..9486116d8a --- /dev/null +++ b/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/twoWayLever.yml @@ -0,0 +1,21 @@ +- type: entity + id: TwoWayLever + name: two way switch + description: A two way switch. + components: + - type: Clickable + - type: InteractionOutline + - type: Sprite + netsync: false + sprite: Constructible/Power/conveyor.rsi + state: switch-off + - type: TwoWayLever + - type: Appearance + visuals: + - type: TwoWayLeverVisualizer + state_forward: switch-fwd + state_off: switch-off + state_reversed: switch-rev + - type: Construction + graph: leverGraph + node: lever