Revert 'Revert 'Solution Entities'' (#23168)

This commit is contained in:
TemporalOroboros
2023-12-29 04:47:43 -08:00
committed by GitHub
parent 93e1af2f8d
commit d23c8d5c19
180 changed files with 3541 additions and 2956 deletions

View File

@@ -1,6 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Server.Labels;
using Content.Server.Popups;
using Content.Server.Storage.EntitySystems;
@@ -19,6 +18,8 @@ using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace Content.Server.Chemistry.EntitySystems
{
@@ -47,7 +48,7 @@ namespace Content.Server.Chemistry.EntitySystems
base.Initialize();
SubscribeLocalEvent<ChemMasterComponent, ComponentStartup>(SubscribeUpdateUiState);
SubscribeLocalEvent<ChemMasterComponent, SolutionChangedEvent>(SubscribeUpdateUiState);
SubscribeLocalEvent<ChemMasterComponent, SolutionContainerChangedEvent>(SubscribeUpdateUiState);
SubscribeLocalEvent<ChemMasterComponent, EntInsertedIntoContainerMessage>(SubscribeUpdateUiState);
SubscribeLocalEvent<ChemMasterComponent, EntRemovedFromContainerMessage>(SubscribeUpdateUiState);
SubscribeLocalEvent<ChemMasterComponent, BoundUIOpenedEvent>(SubscribeUpdateUiState);
@@ -67,7 +68,7 @@ namespace Content.Server.Chemistry.EntitySystems
private void UpdateUiState(Entity<ChemMasterComponent> ent, bool updateLabel = false)
{
var (owner, chemMaster) = ent;
if (!_solutionContainerSystem.TryGetSolution(owner, SharedChemMaster.BufferSolutionName, out var bufferSolution))
if (!_solutionContainerSystem.TryGetSolution(owner, SharedChemMaster.BufferSolutionName, out _, out var bufferSolution))
return;
var inputContainer = _itemSlotsSystem.GetItemOrNull(owner, SharedChemMaster.InputSlotName);
var outputContainer = _itemSlotsSystem.GetItemOrNull(owner, SharedChemMaster.OutputSlotName);
@@ -130,8 +131,8 @@ namespace Content.Server.Chemistry.EntitySystems
{
var container = _itemSlotsSystem.GetItemOrNull(chemMaster, SharedChemMaster.InputSlotName);
if (container is null ||
!_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSolution) ||
!_solutionContainerSystem.TryGetSolution(chemMaster, SharedChemMaster.BufferSolutionName, out var bufferSolution))
!_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSoln, out var containerSolution) ||
!_solutionContainerSystem.TryGetSolution(chemMaster.Owner, SharedChemMaster.BufferSolutionName, out _, out var bufferSolution))
{
return;
}
@@ -140,12 +141,12 @@ namespace Content.Server.Chemistry.EntitySystems
{
amount = FixedPoint2.Min(amount, containerSolution.AvailableVolume);
amount = bufferSolution.RemoveReagent(id, amount);
_solutionContainerSystem.TryAddReagent(container.Value, containerSolution, id, amount, out var _);
_solutionContainerSystem.TryAddReagent(containerSoln.Value, id, amount, out var _);
}
else // Container to buffer
{
amount = FixedPoint2.Min(amount, containerSolution.GetReagentQuantity(id));
_solutionContainerSystem.RemoveReagent(container.Value, containerSolution, id, amount);
_solutionContainerSystem.RemoveReagent(containerSoln.Value, id, amount);
bufferSolution.AddReagent(id, amount);
}
@@ -156,7 +157,7 @@ namespace Content.Server.Chemistry.EntitySystems
{
if (fromBuffer)
{
if (_solutionContainerSystem.TryGetSolution(chemMaster, SharedChemMaster.BufferSolutionName, out var bufferSolution))
if (_solutionContainerSystem.TryGetSolution(chemMaster.Owner, SharedChemMaster.BufferSolutionName, out _, out var bufferSolution))
bufferSolution.RemoveReagent(id, amount);
else
return;
@@ -165,9 +166,9 @@ namespace Content.Server.Chemistry.EntitySystems
{
var container = _itemSlotsSystem.GetItemOrNull(chemMaster, SharedChemMaster.InputSlotName);
if (container is not null &&
_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSolution))
_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSolution, out _))
{
_solutionContainerSystem.RemoveReagent(container.Value, containerSolution, id, amount);
_solutionContainerSystem.RemoveReagent(containerSolution.Value, id, amount);
}
else
return;
@@ -210,10 +211,8 @@ namespace Content.Server.Chemistry.EntitySystems
_storageSystem.Insert(container, item, out _, user: user, storage);
_labelSystem.Label(item, message.Label);
var itemSolution = _solutionContainerSystem.EnsureSolution(item, SharedChemMaster.PillSolutionName);
_solutionContainerSystem.TryAddSolution(
item, itemSolution, withdrawal.SplitSolution(message.Dosage));
var itemSolution = _solutionContainerSystem.EnsureSolutionEntity(item, SharedChemMaster.PillSolutionName, message.Dosage, null, out _);
_solutionContainerSystem.TryAddSolution(itemSolution, withdrawal.SplitSolution(message.Dosage));
var pill = EnsureComp<PillComponent>(item);
pill.PillType = chemMaster.Comp.PillType;
@@ -223,13 +222,13 @@ namespace Content.Server.Chemistry.EntitySystems
{
// Log pill creation by a user
_adminLogger.Add(LogType.Action, LogImpact.Low,
$"{ToPrettyString(user.Value):user} printed {ToPrettyString(item):pill} {SolutionContainerSystem.ToPrettyString(itemSolution)}");
$"{ToPrettyString(user.Value):user} printed {ToPrettyString(item):pill} {SolutionContainerSystem.ToPrettyString(itemSolution.Comp.Solution)}");
}
else
{
// Log pill creation by magic? This should never happen... right?
_adminLogger.Add(LogType.Action, LogImpact.Low,
$"Unknown printed {ToPrettyString(item):pill} {SolutionContainerSystem.ToPrettyString(itemSolution)}");
$"Unknown printed {ToPrettyString(item):pill} {SolutionContainerSystem.ToPrettyString(itemSolution.Comp.Solution)}");
}
}
@@ -242,8 +241,7 @@ namespace Content.Server.Chemistry.EntitySystems
var user = message.Session.AttachedEntity;
var maybeContainer = _itemSlotsSystem.GetItemOrNull(chemMaster, SharedChemMaster.OutputSlotName);
if (maybeContainer is not { Valid: true } container
|| !_solutionContainerSystem.TryGetSolution(
container, SharedChemMaster.BottleSolutionName, out var solution))
|| !_solutionContainerSystem.TryGetSolution(container, SharedChemMaster.BottleSolutionName, out var soln, out var solution))
{
return; // output can't fit reagents
}
@@ -260,8 +258,7 @@ namespace Content.Server.Chemistry.EntitySystems
return;
_labelSystem.Label(container, message.Label);
_solutionContainerSystem.TryAddSolution(
container, solution, withdrawal);
_solutionContainerSystem.TryAddSolution(soln.Value, withdrawal);
if (user.HasValue)
{
@@ -287,8 +284,7 @@ namespace Content.Server.Chemistry.EntitySystems
{
outputSolution = null;
if (!_solutionContainerSystem.TryGetSolution(
chemMaster, SharedChemMaster.BufferSolutionName, out var solution))
if (!_solutionContainerSystem.TryGetSolution(chemMaster.Owner, SharedChemMaster.BufferSolutionName, out _, out var solution))
{
return false;
}
@@ -323,7 +319,7 @@ namespace Content.Server.Chemistry.EntitySystems
return null;
if (!TryComp(container, out FitsInDispenserComponent? fits)
|| !_solutionContainerSystem.TryGetSolution(container.Value, fits.Solution, out var solution))
|| !_solutionContainerSystem.TryGetSolution(container.Value, fits.Solution, out _, out var solution))
{
return null;
}
@@ -339,7 +335,7 @@ namespace Content.Server.Chemistry.EntitySystems
var name = Name(container.Value);
{
if (_solutionContainerSystem.TryGetSolution(
container.Value, SharedChemMaster.BottleSolutionName, out var solution))
container.Value, SharedChemMaster.BottleSolutionName, out _, out var solution))
{
return BuildContainerInfo(name, solution);
}
@@ -350,7 +346,7 @@ namespace Content.Server.Chemistry.EntitySystems
var pills = storage.Container.ContainedEntities.Select((Func<EntityUid, (string, FixedPoint2 quantity)>) (pill =>
{
_solutionContainerSystem.TryGetSolution(pill, SharedChemMaster.PillSolutionName, out var solution);
_solutionContainerSystem.TryGetSolution(pill, SharedChemMaster.PillSolutionName, out _, out var solution);
var quantity = solution?.Volume ?? FixedPoint2.Zero;
return (Name(pill), quantity);
})).ToList();

View File

