2023-02-16 18:27:43 -06:00
using Content.Server.Administration.Logs ;
2023-02-24 19:01:25 -05:00
using Content.Shared.DoAfter ;
2023-02-16 18:27:43 -06:00
using Content.Shared.Database ;
2023-01-03 01:53:16 -06:00
using Content.Shared.Interaction.Events ;
2023-01-02 19:58:25 -06:00
using Content.Shared.Teleportation.Components ;
using Content.Shared.Teleportation.Systems ;
using Robust.Server.GameObjects ;
namespace Content.Server.Teleportation ;
/// <summary>
/// This handles creating portals from a hand teleporter.
/// </summary>
public sealed class HandTeleporterSystem : EntitySystem
{
2023-02-16 18:27:43 -06:00
[Dependency] private readonly IAdminLogManager _adminLogger = default ! ;
2023-01-02 19:58:25 -06:00
[Dependency] private readonly LinkedEntitySystem _link = default ! ;
[Dependency] private readonly AudioSystem _audio = default ! ;
2023-04-03 13:13:48 +12:00
[Dependency] private readonly SharedDoAfterSystem _doafter = default ! ;
2023-01-02 19:58:25 -06:00
/// <inheritdoc/>
public override void Initialize ( )
{
SubscribeLocalEvent < HandTeleporterComponent , UseInHandEvent > ( OnUseInHand ) ;
2023-04-03 13:13:48 +12:00
SubscribeLocalEvent < HandTeleporterComponent , TeleporterDoAfterEvent > ( OnDoAfter ) ;
2023-01-03 01:53:16 -06:00
}
2023-02-24 19:01:25 -05:00
private void OnDoAfter ( EntityUid uid , HandTeleporterComponent component , DoAfterEvent args )
2023-01-03 01:53:16 -06:00
{
2023-02-24 19:01:25 -05:00
if ( args . Cancelled | | args . Handled )
return ;
2023-01-03 01:53:16 -06:00
2023-02-24 19:01:25 -05:00
HandlePortalUpdating ( uid , component , args . Args . User ) ;
args . Handled = true ;
2023-01-02 19:58:25 -06:00
}
private void OnUseInHand ( EntityUid uid , HandTeleporterComponent component , UseInHandEvent args )
{
if ( Deleted ( component . FirstPortal ) )
component . FirstPortal = null ;
if ( Deleted ( component . SecondPortal ) )
component . SecondPortal = null ;
2023-01-03 01:53:16 -06:00
if ( component . FirstPortal ! = null & & component . SecondPortal ! = null )
{
// handle removing portals immediately as opposed to a doafter
HandlePortalUpdating ( uid , component , args . User ) ;
}
else
{
var xform = Transform ( args . User ) ;
if ( xform . ParentUid ! = xform . GridUid )
return ;
2023-04-03 13:13:48 +12:00
var doafterArgs = new DoAfterArgs ( args . User , component . PortalCreationDelay , new TeleporterDoAfterEvent ( ) , uid , used : uid )
2023-01-03 01:53:16 -06:00
{
BreakOnDamage = true ,
BreakOnUserMove = true ,
MovementThreshold = 0.5f ,
} ;
2023-04-03 13:13:48 +12:00
_doafter . TryStartDoAfter ( doafterArgs ) ;
2023-01-03 01:53:16 -06:00
}
}
/// <summary>
/// Creates or removes a portal given the state of the hand teleporter.
/// </summary>
private void HandlePortalUpdating ( EntityUid uid , HandTeleporterComponent component , EntityUid user )
{
if ( Deleted ( user ) )
return ;
var xform = Transform ( user ) ;
2023-01-02 19:58:25 -06:00
// Create the first portal.
2023-07-24 16:21:44 -04:00
if ( Deleted ( component . FirstPortal ) & & Deleted ( component . SecondPortal ) )
2023-01-02 19:58:25 -06:00
{
2023-01-03 01:53:16 -06:00
// don't portal
if ( xform . ParentUid ! = xform . GridUid )
return ;
var timeout = EnsureComp < PortalTimeoutComponent > ( user ) ;
2023-01-02 19:58:25 -06:00
timeout . EnteredPortal = null ;
2023-01-03 01:53:16 -06:00
component . FirstPortal = Spawn ( component . FirstPortalPrototype , Transform ( user ) . Coordinates ) ;
2023-02-16 18:27:43 -06:00
_adminLogger . Add ( LogType . EntitySpawn , LogImpact . Low , $"{ToPrettyString(user):player} opened {ToPrettyString(component.FirstPortal.Value)} at {Transform(component.FirstPortal.Value).Coordinates} using {ToPrettyString(uid)}" ) ;
2023-01-02 19:58:25 -06:00
_audio . PlayPvs ( component . NewPortalSound , uid ) ;
}
2023-07-24 16:21:44 -04:00
else if ( Deleted ( component . SecondPortal ) )
2023-01-02 19:58:25 -06:00
{
2023-01-03 01:53:16 -06:00
var timeout = EnsureComp < PortalTimeoutComponent > ( user ) ;
2023-01-02 19:58:25 -06:00
timeout . EnteredPortal = null ;
2023-01-03 01:53:16 -06:00
component . SecondPortal = Spawn ( component . SecondPortalPrototype , Transform ( user ) . Coordinates ) ;
2023-02-16 18:27:43 -06:00
_adminLogger . Add ( LogType . EntitySpawn , LogImpact . Low , $"{ToPrettyString(user):player} opened {ToPrettyString(component.SecondPortal.Value)} at {Transform(component.SecondPortal.Value).Coordinates} linked to {ToPrettyString(component.FirstPortal!.Value)} using {ToPrettyString(uid)}" ) ;
2023-01-02 19:58:25 -06:00
_link . TryLink ( component . FirstPortal ! . Value , component . SecondPortal . Value , true ) ;
_audio . PlayPvs ( component . NewPortalSound , uid ) ;
}
else
{
2023-02-16 18:27:43 -06:00
// Logging
var portalStrings = "" ;
portalStrings + = ToPrettyString ( component . FirstPortal ! . Value ) ;
if ( portalStrings ! = "" )
portalStrings + = " and " ;
portalStrings + = ToPrettyString ( component . SecondPortal ! . Value ) ;
if ( portalStrings ! = "" )
_adminLogger . Add ( LogType . EntityDelete , LogImpact . Low , $"{ToPrettyString(user):player} closed {portalStrings} with {ToPrettyString(uid)}" ) ;
2023-01-02 19:58:25 -06:00
// Clear both portals
QueueDel ( component . FirstPortal ! . Value ) ;
QueueDel ( component . SecondPortal ! . Value ) ;
component . FirstPortal = null ;
component . SecondPortal = null ;
_audio . PlayPvs ( component . ClearPortalsSound , uid ) ;
}
}
}