From 0d62fdc98019decc16ec18fbac41f1fb4fade3d6 Mon Sep 17 00:00:00 2001
From: gnembon Numeric function, indicating hardness of a block. Numeric function, indicating blast_resistance of a block. Boolean indicating if the given block position is in a slime chunk. Returns the Y value of the topmost block at given x, z coords (y value of a block is not important), according to the
@@ -623,7 +626,7 @@ public class CarpetExpression
* top('ocean_floor', x, y, z) => 41
*
* Boolean function, true if the block is accessible forthe game mechanics.
+ * Boolean function, true if the block is accessible for the game mechanics.
* Normally Returns current world seed. Returns current dimension that the script runs in. returns a random number from
* blast_resistance(pos)
+ * in_slime_chunk(pos)
* top(type, pos)
- * loaded(pos)scarpet doesn't check if operates on
* loaded area - the game will automatically load missing blocks. We see this as advantage.
* Vanilla fill/clone commands only check the specified corners for loadness.
+ * seed()
* current_dimension()
@@ -3399,6 +3417,12 @@ public class CarpetExpression
return (cc, tt) -> Value.TRUE;
});
+ this.expr.addLazyFunction("seed", -1, (c, t, lv) -> {
+ ServerCommandSource s = ((CarpetContext)c).s;
+ Value ret = new NumericValue(s.getWorld().getSeed());
+ return (cc, tt) -> ret;
+ });
+
this.expr.addLazyFunction("current_dimension", 0, (c, t, lv) -> {
ServerCommandSource s = ((CarpetContext)c).s;
Value retval = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.DIMENSION.getId(s.getWorld().dimension.getType())));
diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java
index d5ad5457..4e7a63d4 100644
--- a/src/main/java/carpet/script/Expression.java
+++ b/src/main/java/carpet/script/Expression.java
@@ -2720,12 +2720,15 @@ public class Expression
* length('foo') => 3
*
*
- * in_dimension(smth, expr)
+ * rand(expr)
* rand(expr), rand(expr, seed)0.0
* (inclusive) to expr (exclusive).
* In boolean context (in conditions, boolean functions, or bool), returns
* false if the randomly selected value is less than 1. This means that rand(2) returns true half
- * of the time and rand(5) returns true for 80% (4/5) of the timerand(5) returns true for 80% (4/5) of the time. If seed is not provided, uses a random seed.
+ * If seed is provided, each consecutive call to rand() will act like 'next' call to the same random object.
+ * Scarpet keeps track of up to 1024 custom random number generators, so if you exceed this number (per app), then your
+ * random sequence will revert to the beginning.
* map(range(10), floor(rand(10))) => [5, 8, 0, 6, 9, 3, 9, 9, 1, 8]
* map(range(10), bool(rand(2))) => [1, 1, 1, 0, 0, 1, 1, 0, 0, 0]
@@ -2982,7 +2985,12 @@ public class Expression
addUnaryFunction("type", v -> new StringValue(v.getTypeString()));
addUnaryFunction("length", v -> new NumericValue(v.length()));
- addLazyFunction("rand", 1, (c, t, lv) -> {
+ addLazyFunction("rand", -1, (c, t, lv) -> {
+ int argsize = lv.size();
+ Random randomizer = Expression.randomizer;
+ if (argsize != 1 && argsize != 2)
+ throw new InternalExpressionException("'rand' takes one (range) or two arguments (range and seed)");
+ if (argsize == 2) randomizer = c.host.getRandom(NumericValue.asNumber(lv.get(1).evalValue(c)).getLong());
Value argument = lv.get(0).evalValue(c);
if (argument instanceof ListValue)
{
diff --git a/src/main/java/carpet/script/ScriptHost.java b/src/main/java/carpet/script/ScriptHost.java
index ad2ba58f..63ef1dc2 100644
--- a/src/main/java/carpet/script/ScriptHost.java
+++ b/src/main/java/carpet/script/ScriptHost.java
@@ -4,11 +4,13 @@ import carpet.script.bundled.Module;
import carpet.script.exception.InternalExpressionException;
import carpet.script.value.FunctionValue;
import carpet.script.value.Value;
+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import java.util.stream.Stream;
@@ -16,6 +18,14 @@ import java.util.stream.Stream;
public abstract class ScriptHost
{
public static Map systemGlobals = new ConcurrentHashMap<>();
+ private static Map randomizers = new Long2ObjectOpenHashMap<>();
+
+ public Random getRandom(long aLong)
+ {
+ if (randomizers.size() > 1024)
+ randomizers.clear();
+ return randomizers.computeIfAbsent(aLong, Random::new);
+ }
public static class ModuleData