@@ -1,21 +1,22 @@
using Content.Server.Body.Components;
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Database;
using Content.Shared.DoAfter;
using Content.Shared.FixedPoint;
using Content.Shared.Forensics;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
using Robust.Shared.GameStates;
using Content.Shared.DoAfter;
using Content.Shared.Mobs.Components;
using Content.Shared.Verbs;
using Content.Shared.Stacks;
using Content.Shared.Verbs;
using Robust.Shared.GameStates;
using Robust.Shared.Player;
using Content.Shared.Forensics;
namespace Content.Server.Chemistry.EntitySystems;
@@ -25,11 +26,11 @@ public sealed partial class ChemistrySystem
/// <summary>
/// Default transfer amounts for the set-transfer verb.
/// </summary>
public static readonly List<int> TransferAmounts = new() {1, 5, 10, 15};
public static readonly List<int> TransferAmounts = new() { 1, 5, 10, 15 };
private void InitializeInjector()
{
SubscribeLocalEvent<InjectorComponent, GetVerbsEvent<AlternativeVerb>>(AddSetTransferVerbs);
SubscribeLocalEvent<InjectorComponent, SolutionChangedEvent>(OnSolutionChange);
SubscribeLocalEvent<InjectorComponent, SolutionContainerChangedEvent>(OnSolutionChange);
SubscribeLocalEvent<InjectorComponent, InjectorDoAfterEvent>(OnInjectDoAfter);
SubscribeLocalEvent<InjectorComponent, ComponentStartup>(OnInjectorStartup);
SubscribeLocalEvent<InjectorComponent, UseInHandEvent>(OnInjectorUse);
@@ -37,7 +38,7 @@ public sealed partial class ChemistrySystem
SubscribeLocalEvent<InjectorComponent, ComponentGetState>(OnInjectorGetState);
}
private void AddSetTransferVerbs(EntityUid uid, InjectorComponent component, GetVerbsEvent<AlternativeVerb> args)
private void AddSetTransferVerbs(Entity<InjectorComponent> entity, ref GetVerbsEvent<AlternativeVerb> args)
{
if (!args.CanAccess || !args.CanInteract || args.Hands == null)
return;
@@ -45,11 +46,14 @@ public sealed partial class ChemistrySystem
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
return;
var (uid, component) = entity;
// Add specific transfer verbs according to the container's size
var priority = 0;
var user = args.User;
foreach (var amount in TransferAmounts)
{
if ( amount < component.MinimumTransferAmount.Int() || amount > component.MaximumTransferAmount.Int())
if (amount < component.MinimumTransferAmount.Int() || amount > component.MaximumTransferAmount.Int())
continue;
AlternativeVerb verb = new();
@@ -58,7 +62,7 @@ public sealed partial class ChemistrySystem
verb.Act = () =>
{
component.TransferAmount = FixedPoint2.New(amount);
_popup.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", amount)), args.User, args.User);
_popup.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", amount)), user, user);
};
// we want to sort by size, not alphabetically by the verb text.
@@ -69,22 +73,22 @@ public sealed partial class ChemistrySystem
}
}
private void UseInjector(EntityUid target, EntityUid user, EntityUid injector, InjectorComponent component)
private void UseInjector(Entity<InjectorComponent> injector, EntityUid target, EntityUid user)
{
// Handle injecting/drawing for solutions
if (component.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject)
if (injector.Comp.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject)
{
if (_solutions.TryGetInjectableSolution(target, out var injectableSolution))
if (_solutionContainers.TryGetInjectableSolution(target, out var injectableSolution, out _))
{
TryInject(component, injector, target, injectableSolution, user, false);
TryInject(injector, target, injectableSolution.Value, user, false);
}
else if (_solutions.TryGetRefillableSolution(target, out var refillableSolution))
else if (_solutionContainers.TryGetRefillableSolution(target, out var refillableSolution, out _))
{
TryInject(component, injector, target, refillableSolution, user, true);
TryInject(injector, target, refillableSolution.Value, user, true);
}
else if (TryComp<BloodstreamComponent>(target, out var bloodstream))
{
TryInjectIntoBloodstream(component, injector, target, bloodstream, user);
TryInjectIntoBloodstream(injector, (target, bloodstream), user);
}
else
{
@@ -92,111 +96,112 @@ public sealed partial class ChemistrySystem
("target", Identity.Entity(target, EntityManager))), injector, user);
}
}
else if (component.ToggleState == SharedInjectorComponent.InjectorToggleMode.Draw)
else if (injector.Comp.ToggleState == SharedInjectorComponent.InjectorToggleMode.Draw)
{
// Draw from a bloodstream, if the target has that
if (TryComp<BloodstreamComponent>(target, out var stream))
if (TryComp<BloodstreamComponent>(target, out var stream) &&
_solutionContainers.ResolveSolution(target, stream.BloodSolutionName, ref stream.BloodSolution))
{
TryDraw(component, injector, target, stream.BloodSolution, user, stream);
TryDraw(injector, (target, stream), stream.BloodSolution.Value, user);
return;
}
// Draw from an object (food, beaker, etc)
if (_solutions.TryGetDrawableSolution(target, out var drawableSolution))
if (_solutionContainers.TryGetDrawableSolution(target, out var drawableSolution, out _))
{
TryDraw(component, injector, target, drawableSolution, user);
TryDraw(injector, target, drawableSolution.Value, user);
}
else
{
_popup.PopupEntity(Loc.GetString("injector-component-cannot-draw-message",
("target", Identity.Entity(target, EntityManager))), injector, user);
("target", Identity.Entity(target, EntityManager))), injector.Owner, user);
}
}
}
private void OnSolutionChange(EntityUid uid, InjectorComponent component, SolutionChangedEvent args)
private void OnSolutionChange(Entity<InjectorComponent> entity, ref SolutionContainerChangedEvent args)
{
Dirty(component);
Dirty(entity);
}
private void OnInjectorGetState(EntityUid uid, InjectorComponent component, ref ComponentGetState args)
private void OnInjectorGetState(Entity<InjectorComponent> entity, ref ComponentGetState args)
{
_solutions.TryGetSolution(uid, InjectorComponent.SolutionName, out var solution);
_solutionContainers.TryGetSolution(entity.Owner, InjectorComponent.SolutionName, out _, out var solution);
var currentVolume = solution?.Volume ?? FixedPoint2.Zero;
var maxVolume = solution?.MaxVolume ?? FixedPoint2.Zero;
args.State = new SharedInjectorComponent.InjectorComponentState(currentVolume, maxVolume, component.ToggleState);
args.State = new SharedInjectorComponent.InjectorComponentState(currentVolume, maxVolume, entity.Comp.ToggleState);
}
private void OnInjectDoAfter(EntityUid uid, InjectorComponent component, DoAfterEvent args)
private void OnInjectDoAfter(Entity<InjectorComponent> entity, ref InjectorDoAfterEvent args)
{
if (args.Cancelled || args.Handled || args.Args.Target == null)
return;
UseInjector(args.Args.Target.Value, args.Args.User, uid, component);
UseInjector(entity, args.Args.Target.Value, args.Args.User);
args.Handled = true;
}
private void OnInjectorAfterInteract(EntityUid uid, InjectorComponent component, AfterInteractEvent args)
private void OnInjectorAfterInteract(Entity<InjectorComponent> entity, ref AfterInteractEvent args)
{
if (args.Handled || !args.CanReach)
return;
//Make sure we have the attacking entity
if (args.Target is not { Valid: true } target || !HasComp<SolutionContainerManagerComponent>(uid))
if (args.Target is not { Valid: true } target || !HasComp<SolutionContainerManagerComponent>(entity))
return;
// Is the target a mob? If yes, use a do-after to give them time to respond.
if (HasComp<MobStateComponent>(target) || HasComp<BloodstreamComponent>(target))
{
// Are use using an injector capible of targeting a mob?
if (component.IgnoreMobs)
if (entity.Comp.IgnoreMobs)
return;
InjectDoAfter(component, args.User, target, uid);
InjectDoAfter(entity, target, args.User);
args.Handled = true;
return;
}
UseInjector(target, args.User, uid, component);
UseInjector(entity, target, args.User);
args.Handled = true;
}
private void OnInjectorStartup(EntityUid uid, InjectorComponent component, ComponentStartup args)
private void OnInjectorStartup(Entity<InjectorComponent> entity, ref ComponentStartup args)
{
// ???? why ?????
Dirty(component);
Dirty(entity);
}
private void OnInjectorUse(EntityUid uid, InjectorComponent component, UseInHandEvent args)
private void OnInjectorUse(Entity<InjectorComponent> entity, ref UseInHandEvent args)
{
if (args.Handled)
return;
Toggle(component, args.User, uid);
Toggle(entity, args.User);
args.Handled = true;
}
/// <summary>
/// Toggle between draw/inject state if applicable
/// </summary>
private void Toggle(InjectorComponent component, EntityUid user, EntityUid injector)
private void Toggle(Entity<InjectorComponent> injector, EntityUid user)
{
if (component.InjectOnly)
if (injector.Comp.InjectOnly)
{
return;
}
string msg;
switch (component.ToggleState)
switch (injector.Comp.ToggleState)
{
case SharedInjectorComponent.InjectorToggleMode.Inject:
component.ToggleState = SharedInjectorComponent.InjectorToggleMode.Draw;
injector.Comp.ToggleState = SharedInjectorComponent.InjectorToggleMode.Draw;
msg = "injector-component-drawing-text";
break;
case SharedInjectorComponent.InjectorToggleMode.Draw:
component.ToggleState = SharedInjectorComponent.InjectorToggleMode.Inject;
injector.Comp.ToggleState = SharedInjectorComponent.InjectorToggleMode.Inject;
msg = "injector-component-injecting-text";
break;
default:
@@ -209,18 +214,18 @@ public sealed partial class ChemistrySystem
/// <summary>
/// Send informative pop-up messages and wait for a do-after to complete.
/// </summary>
private void InjectDoAfter(InjectorComponent component, EntityUid user, EntityUid target, EntityUid injector)
private void InjectDoAfter(Entity<InjectorComponent> injector, EntityUid target, EntityUid user)
{
// Create a pop-up for the user
_popup.PopupEntity(Loc.GetString("injector-component-injecting-user"), target, user);
if (!_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution))
if (!_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out _, out var solution))
return;
var actualDelay = MathF.Max(component.Delay, 1f);
var actualDelay = MathF.Max(injector.Comp.Delay, 1f);
// Injections take 0.5 seconds longer per additional 5u
actualDelay += (float) component.TransferAmount / component.Delay - 0.5f;
actualDelay += (float) injector.Comp.TransferAmount / injector.Comp.Delay - 0.5f;
var isTarget = user != target;
@@ -244,7 +249,7 @@ public sealed partial class ChemistrySystem
}
// Add an admin log, using the "force feed" log type. It's not quite feeding, but the effect is the same.
if (component.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject)
if (injector.Comp.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject)
{
_adminLogger.Add(LogType.ForceFeed,
$"{EntityManager.ToPrettyString(user):user} is attempting to inject {EntityManager.ToPrettyString(target):target} with a solution {SolutionContainerSystem.ToPrettyString(solution):solution}");
@@ -255,11 +260,11 @@ public sealed partial class ChemistrySystem
// Self-injections take half as long.
actualDelay /= 2;
if (component.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject)
if (injector.Comp.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject)
_adminLogger.Add(LogType.Ingestion, $"{EntityManager.ToPrettyString(user):user} is attempting to inject themselves with a solution {SolutionContainerSystem.ToPrettyString(solution):solution}.");
}
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, actualDelay, new InjectorDoAfterEvent(), injector, target: target, used: injector)
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, actualDelay, new InjectorDoAfterEvent(), injector.Owner, target: target, used: injector.Owner)
{
BreakOnUserMove = true,
BreakOnDamage = true,
@@ -268,77 +273,80 @@ public sealed partial class ChemistrySystem
});
}
private void TryInjectIntoBloodstream(InjectorComponent component, EntityUid injector, EntityUid target, BloodstreamComponent targetBloodstream, EntityUid user)
private void TryInjectIntoBloodstream(Entity<InjectorComponent> injector, Entity<BloodstreamComponent> target, EntityUid user)
{
// Get transfer amount. May be smaller than _transferAmount if not enough room
var realTransferAmount = FixedPoint2.Min(component.TransferAmount, targetBloodstream.ChemicalSolution.AvailableVolume);
if (!_solutionContainers.ResolveSolution(target.Owner, target.Comp.ChemicalSolutionName, ref target.Comp.ChemicalSolution, out var chemSolution))
{
_popup.PopupEntity(Loc.GetString("injector-component-cannot-inject-message", ("target", Identity.Entity(target, EntityManager))), injector.Owner, user);
return;
}
var realTransferAmount = FixedPoint2.Min(injector.Comp.TransferAmount, chemSolution.AvailableVolume);
if (realTransferAmount <= 0)
{
_popup.PopupEntity(Loc.GetString("injector-component-cannot-inject-message", ("target", Identity.Entity(target, EntityManager))), injector, user);
_popup.PopupEntity(Loc.GetString("injector-component-cannot-inject-message", ("target", Identity.Entity(target, EntityManager))), injector.Owner, user);
return;
}
// Move units from attackSolution to targetSolution
var removedSolution = _solutions.SplitSolution(user, targetBloodstream.ChemicalSolution, realTransferAmount);
var removedSolution = _solutionContainers.SplitSolution(target.Comp.ChemicalSolution.Value, realTransferAmount);
_blood.TryAddToChemicals(target, removedSolution, targetBloodstream);
_blood.TryAddToChemicals(target, removedSolution, target.Comp);
_reactiveSystem.DoEntityReaction(target, removedSolution, ReactionMethod.Injection);
_popup.PopupEntity(Loc.GetString("injector-component-inject-success-message",
("amount", removedSolution.Volume),
("target", Identity.Entity(target, EntityManager))), injector, user);
("target", Identity.Entity(target, EntityManager))), injector.Owner, user);
Dirty(component);
AfterInject(component, injector, target);
Dirty(injector);
AfterInject(injector, target);
}
private void TryInject(InjectorComponent component, EntityUid injector, EntityUid targetEntity, Solution targetSolution, EntityUid user, bool asRefill)
private void TryInject(Entity<InjectorComponent> injector, EntityUid targetEntity, Entity<SolutionComponent> targetSolution, EntityUid user, bool asRefill)
{
if (!_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution)
|| solution.Volume == 0)
if (!_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out var soln, out var solution) || solution.Volume == 0)
return;
// Get transfer amount. May be smaller than _transferAmount if not enough room
var realTransferAmount = FixedPoint2.Min(component.TransferAmount, targetSolution.AvailableVolume);
var realTransferAmount = FixedPoint2.Min(injector.Comp.TransferAmount, targetSolution.Comp.Solution.AvailableVolume);
if (realTransferAmount <= 0)
{
_popup.PopupEntity(Loc.GetString("injector-component-target-already-full-message", ("target", Identity.Entity(targetEntity, EntityManager))),
injector, user);
injector.Owner, user);
return;
}
// Move units from attackSolution to targetSolution
Solution removedSolution;
if (TryComp<StackComponent>(targetEntity, out var stack))
removedSolution = _solutions.SplitStackSolution(injector, solution, realTransferAmount, stack.Count);
removedSolution = _solutionContainers.SplitStackSolution(soln.Value, realTransferAmount, stack.Count);
else
removedSolution = _solutions.SplitSolution(injector, solution, realTransferAmount);
removedSolution = _solutionContainers.SplitSolution(soln.Value, realTransferAmount);
_reactiveSystem.DoEntityReaction(targetEntity, removedSolution, ReactionMethod.Injection);
if (!asRefill)
_solutions.Inject(targetEntity, targetSolution, removedSolution);
_solutionContainers.Inject(targetEntity, targetSolution, removedSolution);
else
_solutions.Refill(targetEntity, targetSolution, removedSolution);
_solutionContainers.Refill(targetEntity, targetSolution, removedSolution);
_popup.PopupEntity(Loc.GetString("injector-component-transfer-success-message",
("amount", removedSolution.Volume),
("target", Identity.Entity(targetEntity, EntityManager))), injector, user);
("target", Identity.Entity(targetEntity, EntityManager))), injector.Owner, user);
Dirty(component);
AfterInject(component, injector, targetEntity);
Dirty(injector);
AfterInject(injector, targetEntity);
}
private void AfterInject(InjectorComponent component, EntityUid injector, EntityUid target)
private void AfterInject(Entity<InjectorComponent> injector, EntityUid target)
{
// Automatically set syringe to draw after completely draining it.
if (_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution)
&& solution.Volume == 0)
if (_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out _, out var solution) && solution.Volume == 0)
{
component.ToggleState = SharedInjectorComponent.InjectorToggleMode.Draw;
injector.Comp.ToggleState = SharedInjectorComponent.InjectorToggleMode.Draw;
}
// Leave some DNA from the injectee on it
@@ -346,13 +354,12 @@ public sealed partial class ChemistrySystem
RaiseLocalEvent(target, ref ev);
}
private void AfterDraw(InjectorComponent component, EntityUid injector, EntityUid target)
private void AfterDraw(Entity<InjectorComponent> injector, EntityUid target)
{
// Automatically set syringe to inject after completely filling it.
if (_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution)
&& solution.AvailableVolume == 0)
if (_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out _, out var solution) && solution.AvailableVolume == 0)
{
component.ToggleState = SharedInjectorComponent.InjectorToggleMode.Inject;
injector.Comp.ToggleState = SharedInjectorComponent.InjectorToggleMode.Inject;
}
// Leave some DNA from the drawee on it
@@ -360,70 +367,68 @@ public sealed partial class ChemistrySystem
RaiseLocalEvent(target, ref ev);
}
private void TryDraw(InjectorComponent component, EntityUid injector, EntityUid targetEntity, Solution targetSolution, EntityUid user, BloodstreamComponent? stream = null)
private void TryDraw(Entity<InjectorComponent> injector, Entity<BloodstreamComponent?> target, Entity<SolutionComponent> targetSolution, EntityUid user)
{
if (!_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution)
|| solution.AvailableVolume == 0)
if (!_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out var soln, out var solution) || solution.AvailableVolume == 0)
{
return;
}
// Get transfer amount. May be smaller than _transferAmount if not enough room, also make sure there's room in the injector
var realTransferAmount = FixedPoint2.Min(component.TransferAmount, targetSolution.Volume, solution.AvailableVolume);
var realTransferAmount = FixedPoint2.Min(injector.Comp.TransferAmount, targetSolution.Comp.Solution.Volume, solution.AvailableVolume);
if (realTransferAmount <= 0)
{
_popup.PopupEntity(Loc.GetString("injector-component-target-is-empty-message", ("target", Identity.Entity(targetEntity, EntityManager))),
injector, user);
_popup.PopupEntity(Loc.GetString("injector-component-target-is-empty-message", ("target", Identity.Entity(target, EntityManager))),
injector.Owner, user);
return;
}
// We have some snowflaked behavior for streams.
if (stream != null)
if (target.Comp != null)
{
DrawFromBlood(user, injector, targetEntity, component, solution, stream, realTransferAmount);
DrawFromBlood(injector, (target.Owner, target.Comp), soln.Value, realTransferAmount, user);
return;
}
// Move units from attackSolution to targetSolution
var removedSolution = _solutions.Draw(targetEntity, targetSolution, realTransferAmount);
var removedSolution = _solutionContainers.Draw(target.Owner, targetSolution, realTransferAmount);
if (!_solutions.TryAddSolution(injector, solution, removedSolution))
if (!_solutionContainers.TryAddSolution(soln.Value, removedSolution))
{
return;
}
_popup.PopupEntity(Loc.GetString("injector-component-draw-success-message",
("amount", removedSolution.Volume),
("target", Identity.Entity(targetEntity, EntityManager))), injector, user);
("target", Identity.Entity(target, EntityManager))), injector.Owner, user);
Dirty(component);
AfterDraw(component, injector, targetEntity);
Dirty(injector);
AfterDraw(injector, target);
}
private void DrawFromBlood(EntityUid user, EntityUid injector, EntityUid target, InjectorComponent component, Solution injectorSolution, BloodstreamComponent stream, FixedPoint2 transferAmount)
private void DrawFromBlood(Entity<InjectorComponent> injector, Entity<BloodstreamComponent> target, Entity<SolutionComponent> injectorSolution, FixedPoint2 transferAmount, EntityUid user)
{
var drawAmount = (float) transferAmount;
var bloodAmount = drawAmount;
var chemAmount = 0f;
if (stream.ChemicalSolution.Volume > 0f) // If they have stuff in their chem stream, we'll draw some of that
if (_solutionContainers.ResolveSolution(target.Owner, target.Comp.ChemicalSolutionName, ref target.Comp.ChemicalSolution))
{
bloodAmount = drawAmount * 0.85f;
chemAmount = drawAmount * 0.15f;
var chemTemp = _solutionContainers.SplitSolution(target.Comp.ChemicalSolution.Value, drawAmount * 0.15f);
_solutionContainers.TryAddSolution(injectorSolution, chemTemp);
drawAmount -= (float) chemTemp.Volume;
}
var bloodTemp = stream.BloodSolution.SplitSolution(bloodAmount);
var chemTemp = stream.ChemicalSolution.SplitSolution(chemAmount);
_solutions.TryAddSolution(injector, injectorSolution, bloodTemp);
_solutions.TryAddSolution(injector, injectorSolution, chemTemp);
if (_solutionContainers.ResolveSolution(target.Owner, target.Comp.BloodSolutionName, ref target.Comp.BloodSolution))
{
var bloodTemp = _solutionContainers.SplitSolution(target.Comp.BloodSolution.Value, drawAmount);
_solutionContainers.TryAddSolution(injectorSolution, bloodTemp);
}
_popup.PopupEntity(Loc.GetString("injector-component-draw-success-message",
("amount", transferAmount),
("target", Identity.Entity(target, EntityManager))), injector, user);
("target", Identity.Entity(target, EntityManager))), injector.Owner, user);
Dirty(component);
AfterDraw(component, injector, target);
Dirty(injector);
AfterDraw(injector, target);
}
}

