Add Microwave (#862)

* Add meal recipe prototype class and yaml file.
Add bare bones MicrowaveComponent.

* Reformat the way recipe prototypes work to something sensible.
More work on Microwave component.

* Rewrite recipe prototype.
Fix comparer in microwavecomponent.

* Add Eris microwave RSI.
Cleaned up  the Microwave component code.

* Refactor "output" to "result" for recipes/prototypes.
Remove a debug recipe from meal_recipes.yml
Add food.yml for food related reagents: sugar, flour, etc.

* Unfuck mostly everything.

* ShadowCommander is MVP.

* Add microwave visualizer. Clean up microwave code.

* Reformat 'PoweredIdle' to 'Idle'

* Refactor SoundComponent for stopping sounds.

* A shit ton of microwave stuff i can't really explain this.

* Microwave interface.

* Add (not working) basis for allowing solids (entities) in recipes.

* Microwave UI + solids implemented.

* Next up timer buttons

* Microwave is done. Added an easter egg recipe and made the cheeseburger recipe more sensible.

* Delete microwave.dmi, unneeded. Revert accidently changes to Shared EntryPoint.cs

* trying that again

* Remove unused 'ding.ogg'

* revert entrypoint to master

* revert sharedlathecomponent to master

* Pretty up the microwave menu, add click sounds. Remove some unnecessary ToList() calls. Remove unnecessary IoC resolves.

* And not a single "ToList()" went home to their family that day.....

* Seperated Reagent item list and Solid item list to allow for vaporizing particular reagents at will. (also fixes a really nasty null reference exception because they shared the same list before D: )

* Remove unncessary class dictionary and list. Fix meal prototype properties.

* lol

Co-authored-by: FL-OZ <yetanotherscuffed@gmail.com>
Co-authored-by: FLOZ <anotherscuffed@gmail.com>
Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
This commit is contained in:
Pieter-Jan Briers
2020-05-05 11:44:49 +02:00
committed by GitHub
31 changed files with 1207 additions and 28 deletions

View File

@@ -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<SharedWiresComponent>();
factory.Register<SharedCargoConsoleComponent>();
factory.Register<SharedReagentDispenserComponent>();
factory.Register<SharedMicrowaveComponent>();
factory.Register<SharedGravityGeneratorComponent>();
prototypes.RegisterIgnore("material");

View File

@@ -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<int, EntityUid> _solids = new Dictionary<int, EntityUid>();
private Dictionary<int, Solution.ReagentQuantity> _reagents =new Dictionary<int, Solution.ReagentQuantity>();
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<Solution.ReagentQuantity> reagents, List<EntityUid> 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);
}
}
}
}
}

View File

@@ -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<BaseButton.ButtonEventArgs> 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);
}
}
}

View File

@@ -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<ISpriteComponent>();
_soundComponent ??= component.Owner.GetComponent<SoundComponent>();
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
}
}
}

View File

@@ -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<ScheduledSound> _schedules = new List<ScheduledSound>();
private readonly Dictionary<ScheduledSound, IPlayingAudioStream> _audioStreams = new Dictionary<ScheduledSound, IPlayingAudioStream>();
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<IEntitySystemManager>().GetEntitySystem<AudioSystem>();
_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);
});

View File

@@ -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<IServerPreferencesManager>().StartInit();
}
public override void PostInit()
@@ -79,6 +81,7 @@ namespace Content.Server
_gameTicker.Initialize();
IoCManager.Resolve<ISandboxManager>().Initialize();
IoCManager.Resolve<IServerPreferencesManager>().FinishInit();
IoCManager.Resolve<RecipeManager>().Initialize();
}
public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs)

View File

@@ -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;
/// <summary>
/// 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.
/// </summary>
[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<SolutionComponent>();
_storage = ContainerManagerComponent.Ensure<Container>("microwave_entity_container", Owner, out var existed);
_appearance = Owner.GetComponent<AppearanceComponent>();
_powerDevice = Owner.GetComponent<PowerDeviceComponent>();
_audioSystem = _entitySystemManager.GetEntitySystem<AudioSystem>();
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
.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<EntityUid>();
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<HandsComponent>().GetActiveHand.Owner;
if(itemEntity.TryGetComponent<PourableComponent>(out var attackPourable))
{
//Get target and check if it can be poured into
if (!Owner.TryGetComponent<SolutionComponent>(out var mySolution)
|| !mySolution.CanPourIn)
{
return false;
}
if (!itemEntity.TryGetComponent<SolutionComponent>(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<string, int>();
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<string,int> 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));
}
}
}

View File

@@ -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<ICargoOrderDataManager, CargoOrderDataManager>();
IoCManager.Register<IModuleManager, ServerModuleManager>();
IoCManager.Register<IServerPreferencesManager, ServerPreferencesManager>();
IoCManager.Register<RecipeManager, RecipeManager>();
}
}
}

View File

@@ -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;
}
}

View File

@@ -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<FoodRecipePrototype> Recipes { get; private set; }
public void Initialize()
{
Recipes = new List<FoodRecipePrototype>();
foreach (var item in _prototypeManager.EnumeratePrototypes<FoodRecipePrototype>())
{
Recipes.Add(item);
}
Recipes.Sort(new RecipeComparer());
}
private class RecipeComparer : Comparer<FoodRecipePrototype>
{
public override int Compare(FoodRecipePrototype x, FoodRecipePrototype y)
{
if (x == null || y == null)
{
return 0;
}
return -x.IngredientsReagents.Count.CompareTo(y.IngredientsReagents.Count);
}
}
}
}

View File

@@ -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<Solution.ReagentQuantity> ReagentsReagents;
public readonly List<EntityUid> ContainedSolids;
public MicrowaveUpdateUserInterfaceState(IReadOnlyList<Solution.ReagentQuantity> reagents, List<EntityUid> solids)
{
ReagentsReagents = reagents;
ContainedSolids = solids;
}
}
[Serializable, NetSerializable]
public enum MicrowaveVisualState
{
Idle,
Cooking
}
[NetSerializable, Serializable]
public enum MicrowaveUiKey
{
Key
}
}

View File

@@ -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
{
/// <summary>
/// A recipe for space microwaves.
/// </summary>
[Prototype("microwaveMealRecipe")]
public class FoodRecipePrototype : IPrototype, IIndexedPrototype
{
private string _id;
private string _name;
private string _result;
private int _cookTime;
private Dictionary<string, int> _ingsReagents;
private Dictionary<string, int> _ingsSolids;
public string Name => Loc.GetString(_name);
public string ID => _id;
public string Result => _result;
public int CookTime => _cookTime;
public IReadOnlyDictionary<string, int> IngredientsReagents => _ingsReagents;
public IReadOnlyDictionary<string, int> 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<string, int>());
serializer.DataField(ref _ingsSolids, "solids", new Dictionary<string, int>());
serializer.DataField(ref _cookTime, "time", 5);
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,8 @@
- type: reagent
id: chem.Flour
name: Flour
desc: Used for baking.
color: "#FFFFFF"
metabolism:
- !type:DefaultFood
rate: 1

View File

@@ -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
]
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 825 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB