using Content.Server.Items; using Content.Server.MachineLinking.Components; using Content.Server.Power.Components; using Content.Shared.Conveyor; using Content.Shared.MachineLinking; using Robust.Server.GameObjects; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; namespace Content.Server.Conveyor { [RegisterComponent] public class ConveyorComponent : Component { public override string Name => "Conveyor"; [ViewVariables] private bool Powered => !Owner.TryGetComponent(out ApcPowerReceiverComponent? receiver) || receiver.Powered; /// /// The angle to move entities by in relation to the owner's rotation. /// [ViewVariables(VVAccess.ReadWrite)] [DataField("angle")] private Angle _angle = Angle.Zero; public float Speed => _speed; /// /// The amount of units to move the entity by per second. /// [ViewVariables(VVAccess.ReadWrite)] [DataField("speed")] private float _speed = 2f; private ConveyorState _state; /// /// The current state of this conveyor /// [ViewVariables(VVAccess.ReadWrite)] private ConveyorState State { get => _state; set { _state = value; UpdateAppearance(); } } public override void HandleMessage(ComponentMessage message, IComponent? component) { base.HandleMessage(message, component); switch (message) { case PowerChangedMessage powerChanged: OnPowerChanged(powerChanged); break; } } private void OnPowerChanged(PowerChangedMessage e) { UpdateAppearance(); } private void UpdateAppearance() { if (Owner.TryGetComponent(out var appearance)) { if (Powered) { appearance.SetData(ConveyorVisuals.State, _state); } else { appearance.SetData(ConveyorVisuals.State, ConveyorState.Off); } } } /// /// Calculates the angle in which entities on top of this conveyor /// belt are pushed in /// /// /// The angle when taking into account if the conveyor is reversed /// public Angle GetAngle() { var adjustment = _state == ConveyorState.Reversed ? MathHelper.Pi : 0; var radians = MathHelper.DegreesToRadians(_angle); return new Angle(Owner.Transform.LocalRotation.Theta + radians + adjustment); } public bool CanRun() { if (State == ConveyorState.Off) { return false; } if (Owner.TryGetComponent(out ApcPowerReceiverComponent? receiver) && !receiver.Powered) { return false; } if (Owner.HasComponent()) { return false; } return true; } public bool CanMove(IEntity entity) { // TODO We should only check status InAir or Static or MapGrid or /mayber/ container if (entity == Owner) { return false; } if (!entity.TryGetComponent(out IPhysBody? physics) || physics.BodyType == BodyType.Static) { return false; } if (entity.HasComponent()) { return false; } if (entity.HasComponent()) { return false; } if (entity.IsInContainer()) { return false; } return true; } public void SetState(TwoWayLeverSignal signal) { State = signal switch { TwoWayLeverSignal.Left => ConveyorState.Reversed, TwoWayLeverSignal.Middle => ConveyorState.Off, TwoWayLeverSignal.Right => ConveyorState.Forward, _ => ConveyorState.Off }; } } }