From 968ef0cd9f863ec071d46c228a160402406ed1d7 Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 21 Aug 2020 00:47:19 -0300 Subject: [PATCH] numbers in scarpet better handle long type values. If possible, numbers that can be represented as longs (seeds, etc) will be handled as longs but they will loose their longinness with a single arithmetic operation. --- docs/scarpet/Full.md | 43 ++++++++++++++++--- .../scarpet/language/VariablesAndConstants.md | 7 ++- src/main/java/carpet/script/Expression.java | 14 ++++-- .../carpet/script/value/FunctionValue.java | 2 +- .../java/carpet/script/value/ListValue.java | 2 +- .../java/carpet/script/value/MapValue.java | 2 +- .../carpet/script/value/NumericValue.java | 37 +++++++++++++--- src/main/java/carpet/script/value/Value.java | 4 +- 8 files changed, 87 insertions(+), 24 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 1d0473a7..d51cb75c 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -308,8 +308,11 @@ block positions. All variables starting with `_` are read-only, and cannot be de ## Literals `scarpet` accepts numeric and string liters constants. Numbers look like `1, 2.5, -3e-7, 0xff,` and are internally -represented as Java's `double` but `scarpet` will try to trim trailing zeros as much as possible so if you need to -use them as intergers, you can. Strings use single quoting, for multiple reasons, but primarily to allow for +represented primarily as Java's `double` but `scarpet` will try to trim trailing zeros as much as possible so if you +need to use them as integers or even longs - you can. However any operation on a number even if it can be properly +represented as long, but not a double type, will make them round up to be doubles. + +Strings use single quoting, for multiple reasons, but primarily to allow for easier use of strings inside doubly quoted command arguments (when passing a script as a parameter of `/script fill` for example), or when typing in jsons inside scarpet (to feed back into a `/data merge` command for example). Strings also use backslashes `\` for quoting special characters, in both plain strings and regular expressions @@ -1109,7 +1112,7 @@ for(range(1000000,1100000),check_prime(_)) => 7216 From which we can learn that there is 7216 primes between 1M and 1.1M -### `while(cond, limit,expr)` +### `while(cond, limit, expr)` Evaluates expression `expr` repeatedly until condition `cond` becomes false, but not more than `limit` times. Returns the result of the last `expr` evaluation, or `null` if nothing was successful. Both `expr` and `cond` will @@ -1205,7 +1208,8 @@ it will be used from now on as a new value for the accumulator.
 reduce([1,2,3,4],_a+_,0)  => 10
 reduce([1,2,3,4],_a*_,1)  => 24
