| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- using Content.Server.DeviceLinking.Events;
- using Content.Server.DeviceLinking.Systems;
- using Content.Server.Materials;
- using Content.Server.Power.Components;
- using Content.Shared.Conveyor;
- using Content.Shared.Destructible;
- using Content.Shared.Maps;
- using Content.Shared.Physics;
- using Content.Shared.Physics.Controllers;
- using Content.Shared.Power;
- using Robust.Shared.Physics;
- using Robust.Shared.Physics.Collision.Shapes;
- using Robust.Shared.Physics.Components;
- using Robust.Shared.Physics.Systems;
- namespace Content.Server.Physics.Controllers;
- public sealed class ConveyorController : SharedConveyorController
- {
- [Dependency] private readonly FixtureSystem _fixtures = default!;
- [Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
- [Dependency] private readonly MaterialReclaimerSystem _materialReclaimer = default!;
- [Dependency] private readonly SharedBroadphaseSystem _broadphase = default!;
- [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
- public override void Initialize()
- {
- UpdatesAfter.Add(typeof(MoverController));
- SubscribeLocalEvent<ConveyorComponent, ComponentInit>(OnInit);
- SubscribeLocalEvent<ConveyorComponent, ComponentShutdown>(OnConveyorShutdown);
- SubscribeLocalEvent<ConveyorComponent, BreakageEventArgs>(OnBreakage);
- SubscribeLocalEvent<ConveyorComponent, SignalReceivedEvent>(OnSignalReceived);
- SubscribeLocalEvent<ConveyorComponent, PowerChangedEvent>(OnPowerChanged);
- base.Initialize();
- }
- private void OnInit(EntityUid uid, ConveyorComponent component, ComponentInit args)
- {
- _signalSystem.EnsureSinkPorts(uid, component.ReversePort, component.ForwardPort, component.OffPort);
- if (TryComp<PhysicsComponent>(uid, out var physics))
- {
- var shape = new PolygonShape();
- shape.SetAsBox(0.55f, 0.55f);
- _fixtures.TryCreateFixture(uid, shape, ConveyorFixture,
- collisionLayer: (int) (CollisionGroup.LowImpassable | CollisionGroup.MidImpassable |
- CollisionGroup.Impassable), hard: false, body: physics);
- }
- }
- private void OnConveyorShutdown(EntityUid uid, ConveyorComponent component, ComponentShutdown args)
- {
- if (MetaData(uid).EntityLifeStage >= EntityLifeStage.Terminating)
- return;
- if (!TryComp<PhysicsComponent>(uid, out var physics))
- return;
- _fixtures.DestroyFixture(uid, ConveyorFixture, body: physics);
- }
- private void OnBreakage(Entity<ConveyorComponent> ent, ref BreakageEventArgs args)
- {
- SetState(ent, ConveyorState.Off, ent);
- }
- private void OnPowerChanged(EntityUid uid, ConveyorComponent component, ref PowerChangedEvent args)
- {
- component.Powered = args.Powered;
- UpdateAppearance(uid, component);
- Dirty(uid, component);
- }
- private void UpdateAppearance(EntityUid uid, ConveyorComponent component)
- {
- _appearance.SetData(uid, ConveyorVisuals.State, component.Powered ? component.State : ConveyorState.Off);
- }
- private void OnSignalReceived(EntityUid uid, ConveyorComponent component, ref SignalReceivedEvent args)
- {
- if (args.Port == component.OffPort)
- SetState(uid, ConveyorState.Off, component);
- else if (args.Port == component.ForwardPort)
- {
- AwakenEntities(uid, component);
- SetState(uid, ConveyorState.Forward, component);
- }
- else if (args.Port == component.ReversePort)
- {
- AwakenEntities(uid, component);
- SetState(uid, ConveyorState.Reverse, component);
- }
- }
- private void SetState(EntityUid uid, ConveyorState state, ConveyorComponent? component = null)
- {
- if (!Resolve(uid, ref component))
- return;
- if (!_materialReclaimer.SetReclaimerEnabled(uid, state != ConveyorState.Off))
- return;
- component.State = state;
- if (TryComp<PhysicsComponent>(uid, out var physics))
- _broadphase.RegenerateContacts((uid, physics));
- UpdateAppearance(uid, component);
- Dirty(uid, component);
- }
- /// <summary>
- /// Awakens sleeping entities on the conveyor belt's tile when it's turned on.
- /// Fixes an issue where non-hard/sleeping entities refuse to wake up + collide if a belt is turned off and on again.
- /// </summary>
- private void AwakenEntities(EntityUid uid, ConveyorComponent component)
- {
- var xformQuery = GetEntityQuery<TransformComponent>();
- var bodyQuery = GetEntityQuery<PhysicsComponent>();
- if (!xformQuery.TryGetComponent(uid, out var xform))
- return;
- var beltTileRef = xform.Coordinates.GetTileRef(EntityManager, MapManager);
- if (beltTileRef != null)
- {
- var intersecting = Lookup.GetLocalEntitiesIntersecting(beltTileRef.Value, 0f);
- foreach (var entity in intersecting)
- {
- if (!bodyQuery.TryGetComponent(entity, out var physics))
- continue;
- if (physics.BodyType != BodyType.Static)
- Physics.WakeBody(entity, body: physics);
- }
- }
- }
- }
|