View File

@@ -1,13 +1,12 @@
using Content.Server.Administration.Logs;
using Content.Server.Body.Systems;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Server.Interaction;
using Content.Server.Popups;
using Content.Shared.CombatMode;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.CombatMode;
using Content.Shared.DoAfter;
using Content.Shared.Mobs.Systems;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
namespace Content.Server.Chemistry.EntitySystems;
@@ -24,7 +23,7 @@ public sealed partial class ChemistrySystem : EntitySystem
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly SharedCombatModeSystem _combat = default!;
[Dependency] private readonly SolutionContainerSystem _solutions = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainers = default!;
public override void Initialize()
{

View File

@@ -1,20 +1,21 @@
using System.Linq;
using System.Diagnostics.CodeAnalysis;
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Database;
using Content.Shared.FixedPoint;
using Content.Shared.Forensics;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
using Content.Shared.Mobs.Components;
using Content.Shared.Weapons.Melee.Events;
using Content.Shared.Timing;
using Content.Shared.Weapons.Melee.Events;
using Robust.Shared.GameStates;
using Content.Shared.Forensics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace Content.Server.Chemistry.EntitySystems
{
@@ -26,33 +27,33 @@ namespace Content.Server.Chemistry.EntitySystems
{
SubscribeLocalEvent<HyposprayComponent, AfterInteractEvent>(OnAfterInteract);
SubscribeLocalEvent<HyposprayComponent, MeleeHitEvent>(OnAttack);
SubscribeLocalEvent<HyposprayComponent, SolutionChangedEvent>(OnSolutionChange);
SubscribeLocalEvent<HyposprayComponent, SolutionContainerChangedEvent>(OnSolutionChange);
SubscribeLocalEvent<HyposprayComponent, UseInHandEvent>(OnUseInHand);
SubscribeLocalEvent<HyposprayComponent, ComponentGetState>(OnHypoGetState);
}
private void OnHypoGetState(EntityUid uid, HyposprayComponent component, ref ComponentGetState args)
private void OnHypoGetState(Entity<HyposprayComponent> entity, ref ComponentGetState args)
{
args.State = _solutions.TryGetSolution(uid, component.SolutionName, out var solution)
args.State = _solutionContainers.TryGetSolution(entity.Owner, entity.Comp.SolutionName, out _, out var solution)
? new HyposprayComponentState(solution.Volume, solution.MaxVolume)
: new HyposprayComponentState(FixedPoint2.Zero, FixedPoint2.Zero);
}
private void OnUseInHand(EntityUid uid, HyposprayComponent component, UseInHandEvent args)
private void OnUseInHand(Entity<HyposprayComponent> entity, ref UseInHandEvent args)
{
if (args.Handled)
return;
TryDoInject(uid, args.User, args.User);
TryDoInject(entity, args.User, args.User);
args.Handled = true;
}
private void OnSolutionChange(EntityUid uid, HyposprayComponent component, SolutionChangedEvent args)
private void OnSolutionChange(Entity<HyposprayComponent> entity, ref SolutionContainerChangedEvent args)
{
Dirty(component);
Dirty(entity);
}
public void OnAfterInteract(EntityUid uid, HyposprayComponent component, AfterInteractEvent args)
public void OnAfterInteract(Entity<HyposprayComponent> entity, ref AfterInteractEvent args)
{
if (!args.CanReach)
return;
@@ -60,21 +61,20 @@ namespace Content.Server.Chemistry.EntitySystems
var target = args.Target;
var user = args.User;
TryDoInject(uid, target, user);
TryDoInject(entity, target, user);
}
public void OnAttack(EntityUid uid, HyposprayComponent component, MeleeHitEvent args)
public void OnAttack(Entity<HyposprayComponent> entity, ref MeleeHitEvent args)
{
if (!args.HitEntities.Any())
return;
TryDoInject(uid, args.HitEntities.First(), args.User);
TryDoInject(entity, args.HitEntities.First(), args.User);
}
public bool TryDoInject(EntityUid uid, EntityUid? target, EntityUid user, HyposprayComponent? component=null)
public bool TryDoInject(Entity<HyposprayComponent> hypo, EntityUid? target, EntityUid user)
{
if (!Resolve(uid, ref component))
return false;
var (uid, component) = hypo;
if (!EligibleEntity(target, _entMan, component))
return false;
@@ -92,15 +92,13 @@ namespace Content.Server.Chemistry.EntitySystems
target = user;
}
_solutions.TryGetSolution(uid, component.SolutionName, out var hypoSpraySolution);
if (hypoSpraySolution == null || hypoSpraySolution.Volume == 0)
if (!_solutionContainers.TryGetSolution(uid, component.SolutionName, out var hypoSpraySoln, out var hypoSpraySolution) || hypoSpraySolution.Volume == 0)
{
_popup.PopupCursor(Loc.GetString("hypospray-component-empty-message"), user);
return true;
}
if (!_solutions.TryGetInjectableSolution(target.Value, out var targetSolution))
if (!_solutionContainers.TryGetInjectableSolution(target.Value, out var targetSoln, out var targetSolution))
{
_popup.PopupCursor(Loc.GetString("hypospray-cant-inject", ("target", Identity.Entity(target.Value, _entMan))), user);
return false;
@@ -127,17 +125,17 @@ namespace Content.Server.Chemistry.EntitySystems
if (realTransferAmount <= 0)
{
_popup.PopupCursor(Loc.GetString("hypospray-component-transfer-already-full-message",("owner", target)), user);
_popup.PopupCursor(Loc.GetString("hypospray-component-transfer-already-full-message", ("owner", target)), user);
return true;
}
// Move units from attackSolution to targetSolution
var removedSolution = _solutions.SplitSolution(uid, hypoSpraySolution, realTransferAmount);
var removedSolution = _solutionContainers.SplitSolution(hypoSpraySoln.Value, realTransferAmount);
if (!targetSolution.CanAddSolution(removedSolution))
return true;
_reactiveSystem.DoEntityReaction(target.Value, removedSolution, ReactionMethod.Injection);
_solutions.TryAddSolution(target.Value, targetSolution, removedSolution);
_solutionContainers.TryAddSolution(targetSoln.Value, removedSolution);
var ev = new TransferDnaEvent { Donor = target.Value, Recipient = uid };
RaiseLocalEvent(target.Value, ref ev);

View File

@@ -1,10 +1,6 @@
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Events;
using Robust.Shared.Player;
namespace Content.Server.Chemistry.EntitySystems;
@@ -15,27 +11,26 @@ public sealed partial class ChemistrySystem
SubscribeLocalEvent<ReactionMixerComponent, AfterInteractEvent>(OnAfterInteract);
}
private void OnAfterInteract(EntityUid uid, ReactionMixerComponent component, AfterInteractEvent args)
private void OnAfterInteract(Entity<ReactionMixerComponent> entity, ref AfterInteractEvent args)
{
if (!args.Target.HasValue || !args.CanReach)
return;
var mixAttemptEvent = new MixingAttemptEvent(uid);
RaiseLocalEvent(uid, ref mixAttemptEvent);
if(mixAttemptEvent.Cancelled)
var mixAttemptEvent = new MixingAttemptEvent(entity);
RaiseLocalEvent(entity, ref mixAttemptEvent);
if (mixAttemptEvent.Cancelled)
{
return;
}
Solution? solution = null;
if (!_solutions.TryGetMixableSolution(args.Target.Value, out solution))
return;
if (!_solutionContainers.TryGetMixableSolution(args.Target.Value, out var solution))
return;
_popup.PopupEntity(Loc.GetString(component.MixMessage, ("mixed", Identity.Entity(args.Target.Value, EntityManager)), ("mixer", Identity.Entity(uid, EntityManager))), args.User, args.User);
_popup.PopupEntity(Loc.GetString(entity.Comp.MixMessage, ("mixed", Identity.Entity(args.Target.Value, EntityManager)), ("mixer", Identity.Entity(entity.Owner, EntityManager))), args.User, args.User);
_solutions.UpdateChemicals(args.Target.Value, solution, true, component);
_solutionContainers.UpdateChemicals(solution.Value, true, entity.Comp);
var afterMixingEvent = new AfterMixingEvent(uid, args.Target.Value);
RaiseLocalEvent(uid, afterMixingEvent);
var afterMixingEvent = new AfterMixingEvent(entity, args.Target.Value);
RaiseLocalEvent(entity, afterMixingEvent);
}
}

View File

@@ -1,4 +1,5 @@
using Content.Server.Chemistry.Components.DeleteOnSolutionEmptyComponent;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
@@ -12,27 +13,27 @@ namespace Content.Server.Chemistry.EntitySystems.DeleteOnSolutionEmptySystem
{
base.Initialize();
SubscribeLocalEvent<DeleteOnSolutionEmptyComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<DeleteOnSolutionEmptyComponent, SolutionChangedEvent>(OnSolutionChange);
SubscribeLocalEvent<DeleteOnSolutionEmptyComponent, SolutionContainerChangedEvent>(OnSolutionChange);
}
public void OnStartup(EntityUid uid, DeleteOnSolutionEmptyComponent component, ComponentStartup args)
public void OnStartup(Entity<DeleteOnSolutionEmptyComponent> entity, ref ComponentStartup args)
{
CheckSolutions(uid, component);
CheckSolutions(entity);
}
public void OnSolutionChange(EntityUid uid, DeleteOnSolutionEmptyComponent component, SolutionChangedEvent args)
public void OnSolutionChange(Entity<DeleteOnSolutionEmptyComponent> entity, ref SolutionContainerChangedEvent args)
{
CheckSolutions(uid, component);
CheckSolutions(entity);
}
public void CheckSolutions(EntityUid uid, DeleteOnSolutionEmptyComponent component)
public void CheckSolutions(Entity<DeleteOnSolutionEmptyComponent> entity)
{
if (!EntityManager.HasComponent<SolutionContainerManagerComponent>(uid))
if (!TryComp(entity, out SolutionContainerManagerComponent? solutions))
return;
if (_solutionContainerSystem.TryGetSolution(uid, component.Solution, out var solution))
if (_solutionContainerSystem.TryGetSolution((entity.Owner, solutions), entity.Comp.Solution, out _, out var solution))
if (solution.Volume <= 0)
EntityManager.QueueDeleteEntity(uid);
EntityManager.QueueDeleteEntity(entity);
}
}
}

