args)
+ {
ExecutorService executor = ctx.host.getExecutor(pool);
if (executor == null)
{
// app is shutting down - no more threads can be spawned.
- taskFuture = CompletableFuture.completedFuture(Value.NULL);
+ return CompletableFuture.completedFuture(Value.NULL);
}
else
{
- taskFuture = CompletableFuture.supplyAsync(
+ return CompletableFuture.supplyAsync(
() ->
{
try
@@ -52,7 +63,6 @@ public class ThreadValue extends Value
ctx.host.getExecutor(pool)
);
}
- Thread.yield();
}
@Override
From eed64f224e1c72b8718484e2dab786ea3896cf9f Mon Sep 17 00:00:00 2001
From: Crec0 <83436716+Crec0@users.noreply.github.com>
Date: Sat, 8 Jan 2022 11:41:54 -0800
Subject: [PATCH 02/17] Minor Docs update (#1214)
---
docs/scarpet/api/Entities.md | 14 ++++++++++----
docs/scarpet/language/Operators.md | 2 +-
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md
index af0dbc52..044e1837 100644
--- a/docs/scarpet/api/Entities.md
+++ b/docs/scarpet/api/Entities.md
@@ -202,13 +202,19 @@ List of entities riding the entity.
Entity that `e` rides.
-### `query(e, 'scoreboard_tags')` and
-### `query(e, 'tags')`(deprecated)
+### `(deprecated) query(e, 'tags')`
+
+Deprecated by `query(e, 'scoreboard_tags')`
+
+### `query(e, 'scoreboard_tags')`
List of entity's scoreboard tags.
-### `query(e, 'has_scoreboard_tag',tag)` and
-### `query(e, 'has_tag',tag)`(deprecated)
+### `(deprecated) query(e, 'has_tag',tag)`
+
+Deprecated by `query(e, 'has_scoreboard_tag',tag)`
+
+### `query(e, 'has_scoreboard_tag',tag)`
Boolean, true if the entity is marked with a `tag` scoreboad tag.
diff --git a/docs/scarpet/language/Operators.md b/docs/scarpet/language/Operators.md
index cc5b8d0a..c0e8dd5a 100644
--- a/docs/scarpet/language/Operators.md
+++ b/docs/scarpet/language/Operators.md
@@ -110,7 +110,7 @@ Or an example to find if a player has specific enchantment on a held axe (either
global_get_enchantment(p, ench) -> (
-$ for(['main','offhand'],
+$ for(['mainhand','offhand'],
$ holds = query(p, 'holds', _);
$ if( holds,
$ [what, count, nbt] = holds;
From a8f9b96e9e5e519ea61b7f6a07eb6022b98f0b1f Mon Sep 17 00:00:00 2001
From: Ghoulboy
Date: Sat, 8 Jan 2022 20:58:43 +0100
Subject: [PATCH 03/17] Fixes #1222 (#1224)
---
src/main/java/carpet/script/value/EntityValue.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java
index 33480c06..19a0f670 100644
--- a/src/main/java/carpet/script/value/EntityValue.java
+++ b/src/main/java/carpet/script/value/EntityValue.java
@@ -1584,7 +1584,7 @@ public class EntityValue extends Value
});
put("absorption", (e, v) -> {
- if (e instanceof PlayerEntity) ((PlayerEntity) e).setAbsorptionAmount((float) NumericValue.asNumber(v, "absorbtion").getLong());
+ if (e instanceof PlayerEntity) ((PlayerEntity) e).setAbsorptionAmount(NumericValue.asNumber(v, "absorbtion").getFloat());
});
put("add_xp", (e, v) -> {
From de305f428460ed7945d3905cf0bd633082c104c9 Mon Sep 17 00:00:00 2001
From: altrisi
Date: Sat, 8 Jan 2022 21:08:26 +0100
Subject: [PATCH 04/17] Allow apps to retrieve information about the source
(#1229)
* Give information about the sources
* Document source related system_info properties
---
docs/scarpet/api/Auxiliary.md | 26 ++++++++++++++-----
.../java/carpet/script/api/Auxiliary.java | 1 +
.../java/carpet/script/utils/SystemInfo.java | 14 +++++++---
3 files changed, 32 insertions(+), 9 deletions(-)
diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md
index 072f401e..9f84424b 100644
--- a/docs/scarpet/api/Auxiliary.md
+++ b/docs/scarpet/api/Auxiliary.md
@@ -681,13 +681,13 @@ Fetches the value of a system property or returns all inforation as a map when c
fetch various information, mostly not changing, or only available via low level
system calls. In all circumstances, these are only provided as read-only.
-Available options in the scarpet app space:
+##### Available options in the scarpet app space:
* `app_name` - current app name or `null` if its a default app
* `app_list` - list of all loaded apps excluding default commandline app
* `app_scope` - scope of the global variables and function. Available options is `player` and `global`
* `app_player` - returns a player list that have app run under them. For `global` apps, the list is always empty
- Relevant world related properties
+##### Relevant world related properties
* `world_name` - name of the world
* `world_seed` - a numeric seed of the world
* `world_dimensions` - a list of dimensions in the world
@@ -702,7 +702,7 @@ Available options in the scarpet app space:
* `world_center` - Returns coordinates of the center of the world with respect of the world border
* `world_size` - Returns size of the world where at this distance from `world_center` world border appears.
*
- Relevant gameplay related properties
+##### Relevant gameplay related properties
* `game_difficulty` - current difficulty of the game: `'peaceful'`, `'easy'`, `'normal'`, or `'hard'`
* `game_hardcore` - boolean whether the game is in hardcore mode
* `game_storage_format` - format of the world save files, either `'McRegion'` or `'Anvil'`
@@ -719,7 +719,7 @@ Available options in the scarpet app space:
* `game_data_version` - data version of the game. Returns an integer, so it can be compared.
* `game_stable` - indicating if its a production release or a snapshot
- Server related properties
+##### Server related properties
* `server_motd` - the motd of the server visible when joining
* `server_ip` - IP adress of the game hosted
* `server_whitelisted` - boolean indicating whether the access to the server is only for whitelisted players
@@ -734,7 +734,21 @@ list may refer to the previous tick performance. In this case the last entry (ti
tick. For all intent and purpose, `system_info('last_tick_times'):0` should be used as last tick execution time, but
individual tick times may vary greatly, and these need to be taken with the little grain of averaging.
- System related properties
+##### Source related properties
+
+ The source is what is the cause of the code running, with Carpet using it same way as Minecraft commands use to run. Those are used in
+ some API functions that interact with the game or with commands, and can be manipulated if the execution is caused by an `execute` command, modified
+ by some functions or ran in non-standard ways. This section provides useful information from these cases (like running from a command
+ block, right clicking a sign, etc)
+ * `source_entity` - The entity associated with the execution. This is usually a player (in which case `player()` would get the entity from this),
+ but it may also be a different entity or `null` if the execution comes from the server console or a command block.
+ * `source_position` - The position associated with the execution. This is usually the position of the entity, but it may have been manipulated or
+ it could come from a command block (no entity then). If this call comes from the server console, it will be the world spawn.
+ * `source_dimension` - The dimension associated with the execution. Execution from the server console provides `overworld` as the dimension.
+ This can be manipulated by running code inside `in_dimension()`.
+ * `source_rotation` - The rotation associated with the execution. Usually `[0, 0]` in non-standard situations, the rotation of the entity otherwise.
+
+##### System related properties
* `java_max_memory` - maximum allowed memory accessible by JVM
* `java_allocated_memory` - currently allocated memory by JVM
* `java_used_memory` - currently used memory by JVM
@@ -744,7 +758,7 @@ individual tick times may vary greatly, and these need to be taken with the litt
* `java_system_cpu_load` - current percentage of CPU used by the system
* `java_process_cpu_load` - current percentage of CPU used by JVM
- Scarpet related properties
+##### Scarpet related properties
* `scarpet_version` - returns the version of the carpet your scarpet comes with.
## NBT Storage
diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java
index da35463d..b89ee933 100644
--- a/src/main/java/carpet/script/api/Auxiliary.java
+++ b/src/main/java/carpet/script/api/Auxiliary.java
@@ -736,6 +736,7 @@ public class Auxiliary {
return Value.TRUE;
});
+ // Should this be deprecated for system_info('source_dimension')?
expression.addContextFunction("current_dimension", 0, (c, t, lv) ->
ValueConversions.of( ((CarpetContext)c).s.getWorld()));
diff --git a/src/main/java/carpet/script/utils/SystemInfo.java b/src/main/java/carpet/script/utils/SystemInfo.java
index 6aa56030..7d033cfb 100644
--- a/src/main/java/carpet/script/utils/SystemInfo.java
+++ b/src/main/java/carpet/script/utils/SystemInfo.java
@@ -5,6 +5,7 @@ import carpet.CarpetSettings;
import carpet.script.CarpetContext;
import carpet.script.CarpetScriptHost;
import carpet.script.value.BooleanValue;
+import carpet.script.value.EntityValue;
import carpet.script.value.ListValue;
import carpet.script.value.MapValue;
import carpet.script.value.NumericValue;
@@ -17,11 +18,9 @@ import com.sun.management.OperatingSystemMXBean;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.SharedConstants;
-import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.WorldSavePath;
-import net.minecraft.util.registry.RegistryKey;
+import net.minecraft.util.math.Vec2f;
import net.minecraft.world.GameRules;
-import net.minecraft.world.World;
import net.minecraft.world.WorldProperties;
import net.minecraft.world.border.WorldBorder;
@@ -199,6 +198,15 @@ public class SystemInfo {
});
return MapValue.wrap(rules);
});
+
+ put("source_entity", c -> EntityValue.of(c.s.getEntity()));
+ put("source_position", c -> ValueConversions.of(c.s.getPosition()));
+ put("source_dimension", c -> ValueConversions.of(c.s.getWorld()));
+ put("source_rotation", c -> {
+ Vec2f rotation = c.s.getRotation();
+ return ListValue.of(new NumericValue(rotation.x), new NumericValue(rotation.y));
+ });
+
put("scarpet_version", c -> StringValue.of(CarpetSettings.carpetVersion));
}};
From f2989d51fda5206691343d33b45b901d52195335 Mon Sep 17 00:00:00 2001
From: altrisi
Date: Sat, 8 Jan 2022 21:09:15 +0100
Subject: [PATCH 05/17] Improve CarpetExpressionException error messages
(#1230)
---
src/main/java/carpet/script/CarpetExpression.java | 2 +-
src/main/java/carpet/script/CarpetScriptHost.java | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java
index d8b9c5f9..60da9003 100644
--- a/src/main/java/carpet/script/CarpetExpression.java
+++ b/src/main/java/carpet/script/CarpetExpression.java
@@ -91,7 +91,7 @@ public class CarpetExpression
public Value scriptRunCommand(ScriptHost host, BlockPos pos)
{
if (CarpetServer.scriptServer.stopAll)
- throw new CarpetExpressionException("SCRIPTING PAUSED", null);
+ throw new CarpetExpressionException("SCRIPTING PAUSED (unpause with /script resume)", null);
try
{
Context context = new CarpetContext(host, source, origin).
diff --git a/src/main/java/carpet/script/CarpetScriptHost.java b/src/main/java/carpet/script/CarpetScriptHost.java
index ef67e102..67614b11 100644
--- a/src/main/java/carpet/script/CarpetScriptHost.java
+++ b/src/main/java/carpet/script/CarpetScriptHost.java
@@ -732,10 +732,10 @@ public class CarpetScriptHost extends ScriptHost
public Value callLegacy(ServerCommandSource source, String call, List coords, String arg)
{
if (CarpetServer.scriptServer.stopAll)
- throw new CarpetExpressionException("SCARPET PAUSED", null);
+ throw new CarpetExpressionException("SCARPET PAUSED (unpause with /script resume)", null);
FunctionValue function = getFunction(call);
if (function == null)
- throw new CarpetExpressionException("UNDEFINED", null);
+ throw new CarpetExpressionException("Couldn't find function '" + call + "' in app '" + this.getName() + "'", null);
List argv = new ArrayList<>();
if (coords != null)
for (Integer i: coords)
@@ -832,7 +832,7 @@ public class CarpetScriptHost extends ScriptHost
public Value call(ServerCommandSource source, FunctionValue function, List argv)
{
if (CarpetServer.scriptServer.stopAll)
- throw new CarpetExpressionException("SCARPET PAUSED", null);
+ throw new CarpetExpressionException("SCARPET PAUSED (unpause with /script resume)", null);
List args = function.getArguments();
if (argv.size() != args.size())
From 212eb07131cdb920dc87a2e3738a507ec3050782 Mon Sep 17 00:00:00 2001
From: altrisi
Date: Sat, 8 Jan 2022 21:12:23 +0100
Subject: [PATCH 06/17] Give feedback when stepping ticks (#1234)
---
src/main/java/carpet/commands/TickCommand.java | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/main/java/carpet/commands/TickCommand.java b/src/main/java/carpet/commands/TickCommand.java
index b4ada51e..78a8af5d 100644
--- a/src/main/java/carpet/commands/TickCommand.java
+++ b/src/main/java/carpet/commands/TickCommand.java
@@ -51,10 +51,10 @@ public class TickCommand
then(literal("deep").executes( (c)-> setFreeze(c.getSource(), true, true)))).
then(literal("off").executes( (c) -> setFreeze(c.getSource(), false, false)))).
then(literal("step").
- executes((c) -> step(1)).
+ executes((c) -> step(c.getSource(), 1)).
then(argument("ticks", integer(1,72000)).
suggests( (c, b) -> suggestMatching(new String[]{"20"},b)).
- executes((c) -> step(getInteger(c,"ticks"))))).
+ executes((c) -> step(c.getSource(), getInteger(c,"ticks"))))).
then(literal("superHot").executes( (c)-> toggleSuperHot(c.getSource()))).
then(literal("health").
executes( (c) -> healthReport(c.getSource(), 100)).
@@ -130,9 +130,10 @@ public class TickCommand
return setFreeze(source, isDeep, !TickSpeed.isPaused());
}
- private static int step(int advance)
+ private static int step(ServerCommandSource source, int advance)
{
TickSpeed.add_ticks_to_run_in_pause(advance);
+ Messenger.m(source, "gi Stepping " + advance + " tick" + (advance != 1 ? "s" : ""));
return 1;
}
From 9fb6ec91cb7a1e76b5ceb5c03966ef116c991c07 Mon Sep 17 00:00:00 2001
From: altrisi
Date: Sat, 8 Jan 2022 23:05:21 +0100
Subject: [PATCH 07/17] Minor improvements to scarpet annotation API (#1239)
---
src/main/java/carpet/script/Expression.java | 11 +++++++----
src/main/java/carpet/script/Fluff.java | 2 ++
.../script/annotation/AnnotationParser.java | 19 +++++++++++--------
.../script/annotation/ScarpetFunction.java | 9 +++++++--
.../script/annotation/ValueConverter.java | 6 +++---
5 files changed, 30 insertions(+), 17 deletions(-)
diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java
index e4109da4..4796765c 100644
--- a/src/main/java/carpet/script/Expression.java
+++ b/src/main/java/carpet/script/Expression.java
@@ -481,9 +481,9 @@ public class Expression
}
- public void addLazyFunction(String name, int num_params, TriFunction, LazyValue> fun)
+ public void addLazyFunction(String name, int numParams, TriFunction, LazyValue> fun)
{
- functions.put(name, new AbstractLazyFunction(num_params, name)
+ functions.put(name, new AbstractLazyFunction(numParams, name)
{
@Override
public boolean pure() {
@@ -499,8 +499,11 @@ public class Expression
public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List lazyParams)
{
ILazyFunction.checkInterrupts();
- if (num_params >= 0 && lazyParams.size() != num_params)
- throw new InternalExpressionException("'"+name+"' requires "+num_params+" parameters, "+lazyParams.size()+" provided.");
+ if (numParams >= 0 && lazyParams.size() != numParams)
+ {
+ String error = "Function '"+name+"' requires "+numParams+" arguments, got "+lazyParams.size()+". ";
+ throw new InternalExpressionException(error + (fun instanceof Fluff.UsageProvider up ? up.getUsage() : ""));
+ }
try
{
diff --git a/src/main/java/carpet/script/Fluff.java b/src/main/java/carpet/script/Fluff.java
index d2e07fdc..ab2e45ba 100644
--- a/src/main/java/carpet/script/Fluff.java
+++ b/src/main/java/carpet/script/Fluff.java
@@ -30,6 +30,8 @@ public abstract class Fluff
@FunctionalInterface
public interface SexFunction { R apply(A a, B b, C c, D d, E e, F f);}
+ public interface UsageProvider { String getUsage();}
+
public interface EvalNode
{
/**
diff --git a/src/main/java/carpet/script/annotation/AnnotationParser.java b/src/main/java/carpet/script/annotation/AnnotationParser.java
index a2c759c6..2e8907dd 100644
--- a/src/main/java/carpet/script/annotation/AnnotationParser.java
+++ b/src/main/java/carpet/script/annotation/AnnotationParser.java
@@ -21,6 +21,7 @@ import carpet.script.Context;
import carpet.script.Expression;
import carpet.script.Fluff.AbstractLazyFunction;
import carpet.script.Fluff.TriFunction;
+import carpet.script.Fluff.UsageProvider;
import carpet.script.exception.InternalExpressionException;
import carpet.script.LazyValue;
import carpet.script.value.Value;
@@ -73,6 +74,7 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
*/
public final class AnnotationParser
{
+ static final int UNDEFINED_PARAMS = -2;
private static final List functionList = new ArrayList<>();
/**
@@ -90,8 +92,8 @@ public final class AnnotationParser
* {@link InternalExpressionException}).
* Basically, it's fine as long as you don't add a {@code throws} declaration to your methods.
* Varargs (or effectively varargs) annotated methods must explicitly declare a maximum number of parameters to ingest in the {@link ScarpetFunction}
- * annotation. They can still declare an unlimited amount by setting that maximum to {@code -1}. "Effectively varargs" means a function that has
- * a parameter using/requiring a {@link ValueConverter} that has declared {@link ValueConverter#consumesVariableArgs()}.
+ * annotation. They can still declare an unlimited amount by setting that maximum to {@link ScarpetFunction#UNLIMITED_PARAMS}. "Effectively varargs"
+ * means a function that has at least a parameter requiring a {@link ValueConverter} that has declared {@link ValueConverter#consumesVariableArgs()}.
* Annotated methods must not have a parameter with generics as the varargs parameter. This is just because it was painful for me (altrisi) and
* didn't want to support it. Those will crash with a {@code ClassCastException}
*
@@ -141,7 +143,7 @@ public final class AnnotationParser
expr.addLazyFunction(function.name, function.scarpetParamCount, function);
}
- private static class ParsedFunction implements TriFunction, LazyValue>
+ private static class ParsedFunction implements TriFunction, LazyValue>, UsageProvider
{
private final String name;
private final boolean isMethodVarArgs;
@@ -186,14 +188,14 @@ public final class AnnotationParser
if (this.isEffectivelyVarArgs)
{
maxParams = method.getAnnotation(ScarpetFunction.class).maxParams();
- if (maxParams == -2)
- throw new IllegalArgumentException("No maximum number of params specified for " + name + ", use -1 for unlimited. "
+ if (maxParams == UNDEFINED_PARAMS)
+ throw new IllegalArgumentException("No maximum number of params specified for " + name + ", use ScarpetFunction.UNLIMITED_PARAMS for unlimited. "
+ "Provided in " + instance.getClass());
+ if (maxParams == ScarpetFunction.UNLIMITED_PARAMS)
+ maxParams = Integer.MAX_VALUE;
if (maxParams < this.minParams)
throw new IllegalArgumentException("Provided maximum number of params for " + name + " is smaller than method's param count."
+ "Provided in " + instance.getClass());
- if (maxParams == -1)
- maxParams = Integer.MAX_VALUE;
}
this.maxParams = maxParams;
@@ -293,7 +295,8 @@ public final class AnnotationParser
return params;
}
- private String getUsage()
+ @Override
+ public String getUsage()
{
// Possibility: More descriptive messages using param.getName()? Would need changing gradle setup to keep those
StringBuilder builder = new StringBuilder("Usage: '");
diff --git a/src/main/java/carpet/script/annotation/ScarpetFunction.java b/src/main/java/carpet/script/annotation/ScarpetFunction.java
index 466bda7e..edb980fd 100644
--- a/src/main/java/carpet/script/annotation/ScarpetFunction.java
+++ b/src/main/java/carpet/script/annotation/ScarpetFunction.java
@@ -51,6 +51,11 @@ import carpet.script.value.Value;
@Retention(RUNTIME)
public @interface ScarpetFunction
{
+ /**
+ * Used to define that this {@link ScarpetFunction} can accept an unlimited number of parameters
+ */
+ public static final int UNLIMITED_PARAMS = -1;
+
/**
* If the function can accept a variable number of parameters, either by declaring its last parameter as a varargs parameter or by having one
* of their parameters use a converter that consumes a variable number of arguments, this must define the maximum number of parameters this
@@ -65,11 +70,11 @@ public @interface ScarpetFunction
* consider that those can take either a single triple of values or 3 independent values, that would be counted in the maximum number of
* parameters.
*
- * Use -1 to specify an unlimited number of parameters.
+ * Use {@link ScarpetFunction#UNLIMITED_PARAMS} to allow an unlimited number of parameters.
*
* @return The maximum number of parameters this function can accept
*/
- int maxParams() default -2;
+ int maxParams() default AnnotationParser.UNDEFINED_PARAMS;
/**
* Defines the Context Type that will be used when evaluating arguments to annotated methods.
diff --git a/src/main/java/carpet/script/annotation/ValueConverter.java b/src/main/java/carpet/script/annotation/ValueConverter.java
index 2a5e50c8..ed1a1812 100644
--- a/src/main/java/carpet/script/annotation/ValueConverter.java
+++ b/src/main/java/carpet/script/annotation/ValueConverter.java
@@ -162,13 +162,13 @@ public interface ValueConverter
* constraints as {@link #convert(Value)}