Fix area pickup bug (#10902)

Co-authored-by: metalgearsloth <metalgearsloth@gmail.com>
This commit is contained in:
metalgearsloth
2022-08-31 22:09:31 +10:00
committed by GitHub
parent 2f56724d18
commit 65954d207b

View File

@@ -48,6 +48,7 @@ namespace Content.Server.Storage.EntitySystems
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
/// <inheritdoc />
public override void Initialize()
@@ -67,12 +68,64 @@ namespace Content.Server.Storage.EntitySystems
SubscribeLocalEvent<ServerStorageComponent, BoundUIClosedEvent>(OnBoundUIClosed);
SubscribeLocalEvent<ServerStorageComponent, EntRemovedFromContainerMessage>(OnStorageItemRemoved);
SubscribeLocalEvent<ServerStorageComponent, AreaPickupCompleteEvent>(OnAreaPickupComplete);
SubscribeLocalEvent<ServerStorageComponent, AreaPickupCancelledEvent>(OnAreaPickupCancelled);
SubscribeLocalEvent<EntityStorageComponent, GetVerbsEvent<InteractionVerb>>(AddToggleOpenVerb);
SubscribeLocalEvent<EntityStorageComponent, ContainerRelayMovementEntityEvent>(OnRelayMovement);
SubscribeLocalEvent<StorageFillComponent, MapInitEvent>(OnStorageFillMapInit);
}
private void OnAreaPickupCancelled(EntityUid uid, ServerStorageComponent component, AreaPickupCancelledEvent args)
{
component.CancelToken = null;
}
private void OnAreaPickupComplete(EntityUid uid, ServerStorageComponent component, AreaPickupCompleteEvent args)
{
component.CancelToken = null;
var successfullyInserted = new List<EntityUid>();
var successfullyInsertedPositions = new List<EntityCoordinates>();
var itemQuery = GetEntityQuery<ItemComponent>();
var xformQuery = GetEntityQuery<TransformComponent>();
xformQuery.TryGetComponent(uid, out var xform);
foreach (var entity in args.ValidStorables)
{
// Check again, situation may have changed for some entities, but we'll still pick up any that are valid
if (_containerSystem.IsEntityInContainer(entity)
|| entity == args.User
|| !itemQuery.HasComponent(entity))
continue;
if (xform == null ||
!xformQuery.TryGetComponent(entity, out var targetXform) ||
targetXform.MapID != xform.MapID)
{
continue;
}
var position = EntityCoordinates.FromMap(
xform.ParentUid.IsValid() ? xform.ParentUid : uid,
new MapCoordinates(_transform.GetWorldPosition(targetXform, xformQuery),
targetXform.MapID), EntityManager);
if (PlayerInsertEntityInWorld(uid, args.User, entity, component))
{
successfullyInserted.Add(entity);
successfullyInsertedPositions.Add(position);
}
}
// If we picked up atleast one thing, play a sound and do a cool animation!
if (successfullyInserted.Count > 0)
{
_audio.PlayPvs(component.StorageInsertSound, uid);
RaiseNetworkEvent(new AnimateInsertingEntitiesEvent(uid, successfullyInserted, successfullyInsertedPositions));
}
}
private void OnComponentInit(EntityUid uid, ServerStorageComponent storageComp, ComponentInit args)
{
base.Initialize();
@@ -130,14 +183,16 @@ namespace Content.Server.Storage.EntitySystems
return;
// Get the session for the user
if (!TryComp<ActorComponent>(args.User, out var actor) || actor?.PlayerSession == null)
if (!TryComp<ActorComponent>(args.User, out var actor))
return;
// Does this player currently have the storage UI open?
bool uiOpen = _uiSystem.SessionHasOpenUi(uid, StorageUiKey.Key, actor.PlayerSession);
ActivationVerb verb = new();
verb.Act = () => OpenStorageUI(uid, args.User, component);
ActivationVerb verb = new()
{
Act = () => OpenStorageUI(uid, args.User, component)
};
if (uiOpen)
{
verb.Text = Loc.GetString("verb-common-close-ui");
@@ -178,8 +233,6 @@ namespace Content.Server.Storage.EntitySystems
}
}
/// <summary>
/// Inserts storable entities into this storage container if possible, otherwise return to the hand of the user
/// </summary>
@@ -210,9 +263,6 @@ namespace Content.Server.Storage.EntitySystems
/// <returns></returns>
private void OnActivate(EntityUid uid, ServerStorageComponent storageComp, ActivateInWorldEvent args)
{
if (!TryComp<ActorComponent>(args.User, out var actor))
return;
if (TryComp(uid, out LockComponent? lockComponent) && lockComponent.Locked)
return;
@@ -224,27 +274,27 @@ namespace Content.Server.Storage.EntitySystems
/// around a click.
/// </summary>
/// <returns></returns>
private async void AfterInteract(EntityUid uid, ServerStorageComponent storageComp, AfterInteractEvent eventArgs)
private async void AfterInteract(EntityUid uid, ServerStorageComponent storageComp, AfterInteractEvent args)
{
if (!eventArgs.CanReach) return;
if (!args.CanReach) return;
if (storageComp.CancelToken != null)
{
storageComp.CancelToken.Cancel();
storageComp.CancelToken = null;
return;
}
// Pick up all entities in a radius around the clicked location.
// The last half of the if is because carpets exist and this is terrible
if (storageComp.AreaInsert && (eventArgs.Target == null || !HasComp<ItemComponent>(eventArgs.Target.Value)))
if (storageComp.AreaInsert && (args.Target == null || !HasComp<ItemComponent>(args.Target.Value)))
{
var validStorables = new List<EntityUid>();
foreach (var entity in _entityLookupSystem.GetEntitiesInRange(eventArgs.ClickLocation, storageComp.AreaInsertRadius, LookupFlags.None))
var itemQuery = GetEntityQuery<ItemComponent>();
foreach (var entity in _entityLookupSystem.GetEntitiesInRange(args.ClickLocation, storageComp.AreaInsertRadius, LookupFlags.None))
{
if (entity == eventArgs.User
|| !HasComp<ItemComponent>(entity)
|| !_interactionSystem.InRangeUnobstructed(eventArgs.User, entity))
if (entity == args.User
|| !itemQuery.HasComponent(entity)
|| !_interactionSystem.InRangeUnobstructed(args.User, entity))
continue;
validStorables.Add(entity);
@@ -254,57 +304,30 @@ namespace Content.Server.Storage.EntitySystems
if (validStorables.Count > 1)
{
storageComp.CancelToken = new CancellationTokenSource();
var doAfterArgs = new DoAfterEventArgs(eventArgs.User, 0.2f * validStorables.Count, storageComp.CancelToken.Token, uid)
var doAfterArgs = new DoAfterEventArgs(args.User, 0.2f * validStorables.Count, storageComp.CancelToken.Token, target: uid)
{
BreakOnStun = true,
BreakOnDamage = true,
BreakOnUserMove = true,
NeedHand = true,
TargetCancelledEvent = new AreaPickupCancelledEvent(),
TargetFinishedEvent = new AreaPickupCompleteEvent(args.User, validStorables),
};
await _doAfterSystem.WaitDoAfter(doAfterArgs);
_doAfterSystem.DoAfter(doAfterArgs);
}
// TODO: Make it use the event DoAfter
var successfullyInserted = new List<EntityUid>();
var successfullyInsertedPositions = new List<EntityCoordinates>();
foreach (var entity in validStorables)
{
// Check again, situation may have changed for some entities, but we'll still pick up any that are valid
if (_containerSystem.IsEntityInContainer(entity)
|| entity == eventArgs.User
|| !HasComp<ItemComponent>(entity))
continue;
if (TryComp<TransformComponent>(uid, out var transformOwner) && TryComp<TransformComponent>(entity, out var transformEnt))
{
var position = EntityCoordinates.FromMap(transformOwner.Parent?.Owner ?? uid, transformEnt.MapPosition);
if (PlayerInsertEntityInWorld(uid, eventArgs.User, entity, storageComp))
{
successfullyInserted.Add(entity);
successfullyInsertedPositions.Add(position);
}
}
}
// If we picked up atleast one thing, play a sound and do a cool animation!
if (successfullyInserted.Count > 0)
{
if (storageComp.StorageInsertSound is not null)
SoundSystem.Play(storageComp.StorageInsertSound.GetSound(), Filter.Pvs(uid, entityManager: EntityManager), uid, AudioParams.Default);
RaiseNetworkEvent(new AnimateInsertingEntitiesEvent(uid, successfullyInserted, successfullyInsertedPositions));
}
return;
}
// Pick up the clicked entity
else if (storageComp.QuickInsert)
if (storageComp.QuickInsert)
{
if (eventArgs.Target is not {Valid: true} target)
if (args.Target is not {Valid: true} target)
return;
if (_containerSystem.IsEntityInContainer(target)
|| target == eventArgs.User
|| target == args.User
|| !HasComp<ItemComponent>(target))
return;
@@ -313,9 +336,10 @@ namespace Content.Server.Storage.EntitySystems
var parent = transformOwner.ParentUid;
var position = EntityCoordinates.FromMap(
parent.IsValid() ? parent : uid,
transformEnt.MapPosition);
if (PlayerInsertEntityInWorld(uid, eventArgs.User, target, storageComp))
parent.IsValid() ? parent : uid,
transformEnt.MapPosition);
if (PlayerInsertEntityInWorld(uid, args.User, target, storageComp))
{
RaiseNetworkEvent(new AnimateInsertingEntitiesEvent(uid,
new List<EntityUid> { target },
@@ -323,7 +347,6 @@ namespace Content.Server.Storage.EntitySystems
}
}
}
return;
}
private void OnDestroy(EntityUid uid, ServerStorageComponent storageComp, DestructionEventArgs args)
@@ -679,5 +702,25 @@ namespace Content.Server.Storage.EntitySystems
_popupSystem.PopupEntity(Loc.GetString(message), player, Filter.Entities(player));
}
/// <summary>
/// Raised on storage if it successfully completes area pickup.
/// </summary>
private sealed class AreaPickupCompleteEvent : EntityEventArgs
{
public EntityUid User;
public List<EntityUid> ValidStorables;
public AreaPickupCompleteEvent(EntityUid user, List<EntityUid> validStorables)
{
User = user;
ValidStorables = validStorables;
}
}
private sealed class AreaPickupCancelledEvent : EntityEventArgs
{
}
}
}