View File

@@ -1,6 +1,6 @@
using System.Linq;
using Content.Server.Administration.Logs;
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Dispenser;
using Content.Shared.Chemistry.EntitySystems;
@@ -15,6 +15,7 @@ using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
using System.Linq;
namespace Content.Server.Chemistry.EntitySystems
{
@@ -36,7 +37,7 @@ namespace Content.Server.Chemistry.EntitySystems
base.Initialize();
SubscribeLocalEvent<ReagentDispenserComponent, ComponentStartup>(SubscribeUpdateUiState);
SubscribeLocalEvent<ReagentDispenserComponent, SolutionChangedEvent>(SubscribeUpdateUiState);
SubscribeLocalEvent<ReagentDispenserComponent, SolutionContainerChangedEvent>(SubscribeUpdateUiState);
SubscribeLocalEvent<ReagentDispenserComponent, EntInsertedIntoContainerMessage>(SubscribeUpdateUiState);
SubscribeLocalEvent<ReagentDispenserComponent, EntRemovedFromContainerMessage>(SubscribeUpdateUiState);
SubscribeLocalEvent<ReagentDispenserComponent, BoundUIOpenedEvent>(SubscribeUpdateUiState);
@@ -68,7 +69,7 @@ namespace Content.Server.Chemistry.EntitySystems
if (container is not { Valid: true })
return null;
if (_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var solution))
if (_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out _, out var solution))
{
return new ContainerInfo(Name(container.Value), solution.Volume, solution.MaxVolume)
{
@@ -122,10 +123,10 @@ namespace Content.Server.Chemistry.EntitySystems
return;
var outputContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, SharedReagentDispenser.OutputSlotName);
if (outputContainer is not {Valid: true} || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution))
if (outputContainer is not { Valid: true } || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution, out _))
return;
if (_solutionContainerSystem.TryAddReagent(outputContainer.Value, solution, message.ReagentId, (int)reagentDispenser.Comp.DispenseAmount, out var dispensedAmount)
if (_solutionContainerSystem.TryAddReagent(solution.Value, message.ReagentId, (int) reagentDispenser.Comp.DispenseAmount, out var dispensedAmount)
&& message.Session.AttachedEntity is not null)
{
_adminLogger.Add(LogType.ChemicalReaction, LogImpact.Medium,
@@ -139,10 +140,10 @@ namespace Content.Server.Chemistry.EntitySystems
private void OnClearContainerSolutionMessage(Entity<ReagentDispenserComponent> reagentDispenser, ref ReagentDispenserClearContainerSolutionMessage message)
{
var outputContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, SharedReagentDispenser.OutputSlotName);
if (outputContainer is not {Valid: true} || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution))
if (outputContainer is not { Valid: true } || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution, out _))
return;
_solutionContainerSystem.RemoveAllSolution(outputContainer.Value, solution);
_solutionContainerSystem.RemoveAllSolution(solution.Value);
UpdateUiState(reagentDispenser);
ClickSound(reagentDispenser);
}

View File

@@ -1,4 +1,5 @@
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.FixedPoint;
using Content.Shared.Popups;
@@ -16,21 +17,23 @@ public sealed class RehydratableSystem : EntitySystem
{
base.Initialize();
SubscribeLocalEvent<RehydratableComponent, SolutionChangedEvent>(OnSolutionChange);
SubscribeLocalEvent<RehydratableComponent, SolutionContainerChangedEvent>(OnSolutionChange);
}
private void OnSolutionChange(EntityUid uid, RehydratableComponent comp, SolutionChangedEvent args)
private void OnSolutionChange(Entity<RehydratableComponent> entity, ref SolutionContainerChangedEvent args)
{
var quantity = _solutions.GetTotalPrototypeQuantity(uid, comp.CatalystPrototype);
if (quantity != FixedPoint2.Zero && quantity >= comp.CatalystMinimum)
var quantity = _solutions.GetTotalPrototypeQuantity(entity, entity.Comp.CatalystPrototype);
if (quantity != FixedPoint2.Zero && quantity >= entity.Comp.CatalystMinimum)
{
Expand(uid, comp);
Expand(entity);
}
}
// Try not to make this public if you can help it.
private void Expand(EntityUid uid, RehydratableComponent comp)
private void Expand(Entity<RehydratableComponent> entity)
{
var (uid, comp) = entity;
_popups.PopupEntity(Loc.GetString("rehydratable-component-expands-message", ("owner", uid)), uid);
var randomMob = _random.Pick(comp.PossibleSpawns);

View File

@@ -1,10 +1,10 @@
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Server.Construction;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Placeable;
namespace Content.Server.Chemistry.EntitySystems;
@@ -13,7 +13,7 @@ public sealed class SolutionHeaterSystem : EntitySystem
{
[Dependency] private readonly PowerReceiverSystem _powerReceiver = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SolutionContainerSystem _solution = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainer = default!;
/// <inheritdoc/>
public override void Initialize()
@@ -51,41 +51,41 @@ public sealed class SolutionHeaterSystem : EntitySystem
RemComp<ActiveSolutionHeaterComponent>(uid);
}
private void OnPowerChanged(EntityUid uid, SolutionHeaterComponent component, ref PowerChangedEvent args)
private void OnPowerChanged(Entity<SolutionHeaterComponent> entity, ref PowerChangedEvent args)
{
var placer = Comp<ItemPlacerComponent>(uid);
var placer = Comp<ItemPlacerComponent>(entity);
if (args.Powered && placer.PlacedEntities.Count > 0)
{
TurnOn(uid);
TurnOn(entity);
}
else
{
TurnOff(uid);
TurnOff(entity);
}
}
private void OnRefreshParts(EntityUid uid, SolutionHeaterComponent component, RefreshPartsEvent args)
private void OnRefreshParts(Entity<SolutionHeaterComponent> entity, ref RefreshPartsEvent args)
{
var heatRating = args.PartRatings[component.MachinePartHeatMultiplier] - 1;
var heatRating = args.PartRatings[entity.Comp.MachinePartHeatMultiplier] - 1;
component.HeatPerSecond = component.BaseHeatPerSecond * MathF.Pow(component.PartRatingHeatMultiplier, heatRating);
entity.Comp.HeatPerSecond = entity.Comp.BaseHeatPerSecond * MathF.Pow(entity.Comp.PartRatingHeatMultiplier, heatRating);
}
private void OnUpgradeExamine(EntityUid uid, SolutionHeaterComponent component, UpgradeExamineEvent args)
private void OnUpgradeExamine(Entity<SolutionHeaterComponent> entity, ref UpgradeExamineEvent args)
{
args.AddPercentageUpgrade("solution-heater-upgrade-heat", component.HeatPerSecond / component.BaseHeatPerSecond);
args.AddPercentageUpgrade("solution-heater-upgrade-heat", entity.Comp.HeatPerSecond / entity.Comp.BaseHeatPerSecond);
}
private void OnItemPlaced(EntityUid uid, SolutionHeaterComponent comp, ref ItemPlacedEvent args)
private void OnItemPlaced(Entity<SolutionHeaterComponent> entity, ref ItemPlacedEvent args)
{
TryTurnOn(uid);
TryTurnOn(entity);
}
private void OnItemRemoved(EntityUid uid, SolutionHeaterComponent component, ref ItemRemovedEvent args)
private void OnItemRemoved(Entity<SolutionHeaterComponent> entity, ref ItemRemovedEvent args)
{
var placer = Comp<ItemPlacerComponent>(uid);
var placer = Comp<ItemPlacerComponent>(entity);
if (placer.PlacedEntities.Count == 0) // Last entity was removed
TurnOff(uid);
TurnOff(entity);
}
public override void Update(float frameTime)
@@ -97,13 +97,13 @@ public sealed class SolutionHeaterSystem : EntitySystem
{
foreach (var heatingEntity in placer.PlacedEntities)
{
if (!TryComp<SolutionContainerManagerComponent>(heatingEntity, out var solution))
if (!TryComp<SolutionContainerManagerComponent>(heatingEntity, out var container))
continue;
var energy = heater.HeatPerSecond * frameTime;
foreach (var s in solution.Solutions.Values)
foreach (var (_, soln) in _solutionContainer.EnumerateSolutions((heatingEntity, container)))
{
_solution.AddThermalEnergy(heatingEntity, s, energy);
_solutionContainer.AddThermalEnergy(soln, energy);
}
}
}

View File

@@ -1,19 +1,17 @@
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Server.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Inventory;
using JetBrains.Annotations;
using Robust.Shared.Physics.Events;
using Robust.Shared.Prototypes;
namespace Content.Server.Chemistry.EntitySystems
{
[UsedImplicitly]
internal sealed class SolutionInjectOnCollideSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _protoManager = default!;
[Dependency] private readonly SolutionContainerSystem _solutionsSystem = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainersSystem = default!;
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
@@ -30,7 +28,7 @@ namespace Content.Server.Chemistry.EntitySystems
if (!args.OtherBody.Hard ||
!EntityManager.TryGetComponent<BloodstreamComponent>(target, out var bloodstream) ||
!_solutionsSystem.TryGetInjectableSolution(ent, out var solution))
!_solutionContainersSystem.TryGetInjectableSolution(ent.Owner, out var solution, out _))
{
return;
}
@@ -44,7 +42,7 @@ namespace Content.Server.Chemistry.EntitySystems
return;
}
var solRemoved = solution.SplitSolution(component.TransferAmount);
var solRemoved = _solutionContainersSystem.SplitSolution(solution.Value, component.TransferAmount);
var solRemovedVol = solRemoved.Volume;
var solToInject = solRemoved.SplitSolution(solRemovedVol * component.TransferEfficiency);

View File

@@ -1,7 +1,6 @@
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.FixedPoint;
using Robust.Shared.Timing;
namespace Content.Server.Chemistry.EntitySystems;
@@ -30,13 +29,13 @@ public sealed class SolutionPurgeSystem : EntitySystem
// timer ignores if it's empty, it's just a fixed cycle
purge.NextPurgeTime += purge.Duration;
if (_solutionContainer.TryGetSolution(uid, purge.Solution, out var solution, manager))
_solutionContainer.SplitSolutionWithout(uid, solution, purge.Quantity, purge.Preserve.ToArray());
if (_solutionContainer.TryGetSolution((uid, manager), purge.Solution, out var solution))
_solutionContainer.SplitSolutionWithout(solution.Value, purge.Quantity, purge.Preserve.ToArray());
}
}
private void OnUnpaused(EntityUid uid, SolutionPurgeComponent comp, ref EntityUnpausedEvent args)
private void OnUnpaused(Entity<SolutionPurgeComponent> entity, ref EntityUnpausedEvent args)
{
comp.NextPurgeTime += args.PausedTime;
entity.Comp.NextPurgeTime += args.PausedTime;
}
}

View File

@@ -1,5 +1,5 @@
using Content.Server.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Random;
using Content.Shared.Random.Helpers;
@@ -21,13 +21,12 @@ public sealed class SolutionRandomFillSystem : EntitySystem
SubscribeLocalEvent<RandomFillSolutionComponent, MapInitEvent>(OnRandomSolutionFillMapInit);
}
private void OnRandomSolutionFillMapInit(EntityUid uid, RandomFillSolutionComponent component, MapInitEvent args)
private void OnRandomSolutionFillMapInit(Entity<RandomFillSolutionComponent> entity, ref MapInitEvent args)
{
if (component.WeightedRandomId == null)
if (entity.Comp.WeightedRandomId == null)
return;
var target = _solutionsSystem.EnsureSolution(uid, component.Solution);
var pick = _proto.Index<WeightedRandomFillSolutionPrototype>(component.WeightedRandomId).Pick(_random);
var pick = _proto.Index<WeightedRandomFillSolutionPrototype>(entity.Comp.WeightedRandomId).Pick(_random);
var reagent = pick.reagent;
var quantity = pick.quantity;
@@ -38,6 +37,7 @@ public sealed class SolutionRandomFillSystem : EntitySystem
return;
}
target.AddReagent(reagent, quantity);
var target = _solutionsSystem.EnsureSolutionEntity(entity.Owner, entity.Comp.Solution, pick.quantity, null, out _);
_solutionsSystem.TryAddReagent(target, reagent, quantity, out _);
}
}

View File

@@ -1,7 +1,7 @@
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.FixedPoint;
using Robust.Shared.Timing;
@@ -31,7 +31,7 @@ public sealed class SolutionRegenerationSystem : EntitySystem
// timer ignores if its full, it's just a fixed cycle
regen.NextRegenTime = _timing.CurTime + regen.Duration;
if (_solutionContainer.TryGetSolution(uid, regen.Solution, out var solution, manager))
if (_solutionContainer.ResolveSolution((uid, manager), regen.SolutionName, ref regen.Solution, out var solution))
{
var amount = FixedPoint2.Min(solution.AvailableVolume, regen.Generated.Volume);
if (amount <= FixedPoint2.Zero)
@@ -48,13 +48,13 @@ public sealed class SolutionRegenerationSystem : EntitySystem
generated = regen.Generated.Clone().SplitSolution(amount);
}
_solutionContainer.TryAddSolution(uid, solution, generated);
_solutionContainer.TryAddSolution(regen.Solution.Value, generated);
}
}
}
private void OnUnpaused(EntityUid uid, SolutionRegenerationComponent comp, ref EntityUnpausedEvent args)
private void OnUnpaused(Entity<SolutionRegenerationComponent> entity, ref EntityUnpausedEvent args)
{
comp.NextRegenTime += args.PausedTime;
entity.Comp.NextRegenTime += args.PausedTime;
}
}

View File

