CatStation/Content.Shared/Kitchen/EntitySystems/MicrowaveSystem.cs
portfiend b9b794deef
Microwave Refactor and Prediction (#43129)
* adjust fields of meal recipe prototype

* document microwave recipe datafields

* use file scoped namespace for microwave recipes

* more of this

* localize every microwave recipe

* make microwave system shared

* refactor recipe reagent contents

* refactor recipe solids + add material ingredient datafield

* im making this a bit less silly

* awa

* move this shit out

* move this shit out also

* refactor Wzhzhzh

* im gonna shorten this parameter by 1 actually

* move this into recipes

* make processcontents a little better(?)

* clean imports

* rename a struct

* use cooking ingredients struct

* comment

* use whitelist for this

* unused dependency

* rearranged the parameters of get recipe portions

* rearrange some stuff

* clean up more imports

* move container related functions into separate file

* move this function out of ProcessContents

* prevent microwaves from having items inserted while active

* use IsPowered in microwave system

* use byref syntax and Entity<>

* moving the override up
sorry i like it being up here

* refactor microwave updating

* clean up recipe finish logic

* im renaming this function actually

* move some functions around

* move more stuff around

* some comments

* fix compiler error

* fix the yml of all microwave recipes

* use materials instead of solids for this stuff

* oops

* fix this

* turn microwave sparks into datafield

* move activelymicrowaved events into separate folder

* make UpdateUserInterfaceState use entity only

* rearrange some functions

* move UI functions out

* comment microwave UI stuff

* more comments

* comment recipe functions

* refactor GetTotalIngredients to use an operator

* give CookingIngredients addition methods

* comment the rest of CookingIngredients

* make subtraction functions clearer?

* remove redundant comment

* handle zero/negative ingredient cases

* simplify subtract contents logic

* fix these comments

* typo

* add microwave recipe test

* move active microwave methods

* comment active microwave methods

* comment cooking methods

* comment microwave methods

* change setappearance to use entity<>

* add some public api decorators

* comment all of MicrowaveComponent

* use file-scoped namespace for MicrowaveComponent

* comment

* fix baguette sword

* maybe...?

* oh oops

* document the rest of the owl

* kill the massive YML breaking change

* fix protoman dependency

* move shared microwave stuff to SharedMicrowaveSystem

* fix usings

* move microwave components to shared

* fix up microwave datafields

* move APIs to shared

* move activemicrowave methods to shared

* initialize on shared

* move ui functions to shared

* add actor here

* stuff

* predict microwave update loop

* make clientside microwave system

* adjust the update loop for microwaves

* clean up

* add field deltas to microwaves

* dirty fields instead of whole component

* move this to the partial

* move GetRecipesForMicrowave to shared

* comments

* predict microwave BUI

* oops

* refactor microwave bui update

* move UI messages to shared

* move messages to UI file

* move init to shared

* move container methosd to shared

* oops my using

* move cooking functions into partial

* move cooking methods to shared

* move microwave recipe methods to shared

* move the rest of the microwave events to shared

* update imports

* remove custom type serializer

* better (?) microwave UI prediction

* fix list notations

* OK IT WAS THE DATAFIELDS

* add IOC inject

* dont use IOC for htis

* sealed

* prediction fixes pt1

* make microwave cooking updates more consistent

* datafield tweaks

* test for multiple portions in microwave recipes

* test for multiple recipe portions

* better(?) prediction for malfunctions

* remove redundant comment

* prevent solution reactions in microwave

* cleanup some microwave stuff

* eh i think this should be container actually

* this can be API i think

* reduce system redundancy

* this has to be public

* use resolve pattern for explode

* use GetMicrowaveContents in microwave system

* this can be an API too

* add conversion script for unlocalized recipes

* use EnsureComp instead of AddComp

* suffering

* fix recipe prediction

* fix the audio

* reduce redundant networking

* i think this should be autopaused?

* nevermind we use dynamic portions in the test

* oops i wrote the test wrong

* make lemoon cake take 2 lemoons again
sorry test fail

* rename "materials" to "stacks"
realized theyre different

* add stack guidebook quantities

* Kill audio

* fix lemoon cake recipe for real?

* mark PortionedRecipe as a datadefinition

* fix the microwave timer

* review

* cleanup

* Update SharedMicrowaveSystem.Recipes.cs

* update

* add audio params

* review: inject microwavesystem

* review: named variable

* review: move dependencies

* review: use gametest for recipe test

* review: make access attributes standalone

* rename prototypes and datafields

* review: rename this var

* review: move this function down

* review: remove these scripts

* actually this should stay

* refactor cook time buttons

* review: use a color name for this

* fix timer reset

* Dirty

* review: make ActivelyMicrowavedComponent networked

* review: slarti comments part 1

* review: remove serializable attribute from CookingIngredients

* rename file

* review: more microwave audio boilerplate. yippee!

* review: use resolve pattern for TryGetStackId
i dont like the way this makes the rest of the code look but we ball maybe. i dont know what else to do here

* review: move ui update to constructor

* review: kill LastCookUpdated

* actually i do this instead

* fixed up the PR

* cleanup

* ///

* Update microwave.yml

---------

Co-authored-by: Princess Cheeseballs <66055347+Princess-Cheeseballs@users.noreply.github.com>
Co-authored-by: Pok245 <113675512+Pok27@users.noreply.github.com>
2026-10-04 23:38:48 +00:00

191 lines
6.5 KiB
C#

using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Destructible;
using Content.Shared.DeviceLinking;
using Content.Shared.DeviceLinking.Events;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Item;
using Content.Shared.Kitchen.Components;
using Content.Shared.Popups;
using Content.Shared.Power;
using Content.Shared.Power.EntitySystems;
using Content.Shared.Stacks;
using Content.Shared.Temperature.Systems;
using Content.Shared.Whitelist;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Network;
using Robust.Shared.Serialization;
using Robust.Shared.Timing;
namespace Content.Shared.Kitchen.EntitySystems;
/// <summary>
/// A system that handles microwave logic, such as activation, malfunctions, and producing cooked recipes.
/// TODO: Replace with a more sophisticated(?) cooking system.
/// </summary>
public abstract partial class MicrowaveSystem : EntitySystem
{
[Dependency] protected IGameTiming Timing = default!;
[Dependency] protected SharedAppearanceSystem Appearance = default!;
[Dependency] protected SharedAudioSystem Audio = default!;
[Dependency] protected SharedContainerSystem Container = default!;
[Dependency] protected SharedPopupSystem Popup = default!;
[Dependency] protected SharedSolutionContainerSystem Solution = default!;
[Dependency] private INetManager _net = default!;
[Dependency] private EntityWhitelistSystem _whitelist = default!;
[Dependency] private RecipeSystem _recipes = default!;
[Dependency] private SharedDeviceLinkSystem _deviceLink = default!;
[Dependency] private SharedHandsSystem _hands = default!;
[Dependency] private SharedItemSystem _item = default!;
[Dependency] private SharedPowerReceiverSystem _power = default!;
[Dependency] private SharedPowerStateSystem _powerState = default!;
[Dependency] private SharedStackSystem _stack = default!;
[Dependency] private SharedTemperatureSystem _temperature = default!;
[Dependency] protected EntityQuery<MicrowaveComponent> MicrowaveQuery;
[Dependency] protected EntityQuery<ActiveMicrowaveComponent> ActiveMicrowaveQuery;
[Dependency] protected EntityQuery<ItemComponent> ItemQuery;
[Dependency] protected EntityQuery<StackComponent> StackQuery;
public override void Initialize()
{
base.Initialize();
InitializeUI();
}
/// <summary>
/// Processes every active microwave's ongoing cooking operation.
/// </summary>
public override void Update(float frameTime)
{
base.Update(frameTime);
var curTime = Timing.CurTime;
var query = EntityQueryEnumerator<ActiveMicrowaveComponent, MicrowaveComponent>();
while (query.MoveNext(out var uid, out var active, out var microwave))
{
// Roll malfunctions
if (active.Malfunctioning && active.NextMalfunction < curTime)
{
active.NextMalfunction += microwave.MalfunctionInterval;
DirtyField(uid, active, nameof(active.NextMalfunction));
RollMalfunction((uid, microwave));
}
var timeSinceUpdate = curTime - active.LastCookUpdated;
var timeElapsed = (float)timeSinceUpdate.TotalSeconds;
// Finish cooking
if (active.CookTimeEnd < curTime)
{
AddTemperature((uid, microwave), timeElapsed);
CompleteCooking((uid, active, microwave));
continue;
}
// Otherwise, process the cooking cycle
if (active.NextCookUpdate > curTime)
continue;
active.NextCookUpdate += microwave.UpdateInterval;
active.LastCookUpdated = curTime;
DirtyFields(uid, active, null, nameof(active.NextCookUpdate), nameof(active.LastCookUpdated));
AddTemperature((uid, microwave), timeElapsed);
}
}
/// <summary>
/// Adds an "on" port to this microwave.
/// </summary>
[SubscribeLocalEvent]
private void OnMapInit(Entity<MicrowaveComponent> ent, ref MapInitEvent args)
{
_deviceLink.EnsureSinkPorts(ent, ent.Comp.OnPort);
}
/// <summary>
/// When a microwave is broken, its appearance changes and it stops being usable for cooking.
/// It will stop any ongoing cooking operations and empty its contents.
/// </summary>
[SubscribeLocalEvent]
private void OnBreak(Entity<MicrowaveComponent> ent, ref BreakageEventArgs args)
{
ent.Comp.Broken = true;
DirtyField(ent.AsNullable(), nameof(ent.Comp.Broken));
SetAppearance(ent, MicrowaveVisualState.Broken);
StopCooking(ent);
Container.EmptyContainer(ent.Comp.Storage);
UpdateUI(ent.AsNullable());
}
/// <summary>
/// Stop cooking if the microwave loses power.
/// </summary>
[SubscribeLocalEvent]
private void OnPowerChanged(Entity<MicrowaveComponent> ent, ref PowerChangedEvent args)
{
if (!args.Powered)
{
SetAppearance(ent, MicrowaveVisualState.Idle);
StopCooking(ent);
}
UpdateUI(ent.AsNullable());
}
/// <summary>
/// Empty the microwave if it is unanchored.
/// </summary>
[SubscribeLocalEvent]
private void OnAnchorChanged(Entity<MicrowaveComponent> ent, ref AnchorStateChangedEvent args)
{
if (!args.Anchored)
Container.EmptyContainer(ent.Comp.Storage);
}
/// <summary>
/// Turns the microwave on if its "on" port is activated.
/// </summary>
[SubscribeLocalEvent]
private void OnSignalReceived(Entity<MicrowaveComponent> ent, ref SignalReceivedEvent args)
{
if (ent.Comp.Broken || !_power.IsPowered(ent.Owner))
return;
if (args.Port == ent.Comp.OnPort)
StartCooking(ent, null);
}
/// <summary>
/// Updates the microwave's appearance state.
/// </summary>
/// <param name="ent">The microwave entity.</param>
/// <param name="state">The visual state of the microwave.</param>
private void SetAppearance(Entity<MicrowaveComponent> ent,
MicrowaveVisualState state)
{
var display = ent.Comp.Broken ? MicrowaveVisualState.Broken : state;
Appearance.SetData(ent.Owner,
PowerDeviceVisuals.VisualState,
display);
}
}
[Serializable, NetSerializable]
public enum MicrowaveVisualState
{
Idle,
Cooking,
Broken,
Bloody
}
[NetSerializable, Serializable]
public enum MicrowaveUiKey
{
Key
}