#nullable enable using System; using System.Collections.Generic; using System.Linq; 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(user, 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(), conveyors => { if (conveyors == null) { return; } foreach (var conveyor in conveyors) { if (!conveyor.TryGetComponent(out ConveyorComponent component)) { continue; } Connect(component); } }, () => _group?.Conveyors.Select(conveyor => conveyor.Owner)); serializer.DataReadWriteFunction( "switches", new List(), switches => { if (switches == null) { return; } foreach (var @switch in switches) { if (!@switch.TryGetComponent(out ConveyorSwitchComponent component)) { continue; } component.SyncWith(this); } }, () => _group?.Switches.Select(@switch => @switch.Owner)); } public override void OnRemove() { base.OnRemove(); Disconnect(); } bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs) { return NextState(); } bool 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(); } } }