-
# User-defined functions and program control flow + +# User-defined functions and program control flow ## Writing programs with more than 1 line @@ -1801,6 +1805,11 @@ markers for scarpet apps. `meeting` is the only one with increased max occupancy Changes the biome at that block position. if update is specified and false, then chunk will not be refreshed on the clients. Biome changes can only be send to clients with the entire data from the chunk. +Setting a biome is now (as of 1.16) dimension specific. In the overworld and the end changing the biome +is only effective if you set it at y=0, and affects the entire column of. In the nether - you have to use the +specific Y coordinate of the biome you want to change, and it affects roughly 4x4x4 area (give or take some random +noise). + ### `update(pos)` Causes a block update at position. @@ -2380,6 +2389,28 @@ All generated structures will retain their properties, like mob spawning, howeve itself has certain rules to spawn mobs, like plopping a nether fortress in the overworld will not spawn nether mobs, because nether mobs can spawn only in the nether, but plopped in the nether - will behave like a valid nether fortress. +### `custom_dimension(name, seed?)` + +Ensures the dimension with the given `'name'` is available and configured with the given seed. It merely sets the world +generator settings to the overworld, and the optional custom seed (or using current world seed, if not provided). + +If the dimension with this name already exists, returns `false` and does nothing. + +Created dimension with `custom_dimension` only exist till the game restart (same with the datapacks, if removed), but +all the world data should be saved. If custom dimension is re-created next time the app is loaded it will be using +the existing world content. This means that it is up to the programmer to make sure the custom dimensions settings +are stored in app data and restored when app reloads and wants to use previous worlds. Since vanilla game only keeps +track of world data, not the world settings, if the dimension hasn't been yet configured via `custom_dimension` and +the app hasn't yet initalized their dimension, the players will be positioned in the overworld at the same coordinates. + +List of custom dimensions (to be used in the likes of `/execute in `) is only send to the clients when joining the +game, meaning custom worlds created after a player has joined will not be suggested in vanilla commands, but running +vanilla commands on them will be successful. Its due to the fact that datapacks with dimensions are always loaded +with the game and assumed not changing. + +`custom_dimension` is experimental and considered a WIP. More customization options besides the seed will be added in +the future. + # Iterating over larger areas of blocks These functions help scan larger areas of blocks without using generic loop functions, like nested `loop`. @@ -2589,12 +2620,12 @@ query(e,'custom_name') => null query(e,'type') => villager -## `query(e, 'command_name')` +### `query(e, 'command_name')` Returns a valid string to be used in commands to address an entity. Its UUID for all entities except player, where its their name. -## `query(e, 'persistence')` +### `query(e, 'persistence')` Returns if a mob has a persistence tag or not. Returns `null` for non-mob entities. diff --git a/docs/scarpet/language/VariablesAndConstants.md b/docs/scarpet/language/VariablesAndConstants.md index f45f46b8..8256c550 100644 --- a/docs/scarpet/language/VariablesAndConstants.md +++ b/docs/scarpet/language/VariablesAndConstants.md @@ -16,8 +16,11 @@ block positions. All variables starting with `_` are read-only, and cannot be de ## Literals `scarpet` accepts numeric and string liters constants. Numbers look like `1, 2.5, -3e-7, 0xff,` and are internally -represented as Java's `double` but `scarpet` will try to trim trailing zeros as much as possible so if you need to -use them as intergers, you can. Strings use single quoting, for multiple reasons, but primarily to allow for +represented primarily as Java's `double` but `scarpet` will try to trim trailing zeros as much as possible so if you +need to use them as integers or even longs - you can. However any operation on a number even if it can be properly +represented as long, but not a double type, will make them round up to be doubles. + +Strings use single quoting, for multiple reasons, but primarily to allow for easier use of strings inside doubly quoted command arguments (when passing a script as a parameter of `/script fill` for example), or when typing in jsons inside scarpet (to feed back into a `/data merge` command for example). Strings also use backslashes `\` for quoting special characters, in both plain strings and regular expressions diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 041d2221..a154cb6d 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -1546,11 +1546,17 @@ public class Expression }); addUnaryFunction("number", v -> { if (v instanceof NumericValue) + { return v; - double res = v.readNumber(); - if (Double.isNaN(res)) + } + try + { + return new NumericValue(v.getString()); + } + catch (NumberFormatException format) + { return Value.NULL; - return new NumericValue(v.readNumber()); + } }); addFunction("str", lv -> { @@ -1593,7 +1599,7 @@ public class Expression { if (argIndex >= lv.size()) throw new InternalExpressionException("Not enough arguments for "+m.group(0)); - args.add(lv.get(argIndex).readNumber()); + args.add(lv.get(argIndex).readDoubleNumber()); argIndex++; } else if (fmt == 'b') diff --git a/src/main/java/carpet/script/value/FunctionValue.java b/src/main/java/carpet/script/value/FunctionValue.java index 45791fad..d36f3113 100644 --- a/src/main/java/carpet/script/value/FunctionValue.java +++ b/src/main/java/carpet/script/value/FunctionValue.java @@ -120,7 +120,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction } @Override - public double readNumber() + public double readDoubleNumber() { throw new InternalExpressionException("Function value has no numeric value"); } diff --git a/src/main/java/carpet/script/value/ListValue.java b/src/main/java/carpet/script/value/ListValue.java index bd2f03e1..7409e9de 100644 --- a/src/main/java/carpet/script/value/ListValue.java +++ b/src/main/java/carpet/script/value/ListValue.java @@ -352,7 +352,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } @Override - public double readNumber() + public double readDoubleNumber() { return (double)items.size(); } diff --git a/src/main/java/carpet/script/value/MapValue.java b/src/main/java/carpet/script/value/MapValue.java index 099206d2..9787304c 100644 --- a/src/main/java/carpet/script/value/MapValue.java +++ b/src/main/java/carpet/script/value/MapValue.java @@ -202,7 +202,7 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa } @Override - public double readNumber() + public double readDoubleNumber() { return (double)map.size(); } diff --git a/src/main/java/carpet/script/value/NumericValue.java b/src/main/java/carpet/script/value/NumericValue.java index 482d9fab..b1c81eaf 100644 --- a/src/main/java/carpet/script/value/NumericValue.java +++ b/src/main/java/carpet/script/value/NumericValue.java @@ -15,6 +15,7 @@ import static java.lang.Math.abs; public class NumericValue extends Value { private Double value; + private Long longValue; final static double epsilon = 1024*Double.MIN_VALUE; public static NumericValue asNumber(Value v1, String id) @@ -35,6 +36,10 @@ public class NumericValue extends Value @Override public String getString() { + if (longValue != null) + { + return Long.toString(getLong()); + } try { return BigDecimal.valueOf(value).stripTrailingZeros().toPlainString(); @@ -48,7 +53,8 @@ public class NumericValue extends Value @Override public String getPrettyString() { - if (getDouble() == (double)getLong()) + + if (longValue!= null || getDouble() == (double)getLong()) { return Long.toString(getLong()); } @@ -72,13 +78,14 @@ public class NumericValue extends Value return value.floatValue(); } - public static long floor(double double_1) { + private static long floor(double double_1) { long int_1 = (long)double_1; return double_1 < (double)int_1 ? int_1 - 1 : int_1; } public long getLong() { + if (longValue != null) return longValue; return floor((value+epsilon)); } @@ -119,12 +126,10 @@ public class NumericValue extends Value return super.divide(v); } - - @Override public Value clone() { - return new NumericValue(value); + return new NumericValue(value, longValue); } @Override @@ -158,12 +163,28 @@ public class NumericValue extends Value { this.value = value; } + private NumericValue(double value, Long longValue) + { + this.value = value; + this.longValue = longValue; + } + public NumericValue(String value) { - this(new BigDecimal(value).doubleValue()); + BigDecimal decimal = new BigDecimal(value); + if (decimal.stripTrailingZeros().scale() <= 0) + { + try + { + longValue = decimal.longValueExact(); + } + catch (ArithmeticException ignored) {} + } + this.value = decimal.doubleValue(); } public NumericValue(long value) { + this.longValue = value; this.value = (double)value; } public NumericValue(boolean boolval) @@ -178,7 +199,7 @@ public class NumericValue extends Value } @Override - public double readNumber() + public double readDoubleNumber() { return value; } @@ -212,6 +233,8 @@ public class NumericValue extends Value @Override public Tag toTag(boolean force) { + if (longValue != null) + return LongTag.of(longValue); long longValue = getLong(); if (value == (double)longValue) { diff --git a/src/main/java/carpet/script/value/Value.java b/src/main/java/carpet/script/value/Value.java index 82bdd664..94634bf0 100644 --- a/src/main/java/carpet/script/value/Value.java +++ b/src/main/java/carpet/script/value/Value.java @@ -161,7 +161,7 @@ public abstract class Value implements Comparable, Cloneable return new StringValue(value.substring((int)from, (int)to)); return new StringValue(value.substring((int)from)); } - public double readNumber() + public double readDoubleNumber() { String s = getString(); try @@ -176,7 +176,7 @@ public abstract class Value implements Comparable, Cloneable public long readInteger() { - return (long)readNumber(); + return (long) readDoubleNumber(); } public String getTypeString()