CatStation/Content.Shared/Kitchen/Components/MicrowaveComponent.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

231 lines
7.3 KiB
C#

using Content.Shared.DeviceLinking;
using Content.Shared.Item;
using Content.Shared.Kitchen.EntitySystems;
using Content.Shared.Temperature.Components;
using Content.Shared.Whitelist;
using Robust.Shared.Audio;
using Robust.Shared.Containers;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared.Kitchen.Components;
/// <summary>
/// A component applied to microwaves, which are used to heat entities/solutions
/// and produce microwave recipes.
/// </summary>
[RegisterComponent]
[Access(typeof(MicrowaveSystem))]
[NetworkedComponent, AutoGenerateComponentState(fieldDeltas: true, raiseAfterAutoHandleState: true)]
public sealed partial class MicrowaveComponent : Component
{
/// <summary>
/// A multiplier applied to all microwave cooking timers.
/// </summary>
/// <remarks>
/// If you set a microwave for 30 seconds, but have a CookTimeMultiplier of 0.5,
/// recipes will be processed as if you're portioning for 30 seconds, but the
/// microwave's timer will take 15 seconds instead. So, if you have a recipe with
/// a cookTime of 10 seconds, you can still make that recipe 3 at a time.
///
/// Note that faster cooking times make the microwave less useful for actual heating
/// (temperature) as thermal energy added to the contents is based on elapsed time.
/// </remarks>
[DataField]
public float CookTimeMultiplier = 1;
/// <summary>
/// A multiplier for heat added to the contents of a microwave every cook cycle.
/// </summary>
/// <remarks>
/// The formula is (elapsed time between dt * <see cref="DeltaHeat"/>).
/// </remarks>
[DataField]
public float DeltaHeat = 100;
/// <summary>
/// A multiplier for added heat on entities with a <see cref="TemperatureComponent"/>.
/// </summary>
[DataField]
public float ObjectHeatMultiplier = 100;
/// <summary>
/// An entity that is produced when an item is melted in the microwave.
/// </summary>
/// <remarks>
/// The microwave will burn items that pass the <see cref="BurnWhenCookedWhitelist" />.
/// </remarks>
[DataField]
public EntProtoId FailureResult = "FoodBadRecipe";
#region Audio
/// <summary>
/// A sound that is played when the microwave is activated.
/// </summary>
[DataField]
public SoundSpecifier BeginCookingSound = new SoundPathSpecifier("/Audio/Machines/microwave_start_beep.ogg");
/// <summary>
/// A sound that is played when the microwave finishes.
/// </summary>
/// <remarks>
/// Beep... beep... beep
/// </remarks>
[DataField]
public SoundSpecifier FoodDoneSound = new SoundPathSpecifier("/Audio/Machines/microwave_done_beep.ogg");
/// <summary>
/// A sound that is played when a player navigates the microwave's UI - for example, selecting
/// a new cooking time.
/// </summary>
[DataField]
public SoundSpecifier ClickSound = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg")
{
Params = AudioParams.Default.AddVolume(-2),
};
/// <summary>
/// The humming sound played when a microwave is actively cooking.
/// </summary>
[DataField]
public SoundSpecifier LoopingSound = new SoundPathSpecifier("/Audio/Machines/microwave_loop.ogg");
#endregion Audio
/// <summary>
/// An audio stream for the microwave's "cooking" hum.
/// </summary>
[DataField]
public EntityUid? PlayingStream;
/// <summary>
/// Whether or not this microwave is broken.
/// </summary>
[DataField]
[AutoNetworkedField]
public bool Broken;
/// <summary>
/// A port used to activate the microwave via remote signal.
/// </summary>
[DataField]
public ProtoId<SinkPortPrototype> OnPort = "On";
/// <summary>
/// The currently-selected cook time, in seconds. This must be a multiple of 5 (or 0).
/// </summary>
/// <remarks>
/// The cook times for all recipes should be divisible by 5, with a minimum of 1 second.
/// For right now, I don't think any recipe cook time should be greater than 60 seconds.
/// </remarks>
[DataField]
[AutoNetworkedField]
[Access(typeof(MicrowaveSystem), Other = AccessPermissions.ReadExecute)]
public uint CurrentCookTimerTime;
/// <summary>
/// The index of the currently-selected "cook time" button.
/// </summary>
[DataField]
[AutoNetworkedField]
public int CurrentCookTimeButtonIndex;
/// <summary>
/// The maximum number of seconds a microwave can be set to.
/// This is currently only used for validation and the client does not check this.
/// </summary>
[DataField]
public uint MaxCookTime = 30;
/// <summary>
/// The max temperature that this microwave can heat objects to.
/// </summary>
[DataField]
public float TemperatureUpperThreshold = 373.15f;
/// <summary>
/// The microwave's contents container.
/// </summary>
public Container Storage = default!;
/// <summary>
/// The ID of the storage container for the microwave.
/// </summary>
[DataField]
public string ContainerId = "microwave_entity_container";
/// <summary>
/// How many items the microwave can hold.
/// </summary>
[DataField]
public int Capacity = 10;
/// <summary>
/// The largest item size that can fit in the microwave.
/// </summary>
[DataField]
public ProtoId<ItemSizePrototype> MaxItemSize = "Normal";
/// <summary>
/// How frequently the microwave can malfunction while active.
/// </summary>
[DataField]
public TimeSpan MalfunctionInterval = TimeSpan.FromSeconds(1.0f);
/// <summary>
/// How frequently the microwave can update (process cooking cycle) while active.
/// </summary>
[DataField]
public TimeSpan UpdateInterval = TimeSpan.FromSeconds(1.0f);
/// <summary>
/// Chance of an explosion occurring when we microwave a metallic object.
/// </summary>
/// <remarks>
/// This is rolled every <see cref="MalfunctionInterval"/>.
/// </remarks>
[DataField]
public float ExplosionChance = 0.1f;
/// <summary>
/// Chance of lightning occurring when we microwave a metallic object.
/// </summary>
/// <remarks>
/// This is rolled every <see cref="MalfunctionInterval"/>.
/// </remarks>
[DataField]
public float LightningChance = 0.75f;
/// <summary>
/// If this microwave can give ID cards new accesses without exploding.
/// </summary>
[DataField]
public bool CanMicrowaveIdsSafely = true;
/// <summary>
/// Entities that fulfill this whitelist will cause the microwave to malfunction
/// on activation. By default, this is metal objects.
/// </summary>
[DataField]
public EntityWhitelist? MalfunctionWhenCookedWhitelist = new()
{
Tags = new() { "Metal" }
};
/// <summary>
/// Entities that fulfill this whitelist will create a burned mess when microwaved.
/// By default, this is plastic objects.
/// </summary>
[DataField]
public EntityWhitelist? BurnWhenCookedWhitelist = new()
{
Tags = new() { "Plastic" }
};
/// <summary>
/// A "spark" entity spawned when this microwave malfunctions.
/// </summary>
[DataField]
public EntProtoId MalfunctionSpark = "Spark";
}