diff --git a/Content.Client/EntryPoint.cs b/Content.Client/EntryPoint.cs index bed89711c9..7604f3e8e9 100644 --- a/Content.Client/EntryPoint.cs +++ b/Content.Client/EntryPoint.cs @@ -16,6 +16,7 @@ using Content.Shared.GameObjects.Components.Gravity; using Content.Shared.GameObjects.Components.Markers; using Content.Shared.GameObjects.Components.Research; using Content.Shared.GameObjects.Components.VendingMachines; +using Content.Shared.Kitchen; using Robust.Client; using Robust.Client.Interfaces; using Robust.Client.Interfaces.Graphics.Overlays; @@ -143,7 +144,7 @@ namespace Content.Client "Mop", "Bucket", "Puddle", - "CanSpill", + "CanSpill" }; foreach (var ignoreName in registerIgnore) @@ -161,7 +162,7 @@ namespace Content.Client factory.Register(); factory.Register(); factory.Register(); - + factory.Register(); factory.Register(); prototypes.RegisterIgnore("material"); diff --git a/Content.Client/GameObjects/Components/Kitchen/MicrowaveBoundUserInterface.cs b/Content.Client/GameObjects/Components/Kitchen/MicrowaveBoundUserInterface.cs new file mode 100644 index 0000000000..e93d016806 --- /dev/null +++ b/Content.Client/GameObjects/Components/Kitchen/MicrowaveBoundUserInterface.cs @@ -0,0 +1,119 @@ +using Robust.Client.GameObjects.Components.UserInterface; +using Content.Shared.Kitchen; +using Robust.Shared.GameObjects.Components.UserInterface; +using Robust.Shared.IoC; +using Robust.Shared.Prototypes; +using Content.Shared.Chemistry; +using Robust.Shared.GameObjects; +using System.Collections.Generic; +using Robust.Shared.Interfaces.GameObjects; + + +using Robust.Client.GameObjects; +using Robust.Client.UserInterface.Controls; + +namespace Content.Client.GameObjects.Components.Kitchen +{ + public class MicrowaveBoundUserInterface : BoundUserInterface + { +#pragma warning disable 649 + [Dependency] private readonly IEntityManager _entityManager; + [Dependency] private readonly IPrototypeManager _prototypeManager; +#pragma warning restore 649 + private MicrowaveMenu _menu; + + private Dictionary _solids = new Dictionary(); + private Dictionary _reagents =new Dictionary(); + + public MicrowaveBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner,uiKey) + { + + } + + protected override void Open() + { + base.Open(); + _menu = new MicrowaveMenu(this); + _menu.OpenCentered(); + _menu.OnClose += Close; + _menu.StartButton.OnPressed += args => SendMessage(new SharedMicrowaveComponent.MicrowaveStartCookMessage()); + _menu.EjectButton.OnPressed += args => SendMessage(new SharedMicrowaveComponent.MicrowaveEjectMessage()); + _menu.IngredientsList.OnItemSelected += args => + { + SendMessage(new SharedMicrowaveComponent.MicrowaveEjectSolidIndexedMessage(_solids[args.ItemIndex])); + + }; + + _menu.IngredientsListReagents.OnItemSelected += args => + { + SendMessage( + new SharedMicrowaveComponent.MicrowaveVaporizeReagentIndexedMessage(_reagents[args.ItemIndex])); + }; + + _menu.OnCookTimeSelected += args => + { + var actualButton = args.Button as Button; + var newTime = (uint) int.Parse(actualButton.Text); + _menu.VisualCookTime = newTime; + SendMessage(new SharedMicrowaveComponent.MicrowaveSelectCookTimeMessage(newTime)); + }; + + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + { + return; + } + _solids?.Clear(); + _menu?.Dispose(); + } + + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + if (!(state is MicrowaveUpdateUserInterfaceState cstate)) + { + return; + } + + RefreshContentsDisplay(cstate.ReagentsReagents, cstate.ContainedSolids); + + } + + + private void RefreshContentsDisplay(IReadOnlyList reagents, List solids) + { + _reagents.Clear(); + _menu.IngredientsListReagents.Clear(); + foreach (var reagent in reagents) + { + _prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto); + var reagentAdded = _menu.IngredientsListReagents.AddItem($"{reagent.Quantity} {proto.Name}"); + var reagentIndex = _menu.IngredientsListReagents.IndexOf(reagentAdded); + _reagents.Add(reagentIndex, reagent); + } + + _solids.Clear(); + _menu.IngredientsList.Clear(); + foreach (var entityID in solids) + { + var entity = _entityManager.GetEntity(entityID); + + if (entity.TryGetComponent(out IconComponent icon)) + { + var solidItem = _menu.IngredientsList.AddItem(entity.Name, icon.Icon.Default); + + var solidIndex = _menu.IngredientsList.IndexOf(solidItem); + _solids.Add(solidIndex, entityID); + } + + + } + + } + } +} diff --git a/Content.Client/GameObjects/Components/Kitchen/MicrowaveMenu.cs b/Content.Client/GameObjects/Components/Kitchen/MicrowaveMenu.cs new file mode 100644 index 0000000000..a2a9e02625 --- /dev/null +++ b/Content.Client/GameObjects/Components/Kitchen/MicrowaveMenu.cs @@ -0,0 +1,206 @@ +using System; +using Robust.Client.Graphics.Drawing; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.Localization; +using Robust.Shared.Maths; + +namespace Content.Client.GameObjects.Components.Kitchen +{ + public class MicrowaveMenu : SS14Window + { + protected override Vector2? CustomSize => (512, 256); + + private MicrowaveBoundUserInterface Owner { get; set; } + + public event Action OnCookTimeSelected; + + public uint VisualCookTime = 1; + + public Button StartButton { get;} + public Button EjectButton { get;} + + public PanelContainer TimerFacePlate { get; } + + public ButtonGroup CookTimeButtonGroup { get; } + private VBoxContainer CookTimeButtonVbox { get; } + + public ItemList IngredientsList { get;} + + public ItemList IngredientsListReagents { get; } + private Label _cookTimeInfoLabel { get; } + + public MicrowaveMenu(MicrowaveBoundUserInterface owner = null) + { + Owner = owner; + Title = Loc.GetString("Microwave"); + var hSplit = new HBoxContainer + { + SizeFlagsHorizontal = SizeFlags.Fill, + SizeFlagsVertical = SizeFlags.Fill + }; + + IngredientsListReagents = new ItemList + { + SizeFlagsVertical = SizeFlags.FillExpand, + SizeFlagsHorizontal = SizeFlags.FillExpand, + SelectMode = ItemList.ItemListSelectMode.Button, + SizeFlagsStretchRatio = 2, + CustomMinimumSize = (100,128) + }; + + IngredientsList = new ItemList + { + SizeFlagsVertical = SizeFlags.FillExpand, + SizeFlagsHorizontal = SizeFlags.FillExpand, + SelectMode = ItemList.ItemListSelectMode.Button, + SizeFlagsStretchRatio = 2, + CustomMinimumSize = (100,128) + }; + + hSplit.AddChild(IngredientsListReagents); + //Padding between the lists. + hSplit.AddChild(new Control + { + CustomMinimumSize = (0,5), + }); + + hSplit.AddChild(IngredientsList); + + var vSplit = new VBoxContainer + { + SizeFlagsVertical = SizeFlags.FillExpand, + SizeFlagsHorizontal = SizeFlags.FillExpand, + }; + + hSplit.AddChild(vSplit); + + var buttonGridContainer = new VBoxContainer + { + Align = BoxContainer.AlignMode.Center, + SizeFlagsStretchRatio = 3 + }; + + StartButton = new Button + { + Text = Loc.GetString("Start"), + TextAlign = Label.AlignMode.Center, + + }; + + EjectButton = new Button + { + Text = Loc.GetString("Eject All Contents"), + ToolTip = Loc.GetString("This vaporizes all reagents, but ejects any solids."), + TextAlign = Label.AlignMode.Center, + }; + + buttonGridContainer.AddChild(StartButton); + buttonGridContainer.AddChild(EjectButton); + vSplit.AddChild(buttonGridContainer); + + //Padding + vSplit.AddChild(new Control + { + CustomMinimumSize = (0, 15), + SizeFlagsVertical = SizeFlags.Fill, + }); + + CookTimeButtonGroup = new ButtonGroup(); + CookTimeButtonVbox = new VBoxContainer + { + SizeFlagsVertical = SizeFlags.FillExpand, + Align = BoxContainer.AlignMode.Center, + }; + + var index = 0; + for (var i = 0; i <= 12; i++) + { + var newButton = new Button + { + Text = (index <= 0 ? 1 : index).ToString(), + TextAlign = Label.AlignMode.Center, + Group = CookTimeButtonGroup, + }; + CookTimeButtonVbox.AddChild(newButton); + newButton.OnPressed += args => + { + OnCookTimeSelected?.Invoke(args); + _cookTimeInfoLabel.Text = $"{Loc.GetString("COOK TIME")}: {VisualCookTime}"; + }; + index+=5; + } + + var cookTimeOneSecondButton = (Button)CookTimeButtonVbox.GetChild(0); + cookTimeOneSecondButton.Pressed = true; + + _cookTimeInfoLabel = new Label + { + Text = Loc.GetString($"COOK TIME: {VisualCookTime}"), + Align = Label.AlignMode.Center, + Modulate = Color.White, + SizeFlagsVertical = SizeFlags.ShrinkCenter + }; + + var innerTimerPanel = new PanelContainer + { + SizeFlagsVertical = SizeFlags.FillExpand, + ModulateSelfOverride = Color.Red, + CustomMinimumSize = (100, 128), + PanelOverride = new StyleBoxFlat {BackgroundColor = Color.Black.WithAlpha(0.5f)}, + + Children = + { + + new VBoxContainer + { + + Children = + { + + new PanelContainer + { + PanelOverride = new StyleBoxFlat(){BackgroundColor = Color.Gray.WithAlpha(0.2f)}, + + Children = + { + _cookTimeInfoLabel + } + }, + + new ScrollContainer() + { + SizeFlagsVertical = SizeFlags.FillExpand, + + Children = + { + CookTimeButtonVbox, + } + }, + + } + } + + + } + }; + + TimerFacePlate = new PanelContainer() + { + SizeFlagsVertical = SizeFlags.FillExpand, + SizeFlagsHorizontal = SizeFlags.FillExpand, + Children = + { + + innerTimerPanel + }, + }; + + vSplit.AddChild(TimerFacePlate); + Contents.AddChild(hSplit); + + } + + } +} diff --git a/Content.Client/GameObjects/Components/Kitchen/MicrowaveVisualizer.cs b/Content.Client/GameObjects/Components/Kitchen/MicrowaveVisualizer.cs new file mode 100644 index 0000000000..1591670f16 --- /dev/null +++ b/Content.Client/GameObjects/Components/Kitchen/MicrowaveVisualizer.cs @@ -0,0 +1,67 @@ +using Content.Client.GameObjects.Components.Sound; +using Content.Shared.GameObjects.Components.Power; +using Content.Shared.GameObjects.Components.Sound; +using Content.Shared.Kitchen; +using Robust.Client.GameObjects; +using Robust.Client.Interfaces.GameObjects.Components; +using Robust.Shared.Audio; +using Robust.Shared.Log; + + +namespace Content.Client.GameObjects.Components.Kitchen +{ + public sealed class MicrowaveVisualizer : AppearanceVisualizer + { + private SoundComponent _soundComponent; + private const string MicrowaveSoundLoop = "/Audio/machines/microwave_loop.ogg"; + + public override void OnChangeData(AppearanceComponent component) + { + base.OnChangeData(component); + var sprite = component.Owner.GetComponent(); + _soundComponent ??= component.Owner.GetComponent(); + if (!component.TryGetData(PowerDeviceVisuals.VisualState, out MicrowaveVisualState state)) + { + state = MicrowaveVisualState.Idle; + } + switch (state) + { + case MicrowaveVisualState.Idle: + sprite.LayerSetState(MicrowaveVisualizerLayers.Base, "mw"); + sprite.LayerSetState(MicrowaveVisualizerLayers.BaseUnlit, "mw_unlit"); + _soundComponent.StopAllSounds(); + break; + + case MicrowaveVisualState.Cooking: + sprite.LayerSetState(MicrowaveVisualizerLayers.Base, "mw"); + sprite.LayerSetState(MicrowaveVisualizerLayers.BaseUnlit, "mw_running_unlit"); + var audioParams = AudioParams.Default; + audioParams.Loop = true; + var schedSound = new ScheduledSound(); + schedSound.Filename = MicrowaveSoundLoop; + schedSound.AudioParams = audioParams; + _soundComponent.AddScheduledSound(schedSound); + break; + + default: + Logger.Debug($"Something terrible happened in {this}"); + break; + + } + + var glowingPartsVisible = !(component.TryGetData(PowerDeviceVisuals.Powered, out bool powered) && !powered); + sprite.LayerSetVisible(MicrowaveVisualizerLayers.BaseUnlit, glowingPartsVisible); + + + } + + + private enum MicrowaveVisualizerLayers + { + Base, + BaseUnlit + } + } + + +} diff --git a/Content.Client/GameObjects/Components/Sound/SoundComponent.cs b/Content.Client/GameObjects/Components/Sound/SoundComponent.cs index c36f79fe83..076ac902a6 100644 --- a/Content.Client/GameObjects/Components/Sound/SoundComponent.cs +++ b/Content.Client/GameObjects/Components/Sound/SoundComponent.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; +using System.Linq; using Content.Shared.GameObjects.Components.Sound; +using Microsoft.DiaSymReader; using Robust.Client.GameObjects.EntitySystems; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; @@ -15,7 +17,7 @@ namespace Content.Client.GameObjects.Components.Sound [RegisterComponent] public class SoundComponent : SharedSoundComponent { - private readonly List _schedules = new List(); + private readonly Dictionary _audioStreams = new Dictionary(); private AudioSystem _audioSystem; #pragma warning disable 649 [Dependency] private readonly IRobustRandom _random; @@ -23,26 +25,27 @@ namespace Content.Client.GameObjects.Components.Sound public override void StopAllSounds() { - foreach (var schedule in _schedules) + foreach (var kvp in _audioStreams) { - schedule.Play = false; + kvp.Key.Play = false; + kvp.Value.Stop(); } - _schedules.Clear(); + _audioStreams.Clear(); } public override void StopScheduledSound(string filename) { - foreach (var schedule in _schedules.ToArray()) + foreach (var kvp in _audioStreams) { - if (schedule.Filename != filename) continue; - schedule.Play = false; - _schedules.Remove(schedule); + if (kvp.Key.Filename != filename) continue; + kvp.Key.Play = false; + kvp.Value.Stop(); + _audioStreams.Remove(kvp.Key); } } public override void AddScheduledSound(ScheduledSound schedule) { - _schedules.Add(schedule); Play(schedule); } @@ -54,16 +57,11 @@ namespace Content.Client.GameObjects.Components.Sound { if (!schedule.Play) return; // We make sure this hasn't changed. if (_audioSystem == null) _audioSystem = IoCManager.Resolve().GetEntitySystem(); - _audioSystem.Play(schedule.Filename, Owner, schedule.AudioParams); + _audioStreams.Add(schedule,_audioSystem.Play(schedule.Filename, Owner, schedule.AudioParams)); - if (schedule.Times == 0) - { - _schedules.Remove(schedule); - return; - } + if (schedule.Times == 0) return; - if (schedule.Times > 0) - schedule.Times--; + if (schedule.Times > 0) schedule.Times--; Play(schedule); }); diff --git a/Content.Server/EntryPoint.cs b/Content.Server/EntryPoint.cs index 7a97e2f538..6eb0c31d8c 100644 --- a/Content.Server/EntryPoint.cs +++ b/Content.Server/EntryPoint.cs @@ -4,6 +4,7 @@ using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.GameTicking; using Content.Server.Preferences; using Content.Server.Sandbox; +using Content.Shared.Kitchen; using Robust.Server.Interfaces.Player; using Robust.Shared.ContentPack; using Robust.Shared.Interfaces.GameObjects; @@ -70,6 +71,7 @@ namespace Content.Server logManager.GetSawmill("Storage").Level = LogLevel.Info; IoCManager.Resolve().StartInit(); + } public override void PostInit() @@ -79,6 +81,7 @@ namespace Content.Server _gameTicker.Initialize(); IoCManager.Resolve().Initialize(); IoCManager.Resolve().FinishInit(); + IoCManager.Resolve().Initialize(); } public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs) diff --git a/Content.Server/GameObjects/Components/Kitchen/KitchenMicrowaveComponent.cs b/Content.Server/GameObjects/Components/Kitchen/KitchenMicrowaveComponent.cs new file mode 100644 index 0000000000..ac6ab14c65 --- /dev/null +++ b/Content.Server/GameObjects/Components/Kitchen/KitchenMicrowaveComponent.cs @@ -0,0 +1,408 @@ +using System.Collections.Generic; +using System.Linq; +using Content.Server.GameObjects.EntitySystems; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.ViewVariables; +using Content.Server.GameObjects.Components.Chemistry; +using Content.Server.GameObjects.Components.Nutrition; +using Content.Shared.Chemistry; +using Robust.Shared.Serialization; +using Robust.Shared.Interfaces.GameObjects; +using Content.Shared.Prototypes.Kitchen; +using Content.Shared.Kitchen; +using Robust.Shared.Timers; +using Robust.Server.GameObjects; +using Content.Shared.GameObjects.Components.Power; +using Robust.Server.GameObjects.EntitySystems; +using Robust.Server.GameObjects.Components.Container; +using Content.Server.GameObjects.Components.Power; +using Robust.Server.GameObjects.Components.UserInterface; +using Robust.Server.Interfaces.GameObjects; +using Robust.Shared.Prototypes; +using Robust.Shared.Localization; +using Content.Server.Interfaces; +using Robust.Shared.Audio; +using YamlDotNet.Serialization.NodeTypeResolvers; + +namespace Content.Server.GameObjects.Components.Kitchen +{ + [RegisterComponent] + [ComponentReference(typeof(IActivate))] + public class KitchenMicrowaveComponent : SharedMicrowaveComponent, IActivate, IAttackBy, ISolutionChange + { +#pragma warning disable 649 + [Dependency] private readonly IEntitySystemManager _entitySystemManager; + [Dependency] private readonly IEntityManager _entityManager; + [Dependency] private readonly RecipeManager _recipeManager; + [Dependency] private readonly IServerNotifyManager _notifyManager; +#pragma warning restore 649 + +#region YAMLSERIALIZE + private int _cookTimeDefault; + private int _cookTimeMultiplier; //For upgrades and stuff I guess? + private string _badRecipeName; + private string _startCookingSound; + private string _cookingCompleteSound; +#endregion + +#region VIEWVARIABLES + [ViewVariables] + private SolutionComponent _solution; + + [ViewVariables] + private bool _busy = false; + + /// + /// This is a fixed offset of 5. + /// 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. + /// + [ViewVariables] + private uint _currentCookTimerTime { get; set; } = 1; +#endregion + + private bool Powered => _powerDevice.Powered; + + private bool HasContents => _solution.ReagentList.Count > 0 || _storage.ContainedEntities.Count > 0; + + void ISolutionChange.SolutionChanged(SolutionChangeEventArgs eventArgs) => UpdateUserInterface(); + + private AudioSystem _audioSystem; + + private AppearanceComponent _appearance; + private PowerDeviceComponent _powerDevice; + + private BoundUserInterface _userInterface; + + private Container _storage; + + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + serializer.DataField(ref _badRecipeName, "failureResult", "FoodBadRecipe"); + serializer.DataField(ref _cookTimeDefault, "cookTime", 5); + serializer.DataField(ref _cookTimeMultiplier, "cookTimeMultiplier", 1000); + serializer.DataField(ref _startCookingSound, "beginCookingSound","/Audio/machines/microwave_start_beep.ogg" ); + serializer.DataField(ref _cookingCompleteSound, "foodDoneSound","/Audio/machines/microwave_done_beep.ogg" ); + } + + public override void Initialize() + { + base.Initialize(); + _solution ??= Owner.TryGetComponent(out SolutionComponent solutionComponent) + ? solutionComponent + : Owner.AddComponent(); + + _storage = ContainerManagerComponent.Ensure("microwave_entity_container", Owner, out var existed); + _appearance = Owner.GetComponent(); + _powerDevice = Owner.GetComponent(); + _audioSystem = _entitySystemManager.GetEntitySystem(); + _userInterface = Owner.GetComponent() + .GetBoundUserInterface(MicrowaveUiKey.Key); + + _userInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage; + } + + private void UserInterfaceOnReceiveMessage(ServerBoundUserInterfaceMessage message) + { + if (!Powered || _busy) + { + return; + } + + switch (message.Message) + { + case MicrowaveStartCookMessage msg : + wzhzhzh(); + break; + + case MicrowaveEjectMessage msg : + if (HasContents) + { + VaporizeReagents(); + EjectSolids(); + ClickSound(); + UpdateUserInterface(); + } + + break; + + case MicrowaveEjectSolidIndexedMessage msg: + if (HasContents) + { + EjectSolidWithIndex(msg.EntityID); + ClickSound(); + UpdateUserInterface(); + } + break; + + case MicrowaveVaporizeReagentIndexedMessage msg: + if (HasContents) + { + VaporizeReagentWithReagentQuantity(msg.ReagentQuantity); + ClickSound(); + UpdateUserInterface(); + } + break; + + case MicrowaveSelectCookTimeMessage msg: + _currentCookTimerTime = msg.newCookTime; + ClickSound(); + UpdateUserInterface(); + break; + } + + } + + private void SetAppearance(MicrowaveVisualState state) + { + if (_appearance != null || Owner.TryGetComponent(out _appearance)) + { + _appearance.SetData(PowerDeviceVisuals.VisualState, state); + } + + } + + private void UpdateUserInterface() + { + var solidsVisualList = new List(); + foreach(var item in _storage.ContainedEntities) + { + solidsVisualList.Add(item.Uid); + } + + _userInterface.SetState(new MicrowaveUpdateUserInterfaceState(_solution.Solution.Contents, solidsVisualList)); + } + + void IActivate.Activate(ActivateEventArgs eventArgs) + { + if (!eventArgs.User.TryGetComponent(out IActorComponent actor) || !Powered) + { + return; + } + UpdateUserInterface(); + _userInterface.Open(actor.playerSession); + + } + + public bool AttackBy(AttackByEventArgs eventArgs) + { + var itemEntity = eventArgs.User.GetComponent().GetActiveHand.Owner; + + if(itemEntity.TryGetComponent(out var attackPourable)) + { + //Get target and check if it can be poured into + if (!Owner.TryGetComponent(out var mySolution) + || !mySolution.CanPourIn) + { + return false; + } + + if (!itemEntity.TryGetComponent(out var attackSolution) + || !attackSolution.CanPourOut) + { + return false; + } + + //Get transfer amount. May be smaller than _transferAmount if not enough room + var realTransferAmount = ReagentUnit.Min(attackPourable.TransferAmount, mySolution.EmptyVolume); + if (realTransferAmount <= 0) //Special message if container is full + { + _notifyManager.PopupMessage(Owner.Transform.GridPosition, eventArgs.User, + Loc.GetString("Container is full")); + return false; + } + + //Move units from attackSolution to targetSolution + var removedSolution = attackSolution.SplitSolution(realTransferAmount); + if (!mySolution.TryAddSolution(removedSolution)) + { + return false; + } + + _notifyManager.PopupMessage(Owner.Transform.GridPosition, eventArgs.User, + Loc.GetString("Transferred {0}u", removedSolution.TotalVolume)); + return true; + } + + if (!itemEntity.TryGetComponent(typeof(FoodComponent), out var food)) + { + return false; + } + + var ent = food.Owner; //Get the entity of the ItemComponent. + _storage.Insert(ent); + UpdateUserInterface(); + return true; + + } + + //This is required. It's 'cook'. + private void wzhzhzh() + { + if (!HasContents) + { + return; + } + + _busy = true; + // Convert storage into Dictionary of ingredients + var solidsDict = new Dictionary(); + foreach(var item in _storage.ContainedEntities) + { + if(solidsDict.ContainsKey(item.Prototype.ID)) + { + solidsDict[item.Prototype.ID]++; + } + else + { + solidsDict.Add(item.Prototype.ID, 1); + } + } + + // Check recipes + FoodRecipePrototype recipeToCook = null; + foreach(var r in _recipeManager.Recipes) + { + if (!CanSatisfyRecipe(r, solidsDict)) + { + continue; + } + + recipeToCook = r; + } + + var goodMeal = (recipeToCook != null) + && + (_currentCookTimerTime == (uint)recipeToCook.CookTime) ? true : false; + + SetAppearance(MicrowaveVisualState.Cooking); + _audioSystem.Play(_startCookingSound); + Timer.Spawn((int)(_currentCookTimerTime * _cookTimeMultiplier), () => + { + + if (goodMeal) + { + SubtractContents(recipeToCook); + } + else + { + VaporizeReagents(); + VaporizeSolids(); + } + + var entityToSpawn = goodMeal ? recipeToCook.Result : _badRecipeName; + _entityManager.SpawnEntity(entityToSpawn, Owner.Transform.GridPosition); + _audioSystem.Play(_cookingCompleteSound); + SetAppearance(MicrowaveVisualState.Idle); + _busy = false; + }); + UpdateUserInterface(); + return; + } + + private void VaporizeReagents() + { + _solution.RemoveAllSolution(); + } + + private void VaporizeReagentWithReagentQuantity(Solution.ReagentQuantity reagentQuantity) + { + _solution.TryRemoveReagent(reagentQuantity.ReagentId, reagentQuantity.Quantity); + } + + private void VaporizeSolids() + { + for(var i = _storage.ContainedEntities.Count-1; i>=0; i--) + { + var item = _storage.ContainedEntities.ElementAt(i); + _storage.Remove(item); + item.Delete(); + } + } + + private void EjectSolids() + { + + for(var i = _storage.ContainedEntities.Count-1; i>=0; i--) + { + _storage.Remove(_storage.ContainedEntities.ElementAt(i)); + } + } + + private void EjectSolidWithIndex(EntityUid entityID) + { + if (_entityManager.EntityExists(entityID)) + { + _storage.Remove(_entityManager.GetEntity(entityID)); + } + } + + + private void SubtractContents(FoodRecipePrototype recipe) + { + foreach(var recipeReagent in recipe.IngredientsReagents) + { + _solution.TryRemoveReagent(recipeReagent.Key, ReagentUnit.New(recipeReagent.Value)); + } + + foreach (var recipeSolid in recipe.IngredientsSolids) + { + for (var i = 0; i < recipeSolid.Value; i++) + { + foreach (var item in _storage.ContainedEntities) + { + if (item.Prototype.ID == recipeSolid.Key) + { + _storage.Remove(item); + item.Delete(); + break; + } + } + } + } + + } + + private bool CanSatisfyRecipe(FoodRecipePrototype recipe, Dictionary solids) + { + foreach (var reagent in recipe.IngredientsReagents) + { + if (!_solution.ContainsReagent(reagent.Key, out var amount)) + { + return false; + } + + if (amount.Int() < reagent.Value) + { + return false; + } + } + + foreach (var solid in recipe.IngredientsSolids) + { + if (!solids.ContainsKey(solid.Key)) + { + return false; + } + + if (solids[solid.Key] < solid.Value) + { + return false; + } + } + + return true; + } + + private void ClickSound() + { + + _audioSystem.Play("/Audio/machines/machine_switch.ogg", AudioParams.Default.WithVolume(-2f)); + + } + + } +} diff --git a/Content.Server/ServerContentIoC.cs b/Content.Server/ServerContentIoC.cs index f4bb04b9cc..7ca422e4c4 100644 --- a/Content.Server/ServerContentIoC.cs +++ b/Content.Server/ServerContentIoC.cs @@ -8,6 +8,7 @@ using Content.Server.Preferences; using Content.Server.Sandbox; using Content.Server.Utility; using Content.Shared.Chemistry; +using Content.Shared.Kitchen; using Content.Shared.Interfaces; using Content.Shared.Interfaces.Chemistry; using Robust.Shared.IoC; @@ -28,6 +29,7 @@ namespace Content.Server IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); + IoCManager.Register(); } } } diff --git a/Content.Shared/GameObjects/ContentNetIDs.cs b/Content.Shared/GameObjects/ContentNetIDs.cs index 28ef999efc..854628acc0 100644 --- a/Content.Shared/GameObjects/ContentNetIDs.cs +++ b/Content.Shared/GameObjects/ContentNetIDs.cs @@ -42,6 +42,7 @@ public const uint PAPER = 1037; public const uint REAGENT_INJECTOR = 1038; public const uint GHOST = 1039; - public const uint GRAVITY_GENERATOR = 1040; + public const uint MICROWAVE = 1040; + public const uint GRAVITY_GENERATOR = 1041; } } diff --git a/Content.Shared/Kitchen/RecipeManager.cs b/Content.Shared/Kitchen/RecipeManager.cs new file mode 100644 index 0000000000..5ac01ad64f --- /dev/null +++ b/Content.Shared/Kitchen/RecipeManager.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using Content.Shared.Prototypes.Kitchen; +using Robust.Shared.IoC; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Kitchen +{ + + public class RecipeManager + { +#pragma warning disable 649 + [Dependency] private readonly IPrototypeManager _prototypeManager; +#pragma warning restore 649 + public List Recipes { get; private set; } + + public void Initialize() + { + Recipes = new List(); + foreach (var item in _prototypeManager.EnumeratePrototypes()) + { + Recipes.Add(item); + } + + Recipes.Sort(new RecipeComparer()); + } + private class RecipeComparer : Comparer + { + public override int Compare(FoodRecipePrototype x, FoodRecipePrototype y) + { + if (x == null || y == null) + { + return 0; + } + + return -x.IngredientsReagents.Count.CompareTo(y.IngredientsReagents.Count); + } + } + } +} diff --git a/Content.Shared/Kitchen/SharedMicrowaveComponent.cs b/Content.Shared/Kitchen/SharedMicrowaveComponent.cs new file mode 100644 index 0000000000..31349c86b5 --- /dev/null +++ b/Content.Shared/Kitchen/SharedMicrowaveComponent.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using Content.Shared.Chemistry; +using Content.Shared.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.Serialization; +using Robust.Shared.GameObjects.Components.UserInterface; + +namespace Content.Shared.Kitchen +{ + + public class SharedMicrowaveComponent : Component + { + + public override string Name => "Microwave"; + public override uint? NetID => ContentNetIDs.MICROWAVE; + + [Serializable, NetSerializable] + public class MicrowaveStartCookMessage : BoundUserInterfaceMessage + { + public MicrowaveStartCookMessage() + { + } + } + + [Serializable, NetSerializable] + public class MicrowaveEjectMessage : BoundUserInterfaceMessage + { + public MicrowaveEjectMessage() + { + } + } + + [Serializable, NetSerializable] + public class MicrowaveEjectSolidIndexedMessage : BoundUserInterfaceMessage + { + + public EntityUid EntityID; + public MicrowaveEjectSolidIndexedMessage(EntityUid entityID) + { + EntityID = entityID; + } + } + + [Serializable, NetSerializable] + public class MicrowaveVaporizeReagentIndexedMessage : BoundUserInterfaceMessage + { + + public Solution.ReagentQuantity ReagentQuantity; + public MicrowaveVaporizeReagentIndexedMessage(Solution.ReagentQuantity reagentQuantity) + { + ReagentQuantity = reagentQuantity; + } + } + [Serializable, NetSerializable] + public class MicrowaveSelectCookTimeMessage : BoundUserInterfaceMessage + { + public uint newCookTime; + public MicrowaveSelectCookTimeMessage(uint inputTime) + { + newCookTime = inputTime; + } + } + } + + + + [NetSerializable, Serializable] + public class MicrowaveUpdateUserInterfaceState : BoundUserInterfaceState + { + public readonly IReadOnlyList ReagentsReagents; + public readonly List ContainedSolids; + public MicrowaveUpdateUserInterfaceState(IReadOnlyList reagents, List solids) + { + ReagentsReagents = reagents; + ContainedSolids = solids; + } + } + + [Serializable, NetSerializable] + public enum MicrowaveVisualState + { + Idle, + Cooking + } + + [NetSerializable, Serializable] + public enum MicrowaveUiKey + { + Key + } + +} diff --git a/Content.Shared/Prototypes/Kitchen/MicrowaveMealRecipePrototype.cs b/Content.Shared/Prototypes/Kitchen/MicrowaveMealRecipePrototype.cs new file mode 100644 index 0000000000..0d64a7d073 --- /dev/null +++ b/Content.Shared/Prototypes/Kitchen/MicrowaveMealRecipePrototype.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Robust.Shared.Localization; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; +using YamlDotNet.RepresentationModel; + +namespace Content.Shared.Prototypes.Kitchen +{ + /// + /// A recipe for space microwaves. + /// + + [Prototype("microwaveMealRecipe")] + + public class FoodRecipePrototype : IPrototype, IIndexedPrototype + { + + private string _id; + private string _name; + private string _result; + private int _cookTime; + + private Dictionary _ingsReagents; + private Dictionary _ingsSolids; + + public string Name => Loc.GetString(_name); + public string ID => _id; + public string Result => _result; + public int CookTime => _cookTime; + public IReadOnlyDictionary IngredientsReagents => _ingsReagents; + public IReadOnlyDictionary IngredientsSolids => _ingsSolids; + + + public void LoadFrom(YamlMappingNode mapping) + { + var serializer = YamlObjectSerializer.NewReader(mapping); + + serializer.DataField(ref _id, "id", string.Empty); + serializer.DataField(ref _name, "name", string.Empty); + serializer.DataField(ref _result, "result", string.Empty); + serializer.DataField(ref _ingsReagents, "reagents", new Dictionary()); + serializer.DataField(ref _ingsSolids, "solids", new Dictionary()); + serializer.DataField(ref _cookTime, "time", 5); + } + + } +} diff --git a/Resources/Audio/machines/microwave_done_beep.ogg b/Resources/Audio/machines/microwave_done_beep.ogg new file mode 100644 index 0000000000..e11bd45107 Binary files /dev/null and b/Resources/Audio/machines/microwave_done_beep.ogg differ diff --git a/Resources/Audio/machines/microwave_loop.ogg b/Resources/Audio/machines/microwave_loop.ogg new file mode 100644 index 0000000000..d72097e73b Binary files /dev/null and b/Resources/Audio/machines/microwave_loop.ogg differ diff --git a/Resources/Audio/machines/microwave_start_beep.ogg b/Resources/Audio/machines/microwave_start_beep.ogg new file mode 100644 index 0000000000..43f6c24660 Binary files /dev/null and b/Resources/Audio/machines/microwave_start_beep.ogg differ diff --git a/Resources/Prototypes/Entities/Items/Consumables/food.yml b/Resources/Prototypes/Entities/Items/Consumables/food.yml index 8e6dd97175..d07c9a4fe9 100644 --- a/Resources/Prototypes/Entities/Items/Consumables/food.yml +++ b/Resources/Prototypes/Entities/Items/Consumables/food.yml @@ -90,7 +90,7 @@ # name: Ambrosia vulgar is crushed # parent: FoodBase # id: FoodAmbrosiaVulgarIsCrushed -# description: +# description: # components: # - type: Food # uses: 1 @@ -137,7 +137,7 @@ # name: Bacon # parent: FoodBase # id: FoodBacon -# description: +# description: # components: # - type: Food # uses: 1 @@ -182,7 +182,7 @@ name: Bread (slice) parent: FoodBase id: FoodBreadSlice - description: + description: components: - type: Food contents: @@ -199,7 +199,7 @@ name: Banana bread (slice) parent: FoodBase id: FoodBananaBreadSlice - description: + description: components: - type: Food contents: @@ -233,7 +233,7 @@ # name: Bear meat # parent: FoodBase # id: FoodBearMeat -# description: +# description: # components: # - type: Food # uses: 1 @@ -612,7 +612,7 @@ # name: Cocoa # parent: FoodBase # id: FoodCocoa -# description: +# description: # components: # - type: Food # uses: 1 @@ -1482,11 +1482,11 @@ - type: Icon sprite: Objects/Food/loadedbakedpotato.rsi -#- type: entity +# - type: entity # parent: FoodBase # id: FoodMeat # name: Meat -# description: '' +# description: A slab of meat. # components: # - type: Food # uses: 1 @@ -2865,3 +2865,20 @@ sprite: Objects/Food/xenomeatpie.rsi - type: Icon sprite: Objects/Food/xenomeatpie.rsi + +- type: entity + parent: FoodBase + id: DisgustingSweptSoup + name: Salty Sweet Miso Cola Soup + description: Jesus christ. + components: + - type: Food + contents: + reagents: + - ReagentId: chem.Bleach + Quantity: 15 + spawn_on_finish: TrashSnackBowl + - type: Sprite + sprite: Objects/Food/stew.rsi + - type: Icon + sprite: Objects/Food/stew.rsi diff --git a/Resources/Prototypes/Entities/kitchen.yml b/Resources/Prototypes/Entities/kitchen.yml new file mode 100644 index 0000000000..f517051c87 --- /dev/null +++ b/Resources/Prototypes/Entities/kitchen.yml @@ -0,0 +1,40 @@ +- type: entity + id: KitchenMicrowave + name: Microwave + description: It's magic. + components: + - type: Microwave + - type: Clickable + - type: InteractionOutline + - type: Solution + maxVol: 100 + caps: 1 + - type: Appearance + visuals: + - type: MicrowaveVisualizer + - type: Sound + - type: UserInterface + interfaces: + - key: enum.MicrowaveUiKey.Key + type: MicrowaveBoundUserInterface + + + - type: Collidable + shapes: + - !type:PhysShapeAabb + bounds: "-0.25,-0.4,0.25,0.4" + layer: 15 + IsScrapingFloor: true + - type: Sprite + netsync: false + sprite: Objects/Kitchen/microwave.rsi + layers: + - state: mw0 + map: ["enum.MicrowaveVisualizerLayers.Base"] + - state: mw_unlit + shader: unshaded + map: ["enum.MicrowaveVisualizerLayers.BaseUnlit"] + - type: PowerDevice + - type: Icon + sprite: Objects/Kitchen/microwave.rsi + state: mw0 diff --git a/Resources/Prototypes/Kitchen/meal_recipes.yml b/Resources/Prototypes/Kitchen/meal_recipes.yml new file mode 100644 index 0000000000..7d936bc846 --- /dev/null +++ b/Resources/Prototypes/Kitchen/meal_recipes.yml @@ -0,0 +1,21 @@ +- type: microwaveMealRecipe + id: RecipeCheeseburger + name: Cheeseburger Recipe + result: FoodCheeseburger + time: 5 + reagents: + chem.Nutriment: 10 + solids: + FoodBreadSlice: 2 + + +- type: microwaveMealRecipe + id: RecipeMisoColaSoup + name: Salty Sweet MisoCola Soup Recipe + result: DisgustingSweptSoup + time: 15 + reagents: + chem.Cola: 5 + solids: + FoodMiloSoup: 1 + diff --git a/Resources/Prototypes/Reagents/food.yml b/Resources/Prototypes/Reagents/food.yml new file mode 100644 index 0000000000..6c838830da --- /dev/null +++ b/Resources/Prototypes/Reagents/food.yml @@ -0,0 +1,8 @@ +- type: reagent + id: chem.Flour + name: Flour + desc: Used for baking. + color: "#FFFFFF" + metabolism: + - !type:DefaultFood + rate: 1 diff --git a/Resources/Textures/Objects/Kitchen/microwave.rsi/meta.json b/Resources/Textures/Objects/Kitchen/microwave.rsi/meta.json new file mode 100644 index 0000000000..e1c3ede466 --- /dev/null +++ b/Resources/Textures/Objects/Kitchen/microwave.rsi/meta.json @@ -0,0 +1,105 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "AGPL v3", + "copyright": "Taken from https://github.com/discordia-space/CEV-Eris", + "states": [ + { + "name": "mw", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "mw_unlit", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "mw0", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "mw_running_unlit", + "directions": 1, + "delays": [ + [ + 1.0, + 1.0 + ] + ] + }, + { + "name": "mwb", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "mwbloody", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "mwbloody0", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] + }, + { + "name": "mwbloody1", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1 + ] + ] + }, + { + "name": "mwbloodyo", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1 + ] + ] + }, + { + "name": "mwo", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Objects/Kitchen/microwave.rsi/mw.png b/Resources/Textures/Objects/Kitchen/microwave.rsi/mw.png new file mode 100644 index 0000000000..88e285a134 Binary files /dev/null and b/Resources/Textures/Objects/Kitchen/microwave.rsi/mw.png differ diff --git a/Resources/Textures/Objects/Kitchen/microwave.rsi/mw0.png b/Resources/Textures/Objects/Kitchen/microwave.rsi/mw0.png new file mode 100644 index 0000000000..da9b07a55b Binary files /dev/null and b/Resources/Textures/Objects/Kitchen/microwave.rsi/mw0.png differ diff --git a/Resources/Textures/Objects/Kitchen/microwave.rsi/mw1.png b/Resources/Textures/Objects/Kitchen/microwave.rsi/mw1.png new file mode 100644 index 0000000000..7525b08a80 Binary files /dev/null and b/Resources/Textures/Objects/Kitchen/microwave.rsi/mw1.png differ diff --git a/Resources/Textures/Objects/Kitchen/microwave.rsi/mw_running_unlit.png b/Resources/Textures/Objects/Kitchen/microwave.rsi/mw_running_unlit.png new file mode 100644 index 0000000000..d259712b6d Binary files /dev/null and b/Resources/Textures/Objects/Kitchen/microwave.rsi/mw_running_unlit.png differ diff --git a/Resources/Textures/Objects/Kitchen/microwave.rsi/mw_unlit.png b/Resources/Textures/Objects/Kitchen/microwave.rsi/mw_unlit.png new file mode 100644 index 0000000000..4ad790b4e8 Binary files /dev/null and b/Resources/Textures/Objects/Kitchen/microwave.rsi/mw_unlit.png differ diff --git a/Resources/Textures/Objects/Kitchen/microwave.rsi/mwb.png b/Resources/Textures/Objects/Kitchen/microwave.rsi/mwb.png new file mode 100644 index 0000000000..fd933b346b Binary files /dev/null and b/Resources/Textures/Objects/Kitchen/microwave.rsi/mwb.png differ diff --git a/Resources/Textures/Objects/Kitchen/microwave.rsi/mwbloody.png b/Resources/Textures/Objects/Kitchen/microwave.rsi/mwbloody.png new file mode 100644 index 0000000000..3b144ce310 Binary files /dev/null and b/Resources/Textures/Objects/Kitchen/microwave.rsi/mwbloody.png differ diff --git a/Resources/Textures/Objects/Kitchen/microwave.rsi/mwbloody0.png b/Resources/Textures/Objects/Kitchen/microwave.rsi/mwbloody0.png new file mode 100644 index 0000000000..3b144ce310 Binary files /dev/null and b/Resources/Textures/Objects/Kitchen/microwave.rsi/mwbloody0.png differ diff --git a/Resources/Textures/Objects/Kitchen/microwave.rsi/mwbloody1.png b/Resources/Textures/Objects/Kitchen/microwave.rsi/mwbloody1.png new file mode 100644 index 0000000000..c62ca8560a Binary files /dev/null and b/Resources/Textures/Objects/Kitchen/microwave.rsi/mwbloody1.png differ diff --git a/Resources/Textures/Objects/Kitchen/microwave.rsi/mwbloodyo.png b/Resources/Textures/Objects/Kitchen/microwave.rsi/mwbloodyo.png new file mode 100644 index 0000000000..4d90ec33cc Binary files /dev/null and b/Resources/Textures/Objects/Kitchen/microwave.rsi/mwbloodyo.png differ diff --git a/Resources/Textures/Objects/Kitchen/microwave.rsi/mwo.png b/Resources/Textures/Objects/Kitchen/microwave.rsi/mwo.png new file mode 100644 index 0000000000..35ed2e9bae Binary files /dev/null and b/Resources/Textures/Objects/Kitchen/microwave.rsi/mwo.png differ