mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 10:21:18 +03:00
Predict CardboardBoxSystem (#43994)
* CardboardBox-System-Predict * review * SubscribeLocalEvent * Storage * Apply suggestions from code review Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --------- Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
This commit is contained in:
parent
0446d900d6
commit
68ec73bea6
10 changed files with 225 additions and 217 deletions
|
|
@ -11,10 +11,11 @@ namespace Content.Client.CardboardBox;
|
|||
public sealed partial class CardboardBoxSystem : SharedCardboardBoxSystem
|
||||
{
|
||||
[Dependency] private EntityLookupSystem _entityLookup = default!;
|
||||
[Dependency] private TransformSystem _transform = default!;
|
||||
[Dependency] private ExamineSystemShared _examine = default!;
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
[Dependency] private EntityQuery<MobStateComponent> _mobStateQuery = default!;
|
||||
[Dependency] private TransformSystem _transform = default!;
|
||||
|
||||
[Dependency] private EntityQuery<MobStateComponent> _mobStateQuery;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
|
|
@ -33,13 +34,13 @@ public sealed partial class CardboardBoxSystem : SharedCardboardBoxSystem
|
|||
var xform = Transform(source);
|
||||
var sourcePos = _transform.GetMapCoordinates(source, xform);
|
||||
|
||||
//Any mob that can move should be surprised?
|
||||
//God mind rework needs to come faster so it can just check for mind
|
||||
//TODO: Replace with Mind Query when mind rework is in.
|
||||
// Any mob that can move should be surprised?
|
||||
// God mind rework needs to come faster so it can just check for mind
|
||||
// TODO: Replace with Mind Query when mind rework is in.
|
||||
var mobMoverEntities = new List<EntityUid>();
|
||||
var mover = GetEntity(msg.Mover);
|
||||
|
||||
//Filter out entities in range to see that they're a mob and add them to the mobMoverEntities hash for faster lookup
|
||||
// Filter out entities in range to see that they're a mob and add them to the mobMoverEntities hash for faster lookup
|
||||
var movers = new HashSet<Entity<MobMoverComponent>>();
|
||||
_entityLookup.GetEntitiesInRange(xform.Coordinates, box.Distance, movers);
|
||||
|
||||
|
|
@ -52,7 +53,7 @@ public sealed partial class CardboardBoxSystem : SharedCardboardBoxSystem
|
|||
mobMoverEntities.Add(uid);
|
||||
}
|
||||
|
||||
//Play the effect for the mobs as long as they can see the box and are in range.
|
||||
// Play the effect for the mobs as long as they can see the box and are in range.
|
||||
foreach (var mob in mobMoverEntities)
|
||||
{
|
||||
var mapPos = _transform.GetMapCoordinates(mob);
|
||||
|
|
@ -64,13 +65,11 @@ public sealed partial class CardboardBoxSystem : SharedCardboardBoxSystem
|
|||
continue;
|
||||
|
||||
var ent = Spawn(box.Effect, mapPos);
|
||||
|
||||
if (!TryComp(ent, out TransformComponent? entTransform) || !TryComp<SpriteComponent>(ent, out var sprite))
|
||||
continue;
|
||||
|
||||
_sprite.SetOffset((ent, sprite), new Vector2(0, 1));
|
||||
_transform.SetParent(ent, entTransform, mob);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,138 +1,5 @@
|
|||
using Content.Server.Storage.EntitySystems;
|
||||
using Content.Shared.Access.Components;
|
||||
using Content.Shared.CardboardBox;
|
||||
using Content.Shared.CardboardBox.Components;
|
||||
using Content.Shared.Damage.Systems;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Movement.Components;
|
||||
using Content.Shared.Movement.Systems;
|
||||
using Content.Shared.Stealth;
|
||||
using Content.Shared.Stealth.Components;
|
||||
using Content.Shared.Storage.Components;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.CardboardBox;
|
||||
|
||||
public sealed partial class CardboardBoxSystem : SharedCardboardBoxSystem
|
||||
{
|
||||
[Dependency] private SharedAudioSystem _audio = default!;
|
||||
[Dependency] private SharedMoverController _mover = default!;
|
||||
[Dependency] private IGameTiming _timing = default!;
|
||||
[Dependency] private SharedStealthSystem _stealth = default!;
|
||||
[Dependency] private DamageableSystem _damageable = default!;
|
||||
[Dependency] private EntityStorageSystem _storage = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<CardboardBoxComponent, StorageAfterOpenEvent>(AfterStorageOpen);
|
||||
SubscribeLocalEvent<CardboardBoxComponent, StorageBeforeOpenEvent>(BeforeStorageOpen);
|
||||
SubscribeLocalEvent<CardboardBoxComponent, StorageAfterCloseEvent>(AfterStorageClosed);
|
||||
SubscribeLocalEvent<CardboardBoxComponent, GetAdditionalAccessEvent>(OnGetAdditionalAccess);
|
||||
SubscribeLocalEvent<CardboardBoxComponent, ActivateInWorldEvent>(OnInteracted);
|
||||
SubscribeLocalEvent<CardboardBoxComponent, EntInsertedIntoContainerMessage>(OnEntInserted);
|
||||
SubscribeLocalEvent<CardboardBoxComponent, EntRemovedFromContainerMessage>(OnEntRemoved);
|
||||
|
||||
SubscribeLocalEvent<CardboardBoxComponent, DamageChangedEvent>(OnDamage);
|
||||
}
|
||||
|
||||
private void OnInteracted(EntityUid uid, CardboardBoxComponent component, ActivateInWorldEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
if (!TryComp<EntityStorageComponent>(uid, out var box))
|
||||
return;
|
||||
|
||||
if (!args.Complex)
|
||||
{
|
||||
if (box.Open || !box.Contents.Contains(args.User))
|
||||
return;
|
||||
}
|
||||
|
||||
args.Handled = true;
|
||||
_storage.ToggleOpen(args.User, uid, box);
|
||||
|
||||
if (box.Contents.Contains(args.User) && !box.Open)
|
||||
{
|
||||
_mover.SetRelay(args.User, uid);
|
||||
component.Mover = args.User;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGetAdditionalAccess(EntityUid uid, CardboardBoxComponent component, ref GetAdditionalAccessEvent args)
|
||||
{
|
||||
if (component.Mover == null)
|
||||
return;
|
||||
args.Entities.Add(component.Mover.Value);
|
||||
}
|
||||
|
||||
private void BeforeStorageOpen(EntityUid uid, CardboardBoxComponent component, ref StorageBeforeOpenEvent args)
|
||||
{
|
||||
if (component.Quiet)
|
||||
return;
|
||||
|
||||
//Play effect & sound
|
||||
if (component.Mover != null)
|
||||
{
|
||||
if (_timing.CurTime > component.EffectCooldown)
|
||||
{
|
||||
RaiseNetworkEvent(new PlayBoxEffectMessage(GetNetEntity(uid), GetNetEntity(component.Mover.Value)));
|
||||
_audio.PlayPvs(component.EffectSound, uid);
|
||||
component.EffectCooldown = _timing.CurTime + component.CooldownDuration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AfterStorageOpen(EntityUid uid, CardboardBoxComponent component, ref StorageAfterOpenEvent args)
|
||||
{
|
||||
// If this box has a stealth/chameleon effect, disable the stealth effect while the box is open.
|
||||
_stealth.SetEnabled(uid, false);
|
||||
}
|
||||
|
||||
private void AfterStorageClosed(EntityUid uid, CardboardBoxComponent component, ref StorageAfterCloseEvent args)
|
||||
{
|
||||
// If this box has a stealth/chameleon effect, enable the stealth effect.
|
||||
if (TryComp(uid, out StealthComponent? stealth))
|
||||
{
|
||||
_stealth.SetVisibility(uid, stealth.MaxVisibility, stealth);
|
||||
_stealth.SetEnabled(uid, true, stealth);
|
||||
}
|
||||
}
|
||||
|
||||
//Relay damage to the mover
|
||||
private void OnDamage(EntityUid uid, CardboardBoxComponent component, DamageChangedEvent args)
|
||||
{
|
||||
if (args.DamageDelta == null || !args.DamageIncreased || component.Mover is not { } mover)
|
||||
return;
|
||||
|
||||
_damageable.ChangeDamage(mover, args.DamageDelta, origin: args.Origin);
|
||||
}
|
||||
|
||||
private void OnEntInserted(EntityUid uid, CardboardBoxComponent component, EntInsertedIntoContainerMessage args)
|
||||
{
|
||||
if (!TryComp(args.Entity, out MobMoverComponent? mover))
|
||||
return;
|
||||
|
||||
if (component.Mover == null)
|
||||
{
|
||||
_mover.SetRelay(args.Entity, uid);
|
||||
component.Mover = args.Entity;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Through e.g. teleporting, it's possible for the mover to exit the box without opening it.
|
||||
/// Handle those situations but don't play the sound.
|
||||
/// </summary>
|
||||
private void OnEntRemoved(EntityUid uid, CardboardBoxComponent component, EntRemovedFromContainerMessage args)
|
||||
{
|
||||
if (args.Entity != component.Mover)
|
||||
return;
|
||||
|
||||
RemComp<RelayInputMoverComponent>(component.Mover.Value);
|
||||
component.Mover = null;
|
||||
}
|
||||
}
|
||||
public sealed partial class CardboardBoxSystem : SharedCardboardBoxSystem;
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ public sealed partial class RevenantSystem
|
|||
[Dependency] private SharedMapSystem _mapSystem = default!;
|
||||
|
||||
[Dependency] private EntityQuery<TagComponent> _tagQuery = default!;
|
||||
[Dependency] private EntityQuery<EntityStorageComponent> _entityStorageQuery = default!;
|
||||
[Dependency] private EntityQuery<ItemComponent> _itemQuery = default!;
|
||||
[Dependency] private EntityQuery<PoweredLightComponent> _poweredLightQuery = default!;
|
||||
[Dependency] private EntityQuery<MobStateComponent> _mobStateQuery = default!;
|
||||
|
|
@ -281,8 +280,7 @@ public sealed partial class RevenantSystem
|
|||
continue;
|
||||
|
||||
//randomly opens some lockers and such.
|
||||
if (_entityStorageQuery.TryGetComponent(ent, out var entstorecomp))
|
||||
_entityStorage.OpenStorage(ent, entstorecomp);
|
||||
_entityStorage.OpenStorage(ent, args.Performer);
|
||||
|
||||
//chucks shit
|
||||
if (_itemQuery.HasComponent(ent) &&
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ public sealed partial class BluespaceLockerSystem : EntitySystem
|
|||
|
||||
// Close target if it is open
|
||||
if (target.Value.storageComponent.Open)
|
||||
_entityStorage.CloseStorage(target.Value.uid, target.Value.storageComponent);
|
||||
_entityStorage.CloseStorage((target.Value.uid, target.Value.storageComponent));
|
||||
|
||||
// Apply bluespace effects if target is not a bluespace locker, otherwise let it handle it
|
||||
if (target.Value.bluespaceLockerComponent == null)
|
||||
|
|
@ -352,7 +352,7 @@ public sealed partial class BluespaceLockerSystem : EntitySystem
|
|||
if (Resolve(target.Value.uid, ref lockComponent, false) && lockComponent.Locked)
|
||||
_lockSystem.Unlock(target.Value.uid, target.Value.uid, lockComponent);
|
||||
|
||||
_entityStorage.OpenStorage(target.Value.uid, target.Value.storageComponent);
|
||||
_entityStorage.OpenStorage((target.Value.uid, target.Value.storageComponent));
|
||||
}
|
||||
|
||||
// Bluespace effects
|
||||
|
|
|
|||
|
|
@ -1,72 +1,67 @@
|
|||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Shared.CardboardBox.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Allows a user to control an EntityStorage entity while inside of it.
|
||||
/// Used for big cardboard box entities.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
|
||||
public sealed partial class CardboardBoxComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The person in control of this box
|
||||
/// </summary>
|
||||
[DataField("mover")]
|
||||
[DataField, AutoNetworkedField]
|
||||
public EntityUid? Mover;
|
||||
|
||||
/// <summary>
|
||||
/// The entity used for the box opening effect
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("effect")]
|
||||
public string Effect = "Exclamation";
|
||||
[DataField]
|
||||
public EntProtoId Effect = "Exclamation";
|
||||
|
||||
/// <summary>
|
||||
/// Sound played upon effect creation
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("effectSound")]
|
||||
[DataField]
|
||||
public SoundSpecifier? EffectSound;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to prevent the box from making the sound and effect
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("quiet")]
|
||||
public bool Quiet = false;
|
||||
[DataField]
|
||||
public bool Quiet;
|
||||
|
||||
/// <summary>
|
||||
/// How far should the box opening effect go?
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("distance")]
|
||||
[DataField]
|
||||
public float Distance = 6f;
|
||||
|
||||
/// <summary>
|
||||
/// Time at which the sound effect can next be played.
|
||||
/// </summary>
|
||||
[DataField("effectCooldown", customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField, AutoPausedField]
|
||||
public TimeSpan EffectCooldown;
|
||||
|
||||
/// <summary>
|
||||
/// Time between sound effects. Prevents effect spam
|
||||
/// </summary>
|
||||
[DataField("cooldownDuration")]
|
||||
[DataField]
|
||||
public TimeSpan CooldownDuration = TimeSpan.FromSeconds(5f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Message to play the box effect.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class PlayBoxEffectMessage : EntityEventArgs
|
||||
public sealed class PlayBoxEffectMessage(NetEntity source, NetEntity mover) : EntityEventArgs
|
||||
{
|
||||
public NetEntity Source;
|
||||
public NetEntity Mover;
|
||||
|
||||
public PlayBoxEffectMessage(NetEntity source, NetEntity mover)
|
||||
{
|
||||
Source = source;
|
||||
Mover = mover;
|
||||
}
|
||||
public NetEntity Source = source;
|
||||
public NetEntity Mover = mover;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,156 @@
|
|||
namespace Content.Shared.CardboardBox;
|
||||
using System.Numerics;
|
||||
using Content.Shared.Access.Components;
|
||||
using Content.Shared.CardboardBox.Components;
|
||||
using Content.Shared.Damage.Systems;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Movement.Components;
|
||||
using Content.Shared.Movement.Systems;
|
||||
using Content.Shared.Stealth;
|
||||
using Content.Shared.Stealth.Components;
|
||||
using Content.Shared.Storage.Components;
|
||||
using Content.Shared.Storage.EntitySystems;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
public abstract class SharedCardboardBoxSystem : EntitySystem
|
||||
namespace Content.Shared.CardboardBox;
|
||||
|
||||
public abstract partial class SharedCardboardBoxSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private IGameTiming _timing = default!;
|
||||
[Dependency] private INetManager _net = default!;
|
||||
[Dependency] private DamageableSystem _damageable = default!;
|
||||
[Dependency] private SharedAudioSystem _audio = default!;
|
||||
[Dependency] private SharedEntityStorageSystem _storage = default!;
|
||||
[Dependency] private SharedMoverController _mover = default!;
|
||||
[Dependency] private SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] private SharedStealthSystem _stealth = default!;
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnInteracted(Entity<CardboardBoxComponent> ent, ref ActivateInWorldEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
if (!TryComp<EntityStorageComponent>(ent, out var box))
|
||||
return;
|
||||
|
||||
if (!args.Complex)
|
||||
{
|
||||
if (box.Open || !box.Contents.Contains(args.User))
|
||||
return;
|
||||
}
|
||||
|
||||
args.Handled = true;
|
||||
_storage.ToggleOpen(args.User, ent, box);
|
||||
|
||||
if (!box.Contents.Contains(args.User) || box.Open)
|
||||
return;
|
||||
|
||||
_mover.SetRelay(args.User, ent);
|
||||
ent.Comp.Mover = args.User;
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnGetAdditionalAccess(Entity<CardboardBoxComponent> ent, ref GetAdditionalAccessEvent args)
|
||||
{
|
||||
if (ent.Comp.Mover == null)
|
||||
return;
|
||||
|
||||
args.Entities.Add(ent.Comp.Mover.Value);
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void BeforeStorageOpen(Entity<CardboardBoxComponent> ent, ref StorageBeforeOpenEvent args)
|
||||
{
|
||||
if (ent.Comp.Quiet)
|
||||
return;
|
||||
|
||||
// Play effect & sound.
|
||||
if (ent.Comp.Mover == null)
|
||||
return;
|
||||
|
||||
if (_timing.CurTime <= ent.Comp.EffectCooldown)
|
||||
return;
|
||||
|
||||
if (_net.IsServer)
|
||||
RaiseNetworkEvent(new PlayBoxEffectMessage(GetNetEntity(ent), GetNetEntity(ent.Comp.Mover.Value)));
|
||||
|
||||
_audio.PlayPredicted(ent.Comp.EffectSound, ent, args.User);
|
||||
ent.Comp.EffectCooldown = _timing.CurTime + ent.Comp.CooldownDuration;
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void AfterStorageOpen(Entity<CardboardBoxComponent> ent, ref StorageAfterOpenEvent args)
|
||||
{
|
||||
// If this box has a stealth/chameleon effect, disable the stealth effect while the box is open.
|
||||
if (!TryComp<StealthComponent>(ent, out var stealth))
|
||||
return;
|
||||
|
||||
_stealth.SetEnabled(ent, false, stealth);
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void AfterStorageClosed(Entity<CardboardBoxComponent> ent, ref StorageAfterCloseEvent args)
|
||||
{
|
||||
// If this box has a stealth/chameleon effect, enable the stealth effect.
|
||||
if (!TryComp<StealthComponent>(ent, out var stealth))
|
||||
return;
|
||||
|
||||
_stealth.SetVisibility(ent, stealth.MaxVisibility, stealth);
|
||||
_stealth.SetEnabled(ent, true, stealth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Relay damage to the mover.
|
||||
/// </summary>
|
||||
[SubscribeLocalEvent]
|
||||
private void OnDamage(Entity<CardboardBoxComponent> ent, ref DamageDealtEvent args)
|
||||
{
|
||||
if (ent.Comp.Mover is not { } mover)
|
||||
return;
|
||||
|
||||
_damageable.ChangeDamage(mover, args.Damage, origin: args.Origin);
|
||||
}
|
||||
|
||||
[SubscribeLocalEvent]
|
||||
private void OnEntInserted(Entity<CardboardBoxComponent> ent, ref EntInsertedIntoContainerMessage args)
|
||||
{
|
||||
if (_timing.ApplyingState)
|
||||
return;
|
||||
|
||||
if (!HasComp<MobMoverComponent>(args.Entity))
|
||||
return;
|
||||
|
||||
if (ent.Comp.Mover != null)
|
||||
return;
|
||||
|
||||
_mover.SetRelay(args.Entity, ent);
|
||||
ent.Comp.Mover = args.Entity;
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Through e.g. teleporting, it's possible for the mover to exit the box without opening it.
|
||||
/// Handle those situations but don't play the sound.
|
||||
/// </summary>
|
||||
[SubscribeLocalEvent]
|
||||
private void OnEntRemoved(Entity<CardboardBoxComponent> ent, ref EntRemovedFromContainerMessage args)
|
||||
{
|
||||
if (_timing.ApplyingState)
|
||||
return;
|
||||
|
||||
if (args.Entity != ent.Comp.Mover)
|
||||
return;
|
||||
|
||||
// Stops movement after exit.
|
||||
_physics.SetLinearVelocity(ent, Vector2.Zero);
|
||||
RemComp<RelayInputMoverComponent>(ent.Comp.Mover.Value);
|
||||
ent.Comp.Mover = null;
|
||||
Dirty(ent);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ public abstract partial class SharedCrematoriumSystem : EntitySystem
|
|||
PredictedTrySpawnInContainer(ent.Comp1.LeftOverProtoId, ent.Owner, ent.Comp2.Contents.ID, out _);
|
||||
}
|
||||
|
||||
EntityStorage.OpenStorage(ent.Owner, ent.Comp2);
|
||||
EntityStorage.OpenStorage((ent.Owner, ent.Comp2));
|
||||
|
||||
if (_net.IsServer) // can't predict without the user
|
||||
_audio.PlayPvs(ent.Comp1.CremateFinishSound, ent.Owner);
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public abstract partial class SharedGenpopSystem : EntitySystem
|
|||
ent.Comp.LinkedId = EntityUid.Invalid;
|
||||
|
||||
_lock.Lock(ent.Owner, args.Actor);
|
||||
_entityStorage.CloseStorage(ent);
|
||||
_entityStorage.CloseStorage(ent.Owner, args.Actor);
|
||||
|
||||
CreateId(ent, args.Name, args.Sentence, args.Crime);
|
||||
}
|
||||
|
|
@ -200,7 +200,7 @@ public abstract partial class SharedGenpopSystem : EntitySystem
|
|||
|
||||
ent.Comp.LinkedId = null;
|
||||
_lock.Unlock(ent.Owner, user);
|
||||
_entityStorage.OpenStorage(ent.Owner);
|
||||
_entityStorage.OpenStorage(ent.Owner, user);
|
||||
|
||||
if (TryComp<ExpireIdCardComponent>(ent.Comp.LinkedId, out var expire))
|
||||
IdCard.ExpireId((ent.Comp.LinkedId.Value, expire));
|
||||
|
|
|
|||
|
|
@ -184,16 +184,16 @@ public record struct EntityStorageIntoContainerAttemptEvent(BaseContainer Contai
|
|||
public record struct StorageOpenAttemptEvent(EntityUid User, bool Silent, bool Cancelled = false);
|
||||
|
||||
[ByRefEvent]
|
||||
public readonly record struct StorageBeforeOpenEvent;
|
||||
public readonly record struct StorageBeforeOpenEvent(EntityUid? User);
|
||||
|
||||
[ByRefEvent]
|
||||
public readonly record struct StorageAfterOpenEvent;
|
||||
public readonly record struct StorageAfterOpenEvent(EntityUid? User);
|
||||
|
||||
[ByRefEvent]
|
||||
public record struct StorageCloseAttemptEvent(EntityUid? User, bool Cancelled = false);
|
||||
|
||||
[ByRefEvent]
|
||||
public readonly record struct StorageBeforeCloseEvent(HashSet<EntityUid> Contents, HashSet<EntityUid> BypassChecks);
|
||||
public readonly record struct StorageBeforeCloseEvent(EntityUid? User, HashSet<EntityUid> Contents, HashSet<EntityUid> BypassChecks);
|
||||
|
||||
[ByRefEvent]
|
||||
public readonly record struct StorageAfterCloseEvent;
|
||||
public readonly record struct StorageAfterCloseEvent(EntityUid? User);
|
||||
|
|
|
|||
|
|
@ -225,77 +225,76 @@ public abstract partial class SharedEntityStorageSystem : EntitySystem
|
|||
}
|
||||
}
|
||||
|
||||
public void OpenStorage(EntityUid uid, EntityStorageComponent? component = null)
|
||||
public void OpenStorage(Entity<EntityStorageComponent?> target, EntityUid? user = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
if (!Resolve(target, ref target.Comp))
|
||||
return;
|
||||
|
||||
if (component.Open)
|
||||
if (target.Comp.Open)
|
||||
return;
|
||||
|
||||
var beforeev = new StorageBeforeOpenEvent();
|
||||
RaiseLocalEvent(uid, ref beforeev);
|
||||
component.Open = true;
|
||||
Dirty(uid, component);
|
||||
EmptyContents(uid, component);
|
||||
ModifyComponents(uid, component);
|
||||
if (_net.IsClient && _timing.IsFirstTimePredicted)
|
||||
_audio.PlayPvs(component.OpenSound, uid);
|
||||
ReleaseGas(uid, component);
|
||||
var afterev = new StorageAfterOpenEvent();
|
||||
RaiseLocalEvent(uid, ref afterev);
|
||||
var beforeev = new StorageBeforeOpenEvent(user);
|
||||
RaiseLocalEvent(target, ref beforeev);
|
||||
target.Comp.Open = true;
|
||||
Dirty(target);
|
||||
EmptyContents(target, target.Comp);
|
||||
ModifyComponents(target, target.Comp);
|
||||
_audio.PlayLocal(target.Comp.OpenSound, target, user);
|
||||
ReleaseGas(target, target.Comp);
|
||||
var afterev = new StorageAfterOpenEvent(user);
|
||||
RaiseLocalEvent(target, ref afterev);
|
||||
}
|
||||
|
||||
public void CloseStorage(EntityUid uid, EntityStorageComponent? component = null)
|
||||
public void CloseStorage(Entity<EntityStorageComponent?> target, EntityUid? user = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
if (!Resolve(target, ref target.Comp))
|
||||
return;
|
||||
|
||||
if (!component.Open)
|
||||
if (!target.Comp.Open)
|
||||
return;
|
||||
|
||||
// Prevent the container from closing if it is queued for deletion. This is so that the container-emptying
|
||||
// behaviour of DestructionEventArgs is respected. This exists because malicious players were using
|
||||
// destructible boxes to delete entities by having two players simultaneously destroy and close the box in
|
||||
// the same tick.
|
||||
if (EntityManager.IsQueuedForDeletion(uid))
|
||||
if (EntityManager.IsQueuedForDeletion(target))
|
||||
return;
|
||||
|
||||
component.Open = false;
|
||||
Dirty(uid, component);
|
||||
target.Comp.Open = false;
|
||||
Dirty(target);
|
||||
|
||||
var entities = _lookup.GetEntitiesInRange(
|
||||
new EntityCoordinates(uid, component.EnteringOffset),
|
||||
component.EnteringRange,
|
||||
new EntityCoordinates(target, target.Comp.EnteringOffset),
|
||||
target.Comp.EnteringRange,
|
||||
LookupFlags.Approximate | LookupFlags.Dynamic | LookupFlags.Sundries
|
||||
);
|
||||
|
||||
// Don't insert the container into itself.
|
||||
entities.Remove(uid);
|
||||
entities.Remove(target);
|
||||
|
||||
var ev = new StorageBeforeCloseEvent(entities, []);
|
||||
RaiseLocalEvent(uid, ref ev);
|
||||
var ev = new StorageBeforeCloseEvent(user, entities, []);
|
||||
RaiseLocalEvent(target, ref ev);
|
||||
|
||||
foreach (var entity in ev.Contents)
|
||||
{
|
||||
if (!ev.BypassChecks.Contains(entity) && !CanInsert(entity, uid, component))
|
||||
if (!ev.BypassChecks.Contains(entity) && !CanInsert(entity, target, target.Comp))
|
||||
continue;
|
||||
|
||||
if (!AddToContents(entity, uid, component))
|
||||
if (!AddToContents(entity, target, target.Comp))
|
||||
continue;
|
||||
|
||||
if (component.Contents.ContainedEntities.Count >= component.Capacity)
|
||||
if (target.Comp.Contents.ContainedEntities.Count >= target.Comp.Capacity)
|
||||
break;
|
||||
}
|
||||
|
||||
if (LifeStage(uid) >= EntityLifeStage.MapInitialized) // stop mappers from serializing air in locker
|
||||
TakeGas(uid, component);
|
||||
ModifyComponents(uid, component);
|
||||
if (_net.IsClient && _timing.IsFirstTimePredicted)
|
||||
_audio.PlayPvs(component.CloseSound, uid);
|
||||
if (LifeStage(target) >= EntityLifeStage.MapInitialized) // stop mappers from serializing air in locker
|
||||
TakeGas(target, target.Comp);
|
||||
|
||||
var afterev = new StorageAfterCloseEvent();
|
||||
RaiseLocalEvent(uid, ref afterev);
|
||||
ModifyComponents(target, target.Comp);
|
||||
_audio.PlayLocal(target.Comp.CloseSound, target, user);
|
||||
|
||||
var afterev = new StorageAfterCloseEvent(user);
|
||||
RaiseLocalEvent(target, ref afterev);
|
||||
}
|
||||
|
||||
public bool Insert(EntityUid toInsert, EntityUid container, EntityStorageComponent? component = null)
|
||||
|
|
@ -388,7 +387,7 @@ public abstract partial class SharedEntityStorageSystem : EntitySystem
|
|||
if (!CanOpen(user, target, silent))
|
||||
return false;
|
||||
|
||||
OpenStorage(target);
|
||||
OpenStorage(target, user);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -399,7 +398,7 @@ public abstract partial class SharedEntityStorageSystem : EntitySystem
|
|||
return false;
|
||||
}
|
||||
|
||||
CloseStorage(target);
|
||||
CloseStorage(target, user);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue