SRMP-Public/SRMP/Lidgren.Network/NetRandom.cs
2023-05-29 22:23:11 +02:00

177 lines
4.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Threading;
namespace Lidgren.Network
{
/// <summary>
/// NetRandom base class
/// </summary>
public abstract class NetRandom : Random
{
/// <summary>
/// Get global instance of NetRandom (uses MWCRandom)
/// </summary>
public static NetRandom Instance = new MWCRandom();
private const double c_realUnitInt = 1.0 / ((double)int.MaxValue + 1.0);
/// <summary>
/// Constructor with randomized seed
/// </summary>
public NetRandom()
{
Initialize(NetRandomSeed.GetUInt32());
}
/// <summary>
/// Constructor with provided 32 bit seed
/// </summary>
public NetRandom(int seed)
{
Initialize((uint)seed);
}
/// <summary>
/// (Re)initialize this instance with provided 32 bit seed
/// </summary>
[CLSCompliant(false)]
public virtual void Initialize(uint seed)
{
// should be abstract, but non-CLS compliant methods can't be abstract!
throw new NotImplementedException("Implement this in inherited classes");
}
/// <summary>
/// Generates a random value from UInt32.MinValue to UInt32.MaxValue, inclusively
/// </summary>
[CLSCompliant(false)]
public virtual uint NextUInt32()
{
// should be abstract, but non-CLS compliant methods can't be abstract!
throw new NotImplementedException("Implement this in inherited classes");
}
/// <summary>
/// Generates a random value that is greater or equal than 0 and less than Int32.MaxValue
/// </summary>
public override int Next()
{
var retval = (int)(0x7FFFFFFF & NextUInt32());
if (retval == 0x7FFFFFFF)
return NextInt32();
return retval;
}
/// <summary>
/// Generates a random value greater or equal than 0 and less or equal than Int32.MaxValue (inclusively)
/// </summary>
public int NextInt32()
{
return (int)(0x7FFFFFFF & NextUInt32());
}
/// <summary>
/// Returns random value larger or equal to 0.0 and less than 1.0
/// </summary>
public override double NextDouble()
{
return c_realUnitInt * NextInt32();
}
/// <summary>
/// Returns random value is greater or equal than 0.0 and less than 1.0
/// </summary>
protected override double Sample()
{
return c_realUnitInt * NextInt32();
}
/// <summary>
/// Returns random value is greater or equal than 0.0f and less than 1.0f
/// </summary>
public float NextSingle()
{
var retval = (float)(c_realUnitInt * NextInt32());
if (retval == 1.0f)
return NextSingle();
return retval;
}
/// <summary>
/// Returns a random value is greater or equal than 0 and less than maxValue
/// </summary>
public override int Next(int maxValue)
{
return (int)(NextDouble() * maxValue);
}
/// <summary>
/// Returns a random value is greater or equal than minValue and less than maxValue
/// </summary>
public override int Next(int minValue, int maxValue)
{
return minValue + (int)(NextDouble() * (double)(maxValue - minValue));
}
/// <summary>
/// Generates a random value between UInt64.MinValue to UInt64.MaxValue
/// </summary>
[CLSCompliant(false)]
public ulong NextUInt64()
{
ulong retval = NextUInt32();
retval |= NextUInt32() << 32;
return retval;
}
private uint m_boolValues;
private int m_nextBoolIndex;
/// <summary>
/// Returns true or false, randomly
/// </summary>
public bool NextBool()
{
if (m_nextBoolIndex >= 32)
{
m_boolValues = NextUInt32();
m_nextBoolIndex = 1;
}
var retval = ((m_boolValues >> m_nextBoolIndex) & 1) == 1;
m_nextBoolIndex++;
return retval;
}
/// <summary>
/// Fills all bytes from offset to offset + length in buffer with random values
/// </summary>
public virtual void NextBytes(byte[] buffer, int offset, int length)
{
int full = length / 4;
int ptr = offset;
for (int i = 0; i < full; i++)
{
uint r = NextUInt32();
buffer[ptr++] = (byte)r;
buffer[ptr++] = (byte)(r >> 8);
buffer[ptr++] = (byte)(r >> 16);
buffer[ptr++] = (byte)(r >> 24);
}
int rest = length - (full * 4);
for (int i = 0; i < rest; i++)
buffer[ptr++] = (byte)NextUInt32();
}
/// <summary>
/// Fill the specified buffer with random values
/// </summary>
public override void NextBytes(byte[] buffer)
{
NextBytes(buffer, 0, buffer.Length);
}
}
}