6
2026-01-24 12:49:55 +03:00

181 lines
7.0 KiB
C#

// Overlaps with existing namespace.
using System.Linq;
using Content.Server.Kitchen.Components;
using Content.Server.Power.Components;
using Content.Shared._NF.Kitchen.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.FixedPoint;
using Content.Shared.Kitchen;
using Content.Shared.Stacks;
namespace Content.Server.Kitchen.EntitySystems;
public sealed partial class MicrowaveSystem : EntitySystem
{
/// <summary>
/// Runs a set of minimal pre-reqs to check the timing, needed to enable dummy-proof, one-button interface to Wzhzhzh
/// </summary>
public void TryStartAssembly(EntityUid uid, MicrowaveComponent component, AssemblerStartCookMessage args)
{
if (!HasContents(component) || HasComp<ActiveMicrowaveComponent>(uid) || !(TryComp<ApcPowerReceiverComponent>(uid, out var apc) && apc.Powered))
return;
var user = args.Actor;
var solidsDict = new Dictionary<string, int>();
var reagentDict = new Dictionary<string, FixedPoint2>();
var malfunctioning = false;
// TODO use lists of Reagent quantities instead of reagent prototype ids.
foreach (var item in component.Storage.ContainedEntities.ToArray())
{
string? solidID = null;
int amountToAdd = 1;
// If a microwave recipe uses a stacked item, use the default stack prototype id instead of prototype id
if (TryComp<StackComponent>(item, out var stackComp))
{
solidID = _prototype.Index<StackPrototype>(stackComp.StackTypeId).Spawn;
amountToAdd = stackComp.Count;
}
else
{
var metaData = MetaData(item); //this simply begs for cooking refactor
if (metaData.EntityPrototype is not null)
solidID = metaData.EntityPrototype.ID;
}
if (solidID is null)
{
continue;
}
if (solidsDict.ContainsKey(solidID))
{
solidsDict[solidID] += amountToAdd;
}
else
{
solidsDict.Add(solidID, amountToAdd);
}
if (!TryComp<SolutionContainerManagerComponent>(item, out var solMan))
continue;
foreach (var (_, soln) in _solutionContainer.EnumerateSolutions((item, solMan)))
{
var solution = soln.Comp.Solution;
foreach (var (reagent, quantity) in solution.Contents)
{
if (reagentDict.ContainsKey(reagent.Prototype))
reagentDict[reagent.Prototype] += quantity;
else
reagentDict.Add(reagent.Prototype, quantity);
}
}
}
// Check recipes
var getRecipesEv = new GetSecretRecipesEvent();
RaiseLocalEvent(uid, ref getRecipesEv);
List<FoodRecipePrototype> recipes = getRecipesEv.Recipes;
recipes.AddRange(_recipeManager.Recipes);
var portionedRecipe = recipes.Select(r =>
GetPortionsForRecipe(component, r, solidsDict, reagentDict)).FirstOrDefault(r => r.Item2 > 0);
if (portionedRecipe.Item2 <= 0)
{
// Display popup
_popupSystem.PopupEntity(Loc.GetString("microwave-component-assembler-no-valid-recipe"), uid);
_audio.PlayPvs(component.NoRecipeSound, uid);
return;
}
// We're actually microwaving things, run the wzhzhzh checks
foreach (var item in component.Storage.ContainedEntities.ToArray())
{
var ev = new BeingMicrowavedEvent(uid, user, component.CanHeat, component.CanIrradiate);
RaiseLocalEvent(item, ev);
if (ev.Handled)
{
UpdateUserInterfaceState(uid, component);
return;
}
if (_tag.HasTag(item, MetalTag) && component.CanIrradiate)
{
malfunctioning = true;
}
if (_tag.HasTag(item, PlasticTag) && (component.CanHeat || component.CanIrradiate))
{
var junk = Spawn(component.BadRecipeEntityId, Transform(uid).Coordinates);
_container.Insert(junk, component.Storage);
Del(item);
continue;
}
AddComp<ActivelyMicrowavedComponent>(item);
}
_audio.PlayPvs(component.StartCookingSound, uid);
var activeComp = AddComp<ActiveMicrowaveComponent>(uid); //microwave is now cooking
component.CurrentCookTimerTime = (uint)portionedRecipe.Item2 * portionedRecipe.Item1.CookTime;
activeComp.CookTimeRemaining = component.CurrentCookTimerTime * component.FinalCookTimeMultiplier; // Frontier: CookTimeMultiplier<FinalCookTimeMultiplier
activeComp.TotalTime = component.CurrentCookTimerTime; //this doesn't scale so that we can have the "actual" time
activeComp.PortionedRecipe = portionedRecipe;
//Scale times with cook times
component.CurrentCookTimeEnd = _gameTiming.CurTime + TimeSpan.FromSeconds(component.CurrentCookTimerTime * component.FinalCookTimeMultiplier); // Frontier: CookTimeMultiplier<FinalCookTimeMultiplier
if (malfunctioning)
activeComp.MalfunctionTime = _gameTiming.CurTime + TimeSpan.FromSeconds(component.MalfunctionInterval);
UpdateUserInterfaceState(uid, component);
}
/// <summary>
/// Frontier: gets the largest number of portions
/// </summary>
public static (FoodRecipePrototype, int) GetPortionsForRecipe(MicrowaveComponent component, FoodRecipePrototype recipe, Dictionary<string, int> solids, Dictionary<string, FixedPoint2> reagents)
{
var portions = 0;
// Frontier: microwave recipe machine types
if ((recipe.RecipeType & component.ValidRecipeTypes) == 0)
{
return (recipe, 0);
}
// End Frontier
foreach (var solid in recipe.IngredientsSolids)
{
if (!solids.ContainsKey(solid.Key))
return (recipe, 0);
if (solids[solid.Key] < solid.Value)
return (recipe, 0);
portions = portions == 0
? solids[solid.Key] / solid.Value.Int()
: Math.Min(portions, solids[solid.Key] / solid.Value.Int());
}
foreach (var reagent in recipe.IngredientsReagents)
{
// TODO Turn recipe.IngredientsReagents into a ReagentQuantity[]
if (!reagents.ContainsKey(reagent.Key))
return (recipe, 0);
if (reagents[reagent.Key] < reagent.Value)
return (recipe, 0);
portions = portions == 0
? reagents[reagent.Key].Int() / reagent.Value.Int()
: Math.Min(portions, reagents[reagent.Key].Int() / reagent.Value.Int());
}
//Return as many portions as we can assemble with the given materials
return (recipe, portions);
}
}