using Content.Server.Body.Systems;
using Content.Shared.Administration.Logs;
using Content.Shared.Body.Components;
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.Fluids.Components;
using Content.Shared.Rootable;
using Robust.Shared.Timing;
namespace Content.Server.Rootable;
// TODO: Move all of this to shared
///
/// Adds an action to toggle rooting to the ground, primarily for the Diona species.
///
public sealed class RootableSystem : SharedRootableSystem
{
[Dependency] private readonly ISharedAdminLogManager _logger = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
[Dependency] private readonly ReactiveSystem _reactive = default!;
[Dependency] private readonly BloodstreamSystem _blood = default!;
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator();
var curTime = _timing.CurTime;
while (query.MoveNext(out var uid, out var rooted, out var bloodstream))
{
if (!rooted.Rooted || rooted.PuddleEntity == null || curTime < rooted.NextUpdate || !PuddleQuery.TryComp(rooted.PuddleEntity, out var puddleComp))
continue;
rooted.NextUpdate += rooted.TransferFrequency;
PuddleReact((uid, rooted, bloodstream), (rooted.PuddleEntity.Value, puddleComp!));
}
}
///
/// Determines if the puddle is set up properly and if so, moves on to reacting.
///
private void PuddleReact(Entity entity, Entity puddleEntity)
{
if (!_solutionContainer.ResolveSolution(puddleEntity.Owner, puddleEntity.Comp.SolutionName, ref puddleEntity.Comp.Solution, out var solution) ||
solution.Contents.Count == 0)
{
return;
}
ReactWithEntity(entity, puddleEntity, solution);
}
///
/// Attempt to transfer an amount of the solution to the entity's bloodstream.
///
private void ReactWithEntity(Entity entity, Entity puddleEntity, Solution solution)
{
if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp2.ChemicalSolutionName, ref entity.Comp2.ChemicalSolution, out var chemSolution) || chemSolution.AvailableVolume <= 0)
return;
var availableTransfer = FixedPoint2.Min(solution.Volume, entity.Comp1.TransferRate);
var transferAmount = FixedPoint2.Min(availableTransfer, chemSolution.AvailableVolume);
var transferSolution = _solutionContainer.SplitSolution(puddleEntity.Comp.Solution!.Value, transferAmount);
_reactive.DoEntityReaction(entity, transferSolution, ReactionMethod.Ingestion);
if (_blood.TryAddToChemicals((entity, entity.Comp2), transferSolution))
{
// Log solution addition by puddle
_logger.Add(LogType.ForceFeed, LogImpact.Medium, $"{ToPrettyString(entity):target} absorbed puddle {SharedSolutionContainerSystem.ToPrettyString(transferSolution)}");
}
}
}