Files
wwdpublic/Content.Server/Nutrition/EntitySystems/SliceableFoodSystem.cs
Magnus Larsen e0a3cfacea Fix clientside storage Whitelists (#24063)
* Fix outdated component name in assaultbelt whitelist

RangedMagazine was replaced with BallisticAmmoProvider in the Gun
refactor (#8301)

* Move FlashOnTrigger, SmokeOnTrigger, Flash components to Shared

* Move LightReplacerComponent to Shared

* Move Utensil, Mousetrap components to Shared

* Move SprayPainterComponent to Shared

The PaintableAirlock tag has also been removed, as it was unused &
unnecessary, likely a vestige of spray painter development when the
PaintableAirlock component wasn't in Content.Shared.

* Add trivial Produce and Seed components to Client

This allows the plant bag and botanical belt whitelists to correctly
match produce and seeds on the client, fixing the extraneous "Can't
insert" message that previously appeared.

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
(cherry picked from commit 9cd6e4dccdfaa7e273417e3c94d66b5171c7d841)
2024-02-08 12:22:58 +01:00

191 lines
7.4 KiB
C#

using Content.Server.Nutrition; // DeltaV
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Server.Nutrition.Components;
using Content.Shared.Nutrition.Components;
using Content.Shared.Chemistry.Components;
using Content.Shared.Examine;
using Content.Shared.FixedPoint;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
namespace Content.Server.Nutrition.EntitySystems
{
public sealed class SliceableFoodSystem : EntitySystem
{
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
[Dependency] private readonly TransformSystem _xformSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SliceableFoodComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<SliceableFoodComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<SliceableFoodComponent, ComponentStartup>(OnComponentStartup);
}
private void OnInteractUsing(Entity<SliceableFoodComponent> entity, ref InteractUsingEvent args)
{
if (args.Handled)
return;
if (TrySliceFood(entity, args.User, args.Used, entity.Comp))
args.Handled = true;
}
private bool TrySliceFood(EntityUid uid, EntityUid user, EntityUid usedItem,
SliceableFoodComponent? component = null, FoodComponent? food = null, TransformComponent? transform = null)
{
if (!Resolve(uid, ref component, ref food, ref transform) ||
string.IsNullOrEmpty(component.Slice))
{
return false;
}
if (!_solutionContainerSystem.TryGetSolution(uid, food.Solution, out var soln, out var solution))
{
return false;
}
if (!TryComp<UtensilComponent>(usedItem, out var utensil) || (utensil.Types & UtensilType.Knife) == 0)
{
return false;
}
var sliceUid = Slice(uid, user, component, transform);
var lostSolution = _solutionContainerSystem.SplitSolution(soln.Value, solution.Volume / FixedPoint2.New(component.Count));
// Fill new slice
FillSlice(sliceUid, lostSolution);
_audio.PlayPvs(component.Sound, transform.Coordinates, AudioParams.Default.WithVolume(-2));
// Decrease size of item based on count - Could implement in the future
// Bug with this currently is the size in a container is not updated
// if (TryComp(uid, out ItemComponent? itemComp) && TryComp(sliceUid, out ItemComponent? sliceComp))
// {
// itemComp.Size -= sliceComp.Size;
// }
component.Count--;
// If someone makes food proto with 1 slice...
if (component.Count < 1)
{
DeleteFood(uid, user, food);
return true;
}
// Split last slice
if (component.Count > 1)
return true;
sliceUid = Slice(uid, user, component, transform);
// Fill last slice with the rest of the solution
FillSlice(sliceUid, solution);
DeleteFood(uid, user, food);
return true;
}
/// <summary>
/// Create a new slice in the world and returns its entity.
/// The solutions must be set afterwards.
/// </summary>
public EntityUid Slice(EntityUid uid, EntityUid user, SliceableFoodComponent? comp = null, TransformComponent? transform = null)
{
if (!Resolve(uid, ref comp, ref transform))
return EntityUid.Invalid;
var sliceUid = Spawn(comp.Slice, _xformSystem.GetMapCoordinates(uid));
// try putting the slice into the container if the food being sliced is in a container!
// this lets you do things like slice a pizza up inside of a hot food cart without making a food-everywhere mess
if (_containerSystem.TryGetContainingContainer(uid, out var container) && _containerSystem.CanInsert(sliceUid, container))
{
_containerSystem.Insert(sliceUid, container);
}
else // puts it down "right-side up"
{
_xformSystem.AttachToGridOrMap(sliceUid);
_xformSystem.SetLocalRotation(sliceUid, 0);
}
// DeltaV - Begin deep frier related code
var sliceEvent = new SliceFoodEvent(user, uid, sliceUid);
RaiseLocalEvent(uid, sliceEvent);
// DeltaV - End deep frier related code
return sliceUid;
}
private void DeleteFood(EntityUid uid, EntityUid user, FoodComponent foodComp)
{
var ev = new BeforeFullySlicedEvent
{
User = user
};
RaiseLocalEvent(uid, ev);
if (ev.Cancelled)
return;
if (string.IsNullOrEmpty(foodComp.Trash))
{
QueueDel(uid);
return;
}
// Locate the sliced food and spawn its trash
var trashUid = Spawn(foodComp.Trash, _xformSystem.GetMapCoordinates(uid));
// try putting the trash in the food's container too, to be consistent with slice spawning?
if (_containerSystem.TryGetContainingContainer(uid, out var container) && _containerSystem.CanInsert(trashUid, container))
{
_containerSystem.Insert(trashUid, container);
}
else // puts it down "right-side up"
{
_xformSystem.AttachToGridOrMap(trashUid);
_xformSystem.SetLocalRotation(trashUid, 0);
}
QueueDel(uid);
}
private void FillSlice(EntityUid sliceUid, Solution solution)
{
// Replace all reagents on prototype not just copying poisons (example: slices of eaten pizza should have less nutrition)
if (TryComp<FoodComponent>(sliceUid, out var sliceFoodComp) &&
_solutionContainerSystem.TryGetSolution(sliceUid, sliceFoodComp.Solution, out var itsSoln, out var itsSolution))
{
_solutionContainerSystem.RemoveAllSolution(itsSoln.Value);
var lostSolutionPart = solution.SplitSolution(itsSolution.AvailableVolume);
_solutionContainerSystem.TryAddSolution(itsSoln.Value, lostSolutionPart);
}
}
private void OnComponentStartup(Entity<SliceableFoodComponent> entity, ref ComponentStartup args)
{
entity.Comp.Count = entity.Comp.TotalCount;
var foodComp = EnsureComp<FoodComponent>(entity);
_solutionContainerSystem.EnsureSolution(entity.Owner, foodComp.Solution);
}
private void OnExamined(Entity<SliceableFoodComponent> entity, ref ExaminedEvent args)
{
args.PushMarkup(Loc.GetString("sliceable-food-component-on-examine-remaining-slices-text", ("remainingCount", entity.Comp.Count)));
}
}
}