@@ -1,12 +1,10 @@
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Server.Explosion.EntitySystems;
using Content.Server.Popups;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.FixedPoint;
using Content.Shared.Interaction;
using Robust.Shared.Player;
namespace Content.Server.Chemistry.EntitySystems;
@@ -21,7 +19,7 @@ namespace Content.Server.Chemistry.EntitySystems;
/// </summary>
public sealed class SolutionSpikableSystem : EntitySystem
{
[Dependency] private readonly SolutionContainerSystem _solutionSystem = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly TriggerSystem _triggerSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
@@ -30,9 +28,9 @@ public sealed class SolutionSpikableSystem : EntitySystem
SubscribeLocalEvent<RefillableSolutionComponent, InteractUsingEvent>(OnInteractUsing);
}
private void OnInteractUsing(EntityUid uid, RefillableSolutionComponent target, InteractUsingEvent args)
private void OnInteractUsing(Entity<RefillableSolutionComponent> entity, ref InteractUsingEvent args)
{
TrySpike(args.Used, args.Target, args.User, target);
TrySpike(args.Used, args.Target, args.User, entity.Comp);
}
/// <summary>
@@ -49,8 +47,8 @@ public sealed class SolutionSpikableSystem : EntitySystem
{
if (!Resolve(source, ref spikableSource, ref managerSource, false)
|| !Resolve(target, ref spikableTarget, ref managerTarget, false)
|| !_solutionSystem.TryGetRefillableSolution(target, out var targetSolution, managerTarget, spikableTarget)
|| !managerSource.Solutions.TryGetValue(spikableSource.SourceSolution, out var sourceSolution))
|| !_solutionContainerSystem.TryGetRefillableSolution((target, spikableTarget, managerTarget), out var targetSoln, out var targetSolution)
|| !_solutionContainerSystem.TryGetSolution((source, managerSource), spikableSource.SourceSolution, out _, out var sourceSolution))
{
return;
}
@@ -61,7 +59,7 @@ public sealed class SolutionSpikableSystem : EntitySystem
return;
}
if (!_solutionSystem.ForceAddSolution(target, targetSolution, sourceSolution))
if (!_solutionContainerSystem.ForceAddSolution(targetSoln.Value, sourceSolution))
return;
_popupSystem.PopupEntity(Loc.GetString(spikableSource.Popup, ("spiked-entity", target), ("spike-entity", source)), user, user);

View File

@@ -1,14 +1,14 @@
using Content.Server.Administration.Logs;
using Content.Shared.Verbs;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Database;
using Content.Shared.FixedPoint;
using Content.Shared.Interaction;
using Content.Shared.Popups;
using Content.Shared.Verbs;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
using Robust.Shared.Player;
namespace Content.Server.Chemistry.EntitySystems
@@ -24,7 +24,7 @@ namespace Content.Server.Chemistry.EntitySystems
/// <summary>
/// Default transfer amounts for the set-transfer verb.
/// </summary>
public static readonly List<int> DefaultTransferAmounts = new() { 1, 5, 10, 25, 50, 100, 250, 500, 1000};
public static readonly List<int> DefaultTransferAmounts = new() { 1, 5, 10, 25, 50, 100, 250, 500, 1000 };
public override void Initialize()
{
@@ -35,17 +35,19 @@ namespace Content.Server.Chemistry.EntitySystems
SubscribeLocalEvent<SolutionTransferComponent, TransferAmountSetValueMessage>(OnTransferAmountSetValueMessage);
}
private void OnTransferAmountSetValueMessage(EntityUid uid, SolutionTransferComponent solutionTransfer, TransferAmountSetValueMessage message)
private void OnTransferAmountSetValueMessage(Entity<SolutionTransferComponent> entity, ref TransferAmountSetValueMessage message)
{
var newTransferAmount = FixedPoint2.Clamp(message.Value, solutionTransfer.MinimumTransferAmount, solutionTransfer.MaximumTransferAmount);
solutionTransfer.TransferAmount = newTransferAmount;
var newTransferAmount = FixedPoint2.Clamp(message.Value, entity.Comp.MinimumTransferAmount, entity.Comp.MaximumTransferAmount);
entity.Comp.TransferAmount = newTransferAmount;
if (message.Session.AttachedEntity is {Valid: true} user)
_popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", newTransferAmount)), uid, user);
if (message.Session.AttachedEntity is { Valid: true } user)
_popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", newTransferAmount)), entity.Owner, user);
}
private void AddSetTransferVerbs(EntityUid uid, SolutionTransferComponent component, GetVerbsEvent<AlternativeVerb> args)
private void AddSetTransferVerbs(Entity<SolutionTransferComponent> entity, ref GetVerbsEvent<AlternativeVerb> args)
{
var (uid, component) = entity;
if (!args.CanAccess || !args.CanInteract || !component.CanChangeTransferAmount || args.Hands == null)
return;
@@ -56,15 +58,16 @@ namespace Content.Server.Chemistry.EntitySystems
AlternativeVerb custom = new();
custom.Text = Loc.GetString("comp-solution-transfer-verb-custom-amount");
custom.Category = VerbCategory.SetTransferAmount;
custom.Act = () => _userInterfaceSystem.TryOpen(args.Target, TransferAmountUiKey.Key, actor.PlayerSession);
custom.Act = () => _userInterfaceSystem.TryOpen(uid, TransferAmountUiKey.Key, actor.PlayerSession);
custom.Priority = 1;
args.Verbs.Add(custom);
// Add specific transfer verbs according to the container's size
var priority = 0;
var user = args.User;
foreach (var amount in DefaultTransferAmounts)
{
if ( amount < component.MinimumTransferAmount.Int() || amount > component.MaximumTransferAmount.Int())
if (amount < component.MinimumTransferAmount.Int() || amount > component.MaximumTransferAmount.Int())
continue;
AlternativeVerb verb = new();
@@ -73,7 +76,7 @@ namespace Content.Server.Chemistry.EntitySystems
verb.Act = () =>
{
component.TransferAmount = FixedPoint2.New(amount);
_popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", amount)), uid, args.User);
_popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", amount)), uid, user);
};
// we want to sort by size, not alphabetically by the verb text.
@@ -84,18 +87,19 @@ namespace Content.Server.Chemistry.EntitySystems
}
}
private void OnAfterInteract(EntityUid uid, SolutionTransferComponent component, AfterInteractEvent args)
private void OnAfterInteract(Entity<SolutionTransferComponent> entity, ref AfterInteractEvent args)
{
if (!args.CanReach || args.Target == null)
return;
var target = args.Target!.Value;
var (uid, component) = entity;
//Special case for reagent tanks, because normally clicking another container will give solution, not take it.
if (component.CanReceive && !EntityManager.HasComponent<RefillableSolutionComponent>(target) // target must not be refillable (e.g. Reagent Tanks)
&& _solutionContainerSystem.TryGetDrainableSolution(target, out var targetDrain) // target must be drainable
&& EntityManager.TryGetComponent(uid, out RefillableSolutionComponent? refillComp)
&& _solutionContainerSystem.TryGetRefillableSolution(uid, out var ownerRefill, refillable: refillComp))
if (component.CanReceive && !EntityManager.HasComponent<RefillableSolutionComponent>(target) // target must not be refillable (e.g. Reagent Tanks)
&& _solutionContainerSystem.TryGetDrainableSolution(target, out var targetSoln, out _) // target must be drainable
&& EntityManager.TryGetComponent(uid, out RefillableSolutionComponent? refillComp)
&& _solutionContainerSystem.TryGetRefillableSolution((uid, refillComp, null), out var ownerSoln, out var ownerRefill))
{
@@ -106,7 +110,7 @@ namespace Content.Server.Chemistry.EntitySystems
transferAmount = FixedPoint2.Min(transferAmount, (FixedPoint2) refill.MaxRefill); // if the receiver has a smaller transfer limit, use that instead
}
var transferred = Transfer(args.User, target, targetDrain, uid, ownerRefill, transferAmount);
var transferred = Transfer(args.User, target, targetSoln.Value, uid, ownerSoln.Value, transferAmount);
if (transferred > 0)
{
var toTheBrim = ownerRefill.AvailableVolume == 0;
@@ -122,8 +126,8 @@ namespace Content.Server.Chemistry.EntitySystems
}
// if target is refillable, and owner is drainable
if (component.CanSend && _solutionContainerSystem.TryGetRefillableSolution(target, out var targetRefill)
&& _solutionContainerSystem.TryGetDrainableSolution(uid, out var ownerDrain))
if (component.CanSend && _solutionContainerSystem.TryGetRefillableSolution(target, out targetSoln, out var targetRefill)
&& _solutionContainerSystem.TryGetDrainableSolution(uid, out ownerSoln, out var ownerDrain))
{
var transferAmount = component.TransferAmount;
@@ -132,7 +136,7 @@ namespace Content.Server.Chemistry.EntitySystems
transferAmount = FixedPoint2.Min(transferAmount, (FixedPoint2) refill.MaxRefill);
}
var transferred = Transfer(args.User, uid, ownerDrain, target, targetRefill, transferAmount);
var transferred = Transfer(args.User, uid, ownerSoln.Value, target, targetSoln.Value, transferAmount);
if (transferred > 0)
{
@@ -150,9 +154,9 @@ namespace Content.Server.Chemistry.EntitySystems
/// <returns>The actual amount transferred.</returns>
public FixedPoint2 Transfer(EntityUid user,
EntityUid sourceEntity,
Solution source,
Entity<SolutionComponent> source,
EntityUid targetEntity,
Solution target,
Entity<SolutionComponent> target,
FixedPoint2 amount)
{
var transferAttempt = new SolutionTransferAttemptEvent(sourceEntity, targetEntity);
@@ -165,7 +169,8 @@ namespace Content.Server.Chemistry.EntitySystems
return FixedPoint2.Zero;
}
if (source.Volume == 0)
var sourceSolution = source.Comp.Solution;
if (sourceSolution.Volume == 0)
{
_popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-is-empty", ("target", sourceEntity)), sourceEntity, user);
return FixedPoint2.Zero;
@@ -179,19 +184,20 @@ namespace Content.Server.Chemistry.EntitySystems
return FixedPoint2.Zero;
}
if (target.AvailableVolume == 0)
var targetSolution = target.Comp.Solution;
if (targetSolution.AvailableVolume == 0)
{
_popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-is-full", ("target", targetEntity)), targetEntity, user);
return FixedPoint2.Zero;
}
var actualAmount = FixedPoint2.Min(amount, FixedPoint2.Min(source.Volume, target.AvailableVolume));
var actualAmount = FixedPoint2.Min(amount, FixedPoint2.Min(sourceSolution.Volume, targetSolution.AvailableVolume));
var solution = _solutionContainerSystem.Drain(sourceEntity, source, actualAmount);
_solutionContainerSystem.Refill(targetEntity, target, solution);
_adminLogger.Add(LogType.Action, LogImpact.Medium,
$"{EntityManager.ToPrettyString(user):player} transferred {string.Join(", ", solution.Contents)} to {EntityManager.ToPrettyString(targetEntity):entity}, which now contains {string.Join(", ", target.Contents)}");
$"{EntityManager.ToPrettyString(user):player} transferred {string.Join(", ", solution.Contents)} to {EntityManager.ToPrettyString(targetEntity):entity}, which now contains {SolutionContainerSystem.ToPrettyString(targetSolution)}");
return actualAmount;
}

