Re-organize all projects (#4166)

This commit is contained in:
DrSmugleaf
2021-06-09 22:19:39 +02:00
committed by GitHub
parent 9f50e4061b
commit ff1a2d97ea
1773 changed files with 5258 additions and 5508 deletions

View File

@@ -0,0 +1,39 @@
using Content.Server.Disposal.Unit.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Server.Disposal.Tube.Components
{
[RegisterComponent]
[ComponentReference(typeof(IDisposalTubeComponent))]
public class DisposalBendComponent : DisposalTubeComponent
{
[DataField("sideDegrees")]
private int _sideDegrees = -90;
public override string Name => "DisposalBend";
protected override Direction[] ConnectableDirections()
{
var direction = Owner.Transform.LocalRotation;
var side = new Angle(MathHelper.DegreesToRadians(direction.Degrees + _sideDegrees));
return new[] {direction.GetDir(), side.GetDir()};
}
public override Direction NextDirection(DisposalHolderComponent holder)
{
var directions = ConnectableDirections();
var previousTube = holder.PreviousTube;
if (previousTube == null)
{
return directions[0];
}
var previousDirection = DirectionTo(previousTube);
return previousDirection == directions[0] ? directions[1] : directions[0];
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using System.Linq;
using Content.Server.Disposal.Unit.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Random;
namespace Content.Server.Disposal.Tube.Components
{
[RegisterComponent]
[ComponentReference(typeof(IDisposalTubeComponent))]
public class DisposalEntryComponent : DisposalTubeComponent
{
[Dependency] private readonly IRobustRandom _random = default!;
private const string HolderPrototypeId = "DisposalHolder";
public override string Name => "DisposalEntry";
public bool TryInsert(DisposalUnitComponent from)
{
var holder = Owner.EntityManager.SpawnEntity(HolderPrototypeId, Owner.Transform.MapPosition);
var holderComponent = holder.GetComponent<DisposalHolderComponent>();
foreach (var entity in from.ContainedEntities.ToArray())
{
holderComponent.TryInsert(entity);
}
holderComponent.Air.Merge(from.Air);
from.Air.Clear();
return TryInsert(holderComponent);
}
public bool TryInsert(DisposalHolderComponent holder)
{
if (!Contents.Insert(holder.Owner))
{
return false;
}
holder.EnterTube(this);
return true;
}
protected override Direction[] ConnectableDirections()
{
return new[] {Owner.Transform.LocalRotation.GetDir()};
}
/// <summary>
/// Ejects contents when they come from the same direction the entry is facing.
/// </summary>
public override Direction NextDirection(DisposalHolderComponent holder)
{
if (holder.PreviousTube != null && DirectionTo(holder.PreviousTube) == ConnectableDirections()[0])
{
var invalidDirections = new[] { ConnectableDirections()[0], Direction.Invalid };
var directions = Enum.GetValues(typeof(Direction))
.Cast<Direction>().Except(invalidDirections).ToList();
return _random.Pick(directions);
}
return ConnectableDirections()[0];
}
}
}

View File

@@ -0,0 +1,49 @@
using System.Collections.Generic;
using System.Linq;
using Content.Server.Disposal.Unit.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Random;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Server.Disposal.Tube.Components
{
[RegisterComponent]
[ComponentReference(typeof(IDisposalTubeComponent))]
public class DisposalJunctionComponent : DisposalTubeComponent
{
[Dependency] private readonly IRobustRandom _random = default!;
/// <summary>
/// The angles to connect to.
/// </summary>
[ViewVariables]
[DataField("degrees")]
private List<Angle> _degrees = new();
public override string Name => "DisposalJunction";
protected override Direction[] ConnectableDirections()
{
var direction = Owner.Transform.LocalRotation;
return _degrees.Select(degree => new Angle(degree.Theta + direction.Theta).GetDir()).ToArray();
}
public override Direction NextDirection(DisposalHolderComponent holder)
{
var next = Owner.Transform.LocalRotation.GetDir();
var directions = ConnectableDirections().Skip(1).ToArray();
if (holder.PreviousTube == null ||
DirectionTo(holder.PreviousTube) == next)
{
return _random.Pick(directions);
}
return next;
}
}
}

View File

@@ -0,0 +1,216 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Text;
using Content.Server.Disposal.Unit.Components;
using Content.Server.Hands.Components;
using Content.Server.UserInterface;
using Content.Shared.ActionBlocker;
using Content.Shared.Interaction;
using Content.Shared.Notification;
using Content.Shared.Verbs;
using Robust.Server.Console;
using Robust.Server.GameObjects;
using Robust.Server.Player;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Player;
using Robust.Shared.ViewVariables;
using static Content.Shared.Disposal.Components.SharedDisposalRouterComponent;
namespace Content.Server.Disposal.Tube.Components
{
[RegisterComponent]
[ComponentReference(typeof(IActivate))]
[ComponentReference(typeof(IDisposalTubeComponent))]
public class DisposalRouterComponent : DisposalJunctionComponent, IActivate
{
public override string Name => "DisposalRouter";
[ViewVariables]
private readonly HashSet<string> _tags = new();
[ViewVariables]
public bool Anchored =>
!Owner.TryGetComponent(out IPhysBody? physics) ||
physics.BodyType == BodyType.Static;
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(DisposalRouterUiKey.Key);
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();
if (UserInterface != null)
{
UserInterface.OnReceiveMessage += OnUiReceiveMessage;
}
UpdateUserInterface();
}
/// <summary>
/// Handles ui messages from the client. For things such as button presses
/// which interact with the world and require server action.
/// </summary>
/// <param name="obj">A user interface message from the client.</param>
private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
{
if (obj.Session.AttachedEntity == null)
{
return;
}
var msg = (UiActionMessage) obj.Message;
if (!PlayerCanUseDisposalTagger(obj.Session))
return;
//Check for correct message and ignore maleformed strings
if (msg.Action == UiAction.Ok && TagRegex.IsMatch(msg.Tags))
{
_tags.Clear();
foreach (var tag in msg.Tags.Split(',', StringSplitOptions.RemoveEmptyEntries))
{
_tags.Add(tag.Trim());
ClickSound();
}
}
}
/// <summary>
/// Checks whether the player entity is able to use the configuration interface of the pipe tagger.
/// </summary>
/// <param name="IPlayerSession">The player session.</param>
/// <returns>Returns true if the entity can use the configuration interface, and false if it cannot.</returns>
private bool PlayerCanUseDisposalTagger(IPlayerSession session)
{
//Need player entity to check if they are still able to use the configuration interface
if (session.AttachedEntity == null)
return false;
if (!Anchored)
return false;
var groupController = IoCManager.Resolve<IConGroupController>();
//Check if player can interact in their current state
if (!groupController.CanAdminMenu(session) && (!ActionBlockerSystem.CanInteract(session.AttachedEntity) || !ActionBlockerSystem.CanUse(session.AttachedEntity)))
return false;
return true;
}
/// <summary>
/// Gets component data to be used to update the user interface client-side.
/// </summary>
/// <returns>Returns a <see cref="DisposalRouterUserInterfaceState"/></returns>
private DisposalRouterUserInterfaceState GetUserInterfaceState()
{
if(_tags.Count <= 0)
{
return new DisposalRouterUserInterfaceState("");
}
var taglist = new 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()
{
SoundSystem.Play(Filter.Pvs(Owner), "/Audio/Machines/machine_switch.ogg", Owner, AudioParams.Default.WithVolume(-2f));
}
/// <summary>
/// Called when you click the owner entity with an empty hand. Opens the UI client-side if possible.
/// </summary>
/// <param name="args">Data relevant to the event such as the actor which triggered it.</param>
void IActivate.Activate(ActivateEventArgs args)
{
if (!args.User.TryGetComponent(out ActorComponent? actor))
{
return;
}
if (!args.User.TryGetComponent(out IHandsComponent? hands))
{
Owner.PopupMessage(args.User, Loc.GetString("You have no hands."));
return;
}
var activeHandEntity = hands.GetActiveHand?.Owner;
if (activeHandEntity == null)
{
OpenUserInterface(actor);
}
}
public override void OnRemove()
{
UserInterface?.CloseAll();
base.OnRemove();
}
private void OpenUserInterface(ActorComponent actor)
{
UpdateUserInterface();
UserInterface?.Open(actor.PlayerSession);
}
[Verb]
public sealed class ConfigureVerb : Verb<DisposalRouterComponent>
{
protected override void GetData(IEntity user, DisposalRouterComponent component, VerbData data)
{
var session = user.PlayerSession();
var groupController = IoCManager.Resolve<IConGroupController>();
if (session == null || !groupController.CanAdminMenu(session))
{
data.Visibility = VerbVisibility.Invisible;
return;
}
data.Text = Loc.GetString("Open Configuration");
data.IconTexture = "/Textures/Interface/VerbIcons/settings.svg.192dpi.png";
}
protected override void Activate(IEntity user, DisposalRouterComponent component)
{
if (user.TryGetComponent(out ActorComponent? actor))
{
component.OpenUserInterface(actor);
}
}
}
}
}

View File

@@ -0,0 +1,182 @@
#nullable enable
using Content.Server.Disposal.Unit.Components;
using Content.Server.Hands.Components;
using Content.Server.UserInterface;
using Content.Shared.ActionBlocker;
using Content.Shared.Interaction;
using Content.Shared.Notification;
using Content.Shared.Verbs;
using Robust.Server.Console;
using Robust.Server.GameObjects;
using Robust.Server.Player;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Player;
using Robust.Shared.ViewVariables;
using static Content.Shared.Disposal.Components.SharedDisposalTaggerComponent;
namespace Content.Server.Disposal.Tube.Components
{
[RegisterComponent]
[ComponentReference(typeof(IActivate))]
[ComponentReference(typeof(IDisposalTubeComponent))]
public class DisposalTaggerComponent : DisposalTransitComponent, IActivate
{
public override string Name => "DisposalTagger";
[ViewVariables(VVAccess.ReadWrite)]
private string _tag = "";
[ViewVariables]
public bool Anchored =>
!Owner.TryGetComponent(out PhysicsComponent? physics) ||
physics.BodyType == BodyType.Static;
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(DisposalTaggerUiKey.Key);
public override Direction NextDirection(DisposalHolderComponent holder)
{
holder.Tags.Add(_tag);
return base.NextDirection(holder);
}
public override void Initialize()
{
base.Initialize();
if (UserInterface != null)
{
UserInterface.OnReceiveMessage += OnUiReceiveMessage;
}
UpdateUserInterface();
}
/// <summary>
/// Handles ui messages from the client. For things such as button presses
/// which interact with the world and require server action.
/// </summary>
/// <param name="obj">A user interface message from the client.</param>
private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
{
var msg = (UiActionMessage) obj.Message;
if (!PlayerCanUseDisposalTagger(obj.Session))
return;
//Check for correct message and ignore maleformed strings
if (msg.Action == UiAction.Ok && TagRegex.IsMatch(msg.Tag))
{
_tag = msg.Tag;
ClickSound();
}
}
/// <summary>
/// Checks whether the player entity is able to use the configuration interface of the pipe tagger.
/// </summary>
/// <param name="IPlayerSession">The player entity.</param>
/// <returns>Returns true if the entity can use the configuration interface, and false if it cannot.</returns>
private bool PlayerCanUseDisposalTagger(IPlayerSession session)
{
//Need player entity to check if they are still able to use the configuration interface
if (session.AttachedEntity == null)
return false;
if (!Anchored)
return false;
var groupController = IoCManager.Resolve<IConGroupController>();
//Check if player can interact in their current state
if (!groupController.CanAdminMenu(session) && (!ActionBlockerSystem.CanInteract(session.AttachedEntity) || !ActionBlockerSystem.CanUse(session.AttachedEntity)))
return false;
return true;
}
/// <summary>
/// Gets component data to be used to update the user interface client-side.
/// </summary>
/// <returns>Returns a <see cref="DisposalTaggerUserInterfaceState"/></returns>
private DisposalTaggerUserInterfaceState GetUserInterfaceState()
{
return new(_tag);
}
private void UpdateUserInterface()
{
var state = GetUserInterfaceState();
UserInterface?.SetState(state);
}
private void ClickSound()
{
SoundSystem.Play(Filter.Pvs(Owner), "/Audio/Machines/machine_switch.ogg", Owner, AudioParams.Default.WithVolume(-2f));
}
/// <summary>
/// Called when you click the owner entity with an empty hand. Opens the UI client-side if possible.
/// </summary>
/// <param name="args">Data relevant to the event such as the actor which triggered it.</param>
void IActivate.Activate(ActivateEventArgs args)
{
if (!args.User.TryGetComponent(out ActorComponent? actor))
{
return;
}
if (!args.User.TryGetComponent(out IHandsComponent? hands))
{
Owner.PopupMessage(args.User, Loc.GetString("You have no hands."));
return;
}
var activeHandEntity = hands.GetActiveHand?.Owner;
if (activeHandEntity == null)
{
OpenUserInterface(actor);
}
}
public override void OnRemove()
{
base.OnRemove();
UserInterface?.CloseAll();
}
[Verb]
public sealed class ConfigureVerb : Verb<DisposalTaggerComponent>
{
protected override void GetData(IEntity user, DisposalTaggerComponent component, VerbData data)
{
var groupController = IoCManager.Resolve<IConGroupController>();
if (!user.TryGetComponent(out ActorComponent? actor) || !groupController.CanAdminMenu(actor.PlayerSession))
{
data.Visibility = VerbVisibility.Invisible;
return;
}
data.Text = Loc.GetString("Open Configuration");
data.IconTexture = "/Textures/Interface/VerbIcons/settings.svg.192dpi.png";
}
protected override void Activate(IEntity user, DisposalTaggerComponent component)
{
if (user.TryGetComponent(out ActorComponent? actor))
{
component.OpenUserInterface(actor);
}
}
}
private void OpenUserInterface(ActorComponent actor)
{
UpdateUserInterface();
UserInterface?.Open(actor.PlayerSession);
}
}
}

View File

@@ -0,0 +1,38 @@
using System;
using Content.Server.Disposal.Unit.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
namespace Content.Server.Disposal.Tube.Components
{
// TODO: Different types of tubes eject in random direction with no exit point
[RegisterComponent]
[ComponentReference(typeof(IDisposalTubeComponent))]
public class DisposalTransitComponent : DisposalTubeComponent
{
public override string Name => "DisposalTransit";
protected override Direction[] ConnectableDirections()
{
var rotation = Owner.Transform.LocalRotation;
var opposite = new Angle(rotation.Theta + Math.PI);
return new[] {rotation.GetDir(), opposite.GetDir()};
}
public override Direction NextDirection(DisposalHolderComponent holder)
{
var directions = ConnectableDirections();
var previousTube = holder.PreviousTube;
var forward = directions[0];
if (previousTube == null)
{
return forward;
}
var backward = directions[1];
return DirectionTo(previousTube) == forward ? backward : forward;
}
}
}

View File

@@ -0,0 +1,313 @@
#nullable enable
using System;
using System.Linq;
using Content.Server.Anchor;
using Content.Server.Disposal.Unit.Components;
using Content.Shared.Acts;
using Content.Shared.Disposal.Components;
using Content.Shared.Notification;
using Content.Shared.Verbs;
using Robust.Server.Console;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Player;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Timing;
using Robust.Shared.ViewVariables;
namespace Content.Server.Disposal.Tube.Components
{
public abstract class DisposalTubeComponent : Component, IDisposalTubeComponent, IBreakAct
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
private static readonly TimeSpan ClangDelay = TimeSpan.FromSeconds(0.5);
private TimeSpan _lastClang;
private bool _connected;
private bool _broken;
[DataField("clangSound")]
private string _clangSound = "/Audio/Effects/clang.ogg";
/// <summary>
/// Container of entities that are currently inside this tube
/// </summary>
[ViewVariables]
public Container Contents { get; private set; } = default!;
[ViewVariables]
private bool Anchored =>
!Owner.TryGetComponent(out PhysicsComponent? physics) ||
physics.BodyType == BodyType.Static;
/// <summary>
/// The directions that this tube can connect to others from
/// </summary>
/// <returns>a new array of the directions</returns>
protected abstract Direction[] ConnectableDirections();
public abstract Direction NextDirection(DisposalHolderComponent holder);
public virtual Vector2 ExitVector(DisposalHolderComponent holder)
{
return NextDirection(holder).ToVec();
}
protected Direction DirectionTo(IDisposalTubeComponent other)
{
return (other.Owner.Transform.WorldPosition - Owner.Transform.WorldPosition).GetDir();
}
public IDisposalTubeComponent? NextTube(DisposalHolderComponent holder)
{
var nextDirection = NextDirection(holder);
var oppositeDirection = new Angle(nextDirection.ToAngle().Theta + Math.PI).GetDir();
var grid = _mapManager.GetGrid(Owner.Transform.GridID);
var position = Owner.Transform.Coordinates;
foreach (var entity in grid.GetInDir(position, nextDirection))
{
if (!Owner.EntityManager.ComponentManager.TryGetComponent(entity, out IDisposalTubeComponent? tube))
{
continue;
}
if (!tube.CanConnect(oppositeDirection, this))
{
continue;
}
if (!CanConnect(nextDirection, tube))
{
continue;
}
return tube;
}
return null;
}
public bool Remove(DisposalHolderComponent holder)
{
var removed = Contents.Remove(holder.Owner);
holder.ExitDisposals();
return removed;
}
public bool TransferTo(DisposalHolderComponent holder, IDisposalTubeComponent to)
{
var position = holder.Owner.Transform.LocalPosition;
if (!to.Contents.Insert(holder.Owner))
{
return false;
}
holder.Owner.Transform.LocalPosition = position;
Contents.Remove(holder.Owner);
holder.EnterTube(to);
return true;
}
// TODO: Make disposal pipes extend the grid
private void Connect()
{
if (_connected || _broken)
{
return;
}
_connected = true;
}
public bool CanConnect(Direction direction, IDisposalTubeComponent with)
{
if (!_connected)
{
return false;
}
if (_broken)
{
return false;
}
if (!ConnectableDirections().Contains(direction))
{
return false;
}
return true;
}
private void Disconnect()
{
if (!_connected)
{
return;
}
_connected = false;
foreach (var entity in Contents.ContainedEntities.ToArray())
{
if (!entity.TryGetComponent(out DisposalHolderComponent? holder))
{
continue;
}
holder.ExitDisposals();
}
}
public void PopupDirections(IEntity entity)
{
var directions = string.Join(", ", ConnectableDirections());
Owner.PopupMessage(entity, Loc.GetString("{0}", directions));
}
private void UpdateVisualState()
{
if (!Owner.TryGetComponent(out AppearanceComponent? appearance))
{
return;
}
var state = _broken
? DisposalTubeVisualState.Broken
: Anchored
? DisposalTubeVisualState.Anchored
: DisposalTubeVisualState.Free;
appearance.SetData(DisposalTubeVisuals.VisualState, state);
}
public void AnchoredChanged()
{
if (!Owner.TryGetComponent(out PhysicsComponent? physics))
{
return;
}
if (physics.BodyType == BodyType.Static)
{
OnAnchor();
}
else
{
OnUnAnchor();
}
}
private void OnAnchor()
{
Connect();
UpdateVisualState();
}
private void OnUnAnchor()
{
Disconnect();
UpdateVisualState();
}
public override void Initialize()
{
base.Initialize();
Contents = ContainerHelpers.EnsureContainer<Container>(Owner, Name);
Owner.EnsureComponent<AnchorableComponent>();
}
protected override void Startup()
{
base.Startup();
Owner.EnsureComponent<PhysicsComponent>(out var physicsComponent);
if (physicsComponent.BodyType != BodyType.Static)
{
return;
}
Connect();
UpdateVisualState();
}
public override void OnRemove()
{
base.OnRemove();
Disconnect();
}
public override void HandleMessage(ComponentMessage message, IComponent? component)
{
base.HandleMessage(message, component);
switch (message)
{
case RelayMovementEntityMessage _:
if (_gameTiming.CurTime < _lastClang + ClangDelay)
{
break;
}
_lastClang = _gameTiming.CurTime;
SoundSystem.Play(Filter.Pvs(Owner), _clangSound, Owner.Transform.Coordinates);
break;
}
}
void IBreakAct.OnBreak(BreakageEventArgs eventArgs)
{
_broken = true; // TODO: Repair
Disconnect();
UpdateVisualState();
}
[Verb]
private sealed class TubeDirectionsVerb : Verb<IDisposalTubeComponent>
{
protected override void GetData(IEntity user, IDisposalTubeComponent component, VerbData data)
{
data.Text = Loc.GetString("Tube Directions");
data.CategoryData = VerbCategories.Debug;
data.Visibility = VerbVisibility.Invisible;
var groupController = IoCManager.Resolve<IConGroupController>();
if (user.TryGetComponent<ActorComponent>(out var player))
{
if (groupController.CanCommand(player.PlayerSession, "tubeconnections"))
{
data.Visibility = VerbVisibility.Visible;
}
}
}
protected override void Activate(IEntity user, IDisposalTubeComponent component)
{
var groupController = IoCManager.Resolve<IConGroupController>();
if (user.TryGetComponent<ActorComponent>(out var player))
{
if (groupController.CanCommand(player.PlayerSession, "tubeconnections"))
{
component.PopupDirections(user);
}
}
}
}
}
}

View File

@@ -0,0 +1,21 @@
#nullable enable
using Content.Server.Disposal.Unit.Components;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
namespace Content.Server.Disposal.Tube.Components
{
public interface IDisposalTubeComponent : IComponent
{
Container Contents { get; }
Direction NextDirection(DisposalHolderComponent holder);
Vector2 ExitVector(DisposalHolderComponent holder);
IDisposalTubeComponent? NextTube(DisposalHolderComponent holder);
bool Remove(DisposalHolderComponent holder);
bool TransferTo(DisposalHolderComponent holder, IDisposalTubeComponent to);
bool CanConnect(Direction direction, IDisposalTubeComponent with);
void PopupDirections(IEntity entity);
}
}

View File

@@ -0,0 +1,30 @@
using Content.Server.Disposal.Tube.Components;
using Robust.Shared.GameObjects;
namespace Content.Server.Disposal.Tube
{
public sealed class DisposalTubeSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DisposalTubeComponent, PhysicsBodyTypeChangedEvent>(BodyTypeChanged);
}
public override void Shutdown()
{
base.Shutdown();
UnsubscribeLocalEvent<DisposalTubeComponent, PhysicsBodyTypeChangedEvent>();
}
private static void BodyTypeChanged(
EntityUid uid,
DisposalTubeComponent component,
PhysicsBodyTypeChangedEvent args)
{
component.AnchoredChanged();
}
}
}