From b029d05620292f4c9c793edfb2a52254f4f4d484 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Thu, 1 Feb 2024 04:36:41 +0100 Subject: [PATCH] Fix chemical fuel generator division by zero (#24793) This would happen when they run out of fuel. --- .../Power/Generator/GeneratorSystem.cs | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/Content.Server/Power/Generator/GeneratorSystem.cs b/Content.Server/Power/Generator/GeneratorSystem.cs index a9ec2e642b..a75d1e4113 100644 --- a/Content.Server/Power/Generator/GeneratorSystem.cs +++ b/Content.Server/Power/Generator/GeneratorSystem.cs @@ -92,17 +92,28 @@ public sealed class GeneratorSystem : SharedGeneratorSystem if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution, out var solution)) return; - var totalAvailableReagents = solution.GetTotalPrototypeQuantity(entity.Comp.Reagents.Keys.Select(p => p.Id).ToArray()).Value; + var totalReagent = 0f; + foreach (var (reagentId, _) in entity.Comp.Reagents) + { + totalReagent += solution.GetTotalPrototypeQuantity(reagentId).Float(); + totalReagent += entity.Comp.FractionalReagents.GetValueOrDefault(reagentId); + } + + if (totalReagent == 0) + return; + foreach (var (reagentId, multiplier) in entity.Comp.Reagents) { - var availableReagent = solution.GetTotalPrototypeQuantity(reagentId).Value; - var removalPercentage = availableReagent / totalAvailableReagents; var fractionalReagent = entity.Comp.FractionalReagents.GetValueOrDefault(reagentId); + var availableReagent = solution.GetTotalPrototypeQuantity(reagentId); + var availForRatio = fractionalReagent + availableReagent.Float(); + var removalPercentage = availForRatio / totalReagent; + var toRemove = RemoveFractionalFuel( ref fractionalReagent, args.FuelUsed * removalPercentage, multiplier * FixedPoint2.Epsilon.Float(), - availableReagent); + availableReagent.Value); entity.Comp.FractionalReagents[reagentId] = fractionalReagent; _solutionContainer.RemoveReagent(entity.Comp.Solution.Value, reagentId, FixedPoint2.FromCents(toRemove)); @@ -114,15 +125,12 @@ public sealed class GeneratorSystem : SharedGeneratorSystem if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution, out var solution)) return; - var totalAvailableReagents = solution.GetTotalPrototypeQuantity(entity.Comp.Reagents.Keys.Select(p => p.Id).ToArray()); var fuel = 0f; foreach (var (reagentId, multiplier) in entity.Comp.Reagents) { - var availableReagent = solution.GetTotalPrototypeQuantity(reagentId); - var percentage = availableReagent / totalAvailableReagents; - var fractionalReagent = (availableReagent * percentage).Float(); + var reagent = solution.GetTotalPrototypeQuantity(reagentId).Float(); + reagent += entity.Comp.FractionalReagents.GetValueOrDefault(reagentId) * FixedPoint2.Epsilon.Float(); - var reagent = entity.Comp.FractionalReagents.GetValueOrDefault(reagentId) * FixedPoint2.Epsilon.Float() + fractionalReagent; fuel += reagent * multiplier; } @@ -143,6 +151,10 @@ public sealed class GeneratorSystem : SharedGeneratorSystem private int RemoveFractionalFuel(ref float fractional, float fuelUsed, float multiplier, int availableQuantity) { + // Just a sanity thing since I got worried this might be possible. + if (!float.IsFinite(fractional)) + fractional = 0; + fractional -= fuelUsed / multiplier; if (fractional >= 0) return 0; -- 2.51.2