View File

@@ -1,4 +1,5 @@
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Robust.Shared.Prototypes;
@@ -16,38 +17,38 @@ public sealed class TransformableContainerSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent<TransformableContainerComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<TransformableContainerComponent, SolutionChangedEvent>(OnSolutionChange);
SubscribeLocalEvent<TransformableContainerComponent, SolutionContainerChangedEvent>(OnSolutionChange);
}
private void OnMapInit(EntityUid uid, TransformableContainerComponent component, MapInitEvent args)
private void OnMapInit(Entity<TransformableContainerComponent> entity, ref MapInitEvent args)
{
var meta = MetaData(uid);
if (string.IsNullOrEmpty(component.InitialName))
var meta = MetaData(entity.Owner);
if (string.IsNullOrEmpty(entity.Comp.InitialName))
{
component.InitialName = meta.EntityName;
entity.Comp.InitialName = meta.EntityName;
}
if (string.IsNullOrEmpty(component.InitialDescription))
if (string.IsNullOrEmpty(entity.Comp.InitialDescription))
{
component.InitialDescription = meta.EntityDescription;
entity.Comp.InitialDescription = meta.EntityDescription;
}
}
private void OnSolutionChange(EntityUid owner, TransformableContainerComponent component,
SolutionChangedEvent args)
private void OnSolutionChange(Entity<TransformableContainerComponent> entity, ref SolutionContainerChangedEvent args)
{
if (!_solutionsSystem.TryGetFitsInDispenser(owner, out var solution))
if (!_solutionsSystem.TryGetFitsInDispenser(entity.Owner, out _, out var solution))
return;
//Transform container into initial state when emptied
if (component.CurrentReagent != null && solution.Contents.Count == 0)
if (entity.Comp.CurrentReagent != null && solution.Contents.Count == 0)
{
CancelTransformation(owner, component);
CancelTransformation(entity);
}
//the biggest reagent in the solution decides the appearance
var reagentId = solution.GetPrimaryReagentId();
//If biggest reagent didn't changed - don't change anything at all
if (component.CurrentReagent != null && component.CurrentReagent.ID == reagentId?.Prototype)
if (entity.Comp.CurrentReagent != null && entity.Comp.CurrentReagent.ID == reagentId?.Prototype)
{
return;
}
@@ -56,29 +57,29 @@ public sealed class TransformableContainerSystem : EntitySystem
if (!string.IsNullOrWhiteSpace(reagentId?.Prototype)
&& _prototypeManager.TryIndex(reagentId.Value.Prototype, out ReagentPrototype? proto))
{
var metadata = MetaData(owner);
var metadata = MetaData(entity.Owner);
var val = Loc.GetString("transformable-container-component-glass", ("name", proto.LocalizedName));
_metadataSystem.SetEntityName(owner, val, metadata);
_metadataSystem.SetEntityDescription(owner, proto.LocalizedDescription, metadata);
component.CurrentReagent = proto;
component.Transformed = true;
_metadataSystem.SetEntityName(entity.Owner, val, metadata);
_metadataSystem.SetEntityDescription(entity.Owner, proto.LocalizedDescription, metadata);
entity.Comp.CurrentReagent = proto;
entity.Comp.Transformed = true;
}
}
private void CancelTransformation(EntityUid owner, TransformableContainerComponent component)
private void CancelTransformation(Entity<TransformableContainerComponent> entity)
{
component.CurrentReagent = null;
component.Transformed = false;
entity.Comp.CurrentReagent = null;
entity.Comp.Transformed = false;
var metadata = MetaData(owner);
var metadata = MetaData(entity);
if (!string.IsNullOrEmpty(component.InitialName))
if (!string.IsNullOrEmpty(entity.Comp.InitialName))
{
_metadataSystem.SetEntityName(owner, component.InitialName, metadata);
_metadataSystem.SetEntityName(entity.Owner, entity.Comp.InitialName, metadata);
}
if (!string.IsNullOrEmpty(component.InitialDescription))
if (!string.IsNullOrEmpty(entity.Comp.InitialDescription))
{
_metadataSystem.SetEntityDescription(owner, component.InitialDescription, metadata);
_metadataSystem.SetEntityDescription(entity.Owner, entity.Comp.InitialDescription, metadata);
}
}
}

View File

@@ -1,9 +1,8 @@
using System.Numerics;
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using Content.Shared.Physics;
@@ -16,6 +15,7 @@ using Robust.Shared.Physics.Events;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Prototypes;
using Robust.Shared.Spawners;
using System.Numerics;
namespace Content.Server.Chemistry.EntitySystems
{
@@ -40,19 +40,20 @@ namespace Content.Server.Chemistry.EntitySystems
SubscribeLocalEvent<VaporComponent, StartCollideEvent>(HandleCollide);
}
private void HandleCollide(EntityUid uid, VaporComponent component, ref StartCollideEvent args)
private void HandleCollide(Entity<VaporComponent> entity, ref StartCollideEvent args)
{
if (!EntityManager.TryGetComponent(uid, out SolutionContainerManagerComponent? contents)) return;
if (!EntityManager.TryGetComponent(entity.Owner, out SolutionContainerManagerComponent? contents)) return;
foreach (var value in contents.Solutions.Values)
foreach (var (_, soln) in _solutionContainerSystem.EnumerateSolutions((entity.Owner, contents)))
{
_reactive.DoEntityReaction(args.OtherEntity, value, ReactionMethod.Touch);
var solution = soln.Comp.Solution;
_reactive.DoEntityReaction(args.OtherEntity, solution, ReactionMethod.Touch);
}
// Check for collision with a impassable object (e.g. wall) and stop
if ((args.OtherFixture.CollisionLayer & (int) CollisionGroup.Impassable) != 0 && args.OtherFixture.Hard)
{
EntityManager.QueueDeleteEntity(uid);
EntityManager.QueueDeleteEntity(entity);
}
}
@@ -83,28 +84,27 @@ namespace Content.Server.Chemistry.EntitySystems
return false;
}
if (!_solutionContainerSystem.TryGetSolution(vapor, VaporComponent.SolutionName,
out var vaporSolution))
if (!_solutionContainerSystem.TryGetSolution(vapor.Owner, VaporComponent.SolutionName, out var vaporSolution))
{
return false;
}
return _solutionContainerSystem.TryAddSolution(vapor, vaporSolution, solution);
return _solutionContainerSystem.TryAddSolution(vaporSolution.Value, solution);
}
public override void Update(float frameTime)
{
var query = EntityQueryEnumerator<VaporComponent, SolutionContainerManagerComponent, TransformComponent>();
while (query.MoveNext(out var uid, out var vaporComp, out var solution, out var xform))
while (query.MoveNext(out var uid, out var vaporComp, out var container, out var xform))
{
foreach (var (_, value) in solution.Solutions)
foreach (var (_, soln) in _solutionContainerSystem.EnumerateSolutions((uid, container)))
{
Update(frameTime, (uid, vaporComp), value, xform);
Update(frameTime, (uid, vaporComp), soln, xform);
}
}
}
private void Update(float frameTime, Entity<VaporComponent> ent, Solution contents, TransformComponent xform)
private void Update(float frameTime, Entity<VaporComponent> ent, Entity<SolutionComponent> soln, TransformComponent xform)
{
var (entity, vapor) = ent;
if (!vapor.Active)
@@ -112,6 +112,7 @@ namespace Content.Server.Chemistry.EntitySystems
vapor.ReactTimer += frameTime;
var contents = soln.Comp.Solution;
if (vapor.ReactTimer >= ReactTime && TryComp(xform.GridUid, out MapGridComponent? gridComp))
{
vapor.ReactTimer = 0;
@@ -131,7 +132,7 @@ namespace Content.Server.Chemistry.EntitySystems
reaction = reagentQuantity.Quantity;
}
_solutionContainerSystem.RemoveReagent(entity, contents, reagentQuantity.Reagent, reaction);
_solutionContainerSystem.RemoveReagent(soln, reagentQuantity.Reagent, reaction);
}
}