refactor: new overload for SharedRandomExtensions.HashCodeCombine (#40990)

* refactor: new overload for SharedRandomExtensions.HashCodeCombine

* Update Content.Shared/Random/Helpers/SharedRandomExtensions.cs

---------

Co-authored-by: pa.pecherskij <pa.pecherskij@interfax.ru>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
This commit is contained in:
Fildrance
2025-10-20 00:29:31 +03:00
committed by GitHub
parent 9c44c1707e
commit 22fe5185a3
10 changed files with 23 additions and 17 deletions

View File

@@ -217,7 +217,7 @@ public abstract class SharedBloodstreamSystem : EntitySystem
// TODO: Replace with RandomPredicted once the engine PR is merged // TODO: Replace with RandomPredicted once the engine PR is merged
// Use both the receiver and the damage causing entity for the seed so that we have different results for multiple attacks in the same tick // Use both the receiver and the damage causing entity for the seed so that we have different results for multiple attacks in the same tick
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id, GetNetEntity(args.Origin)?.Id ?? 0 }); var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id, GetNetEntity(args.Origin)?.Id ?? 0 );
var rand = new System.Random(seed); var rand = new System.Random(seed);
var prob = Math.Clamp(totalFloat / 25, 0, 1); var prob = Math.Clamp(totalFloat / 25, 0, 1);
if (totalFloat > 0 && rand.Prob(prob)) if (totalFloat > 0 && rand.Prob(prob))

View File

@@ -49,7 +49,7 @@ public sealed class ClumsySystem : EntitySystem
return; return;
// TODO: Replace with RandomPredicted once the engine PR is merged // TODO: Replace with RandomPredicted once the engine PR is merged
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id }); var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed); var rand = new System.Random(seed);
if (!rand.Prob(ent.Comp.ClumsyDefaultCheck)) if (!rand.Prob(ent.Comp.ClumsyDefaultCheck))
return; return;
@@ -68,7 +68,7 @@ public sealed class ClumsySystem : EntitySystem
return; return;
// TODO: Replace with RandomPredicted once the engine PR is merged // TODO: Replace with RandomPredicted once the engine PR is merged
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id }); var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed); var rand = new System.Random(seed);
if (!rand.Prob(ent.Comp.ClumsyDefaultCheck)) if (!rand.Prob(ent.Comp.ClumsyDefaultCheck))
return; return;
@@ -87,7 +87,7 @@ public sealed class ClumsySystem : EntitySystem
return; return;
// TODO: Replace with RandomPredicted once the engine PR is merged // TODO: Replace with RandomPredicted once the engine PR is merged
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(args.Item).Id }); var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(args.Item).Id);
var rand = new System.Random(seed); var rand = new System.Random(seed);
if (!rand.Prob(ent.Comp.ClumsyDefaultCheck)) if (!rand.Prob(ent.Comp.ClumsyDefaultCheck))
return; return;
@@ -121,7 +121,7 @@ public sealed class ClumsySystem : EntitySystem
return; return;
// TODO: Replace with RandomPredicted once the engine PR is merged // TODO: Replace with RandomPredicted once the engine PR is merged
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(args.Gun).Id }); var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(args.Gun).Id);
var rand = new System.Random(seed); var rand = new System.Random(seed);
if (!rand.Prob(ent.Comp.ClumsyDefaultCheck)) if (!rand.Prob(ent.Comp.ClumsyDefaultCheck))
return; return;
@@ -146,7 +146,7 @@ public sealed class ClumsySystem : EntitySystem
return; return;
// TODO: Replace with RandomPredicted once the engine PR is merged // TODO: Replace with RandomPredicted once the engine PR is merged
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id }); var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed); var rand = new System.Random(seed);
if (!_cfg.GetCVar(CCVars.GameTableBonk) && !rand.Prob(ent.Comp.ClumsyDefaultCheck)) if (!_cfg.GetCVar(CCVars.GameTableBonk) && !rand.Prob(ent.Comp.ClumsyDefaultCheck))
return; return;

View File

@@ -1,4 +1,4 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Content.Shared.Administration.Logs; using Content.Shared.Administration.Logs;
using Content.Shared.Chemistry; using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Reaction; using Content.Shared.Chemistry.Reaction;
@@ -91,7 +91,7 @@ public sealed partial class SharedEntityEffectsSystem : EntitySystem, IEntityEff
// TODO: Replace with proper random prediciton when it exists. // TODO: Replace with proper random prediciton when it exists.
if (effect.Probability <= 1f) if (effect.Probability <= 1f)
{ {
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(target).Id, 0 }); var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(target).Id, 0);
var rand = new System.Random(seed); var rand = new System.Random(seed);
if (!rand.Prob(effect.Probability)) if (!rand.Prob(effect.Probability))
return false; return false;

View File

