2019-07-31 05:10:06 -07:00
|
|
|
|
using System;
|
2019-10-11 16:57:16 -04:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using Content.Server.Chemistry;
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
using Content.Server.GameObjects.EntitySystems;
|
2019-07-31 05:10:06 -07:00
|
|
|
|
using Content.Shared.Chemistry;
|
|
|
|
|
|
using Content.Shared.GameObjects;
|
2019-10-11 16:57:16 -04:00
|
|
|
|
using Robust.Server.GameObjects.EntitySystems;
|
2019-07-31 15:02:36 +02:00
|
|
|
|
using Robust.Shared.GameObjects;
|
2019-07-31 05:10:06 -07:00
|
|
|
|
using Robust.Shared.Interfaces.GameObjects;
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
using Robust.Shared.IoC;
|
|
|
|
|
|
using Robust.Shared.Localization;
|
|
|
|
|
|
using Robust.Shared.Prototypes;
|
|
|
|
|
|
using Robust.Shared.Utility;
|
2019-07-31 05:10:06 -07:00
|
|
|
|
|
|
|
|
|
|
namespace Content.Server.GameObjects.Components.Chemistry
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Shared ECS component that manages a liquid solution of reagents.
|
|
|
|
|
|
/// </summary>
|
2019-07-31 15:02:36 +02:00
|
|
|
|
[RegisterComponent]
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
internal class SolutionComponent : Shared.GameObjects.Components.Chemistry.SolutionComponent, IExamine
|
2019-07-31 05:10:06 -07:00
|
|
|
|
{
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
#pragma warning disable 649
|
|
|
|
|
|
[Dependency] private readonly IPrototypeManager _prototypeManager;
|
2019-10-13 22:49:07 +02:00
|
|
|
|
[Dependency] private readonly ILocalizationManager _loc;
|
2019-10-11 16:57:16 -04:00
|
|
|
|
[Dependency] private readonly IEntitySystemManager _entitySystemManager;
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
#pragma warning restore 649
|
|
|
|
|
|
|
2019-10-11 16:57:16 -04:00
|
|
|
|
private IEnumerable<ReactionPrototype> _reactions;
|
|
|
|
|
|
private AudioSystem _audioSystem;
|
|
|
|
|
|
|
|
|
|
|
|
protected override void Startup()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.Startup();
|
2019-11-12 08:20:03 +11:00
|
|
|
|
|
2019-10-11 16:57:16 -04:00
|
|
|
|
_reactions = _prototypeManager.EnumeratePrototypes<ReactionPrototype>();
|
|
|
|
|
|
_audioSystem = _entitySystemManager.GetEntitySystem<AudioSystem>();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-11-12 08:20:03 +11:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Initializes the SolutionComponent if it doesn't have an owner
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void InitializeFromPrototype()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Because Initialize needs an Owner, Startup isn't called, etc.
|
|
|
|
|
|
IoCManager.InjectDependencies(this);
|
|
|
|
|
|
_reactions = _prototypeManager.EnumeratePrototypes<ReactionPrototype>();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-07-31 05:10:06 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Transfers solution from the held container to the target container.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Verb]
|
|
|
|
|
|
private sealed class FillTargetVerb : Verb<SolutionComponent>
|
2019-10-13 22:49:07 +02:00
|
|
|
|
{
|
2019-07-31 05:10:06 -07:00
|
|
|
|
protected override string GetText(IEntity user, SolutionComponent component)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(!user.TryGetComponent<HandsComponent>(out var hands))
|
|
|
|
|
|
return "<I SHOULD BE INVISIBLE>";
|
|
|
|
|
|
|
|
|
|
|
|
if(hands.GetActiveHand == null)
|
|
|
|
|
|
return "<I SHOULD BE INVISIBLE>";
|
|
|
|
|
|
|
|
|
|
|
|
var heldEntityName = hands.GetActiveHand.Owner?.Prototype?.Name ?? "<Item>";
|
|
|
|
|
|
var myName = component.Owner.Prototype?.Name ?? "<Item>";
|
|
|
|
|
|
|
|
|
|
|
|
return $"Transfer liquid from [{heldEntityName}] to [{myName}].";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override VerbVisibility GetVisibility(IEntity user, SolutionComponent component)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (user.TryGetComponent<HandsComponent>(out var hands))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (hands.GetActiveHand != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (hands.GetActiveHand.Owner.TryGetComponent<SolutionComponent>(out var solution))
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((solution.Capabilities & SolutionCaps.PourOut) != 0 && (component.Capabilities & SolutionCaps.PourIn) != 0)
|
|
|
|
|
|
return VerbVisibility.Visible;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return VerbVisibility.Invisible;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void Activate(IEntity user, SolutionComponent component)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!user.TryGetComponent<HandsComponent>(out var hands))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (hands.GetActiveHand == null)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (!hands.GetActiveHand.Owner.TryGetComponent<SolutionComponent>(out var handSolutionComp))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if ((handSolutionComp.Capabilities & SolutionCaps.PourOut) == 0 || (component.Capabilities & SolutionCaps.PourIn) == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
var transferQuantity = Math.Min(component.MaxVolume - component.CurrentVolume, handSolutionComp.CurrentVolume);
|
|
|
|
|
|
transferQuantity = Math.Min(transferQuantity, 10);
|
|
|
|
|
|
|
|
|
|
|
|
// nothing to transfer
|
|
|
|
|
|
if (transferQuantity <= 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
var transferSolution = handSolutionComp.SplitSolution(transferQuantity);
|
|
|
|
|
|
component.TryAddSolution(transferSolution);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
void IExamine.Examine(FormattedMessage message)
|
|
|
|
|
|
{
|
2019-10-13 22:49:07 +02:00
|
|
|
|
message.AddText(_loc.GetString("Contains:\n"));
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
foreach (var reagent in ReagentList)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto))
|
|
|
|
|
|
{
|
|
|
|
|
|
message.AddText($"{proto.Name}: {reagent.Quantity}u\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2019-10-13 22:49:07 +02:00
|
|
|
|
message.AddText(_loc.GetString("Unknown reagent: {0}u\n", reagent.Quantity));
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-07-31 05:10:06 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Transfers solution from a target container to the held container.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Verb]
|
|
|
|
|
|
private sealed class EmptyTargetVerb : Verb<SolutionComponent>
|
|
|
|
|
|
{
|
|
|
|
|
|
protected override string GetText(IEntity user, SolutionComponent component)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!user.TryGetComponent<HandsComponent>(out var hands))
|
|
|
|
|
|
return "<I SHOULD BE INVISIBLE>";
|
|
|
|
|
|
|
|
|
|
|
|
if (hands.GetActiveHand == null)
|
|
|
|
|
|
return "<I SHOULD BE INVISIBLE>";
|
|
|
|
|
|
|
|
|
|
|
|
var heldEntityName = hands.GetActiveHand.Owner?.Prototype?.Name ?? "<Item>";
|
|
|
|
|
|
var myName = component.Owner.Prototype?.Name ?? "<Item>";
|
|
|
|
|
|
|
|
|
|
|
|
return $"Transfer liquid from [{myName}] to [{heldEntityName}].";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override VerbVisibility GetVisibility(IEntity user, SolutionComponent component)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (user.TryGetComponent<HandsComponent>(out var hands))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (hands.GetActiveHand != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (hands.GetActiveHand.Owner.TryGetComponent<SolutionComponent>(out var solution))
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((solution.Capabilities & SolutionCaps.PourIn) != 0 && (component.Capabilities & SolutionCaps.PourOut) != 0)
|
|
|
|
|
|
return VerbVisibility.Visible;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return VerbVisibility.Invisible;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void Activate(IEntity user, SolutionComponent component)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!user.TryGetComponent<HandsComponent>(out var hands))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (hands.GetActiveHand == null)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if(!hands.GetActiveHand.Owner.TryGetComponent<SolutionComponent>(out var handSolutionComp))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if ((handSolutionComp.Capabilities & SolutionCaps.PourIn) == 0 || (component.Capabilities & SolutionCaps.PourOut) == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
var transferQuantity = Math.Min(handSolutionComp.MaxVolume - handSolutionComp.CurrentVolume, component.CurrentVolume);
|
|
|
|
|
|
transferQuantity = Math.Min(transferQuantity, 10);
|
|
|
|
|
|
|
|
|
|
|
|
// pulling from an empty container, pointless to continue
|
|
|
|
|
|
if (transferQuantity <= 0)
|
|
|
|
|
|
return;
|
2019-07-31 15:02:36 +02:00
|
|
|
|
|
2019-07-31 05:10:06 -07:00
|
|
|
|
var transferSolution = component.SplitSolution(transferQuantity);
|
|
|
|
|
|
handSolutionComp.TryAddSolution(transferSolution);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2019-10-11 16:57:16 -04:00
|
|
|
|
|
|
|
|
|
|
private void CheckForReaction()
|
|
|
|
|
|
{
|
2019-12-04 07:51:05 -05:00
|
|
|
|
bool checkForNewReaction = false;
|
|
|
|
|
|
while (true)
|
2019-10-11 16:57:16 -04:00
|
|
|
|
{
|
2019-12-04 07:51:05 -05:00
|
|
|
|
//Check the solution for every reaction
|
|
|
|
|
|
foreach (var reaction in _reactions)
|
2019-10-11 16:57:16 -04:00
|
|
|
|
{
|
2019-12-04 07:51:05 -05:00
|
|
|
|
if (SolutionValidReaction(reaction, out int unitReactions))
|
|
|
|
|
|
{
|
|
|
|
|
|
PerformReaction(reaction, unitReactions);
|
|
|
|
|
|
checkForNewReaction = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Check for a new reaction if a reaction occurs, run loop again.
|
|
|
|
|
|
if (checkForNewReaction)
|
|
|
|
|
|
{
|
|
|
|
|
|
checkForNewReaction = false;
|
|
|
|
|
|
continue;
|
2019-10-11 16:57:16 -04:00
|
|
|
|
}
|
2019-12-04 07:51:05 -05:00
|
|
|
|
return;
|
2019-10-11 16:57:16 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-11-12 08:20:03 +11:00
|
|
|
|
public bool TryAddReagent(string reagentId, int quantity, out int acceptedQuantity, bool skipReactionCheck = false, bool skipColor = false)
|
2019-10-11 16:57:16 -04:00
|
|
|
|
{
|
|
|
|
|
|
if (quantity > _maxVolume - _containedSolution.TotalVolume)
|
|
|
|
|
|
{
|
|
|
|
|
|
acceptedQuantity = _maxVolume - _containedSolution.TotalVolume;
|
|
|
|
|
|
if (acceptedQuantity == 0) return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
acceptedQuantity = quantity;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_containedSolution.AddReagent(reagentId, acceptedQuantity);
|
2019-11-12 08:20:03 +11:00
|
|
|
|
if (!skipColor) {
|
|
|
|
|
|
RecalculateColor();
|
|
|
|
|
|
}
|
2019-10-11 16:57:16 -04:00
|
|
|
|
if(!skipReactionCheck)
|
|
|
|
|
|
CheckForReaction();
|
|
|
|
|
|
OnSolutionChanged();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-11-12 08:20:03 +11:00
|
|
|
|
public bool TryAddSolution(Solution solution, bool skipReactionCheck = false, bool skipColor = false)
|
2019-10-11 16:57:16 -04:00
|
|
|
|
{
|
|
|
|
|
|
if (solution.TotalVolume > (_maxVolume - _containedSolution.TotalVolume))
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
_containedSolution.AddSolution(solution);
|
2019-11-12 08:20:03 +11:00
|
|
|
|
if (!skipColor) {
|
|
|
|
|
|
RecalculateColor();
|
|
|
|
|
|
}
|
2019-10-11 16:57:16 -04:00
|
|
|
|
if(!skipReactionCheck)
|
|
|
|
|
|
CheckForReaction();
|
|
|
|
|
|
OnSolutionChanged();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Checks if a solution has the reactants required to cause a specified reaction.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="solution">The solution to check for reaction conditions.</param>
|
|
|
|
|
|
/// <param name="reaction">The reaction whose reactants will be checked for in the solution.</param>
|
|
|
|
|
|
/// <param name="unitReactions">The number of times the reaction can occur with the given solution.</param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private bool SolutionValidReaction(ReactionPrototype reaction, out int unitReactions)
|
|
|
|
|
|
{
|
|
|
|
|
|
unitReactions = int.MaxValue; //Set to some impossibly large number initially
|
|
|
|
|
|
foreach (var reactant in reaction.Reactants)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!ContainsReagent(reactant.Key, out int reagentQuantity))
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
int currentUnitReactions = reagentQuantity / reactant.Value.Amount;
|
|
|
|
|
|
if (currentUnitReactions < unitReactions)
|
|
|
|
|
|
{
|
|
|
|
|
|
unitReactions = currentUnitReactions;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (unitReactions == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Perform a reaction on a solution. This assumes all reaction criteria have already been checked and are met.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="solution">Solution to be reacted.</param>
|
|
|
|
|
|
/// <param name="reaction">Reaction to occur.</param>
|
|
|
|
|
|
/// <param name="unitReactions">The number of times to cause this reaction.</param>
|
|
|
|
|
|
private void PerformReaction(ReactionPrototype reaction, int unitReactions)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Remove non-catalysts
|
|
|
|
|
|
foreach (var reactant in reaction.Reactants)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!reactant.Value.Catalyst)
|
|
|
|
|
|
{
|
|
|
|
|
|
int amountToRemove = unitReactions * reactant.Value.Amount;
|
|
|
|
|
|
TryRemoveReagent(reactant.Key, amountToRemove);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//Add products
|
|
|
|
|
|
foreach (var product in reaction.Products)
|
|
|
|
|
|
{
|
|
|
|
|
|
TryAddReagent(product.Key, (int)(unitReactions * product.Value), out int acceptedQuantity, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
//Trigger reaction effects
|
|
|
|
|
|
foreach (var effect in reaction.Effects)
|
|
|
|
|
|
{
|
|
|
|
|
|
effect.React(Owner, unitReactions);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Play reaction sound client-side
|
|
|
|
|
|
_audioSystem.Play("/Audio/effects/chemistry/bubbles.ogg", Owner.Transform.GridPosition);
|
|
|
|
|
|
}
|
2019-07-31 05:10:06 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|