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; /// /// A system that handles microwave logic, such as activation, malfunctions, and producing cooked recipes. /// TODO: Replace with a more sophisticated(?) cooking system. /// 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 MicrowaveQuery; [Dependency] protected EntityQuery ActiveMicrowaveQuery; [Dependency] protected EntityQuery ItemQuery; [Dependency] protected EntityQuery StackQuery; public override void Initialize() { base.Initialize(); InitializeUI(); } /// /// Processes every active microwave's ongoing cooking operation. /// public override void Update(float frameTime) { base.Update(frameTime); var curTime = Timing.CurTime; var query = EntityQueryEnumerator(); 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); } } /// /// Adds an "on" port to this microwave. /// [SubscribeLocalEvent] private void OnMapInit(Entity ent, ref MapInitEvent args) { _deviceLink.EnsureSinkPorts(ent, ent.Comp.OnPort); } /// /// 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. /// [SubscribeLocalEvent] private void OnBreak(Entity 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()); } /// /// Stop cooking if the microwave loses power. /// [SubscribeLocalEvent] private void OnPowerChanged(Entity ent, ref PowerChangedEvent args) { if (!args.Powered) { SetAppearance(ent, MicrowaveVisualState.Idle); StopCooking(ent); } UpdateUI(ent.AsNullable()); } /// /// Empty the microwave if it is unanchored. /// [SubscribeLocalEvent] private void OnAnchorChanged(Entity ent, ref AnchorStateChangedEvent args) { if (!args.Anchored) Container.EmptyContainer(ent.Comp.Storage); } /// /// Turns the microwave on if its "on" port is activated. /// [SubscribeLocalEvent] private void OnSignalReceived(Entity ent, ref SignalReceivedEvent args) { if (ent.Comp.Broken || !_power.IsPowered(ent.Owner)) return; if (args.Port == ent.Comp.OnPort) StartCooking(ent, null); } /// /// Updates the microwave's appearance state. /// /// The microwave entity. /// The visual state of the microwave. private void SetAppearance(Entity 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 }