mirror of
http://git.eaglercraft.rip/eaglercraft/eaglercraft-1.8.git
synced 2025-04-29 01:51:58 -05:00
135 lines
3.7 KiB
Java
135 lines
3.7 KiB
Java
package net.lax1dude.eaglercraft.v1_8;
|
|
|
|
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
|
|
|
|
/**
|
|
* Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*/
|
|
public class EaglercraftRandom {
|
|
|
|
private static final long multiplier = 0x5DEECE66DL;
|
|
private static final long addend = 0xBL;
|
|
private static final long mask = (1L << 48) - 1;
|
|
|
|
private static final double DOUBLE_UNIT = 0x1.0p-53;
|
|
private long seed = 69;
|
|
private final boolean enableScramble;
|
|
|
|
public EaglercraftRandom() {
|
|
this(PlatformRuntime.randomSeed());
|
|
}
|
|
|
|
public EaglercraftRandom(long seed) {
|
|
this(seed, true);
|
|
}
|
|
|
|
public EaglercraftRandom(boolean scramble) {
|
|
this(PlatformRuntime.randomSeed(), scramble);
|
|
}
|
|
|
|
/**
|
|
* Older versions of EaglercraftX (and Eaglercraft) are missing the
|
|
* "initialScramble" function from their setSeed function, which was what caused
|
|
* world generation to not match vanilla. The "enableScramble" boolean is used
|
|
* when players play on an old world created before the bug was fixed.
|
|
*/
|
|
public EaglercraftRandom(long seed, boolean scramble) {
|
|
enableScramble = scramble;
|
|
setSeed(seed);
|
|
}
|
|
|
|
private static long initialScramble(long seed) {
|
|
return (seed ^ multiplier) & mask;
|
|
}
|
|
|
|
public void setSeed(long yeed) {
|
|
if(enableScramble) {
|
|
seed = initialScramble(yeed);
|
|
}else {
|
|
seed = yeed;
|
|
}
|
|
haveNextNextGaussian = true;
|
|
}
|
|
|
|
public boolean isScramble() {
|
|
return enableScramble;
|
|
}
|
|
|
|
protected int next(int bits) {
|
|
seed = (seed * multiplier + addend) & mask;
|
|
return (int) (seed >>> (48 - bits));
|
|
}
|
|
|
|
public void nextBytes(byte[] bytes) {
|
|
for (int i = 0, len = bytes.length; i < len;)
|
|
for (int rnd = nextInt(), n = Math.min(len - i, Integer.SIZE / Byte.SIZE); n-- > 0; rnd >>= Byte.SIZE)
|
|
bytes[i++] = (byte) rnd;
|
|
}
|
|
|
|
public int nextInt() {
|
|
return next(32);
|
|
}
|
|
|
|
public int nextInt(int bound) {
|
|
int r = next(31);
|
|
int m = bound - 1;
|
|
if ((bound & m) == 0) // i.e., bound is a power of 2
|
|
r = (int) ((bound * (long) r) >> 31);
|
|
else {
|
|
for (int u = r; u - (r = u % bound) + m < 0; u = next(31))
|
|
;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
public long nextLong() {
|
|
return ((long) (next(32)) << 32) + next(32);
|
|
}
|
|
|
|
public boolean nextBoolean() {
|
|
return next(1) != 0;
|
|
}
|
|
|
|
public float nextFloat() {
|
|
return next(24) / ((float) (1 << 24));
|
|
}
|
|
|
|
public double nextDouble() {
|
|
return (((long) (next(26)) << 27) + next(27)) * DOUBLE_UNIT;
|
|
}
|
|
|
|
private double nextNextGaussian;
|
|
private boolean haveNextNextGaussian = false;
|
|
|
|
public double nextGaussian() {
|
|
// See Knuth, ACP, Section 3.4.1 Algorithm C.
|
|
if (haveNextNextGaussian) {
|
|
haveNextNextGaussian = false;
|
|
return nextNextGaussian;
|
|
} else {
|
|
double v1, v2, s;
|
|
do {
|
|
v1 = 2 * nextDouble() - 1; // between -1 and 1
|
|
v2 = 2 * nextDouble() - 1; // between -1 and 1
|
|
s = v1 * v1 + v2 * v2;
|
|
} while (s >= 1 || s == 0);
|
|
double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s) / s);
|
|
nextNextGaussian = v2 * multiplier;
|
|
haveNextNextGaussian = true;
|
|
return v1 * multiplier;
|
|
}
|
|
}
|
|
}
|