From: Princess Cheeseballs <66055347+Princess-Cheeseballs@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:48:30 +0000 (-0800) Subject: [Bugfix/Optimization] Metabolize Foreign Blood (#41892) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=c93fea42dd52f704f413d31da7eefdb3c3520d3c;p=space-station-14.git [Bugfix/Optimization] Metabolize Foreign Blood (#41892) * Metabolize foreign blood * fix * misc --------- Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> --- diff --git a/Content.Server/Body/Systems/BloodstreamSystem.cs b/Content.Server/Body/Systems/BloodstreamSystem.cs index 08f640711a..b142d86fad 100644 --- a/Content.Server/Body/Systems/BloodstreamSystem.cs +++ b/Content.Server/Body/Systems/BloodstreamSystem.cs @@ -30,12 +30,12 @@ public sealed class BloodstreamSystem : SharedBloodstreamSystem bloodSolution.MaxVolume = entity.Comp.BloodReferenceSolution.Volume * entity.Comp.MaxVolumeModifier; tempSolution.MaxVolume = entity.Comp.BleedPuddleThreshold * 4; // give some leeway, for chemstream as well + entity.Comp.BloodReferenceSolution.SetReagentData(GetEntityBloodData((entity, entity.Comp))); // Fill blood solution with BLOOD // The DNA string might not be initialized yet, but the reagent data gets updated in the GenerateDnaEvent subscription var solution = entity.Comp.BloodReferenceSolution.Clone(); solution.ScaleTo(entity.Comp.BloodReferenceSolution.Volume - bloodSolution.Volume); - solution.SetReagentData(GetEntityBloodData(entity.Owner)); bloodSolution.AddSolution(solution, PrototypeManager); } @@ -44,11 +44,14 @@ public sealed class BloodstreamSystem : SharedBloodstreamSystem { if (SolutionContainer.ResolveSolution(entity.Owner, entity.Comp.BloodSolutionName, ref entity.Comp.BloodSolution, out var bloodSolution)) { + var data = NewEntityBloodData(entity); + entity.Comp.BloodReferenceSolution.SetReagentData(data); + foreach (var reagent in bloodSolution.Contents) { List reagentData = reagent.Reagent.EnsureReagentData(); reagentData.RemoveAll(x => x is DnaData); - reagentData.AddRange(GetEntityBloodData(entity.Owner)); + reagentData.AddRange(data); } } else diff --git a/Content.Server/Body/Systems/MetabolizerSystem.cs b/Content.Server/Body/Systems/MetabolizerSystem.cs index 35c7b0572a..8e329bc420 100644 --- a/Content.Server/Body/Systems/MetabolizerSystem.cs +++ b/Content.Server/Body/Systems/MetabolizerSystem.cs @@ -16,7 +16,6 @@ using Content.Shared.EntityEffects.Effects.Body; using Content.Shared.EntityEffects.Effects.Solution; using Content.Shared.FixedPoint; using Content.Shared.Mobs.Systems; -using Content.Shared.Random.Helpers; using Robust.Shared.Collections; using Robust.Shared.Prototypes; using Robust.Shared.Random; @@ -138,8 +137,7 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem var list = solution.Contents.ToList(); // Collecting blood reagent for filtering - var bloodList = new List(); - var ev = new MetabolismExclusionEvent(bloodList); + var ev = new MetabolismExclusionEvent(); RaiseLocalEvent(solutionEntityUid.Value, ref ev); // randomize the reagent list so we don't have any weird quirks @@ -155,7 +153,7 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem continue; // Skip blood reagents - if (bloodList.Contains(reagent.Prototype)) + if (ev.Reagents.Contains(reagent)) continue; var mostToRemove = FixedPoint2.Zero; diff --git a/Content.Shared/Body/Components/BloodstreamComponent.cs b/Content.Shared/Body/Components/BloodstreamComponent.cs index 8309397b62..533b486da5 100644 --- a/Content.Shared/Body/Components/BloodstreamComponent.cs +++ b/Content.Shared/Body/Components/BloodstreamComponent.cs @@ -1,6 +1,7 @@ using Content.Shared.Alert; using Content.Shared.Body.Systems; using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.Reagent; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; @@ -137,9 +138,9 @@ public sealed partial class BloodstreamComponent : Component // TODO probably damage bleed thresholds. /// - /// Modifier applied to to determine maximum volume for bloodstream. + /// Modifier applied to to determine maximum volume for bloodstream. /// - [DataField] + [DataField, AutoNetworkedField] public float MaxVolumeModifier = 2f; /// @@ -151,6 +152,13 @@ public sealed partial class BloodstreamComponent : Component [DataField, AutoNetworkedField] public Solution BloodReferenceSolution = new([new("Blood", 300)]); + /// + /// Caches the blood data of an entity. + /// This is modified by DNA on init so it's not savable. + /// + [ViewVariables(VVAccess.ReadOnly)] + public List? BloodData; + /// /// Name/Key that is indexed by. /// diff --git a/Content.Shared/Body/Events/MetabolismExclusionEvent.cs b/Content.Shared/Body/Events/MetabolismExclusionEvent.cs index 791b8ed959..3626e5af77 100644 --- a/Content.Shared/Body/Events/MetabolismExclusionEvent.cs +++ b/Content.Shared/Body/Events/MetabolismExclusionEvent.cs @@ -1,3 +1,5 @@ +using Content.Shared.Chemistry.Reagent; + namespace Content.Shared.Body.Events; /// @@ -5,4 +7,7 @@ namespace Content.Shared.Body.Events; /// blood like reagents for metabolism to skip. /// [ByRefEvent] -public readonly record struct MetabolismExclusionEvent(List ReagentList); \ No newline at end of file +public readonly record struct MetabolismExclusionEvent() +{ + public readonly List Reagents = []; +} diff --git a/Content.Shared/Body/Systems/SharedBloodstreamSystem.cs b/Content.Shared/Body/Systems/SharedBloodstreamSystem.cs index 7c8fca6deb..5f3794acd2 100644 --- a/Content.Shared/Body/Systems/SharedBloodstreamSystem.cs +++ b/Content.Shared/Body/Systems/SharedBloodstreamSystem.cs @@ -296,9 +296,9 @@ public abstract class SharedBloodstreamSystem : EntitySystem private void OnMetabolismExclusion(Entity ent, ref MetabolismExclusionEvent args) { // Adding all blood reagents for filtering blood in metabolizer - foreach (var (reagentId, _) in ent.Comp.BloodReferenceSolution) + foreach (var (reagent, _) in ent.Comp.BloodReferenceSolution) { - args.ReagentList.Add(reagentId.Prototype); + args.Reagents.Add(reagent); } } @@ -424,8 +424,7 @@ public abstract class SharedBloodstreamSystem : EntitySystem if (error > 0) { error = FixedPoint2.Min(error, adjustedAmount); - var reagentToAdd = new ReagentId(referenceReagent.Prototype, GetEntityBloodData(ent)); - bloodSolution.AddReagent(reagentToAdd, error); + bloodSolution.AddReagent(referenceReagent, error); } else if (error < 0) { @@ -561,14 +560,24 @@ public abstract class SharedBloodstreamSystem : EntitySystem var solution = ent.Comp.BloodReferenceSolution.Clone(); solution.ScaleSolution(currentVolume / solution.Volume); - solution.SetReagentData(GetEntityBloodData(ent)); SolutionContainer.AddSolution(ent.Comp.BloodSolution.Value, solution); } /// /// Get the reagent data for blood that a specific entity should have. /// - public List GetEntityBloodData(EntityUid uid) + public List GetEntityBloodData(Entity entity) + { + if (!Resolve(entity, ref entity.Comp)) + return NewEntityBloodData(entity); + + return entity.Comp.BloodData ?? NewEntityBloodData(entity); + } + + /// + /// Gets new blood data for this entity and caches it in + /// + protected List NewEntityBloodData(EntityUid uid) { var bloodData = new List(); var dnaData = new DnaData(); @@ -579,7 +588,6 @@ public abstract class SharedBloodstreamSystem : EntitySystem dnaData.DNA = Loc.GetString("forensics-dna-unknown"); bloodData.Add(dnaData); - return bloodData; } } diff --git a/Content.Shared/Medical/VomitSystem.cs b/Content.Shared/Medical/VomitSystem.cs index cf927754e3..bdde1f0c98 100644 --- a/Content.Shared/Medical/VomitSystem.cs +++ b/Content.Shared/Medical/VomitSystem.cs @@ -121,7 +121,7 @@ public sealed class VomitSystem : EntitySystem } // Makes a vomit solution the size of 90% of the chemicals removed from the chemstream - solution.AddReagent(new ReagentId(VomitPrototype, _bloodstream.GetEntityBloodData(uid)), vomitAmount); + solution.AddReagent(new ReagentId(VomitPrototype, _bloodstream.GetEntityBloodData((uid, bloodStream))), vomitAmount); } if (_puddle.TrySpillAt(uid, solution, out var puddle, false))