first commit
This commit is contained in:
37
NitroxServer/Helper/DeterministicGenerator.cs
Normal file
37
NitroxServer/Helper/DeterministicGenerator.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using NitroxModel.DataStructures;
|
||||
|
||||
namespace NitroxServer.Helper
|
||||
{
|
||||
public class DeterministicGenerator
|
||||
{
|
||||
private readonly Random random;
|
||||
|
||||
public DeterministicGenerator(string worldSeed, object reference)
|
||||
{
|
||||
random = new Random(worldSeed.GetHashCode() + reference.GetHashCode());
|
||||
}
|
||||
|
||||
public double NextDouble()
|
||||
{
|
||||
return random.NextDouble();
|
||||
}
|
||||
|
||||
public double NextDouble(double min, double max)
|
||||
{
|
||||
return random.NextDouble() * (max - min) + min;
|
||||
}
|
||||
|
||||
public int NextInt(int min, int max)
|
||||
{
|
||||
return random.Next(min, max);
|
||||
}
|
||||
|
||||
public NitroxId NextId()
|
||||
{
|
||||
byte[] bytes = new byte[16];
|
||||
random.NextBytes(bytes);
|
||||
return new NitroxId(bytes);
|
||||
}
|
||||
}
|
||||
}
|
142
NitroxServer/Helper/XORRandom.cs
Normal file
142
NitroxServer/Helper/XORRandom.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using NitroxModel.DataStructures.Unity;
|
||||
|
||||
namespace NitroxServer.Helper;
|
||||
|
||||
/// <summary>
|
||||
/// Stolen from <see href="https://gist.github.com/macklinb/a00be6b616cbf20fa95e4227575fe50b" />
|
||||
/// Aims at replicating UnityEngine.Random's implementation which is really uncommon because its uniform.
|
||||
/// </summary>
|
||||
public static class XORRandom
|
||||
{
|
||||
private static uint x;
|
||||
private static uint y;
|
||||
private static uint z;
|
||||
private static uint w;
|
||||
|
||||
private const uint MT19937 = 1812433253;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize Xorshift using a signed integer seed, calculating the state values using the initialization method from Mersenne Twister (MT19937)
|
||||
/// https://en.wikipedia.org/wiki/Mersenne_Twister#Initialization
|
||||
/// </summary>
|
||||
public static void InitSeed(int seed)
|
||||
{
|
||||
x = (uint)seed;
|
||||
y = (MT19937 * x + 1);
|
||||
z = (MT19937 * y + 1);
|
||||
w = (MT19937 * z + 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly set the state parameters
|
||||
/// </summary>
|
||||
public static void InitState(uint initial_x, uint initial_y, uint initial_z, uint initial_w)
|
||||
{
|
||||
x = initial_x;
|
||||
y = initial_y;
|
||||
z = initial_x;
|
||||
w = initial_w;
|
||||
}
|
||||
|
||||
public static uint XORShift()
|
||||
{
|
||||
uint t = x ^ (x << 11);
|
||||
x = y; y = z; z = w;
|
||||
return w = w ^ (w >> 19) ^ t ^ (t >> 8);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Alias of base Next/XORShift.
|
||||
/// UnityEngine.Random doesn't have any uint functions so these functions behave exactly like int Random.Range
|
||||
/// </summary>
|
||||
public static uint NextUInt()
|
||||
{
|
||||
return XORShift();
|
||||
}
|
||||
|
||||
/// <returns>
|
||||
/// A random unsigned 32-bit integer value in the range 0 (inclusive) to max (exclusive)
|
||||
/// </returns>
|
||||
public static uint NextUIntMax(uint max)
|
||||
{
|
||||
if (max == 0) return 0;
|
||||
return XORShift() % max;
|
||||
}
|
||||
|
||||
/// <returns>
|
||||
/// A random unsigned 32-bit integer value in the range min (inclusive) to max (exclusive)
|
||||
/// </returns>
|
||||
public static uint NextUIntRange(uint min, uint max)
|
||||
{
|
||||
if (max - min == 0) return min;
|
||||
|
||||
if (max < min)
|
||||
return min - XORShift() % (max + min);
|
||||
else
|
||||
return min + XORShift() % (max - min);
|
||||
}
|
||||
|
||||
/// <returns>
|
||||
/// A random signed 32-bit integer value in the range -2,147,483,648 (inclusive) to 2,147,483,647 (inclusive)
|
||||
/// </returns>
|
||||
public static int NextInt()
|
||||
{
|
||||
return (int)(XORShift() % int.MaxValue);
|
||||
}
|
||||
|
||||
public static int NextIntMax(int max)
|
||||
{
|
||||
return NextInt() % max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A random signed 32-bit integer value in the range min (inclusive) to max (exclusive)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you only need to generate positive integers, use NextUIntRange instead
|
||||
/// </remarks>
|
||||
public static int NextIntRange(int min, int max)
|
||||
{
|
||||
// If max and min are the same, just return min since it will result in a DivideByZeroException
|
||||
if (max - min == 0) return min;
|
||||
|
||||
// Do operations in Int64 to prevent overflow that might be caused by any of the following operations
|
||||
// I'm sure there's a faster/better way to do this and avoid casting, but we prefer equivalence to Unity over performance
|
||||
long minLong = min;
|
||||
long maxLong = max;
|
||||
long r = XORShift();
|
||||
|
||||
// Flip the first operator if the max is lower than the min,
|
||||
if (max < min)
|
||||
{
|
||||
return (int)(minLong - r % (maxLong - minLong));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (int)(minLong + r % (maxLong - minLong));
|
||||
}
|
||||
}
|
||||
|
||||
/// <returns>
|
||||
/// A random floating point between 0.0 and 1.0 (inclusive?)
|
||||
/// </returns>
|
||||
public static float NextFloat()
|
||||
{
|
||||
return 1.0f - NextFloatRange(0.0f, 1.0f);
|
||||
}
|
||||
|
||||
/// <returns>
|
||||
/// A random floating point between min (inclusive) and max (exclusive)
|
||||
/// </returns>
|
||||
public static float NextFloatRange(float min, float max)
|
||||
{
|
||||
return (min - max) * ((float)(XORShift() << 9) / 0xFFFFFFFF) + max;
|
||||
}
|
||||
|
||||
public static NitroxVector3 NextInsideSphere(float radius = 1f)
|
||||
{
|
||||
NitroxVector3 pointInUnitSphere = new NitroxVector3(NextFloat(), NextFloat(), NextFloat()).Normalized;
|
||||
return pointInUnitSphere * NextFloatRange(0, radius);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user