From 0af17c94848724c0d56d4be12c01983b4793b8bf Mon Sep 17 00:00:00 2001 From: Cinder Date: Wed, 27 May 2015 08:55:49 -0600 Subject: llListRandomize() wasn't very random Signed-off-by: Diva Canto --- OpenSim/Framework/Util.cs | 51 ++++++++++++++++++++++ .../Shared/Api/Implementation/LSL_Api.cs | 13 +++--- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 56a90b1..2d0b280 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -3036,4 +3036,55 @@ namespace OpenSim.Framework } } } + + public class BetterRandom + { + private const int BufferSize = 1024; // must be a multiple of 4 + private byte[] RandomBuffer; + private int BufferOffset; + private RNGCryptoServiceProvider rng; + public BetterRandom() + { + RandomBuffer = new byte[BufferSize]; + rng = new RNGCryptoServiceProvider(); + BufferOffset = RandomBuffer.Length; + } + private void FillBuffer() + { + rng.GetBytes(RandomBuffer); + BufferOffset = 0; + } + public int Next() + { + if (BufferOffset >= RandomBuffer.Length) + { + FillBuffer(); + } + int val = BitConverter.ToInt32(RandomBuffer, BufferOffset) & 0x7fffffff; + BufferOffset += sizeof(int); + return val; + } + public int Next(int maxValue) + { + return Next() % maxValue; + } + public int Next(int minValue, int maxValue) + { + if (maxValue < minValue) + { + throw new ArgumentOutOfRangeException("maxValue must be greater than or equal to minValue"); + } + int range = maxValue - minValue; + return minValue + Next(range); + } + public double NextDouble() + { + int val = Next(); + return (double)val / int.MaxValue; + } + public void GetBytes(byte[] buff) + { + rng.GetBytes(buff); + } + } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index c5e02a6..53c198e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5631,7 +5631,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List llListRandomize(LSL_List src, int stride) { LSL_List result; - Random rand = new Random(); + BetterRandom rand = new BetterRandom(); int chunkk; int[] chunks; @@ -5647,24 +5647,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // If not, then return the src list. This also // traps those cases where stride > length. - if (src.Length != stride && src.Length%stride == 0) + if (src.Length != stride && src.Length % stride == 0) { chunkk = src.Length/stride; chunks = new int[chunkk]; for (int i = 0; i < chunkk; i++) + { chunks[i] = i; + } // Knuth shuffle the chunkk index - for (int i = chunkk - 1; i >= 1; i--) + for (int i = chunkk - 1; i > 0; i--) { // Elect an unrandomized chunk to swap int index = rand.Next(i + 1); - int tmp; // and swap position with first unrandomized chunk - tmp = chunks[i]; + int tmp = chunks[i]; chunks[i] = chunks[index]; chunks[index] = tmp; } @@ -5677,7 +5678,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { for (int j = 0; j < stride; j++) { - result.Add(src.Data[chunks[i]*stride+j]); + result.Add(src.Data[chunks[i] * stride + j]); } } } -- cgit v1.1