2021-10-04 16:10:54 +01:00
using System ;
using System.Collections.Generic ;
using System.Diagnostics.CodeAnalysis ;
2021-11-22 19:31:12 +00:00
using Content.Shared.ActionBlocker ;
2021-10-04 16:10:54 +01:00
using Content.Shared.Alert ;
2021-11-13 21:43:37 +00:00
using Content.Shared.Buckle.Components ;
2021-10-04 16:10:54 +01:00
using Content.Shared.GameTicking ;
using Content.Shared.Input ;
using Content.Shared.Physics.Pull ;
using Content.Shared.Pulling.Components ;
using Content.Shared.Pulling.Events ;
using Content.Shared.Rotatable ;
using JetBrains.Annotations ;
using Robust.Shared.Containers ;
using Robust.Shared.GameObjects ;
using Robust.Shared.Input.Binding ;
using Robust.Shared.Map ;
2021-11-22 19:31:12 +00:00
using Robust.Shared.IoC ;
2021-10-04 16:10:54 +01:00
using Robust.Shared.Maths ;
using Robust.Shared.Physics ;
using Robust.Shared.Players ;
using Robust.Shared.Log ;
namespace Content.Shared.Pulling
{
public abstract partial class SharedPullingSystem : EntitySystem
{
2021-11-22 19:31:12 +00:00
[Dependency] private readonly ActionBlockerSystem _blocker = default ! ;
2021-10-04 16:10:54 +01:00
public bool CanPull ( IEntity puller , IEntity pulled )
{
if ( ! puller . HasComponent < SharedPullerComponent > ( ) )
{
return false ;
}
2021-11-22 19:31:12 +00:00
if ( ! _blocker . CanInteract ( puller . Uid ) )
{
return false ;
}
2021-10-04 16:10:54 +01:00
if ( ! pulled . TryGetComponent < IPhysBody > ( out var _physics ) )
{
return false ;
}
if ( _physics . BodyType = = BodyType . Static )
{
return false ;
}
if ( puller = = pulled )
{
return false ;
}
if ( ! puller . IsInSameOrNoContainer ( pulled ) )
{
return false ;
}
2021-11-13 21:43:37 +00:00
if ( puller . TryGetComponent < SharedBuckleComponent > ( out var buckle ) )
{
// Prevent people pulling the chair they're on, etc.
if ( buckle . Buckled & & ( buckle . LastEntityBuckledTo = = pulled . Uid ) )
{
return false ;
}
}
2021-10-04 16:10:54 +01:00
var startPull = new StartPullAttemptEvent ( puller , pulled ) ;
RaiseLocalEvent ( puller . Uid , startPull ) ;
return ! startPull . Cancelled ;
}
public bool TogglePull ( IEntity puller , SharedPullableComponent pullable )
{
if ( pullable . Puller = = puller )
{
return TryStopPull ( pullable ) ;
}
return TryStartPull ( puller , pullable . Owner ) ;
}
// -- Core attempted actions --
public bool TryStopPull ( SharedPullableComponent pullable , IEntity ? user = null )
{
if ( ! pullable . BeingPulled )
{
return false ;
}
var msg = new StopPullingEvent ( user ? . Uid ) ;
2021-11-09 14:45:14 +01:00
RaiseLocalEvent ( pullable . OwnerUid , msg ) ;
2021-10-04 16:10:54 +01:00
if ( msg . Cancelled ) return false ;
_pullSm . ForceRelationship ( null , pullable ) ;
return true ;
}
public bool TryStartPull ( IEntity puller , IEntity pullable )
{
if ( ! puller . TryGetComponent < SharedPullerComponent > ( out var pullerComp ) )
{
return false ;
}
if ( ! pullable . TryGetComponent < SharedPullableComponent > ( out var pullableComp ) )
{
return false ;
}
return TryStartPull ( pullerComp , pullableComp ) ;
}
// The main "start pulling" function.
public bool TryStartPull ( SharedPullerComponent puller , SharedPullableComponent pullable )
{
2021-11-23 14:02:08 +01:00
if ( puller . Pulling = = pullable . Owner )
2021-10-04 16:10:54 +01:00
return true ;
// Pulling a new object : Perform sanity checks.
if ( ! EntitySystem . Get < SharedPullingSystem > ( ) . CanPull ( puller . Owner , pullable . Owner ) )
{
return false ;
}
if ( ! puller . Owner . TryGetComponent < PhysicsComponent > ( out var pullerPhysics ) )
{
return false ;
}
if ( ! pullable . Owner . TryGetComponent < PhysicsComponent > ( out var pullablePhysics ) )
{
return false ;
}
// Ensure that the puller is not currently pulling anything.
// If this isn't done, then it happens too late, and the start/stop messages go out of order,
// and next thing you know it thinks it's not pulling anything even though it is!
var oldPullable = puller . Pulling ;
if ( oldPullable ! = null )
{
if ( oldPullable . TryGetComponent < SharedPullableComponent > ( out var oldPullableComp ) )
{
if ( ! TryStopPull ( oldPullableComp ) )
{
return false ;
}
}
else
{
Logger . WarningS ( "c.go.c.pulling" , "Well now you've done it, haven't you? Someone transferred pulling (onto {0}) while presently pulling something that has no Pullable component (on {1})!" , pullable . Owner , oldPullable ) ;
return false ;
}
}
// Ensure that the pullable is not currently being pulled.
// Same sort of reasons as before.
var oldPuller = pullable . Puller ;
if ( oldPuller ! = null )
{
if ( ! TryStopPull ( pullable ) )
{
return false ;
}
}
// Continue with pulling process.
var pullAttempt = new PullAttemptMessage ( pullerPhysics , pullablePhysics ) ;
2021-11-09 14:45:14 +01:00
RaiseLocalEvent ( puller . OwnerUid , pullAttempt , broadcast : false ) ;
2021-10-04 16:10:54 +01:00
if ( pullAttempt . Cancelled )
{
return false ;
}
2021-11-09 14:45:14 +01:00
RaiseLocalEvent ( pullable . OwnerUid , pullAttempt ) ;
2021-10-04 16:10:54 +01:00
if ( pullAttempt . Cancelled )
{
return false ;
}
_pullSm . ForceRelationship ( puller , pullable ) ;
return true ;
}
2021-11-07 02:16:49 +00:00
public bool TryMoveTo ( SharedPullableComponent pullable , EntityCoordinates to )
2021-10-04 16:10:54 +01:00
{
if ( pullable . Puller = = null )
{
return false ;
}
if ( ! pullable . Owner . HasComponent < PhysicsComponent > ( ) )
{
return false ;
}
_pullSm . ForceSetMovingTo ( pullable , to ) ;
return true ;
}
public void StopMoveTo ( SharedPullableComponent pullable )
{
_pullSm . ForceSetMovingTo ( pullable , null ) ;
}
}
}