Save Space Station 14 from the Toilet Gibber Forever (#35587)

* The evil is defeated

* Tag body bags

* uwu, cwush me cwusher-chan

* absolute 18+ sloggery

* botos binted? 👽
This commit is contained in:
Hannah Giovanna Dawson
2025-03-03 10:04:33 +00:00
committed by GitHub
parent 184edfe71d
commit 78b2b361e8
7 changed files with 44 additions and 80 deletions

View File

@@ -1,3 +1,4 @@
using Content.Shared.Body.Components;
using Content.Shared.Buckle; using Content.Shared.Buckle;
using Content.Shared.Buckle.Components; using Content.Shared.Buckle.Components;
using Content.Shared.Storage.Components; using Content.Shared.Storage.Components;
@@ -23,7 +24,7 @@ public sealed class FoldableSystem : EntitySystem
SubscribeLocalEvent<FoldableComponent, ComponentInit>(OnFoldableInit); SubscribeLocalEvent<FoldableComponent, ComponentInit>(OnFoldableInit);
SubscribeLocalEvent<FoldableComponent, ContainerGettingInsertedAttemptEvent>(OnInsertEvent); SubscribeLocalEvent<FoldableComponent, ContainerGettingInsertedAttemptEvent>(OnInsertEvent);
SubscribeLocalEvent<FoldableComponent, StoreMobInItemContainerAttemptEvent>(OnStoreThisAttempt); SubscribeLocalEvent<FoldableComponent, InsertIntoEntityStorageAttemptEvent>(OnStoreThisAttempt);
SubscribeLocalEvent<FoldableComponent, StorageOpenAttemptEvent>(OnFoldableOpenAttempt); SubscribeLocalEvent<FoldableComponent, StorageOpenAttemptEvent>(OnFoldableOpenAttempt);
SubscribeLocalEvent<FoldableComponent, StrapAttemptEvent>(OnStrapAttempt); SubscribeLocalEvent<FoldableComponent, StrapAttemptEvent>(OnStrapAttempt);
@@ -45,10 +46,8 @@ public sealed class FoldableSystem : EntitySystem
args.Cancelled = true; args.Cancelled = true;
} }
public void OnStoreThisAttempt(EntityUid uid, FoldableComponent comp, ref StoreMobInItemContainerAttemptEvent args) public void OnStoreThisAttempt(EntityUid uid, FoldableComponent comp, ref InsertIntoEntityStorageAttemptEvent args)
{ {
args.Handled = true;
if (comp.IsFolded) if (comp.IsFolded)
args.Cancelled = true; args.Cancelled = true;
} }

View File

@@ -64,12 +64,6 @@ public abstract partial class SharedEntityStorageComponent : Component
[DataField, ViewVariables(VVAccess.ReadWrite)] [DataField, ViewVariables(VVAccess.ReadWrite)]
public float EnteringRange = 0.18f; public float EnteringRange = 0.18f;
/// <summary>
/// If true, there may be mobs inside the container, even if the container is an Item
/// </summary>
[DataField]
public bool ItemCanStoreMobs = false;
/// <summary> /// <summary>
/// Whether or not to show the contents when the storage is closed /// Whether or not to show the contents when the storage is closed
/// </summary> /// </summary>
@@ -153,10 +147,7 @@ public sealed class EntityStorageComponentState : ComponentState
} }
[ByRefEvent] [ByRefEvent]
public record struct InsertIntoEntityStorageAttemptEvent(bool Cancelled = false); public record struct InsertIntoEntityStorageAttemptEvent(EntityUid ItemToInsert, bool Cancelled = false);
[ByRefEvent]
public record struct StoreMobInItemContainerAttemptEvent(bool Handled, bool Cancelled = false);
[ByRefEvent] [ByRefEvent]
public record struct StorageOpenAttemptEvent(EntityUid User, bool Silent, bool Cancelled = false); public record struct StorageOpenAttemptEvent(EntityUid User, bool Silent, bool Cancelled = false);