@@ -206,7 +206,7 @@ public abstract class SharedFlashSystem : EntitySystem
foreach (var entity in _entSet) foreach (var entity in _entSet)
{ {
// TODO: Use RandomPredicted https://github.com/space-wizards/RobustToolbox/pull/5849 // TODO: Use RandomPredicted https://github.com/space-wizards/RobustToolbox/pull/5849
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(entity).Id }); var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(entity).Id);
var rand = new System.Random(seed); var rand = new System.Random(seed);
if (!rand.Prob(probability)) if (!rand.Prob(probability))
continue; continue;

View File

@@ -292,7 +292,7 @@ public sealed class SharedKitchenSpikeSystem : EntitySystem
// Get a random entry to spawn. // Get a random entry to spawn.
// TODO: Replace with RandomPredicted once the engine PR is merged // TODO: Replace with RandomPredicted once the engine PR is merged
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_gameTiming.CurTick.Value, GetNetEntity(ent).Id }); var seed = SharedRandomExtensions.HashCodeCombine((int)_gameTiming.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed); var rand = new System.Random(seed);
var index = rand.Next(butcherable.SpawnedEntities.Count); var index = rand.Next(butcherable.SpawnedEntities.Count);

View File

@@ -1,4 +1,4 @@
using Content.Shared.Containers.ItemSlots; using Content.Shared.Containers.ItemSlots;
using Content.Shared.Hands.Components; using Content.Shared.Hands.Components;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.Components;
@@ -66,7 +66,7 @@ public sealed partial class IngestionSystem
return; return;
// TODO: Once we have predicted randomness delete this for something sane... // TODO: Once we have predicted randomness delete this for something sane...
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(entity).Id, GetNetEntity(userUid).Id }); var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(entity).Id, GetNetEntity(userUid).Id);
var rand = new System.Random(seed); var rand = new System.Random(seed);
if (!rand.Prob(entity.Comp.BreakChance)) if (!rand.Prob(entity.Comp.BreakChance))

View File

@@ -38,7 +38,7 @@ public sealed class MessyDrinkerSystem : EntitySystem
return; return;
// TODO: Replace with RandomPredicted once the engine PR is merged // TODO: Replace with RandomPredicted once the engine PR is merged
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id }); var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed); var rand = new System.Random(seed);
if (!rand.Prob(ent.Comp.SpillChance)) if (!rand.Prob(ent.Comp.SpillChance))
return; return;

View File

@@ -185,6 +185,12 @@ namespace Content.Shared.Random.Helpers
throw new InvalidOperationException($"Invalid weighted pick for {prototype.ID}!"); throw new InvalidOperationException($"Invalid weighted pick for {prototype.ID}!");
} }
/// <inheritdoc cref="HashCodeCombine(IReadOnlyCollection{int})"/>
public static int HashCodeCombine(params int[] values)
{
return HashCodeCombine((IReadOnlyCollection<int>)values);
}
/// <summary> /// <summary>
/// A very simple, deterministic djb2 hash function for generating a combined seed for the random number generator. /// A very simple, deterministic djb2 hash function for generating a combined seed for the random number generator.
/// We can't use HashCode.Combine because that is initialized with a random value, creating different results on the server and client. /// We can't use HashCode.Combine because that is initialized with a random value, creating different results on the server and client.
@@ -192,10 +198,10 @@ namespace Content.Shared.Random.Helpers
/// <example> /// <example>
/// Combine the current game tick with a NetEntity Id in order to not get the same random result if this is called multiple times in the same tick. /// Combine the current game tick with a NetEntity Id in order to not get the same random result if this is called multiple times in the same tick.
/// <code> /// <code>
/// var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id }); /// var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
/// </code> /// </code>
/// </example> /// </example>
public static int HashCodeCombine(List<int> values) public static int HashCodeCombine(IReadOnlyCollection<int> values)
{ {
int hash = 5381; int hash = 5381;
foreach (var value in values) foreach (var value in values)

View File

@@ -56,7 +56,7 @@ public sealed partial class CatchableSystem : EntitySystem
return; return;
// TODO: Replace with RandomPredicted once the engine PR is merged // TODO: Replace with RandomPredicted once the engine PR is merged
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(ent).Id }); var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed); var rand = new System.Random(seed);
if (!rand.Prob(ent.Comp.CatchChance)) if (!rand.Prob(ent.Comp.CatchChance))
return; return;

View File

@@ -53,7 +53,7 @@ public sealed class NarcolepsySystem : EntitySystem
continue; continue;
// TODO: Replace with RandomPredicted once the engine PR is merged // TODO: Replace with RandomPredicted once the engine PR is merged
var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(uid).Id }); var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(uid).Id);
var rand = new System.Random(seed); var rand = new System.Random(seed);
var duration = narcolepsy.MinDurationOfIncident + (narcolepsy.MaxDurationOfIncident - narcolepsy.MinDurationOfIncident) * rand.NextDouble(); var duration = narcolepsy.MinDurationOfIncident + (narcolepsy.MaxDurationOfIncident - narcolepsy.MinDurationOfIncident) * rand.NextDouble();