2020-09-29 16:05:29 +02:00
using System.Linq ;
2019-10-02 10:45:06 +02:00
using Content.Server.GameTicking ;
2020-09-29 16:05:29 +02:00
using Content.Shared.Access ;
2021-12-16 23:42:02 +13:00
using Content.Shared.Access.Components ;
2021-12-26 17:07:28 +13:00
using Content.Shared.Access.Systems ;
2023-04-27 06:10:06 +06:00
using Content.Shared.Administration.Logs ;
2021-12-05 18:09:01 +01:00
using Content.Shared.Containers.ItemSlots ;
2023-04-27 06:10:06 +06:00
using Content.Shared.Database ;
2023-04-07 11:21:12 -07:00
using Content.Shared.Hands.Components ;
2022-03-17 20:13:31 +13:00
using Content.Shared.Hands.EntitySystems ;
2021-12-30 22:56:10 +01:00
using Content.Shared.Inventory ;
2021-12-16 23:42:02 +13:00
using Content.Shared.PDA ;
2019-10-02 10:45:06 +02:00
using Content.Shared.Sandbox ;
2020-02-08 20:45:02 +01:00
using Robust.Server.Console ;
2021-02-11 01:13:03 -08:00
using Robust.Server.Placement ;
2019-10-02 10:45:06 +02:00
using Robust.Server.Player ;
using Robust.Shared.Enums ;
2023-10-28 09:59:53 +11:00
using Robust.Shared.Player ;
2024-04-01 09:06:13 +03:00
using Robust.Shared.Prototypes ;
2019-10-02 10:45:06 +02:00
namespace Content.Server.Sandbox
{
2022-02-24 11:00:30 +11:00
public sealed class SandboxSystem : SharedSandboxSystem
2019-10-02 10:45:06 +02:00
{
2020-08-24 14:10:28 +02:00
[Dependency] private readonly IPlayerManager _playerManager = default ! ;
[Dependency] private readonly IPlacementManager _placementManager = default ! ;
[Dependency] private readonly IConGroupController _conGroupController = default ! ;
2021-02-01 16:49:43 -08:00
[Dependency] private readonly IServerConsoleHost _host = default ! ;
2022-09-14 19:33:25 +10:00
[Dependency] private readonly SharedAccessSystem _access = default ! ;
2022-02-24 11:00:30 +11:00
[Dependency] private readonly InventorySystem _inventory = default ! ;
[Dependency] private readonly ItemSlotsSystem _slots = default ! ;
[Dependency] private readonly GameTicker _ticker = default ! ;
2022-03-17 20:13:31 +13:00
[Dependency] private readonly SharedHandsSystem _handsSystem = default ! ;
2019-10-02 10:45:06 +02:00
2023-04-27 06:10:06 +06:00
//WD-EDIT
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default ! ;
//WD-EDIT
2019-10-02 10:45:06 +02:00
private bool _isSandboxEnabled ;
2020-02-08 21:23:37 +01:00
[ViewVariables(VVAccess.ReadWrite)]
2019-10-02 10:45:06 +02:00
public bool IsSandboxEnabled
{
get = > _isSandboxEnabled ;
set
{
_isSandboxEnabled = value ;
UpdateSandboxStatusForAll ( ) ;
}
}
2022-02-24 11:00:30 +11:00
public override void Initialize ( )
2019-10-02 10:45:06 +02:00
{
2022-02-24 11:00:30 +11:00
base . Initialize ( ) ;
SubscribeNetworkEvent < MsgSandboxRespawn > ( SandboxRespawnReceived ) ;
SubscribeNetworkEvent < MsgSandboxGiveAccess > ( SandboxGiveAccessReceived ) ;
SubscribeNetworkEvent < MsgSandboxGiveAghost > ( SandboxGiveAghostReceived ) ;
SubscribeNetworkEvent < MsgSandboxSuicide > ( SandboxSuicideReceived ) ;
SubscribeLocalEvent < GameRunLevelChangedEvent > ( GameTickerOnOnRunLevelChanged ) ;
2019-10-02 10:45:06 +02:00
_playerManager . PlayerStatusChanged + = OnPlayerStatusChanged ;
2020-02-08 20:45:02 +01:00
_placementManager . AllowPlacementFunc = placement = >
{
2023-04-27 06:10:06 +06:00
//WD-EDIT
//Logger.Info($"{placement.MsgChannel.UserName} spawned {placement.EntityTemplateName} on position {placement.EntityCoordinates}");
var data = _playerManager . GetSessionByUserId ( placement . MsgChannel . UserId ) ;
var playerUid = data . AttachedEntity . GetValueOrDefault ( ) ;
2023-04-27 08:03:44 +06:00
var coordinates = placement . NetCoordinates ;
2023-04-27 06:10:06 +06:00
switch ( placement . PlaceType )
{
case PlacementManagerMessage . StartPlacement :
break ;
case PlacementManagerMessage . CancelPlacement :
break ;
case PlacementManagerMessage . RequestPlacement :
_adminLogger . Add ( LogType . EntitySpawn , LogImpact . High , $"{placement.EntityTemplateName} was spawned by" +
$" {ToPrettyString(playerUid):player} at " +
2023-04-27 08:03:44 +06:00
$"{ToPrettyString(coordinates.NetEntity):entity} X={coordinates.X}, Y={coordinates.Y}" ) ;
2023-04-27 06:10:06 +06:00
break ;
case PlacementManagerMessage . RequestEntRemove :
_adminLogger . Add ( LogType . EntitySpawn , LogImpact . High , $"{ToPrettyString(placement.EntityUid):entity} was deleted by {ToPrettyString(playerUid):player}" ) ;
break ;
case PlacementManagerMessage . RequestRectRemove :
break ;
}
_adminLogger . Add ( LogType . EntitySpawn , $"{ToPrettyString(placement.EntityUid):entity} spawned" ) ;
//WD-EDIT
2020-02-08 20:45:02 +01:00
if ( IsSandboxEnabled )
{
return true ;
}
var channel = placement . MsgChannel ;
var player = _playerManager . GetSessionByChannel ( channel ) ;
if ( _conGroupController . CanAdminPlace ( player ) )
{
return true ;
}
return false ;
} ;
2019-10-02 10:45:06 +02:00
}
2022-02-24 11:00:30 +11:00
public override void Shutdown ( )
{
base . Shutdown ( ) ;
_placementManager . AllowPlacementFunc = null ;
_playerManager . PlayerStatusChanged - = OnPlayerStatusChanged ;
}
2021-06-20 10:09:24 +02:00
private void GameTickerOnOnRunLevelChanged ( GameRunLevelChangedEvent obj )
2019-10-02 10:45:06 +02:00
{
// Automatically clear sandbox state when round resets.
2021-06-20 10:09:24 +02:00
if ( obj . New = = GameRunLevel . PreRoundLobby )
2019-10-02 10:45:06 +02:00
{
IsSandboxEnabled = false ;
}
}
2021-03-16 15:50:20 +01:00
private void OnPlayerStatusChanged ( object? sender , SessionStatusEventArgs e )
2019-10-02 10:45:06 +02:00
{
if ( e . NewStatus ! = SessionStatus . Connected | | e . OldStatus ! = SessionStatus . Connecting )
return ;
2024-01-22 23:14:13 +01:00
RaiseNetworkEvent ( new MsgSandboxStatus { SandboxAllowed = IsSandboxEnabled } , e . Session . Channel ) ;
2019-10-02 10:45:06 +02:00
}
2022-02-24 11:00:30 +11:00
private void SandboxRespawnReceived ( MsgSandboxRespawn message , EntitySessionEventArgs args )
2019-10-02 10:45:06 +02:00
{
if ( ! IsSandboxEnabled )
return ;
2024-01-22 23:14:13 +01:00
var player = _playerManager . GetSessionByChannel ( args . SenderSession . Channel ) ;
2022-02-24 11:00:30 +11:00
if ( player . AttachedEntity = = null ) return ;
_ticker . Respawn ( player ) ;
2019-10-02 10:45:06 +02:00
}
2022-02-24 11:00:30 +11:00
private void SandboxGiveAccessReceived ( MsgSandboxGiveAccess message , EntitySessionEventArgs args )
2020-07-17 03:38:58 -05:00
{
2020-09-29 16:05:29 +02:00
if ( ! IsSandboxEnabled )
2020-07-17 03:38:58 -05:00
return ;
2024-01-22 23:14:13 +01:00
var player = _playerManager . GetSessionByChannel ( args . SenderSession . Channel ) ;
2023-07-22 21:19:51 -07:00
if ( player . AttachedEntity is not { } attached )
2020-09-29 16:05:29 +02:00
{
return ;
}
2022-02-24 11:00:30 +11:00
var allAccess = PrototypeManager
2020-09-29 16:05:29 +02:00
. EnumeratePrototypes < AccessLevelPrototype > ( )
2024-04-01 09:06:13 +03:00
. Select ( p = > new ProtoId < AccessLevelPrototype > ( p . ID ) ) . ToList ( ) ;
2020-09-29 16:05:29 +02:00
2022-02-24 11:00:30 +11:00
if ( _inventory . TryGetSlotEntity ( attached , "id" , out var slotEntity ) )
2020-09-29 16:05:29 +02:00
{
2022-02-24 11:00:30 +11:00
if ( HasComp < AccessComponent > ( slotEntity ) )
2020-09-29 16:05:29 +02:00
{
2021-12-30 22:56:10 +01:00
UpgradeId ( slotEntity . Value ) ;
2020-09-29 16:05:29 +02:00
}
2023-06-15 03:44:28 +02:00
else if ( TryComp < PdaComponent > ( slotEntity , out var pda ) )
2020-09-29 16:05:29 +02:00
{
2023-07-22 21:19:51 -07:00
if ( pda . ContainedId is null )
2020-09-29 16:05:29 +02:00
{
2021-10-03 07:05:52 +03:00
var newID = CreateFreshId ( ) ;
2023-07-22 21:19:51 -07:00
if ( TryComp < ItemSlotsComponent > ( slotEntity , out var itemSlots ) )
2021-10-03 07:05:52 +03:00
{
2022-02-24 11:00:30 +11:00
_slots . TryInsert ( slotEntity . Value , pda . IdSlot , newID , null ) ;
2021-10-03 07:05:52 +03:00
}
2020-09-29 16:05:29 +02:00
}
else
{
2023-07-22 21:19:51 -07:00
UpgradeId ( pda . ContainedId ! . Value ) ;
2020-09-29 16:05:29 +02:00
}
}
}
2022-02-24 11:00:30 +11:00
else if ( TryComp < HandsComponent > ( attached , out var hands ) )
2020-07-17 03:38:58 -05:00
{
2020-09-29 16:05:29 +02:00
var card = CreateFreshId ( ) ;
2022-02-24 11:00:30 +11:00
if ( ! _inventory . TryEquip ( attached , card , "id" , true , true ) )
2020-09-29 16:05:29 +02:00
{
2022-03-17 20:13:31 +13:00
_handsSystem . PickupOrDrop ( attached , card , handsComp : hands ) ;
2020-09-29 16:05:29 +02:00
}
}
2021-12-05 10:56:17 -08:00
void UpgradeId ( EntityUid id )
2020-09-29 16:05:29 +02:00
{
2022-02-24 11:00:30 +11:00
_access . TrySetTags ( id , allAccess ) ;
2020-09-29 16:05:29 +02:00
}
2021-12-06 00:52:58 +01:00
EntityUid CreateFreshId ( )
2020-09-29 16:05:29 +02:00
{
2022-02-24 11:00:30 +11:00
var card = Spawn ( "CaptainIDCard" , Transform ( attached ) . Coordinates ) ;
2020-09-29 16:05:29 +02:00
UpgradeId ( card ) ;
2022-02-24 11:00:30 +11:00
Comp < IdCardComponent > ( card ) . FullName = MetaData ( attached ) . EntityName ;
2020-09-29 16:05:29 +02:00
return card ;
2020-07-17 03:38:58 -05:00
}
}
2022-02-24 11:00:30 +11:00
private void SandboxGiveAghostReceived ( MsgSandboxGiveAghost message , EntitySessionEventArgs args )
2020-08-14 09:09:58 -07:00
{
if ( ! IsSandboxEnabled )
return ;
2024-01-22 23:14:13 +01:00
var player = _playerManager . GetSessionByChannel ( args . SenderSession . Channel ) ;
2020-08-14 21:55:39 +02:00
2021-02-01 16:49:43 -08:00
_host . ExecuteCommand ( player , _conGroupController . CanCommand ( player , "aghost" ) ? "aghost" : "ghost" ) ;
2020-08-14 09:09:58 -07:00
}
2022-02-24 11:00:30 +11:00
private void SandboxSuicideReceived ( MsgSandboxSuicide message , EntitySessionEventArgs args )
2020-08-14 09:09:58 -07:00
{
if ( ! IsSandboxEnabled )
return ;
2024-01-22 23:14:13 +01:00
var player = _playerManager . GetSessionByChannel ( args . SenderSession . Channel ) ;
2021-02-01 16:49:43 -08:00
_host . ExecuteCommand ( player , "suicide" ) ;
2020-08-14 09:09:58 -07:00
}
2019-10-02 10:45:06 +02:00
private void UpdateSandboxStatusForAll ( )
{
2023-07-22 21:19:51 -07:00
RaiseNetworkEvent ( new MsgSandboxStatus { SandboxAllowed = IsSandboxEnabled } ) ;
2019-10-02 10:45:06 +02:00
}
}
}