mirror of
https://github.com/Dreeam-qwq/Gale.git
synced 2025-12-20 15:29:30 +00:00
576 lines
24 KiB
Diff
576 lines
24 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
|
|
|
|
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 5408cbc21fc7577a6100b5a1ca0463e899d2df8b..8bb5d662d62b0c16dc769d69ca45959e6c3164de 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java
|
|
@@ -16,7 +16,7 @@ import java.util.UUID;
|
|
|
|
public class PaperLootableInventoryData {
|
|
|
|
- private static final Random RANDOM = new Random();
|
|
+ private static final Random RANDOM = org.galemc.gale.configuration.GaleGlobalConfiguration.get().smallOptimizations.useXorShiftRandom.lootableRefill ? new org.galemc.gale.random.XorShiftRandom() : new Random(); // Gale - xor-shift random
|
|
|
|
private long lastFill = -1;
|
|
private long nextRefill = -1;
|
|
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
|
index ded7811cd10bc436957ed9f1576f3231f1af7b7b..da6e9efd48567149123649e1a1014ebf14a4da2b 100644
|
|
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
|
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
|
@@ -51,7 +51,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
|
private static final AtomicInteger UNIQUE_THREAD_ID = new AtomicInteger(0);
|
|
static final Logger LOGGER = LogUtils.getLogger();
|
|
private static final int MAX_TICKS_BEFORE_LOGIN = 600;
|
|
- private static final RandomSource RANDOM = new org.bukkit.craftbukkit.util.RandomSourceWrapper(new java.util.Random()); // Paper - This is called across threads, make safe
|
|
+ private static final RandomSource RANDOM = new org.bukkit.craftbukkit.util.RandomSourceWrapper(org.galemc.gale.configuration.GaleGlobalConfiguration.get().smallOptimizations.useXorShiftRandom.encryptionRequestVerifyToken ? new org.galemc.gale.random.XorShiftRandom() : new java.util.Random()); // Paper - This is called across threads, make safe // Gale - xor-shift random - not thread-safe but it is not really a concern here
|
|
private final byte[] challenge;
|
|
final MinecraftServer server;
|
|
public final Connection connection;
|
|
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 0c5ac12b1f395bba8b7fc50baf8e825ba6488f6c..0671e775ab296d6d591a31a8a0c38f62a7f45652 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 {
|
|
}
|
|
|
|
private void backupRegionFile() {
|
|
- Path backup = this.regionFile.getParent().resolve(this.regionFile.getFileName() + "." + new java.util.Random().nextLong() + ".backup");
|
|
+ Path backup = this.regionFile.getParent().resolve(this.regionFile.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 f857f490ffba2f25f7c06c5fb1a1905f0b51fbe2..18408d64905571283551c358f472c37f8b2593ef 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
@@ -229,7 +229,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
|
}
|
|
// Paper end
|
|
|
|
- private static final Random rand = new Random();
|
|
+ private static final Random rand = org.galemc.gale.configuration.GaleGlobalConfiguration.get().smallOptimizations.useXorShiftRandom.generateTreeWithBukkitAPI ? new org.galemc.gale.random.XorShiftRandom() : new Random(); // Gale - xor-shift random
|
|
|
|
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 68c5af9b67a2834ee6e2f80ceefa19c3a982b8ed..bf9deb9a5f7eae6517fcd6d4476a7961ae3b23b1 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 4114088e56a7974b2da84ff90ab66f72ed538b61..dbddba95d9235b6dd262b5740d63ba41ba08861b 100644
|
|
--- a/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java
|
|
+++ b/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java
|
|
@@ -52,13 +52,40 @@ 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
|
|
+ /**
|
|
+ * Whether to use {@link org.galemc.gale.random.XorShiftRandom} instead of the default implementation
|
|
+ * for several occurrences of random generation.
|
|
+ * <ul>
|
|
+ * <li><i>Default</i>: false</li>
|
|
+ * <li><i>Vanilla</i>: false</li>
|
|
+ * </ul>
|
|
+ */
|
|
+ public UseXorShiftRandom useXorShiftRandom;
|
|
+ public class UseXorShiftRandom extends ConfigurationPart {
|
|
+
|
|
+ public boolean lootableRefill = false;
|
|
+ public boolean encryptionRequestVerifyToken = false;
|
|
+ public boolean entityWakeUpDuration = true;
|
|
+
|
|
+ /**
|
|
+ * <ul>
|
|
+ * <li><i>Default</i>: true</li>
|
|
+ * <li><i>Vanilla</i>: false</li>
|
|
+ * </ul>
|
|
+ */
|
|
+ public boolean generateTreeWithBukkitAPI = true;
|
|
+
|
|
+ /**
|
|
+ * <ul>
|
|
+ * <li><i>Default</i>: true</li>
|
|
+ * <li><i>Vanilla</i>: false</li>
|
|
+ * </ul>
|
|
+ */
|
|
+ public boolean elytraFireworkSpeed = true;
|
|
+
|
|
}
|
|
- // 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>
|
|
+ * Marsaglia, George. (2003).
|
|
+ * <a href="https://www.researchgate.net/publication/5142825_Xorshift_RNGs">Xorshift RNGs</a>.
|
|
+ * <br>
|
|
+ * Code from:
|
|
+ * <br>
|
|
+ * <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>
|
|
+ * <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 50cd68e40c67b83af4e8008ce93782a060658dd4..392c57d0365cc4371f58637ebac11e2b7492bf97 100644
|
|
--- a/src/main/java/org/spigotmc/ActivationRange.java
|
|
+++ b/src/main/java/org/spigotmc/ActivationRange.java
|
|
@@ -38,6 +38,7 @@ import co.aikar.timings.MinecraftTimings;
|
|
import net.minecraft.world.entity.schedule.Activity;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.phys.AABB;
|
|
+import org.galemc.gale.configuration.GaleGlobalConfiguration;
|
|
import org.galemc.gale.configuration.GaleWorldConfiguration;
|
|
|
|
public class ActivationRange
|
|
@@ -94,7 +95,7 @@ public class ActivationRange
|
|
// Paper end
|
|
|
|
// Gale start - variable entity wake-up duration
|
|
- private static final java.util.Random wakeUpDurationRandom = new java.util.Random();
|
|
+ private static final java.util.Random wakeUpDurationRandom = GaleGlobalConfiguration.get().smallOptimizations.useXorShiftRandom.entityWakeUpDuration ? new org.galemc.gale.random.XorShiftRandom() : new java.util.Random(); // Gale - xor-shift random
|
|
|
|
private static int getWakeUpDurationWithVariance(Entity entity, int wakeUpDuration) {
|
|
GaleWorldConfiguration config = entity.level().galeConfig();
|