View File

@@ -241,26 +241,27 @@ public abstract class SharedEntityStorageSystem : EntitySystem
component.Open = false; component.Open = false;
Dirty(uid, component); Dirty(uid, component);
var targetCoordinates = new EntityCoordinates(uid, component.EnteringOffset); var entities = _lookup.GetEntitiesInRange(
new EntityCoordinates(uid, component.EnteringOffset),
component.EnteringRange,
LookupFlags.Approximate | LookupFlags.Dynamic | LookupFlags.Sundries
);
var entities = _lookup.GetEntitiesInRange(targetCoordinates, component.EnteringRange, LookupFlags.Approximate | LookupFlags.Dynamic | LookupFlags.Sundries); // Don't insert the container into itself.
entities.Remove(uid);
var ev = new StorageBeforeCloseEvent(entities, new()); var ev = new StorageBeforeCloseEvent(entities, []);
RaiseLocalEvent(uid, ref ev); RaiseLocalEvent(uid, ref ev);
var count = 0;
foreach (var entity in ev.Contents) foreach (var entity in ev.Contents)
{ {
if (!ev.BypassChecks.Contains(entity)) if (!ev.BypassChecks.Contains(entity) && !CanInsert(entity, uid, component))
{
if (!CanInsert(entity, uid, component))
continue; continue;
}
if (!AddToContents(entity, uid, component)) if (!AddToContents(entity, uid, component))
continue; continue;
count++; if (component.Contents.ContainedEntities.Count >= component.Capacity)
if (count >= component.Capacity)
break; break;
} }
@@ -331,7 +332,23 @@ public abstract class SharedEntityStorageSystem : EntitySystem
if (component.Contents.ContainedEntities.Count >= component.Capacity) if (component.Contents.ContainedEntities.Count >= component.Capacity)
return false; return false;
return CanFit(toInsert, container, component); var aabb = _lookup.GetAABBNoContainer(toInsert, Vector2.Zero, 0);
if (component.MaxSize < aabb.Size.X || component.MaxSize < aabb.Size.Y)
return false;
// Allow other systems to prevent inserting the item: e.g. the item is actually a ghost.
var attemptEvent = new InsertIntoEntityStorageAttemptEvent(toInsert);
RaiseLocalEvent(toInsert, ref attemptEvent);
if (attemptEvent.Cancelled)
return false;
// Consult the whitelist. The whitelist ignores the default assumption about how entity storage works.
if (component.Whitelist != null)
return _whitelistSystem.IsValid(component.Whitelist, toInsert);
// The inserted entity must be a mob or an item.
return HasComp<BodyComponent>(toInsert) || HasComp<ItemComponent>(toInsert);
} }
public bool TryOpenStorage(EntityUid user, EntityUid target, bool silent = false) public bool TryOpenStorage(EntityUid user, EntityUid target, bool silent = false)
@@ -412,60 +429,9 @@ public abstract class SharedEntityStorageSystem : EntitySystem
if (toAdd == container) if (toAdd == container)
return false; return false;
var aabb = _lookup.GetAABBNoContainer(toAdd, Vector2.Zero, 0);
if (component.MaxSize < aabb.Size.X || component.MaxSize < aabb.Size.Y)
return false;
return Insert(toAdd, container, component); return Insert(toAdd, container, component);
} }
private bool CanFit(EntityUid toInsert, EntityUid container, SharedEntityStorageComponent? component = null)
{
if (!Resolve(container, ref component))
return false;
// conditions are complicated because of pizzabox-related issues, so follow this guide
// 0. Accomplish your goals at all costs.
// 1. AddToContents can block anything
// 2. maximum item count can block anything
// 3. ghosts can NEVER be eaten
// 4. items can always be eaten unless a previous law prevents it
// 5. if this is NOT AN ITEM, then mobs can always be eaten unless a previous
// law prevents it
// 6. if this is an item, then mobs must only be eaten if some other component prevents
// pick-up interactions while a mob is inside (e.g. foldable)
var attemptEvent = new InsertIntoEntityStorageAttemptEvent();
RaiseLocalEvent(toInsert, ref attemptEvent);
if (attemptEvent.Cancelled)
return false;
var targetIsMob = HasComp<BodyComponent>(toInsert);
var storageIsItem = HasComp<ItemComponent>(container);
var allowedToEat = component.Whitelist == null ? HasComp<ItemComponent>(toInsert) : _whitelistSystem.IsValid(component.Whitelist, toInsert);
// BEFORE REPLACING THIS WITH, I.E. A PROPERTY:
// Make absolutely 100% sure you have worked out how to stop people ending up in backpacks.
// Seriously, it is insanely hacky and weird to get someone out of a backpack once they end up in there.
// And to be clear, they should NOT be in there.
// For the record, what you need to do is empty the backpack onto a PlacableSurface (table, rack)
if (targetIsMob)
{
if (!storageIsItem)
allowedToEat = true;
else
{
var storeEv = new StoreMobInItemContainerAttemptEvent();
RaiseLocalEvent(container, ref storeEv);
allowedToEat = storeEv is { Handled: true, Cancelled: false };
if (component.ItemCanStoreMobs)
allowedToEat = true;
}
}
return allowedToEat;
}
private void ModifyComponents(EntityUid uid, SharedEntityStorageComponent? component = null) private void ModifyComponents(EntityUid uid, SharedEntityStorageComponent? component = null)
{ {
if (!ResolveStorage(uid, ref component)) if (!ResolveStorage(uid, ref component))

View File

@@ -13,7 +13,6 @@
breakOnAccessBreaker: false breakOnAccessBreaker: false
- type: EntityStorage - type: EntityStorage
capacity: 1 # Its smol. capacity: 1 # Its smol.
itemCanStoreMobs: false # just leaving this here explicitly since I know at some point someone will want to use this to hold a mob. This also prevents it from becoming His Grace.
# - type: StorageFill # - type: StorageFill
# contents: # contents:
# - id: PuddleSparkle # Ha! Cute. Unfortunately it despawns before the container is likely to open. # - id: PuddleSparkle # Ha! Cute. Unfortunately it despawns before the container is likely to open.

View File

@@ -1,7 +1,7 @@
- type: entity - type: entity
id: PetCarrier id: PetCarrier
name: big pet carrier name: big pet carrier
description: Allows large animals to be carried comfortably. description: Allows large animals to be carried comfortably. It smells vaguely of toilet water and explosives.
parent: BaseStructureDynamic parent: BaseStructureDynamic
components: components:
- type: Sprite - type: Sprite
@@ -36,7 +36,9 @@
- type: EntityStorage - type: EntityStorage
capacity: 1 capacity: 1
airtight: false airtight: false
itemCanStoreMobs: true whitelist:
tags:
- VimPilot # If it can fit in a Vim it can fit in a pet carrier.
- type: Weldable - type: Weldable
- type: ResistLocker - type: ResistLocker
- type: PlaceableSurface - type: PlaceableSurface

View File

@@ -44,6 +44,10 @@
- type: EntityStorage - type: EntityStorage
capacity: 1 capacity: 1
isCollidableWhenOpen: true isCollidableWhenOpen: true
whitelist: # Use a tag whitelist rather than filtering for PerishableComponent to avoid chefs using body bags for food preservation
tags:
- VimPilot # Pets
- CanPilot # People
closeSound: closeSound:
path: /Audio/Misc/zip.ogg path: /Audio/Misc/zip.ogg
openSound: openSound:

View File

@@ -128,6 +128,9 @@
whitelist: whitelist:
components: components:
- Artifact - Artifact
tags:
- CanPilot # People
- VimPilot # Pets
- type: Appearance - type: Appearance
- type: GenericVisualizer - type: GenericVisualizer
visuals: visuals: