Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make things pulled by players not despawn when vgroids/uivs/derelicts despawn #2702

Merged
merged 9 commits into from
Jan 23, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Content.Shared.Mobs.Components;
using Content.Shared.Silicons.Borgs.Components;
using Content.Shared.Vehicle.Components;
using Content.Shared.Movement.Pulling.Components;
using Robust.Shared.Map;
using Robust.Shared.Player;

Expand Down Expand Up @@ -87,64 +88,92 @@ private void OnMasterRemoved(EntityUid uid, LinkedLifecycleGridParentComponent c
return (uid, xform);
}

// Returns a list of entities to reparent on a grid.
// Useful if you need to do your own bookkeeping.
public List<(Entity<TransformComponent> Entity, EntityUid MapUid, Vector2 LocalPosition)> GetEntitiesToReparent(EntityUid grid)
/// <summary>
/// Returns a list of entities to reparent on a grid.
/// Useful if you need to do your own bookkeeping.
/// </summary>
public List<(Entity<TransformComponent> Entity, EntityUid MapUid, Vector2 MapPosition)> GetEntitiesToReparent(EntityUid grid)
{
List<(Entity<TransformComponent> Entity, EntityUid MapUid, Vector2 LocalPosition)> reparentEntities = new();
HashSet<EntityUid> handledEntities = new();
List<(Entity<TransformComponent> Entity, EntityUid MapUid, Vector2 MapPosition)> reparentEntities = new();
HashSet<EntityUid> handledMindContainers = new();

// Get player characters
var mobQuery = AllEntityQuery<HumanoidAppearanceComponent, BankAccountComponent, TransformComponent>();
while (mobQuery.MoveNext(out var mobUid, out _, out _, out var xform))
{
handledEntities.Add(mobUid);
handledMindContainers.Add(mobUid);

if (xform.GridUid == null || xform.MapUid == null || xform.GridUid != grid)
continue;

var (targetUid, targetXform) = GetParentToReparent(mobUid, xform);

reparentEntities.Add(((targetUid, targetXform), targetXform.MapUid!.Value, _transform.GetWorldPosition(targetXform)));

HandlePulledEntity(targetUid, ref reparentEntities);
}

// Get silicon
var borgQuery = AllEntityQuery<BorgChassisComponent, ActorComponent, TransformComponent>();
while (borgQuery.MoveNext(out var borgUid, out _, out _, out var xform))
{
handledEntities.Add(borgUid);
handledMindContainers.Add(borgUid);

if (xform.GridUid == null || xform.MapUid == null || xform.GridUid != grid)
continue;

var (targetUid, targetXform) = GetParentToReparent(borgUid, xform);

reparentEntities.Add(((targetUid, targetXform), targetXform.MapUid!.Value, _transform.GetWorldPosition(targetXform)));

HandlePulledEntity(targetUid, ref reparentEntities);
}

// Get occupied MindContainers
// Get occupied MindContainers (non-humanoids, pets, etc.)
var mindQuery = AllEntityQuery<MindContainerComponent, TransformComponent>();
while (mindQuery.MoveNext(out var mobUid, out var mindContainer, out var xform))
{
if (xform.GridUid == null || xform.MapUid == null || xform.GridUid != grid)
continue;

// Not player-controlled, nothing to lose
// Not player-controlled, little to lose
if (_mind.GetMind(mobUid, mindContainer) == null)
continue;

// Already handled
if (handledEntities.Contains(mobUid))
// All humans and borgs should have mind containers - if we've handled them already, no need.
if (handledMindContainers.Contains(mobUid))
continue;

var (targetUid, targetXform) = GetParentToReparent(mobUid, xform);

reparentEntities.Add(((targetUid, targetXform), targetXform.MapUid!.Value, _transform.GetWorldPosition(targetXform)));

HandlePulledEntity(targetUid, ref reparentEntities);
}

return reparentEntities;
}

/// <summary>
/// Tries to get what the passed entity is pulling, if anything, and adds it to the passed list.
/// </summary>
private void HandlePulledEntity(Entity<PullerComponent?> entity, ref List<(Entity<TransformComponent> Entity, EntityUid MapUid, Vector2 MapPosition)> listToReparent)
{
if (!Resolve(entity, ref entity.Comp))
return;

if (entity.Comp.Pulling is not EntityUid pulled)
return;

var pulledXform = Transform(pulled);

if (pulledXform.MapUid is not EntityUid pulledMapUid)
return;

// Note: this entry may be duplicated.
listToReparent.Add(((pulled, pulledXform), pulledMapUid, _transform.GetWorldPosition(pulledXform)));
}

// Deletes a grid, reparenting every humanoid and player character that's on it.
public void UnparentPlayersFromGrid(EntityUid grid, bool deleteGrid, bool ignoreLifeStage = false)
{
Expand All @@ -155,6 +184,10 @@ public void UnparentPlayersFromGrid(EntityUid grid, bool deleteGrid, bool ignore

foreach (var target in reparentEntities)
{
// If the item has already been moved to nullspace, skip it.
if (Transform(target.Entity).MapID == MapId.Nullspace)
continue;

// Move the target and all of its children (for bikes, mechs, etc.)
_transform.DetachEntity(target.Entity.Owner, target.Entity.Comp);
}
Expand All @@ -165,7 +198,11 @@ public void UnparentPlayersFromGrid(EntityUid grid, bool deleteGrid, bool ignore

foreach (var target in reparentEntities)
{
_transform.SetCoordinates(target.Entity.Owner, new EntityCoordinates(target.MapUid, target.LocalPosition));
// If the item has already been moved out of nullspace, skip it.
if (Transform(target.Entity).MapID != MapId.Nullspace)
continue;

_transform.SetCoordinates(target.Entity.Owner, new EntityCoordinates(target.MapUid, target.MapPosition));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ protected override void Ended(EntityUid uid, BluespaceErrorRuleComponent compone

foreach (var mob in playerMobs)
{
_transform.SetCoordinates(mob.Entity.Owner, new EntityCoordinates(mob.MapUid, mob.LocalPosition));
_transform.SetCoordinates(mob.Entity.Owner, new EntityCoordinates(mob.MapUid, mob.MapPosition));
}

foreach (var (account, rewardCoeff) in component.RewardAccounts)
Expand Down
Loading