// 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 { /// /// Runs a set of minimal pre-reqs to check the timing, needed to enable dummy-proof, one-button interface to Wzhzhzh /// public void TryStartAssembly(EntityUid uid, MicrowaveComponent component, AssemblerStartCookMessage args) { if (!HasContents(component) || HasComp(uid) || !(TryComp(uid, out var apc) && apc.Powered)) return; var user = args.Actor; var solidsDict = new Dictionary(); var reagentDict = new Dictionary(); 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(item, out var stackComp)) { solidID = _prototype.Index(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(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 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(item); } _audio.PlayPvs(component.StartCookingSound, uid); var activeComp = AddComp(uid); //microwave is now cooking component.CurrentCookTimerTime = (uint)portionedRecipe.Item2 * portionedRecipe.Item1.CookTime; activeComp.CookTimeRemaining = component.CurrentCookTimerTime * component.FinalCookTimeMultiplier; // Frontier: CookTimeMultiplier /// Frontier: gets the largest number of portions /// public static (FoodRecipePrototype, int) GetPortionsForRecipe(MicrowaveComponent component, FoodRecipePrototype recipe, Dictionary solids, Dictionary 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); } }