From d8e818283c6398840cea394c102f711f0438c643 Mon Sep 17 00:00:00 2001
From: Princess Cheeseballs
<66055347+Princess-Cheeseballs@users.noreply.github.com>
Date: Sun, 14 Sep 2025 13:41:42 -0700
Subject: [PATCH] [STAGING/HOTFIX] Butcher entities in containers. (#40299)
* Kitchen spike and sharp system
* Use transform and parent
* A
* Works
* A
---------
Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
---
.../Kitchen/EntitySystems/SharpSystem.cs | 24 +++++++++-----
.../Interaction/SharedInteractionSystem.cs | 13 ++++++--
.../Kitchen/SharedKitchenSpikeSystem.cs | 33 +++++++++++++++----
.../StationAi/SharedStationAiSystem.cs | 15 ++++-----
4 files changed, 58 insertions(+), 27 deletions(-)
diff --git a/Content.Server/Kitchen/EntitySystems/SharpSystem.cs b/Content.Server/Kitchen/EntitySystems/SharpSystem.cs
index ab6e1db494..39a3ecb7bb 100644
--- a/Content.Server/Kitchen/EntitySystems/SharpSystem.cs
+++ b/Content.Server/Kitchen/EntitySystems/SharpSystem.cs
@@ -102,19 +102,25 @@ public sealed class SharpSystem : EntitySystem
component.Butchering.Remove(args.Args.Target.Value);
- if (_containerSystem.IsEntityInContainer(args.Args.Target.Value))
- {
- args.Handled = true;
- return;
- }
-
var spawnEntities = EntitySpawnCollection.GetSpawns(butcher.SpawnedEntities, _robustRandom);
var coords = _transform.GetMapCoordinates(args.Args.Target.Value);
EntityUid popupEnt = default!;
- foreach (var proto in spawnEntities)
+
+ if (_containerSystem.TryGetContainingContainer(args.Args.Target.Value, out var container))
{
- // distribute the spawned items randomly in a small radius around the origin
- popupEnt = Spawn(proto, coords.Offset(_robustRandom.NextVector2(0.25f)));
+ foreach (var proto in spawnEntities)
+ {
+ // distribute the spawned items randomly in a small radius around the origin
+ popupEnt = SpawnInContainerOrDrop(proto, container.Owner, container.ID);
+ }
+ }
+ else
+ {
+ foreach (var proto in spawnEntities)
+ {
+ // distribute the spawned items randomly in a small radius around the origin
+ popupEnt = Spawn(proto, coords.Offset(_robustRandom.NextVector2(0.25f)));
+ }
}
// only show a big popup when butchering living things.
diff --git a/Content.Shared/Interaction/SharedInteractionSystem.cs b/Content.Shared/Interaction/SharedInteractionSystem.cs
index d29c3436ac..c1bb855f36 100644
--- a/Content.Shared/Interaction/SharedInteractionSystem.cs
+++ b/Content.Shared/Interaction/SharedInteractionSystem.cs
@@ -1303,10 +1303,17 @@ namespace Content.Shared.Interaction
var ev = new AccessibleOverrideEvent(user, target);
RaiseLocalEvent(user, ref ev);
+ RaiseLocalEvent(target, ref ev);
+ // If either has handled it and neither has said we can't access it then we can access it.
if (ev.Handled)
return ev.Accessible;
+ return CanAccess(user, target);
+ }
+
+ public bool CanAccess(EntityUid user, EntityUid target)
+ {
if (_containerSystem.IsInSameOrParentContainer(user, target, out _, out var container))
return true;
@@ -1511,16 +1518,16 @@ namespace Content.Shared.Interaction
///
/// Override event raised directed on the user to say the target is accessible.
///
- ///
- ///
+ /// Entity we're targeting
[ByRefEvent]
public record struct AccessibleOverrideEvent(EntityUid User, EntityUid Target)
{
public readonly EntityUid User = User;
public readonly EntityUid Target = Target;
+ // We set it to true by default for easier validation later.
public bool Handled;
- public bool Accessible = false;
+ public bool Accessible;
}
///
diff --git a/Content.Shared/Kitchen/SharedKitchenSpikeSystem.cs b/Content.Shared/Kitchen/SharedKitchenSpikeSystem.cs
index c691a973f9..cdc831cd67 100644
--- a/Content.Shared/Kitchen/SharedKitchenSpikeSystem.cs
+++ b/Content.Shared/Kitchen/SharedKitchenSpikeSystem.cs
@@ -32,18 +32,19 @@ namespace Content.Shared.Kitchen;
///
public sealed class SharedKitchenSpikeSystem : EntitySystem
{
- [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
- [Dependency] private readonly SharedContainerSystem _containerSystem = default!;
- [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly IGameTiming _gameTiming = default!;
+ [Dependency] private readonly ISharedAdminLogManager _logger = default!;
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly ExamineSystemShared _examineSystem = default!;
- [Dependency] private readonly MobStateSystem _mobStateSystem = default!;
- [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly MetaDataSystem _metaDataSystem = default!;
- [Dependency] private readonly ISharedAdminLogManager _logger = default!;
+ [Dependency] private readonly MobStateSystem _mobStateSystem = default!;
+ [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
[Dependency] private readonly SharedBodySystem _bodySystem = default!;
- [Dependency] private readonly IGameTiming _gameTiming = default!;
+ [Dependency] private readonly SharedContainerSystem _containerSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly SharedInteractionSystem _interaction = default!;
+ [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
public override void Initialize()
{
@@ -76,6 +77,9 @@ public sealed class SharedKitchenSpikeSystem : EntitySystem
SubscribeLocalEvent(OnAttempt);
SubscribeLocalEvent(OnAttempt);
SubscribeLocalEvent(OnAttempt);
+
+ // Container Jank
+ SubscribeLocalEvent(OnAccessibleOverride);
}
private void OnInit(Entity ent, ref ComponentInit args)
@@ -382,6 +386,21 @@ public sealed class SharedKitchenSpikeSystem : EntitySystem
args.Cancel();
}
+ private void OnAccessibleOverride(Entity ent, ref AccessibleOverrideEvent args)
+ {
+ // Check if the entity is the target to avoid giving the hooked entity access to everything.
+ // If we already have access we don't need to run more code.
+ if (args.Accessible || args.Target != ent.Owner)
+ return;
+
+ var xform = Transform(ent);
+ if (!_interaction.CanAccess(args.User, xform.ParentUid))
+ return;
+
+ args.Accessible = true;
+ args.Handled = true;
+ }
+
public override void Update(float frameTime)
{
base.Update(frameTime);
diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs
index d76f16c446..1a3d4c788e 100644
--- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs
+++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs
@@ -145,18 +145,17 @@ public abstract partial class SharedStationAiSystem : EntitySystem
private void OnAiAccessible(Entity ent, ref AccessibleOverrideEvent args)
{
+ // We don't want to allow entities to access the AI just because the eye is nearby.
+ // Only let the AI access entities through the eye.
+ if (args.Accessible || args.User != ent.Owner)
+ return;
+
args.Handled = true;
// Hopefully AI never needs storage
- if (_containers.TryGetContainingContainer(args.Target, out var targetContainer))
- {
- return;
- }
-
- if (!_containers.IsInSameOrTransparentContainer(args.User, args.Target, otherContainer: targetContainer))
- {
+ if (_containers.TryGetContainingContainer(args.Target, out var targetContainer) ||
+ !_containers.IsInSameOrTransparentContainer(ent.Owner, args.Target, otherContainer: targetContainer))
return;
- }
args.Accessible = true;
}
--
2.51.2