mirror of
https://github.com/Dreeam-qwq/Gale.git
synced 2025-12-19 14:59:29 +00:00
[ci skip] cleanup & drop xor-shift random
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
# This file is auto generated, any changes may be overridden!
|
||||
# See CONTRIBUTING.md on how to add access transformers.
|
||||
public net.minecraft.server.players.PlayerList SEND_PLAYER_INFO_INTERVAL
|
||||
public net.minecraft.world.entity.Entity blockPosition
|
||||
public net.minecraft.world.entity.Entity position
|
||||
public net.minecraft.world.level.levelgen.structure.PoolElementStructurePiece LOGGER
|
||||
|
||||
@@ -0,0 +1,564 @@
|
||||
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>
|
||||
+ * 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 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;
|
||||
@@ -13,7 +13,7 @@ As part of: JettPack (https://gitlab.com/Titaniumtown/JettPack)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
|
||||
index d21ce54ebb5724c04eadf56a2cde701d5eeb5db2..848374fa7383d6a82c33dad03deb0e97eca97d23 100644
|
||||
index d21ce54ebb5724c04eadf56a2cde701d5eeb5db2..b6af8da084c83ee38bb3ecea6a98feb0c1c74d2a 100644
|
||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
|
||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
|
||||
@@ -378,7 +378,6 @@ public final class ChunkEntitySlices {
|
||||
@@ -24,17 +24,15 @@ index d21ce54ebb5724c04eadf56a2cde701d5eeb5db2..848374fa7383d6a82c33dad03deb0e97
|
||||
private static final int DEFAULT_CAPACITY = 4;
|
||||
|
||||
private E[] storage;
|
||||
@@ -389,8 +388,8 @@ public final class ChunkEntitySlices {
|
||||
@@ -389,7 +388,7 @@ public final class ChunkEntitySlices {
|
||||
}
|
||||
|
||||
public BasicEntityList(final int cap) {
|
||||
- this.storage = (E[])(cap <= 0 ? EMPTY : new Entity[cap]);
|
||||
- }
|
||||
+ this.storage = (E[])(cap <= 0 ? me.titaniumtown.ArrayConstants.emptyEntityArray : new Entity[cap]); // Gale - JettPack - reduce array allocations
|
||||
+ } // Gale - JettPack - reduce array allocations
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.size == 0;
|
||||
@@ -401,7 +400,7 @@ public final class ChunkEntitySlices {
|
||||
}
|
||||
|
||||
|
||||
@@ -39,10 +39,10 @@ index df972d47848f9cb74be269019b196c4f2699bfc1..c08a7a2d12fbf67dc675f79e8452b90b
|
||||
public void absMoveTo(double x, double y, double z, float yRot, float xRot) {
|
||||
this.absMoveTo(x, y, z);
|
||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||
index 2568a7f2459ed783d4612546b86d46721d48a396..f3eec8b75fcda47e6632a2a7db9a238b515bc8a0 100644
|
||||
index 2568a7f2459ed783d4612546b86d46721d48a396..acf2e306ad26e5f0413ee320b9b514b56fefc21b 100644
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -1594,20 +1594,30 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
||||
@@ -1594,20 +1594,32 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
||||
protected void playAttackSound() {
|
||||
}
|
||||
|
||||
@@ -73,7 +73,9 @@ index 2568a7f2459ed783d4612546b86d46721d48a396..f3eec8b75fcda47e6632a2a7db9a238b
|
||||
+ if (lightLevelDependentMagicValue <= 0.5F) return false;
|
||||
+ if (this.random.nextFloat() * 30.0F >= (lightLevelDependentMagicValue - 0.4F) * 2.0F) return false;
|
||||
+ // Gale end - JettPack - optimize sun burn tick - optimizations and cache eye blockpos
|
||||
+
|
||||
+ boolean flag = this.isInWaterRainOrBubble() || this.isInPowderSnow || this.wasInPowderSnow;
|
||||
+
|
||||
+ return !flag && this.level().canSeeSky(this.cached_eye_blockpos); // Gale - JettPack - optimize sun burn tick - optimizations and cache eye blockpos
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,10 @@ As part of: Lithium (https://github.com/CaffeineMC/lithium-fabric)
|
||||
Licensed under: LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java b/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java
|
||||
index 52cb2dcd714cf8c16f167466333eeb923e4ff183..9661def1311102bbb7e8afdd69f5484320e58d01 100644
|
||||
index 52cb2dcd714cf8c16f167466333eeb923e4ff183..af9d8f5988431eaf82da6a564c19a7a359a693d0 100644
|
||||
--- a/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java
|
||||
+++ b/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java
|
||||
@@ -15,8 +15,17 @@ public class EntityBasedExplosionDamageCalculator extends ExplosionDamageCalcula
|
||||
@@ -15,8 +15,20 @@ public class EntityBasedExplosionDamageCalculator extends ExplosionDamageCalcula
|
||||
|
||||
@Override
|
||||
public Optional<Float> getBlockExplosionResistance(Explosion explosion, BlockGetter reader, BlockPos pos, BlockState state, FluidState fluid) {
|
||||
@@ -25,13 +25,16 @@ index 52cb2dcd714cf8c16f167466333eeb923e4ff183..9661def1311102bbb7e8afdd69f54843
|
||||
- .map(resistance -> this.source.getBlockExplosionResistance(explosion, reader, pos, state, fluid, resistance));
|
||||
+ // Gale start - Lithium - reduce lambda and Optional allocation in EntityBasedExplosionDamageCalculator
|
||||
+ Optional<Float> optionalBlastResistance = super.getBlockExplosionResistance(explosion, reader, pos, state, fluid);
|
||||
+
|
||||
+ if (optionalBlastResistance.isPresent()) {
|
||||
+ float resistance = optionalBlastResistance.get();
|
||||
+ float effectiveExplosionResistance = this.source.getBlockExplosionResistance(explosion, reader, pos, state, fluid, resistance);
|
||||
+
|
||||
+ if (effectiveExplosionResistance != resistance) {
|
||||
+ return Optional.of(effectiveExplosionResistance);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return optionalBlastResistance;
|
||||
+ // Gale end - Lithium - reduce lambda and Optional allocation in EntityBasedExplosionDamageCalculator
|
||||
}
|
||||
|
||||
@@ -17,15 +17,16 @@ Licensed under: LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.html)
|
||||
villagers that have no secondary POI (farmland) do not search for it
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java b/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java
|
||||
index 6b99afb4f237b5d6def98f3e03492975b795bc95..05c664732adfca7d18bfcbebae9bb455f001aa93 100644
|
||||
index 6b99afb4f237b5d6def98f3e03492975b795bc95..d9318a5a9eb3de89f48efa23b944c6d9e2ba37d1 100644
|
||||
--- a/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java
|
||||
@@ -22,6 +22,13 @@ public class SecondaryPoiSensor extends Sensor<Villager> {
|
||||
@@ -22,6 +22,14 @@ public class SecondaryPoiSensor extends Sensor<Villager> {
|
||||
|
||||
@Override
|
||||
protected void doTick(ServerLevel level, Villager entity) {
|
||||
+ // Gale start - Lithium - skip secondary POI sensor if absent
|
||||
+ var secondaryPoi = entity.getVillagerData().getProfession().secondaryPoi();
|
||||
+
|
||||
+ if (secondaryPoi.isEmpty()) {
|
||||
+ entity.getBrain().eraseMemory(MemoryModuleType.SECONDARY_JOB_SITE);
|
||||
+ return;
|
||||
|
||||
@@ -13,15 +13,16 @@ As part of: SportPaper (https://github.com/Electroid/SportPaper)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index c697576d3ae22fbb7ae869fa099bffc8ac5cb2e5..ba0b5961535f0dbffda5216a6e4657ea85f30eb7 100644
|
||||
index c697576d3ae22fbb7ae869fa099bffc8ac5cb2e5..7c9496e8564c2464e79661153fd295bb027b7bdb 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1559,6 +1559,14 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -1559,6 +1559,15 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
|
||||
@Override
|
||||
public void destroyBlockProgress(int breakerId, BlockPos pos, int progress) {
|
||||
+ // Gale start - SportPaper - reduce block destruction packet allocations
|
||||
+ var players = this.server.getPlayerList().getPlayers();
|
||||
+
|
||||
+ if (players.isEmpty()) {
|
||||
+ return;
|
||||
+ }
|
||||
@@ -31,7 +32,7 @@ index c697576d3ae22fbb7ae869fa099bffc8ac5cb2e5..ba0b5961535f0dbffda5216a6e4657ea
|
||||
// CraftBukkit start
|
||||
Player breakerPlayer = null;
|
||||
Entity entity = this.getEntity(breakerId);
|
||||
@@ -1575,7 +1583,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -1575,7 +1584,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
.callEvent();
|
||||
}
|
||||
// Paper end - Add BlockBreakProgressUpdateEvent
|
||||
@@ -40,7 +41,7 @@ index c697576d3ae22fbb7ae869fa099bffc8ac5cb2e5..ba0b5961535f0dbffda5216a6e4657ea
|
||||
if (serverPlayer != null && serverPlayer.level() == this && serverPlayer.getId() != breakerId) {
|
||||
double d = pos.getX() - serverPlayer.getX();
|
||||
double d1 = pos.getY() - serverPlayer.getY();
|
||||
@@ -1586,7 +1594,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -1586,7 +1595,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
}
|
||||
// CraftBukkit end
|
||||
if (d * d + d1 * d1 + d2 * d2 < 1024.0) {
|
||||
|
||||
@@ -37,16 +37,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index b4258db165b509d54b9c15a661c5b66ca984ffb3..af0f608e05262cbb118d92786bcdba9ae834a809 100644
|
||||
index 7d0bbbe0f902a27940bde1cbd0f2a8dbfcd22202..2b4431fd68054bfe8d216fd5461b1c56c692f48b 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -109,11 +109,12 @@ public abstract class PlayerList {
|
||||
public static final Component CHAT_FILTERED_FULL = Component.translatable("chat.filtered_full");
|
||||
public static final Component DUPLICATE_LOGIN_DISCONNECT_MESSAGE = Component.translatable("multiplayer.disconnect.duplicate_login");
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
- private static final int SEND_PLAYER_INFO_INTERVAL = 600;
|
||||
+ public static final int SEND_PLAYER_INFO_INTERVAL = 600; // Gale - Purpur - spread out sending all player info - private -> public
|
||||
private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z");
|
||||
@@ -114,6 +114,7 @@ public abstract class PlayerList {
|
||||
private final MinecraftServer server;
|
||||
public final List<ServerPlayer> players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety
|
||||
private final Map<UUID, ServerPlayer> playersByUUID = Maps.newHashMap();
|
||||
@@ -86,7 +80,7 @@ index b4258db165b509d54b9c15a661c5b66ca984ffb3..af0f608e05262cbb118d92786bcdba9a
|
||||
}
|
||||
// serverPlayer.initInventoryMenu();
|
||||
serverPlayer.setHealth(serverPlayer.getHealth());
|
||||
@@ -890,18 +895,52 @@ public abstract class PlayerList {
|
||||
@@ -890,18 +895,58 @@ public abstract class PlayerList {
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
@@ -96,6 +90,7 @@ index b4258db165b509d54b9c15a661c5b66ca984ffb3..af0f608e05262cbb118d92786bcdba9a
|
||||
- final ServerPlayer target = this.players.get(i);
|
||||
+ // Gale start - Purpur - spread out sending all player info
|
||||
+ ServerPlayer[] sendAllPlayerInfoBucket = this.sendAllPlayerInfoBuckets[this.sendAllPlayerInfoIn];
|
||||
+
|
||||
+ if (sendAllPlayerInfoBucket != null) {
|
||||
+ for (ServerPlayer target : sendAllPlayerInfoBucket) {
|
||||
+ // Gale end - Purpur - spread out sending all player info
|
||||
@@ -105,6 +100,7 @@ index b4258db165b509d54b9c15a661c5b66ca984ffb3..af0f608e05262cbb118d92786bcdba9a
|
||||
- // CraftBukkit end
|
||||
+ // Gale start - Purpur - spread out sending all player info
|
||||
+ }
|
||||
+
|
||||
+ if (++this.sendAllPlayerInfoIn >= SEND_PLAYER_INFO_INTERVAL) {
|
||||
+ // Gale end - Purpur - spread out sending all player info
|
||||
this.sendAllPlayerInfoIn = 0;
|
||||
@@ -114,6 +110,7 @@ index b4258db165b509d54b9c15a661c5b66ca984ffb3..af0f608e05262cbb118d92786bcdba9a
|
||||
+ // Gale start - Purpur - spread out sending all player info
|
||||
+ private void addToSendAllPlayerInfoBuckets(ServerPlayer player) {
|
||||
+ ServerPlayer[] sendAllPlayerInfoBucket = this.sendAllPlayerInfoBuckets[player.sendAllPlayerInfoBucketIndex];
|
||||
+
|
||||
+ if (sendAllPlayerInfoBucket == null) {
|
||||
+ this.sendAllPlayerInfoBuckets[player.sendAllPlayerInfoBucketIndex] = new ServerPlayer[]{player};
|
||||
+ } else {
|
||||
@@ -124,13 +121,16 @@ index b4258db165b509d54b9c15a661c5b66ca984ffb3..af0f608e05262cbb118d92786bcdba9a
|
||||
+
|
||||
+ private void removeFromSendAllPlayerInfoBuckets(ServerPlayer player) {
|
||||
+ ServerPlayer[] sendAllPlayerInfoBucket = this.sendAllPlayerInfoBuckets[player.sendAllPlayerInfoBucketIndex];
|
||||
+
|
||||
+ if (sendAllPlayerInfoBucket != null) {
|
||||
+ if (sendAllPlayerInfoBucket.length == 1) {
|
||||
+ if (sendAllPlayerInfoBucket[0] == player) {
|
||||
+ this.sendAllPlayerInfoBuckets[player.sendAllPlayerInfoBucketIndex] = null;
|
||||
+ }
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0; i < sendAllPlayerInfoBucket.length; i++) {
|
||||
+ if (sendAllPlayerInfoBucket[i] == player) {
|
||||
+ sendAllPlayerInfoBucket[i] = sendAllPlayerInfoBucket[sendAllPlayerInfoBucket.length - 1];
|
||||
|
||||
@@ -37,12 +37,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index af0f608e05262cbb118d92786bcdba9ae834a809..70f3dea61eca3639a4e0cc6a45c1d35fbc4e3e5a 100644
|
||||
index 2b4431fd68054bfe8d216fd5461b1c56c692f48b..e03a0a350fd95406d2a5e3d220c9839326a8e1b6 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -898,10 +898,19 @@ public abstract class PlayerList {
|
||||
// Gale start - Purpur - spread out sending all player info
|
||||
@@ -899,10 +899,19 @@ public abstract class PlayerList {
|
||||
ServerPlayer[] sendAllPlayerInfoBucket = this.sendAllPlayerInfoBuckets[this.sendAllPlayerInfoIn];
|
||||
|
||||
if (sendAllPlayerInfoBucket != null) {
|
||||
- for (ServerPlayer target : sendAllPlayerInfoBucket) {
|
||||
+ for (ServerPlayer targetPlayer : sendAllPlayerInfoBucket) { // Gale - Purpur - optimize player list for sending player info
|
||||
|
||||
@@ -7,16 +7,17 @@ License: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
Gale - https://galemc.org
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index 0fdf22af66945c1b6987e07f6c8a167110033b53..36c442b195db6403e2d86cac4120970fc63010ab 100644
|
||||
index 0fdf22af66945c1b6987e07f6c8a167110033b53..e802cecf30a2bfa4390ca70c45a9840032c8c046 100644
|
||||
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -127,7 +127,10 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
@@ -127,7 +127,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
this.finishLoginAndWaitForClient(this.authenticatedProfile);
|
||||
}
|
||||
|
||||
- if (this.tick++ == 600) {
|
||||
+ // Gale start - make slow login timeout configurable
|
||||
+ int slowLoginTimeout = org.galemc.gale.configuration.GaleGlobalConfiguration.get().misc.premiumAccountSlowLoginTimeout;
|
||||
+
|
||||
+ if (this.tick++ >= (slowLoginTimeout < 1 ? MAX_TICKS_BEFORE_LOGIN : slowLoginTimeout)) {
|
||||
+ // Gale end - make slow login timeout configurable
|
||||
this.disconnect(Component.translatable("multiplayer.disconnect.slow_login"));
|
||||
|
||||
@@ -28,10 +28,10 @@ index bbcfb7b535514d8e394b31f74d2bbc2ba90e7498..55c05f5e8e5045292f77621fed78a049
|
||||
return this.chunkPosition;
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||
index 830ae2b569b533f2ded23826c48727f1d7fd0272..062e83860a3f9e3a40c513ca389d628ba936f465 100644
|
||||
index 830ae2b569b533f2ded23826c48727f1d7fd0272..b242b9b6c1f798c2656fa77b1d04e57b2caec5dc 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -2029,8 +2029,16 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
@@ -2029,8 +2029,17 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
|
||||
public boolean onClimbableCached() {
|
||||
if (!this.blockPosition().equals(this.lastClimbingPosition)) {
|
||||
@@ -39,6 +39,7 @@ index 830ae2b569b533f2ded23826c48727f1d7fd0272..062e83860a3f9e3a40c513ca389d628b
|
||||
- this.lastClimbingPosition = this.blockPosition();
|
||||
+ // Gale start - don't load chunks to activate climbing entities
|
||||
+ Boolean onClimbableIfLoaded = this.onClimbable(this.level().galeConfig().smallOptimizations.loadChunks.toActivateClimbingEntities);
|
||||
+
|
||||
+ if (onClimbableIfLoaded != null) {
|
||||
+ this.cachedOnClimbable = onClimbableIfLoaded;
|
||||
+ this.lastClimbingPosition = this.blockPosition();
|
||||
@@ -50,7 +51,7 @@ index 830ae2b569b533f2ded23826c48727f1d7fd0272..062e83860a3f9e3a40c513ca389d628b
|
||||
}
|
||||
|
||||
return this.cachedOnClimbable;
|
||||
@@ -2038,11 +2046,27 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
@@ -2038,11 +2047,28 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
// Gale end - Airplane - cache on climbable check
|
||||
|
||||
public boolean onClimbable() {
|
||||
@@ -70,6 +71,7 @@ index 830ae2b569b533f2ded23826c48727f1d7fd0272..062e83860a3f9e3a40c513ca389d628b
|
||||
+ inBlockState = this.getInBlockState();
|
||||
+ } else {
|
||||
+ inBlockState = this.getInBlockStateIfLoaded();
|
||||
+
|
||||
+ if (inBlockState == null) {
|
||||
+ return null;
|
||||
+ }
|
||||
|
||||
@@ -13,10 +13,10 @@ As part of: MultiPaper (https://github.com/MultiPaper/MultiPaper)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java b/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java
|
||||
index 28872f70ac27aacc8848cf5659cfd2c55e4cd19a..1f15e0f5e091117e2d7bd9c96e6b67b08fe25224 100644
|
||||
index 28872f70ac27aacc8848cf5659cfd2c55e4cd19a..d928157507dd70645425c51e766783eab17486a0 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java
|
||||
@@ -171,13 +171,18 @@ public class LegacyStructureDataHandler {
|
||||
@@ -171,13 +171,20 @@ public class LegacyStructureDataHandler {
|
||||
|
||||
private void populateCaches(@Nullable DimensionDataStorage storage) {
|
||||
if (storage != null) {
|
||||
@@ -28,7 +28,9 @@ index 28872f70ac27aacc8848cf5659cfd2c55e4cd19a..1f15e0f5e091117e2d7bd9c96e6b67b0
|
||||
- compoundTag = storage.readTagFromDisk(string, DataFixTypes.SAVED_DATA_STRUCTURE_FEATURE_INDICES, 1493)
|
||||
+ // Gale start - MultiPaper - ignore null legacy structure data
|
||||
+ CompoundTag tag = storage.readTagFromDisk(string, DataFixTypes.SAVED_DATA_STRUCTURE_FEATURE_INDICES, 1493);
|
||||
+
|
||||
+ if (ignoreNullLegacyStructureData && tag == null) continue;
|
||||
+
|
||||
+ compoundTag = tag
|
||||
.getCompound("data")
|
||||
.getCompound("Features");
|
||||
|
||||
@@ -13,10 +13,10 @@ As part of: MultiPaper (https://github.com/MultiPaper/MultiPaper)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 5c8d76b80c6cefd87088282e59f5f0f72a4f1611..b6127fff62c49809cfa54e39a35c89f45f46c66c 100644
|
||||
index 5c8d76b80c6cefd87088282e59f5f0f72a4f1611..0e298479c91a2789b3d808d512ec5210dabcbb06 100644
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -550,9 +550,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -550,9 +550,15 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
}
|
||||
|
||||
private void tickChunks(long timeInhabited, List<LevelChunk> chunks) { // Gale - Purpur - remove vanilla profiler
|
||||
@@ -24,6 +24,7 @@ index 5c8d76b80c6cefd87088282e59f5f0f72a4f1611..b6127fff62c49809cfa54e39a35c89f4
|
||||
+ NaturalSpawner.SpawnState spawnState; // moved down
|
||||
+ final boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
|
||||
+ boolean flagAndHasNaturalSpawn = _boolean && this.anySpawnCategoryIsSpawnedThisTick();
|
||||
+
|
||||
+ if (flagAndHasNaturalSpawn) {
|
||||
+ // Gale end - MultiPaper - skip unnecessary mob spawning computations
|
||||
int naturalSpawnChunkCount = this.distanceManager.getNaturalSpawnChunkCount();
|
||||
@@ -32,7 +33,7 @@ index 5c8d76b80c6cefd87088282e59f5f0f72a4f1611..b6127fff62c49809cfa54e39a35c89f4
|
||||
if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled
|
||||
// re-set mob counts
|
||||
for (ServerPlayer player : this.level.players) {
|
||||
@@ -574,10 +579,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -574,10 +580,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
}
|
||||
// Paper end - Optional per player mob spawns
|
||||
this.lastSpawnState = spawnState;
|
||||
@@ -49,7 +50,7 @@ index 5c8d76b80c6cefd87088282e59f5f0f72a4f1611..b6127fff62c49809cfa54e39a35c89f4
|
||||
// Paper start - PlayerNaturallySpawnCreaturesEvent
|
||||
for (ServerPlayer entityPlayer : this.level.players()) {
|
||||
int chunkRange = Math.min(level.spigotConfig.mobSpawnRange, entityPlayer.getBukkitEntity().getViewDistance());
|
||||
@@ -609,6 +618,20 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
@@ -609,6 +619,20 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,10 @@ The above copyright notice and this permission notice shall be included in all c
|
||||
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/net/minecraft/server/Eula.java b/net/minecraft/server/Eula.java
|
||||
index 1f0413214f54e9a47f53c623484d6882c85f54c9..e7db86ad7b0991dcfab101e0a6bb7fb279af3258 100644
|
||||
index 1f0413214f54e9a47f53c623484d6882c85f54c9..2ffd2ee5846c35b0394230116334518ba95ed409 100644
|
||||
--- a/net/minecraft/server/Eula.java
|
||||
+++ b/net/minecraft/server/Eula.java
|
||||
@@ -17,13 +17,29 @@ public class Eula {
|
||||
@@ -17,13 +17,31 @@ public class Eula {
|
||||
|
||||
public Eula(Path file) {
|
||||
this.file = file;
|
||||
@@ -42,10 +42,12 @@ index 1f0413214f54e9a47f53c623484d6882c85f54c9..e7db86ad7b0991dcfab101e0a6bb7fb2
|
||||
+ private boolean readGlobalFile() {
|
||||
+ try {
|
||||
+ Path globalFile = Path.of(System.getProperty("user.home"), "eula.txt");
|
||||
+
|
||||
+ if (globalFile.toFile().exists()) {
|
||||
+ return readFile(globalFile);
|
||||
+ }
|
||||
+ } catch (Throwable ignored) {}
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
@@ -58,7 +60,7 @@ index 1f0413214f54e9a47f53c623484d6882c85f54c9..e7db86ad7b0991dcfab101e0a6bb7fb2
|
||||
Properties map = new Properties();
|
||||
map.load(inputStream);
|
||||
var3 = Boolean.parseBoolean(map.getProperty("eula", "false"));
|
||||
@@ -31,8 +47,10 @@ public class Eula {
|
||||
@@ -31,8 +49,10 @@ public class Eula {
|
||||
|
||||
return var3;
|
||||
} catch (Exception var6) {
|
||||
|
||||
@@ -7,15 +7,16 @@ License: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
Gale - https://galemc.org
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 295dc5f9f7d8765d345e1c543c7ffea5baaf3cfc..985581d3b289911e4d2509a1a2e08f9dbf957e54 100644
|
||||
index 295dc5f9f7d8765d345e1c543c7ffea5baaf3cfc..7cbeb351d40245a159bacc8cc089957a95d095e9 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -1212,8 +1212,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -1212,8 +1212,18 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
}
|
||||
}
|
||||
|
||||
+ // Gale start - skip negligible planar movement multiplication
|
||||
+ Vec3 oldDeltaMovement = this.getDeltaMovement();
|
||||
+
|
||||
+ if (oldDeltaMovement.x < -1e-6 || oldDeltaMovement.x > 1e-6 || oldDeltaMovement.z < -1e-6 || oldDeltaMovement.z > 1e-6) {
|
||||
+ // Gale end - skip negligible planar movement multiplication
|
||||
float blockSpeedFactor = this.getBlockSpeedFactor();
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
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/io/papermc/paper/entity/activation/ActivationRange.java b/io/papermc/paper/entity/activation/ActivationRange.java
|
||||
index 54916fe57ceeab24936ce50709402ecf1fcd9a10..01631bbe14a4bed817a6de41fa268a3e4f949180 100644
|
||||
--- a/io/papermc/paper/entity/activation/ActivationRange.java
|
||||
+++ b/io/papermc/paper/entity/activation/ActivationRange.java
|
||||
@@ -75,7 +75,7 @@ public final class ActivationRange {
|
||||
}
|
||||
|
||||
// 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;
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 95972e7d5e0357ff5884f1cb2f7596c5029f999d..a5f76c81dfb148fc184d137395d5961229cb799b 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -174,7 +174,9 @@ 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
|
||||
}
|
||||
|
||||
public LevelChunk(ServerLevel level, ProtoChunk chunk, @Nullable LevelChunk.PostLoadProcessor postLoad) {
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
index 0c41177462cca5c4bbab6490e323b9535fd6300f..231d1905092532acf7e632197ba0e727adc4b1d7 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
@@ -104,7 +104,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);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ this patch is focused around the sensors used for ai
|
||||
delete the line of sight cache less often and use a faster nearby comparison
|
||||
|
||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||
index 062e83860a3f9e3a40c513ca389d628ba936f465..32e058cc28b48c105271fc4a1115608dc8a7f670 100644
|
||||
index b242b9b6c1f798c2656fa77b1d04e57b2caec5dc..774aa4c2d4d2ba4e9fab6bcca20e7d07bd7fc17f 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -1003,15 +1003,16 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
@@ -18,10 +18,10 @@ this patch is focused around the sensors used for ai
|
||||
delete the line of sight cache less often and use a faster nearby comparison
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/sensing/Sensing.java b/net/minecraft/world/entity/ai/sensing/Sensing.java
|
||||
index e17b1a2a95975d1eae5adaa679e027b9181dddbd..9a2c3a8ee9b0f863bf2761901a7550ff71b58acc 100644
|
||||
index e17b1a2a95975d1eae5adaa679e027b9181dddbd..cc25f5838aec5ed9fca2fb8b0322fafad9397a46 100644
|
||||
--- a/net/minecraft/world/entity/ai/sensing/Sensing.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/Sensing.java
|
||||
@@ -7,33 +7,70 @@ import net.minecraft.world.entity.Mob;
|
||||
@@ -7,33 +7,79 @@ import net.minecraft.world.entity.Mob;
|
||||
|
||||
public class Sensing {
|
||||
private final Mob mob;
|
||||
@@ -41,10 +41,12 @@ index e17b1a2a95975d1eae5adaa679e027b9181dddbd..9a2c3a8ee9b0f863bf2761901a7550ff
|
||||
this.mob = mob;
|
||||
+ // Gale start - Petal - reduce line of sight updates - expiring entity id lists
|
||||
+ int updateLineOfSightInterval = org.galemc.gale.configuration.GaleGlobalConfiguration.get().smallOptimizations.reducedIntervals.updateEntityLineOfSight;
|
||||
+
|
||||
+ if (updateLineOfSightInterval <= 1) {
|
||||
+ this.expiring = null;
|
||||
+ } else {
|
||||
+ this.expiring = new it.unimi.dsi.fastutil.ints.IntList[updateLineOfSightInterval];
|
||||
+
|
||||
+ for (int i = 0; i < updateLineOfSightInterval; i++) {
|
||||
+ this.expiring[i] = new it.unimi.dsi.fastutil.ints.IntArrayList(0);
|
||||
+ }
|
||||
@@ -59,13 +61,18 @@ index e17b1a2a95975d1eae5adaa679e027b9181dddbd..9a2c3a8ee9b0f863bf2761901a7550ff
|
||||
+ // Gale start - Petal - reduce line of sight updates
|
||||
+ } else {
|
||||
+ var expiringNow = this.expiring[this.nextToExpireIndex];
|
||||
+
|
||||
+ expiringNow.forEach(this.seen::remove);
|
||||
+ expiringNow.clear();
|
||||
+
|
||||
+ this.currentCacheAddIndex++;
|
||||
+
|
||||
+ if (this.currentCacheAddIndex == this.expiring.length) {
|
||||
+ this.currentCacheAddIndex = 0;
|
||||
+ }
|
||||
+
|
||||
+ this.nextToExpireIndex++;
|
||||
+
|
||||
+ if (this.nextToExpireIndex == this.expiring.length) {
|
||||
+ this.nextToExpireIndex = 0;
|
||||
+ }
|
||||
@@ -78,6 +85,7 @@ index e17b1a2a95975d1eae5adaa679e027b9181dddbd..9a2c3a8ee9b0f863bf2761901a7550ff
|
||||
- if (this.seen.contains(id)) {
|
||||
+ // Gale start - Petal - reduce line of sight cache lookups - merge sets
|
||||
+ int cached = this.seen.get(id);
|
||||
+
|
||||
+ if (cached == 1) {
|
||||
+ // Gale end - Petal - reduce line of sight cache lookups - merge sets
|
||||
return true;
|
||||
@@ -93,6 +101,7 @@ index e17b1a2a95975d1eae5adaa679e027b9181dddbd..9a2c3a8ee9b0f863bf2761901a7550ff
|
||||
- this.unseen.add(id);
|
||||
+ this.seen.put(id, 2); // Gale - Petal - reduce line of sight cache lookups - merge sets
|
||||
+ }
|
||||
+
|
||||
+ // Gale start - Petal - reduce line of sight updates
|
||||
+ if (this.expiring != null) {
|
||||
+ this.expiring[this.currentCacheAddIndex].add(id);
|
||||
@@ -1,67 +0,0 @@
|
||||
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 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/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index ba32db69c95b325a781cb2dff4200e4464a11baf..91156797d0ffed5227851b398d8b896aef71d614 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -286,7 +286,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) {
|
||||
@@ -43,28 +43,6 @@ public class GaleGlobalConfiguration extends ConfigurationPart {
|
||||
|
||||
}
|
||||
|
||||
// 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();
|
||||
io.papermc.paper.entity.activation.ActivationRange.wakeUpDurationRandom = entityWakeUpDuration ? new org.galemc.gale.random.XorShiftRandom() : new Random();
|
||||
org.bukkit.craftbukkit.CraftWorld.rand = generateTreeWithBukkitAPI ? new org.galemc.gale.random.XorShiftRandom() : new Random();
|
||||
}
|
||||
|
||||
}
|
||||
// Gale end - xor-shift random
|
||||
|
||||
}
|
||||
|
||||
public GameplayMechanics gameplayMechanics;
|
||||
|
||||
@@ -1,404 +0,0 @@
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user