9
0
mirror of https://github.com/Dreeam-qwq/Gale.git synced 2025-12-19 14:59:29 +00:00
Files
Gale/gale-archived-patches/removed/hardfork/server/0113-Add-xor-shift-random.patch
2025-01-27 12:38:00 -05:00

565 lines
23 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martijn Muijsers <martijnmuijsers@live.nl>
Date: Tue, 8 Aug 2023 21:12:58 +0200
Subject: [PATCH] Add xor-shift random
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Removed since Gale 1.21.4, not fast enough, replaced by Leaf's faster random generator
License: LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.html)
Gale - https://galemc.org
This patch is based on the following patch:
"Apply faster random"
By: AlphaKR93 <dev@alpha93.kr>
As part of: Plazma (https://github.com/PlazmaMC/Plazma)
Class `org.plazmamc.plazma.Random` licensed under: LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.html)
Other changes licensed under: MIT (https://opensource.org/licenses/MIT)
* Plazma copyright *
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java
index 861bff267cb397e13e8e1c79bd0776b130c6e5da..30972bf7889973cf63b5f32ad166afdc9800bee1 100644
--- a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java
@@ -21,7 +21,7 @@ import org.checkerframework.framework.qual.DefaultQualifier;
@DefaultQualifier(NonNull.class)
public class PaperLootableInventoryData {
- private static final Random RANDOM = new Random();
+ public static Random RANDOM; // Gale - xor-shift random - set in GaleGlobalConfiguration
private long lastFill = -1;
private long nextRefill = -1;
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index 3f6d60601cbfc138ab004e38bf442d985192fd3f..370266dfa461432b9e22b3ce35d6094949dc2f49 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -132,7 +132,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
this.defaultBlockState = empty ? VOID_AIR_BLOCKSTATE : AIR_BLOCKSTATE;
// Paper end - get block chunk optimisation
- this.lightningTick = this.level.simpleRandom.nextInt(100000) << 1; // Gale - Airplane - optimize random calls in chunk ticking - initialize lightning tick
+ this.lightningTick = org.galemc.gale.configuration.GaleGlobalConfiguration.get().smallOptimizations.useXorShiftRandom.lightningRandomTick ? new org.galemc.gale.random.XorShiftRandom().nextInt(100000) << 1 : this.level.simpleRandom.nextInt(100000) << 1; // Gale - Airplane - optimize random calls in chunk ticking - initialize lightning tick // Gale - xor-shift random
}
// CraftBukkit start
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
index 16f07007a0f73ec0c6f421c9b082518e87e8cc7b..b26a5b76cd30c96ce15ced5ac51222a8333bde52 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
@@ -109,7 +109,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
}
private void backupRegionFile() {
- Path backup = this.path.getParent().resolve(this.path.getFileName() + "." + new java.util.Random().nextLong() + ".backup");
+ Path backup = this.path.getParent().resolve(this.path.getFileName() + "." + new org.galemc.gale.random.XorShiftRandom().nextLong() + ".backup"); // Gale - xor-shift random
this.backupRegionFile(backup);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 57da11c0da7322e74810e7108e9c8000b0c36520..d39a0785f42c72d7b32af5c1c8067b2857f22a48 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -288,7 +288,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
}
// Paper end
- private static final Random rand = new Random();
+ public static Random rand; // Gale - xor-shift random - set in GaleGlobalConfiguration
public CraftWorld(ServerLevel world, ChunkGenerator gen, BiomeProvider biomeProvider, Environment env) {
this.world = world;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
index 759b6e54db93792c9862b1f1625118ac6fa49d7a..4b5e9bc33c25ac98c32aff1bd13788edf0eeee8c 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
@@ -14,7 +14,7 @@ import org.bukkit.inventory.meta.FireworkMeta;
public class CraftFirework extends CraftProjectile implements Firework {
- private final Random random = new Random();
+ private final Random random = org.galemc.gale.configuration.GaleGlobalConfiguration.get().smallOptimizations.useXorShiftRandom.elytraFireworkSpeed ? new org.galemc.gale.random.XorShiftRandom() : new Random(); // Gale - xor-shift random - not thread-safe but it is not really a concern here
//private CraftItemStack item; // Paper - Remove usage, not accurate representation of current item.
public CraftFirework(CraftServer server, FireworkRocketEntity entity) {
diff --git a/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java b/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java
index 3e5efa90180308cbfaaa063d96ad788985720b8c..c57ebf0f37aba2d118e54f3c71697f29bb9a57a0 100644
--- a/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java
+++ b/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java
@@ -10,6 +10,7 @@ import org.spongepowered.configurate.objectmapping.meta.PostProcess;
import org.spongepowered.configurate.objectmapping.meta.Setting;
import java.util.Locale;
+import java.util.Random;
import java.util.function.Consumer;
@SuppressWarnings({"CanBeFinal", "FieldCanBeLocal", "FieldMayBeFinal", "NotNullFieldNotInitialized", "InnerClassMayBeStatic"})
@@ -41,13 +42,27 @@ public class GaleGlobalConfiguration extends ConfigurationPart {
}
- // Gale start - Pufferfish - SIMD support
- public Simd simd;
- public class Simd extends ConfigurationPart {
- public boolean warnIfDisabled = true;
- public boolean logVectorSizesToConsole = false;
+ // Gale start - xor-shift random
+ public UseXorShiftRandom useXorShiftRandom;
+ public class UseXorShiftRandom extends ConfigurationPart {
+
+ public boolean autoReplenishLootableRefill = true;
+ public boolean elytraFireworkSpeed = true;
+ public boolean entityWakeUpDuration = true;
+ public boolean lightningRandomTick = true;
+
+ @Setting("generate-tree-with-bukkit-api")
+ public boolean generateTreeWithBukkitAPI = true;
+
+ @PostProcess
+ public void postProcess() {
+ com.destroystokyo.paper.loottable.PaperLootableInventoryData.RANDOM = autoReplenishLootableRefill ? new org.galemc.gale.random.XorShiftRandom() : new Random();
+ org.spigotmc.ActivationRange.wakeUpDurationRandom = entityWakeUpDuration ? new org.galemc.gale.random.XorShiftRandom() : new java.util.Random();
+ org.bukkit.craftbukkit.CraftWorld.rand = generateTreeWithBukkitAPI ? new org.galemc.gale.random.XorShiftRandom() : new Random();
+ }
+
}
- // Gale end - Pufferfish - SIMD support
+ // Gale end - xor-shift random
}
diff --git a/src/main/java/org/galemc/gale/random/XorShiftRandom.java b/src/main/java/org/galemc/gale/random/XorShiftRandom.java
new file mode 100644
index 0000000000000000000000000000000000000000..60dc2c1deb0749168d03c5d94136e613b09ce534
--- /dev/null
+++ b/src/main/java/org/galemc/gale/random/XorShiftRandom.java
@@ -0,0 +1,404 @@
+// Gale - xor-shift random
+
+package org.galemc.gale.random;
+
+import java.util.Random;
+
+/**
+ * A random number generator based on the simple and fast xor-shift pseudo
+ * random number generator (RNG) specified in:
+ * <br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;Marsaglia, George. (2003).
+ * <a href="https://www.researchgate.net/publication/5142825_Xorshift_RNGs">Xorshift RNGs</a>.
+ * <br>
+ * Code from:
+ * <br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;<a href="https://gist.github.com/Xyene/4637619">Random.java</a>
+ * by <a href="https://gist.github.com/Xyene">Xyene</a>.
+ * <br>
+ * Translated from:
+ * <br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.codeproject.com/Articles/9187/A-fast-equivalent-for-System-Random">
+ * A fast equivalent for System.Random</a> by <a href="https://www.codeproject.com/Members/colgreen">colgreen</a>.
+ * <br>
+ * Licensed under <a href="https://www.gnu.org/licenses/lgpl-3.0.html">GNU Lesser General Public License version 3</a>.
+ */
+public final class XorShiftRandom extends Random {
+ final double REAL_UNIT_INT = 1.0 / (0x7FFFFFFFL);
+ final double REAL_UNIT_UINT = 1.0 / (0xFFFFFFFFL);
+ final long Y = 842502087L, Z = 3579807591L, W = 273326509L;
+ long x, y, z, w;
+
+ public XorShiftRandom() {
+ seed((int) System.currentTimeMillis());
+ }
+
+ @Override
+ public void setSeed(long seed) {
+ seed((int) seed);
+ }
+
+ public void seed(int seed) {
+ // The only stipulation stated for the xorshift RNG is that at least one of
+ // the seeds x,y,z,w is non-zero. We fulfill that requirement by only allowing
+ // resetting of the x seed
+ x = seed;
+ y = Y;
+ z = Z;
+ w = W;
+ }
+
+ long boolBuffer;
+ int boolBufferBits = 0;
+
+ @Override
+ public boolean nextBoolean() {
+ if (boolBufferBits == 0) {
+ boolBuffer = nextUInt();
+ boolBufferBits = 32;
+ }
+ boolBuffer >>= 1;
+ boolean bit = (boolBuffer & 1) == 0;
+ --boolBufferBits;
+ return bit;
+ }
+
+ @Override
+ public void nextBytes(byte[] buffer) {
+ // Fill up the bulk of the buffer in chunks of 4 bytes at a time.
+ long x = this.x, y = this.y, z = this.z, w = this.w;
+ int i = 0;
+ long t;
+ for (int bound = buffer.length - 3; i < bound; ) {
+ // Generate 4 bytes.
+ // Increased performance is achieved by generating 4 random bytes per loop.
+ // Also note that no mask needs to be applied to zero out the higher order bytes before
+ // casting because the cast ignores thos bytes. Thanks to Stefan Trosch黷z for pointing this out.
+ t = (x ^ (x << 11));
+ x = y;
+ y = z;
+ z = w;
+ w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
+
+ buffer[i++] = (byte) w;
+ buffer[i++] = (byte) (w >> 8);
+ buffer[i++] = (byte) (w >> 16);
+ buffer[i++] = (byte) (w >> 24);
+ }
+
+ // Fill up any remaining bytes in the buffer.
+ if (i < buffer.length) {
+ // Generate 4 bytes.
+ t = (x ^ (x << 11));
+ x = y;
+ y = z;
+ z = w;
+ w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
+
+ buffer[i++] = (byte) w;
+ if (i < buffer.length) {
+ buffer[i++] = (byte) (w >> 8);
+ if (i < buffer.length) {
+ buffer[i++] = (byte) (w >> 16);
+ if (i < buffer.length) {
+ buffer[i] = (byte) (w >> 24);
+ }
+ }
+ }
+ }
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+
+ @Override
+ public double nextDouble() {
+ long t = (x ^ (x << 11));
+ x = y;
+ y = z;
+ z = w;
+
+ // Here we can gain a 2x speed improvement by generating a value that can be cast to
+ // an int instead of the more easily available uint. If we then explicitly cast to an
+ // int the compiler will then cast the int to a double to perform the multiplication,
+ // this final cast is a lot faster than casting from a uint to a double. The extra cast
+ // to an int is very fast (the allocated bits remain the same) and so the overall effect
+ // of the extra cast is a significant performance improvement.
+ //
+ // Also note that the loss of one bit of precision is equivalent to what occurs within
+ // System.Random.
+ return (REAL_UNIT_INT * (int) (0x7FFFFFFF & (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)))));
+ }
+
+ public double random() {
+ return nextDouble();
+ }
+
+ @Override
+ public float nextFloat() {
+ return (float) nextDouble();
+ }
+
+ @Override
+ public int nextInt() {
+ long t = (x ^ (x << 11));
+ x = y;
+ y = z;
+ z = w;
+ return (int) (0x7FFFFFFF & (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))));
+ }
+
+ @Override
+ public int nextInt(int upperBound) {
+ if (upperBound < 0)
+ throw new IllegalArgumentException("upperBound must be >=0");
+
+ long t = (x ^ (x << 11));
+ x = y;
+ y = z;
+ z = w;
+
+ return (int) ((REAL_UNIT_INT * (int) (0x7FFFFFFF & (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))))) * upperBound);
+ }
+
+ public int nextInt(int lowerBound, int upperBound) {
+ if (lowerBound > upperBound)
+ throw new IllegalArgumentException("upperBound must be >=lowerBound");
+
+ long t = (x ^ (x << 11));
+ x = y;
+ y = z;
+ z = w;
+
+ // The explicit int cast before the first multiplication gives better performance.
+ // See comments in NextDouble.
+ int range = upperBound - lowerBound;
+ if (range < 0) {
+ // If range is <0 then an overflow has occured and must resort to using long integer arithmetic instead (slower).
+ // We also must use all 32 bits of precision, instead of the normal 31, which again is slower.
+ return lowerBound + (int) ((REAL_UNIT_UINT * (double) (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)))) * (double) ((long) upperBound - (long) lowerBound));
+ }
+ // 31 bits of precision will suffice if range<=int.MaxValue. This allows us to cast to an int and gain
+ // a little more performance.
+ return lowerBound + (int) ((REAL_UNIT_INT * (double) (int) (0x7FFFFFFF & (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))))) * (double) range);
+ }
+
+ public long nextUInt() {
+ long t = (x ^ (x << 11));
+ x = y;
+ y = z;
+ z = w;
+ return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))) & (0xFFFFFFFFL);
+ }
+
+ @Override
+ public long nextLong() {
+ return nextUInt() << 32 + nextUInt();
+ }
+
+ double gaussNext;
+ boolean hasGaussNext;
+ final double TWOPI = Math.PI * 2;
+
+ /**
+ * Get a random number in the range [min, max) or [min, max] depending on rounding.
+ *
+ * @param min Low bound
+ * @param max High bound
+ * @return A uniformly distributed double
+ */
+ public double uniform(double min, double max) {
+ return min + (max - min) * nextDouble();
+ }
+
+ /**
+ * Triangular distribution.
+ * <p/>
+ * Continuous distribution bounded by given lower and upper limits,
+ * and having a given mode value in-between.
+ * http://en.wikipedia.org/wiki/Triangular_distribution
+ *
+ * @param low Low bound
+ * @param high High bound
+ * @param mode Mode
+ * @return A number from the triangular distribution specified
+ */
+ public double triangular(int low, int high, int mode) {
+ double u = nextDouble();
+ double c = (mode - low) / (high - low);
+ if (u > c) {
+ u = 1.0 - u;
+ c = 1.0 - c;
+ int k = low;
+ low = high;
+ high = k;
+ }
+ return low + (high - low) * Math.sqrt(u * c);
+ }
+
+ /**
+ * Gaussian distribution, mean is 0 and standard deviation is 1.
+ * <p/>
+ * mu is the mean, and sigma is the standard deviation.
+ *
+ * @return A double in Gaussian distribution
+ */
+ public double gauss() {
+ return nextGaussian();
+ }
+
+ /**
+ * Gaussian distribution, with user-specified mean and standard deviation.
+ * <p/>
+ * mu is the mean, and sigma is the standard deviation.
+ *
+ * @return A double in Gaussian distribution
+ */
+ public double gauss(double mu, double sigma) {
+ return mu + sigma * nextGaussian();
+ }
+
+ public double gaussUnsigned(double mu, double sigma) {
+ double out = gauss(mu, sigma);
+ return out > 1 ? out : 1;
+ }
+
+ /**
+ * Log normal distribution.
+ * <p/>
+ * If you take the natural logarithm of this distribution, you'll get a
+ * normal distribution with mean mu and standard deviation sigma.
+ * mu can have any value, and sigma must be greater than zero.
+ *
+ * @param mu Mean
+ * @param sigma Standard deviation
+ * @return A number from the log normal distribution specified
+ */
+ public double logNormal(double mu, double sigma) {
+ return Math.exp(gauss(mu, sigma));
+ }
+
+ /**
+ * Exponential distribution.
+ * <p/>
+ * lambda is 1.0 divided by the desired mean. It should be
+ * nonzero. Returned values range from 0 to positive infinity
+ * if lambda is positive, and from negative infinity to 0
+ * if lambda is negative.
+ *
+ * @param lambda A non-zero value
+ */
+ public double exponential(double lambda) {
+ return -Math.log(1.0 - random()) / lambda;
+ }
+
+ /**
+ * Circular data distribution.
+ * <p/>
+ * If kappa is equal to zero, this distribution reduces
+ * to a uniform random angle over the range 0 to 2*pi.
+ *
+ * @param mu the mean angle, expressed in radians between 0 and 2*pi.
+ * @param kappa the concentration parameter, which must be greater than or
+ * equal to zero.
+ * @return A number from the circular data distribution specified
+ */
+ public double circularData(double mu, double kappa) {
+ if (kappa <= 1e-6)
+ return TWOPI * nextDouble();
+
+ double a = 1.0 + Math.sqrt(1.0 + 4.0 * kappa * kappa);
+ double b = (a - Math.sqrt(2.0 * a)) / (2.0 * kappa);
+ double r = (1.0 + b * b) / (2.0 * b);
+ double u1, u2, u3, f, c, z, theta = 0;
+
+ while (true) {
+ u1 = nextDouble();
+
+ z = Math.cos(Math.PI * u1);
+ f = (1.0 + r * z) / (r + z);
+ c = kappa * (r - f);
+
+ u2 = nextDouble();
+
+ if (u2 < c * (2.0 - c) || u2 <= c * Math.exp(1.0 - c))
+ break;
+
+ u3 = nextDouble();
+ if (u3 > 0.5)
+ theta = (mu % TWOPI) + Math.acos(f);
+ else
+ theta = (mu % TWOPI) - Math.acos(f);
+ }
+ return theta;
+ }
+
+
+ final double LOG4 = Math.log(4);
+ final double SG_MAGICCONST = 1.0 + Math.log(4.5);
+
+ /**
+ * Gamma distribution. Not the gamma function!
+ * Conditions on the parameters are alpha > 0 and beta > 0.
+ * <p/>
+ * The probability distribution function is:
+ * pdf(x) = (x ** (alpha - 1) * math.exp(-x / beta)) / (math.gamma(alpha) * beta ** alpha)
+ *
+ * @param alpha Alpha
+ * @param beta Beta
+ * @return A number from the gamma distribution specified
+ */
+ public double gamma(double alpha, double beta) {
+ if (alpha <= 0.0 || beta <= 0.0)
+ throw new IllegalArgumentException("alpha and beta must be > 0.0");
+
+ if (alpha > 1.0) {
+ double ainv = Math.sqrt(2.0 * alpha - 1.0);
+ double bbb = alpha - LOG4;
+ double ccc = alpha + ainv;
+ double u1, u2, v, x, z, r;
+
+ while (true) {
+ u1 = random();
+ if (!(1e-7 < u1 && u1 < .9999999))
+ continue;
+ u2 = 1.0 - random();
+ v = Math.log(u1 / (1.0 - u1)) / ainv;
+ x = alpha * Math.exp(v);
+ z = u1 * u1 * u2;
+ r = bbb + ccc * v - x;
+ if (r + SG_MAGICCONST - 4.5 * z >= 0.0 || r >= Math.log(z))
+ return x * beta;
+ }
+ } else if (alpha == 1.0) {
+ // exponential(1)
+ double u;
+ u = random();
+ while (u <= 1e-7)
+ u = random();
+ return -Math.log(u) * beta;
+ } else {
+ // alpha is between 0 and 1 (exclusive)
+ // Uses ALGORITHM GS of Statistical Computing -Kennedy & Gentle
+
+ double u, b, p, x, u1;
+ while (true) {
+ u = random();
+ b = (Math.E + alpha) / Math.E;
+ p = b * u;
+ if (p <= 1.0)
+ x = Math.pow(p, (1.0 / alpha));
+ else
+ x = -Math.log((b - p) / alpha);
+ u1 = random();
+ if (p > 1.0) {
+ if (u1 <= Math.pow(x, (alpha - 1.0)))
+ break;
+ } else if (u1 <= Math.exp(-x))
+ break;
+ }
+ return x * beta;
+ }
+ }
+}
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
index f1581caf54012ce4d4b9aecbc56b5b815c67a423..5d1cc9b9150f84bb84cef5dd741e72787c02f089 100644
--- a/src/main/java/org/spigotmc/ActivationRange.java
+++ b/src/main/java/org/spigotmc/ActivationRange.java
@@ -92,7 +92,7 @@ public class ActivationRange
// Paper end
// Gale start - variable entity wake-up duration
- private static final java.util.Random wakeUpDurationRandom = new java.util.Random();
+ public static java.util.Random wakeUpDurationRandom; // Gale - xor-shift random - set in GaleGlobalConfiguration
private static int getWakeUpDurationWithVariance(Entity entity, int wakeUpDuration) {
double deviation = entity.level().galeConfig().gameplayMechanics.entityWakeUpDurationRatioStandardDeviation;