From a65d16c9ba7d74321d295105fbfc0dcdd5502cc7 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 21 Apr 2021 12:21:47 -0300 Subject: [PATCH 1/8] WIP unpacking of parameters. --- src/main/java/carpet/script/Context.java | 1 + src/main/java/carpet/script/Expression.java | 16 +++++---- src/main/java/carpet/script/Fluff.java | 34 ++++++++++++++++--- .../java/carpet/script/api/Auxiliary.java | 7 ++-- src/main/java/carpet/script/api/Entities.java | 4 +-- .../script/argument/FunctionArgument.java | 11 ++++++ .../carpet/script/language/Functions.java | 19 +++++++++-- .../carpet/script/language/Threading.java | 4 +-- .../value/FunctionUnpackedArgumentsValue.java | 10 ++++++ .../carpet/script/value/FunctionValue.java | 28 ++++++++++----- .../java/carpet/script/value/ListValue.java | 2 +- 11 files changed, 106 insertions(+), 30 deletions(-) create mode 100644 src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java diff --git a/src/main/java/carpet/script/Context.java b/src/main/java/carpet/script/Context.java index fb9b583e..ad87fa17 100644 --- a/src/main/java/carpet/script/Context.java +++ b/src/main/java/carpet/script/Context.java @@ -19,6 +19,7 @@ public class Context public static final int LOCALIZATION = 8; public static final int LVALUE = 9; public static final int MAPDEF = 10; + public static final int CALLARGS = 11; public Map variables = new HashMap<>(); diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index d0c36074..51443de7 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -773,12 +773,16 @@ public class Expression stack.set(stack.size() - 1, stack.peek() - 2 + 1); break; case FUNCTION: - ILazyFunction f = functions.get(token.surface);// don't validate global - userdef functions - int numParams = stack.pop(); - if (f != null && !f.numParamsVaries() && numParams != f.getNumParams()) - { - throw new ExpressionException(c, this, token, "Function " + token + " expected " + f.getNumParams() + " parameters, got " + numParams); - } + //ILazyFunction f = functions.get(token.surface);// don't validate global - userdef functions + //int numParams = stack.pop(); + //if (f != null && !f.numParamsVaries() && numParams != f.getNumParams()) + //{ + // throw new ExpressionException(c, this, token, "Function " + token + " expected " + f.getNumParams() + " parameters, got " + numParams); + //} + stack.pop(); + // due to unpacking, all functions can have variable number of arguments + // we will be checking that at runtime. + // TODO try analyze arguments and assess if its possible that they are static if (stack.size() <= 0) { throw new ExpressionException(c, this, token, "Too many function calls, maximum scope exceeded"); diff --git a/src/main/java/carpet/script/Fluff.java b/src/main/java/carpet/script/Fluff.java index 9662f265..f492c830 100644 --- a/src/main/java/carpet/script/Fluff.java +++ b/src/main/java/carpet/script/Fluff.java @@ -1,6 +1,9 @@ package carpet.script; import carpet.script.exception.ExpressionException; +import carpet.script.exception.InternalExpressionException; +import carpet.script.value.FunctionUnpackedArgumentsValue; +import carpet.script.value.ListValue; import carpet.script.value.Value; import java.util.ArrayList; @@ -85,6 +88,30 @@ public abstract class Fluff super(numParams); } + public static List unpackArgs(List lzargs, Context c) + { + List args = new ArrayList<>(); + for (LazyValue lv : lzargs) + { + Value arg = lv.evalValue(c, Context.CALLARGS); + if (arg instanceof FunctionUnpackedArgumentsValue) + { + args.addAll(((ListValue) arg).getItems()); + } + else + { + args.add(arg); + } + } + return args; + } + + public void checkArgs(int candidates) + { + if (!numParamsVaries() && getNumParams() !=candidates) + throw new InternalExpressionException("Function " + getName() + " expected " + getNumParams() + " parameters, got " + candidates); + } + @Override public LazyValue lazyEval(Context cc, Integer type, Expression e, Tokenizer.Token t, final List lazyParams) { @@ -100,10 +127,9 @@ public abstract class Fluff private List getParams(Context c) { if (params == null) { - params = new ArrayList<>(); - for (LazyValue lazyParam : lazyParams) { - params.add(lazyParam.evalValue(c)); // none type default by design - } + // very likely needs to be dynamic, so not static like here, or remember if it was. + params = unpackArgs(lazyParams, c); + checkArgs(params.size()); } return params; } diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java index 76d73c31..9859bcb3 100644 --- a/src/main/java/carpet/script/api/Auxiliary.java +++ b/src/main/java/carpet/script/api/Auxiliary.java @@ -834,12 +834,13 @@ public class Auxiliary { throw new InternalExpressionException("'schedule' should have at least 2 arguments, delay and call name"); long delay = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, true); + FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, false); + List args = functionArgument.unpackArgs(c); CarpetServer.scriptServer.events.scheduleCall( (CarpetContext) c, functionArgument.function, - FunctionValue.resolveArgs(functionArgument.args, c, t), + args, delay ); return (c_, t_) -> Value.TRUE; @@ -1043,7 +1044,7 @@ public class Auxiliary { } else { - success = host.getScriptServer().events.handleCustomEvent(event, host, callback.function, FunctionValue.resolveArgs(callback.args, c, t) )?Value.TRUE:Value.FALSE; + success = host.getScriptServer().events.handleCustomEvent(event, host, callback.function, callback.unpackArgs(c) )?Value.TRUE:Value.FALSE; } return (cc, tt) -> success; }); diff --git a/src/main/java/carpet/script/api/Entities.java b/src/main/java/carpet/script/api/Entities.java index 68a02904..ce2cd3b5 100644 --- a/src/main/java/carpet/script/api/Entities.java +++ b/src/main/java/carpet/script/api/Entities.java @@ -308,7 +308,7 @@ public class Entities { } else { - types.forEach(et -> events.addBuiltInEvent(CarpetEventServer.Event.getEntityLoadEventName(et), c.host, funArg.function, FunctionValue.resolveArgs(funArg.args, c, t))); + types.forEach(et -> events.addBuiltInEvent(CarpetEventServer.Event.getEntityLoadEventName(et), c.host, funArg.function, funArg.unpackArgs(c))); } Value ret = new NumericValue(types.size()); return (cc, tt) -> ret; @@ -326,7 +326,7 @@ public class Entities { FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 2, true, false); - ((EntityValue) v).setEvent((CarpetContext)c, what, funArg.function, FunctionValue.resolveArgs(funArg.args, c, t)); + ((EntityValue) v).setEvent((CarpetContext)c, what, funArg.function, funArg.unpackArgs(c)); return LazyValue.NULL; }); diff --git a/src/main/java/carpet/script/argument/FunctionArgument.java b/src/main/java/carpet/script/argument/FunctionArgument.java index 8c52c8d5..ecd09034 100644 --- a/src/main/java/carpet/script/argument/FunctionArgument.java +++ b/src/main/java/carpet/script/argument/FunctionArgument.java @@ -1,6 +1,7 @@ package carpet.script.argument; import carpet.script.Context; +import carpet.script.Fluff; import carpet.script.LazyValue; import carpet.script.ScriptHost; import carpet.script.bundled.Module; @@ -94,4 +95,14 @@ public class FunctionArgument extends Argument return new FunctionArgument<>(function, 0, args); } + + public void checkArgs() { + function.checkArgs(args.size()); + } + + public List unpackArgs(Context c) { + List unpackedArgs = Fluff.AbstractFunction.unpackArgs((List) args, c); + function.checkArgs(unpackedArgs.size()); + return unpackedArgs; + } } diff --git a/src/main/java/carpet/script/language/Functions.java b/src/main/java/carpet/script/language/Functions.java index 1588a3e0..5c03dd13 100644 --- a/src/main/java/carpet/script/language/Functions.java +++ b/src/main/java/carpet/script/language/Functions.java @@ -6,12 +6,14 @@ import carpet.script.LazyValue; import carpet.script.argument.FunctionArgument; import carpet.script.exception.InternalExpressionException; import carpet.script.exception.ReturnStatement; +import carpet.script.value.AbstractListValue; import carpet.script.value.FunctionSignatureValue; import carpet.script.value.FunctionValue; import carpet.script.value.FunctionAnnotationValue; import carpet.script.value.ListValue; import carpet.script.value.StringValue; import carpet.script.value.Value; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.List; @@ -90,9 +92,20 @@ public class Functions { expression.addLazyUnaryOperator("...", Operators.precedence.get("def->..."), false, (c, t, lv) -> { - if (t != Context.LOCALIZATION) - throw new InternalExpressionException("That functionality has not been implemented yet."); - return (cc, tt) -> new FunctionAnnotationValue(lv.evalValue(c), 1); + if (t == Context.LOCALIZATION) + return (cc, tt) -> new FunctionAnnotationValue(lv.evalValue(c), 1); + if (t == Context.CALLARGS) + { + Value params = lv.evalValue(c, Context.NONE); + if (params instanceof ListValue) + return (cc, tt) -> params; + if (!(params instanceof AbstractListValue)) + throw new InternalExpressionException("Unable to unpack a non-list"); + Value unpacked = ListValue.wrap(ImmutableList.copyOf(((AbstractListValue) params).iterator())); + return (cc, tt) -> unpacked; + } + throw new InternalExpressionException("That functionality has not been implemented yet."); + }); //assigns const procedure to the lhs, returning its previous value diff --git a/src/main/java/carpet/script/language/Threading.java b/src/main/java/carpet/script/language/Threading.java index f3149ae6..f7dd0389 100644 --- a/src/main/java/carpet/script/language/Threading.java +++ b/src/main/java/carpet/script/language/Threading.java @@ -19,7 +19,7 @@ public class Threading if (lv.size() == 0) throw new InternalExpressionException("'task' requires at least function to call as a parameter"); FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, false, true); - ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, FunctionValue.resolveArgs(functionArgument.args, c, t)); + ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, functionArgument.unpackArgs(c)); Thread.yield(); return (cc, tt) -> thread; }); @@ -30,7 +30,7 @@ public class Threading throw new InternalExpressionException("'task' requires at least function to call as a parameter"); Value queue = lv.get(0).evalValue(c); FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, true); - ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, FunctionValue.resolveArgs(functionArgument.args, c, t)); + ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.unpackArgs(c)); Thread.yield(); return (cc, tt) -> thread; }); diff --git a/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java b/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java new file mode 100644 index 00000000..8c053e7b --- /dev/null +++ b/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java @@ -0,0 +1,10 @@ +package carpet.script.value; + +import java.util.List; + +public class FunctionUnpackedArgumentsValue extends ListValue +{ + public FunctionUnpackedArgumentsValue(List list) { + super(list); + } +} diff --git a/src/main/java/carpet/script/value/FunctionValue.java b/src/main/java/carpet/script/value/FunctionValue.java index 61e97b18..a05e87b1 100644 --- a/src/main/java/carpet/script/value/FunctionValue.java +++ b/src/main/java/carpet/script/value/FunctionValue.java @@ -11,7 +11,6 @@ import carpet.script.exception.ContinueStatement; import carpet.script.exception.ExpressionException; import carpet.script.exception.InternalExpressionException; import carpet.script.exception.ReturnStatement; -import carpet.script.exception.ThrowStatement; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; @@ -173,15 +172,26 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction } } - @Override - public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lazyParams) + public void checkArgs(int candidates) { - assertArgsOk(lazyParams, (fixedArgs) ->{ + int actual = getArguments().size(); + + if (candidates < actual) + throw new InternalExpressionException("Function " + getPrettyString() + " requires at least " + actual + " arguments"); + if (candidates > actual && getVarArgs() == null) + throw new InternalExpressionException("Function " + getPrettyString() + " requires " + actual + " arguments"); + } + + @Override + public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lazyPrams) + { + List resolvedArgs = Fluff.AbstractFunction.unpackArgs(lazyPrams, c); + assertArgsOk(resolvedArgs, (fixedArgs) ->{ if (fixedArgs) // wrong number of args for fixed args { throw new ExpressionException(c, e, t, "Incorrect number of arguments for function "+name+ - ". Should be "+args.size()+", not "+lazyParams.size()+" like "+args + ". Should be "+args.size()+", not "+resolvedArgs.size()+" like "+args ); } else // too few args for varargs @@ -190,7 +200,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction argList.add("... "+varArgs); throw new ExpressionException(c, e, t, "Incorrect number of arguments for function "+name+ - ". Should be at least "+args.size()+", not "+lazyParams.size()+" like "+argList + ". Should be at least "+args.size()+", not "+resolvedArgs.size()+" like "+argList ); } }); @@ -200,15 +210,15 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction for (int i=0; i val); } if (varArgs != null) { List extraParams = new ArrayList<>(); - for (int i = args.size(), mx = lazyParams.size(); i < mx; i++) + for (int i = args.size(), mx = resolvedArgs.size(); i < mx; i++) { - extraParams.add(lazyParams.get(i).evalValue(c).reboundedTo(null)); // copy by value I guess + extraParams.add(resolvedArgs.get(i).reboundedTo(null)); // copy by value I guess } Value rest = ListValue.wrap(extraParams).bindTo(varArgs); // didn't we just copied that? newFrame.setVariable(varArgs, (cc, tt) -> rest); diff --git a/src/main/java/carpet/script/value/ListValue.java b/src/main/java/carpet/script/value/ListValue.java index de316668..7da9ee92 100644 --- a/src/main/java/carpet/script/value/ListValue.java +++ b/src/main/java/carpet/script/value/ListValue.java @@ -70,7 +70,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf items.addAll(list); } - private ListValue(List list) + protected ListValue(List list) { items = list; } From ba2429e29de1f67684f67e8abc733b7b0a567e24 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 21 Apr 2021 23:16:24 +0000 Subject: [PATCH 2/8] Merge docs for 'Carpet Mod 1.4.33 for Minecraft 1.16.5 and Minecraft 21w16a' --- docs/scarpet/Full.md | 56 ++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 1b1d109e..e4084313 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -1890,6 +1890,30 @@ conflicts and ambiguities between different paths of execution. While ambiguous and they tend to execute correctly, the suggestion support works really poorly in these situations and scarpet will warn and prevent such apps from loading with an error message. If `allow_command_conflicts` is specified and `true`, then scarpet will load all provided commands regardless. +* `'requires'` - defines either a map of mod dependencies in Fabric's mod.json style, or a function to be executed. If it's a map, it will only + allow the app to load if all of the mods specified in the map meet the version criteria. If it's a function, it will prevent the app from + loading if the function does not execute to `false`, displaying whatever is returned to the user. + + Available prefixes for the version comparison are `>=`, `<=`, `>`, `<`, `~`, `^` and `=` (default if none specified), based in the spec + at [NPM docs about SemVer ranges](https://docs.npmjs.com/cli/v6/using-npm/semver#ranges) + ``` + __config() -> { + 'requires' -> { + 'carpet' -> '>=1.4.33', // Will require Carpet with a version >= 1.4.32 + 'minecraft' -> '>=1.16', // Will require Minecraft with a version >= 1.16 + 'chat-up' -> '*' // Will require any version of the chat-up mod + } + } + ``` + ``` + __config() -> { + 'requires' -> _() -> ( + d = convert_date(unix_time()); + if(d:6 == 5 && d:2 == 13, + 'Its Friday, 13th' // Will throw this if Friday 13th, will load else since `if` function returns `null` by default + ) + } + ``` * `'command_permission'` - indicates a custom permission to run the command. It can either be a number indicating permission level (from 1 to 4) or a string value, one of: `'all'` (default), `'ops'` (default opped player with permission level of 2), `'server'` - command accessible only through the server console and commandblocks, but not in chat, `'players'` - opposite @@ -2120,7 +2144,8 @@ if a player is in the other dimension, calls to entities and blocks around that Moreover, running commandblocks in the spawn chunks would mean that commands will always refer to the overworld blocks and entities. In case you would want to run commands across all dimensions, just run three of them, using `/execute in overworld/the_nether/the_end run script run ...` and query players using `player('*')`, -which only returns players in current dimension, or use `in_dimension(expr)` function.# Blocks / World API +which only returns players in current dimension, or use `in_dimension(expr)` function. +# Blocks / World API ## Specifying blocks @@ -3058,20 +3083,8 @@ living entities based on their spawn group. Negative descriptor resolves to all category. * All entity tags including those provided with datapacks. Built-in entity tags include: `skeletons`, `raiders`, `beehive_inhabitors` (bee, duh), `arrows` and `impact_projectiles`. -* Any of the following standard entity types (equivalent to selection from `/summon` vanilla command: -`area_effect_cloud`, `armor_stand`, `arrow`, `bat`, `bee`, `blaze`, `boat`, `cat`, `cave_spider`, `chest_minecart`, -`chicken`, `cod`, `command_block_minecart`, `cow`, `creeper`, `dolphin`, `donkey`, `dragon_fireball`, `drowned`, -`egg`, `elder_guardian`, `end_crystal`, `ender_dragon`, `ender_pearl`, `enderman`, `endermite`, `evoker`, -`evoker_fangs`, `experience_bottle`, `experience_orb`, `eye_of_ender`, `falling_block`, `fireball`, `firework_rocket`, -`fishing_bobber`, `fox`, `furnace_minecart`, `ghast`, `giant`, `guardian`, `hoglin`, `hopper_minecart`, `horse`, -`husk`, `illusioner`, `iron_golem`, `item`, `item_frame`, `leash_knot`, `lightning_bolt`, `llama`, `llama_spit`, -`magma_cube`, `minecart`, `mooshroom`, `mule`, `ocelot`, `painting`, `panda`, `parrot`, `phantom`, `pig`, `piglin`, -`piglin_brute`, `pillager`, `player`, `polar_bear`, `potion`, `pufferfish`, `rabbit`, `ravager`, `salmon`, `sheep`, -`shulker`, `shulker_bullet`, `silverfish`, `skeleton`, `skeleton_horse`, `slime`, `small_fireball`, `snow_golem`, -`snowball`, `spawner_minecart`, `spectral_arrow`, `spider`, `squid`, `stray`, `strider`, `tnt`, `tnt_minecart`, -`trader_llama`, `trident`, `tropical_fish`, `turtle`, `vex`, `villager`, `vindicator`, `wandering_trader`, `witch`, -`wither`, `wither_skeleton`, `wither_skull`, `wolf`, `zoglin`, `zombie`, `zombie_horse`, `zombie_villager`, -`zombified_piglin` +* Any of the standard entity types, equivalent to selection from `/summon` vanilla command, which is one of the options returned +by `entity_types()`, except for `'fishing_bobber'` and `'player'`. All categories can be preceded with `'!'` which will fetch all entities (unless otherwise noted) that are valid (health > 0) but not belonging to that group. @@ -4910,7 +4923,7 @@ Example usages: // not a problem in apps -### `display_title(players, type, title?, fadeInTicks?, stayTicks?, fadeOutTicks),` +### `display_title(players, type, text?, fadeInTicks?, stayTicks?, fadeOutTicks),` Sends the player (or players if `players` is a list) a title of a specific type, with optionally some times. * `players` is either an online player or a list of players. When sending a single player, it will throw if the player is invalid or offline. @@ -4922,9 +4935,17 @@ Sends the player (or players if `players` is a list) a title of a specific type, Executing with those will set the times to the specified ones. Note that `actionbar` type doesn't support changing times (vanilla bug, see [MC-106167](https://bugs.mojang.com/browse/MC-106167)). +### `display_title(players, 'player_list_header', text)` +### `display_title(players, 'player_list_footer', text)` + +Changes the header or footer of the player list for the specified targets. +If `text` is `null` or an empty string it will remove the header or footer for the specified targets. +In case the player has Carpet loggers running, the footer specified by Scarpet will appear above the loggers. + ### `logger(msg), logger(type, msg)` -Prints the message to system logs, and not to chat. By default prints an info, unless you specify otherwise in the `type` parameter. +Prints the message to system logs, and not to chat. +By default prints an info, unless you specify otherwise in the `type` parameter. Available output types: @@ -5321,6 +5342,7 @@ Available options in the scarpet app space: * `server_banned_players` - list of banned player names * `server_banned_ips` - list of banned IP addresses * `server_dev_environment` - boolean indicating whether this server is in a development environment. + * `server_mods` - map with all loaded mods mapped to their versions as strings System related properties * `java_max_memory` - maximum allowed memory accessible by JVM From 74bd0bb81e40d1a2f7e588bfb56143962542a4b1 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 22 Apr 2021 20:37:48 -0300 Subject: [PATCH 3/8] dont be lazy refactor --- .../java/carpet/script/CarpetScriptHost.java | 22 +- src/main/java/carpet/script/Context.java | 1 - src/main/java/carpet/script/Expression.java | 84 +++ src/main/java/carpet/script/Fluff.java | 60 +- .../java/carpet/script/api/Auxiliary.java | 435 ++++++--------- .../carpet/script/api/BlockIterators.java | 49 +- src/main/java/carpet/script/api/Entities.java | 141 ++--- .../java/carpet/script/api/Inventories.java | 202 +++---- .../java/carpet/script/api/Monitoring.java | 34 +- .../java/carpet/script/api/Scoreboards.java | 390 +++++-------- .../java/carpet/script/api/Threading.java | 8 +- .../java/carpet/script/api/WorldAccess.java | 515 ++++++++---------- .../carpet/script/argument/BlockArgument.java | 13 +- .../carpet/script/argument/FileArgument.java | 6 +- .../script/argument/FunctionArgument.java | 31 +- .../script/argument/Vector3Argument.java | 65 +-- .../script/command/CommandArgument.java | 2 +- .../carpet/script/language/Arithmetic.java | 10 +- .../carpet/script/language/ControlFlow.java | 12 +- .../script/language/DataStructures.java | 73 +-- .../carpet/script/language/Functions.java | 53 +- .../java/carpet/script/language/Loops.java | 1 + .../carpet/script/language/Operators.java | 13 +- src/main/java/carpet/script/language/Sys.java | 134 ++--- .../carpet/script/language/Threading.java | 31 +- .../java/carpet/script/value/EntityValue.java | 4 +- .../script/value/FunctionAnnotationValue.java | 10 +- .../carpet/script/value/FunctionValue.java | 39 +- .../carpet/script/value/LContainerValue.java | 1 + .../script/value/NBTSerializableValue.java | 20 +- .../java/carpet/script/value/ThreadValue.java | 2 +- 31 files changed, 1078 insertions(+), 1383 deletions(-) diff --git a/src/main/java/carpet/script/CarpetScriptHost.java b/src/main/java/carpet/script/CarpetScriptHost.java index c265ac11..0d74b4fd 100644 --- a/src/main/java/carpet/script/CarpetScriptHost.java +++ b/src/main/java/carpet/script/CarpetScriptHost.java @@ -134,7 +134,7 @@ public class CarpetScriptHost extends ScriptHost return host; } - private static int execute(CommandContext ctx, String hostName, FunctionArgument funcSpec, List paramNames) throws CommandSyntaxException + private static int execute(CommandContext ctx, String hostName, FunctionArgument funcSpec, List paramNames) throws CommandSyntaxException { CarpetProfiler.ProfilerToken currentSection = CarpetProfiler.start_section(null, "Scarpet command", CarpetProfiler.TYPE.GENERAL); CarpetScriptHost cHost = CarpetServer.scriptServer.modules.get(hostName).retrieveOwnForExecution(ctx.getSource()); @@ -158,7 +158,7 @@ public class CarpetScriptHost extends ScriptHost public LiteralArgumentBuilder addPathToCommand( LiteralArgumentBuilder command, List path, - FunctionArgument functionSpec + FunctionArgument functionSpec ) throws CommandSyntaxException { String hostName = main.getName(); @@ -180,14 +180,14 @@ public class CarpetScriptHost extends ScriptHost } public LiteralArgumentBuilder getNewCommandTree( - List,FunctionArgument>> entries, Function useValidator + List,FunctionArgument>> entries, Function useValidator ) throws CommandSyntaxException { String hostName = main.getName(); Function configValidator = getCommandConfigPermissions(); LiteralArgumentBuilder command = literal(hostName). requires((player) -> CarpetServer.scriptServer.modules.containsKey(hostName) && useValidator.apply(player) && configValidator.apply(player)); - for (Pair,FunctionArgument> commandData : entries) + for (Pair,FunctionArgument> commandData : entries) { command = this.addPathToCommand(command, commandData.getKey(), commandData.getValue()); } @@ -547,12 +547,12 @@ public class CarpetScriptHost extends ScriptHost if (commands == null) return null; if (!(commands instanceof MapValue)) throw CommandArgument.error("'commands' element in config should be a map"); - List,FunctionArgument>> commandEntries = new ArrayList<>(); + List,FunctionArgument>> commandEntries = new ArrayList<>(); for (Map.Entry commandsData : ((MapValue)commands).getMap().entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toList())) { List elements = CommandToken.parseSpec(commandsData.getKey().getString(), this); - FunctionArgument funSpec = FunctionArgument.fromCommandSpec(this, commandsData.getValue()); + FunctionArgument funSpec = FunctionArgument.fromCommandSpec(this, commandsData.getValue()); commandEntries.add(Pair.of(elements, funSpec)); } commandEntries.sort(new ListComparator<>()); @@ -806,20 +806,18 @@ public class CarpetScriptHost extends ScriptHost } } - public Value call(ServerCommandSource source, FunctionValue function, List suppliedArgs) + public Value call(ServerCommandSource source, FunctionValue function, List argv) { if (CarpetServer.scriptServer.stopAll) throw new CarpetExpressionException("SCARPET PAUSED", null); - List argv = FunctionValue.lazify(suppliedArgs); - List args = function.getArguments(); if (argv.size() != args.size()) { String error = "Fail: stored function "+function.getPrettyString()+" takes "+args.size()+" arguments, not "+argv.size()+ ":\n"; for (int i = 0; i < max(argv.size(), args.size()); i++) { - error += (i "+(i "+(i function.lazyEval(context, Context.VOID, function.getExpression(), function.getToken(), argv), + () -> function.execute(context, Context.VOID, function.getExpression(), function.getToken(), argv), context, Context.VOID ); @@ -857,7 +855,7 @@ public class CarpetScriptHost extends ScriptHost // TODO: this is just for now - invoke would be able to invoke other hosts scripts Context context = new CarpetContext(this, source, pos); return fun.getExpression().evalValue( - () -> fun.lazyEval(context, Context.VOID, fun.getExpression(), fun.getToken(), FunctionValue.lazify(argv)), + () -> fun.execute(context, Context.VOID, fun.getExpression(), fun.getToken(), argv), context, Context.VOID); } diff --git a/src/main/java/carpet/script/Context.java b/src/main/java/carpet/script/Context.java index ad87fa17..fb9b583e 100644 --- a/src/main/java/carpet/script/Context.java +++ b/src/main/java/carpet/script/Context.java @@ -19,7 +19,6 @@ public class Context public static final int LOCALIZATION = 8; public static final int LVALUE = 9; public static final int MAPDEF = 10; - public static final int CALLARGS = 11; public Map variables = new HashMap<>(); diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 51443de7..28b6a2fa 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -205,6 +205,27 @@ public class Expression }); } + public void addFunctionWithDelegation(String name, int numpar, + QuinnFunction, Value> fun) + { + functions.put(name, new AbstractLazyFunction(numpar) + { + @Override + public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lv) + { + try + { + Value res = fun.apply(c, type, e, t, unpackArgs(lv, c, Context.NONE)); + return (cc, tt) -> res; + } + catch (RuntimeException exc) + { + throw handleCodeException(c, exc, e, t); + } + } + }); + } + public void addLazyBinaryOperator(String surface, int precedence, boolean leftAssoc, QuadFunction lazyfun) { @@ -226,6 +247,28 @@ public class Expression }); } + public void addBinaryContextOperator(String surface, int precedence, boolean leftAssoc, + QuadFunction fun) + { + operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc) + { + @Override + public LazyValue lazyEval(Context c, Integer t, Expression e, Tokenizer.Token token, LazyValue v1, LazyValue v2) + { + try + { + Value.assertNotNull(v1, v2); // does anybody needs those + Value ret = fun.apply(c, t, v1.evalValue(c, Context.NONE), v2.evalValue(c, Context.NONE)); + return (cc, tt) -> ret; + } + catch (RuntimeException exc) + { + throw handleCodeException(c, exc, e, token); + } + } + }); + } + public static RuntimeException handleCodeException(Context c, RuntimeException exc, Expression e, Tokenizer.Token token) { if (exc instanceof ExitStatement) @@ -343,6 +386,47 @@ public class Expression } }); } + + public void addContextFunction(String name, int num_params, TriFunction, Value> fun) + { + functions.put(name, new AbstractLazyFunction(num_params) + { + @Override + public LazyValue lazyEval(Context c, Integer i, Expression e, Tokenizer.Token t, List lazyParams) + { + try + { + Value ret = fun.apply(c, i, unpackArgs(lazyParams, c, Context.NONE)); + return (cc, tt) -> ret; + } + catch (RuntimeException exc) + { + throw handleCodeException(c, exc, e, t); + } + } + }); + } + + public void addTypedContextFunction(String name, int num_params, int reqType, TriFunction, Value> fun) + { + functions.put(name, new AbstractLazyFunction(num_params) + { + @Override + public LazyValue lazyEval(Context c, Integer i, Expression e, Tokenizer.Token t, List lazyParams) + { + try + { + Value ret = fun.apply(c, i, unpackArgs(lazyParams, c, reqType)); + return (cc, tt) -> ret; + } + catch (RuntimeException exc) + { + throw handleCodeException(c, exc, e, t); + } + } + }); + } + public FunctionValue createUserDefinedFunction(Context context, String name, Expression expr, Tokenizer.Token token, List arguments, String varArgs, List outers, LazyValue code) { if (functions.containsKey(name)) diff --git a/src/main/java/carpet/script/Fluff.java b/src/main/java/carpet/script/Fluff.java index f492c830..dc41d936 100644 --- a/src/main/java/carpet/script/Fluff.java +++ b/src/main/java/carpet/script/Fluff.java @@ -1,5 +1,6 @@ package carpet.script; +import carpet.CarpetSettings; import carpet.script.exception.ExpressionException; import carpet.script.exception.InternalExpressionException; import carpet.script.value.FunctionUnpackedArgumentsValue; @@ -80,6 +81,36 @@ public abstract class Fluff public boolean numParamsVaries() { return numParams < 0; } + + public static List unpackLazy(List lzargs, Context c, int contextType) + { + List args = new ArrayList<>(); + for (LazyValue lv : lzargs) + { + Value arg = lv.evalValue(c, contextType); + if (arg instanceof FunctionUnpackedArgumentsValue) + args.addAll(((ListValue) arg).getItems()); + else + args.add(arg); + } + return args; + } + + public List unpackArgs(List lzargs, Context c, int contextType) + { + List args = new ArrayList<>(); + for (LazyValue lv : lzargs) + { + Value arg = lv.evalValue(c, contextType); + if (arg instanceof FunctionUnpackedArgumentsValue) + args.addAll(((ListValue) arg).getItems()); + else + args.add(arg); + } + if (!numParamsVaries() && getNumParams() != args.size()) + throw new InternalExpressionException("Function " + getName() + " expected " + getNumParams() + " parameters, got " + args.size()); + return args; + } } public abstract static class AbstractFunction extends AbstractLazyFunction implements IFunction @@ -88,29 +119,7 @@ public abstract class Fluff super(numParams); } - public static List unpackArgs(List lzargs, Context c) - { - List args = new ArrayList<>(); - for (LazyValue lv : lzargs) - { - Value arg = lv.evalValue(c, Context.CALLARGS); - if (arg instanceof FunctionUnpackedArgumentsValue) - { - args.addAll(((ListValue) arg).getItems()); - } - else - { - args.add(arg); - } - } - return args; - } - public void checkArgs(int candidates) - { - if (!numParamsVaries() && getNumParams() !=candidates) - throw new InternalExpressionException("Function " + getName() + " expected " + getNumParams() + " parameters, got " + candidates); - } @Override public LazyValue lazyEval(Context cc, Integer type, Expression e, Tokenizer.Token t, final List lazyParams) @@ -128,8 +137,11 @@ public abstract class Fluff private List getParams(Context c) { if (params == null) { // very likely needs to be dynamic, so not static like here, or remember if it was. - params = unpackArgs(lazyParams, c); - checkArgs(params.size()); + params = unpackArgs(lazyParams, c, Context.NONE); + } + else + { + CarpetSettings.LOG.error("How did we get here 1"); } return params; } diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java index 9859bcb3..0db652ca 100644 --- a/src/main/java/carpet/script/api/Auxiliary.java +++ b/src/main/java/carpet/script/api/Auxiliary.java @@ -15,7 +15,6 @@ import carpet.script.CarpetScriptHost; import carpet.script.CarpetScriptServer; import carpet.script.Context; import carpet.script.Expression; -import carpet.script.LazyValue; import carpet.script.argument.BlockArgument; import carpet.script.argument.FunctionArgument; import carpet.script.argument.Vector3Argument; @@ -28,9 +27,9 @@ import carpet.script.utils.InputValidator; import carpet.script.utils.ScarpetJsonDeserializer; import carpet.script.utils.ShapeDispatcher; import carpet.script.utils.WorldTools; +import carpet.script.value.BooleanValue; import carpet.script.value.EntityValue; import carpet.script.value.FormattedTextValue; -import carpet.script.value.FunctionValue; import carpet.script.value.ListValue; import carpet.script.value.MapValue; import carpet.script.value.NBTSerializableValue; @@ -147,16 +146,15 @@ public class Auxiliary { public static void apply(Expression expression) { - expression.addLazyFunction("sound", -1, (c, t, lv) -> { + expression.addContextFunction("sound", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; if (lv.size() == 0) { - Value ret = ListValue.wrap(Registry.SOUND_EVENT.getIds().stream().map(ValueConversions::of)); - return (_c, _t) -> ret; + return ListValue.wrap(Registry.SOUND_EVENT.getIds().stream().map(ValueConversions::of)); } - String rawString = lv.get(0).evalValue(c).getString(); + String rawString = lv.get(0).getString(); Identifier soundName = new Identifier(rawString); - Vector3Argument locator = Vector3Argument.findIn(cc, lv, 1); + Vector3Argument locator = Vector3Argument.findIn(lv, 1); if (Registry.SOUND_EVENT.get(soundName) == null) throw new ThrowStatement(rawString, Throwables.UNKNOWN_SOUND); float volume = 1.0F; @@ -164,13 +162,13 @@ public class Auxiliary { SoundCategory mixer = SoundCategory.MASTER; if (lv.size() > 0+locator.offset) { - volume = (float) NumericValue.asNumber(lv.get(0+locator.offset).evalValue(c)).getDouble(); + volume = (float) NumericValue.asNumber(lv.get(0+locator.offset)).getDouble(); if (lv.size() > 1+locator.offset) { - pitch = (float) NumericValue.asNumber(lv.get(1+locator.offset).evalValue(c)).getDouble(); + pitch = (float) NumericValue.asNumber(lv.get(1+locator.offset)).getDouble(); if (lv.size() > 2+locator.offset) { - String mixerName = lv.get(2+locator.offset).evalValue(c).getString(); + String mixerName = lv.get(2+locator.offset).getString(); mixer = mixerMap.get(mixerName.toLowerCase(Locale.ROOT)); if (mixer == null) throw new InternalExpressionException(mixerName +" is not a valid mixer name"); } @@ -184,39 +182,33 @@ public class Auxiliary { count++; player.networkHandler.sendPacket(new PlaySoundIdS2CPacket(soundName, mixer, vec, volume, pitch)); } - int totalPlayed = count; - return (_c, _t) -> new NumericValue(totalPlayed); + return new NumericValue(count); }); - expression.addLazyFunction("particle", -1, (c, t, lv) -> + expression.addContextFunction("particle", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - if (lv.size() == 0) - { - Value ret = ListValue.wrap(Registry.PARTICLE_TYPE.getIds().stream().map(ValueConversions::of)); - return (_c, _t) -> ret; - } - + if (lv.size() == 0) return ListValue.wrap(Registry.PARTICLE_TYPE.getIds().stream().map(ValueConversions::of)); MinecraftServer ms = cc.s.getMinecraftServer(); ServerWorld world = cc.s.getWorld(); - Vector3Argument locator = Vector3Argument.findIn(cc, lv, 1); - String particleName = lv.get(0).evalValue(c).getString(); + Vector3Argument locator = Vector3Argument.findIn(lv, 1); + String particleName = lv.get(0).getString(); int count = 10; double speed = 0; float spread = 0.5f; ServerPlayerEntity player = null; if (lv.size() > locator.offset) { - count = (int) NumericValue.asNumber(lv.get(locator.offset).evalValue(c)).getLong(); + count = (int) NumericValue.asNumber(lv.get(locator.offset)).getLong(); if (lv.size() > 1+locator.offset) { - spread = (float) NumericValue.asNumber(lv.get(1+locator.offset).evalValue(c)).getDouble(); + spread = (float) NumericValue.asNumber(lv.get(1+locator.offset)).getDouble(); if (lv.size() > 2+locator.offset) { - speed = NumericValue.asNumber(lv.get(2 + locator.offset).evalValue(c)).getDouble(); + speed = NumericValue.asNumber(lv.get(2 + locator.offset)).getDouble(); if (lv.size() > 3 + locator.offset) // should accept entity as well as long as it is player { - player = ms.getPlayerManager().getPlayer(lv.get(3 + locator.offset).evalValue(c).getString()); + player = ms.getPlayerManager().getPlayer(lv.get(3 + locator.offset).getString()); } } } @@ -238,29 +230,29 @@ public class Auxiliary { spread, spread, spread, speed); } - return (c_, t_) -> Value.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("particle_line", -1, (c, t, lv) -> + expression.addContextFunction("particle_line", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); - String particleName = lv.get(0).evalValue(c).getString(); + String particleName = lv.get(0).getString(); ParticleEffect particle = ShapeDispatcher.getParticleData(particleName); - Vector3Argument pos1 = Vector3Argument.findIn(cc, lv, 1); - Vector3Argument pos2 = Vector3Argument.findIn(cc, lv, pos1.offset); + Vector3Argument pos1 = Vector3Argument.findIn(lv, 1); + Vector3Argument pos2 = Vector3Argument.findIn(lv, pos1.offset); double density = 1.0; ServerPlayerEntity player = null; if (lv.size() > pos2.offset+0 ) { - density = NumericValue.asNumber(lv.get(pos2.offset+0).evalValue(c)).getDouble(); + density = NumericValue.asNumber(lv.get(pos2.offset+0)).getDouble(); if (density <= 0) { throw new InternalExpressionException("Particle density should be positive"); } if (lv.size() > pos2.offset+1) { - Value playerValue = lv.get(pos2.offset+1).evalValue(c); + Value playerValue = lv.get(pos2.offset+1); if (playerValue instanceof EntityValue) { Entity e = ((EntityValue) playerValue).getEntity(); @@ -274,34 +266,33 @@ public class Auxiliary { } } - Value retval = new NumericValue(ShapeDispatcher.drawParticleLine( + return new NumericValue(ShapeDispatcher.drawParticleLine( (player == null)?world.getPlayers(): Collections.singletonList(player), - particle, pos1.vec, pos2.vec, density)); - - return (c_, t_) -> retval; + particle, pos1.vec, pos2.vec, density + )); }); - expression.addLazyFunction("particle_box", -1, (c, t, lv) -> + expression.addContextFunction("particle_box", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); - String particleName = lv.get(0).evalValue(c).getString(); + String particleName = lv.get(0).getString(); ParticleEffect particle = ShapeDispatcher.getParticleData(particleName); - Vector3Argument pos1 = Vector3Argument.findIn(cc, lv, 1); - Vector3Argument pos2 = Vector3Argument.findIn(cc, lv, pos1.offset); + Vector3Argument pos1 = Vector3Argument.findIn(lv, 1); + Vector3Argument pos2 = Vector3Argument.findIn(lv, pos1.offset); double density = 1.0; ServerPlayerEntity player = null; if (lv.size() > pos2.offset+0 ) { - density = NumericValue.asNumber(lv.get(pos2.offset+0).evalValue(c)).getDouble(); + density = NumericValue.asNumber(lv.get(pos2.offset+0)).getDouble(); if (density <= 0) { throw new InternalExpressionException("Particle density should be positive"); } if (lv.size() > pos2.offset+1) { - Value playerValue = lv.get(pos2.offset+1).evalValue(c); + Value playerValue = lv.get(pos2.offset+1); if (playerValue instanceof EntityValue) { Entity e = ((EntityValue) playerValue).getEntity(); @@ -322,13 +313,13 @@ public class Auxiliary { player==null?world.getPlayers():Collections.singletonList(player), particle, density, from, to ); - return (c_, t_) -> new NumericValue(particleCount); + return new NumericValue(particleCount); }); // deprecated expression.alias("particle_rect", "particle_box"); - expression.addLazyFunction("draw_shape", -1, (c, t, lv) -> + expression.addContextFunction("draw_shape", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); @@ -337,7 +328,7 @@ public class Auxiliary { List>> shapes = new ArrayList<>(); if (lv.size() == 1) // bulk { - Value specLoad = lv.get(0).evalValue(c); + Value specLoad = lv.get(0); if (!(specLoad instanceof ListValue)) throw new InternalExpressionException("In bulk mode - shapes need to be provided as a list of shape specs"); for (Value list : ((ListValue) specLoad).getItems()) { @@ -347,19 +338,17 @@ public class Auxiliary { } else { - List params = new ArrayList<>(); - for (LazyValue v : lv) params.add(v.evalValue(c)); - shapes.add(ShapeDispatcher.fromFunctionArgs(server, world, params, player)); + shapes.add(ShapeDispatcher.fromFunctionArgs(server, world, lv, player)); } ShapeDispatcher.sendShape( (player[0]==null)?cc.s.getWorld().getPlayers():Collections.singletonList(player[0]), shapes ); - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("create_marker", -1, (c, t, lv) ->{ + expression.addContextFunction("create_marker", -1, (c, t, lv) ->{ CarpetContext cc = (CarpetContext)c; BlockState targetBlock = null; Vector3Argument pointLocator; @@ -367,16 +356,16 @@ public class Auxiliary { String name; try { - Value nameValue = lv.get(0).evalValue(c); + Value nameValue = lv.get(0); name = nameValue instanceof NullValue ? "" : nameValue.getString(); - pointLocator = Vector3Argument.findIn(cc, lv, 1, true, false); + pointLocator = Vector3Argument.findIn(lv, 1, true, false); if (lv.size()>pointLocator.offset) { BlockArgument blockLocator = BlockArgument.findIn(cc, lv, pointLocator.offset, true, true, false); if (blockLocator.block != null) targetBlock = blockLocator.block.getBlockState(); if (lv.size() > blockLocator.offset) { - interactable = lv.get(blockLocator.offset).evalValue(c, Context.BOOLEAN).getBoolean(); + interactable = lv.get(blockLocator.offset).getBoolean(); } } } @@ -429,11 +418,10 @@ public class Auxiliary { armorstand.setInvulnerable(true); armorstand.getDataTracker().set(ArmorStandEntity.ARMOR_STAND_FLAGS, (byte)(interactable?8 : 16|8)); cc.s.getWorld().spawnEntity(armorstand); - EntityValue result = new EntityValue(armorstand); - return (_c, _t) -> result; + return new EntityValue(armorstand); }); - expression.addLazyFunction("remove_all_markers", 0, (c, t, lv) -> { + expression.addContextFunction("remove_all_markers", 0, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; int total = 0; String markerName = MARKER_STRING+"_"+((cc.host.getName()==null)?"":cc.host.getName()); @@ -442,34 +430,18 @@ public class Auxiliary { total ++; e.remove(); } - int finalTotal = total; - return (_cc, _tt) -> new NumericValue(finalTotal); + return new NumericValue(total); }); - expression.addLazyFunction("nbt", 1, (c, t, lv) -> { - Value ret = NBTSerializableValue.fromValue(lv.get(0).evalValue(c)); - return (cc, tt) -> ret; - }); + expression.addUnaryFunction("nbt", NBTSerializableValue::fromValue); - expression.addLazyFunction("escape_nbt", 1, (c, t, lv) -> { - Value v = lv.get(0).evalValue(c); - String string = v.getString(); - Value ret = new StringValue(StringTag.escape(string)); - return (cc, tt) -> ret; - }); + expression.addUnaryFunction("escape_nbt", v -> new StringValue(StringTag.escape(v.getString()))); - expression.addLazyFunction("parse_nbt", 1, (c, t, lv) -> { - Value v = lv.get(0).evalValue(c); - if (v instanceof NBTSerializableValue) - { - Value parsed = ((NBTSerializableValue) v).toValue(); - return (cc, tt) -> parsed; - } + expression.addUnaryFunction("parse_nbt", v -> { + if (v instanceof NBTSerializableValue) return ((NBTSerializableValue) v).toValue(); NBTSerializableValue ret = NBTSerializableValue.parseString(v.getString(), false); - if (ret == null) - return LazyValue.NULL; - Value parsed = ret.toValue(); - return (cc, tt) -> parsed; + if (ret == null) return Value.NULL; + return ret.toValue(); }); expression.addFunction("tag_matches", (lv) -> { @@ -482,11 +454,11 @@ public class Auxiliary { return new NumericValue(NbtHelper.matches(match, source, numParam == 2 || lv.get(2).getBoolean())); }); - expression.addLazyFunction("encode_nbt", -1, (c, t, lv) -> { + expression.addFunction("encode_nbt", lv -> { int argSize = lv.size(); if (argSize==0 || argSize > 2) throw new InternalExpressionException("'encode_nbt' requires 1 or 2 parameters"); - Value v = lv.get(0).evalValue(c); - boolean force = (argSize > 1) && lv.get(1).evalValue(c).getBoolean(); + Value v = lv.get(0); + boolean force = (argSize > 1) && lv.get(1).getBoolean(); Tag tag; try { @@ -496,17 +468,16 @@ public class Auxiliary { { throw new InternalExpressionException("cannot reliably encode to a tag the value of '"+ignored.val.getPrettyString()+"'"); } - Value tagValue = new NBTSerializableValue(tag); - return (cc, tt) -> tagValue; + return new NBTSerializableValue(tag); }); //"overridden" native call that prints to stderr - expression.addLazyFunction("print", -1, (c, t, lv) -> + expression.addContextFunction("print", -1, (c, t, lv) -> { if (lv.size() == 0 || lv.size() > 2) throw new InternalExpressionException("'print' takes one or two arguments"); ServerCommandSource s = ((CarpetContext)c).s; MinecraftServer server = s.getMinecraftServer(); - Value res = lv.get(0).evalValue(c); + Value res = lv.get(0); List targets = null; if (lv.size() == 2) { @@ -518,7 +489,7 @@ public class Auxiliary { playerTargets.add(player); }); targets = playerTargets; - res = lv.get(1).evalValue(c); + res = lv.get(1); } Text message = FormattedTextValue.getTextByValue(res); if (targets == null) @@ -529,12 +500,12 @@ public class Auxiliary { { targets.forEach(p -> p.getCommandSource().sendFeedback(message, false)); } - Value finalRes = res; - return (_c, _t) -> finalRes; // pass through for variables + return res; // pass through for variables }); - expression.addLazyFunction("display_title", -1, (c, t, lv) -> { + + expression.addContextFunction("display_title", -1, (c, t, lv) -> { if (lv.size() < 2) throw new InternalExpressionException("'display_title' needs at least a target, type and message, and optionally times"); - Value pVal = lv.get(0).evalValue(c); + Value pVal = lv.get(0); if (!(pVal instanceof ListValue)) pVal = ListValue.of(pVal); MinecraftServer server = ((CarpetContext)c).s.getMinecraftServer(); Stream targets = ((ListValue) pVal).getItems().stream().map(v -> @@ -544,7 +515,7 @@ public class Auxiliary { return player; }); TitleS2CPacket.Action action; - String actionString = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT); + String actionString = lv.get(1).getString().toLowerCase(Locale.ROOT); switch (actionString) { case "title": @@ -572,7 +543,7 @@ public class Auxiliary { boolean soundsTrue = false; if (lv.size() > 2) { - pVal = lv.get(2).evalValue(c); + pVal = lv.get(2); title = FormattedTextValue.getTextByValue(pVal); soundsTrue = pVal.getBoolean(); } @@ -598,15 +569,15 @@ public class Auxiliary { total.getAndIncrement(); }); HUDController.update_hud(((CarpetContext)c).s.getMinecraftServer(), targetList); - Value ret = NumericValue.of(total.get()); - return (cc, tt) -> ret; + return NumericValue.of(total.get()); } TitleS2CPacket timesPacket; if (lv.size() > 3) { - int in = NumericValue.asNumber(lv.get(3).evalValue(c),"fade in for display_title" ).getInt(); - int stay = NumericValue.asNumber(lv.get(4).evalValue(c),"stay for display_title" ).getInt(); - int out = NumericValue.asNumber(lv.get(5).evalValue(c),"fade out for display_title" ).getInt(); + if (lv.size() != 6) throw new InternalExpressionException("'display_title' needs all fade-in, stay and fade-out times"); + int in = NumericValue.asNumber(lv.get(3),"fade in for display_title" ).getInt(); + int stay = NumericValue.asNumber(lv.get(4),"stay for display_title" ).getInt(); + int out = NumericValue.asNumber(lv.get(5),"fade out for display_title" ).getInt(); timesPacket = new TitleS2CPacket(Action.TIMES, null, in, stay, out); } else timesPacket = null; @@ -618,20 +589,17 @@ public class Auxiliary { p.networkHandler.sendPacket(packet); total.getAndIncrement(); }); - Value ret = NumericValue.of(total.get()); - return (cc, tt) -> ret; + return NumericValue.of(total.get()); }); - expression.addLazyFunction("format", -1, (c, t, lv) -> { - if (lv.size() == 0 ) throw new InternalExpressionException("'format' requires at least one component"); - List values = lv.stream().map(lazy -> lazy.evalValue(c)).collect(Collectors.toList()); + expression.addFunction("format", values -> { + if (values.size() == 0 ) throw new InternalExpressionException("'format' requires at least one component"); if (values.get(0) instanceof ListValue && values.size()==1) values = ((ListValue) values.get(0)).getItems(); - Value ret = new FormattedTextValue(Messenger.c(values.stream().map(Value::getString).toArray())); - return (cc, tt) -> ret; + return new FormattedTextValue(Messenger.c(values.stream().map(Value::getString).toArray())); }); - expression.addLazyFunction("run", 1, (c, t, lv) -> { + expression.addContextFunction("run", 1, (c, t, lv) -> { BlockPos target = ((CarpetContext)c).origin; Vec3d posf = new Vec3d((double)target.getX()+0.5D, target.getY(),(double)target.getZ()+0.5D); ServerCommandSource s = ((CarpetContext)c).s; @@ -641,56 +609,48 @@ public class Auxiliary { List output = new ArrayList<>(); Value retval = new NumericValue(s.getMinecraftServer().getCommandManager().execute( new SnoopyCommandSource(s, posf, error, output), - lv.get(0).evalValue(c).getString()) + lv.get(0).getString()) ); - Value ret = ListValue.of( + return ListValue.of( retval, ListValue.wrap(output.stream().map(FormattedTextValue::new).collect(Collectors.toList())), FormattedTextValue.of(error[0]) ); - return (c_, t_) -> ret; } catch (Exception exc) { - Value ret = ListValue.of(Value.NULL, ListValue.of(), new FormattedTextValue(new LiteralText(exc.getMessage()))); - return (c_, t_) -> ret; + return ListValue.of(Value.NULL, ListValue.of(), new FormattedTextValue(new LiteralText(exc.getMessage()))); } }); - expression.addLazyFunction("save", 0, (c, t, lv) -> { + expression.addContextFunction("save", 0, (c, t, lv) -> { ServerCommandSource s = ((CarpetContext)c).s; s.getMinecraftServer().getPlayerManager().saveAllPlayerData(); s.getMinecraftServer().save(true,true,true); s.getWorld().getChunkManager().tick(() -> true); CarpetSettings.LOG.warn("Saved chunks"); - return (cc, tt) -> Value.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("tick_time", 0, (c, t, lv) -> - { - Value time = new NumericValue(((CarpetContext) c).s.getMinecraftServer().getTicks()); - return (cc, tt) -> time; - }); + expression.addContextFunction("tick_time", 0, (c, t, lv) -> + new NumericValue(((CarpetContext) c).s.getMinecraftServer().getTicks())); - expression.addLazyFunction("world_time", 0, (c, t, lv) -> - { - Value time = new NumericValue(((CarpetContext) c).s.getWorld().getTime()); - return (cc, tt) -> time; - }); + expression.addContextFunction("world_time", 0, (c, t, lv) -> + new NumericValue(((CarpetContext) c).s.getWorld().getTime())); - expression.addLazyFunction("day_time", -1, (c, t, lv) -> + expression.addContextFunction("day_time", -1, (c, t, lv) -> { Value time = new NumericValue(((CarpetContext) c).s.getWorld().getTimeOfDay()); if (lv.size() > 0) { - long newTime = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); + long newTime = NumericValue.asNumber(lv.get(0)).getLong(); if (newTime < 0) newTime = 0; ((CarpetContext) c).s.getWorld().setTimeOfDay(newTime);// setTimeOfDay(newTime); } - return (cc, tt) -> time; + return time; }); - expression.addLazyFunction("last_tick_times", -1, (c, t, lv) -> + expression.addContextFunction("last_tick_times", -1, (c, t, lv) -> { //assuming we are in the tick world section // might be off one tick when run in the off tasks or asynchronously. @@ -701,12 +661,11 @@ public class Auxiliary { { ticks.add(new NumericValue(((double)tickArray[i % 100])/1000000.0)); } - Value ret = ListValue.wrap(ticks); - return (cc, tt) -> ret; + return ListValue.wrap(ticks); }); - expression.addLazyFunction("game_tick", -1, (c, t, lv) -> { + expression.addContextFunction("game_tick", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerCommandSource s = cc.s; if (!s.getMinecraftServer().isOnThread()) throw new InternalExpressionException("Unable to run ticks from threads"); @@ -717,7 +676,7 @@ public class Auxiliary { ((MinecraftServerInterface) s.getMinecraftServer()).forceTick(() -> System.nanoTime() - CarpetServer.scriptServer.tickStart < 50000000L); if (lv.size() > 0) { - long ms_total = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); + long ms_total = NumericValue.asNumber(lv.get(0)).getLong(); long end_expected = CarpetServer.scriptServer.tickStart + ms_total * 1000000L; long wait = end_expected - System.nanoTime(); if (wait > 0L) @@ -740,17 +699,16 @@ public class Auxiliary { } if(CarpetServer.scriptServer.stopAll) throw new ExitStatement(Value.NULL); - return (_c, _t) -> Value.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("seed", -1, (c, t, lv) -> { + expression.addContextFunction("seed", -1, (c, t, lv) -> { ServerCommandSource s = ((CarpetContext)c).s; c.host.issueDeprecation("seed()"); - Value ret = new NumericValue(s.getWorld().getSeed()); - return (cc, tt) -> ret; + return new NumericValue(s.getWorld().getSeed()); }); - expression.addLazyFunction("relight", -1, (c, t, lv) -> + expression.addContextFunction("relight", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); @@ -758,21 +716,16 @@ public class Auxiliary { ServerWorld world = cc.s.getWorld(); ((ThreadedAnvilChunkStorageInterface) world.getChunkManager().threadedAnvilChunkStorage).relightChunk(new ChunkPos(pos)); WorldTools.forceChunkUpdate(pos, world); - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("current_dimension", 0, (c, t, lv) -> { - ServerCommandSource s = ((CarpetContext)c).s; - Value retval = ValueConversions.of(s.getWorld()); - return (cc, tt) -> retval; - }); + expression.addContextFunction("current_dimension", 0, (c, t, lv) -> + ValueConversions.of( ((CarpetContext)c).s.getWorld())); - expression.addLazyFunction("view_distance", 0, (c, t, lv) -> { - ServerCommandSource s = ((CarpetContext)c).s; - Value retval = new NumericValue(s.getMinecraftServer().getPlayerManager().getViewDistance()); - return (cc, tt) -> retval; - }); + expression.addContextFunction("view_distance", 0, (c, t, lv) -> + new NumericValue(((CarpetContext)c).s.getMinecraftServer().getPlayerManager().getViewDistance())); + // lazy due to passthrough and context changing ability expression.addLazyFunction("in_dimension", 2, (c, t, lv) -> { ServerCommandSource outerSource = ((CarpetContext)c).s; Value dimensionValue = lv.get(0).evalValue(c); @@ -786,7 +739,7 @@ public class Auxiliary { return (cc, tt) -> retval; }); - expression.addLazyFunction("plop", -1, (c, t, lv) ->{ + expression.addContextFunction("plop", -1, (c, t, lv) ->{ if (lv.size() == 0) { Map plopData = new HashMap<>(); @@ -807,13 +760,12 @@ public class Auxiliary { plopData.put(StringValue.of("configured_structures"), ListValue.wrap(registryManager.get(Registry.CONFIGURED_STRUCTURE_FEATURE_WORLDGEN).getIds().stream().sorted().map(ValueConversions::of).collect(Collectors.toList())) ); - Value ret = MapValue.wrap(plopData); - return (_c, _t) -> ret; + return MapValue.wrap(plopData); } BlockArgument locator = BlockArgument.findIn((CarpetContext)c, lv, 0); if (lv.size() <= locator.offset) throw new InternalExpressionException("'plop' needs extra argument indicating what to plop"); - String what = lv.get(locator.offset).evalValue(c).getString(); + String what = lv.get(locator.offset).getString(); Value [] result = new Value[]{Value.NULL}; ((CarpetContext)c).s.getMinecraftServer().submitAndJoin( () -> { @@ -825,41 +777,38 @@ public class Auxiliary { WorldTools.forceChunkUpdate(locator.block.getPos(), ((CarpetContext) c).s.getWorld()); result[0] = new NumericValue(res); }); - Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later - return (_c, _t) -> ret; + return result[0]; }); - expression.addLazyFunction("schedule", -1, (c, t, lv) -> { + expression.addContextFunction("schedule", -1, (c, t, lv) -> { if (lv.size()<2) throw new InternalExpressionException("'schedule' should have at least 2 arguments, delay and call name"); - long delay = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); - - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, false); - List args = functionArgument.unpackArgs(c); + long delay = NumericValue.asNumber(lv.get(0)).getLong(); + FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, false); CarpetServer.scriptServer.events.scheduleCall( (CarpetContext) c, functionArgument.function, - args, + functionArgument.checkedArgs(), delay ); - return (c_, t_) -> Value.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("logger", -1, (c, t, lv) -> + expression.addFunction("logger", lv -> { //CarpetSettings.LOG.error(Registry.ENTITY_TYPE.getIds().stream().sorted().map(ValueConversions::simplify).collect(Collectors.joining("`, `"))); Value res; if(lv.size()==1) { - res = lv.get(0).evalValue(c); + res = lv.get(0); CarpetSettings.LOG.info(res.getString()); } else if(lv.size()==2) { - String level = lv.get(0).evalValue(c).getString().toLowerCase(Locale.ROOT); - res = lv.get(1).evalValue(c); + String level = lv.get(0).getString().toLowerCase(Locale.ROOT); + res = lv.get(1); switch(level){ case "error": CarpetSettings.LOG.error(res.getString()); break; case "warn": CarpetSettings.LOG.warn(res.getString()); break; @@ -871,26 +820,25 @@ public class Auxiliary { } else throw new InternalExpressionException("logger takes 1 or 2 arguments"); - return (_c, _t) -> res; // pass through for variables + return res; // pass through for variables }); - expression.addLazyFunction("list_files", 2, (c, t, lv) -> + expression.addContextFunction("list_files", 2, (c, t, lv) -> { - FileArgument fdesc = FileArgument.from(lv, c, true, FileArgument.Reason.READ); + FileArgument fdesc = FileArgument.from(lv,true, FileArgument.Reason.READ); Stream files = ((CarpetScriptHost) c.host).listFolder(fdesc); - if (files == null) return LazyValue.NULL; - Value ret = ListValue.wrap(files.map(StringValue::of).collect(Collectors.toList())); - return (cc, tt) -> ret; + if (files == null) return Value.NULL; + return ListValue.wrap(files.map(StringValue::of).collect(Collectors.toList())); }); - expression.addLazyFunction("read_file", 2, (c, t, lv) -> + expression.addContextFunction("read_file", 2, (c, t, lv) -> { - FileArgument fdesc = FileArgument.from(lv, c, false, FileArgument.Reason.READ); + FileArgument fdesc = FileArgument.from(lv,false, FileArgument.Reason.READ); Value retVal; if (fdesc.type == FileArgument.Type.NBT) { Tag state = ((CarpetScriptHost) c.host).readFileTag(fdesc); - if (state == null) return LazyValue.NULL; + if (state == null) return Value.NULL; retVal = new NBTSerializableValue(state); } else if (fdesc.type == FileArgument.Type.JSON) @@ -906,25 +854,23 @@ public class Auxiliary { else { List content = ((CarpetScriptHost) c.host).readTextResource(fdesc); - if (content == null) return LazyValue.NULL; + if (content == null) return Value.NULL; retVal = ListValue.wrap(content.stream().map(StringValue::new).collect(Collectors.toList())); } - return (cc, tt) -> retVal; + return retVal; }); - expression.addLazyFunction("delete_file", 2, (c, t, lv) -> { - FileArgument fdesc = FileArgument.from(lv, c, false, FileArgument.Reason.DELETE); - return ((CarpetScriptHost) c.host).removeResourceFile(fdesc) ? LazyValue.TRUE : LazyValue.FALSE; - }); + expression.addContextFunction("delete_file", 2, (c, t, lv) -> + BooleanValue.of(((CarpetScriptHost) c.host).removeResourceFile(FileArgument.from(lv,false, FileArgument.Reason.DELETE)))); - expression.addLazyFunction("write_file", -1, (c, t, lv) -> { + expression.addContextFunction("write_file", -1, (c, t, lv) -> { if (lv.size() < 3) throw new InternalExpressionException("'write_file' requires three or more arguments"); - FileArgument fdesc = FileArgument.from(lv, c, false, FileArgument.Reason.CREATE); + FileArgument fdesc = FileArgument.from(lv, false, FileArgument.Reason.CREATE); boolean success; if (fdesc.type == FileArgument.Type.NBT) { - Value val = lv.get(2).evalValue(c); + Value val = lv.get(2); NBTSerializableValue tagValue = (val instanceof NBTSerializableValue) ? (NBTSerializableValue) val : new NBTSerializableValue(val.getString()); @@ -933,7 +879,7 @@ public class Auxiliary { } else if (fdesc.type == FileArgument.Type.JSON) { - List data = Collections.singletonList(GSON.toJson(lv.get(2).evalValue(c).toJson())); + List data = Collections.singletonList(GSON.toJson(lv.get(2).toJson())); ((CarpetScriptHost) c.host).removeResourceFile(fdesc); success = ((CarpetScriptHost) c.host).appendLogFile(fdesc, data); } @@ -942,7 +888,7 @@ public class Auxiliary { List data = new ArrayList<>(); if (lv.size()==3) { - Value val = lv.get(2).evalValue(c); + Value val = lv.get(2); if (val instanceof ListValue) { List lval = ((ListValue) val).getItems(); @@ -957,166 +903,144 @@ public class Auxiliary { { for(int i = 2; i < lv.size(); i++) { - data.add(lv.get(i).evalValue(c).getString()); + data.add(lv.get(i).getString()); } } success = ((CarpetScriptHost) c.host).appendLogFile(fdesc, data); } - return success?LazyValue.TRUE:LazyValue.FALSE; + return BooleanValue.of(success); }); - expression.addLazyFunction("load_app_data", -1, (c, t, lv) -> + expression.addContextFunction("load_app_data", -1, (c, t, lv) -> { FileArgument fdesc = new FileArgument(null, FileArgument.Type.NBT, null, false, false, FileArgument.Reason.READ); if (lv.size()>0) { c.host.issueDeprecation("load_app_data(...) with arguments"); - String resource = recognizeResource(lv.get(0).evalValue(c), false); - boolean shared = lv.size() > 1 && lv.get(1).evalValue(c).getBoolean(); + String resource = recognizeResource(lv.get(0), false); + boolean shared = lv.size() > 1 && lv.get(1).getBoolean(); fdesc = new FileArgument(resource, FileArgument.Type.NBT, null, false, shared, FileArgument.Reason.READ); } - Tag state = ((CarpetScriptHost) c.host).readFileTag(fdesc); - if (state == null) - return (cc, tt) -> Value.NULL; - Value retVal = new NBTSerializableValue(state); - return (cc, tt) -> retVal; + return NBTSerializableValue.of(((CarpetScriptHost) c.host).readFileTag(fdesc)); }); - expression.addLazyFunction("store_app_data", -1, (c, t, lv) -> + expression.addContextFunction("store_app_data", -1, (c, t, lv) -> { if (lv.size() == 0) throw new InternalExpressionException("'store_app_data' needs NBT tag and an optional file"); - Value val = lv.get(0).evalValue(c); + Value val = lv.get(0); FileArgument fdesc = new FileArgument(null, FileArgument.Type.NBT, null, false, false, FileArgument.Reason.CREATE); if (lv.size()>1) { c.host.issueDeprecation("store_app_data(...) with more than one argument"); - String resource = recognizeResource(lv.get(1).evalValue(c), false); - boolean shared = lv.size() > 2 && lv.get(2).evalValue(c).getBoolean(); + String resource = recognizeResource(lv.get(1), false); + boolean shared = lv.size() > 2 && lv.get(2).getBoolean(); fdesc = new FileArgument(resource, FileArgument.Type.NBT, null, false, shared, FileArgument.Reason.CREATE); } NBTSerializableValue tagValue = (val instanceof NBTSerializableValue) ? (NBTSerializableValue) val : new NBTSerializableValue(val.getString()); - Tag tag = tagValue.getTag(); - boolean success = ((CarpetScriptHost) c.host).writeTagFile(tag, fdesc); - return success?LazyValue.TRUE:LazyValue.FALSE; + return BooleanValue.of(((CarpetScriptHost) c.host).writeTagFile(tagValue.getTag(), fdesc)); }); - expression.addLazyFunction("statistic", 3, (c, t, lv) -> + expression.addContextFunction("statistic", 3, (c, t, lv) -> { - Value playerValue = lv.get(0).evalValue(c); CarpetContext cc = (CarpetContext)c; - ServerPlayerEntity player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), playerValue); - if (player == null) return LazyValue.NULL; + ServerPlayerEntity player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), lv.get(0)); + if (player == null) return Value.NULL; Identifier category; Identifier statName; try { - category = new Identifier(lv.get(1).evalValue(c).getString()); - statName = new Identifier(lv.get(2).evalValue(c).getString()); + category = new Identifier(lv.get(1).getString()); + statName = new Identifier(lv.get(2).getString()); } catch (InvalidIdentifierException e) { - return LazyValue.NULL; + return Value.NULL; } StatType type = Registry.STAT_TYPE.get(category); - if (type == null) - return LazyValue.NULL; + if (type == null) return Value.NULL; Stat stat = getStat(type, statName); - if (stat == null) - return LazyValue.NULL; - return (_c, _t) -> new NumericValue(player.getStatHandler().getStat(stat)); + if (stat == null) return Value.NULL; + return new NumericValue(player.getStatHandler().getStat(stat)); }); //handle_event('event', function...) - expression.addLazyFunction("handle_event", -1, (c, t, lv) -> + expression.addContextFunction("handle_event", -1, (c, t, lv) -> { if (lv.size() < 2) throw new InternalExpressionException("'handle_event' requires at least two arguments, event name, and a callback"); - String event = lv.get(0).evalValue(c).getString(); - FunctionArgument callback = FunctionArgument.findIn(c, expression.module, lv, 1, true, false); + String event = lv.get(0).getString(); + FunctionArgument callback = FunctionArgument.findIn(c, expression.module, lv, 1, true, false); CarpetScriptHost host = ((CarpetScriptHost)c.host); - Value success; if (callback.function == null) - { - success = host.getScriptServer().events.removeBuiltInEvent(event, host)?Value.TRUE:Value.FALSE; - } - else - { - success = host.getScriptServer().events.handleCustomEvent(event, host, callback.function, callback.unpackArgs(c) )?Value.TRUE:Value.FALSE; - } - return (cc, tt) -> success; + return BooleanValue.of(host.getScriptServer().events.removeBuiltInEvent(event, host)); + // args don't need to be checked will be checked at the event + return BooleanValue.of( host.getScriptServer().events.handleCustomEvent(event, host, callback.function, callback.args )); }); //signal_event('event', player or null, args.... ) -> number of apps notified - expression.addLazyFunction("signal_event", -1, (c, t, lv) -> + expression.addContextFunction("signal_event", -1, (c, t, lv) -> { if (lv.size() == 0) throw new InternalExpressionException("'signal' requires at least one argument"); CarpetContext cc = (CarpetContext)c; CarpetScriptServer server = ((CarpetScriptHost)c.host).getScriptServer(); - String eventName = lv.get(0).evalValue(c).getString(); + String eventName = lv.get(0).getString(); // no such event yet - if (CarpetEventServer.Event.getEvent(eventName, server) == null) return LazyValue.NULL; + if (CarpetEventServer.Event.getEvent(eventName, server) == null) return Value.NULL; ServerPlayerEntity player = null; List args = Collections.emptyList(); if (lv.size() > 1) { - player = EntityValue.getPlayerByValue(server.server, lv.get(1).evalValue(c)); - if (lv.size() > 2) - { - args = FunctionValue.resolveArgs(lv.subList(2, lv.size()), c, t); - } + player = EntityValue.getPlayerByValue(server.server, lv.get(1)); + if (lv.size() > 2) args = lv.subList(2, lv.size()); } int counts = ((CarpetScriptHost)c.host).getScriptServer().events.signalEvent(eventName, cc, player, args); - if (counts < 0) return LazyValue.NULL; - Value ret = new NumericValue(counts); - return (c_, t_) -> ret; + if (counts < 0) return Value.NULL; + return new NumericValue(counts); }); // nbt_storage() // nbt_storage(key) // nbt_storage(key, nbt) - expression.addLazyFunction("nbt_storage", -1, (c, t, lv) -> { + expression.addContextFunction("nbt_storage", -1, (c, t, lv) -> { if (lv.size() > 2) throw new InternalExpressionException("'nbt_storage' requires 0, 1 or 2 arguments."); CarpetContext cc = (CarpetContext) c; DataCommandStorage storage = cc.s.getMinecraftServer().getDataCommandStorage(); - if (lv.size() == 0) { - Value ret = ListValue.wrap(storage.getIds().map(i -> new StringValue(nameFromRegistryId(i))).collect(Collectors.toList())); - return (_c, _t) -> ret; - } - String key = lv.get(0).evalValue(c).getString(); + if (lv.size() == 0) + return ListValue.wrap(storage.getIds().map(i -> new StringValue(nameFromRegistryId(i))).collect(Collectors.toList())); + String key = lv.get(0).getString(); CompoundTag old_nbt = storage.get(new Identifier(key)); if (lv.size() == 2) { - Value nbt = lv.get(1).evalValue(c); + Value nbt = lv.get(1); NBTSerializableValue new_nbt = (nbt instanceof NBTSerializableValue) ? (NBTSerializableValue) nbt : NBTSerializableValue.parseString(nbt.getString(), true); storage.set(new Identifier(key), new_nbt.getCompoundTag()); } - if (old_nbt == null) return LazyValue.NULL; - return (_c, _t) -> new NBTSerializableValue(old_nbt); + return NBTSerializableValue.of(old_nbt); }); // script run create_datapack('foo', {'foo' -> {'bar.json' -> {'c' -> true,'d' -> false,'e' -> {'foo' -> [1,2,3]},'a' -> 'foobar','b' -> 5}}}) - expression.addLazyFunction("create_datapack", 2, (c, t, lv) -> { + expression.addContextFunction("create_datapack", 2, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - String origName = lv.get(0).evalValue(c).getString(); + String origName = lv.get(0).getString(); String name = InputValidator.validateSimpleString(origName, true); MinecraftServer server = cc.s.getMinecraftServer(); for (String dpName : server.getDataPackManager().getNames()) { if (dpName.equalsIgnoreCase("file/"+name+".zip") || dpName.equalsIgnoreCase("file/"+name)) - return LazyValue.NULL; + return Value.NULL; } - Value dpdata = lv.get(1).evalValue(c); + Value dpdata = lv.get(1); if (!(dpdata instanceof MapValue)) throw new InternalExpressionException("datapack data needs to be a valid map type"); ResourcePackManager packManager = server.getDataPackManager(); Path dbFloder = server.getSavePath(WorldSavePath.DATAPACKS); Path packFloder = dbFloder.resolve(name+".zip"); - if (Files.exists(packFloder) || Files.exists(dbFloder.resolve(name))) return LazyValue.NULL; + if (Files.exists(packFloder) || Files.exists(dbFloder.resolve(name))) return Value.NULL; Boolean [] successful = new Boolean[]{true}; server.submitAndJoin( () -> { @@ -1161,10 +1085,10 @@ public class Auxiliary { } }); - return successful[0]?LazyValue.TRUE:LazyValue.FALSE; + return BooleanValue.of(successful[0]); }); - expression.addLazyFunction("enable_hidden_dimensions", 0, (c, t, lv) -> { + expression.addContextFunction("enable_hidden_dimensions", 0, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; // from minecraft.server.Main.main MinecraftServer server = cc.s.getMinecraftServer(); @@ -1184,7 +1108,7 @@ public class Auxiliary { RegistryOps registryOps = RegistryOps.of(NbtOps.INSTANCE, serverRM.getResourceManager(), (DynamicRegistryManager.Impl) server.getRegistryManager()); SaveProperties saveProperties = session.readLevelProperties(registryOps, dataPackSettings2); - if (saveProperties == null) return LazyValue.NULL; + if (saveProperties == null) return Value.NULL; //session.backupLevelDataFile(server.getRegistryManager(), saveProperties); // no need // MinecraftServer.createWorlds @@ -1209,8 +1133,7 @@ public class Auxiliary { existing_worlds.put(registryKey2, serverWorld2); } } - Value ret = ListValue.wrap(addeds); - return (_c, _t) -> ret; + return ListValue.wrap(addeds); }); } @@ -1267,8 +1190,6 @@ public class Auxiliary { } } - - private static Stat getStat(StatType type, Identifier id) { T key = type.getRegistry().get(id); diff --git a/src/main/java/carpet/script/api/BlockIterators.java b/src/main/java/carpet/script/api/BlockIterators.java index 03582021..0c4ce028 100644 --- a/src/main/java/carpet/script/api/BlockIterators.java +++ b/src/main/java/carpet/script/api/BlockIterators.java @@ -3,6 +3,7 @@ package carpet.script.api; import carpet.script.CarpetContext; import carpet.script.Context; import carpet.script.Expression; +import carpet.script.Fluff; import carpet.script.LazyValue; import carpet.script.argument.BlockArgument; import carpet.script.argument.Vector3Argument; @@ -30,11 +31,14 @@ import static java.lang.Math.min; public class BlockIterators { public static void apply(Expression expression) { - expression.addLazyFunction("scan", -1, (c, t, lv) -> + // lazy cause of lazy expression + expression.addLazyFunction("scan", -1, (c, t, llv) -> { + if (llv.size() < 3) throw new InternalExpressionException("'scan' needs many more arguments"); + List lv = Fluff.AbstractFunction.unpackLazy(llv.subList(0, llv.size()-1), c, Context.NONE); CarpetContext cc = (CarpetContext)c; BlockArgument centerLocator = BlockArgument.findIn(cc, lv, 0); - Vector3Argument rangeLocator = Vector3Argument.findIn(cc, lv, centerLocator.offset); + Vector3Argument rangeLocator = Vector3Argument.findIn(lv, centerLocator.offset); BlockPos center = centerLocator.block.getPos(); Vec3i range; @@ -54,7 +58,7 @@ public class BlockIterators { Vec3i upperRange = range; if (lv.size() > rangeLocator.offset+1) // +1 cause we still need the expression { - rangeLocator = Vector3Argument.findIn(cc, lv, rangeLocator.offset); + rangeLocator = Vector3Argument.findIn(lv, rangeLocator.offset); if (rangeLocator.fromBlock) { upperRange = new Vec3i( @@ -69,11 +73,11 @@ public class BlockIterators { upperRange = new Vec3i(abs(rangeLocator.vec.x), abs(rangeLocator.vec.y), abs(rangeLocator.vec.z)); } } - if (lv.size() != rangeLocator.offset+1) + if (llv.size() != rangeLocator.offset+1) { throw new InternalExpressionException("'scan' takes two, or three block positions, and an expression: "+lv.size()+" "+rangeLocator.offset); } - LazyValue expr = lv.get(rangeLocator.offset); + LazyValue expr = llv.get(rangeLocator.offset); int cx = center.getX(); int cy = center.getY(); @@ -135,9 +139,12 @@ public class BlockIterators { return (c_, t_) -> new NumericValue(finalSCount); }); - expression.addLazyFunction("volume", -1, (c, t, lv) -> + // must be lazy + expression.addLazyFunction("volume", -1, (c, t, llv) -> { CarpetContext cc = (CarpetContext)c; + if (llv.size() < 3) throw new InternalExpressionException("'volume' needs many more arguments"); + List lv = Fluff.AbstractFunction.unpackLazy(llv.subList(0, llv.size()-1), c, Context.NONE); BlockArgument pos1Locator = BlockArgument.findIn(cc, lv, 0); BlockArgument pos2Locator = BlockArgument.findIn(cc, lv, pos1Locator.offset); @@ -156,7 +163,7 @@ public class BlockIterators { int maxx = max(x1, x2); int maxy = max(y1, y2); int maxz = max(z1, z2); - LazyValue expr = lv.get(pos2Locator.offset); + LazyValue expr = llv.get(pos2Locator.offset); //saving outer scope LazyValue _x = c.getVariable("_x"); @@ -207,9 +214,8 @@ public class BlockIterators { return (c_, t_) -> new NumericValue(finalSCount); }); - expression.addLazyFunction("neighbours", -1, (c, t, lv)-> + expression.addContextFunction("neighbours", -1, (c, t, lv)-> { - BlockPos center = BlockArgument.findIn((CarpetContext) c, lv,0).block.getPos(); ServerWorld world = ((CarpetContext) c).s.getWorld(); @@ -220,11 +226,10 @@ public class BlockIterators { neighbours.add(new BlockValue(null, world, center.south())); neighbours.add(new BlockValue(null, world, center.east())); neighbours.add(new BlockValue(null, world, center.west())); - Value retval = ListValue.wrap(neighbours); - return (c_, t_) -> retval; + return ListValue.wrap(neighbours); }); - expression.addLazyFunction("rect", -1, (c, t, lv)-> + expression.addContextFunction("rect", -1, (c, t, lv)-> { CarpetContext cc = (CarpetContext) c; int cx, cy, cz; @@ -237,7 +242,7 @@ public class BlockIterators { cz = cpos.getZ(); if (lv.size() > cposLocator.offset) { - Vector3Argument diffLocator = Vector3Argument.findIn(cc, lv, cposLocator.offset); + Vector3Argument diffLocator = Vector3Argument.findIn(lv, cposLocator.offset); if (diffLocator.fromBlock) { sminx = MathHelper.floor(abs(diffLocator.vec.x - cx)); @@ -252,7 +257,7 @@ public class BlockIterators { } if (lv.size() > diffLocator.offset) { - Vector3Argument posDiff = Vector3Argument.findIn(cc, lv, diffLocator.offset); + Vector3Argument posDiff = Vector3Argument.findIn(lv, diffLocator.offset); if (posDiff.fromBlock) { smaxx = MathHelper.floor(abs(posDiff.vec.x - cx)); @@ -283,7 +288,7 @@ public class BlockIterators { smaxz = 1; } - return (c_, t_) -> new LazyListValue() + return new LazyListValue() { final int minx = cx-sminx; final int miny = cy-sminy; @@ -348,7 +353,7 @@ public class BlockIterators { }; }); - expression.addLazyFunction("diamond", -1, (c, t, lv)-> + expression.addContextFunction("diamond", -1, (c, t, lv)-> { CarpetContext cc = (CarpetContext)c; @@ -377,17 +382,17 @@ public class BlockIterators { BlockValue.fromCoords(cc, cx, cy, cz+1), BlockValue.fromCoords(cc, cx, cy+1, cz) ); - return (_c, _t ) -> retval; + return retval; } else if (lv.size()==1+cposLocator.offset) { - width = (int) ((NumericValue) lv.get(cposLocator.offset).evalValue(c)).getLong(); + width = (int) ((NumericValue) lv.get(cposLocator.offset)).getLong(); height = 0; } else if(lv.size()==2+cposLocator.offset) { - width = (int) ((NumericValue) lv.get(cposLocator.offset).evalValue(c)).getLong(); - height = (int) ((NumericValue) lv.get(cposLocator.offset+1).evalValue(c)).getLong(); + width = (int) ((NumericValue) lv.get(cposLocator.offset)).getLong(); + height = (int) ((NumericValue) lv.get(cposLocator.offset+1)).getLong(); } else{ throw new InternalExpressionException("Incorrect number of arguments for 'diamond'"); } @@ -398,7 +403,7 @@ public class BlockIterators { } if (height == 0) { - return (c_, t_) -> new LazyListValue() + return new LazyListValue() { int curradius; int curpos; @@ -448,7 +453,7 @@ public class BlockIterators { } else { - return (c_, t_) -> new LazyListValue() + return new LazyListValue() { int curradius; int curpos; diff --git a/src/main/java/carpet/script/api/Entities.java b/src/main/java/carpet/script/api/Entities.java index ce2cd3b5..138ac844 100644 --- a/src/main/java/carpet/script/api/Entities.java +++ b/src/main/java/carpet/script/api/Entities.java @@ -4,12 +4,10 @@ import carpet.script.CarpetContext; import carpet.script.CarpetEventServer; import carpet.script.CarpetScriptHost; import carpet.script.Expression; -import carpet.script.LazyValue; import carpet.script.argument.FunctionArgument; import carpet.script.argument.Vector3Argument; import carpet.script.exception.InternalExpressionException; import carpet.script.value.EntityValue; -import carpet.script.value.FunctionValue; import carpet.script.value.ListValue; import carpet.script.value.NBTSerializableValue; import carpet.script.value.NumericValue; @@ -43,7 +41,7 @@ import java.util.stream.Collectors; public class Entities { public static void apply(Expression expression) { - expression.addLazyFunction("player", -1, (c, t, lv) -> + expression.addContextFunction("player", -1, (c, t, lv) -> { if (lv.size() == 0) { @@ -51,26 +49,15 @@ public class Entities { if (cc.host.user != null) { ServerPlayerEntity player = cc.s.getMinecraftServer().getPlayerManager().getPlayer(cc.host.user); - if (player == null) return LazyValue.NULL; - Value ret = new EntityValue(player); - return (_c, _t) -> ret; + return EntityValue.of(player); } Entity callingEntity = cc.s.getEntity(); - if (callingEntity instanceof PlayerEntity) - { - Value retval = new EntityValue(callingEntity); - return (_c, _t) -> retval; - } + if (callingEntity instanceof PlayerEntity) return EntityValue.of(callingEntity); Vec3d pos = ((CarpetContext)c).s.getPosition(); PlayerEntity closestPlayer = ((CarpetContext)c).s.getWorld().getClosestPlayer(pos.x, pos.y, pos.z, -1.0, EntityPredicates.VALID_ENTITY); - if (closestPlayer != null) - { - Value retval = new EntityValue(closestPlayer); - return (_c, _t) -> retval; - } - return (_c, _t) -> Value.NULL; + return EntityValue.of(closestPlayer); } - String playerName = lv.get(0).evalValue(c).getString(); + String playerName = lv.get(0).getString(); Value retval = Value.NULL; if ("all".equalsIgnoreCase(playerName)) { @@ -114,37 +101,36 @@ public class Entities { if (player != null) retval = new EntityValue(player); } - Value finalVar = retval; - return (_c, _t) -> finalVar; + return retval; }); - expression.addLazyFunction("spawn", -1, (c, t, lv) -> + expression.addContextFunction("spawn", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; if (lv.size() < 2) throw new InternalExpressionException("'spawn' function takes mob name, and position to spawn"); - String entityString = lv.get(0).evalValue(c).getString(); + String entityString = lv.get(0).getString(); Identifier entityId; try { entityId = Identifier.fromCommandInput(new StringReader(entityString)); EntityType type = Registry.ENTITY_TYPE.getOrEmpty(entityId).orElse(null); if (type == null || !type.isSummonable()) - return LazyValue.NULL; + return Value.NULL; } catch (CommandSyntaxException exception) { - return LazyValue.NULL; + return Value.NULL; } - Vector3Argument position = Vector3Argument.findIn(cc, lv, 1); + Vector3Argument position = Vector3Argument.findIn(lv, 1); if (position.fromBlock) position.vec = position.vec.subtract(0, 0.5, 0); CompoundTag tag = new CompoundTag(); boolean hasTag = false; if (lv.size() > position.offset) { - Value nbt = lv.get(position.offset).evalValue(c); + Value nbt = lv.get(position.offset); NBTSerializableValue v = (nbt instanceof NBTSerializableValue) ? (NBTSerializableValue) nbt : NBTSerializableValue.parseString(nbt.getString(), true); hasTag = true; @@ -160,51 +146,38 @@ public class Entities { return !serverWorld.tryLoadEntity(entity_1x) ? null : entity_1x; }); if (entity_1 == null) { - return LazyValue.NULL; + return Value.NULL; } else { if (!hasTag && entity_1 instanceof MobEntity) { ((MobEntity)entity_1).initialize(serverWorld, serverWorld.getLocalDifficulty(entity_1.getBlockPos()), SpawnReason.COMMAND, null, null); } - Value res = new EntityValue(entity_1); - return (_c, _t) -> res; + return new EntityValue(entity_1); } }); - expression.addLazyFunction("entity_id", 1, (c, t, lv) -> + expression.addContextFunction("entity_id", 1, (c, t, lv) -> { - Value who = lv.get(0).evalValue(c); - Entity e; + Value who = lv.get(0); if (who instanceof NumericValue) - { - e = ((CarpetContext)c).s.getWorld().getEntityById((int)((NumericValue) who).getLong()); - } - else - { - e = ((CarpetContext)c).s.getWorld().getEntity(UUID.fromString(who.getString())); - } - if (e==null) - { - return LazyValue.NULL; - } - return (cc, tt) -> new EntityValue(e); + return EntityValue.of(((CarpetContext)c).s.getWorld().getEntityById((int)((NumericValue) who).getLong())); + return EntityValue.of(((CarpetContext)c).s.getWorld().getEntity(UUID.fromString(who.getString()))); }); - expression.addLazyFunction("entity_list", 1, (c, t, lv) -> + expression.addContextFunction("entity_list", 1, (c, t, lv) -> { - String who = lv.get(0).evalValue(c).getString(); + String who = lv.get(0).getString(); ServerCommandSource source = ((CarpetContext)c).s; EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, source.getMinecraftServer()); List entityList = source.getWorld().getEntitiesByType(eDesc.directType, eDesc.filteringPredicate); - Value retval = ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList())); - return (_c, _t ) -> retval; + return ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList())); }); - expression.addLazyFunction("entity_area", -1, (c, t, lv) -> + expression.addContextFunction("entity_area", -1, (c, t, lv) -> { if (lv.size()<3) throw new InternalExpressionException("'entity_area' requires entity type, center and range arguments"); - String who = lv.get(0).evalValue(c).getString(); + String who = lv.get(0).getString(); CarpetContext cc = (CarpetContext)c; - Vector3Argument centerLocator = Vector3Argument.findIn(cc, lv, 1, false, true); + Vector3Argument centerLocator = Vector3Argument.findIn(lv, 1, false, true); Box centerBox; if (centerLocator.entity != null) @@ -217,90 +190,87 @@ public class Entities { if (centerLocator.fromBlock) center.add(0.5, 0.5, 0.5); centerBox = new Box(center, center); } - Vector3Argument rangeLocator = Vector3Argument.findIn(cc, lv, centerLocator.offset); + Vector3Argument rangeLocator = Vector3Argument.findIn(lv, centerLocator.offset); if (rangeLocator.fromBlock) throw new InternalExpressionException("Range of 'entity_area' cannot come from a block argument"); Vec3d range = rangeLocator.vec; Box area = centerBox.expand(range.x, range.y, range.z); EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, cc.s.getMinecraftServer()); List entityList = cc.s.getWorld().getEntitiesByType(eDesc.directType, area,eDesc.filteringPredicate); - Value retval = ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList())); - return (_c, _t ) -> retval; + return ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList())); }); - expression.addLazyFunction("entity_selector", -1, (c, t, lv) -> + expression.addContextFunction("entity_selector", -1, (c, t, lv) -> { - String selector = lv.get(0).evalValue(c).getString(); + String selector = lv.get(0).getString(); List retlist = new ArrayList<>(); for (Entity e: EntityValue.getEntitiesFromSelector(((CarpetContext)c).s, selector)) { retlist.add(new EntityValue(e)); } - return (c_, t_) -> ListValue.wrap(retlist); + return ListValue.wrap(retlist); }); - expression.addLazyFunction("query", -1, (c, t, lv) -> + expression.addContextFunction("query", -1, (c, t, lv) -> { if (lv.size()<2) { throw new InternalExpressionException("'query' takes entity as a first argument, and queried feature as a second"); } - Value v = lv.get(0).evalValue(c); + Value v = lv.get(0); if (!(v instanceof EntityValue)) throw new InternalExpressionException("First argument to query should be an entity"); - String what = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT); + String what = lv.get(1).getString().toLowerCase(Locale.ROOT); if (what.equals("tags")) c.host.issueDeprecation("'tags' for entity querying"); Value retval; if (lv.size()==2) retval = ((EntityValue) v).get(what, null); else if (lv.size()==3) - retval = ((EntityValue) v).get(what, lv.get(2).evalValue(c)); + retval = ((EntityValue) v).get(what, lv.get(2)); else - retval = ((EntityValue) v).get(what, ListValue.wrap(lv.subList(2, lv.size()).stream().map((vv) -> vv.evalValue(c)).collect(Collectors.toList()))); - return (cc, tt) -> retval; + retval = ((EntityValue) v).get(what, ListValue.wrap(lv.subList(2, lv.size()))); + return retval; }); // or update - expression.addLazyFunction("modify", -1, (c, t, lv) -> + expression.addContextFunction("modify", -1, (c, t, lv) -> { if (lv.size()<2) { throw new InternalExpressionException("'modify' takes entity as a first argument, and queried feature as a second"); } - Value v = lv.get(0).evalValue(c); + Value v = lv.get(0); if (!(v instanceof EntityValue)) throw new InternalExpressionException("First argument to modify should be an entity"); - String what = lv.get(1).evalValue(c).getString(); + String what = lv.get(1).getString(); if (lv.size()==2) ((EntityValue) v).set(what, null); else if (lv.size()==3) - ((EntityValue) v).set(what, lv.get(2).evalValue(c)); + ((EntityValue) v).set(what, lv.get(2)); else - ((EntityValue) v).set(what, ListValue.wrap(lv.subList(2, lv.size()).stream().map((vv) -> vv.evalValue(c)).collect(Collectors.toList()))); - return (cc, tt) -> v; + ((EntityValue) v).set(what, ListValue.wrap(lv.subList(2, lv.size()))); + return v; }); - expression.addLazyFunction("entity_types", -1, (c, t, lv) -> + expression.addContextFunction("entity_types", -1, (c, t, lv) -> { - if (lv.size() > 1) throw new InternalExpressionException("'entity_types' requires one or no arguments"); - String desc = (lv.size() == 1)?lv.get(0).evalValue(c).getString():"*"; - Value ret = EntityValue.getEntityDescriptor(desc, ((CarpetContext) c).s.getMinecraftServer()).listValue; - return (_c, _t) -> ret; + String desc = (lv.size() == 1)?lv.get(0).getString():"*"; + return EntityValue.getEntityDescriptor(desc, ((CarpetContext) c).s.getMinecraftServer()).listValue; }); - expression.addLazyFunction("entity_load_handler", -1, (c, t, lv) -> + expression.addContextFunction("entity_load_handler", -1, (c, t, lv) -> { if (c.host.isPerUser()) throw new InternalExpressionException("'entity_load_handler' can only be called in apps with global scope"); if (lv.size() < 2) throw new InternalExpressionException("'entity_load_handler' required the entity type, and a function to call"); - Value entityValue = lv.get(0).evalValue(c); + Value entityValue = lv.get(0); List descriptors = (entityValue instanceof ListValue) ? ((ListValue) entityValue).getItems().stream().map(Value::getString).collect(Collectors.toList()) : Collections.singletonList(entityValue.getString()); Set> types = new HashSet<>(); descriptors.forEach(s -> types.addAll(EntityValue.getEntityDescriptor(s, ((CarpetContext) c).s.getMinecraftServer()).typeList)); - FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 1, true, false); + FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 1, true, false); CarpetEventServer events = ((CarpetScriptHost)c.host).getScriptServer().events; if (funArg.function == null) { @@ -308,27 +278,26 @@ public class Entities { } else { - types.forEach(et -> events.addBuiltInEvent(CarpetEventServer.Event.getEntityLoadEventName(et), c.host, funArg.function, funArg.unpackArgs(c))); + types.forEach(et -> events.addBuiltInEvent(CarpetEventServer.Event.getEntityLoadEventName(et), c.host, funArg.function, funArg.args)); } - Value ret = new NumericValue(types.size()); - return (cc, tt) -> ret; + return new NumericValue(types.size()); }); // or update - expression.addLazyFunction("entity_event", -1, (c, t, lv) -> + expression.addContextFunction("entity_event", -1, (c, t, lv) -> { if (lv.size()<3) throw new InternalExpressionException("'entity_event' requires at least 3 arguments, entity, event to be handled, and function name, with optional arguments"); - Value v = lv.get(0).evalValue(c); + Value v = lv.get(0); if (!(v instanceof EntityValue)) throw new InternalExpressionException("First argument to entity_event should be an entity"); - String what = lv.get(1).evalValue(c).getString(); + String what = lv.get(1).getString(); - FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 2, true, false); + FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 2, true, false); - ((EntityValue) v).setEvent((CarpetContext)c, what, funArg.function, funArg.unpackArgs(c)); + ((EntityValue) v).setEvent((CarpetContext)c, what, funArg.function, funArg.args); - return LazyValue.NULL; + return Value.NULL; }); } } diff --git a/src/main/java/carpet/script/api/Inventories.java b/src/main/java/carpet/script/api/Inventories.java index 96dd35e1..a1a9af91 100644 --- a/src/main/java/carpet/script/api/Inventories.java +++ b/src/main/java/carpet/script/api/Inventories.java @@ -4,10 +4,10 @@ import carpet.fakes.IngredientInterface; import carpet.fakes.RecipeManagerInterface; import carpet.script.CarpetContext; import carpet.script.Expression; -import carpet.script.LazyValue; import carpet.script.exception.InternalExpressionException; import carpet.script.exception.ThrowStatement; import carpet.script.exception.Throwables; +import carpet.script.value.BooleanValue; import carpet.script.value.ListValue; import carpet.script.value.NBTSerializableValue; import carpet.script.value.NullValue; @@ -49,68 +49,52 @@ import java.util.stream.Collectors; public class Inventories { public static void apply(Expression expression) { - expression.addLazyFunction("stack_limit", 1, (c, t, lv) -> - { - ItemStackArgument item = NBTSerializableValue.parseItem(lv.get(0).evalValue(c).getString()); - Value res = new NumericValue(item.getItem().getMaxCount()); - return (_c, _t) -> res; - }); + expression.addUnaryFunction("stack_limit", v -> + new NumericValue(NBTSerializableValue.parseItem(v.getString()).getItem().getMaxCount())); - expression.addLazyFunction("item_category", 1, (c, t, lv) -> + expression.addUnaryFunction("item_category", v -> { - ItemStackArgument item = NBTSerializableValue.parseItem(lv.get(0).evalValue(c).getString()); - + ItemStackArgument item = NBTSerializableValue.parseItem(v.getString()); ItemGroup ig = item.getItem().getGroup(); - Value res = (ig==null)?Value.NULL:new StringValue(ig.getName()); - return (_c, _t) -> res; + return (ig==null)?Value.NULL:new StringValue(ig.getName()); }); - expression.addLazyFunction("item_list", -1, (c, t, lv) -> + expression.addContextFunction("item_list", -1, (c, t, lv) -> { if (lv.size() == 0) - { - Value res = ListValue.wrap(Registry.ITEM.getIds().stream().map(ValueConversions::of).collect(Collectors.toList())); - return (cc, tt) -> res; - } + return ListValue.wrap(Registry.ITEM.getIds().stream().map(ValueConversions::of).collect(Collectors.toList())); CarpetContext cc = (CarpetContext)c; TagManager tagManager = cc.s.getMinecraftServer().getTagManager(); - String tag = lv.get(0).evalValue(c).getString(); + String tag = lv.get(0).getString(); net.minecraft.tag.Tag itemTag = tagManager.getItems().getTag(new Identifier(tag)); - if (itemTag == null) return LazyValue.NULL; - Value ret = ListValue.wrap(itemTag.values().stream().map(b -> ValueConversions.of(Registry.ITEM.getId(b))).collect(Collectors.toList())); - return (_c, _t) -> ret; + if (itemTag == null) return Value.NULL; + return ListValue.wrap(itemTag.values().stream().map(b -> ValueConversions.of(Registry.ITEM.getId(b))).collect(Collectors.toList())); }); - expression.addLazyFunction("item_tags", -1, (c, t, lv) -> + expression.addContextFunction("item_tags", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; TagManager tagManager = cc.s.getMinecraftServer().getTagManager(); if (lv.size() == 0) - { - Value ret = ListValue.wrap(tagManager.getItems().getTagIds().stream().map(ValueConversions::of).collect(Collectors.toList())); - return (_c, _t) -> ret; - } - Item item = NBTSerializableValue.parseItem(lv.get(0).evalValue(c).getString()).getItem(); + return ListValue.wrap(tagManager.getItems().getTagIds().stream().map(ValueConversions::of).collect(Collectors.toList())); + Item item = NBTSerializableValue.parseItem(lv.get(0).getString()).getItem(); if (lv.size() == 1) - { - Value ret = ListValue.wrap(tagManager.getItems().getTags().entrySet().stream().filter(e -> e.getValue().contains(item)).map(e -> ValueConversions.of(e.getKey())).collect(Collectors.toList())); - return (_c, _t) -> ret; - } - String tag = lv.get(1).evalValue(c).getString(); + return ListValue.wrap(tagManager.getItems().getTags().entrySet().stream().filter(e -> e.getValue().contains(item)).map(e -> ValueConversions.of(e.getKey())).collect(Collectors.toList())); + String tag = lv.get(1).getString(); net.minecraft.tag.Tag itemTag = tagManager.getItems().getTag(new Identifier(tag)); - if (itemTag == null) return LazyValue.NULL; - return item.isIn(itemTag)?LazyValue.TRUE:LazyValue.FALSE; + if (itemTag == null) return Value.NULL; + return BooleanValue.of(item.isIn(itemTag)); }); - expression.addLazyFunction("recipe_data", -1, (c, t, lv) -> + expression.addContextFunction("recipe_data", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; if (lv.size() < 1) throw new InternalExpressionException("'recipe_data' requires at least one argument"); - String recipeName = lv.get(0).evalValue(c).getString(); + String recipeName = lv.get(0).getString(); RecipeType type = RecipeType.CRAFTING; if (lv.size() > 1) { - String recipeType = lv.get(1).evalValue(c).getString(); + String recipeType = lv.get(1).getString(); try { type = Registry.RECIPE_TYPE.get(new Identifier(recipeType)); @@ -123,7 +107,7 @@ public class Inventories { List> recipes; recipes = ((RecipeManagerInterface) cc.s.getMinecraftServer().getRecipeManager()).getAllMatching(type, new Identifier(recipeName)); if (recipes.isEmpty()) - return LazyValue.NULL; + return Value.NULL; List recipesOutput = new ArrayList<>(); for (Recipe recipe: recipes) { @@ -143,7 +127,7 @@ public class Inventories { else { List alternatives = new ArrayList<>(); - stacks.forEach(col -> col.stream().map(ListValue::fromItemStack).forEach(alternatives::add)); + stacks.forEach(col -> col.stream().map(ValueConversions::of).forEach(alternatives::add)); ingredientValue.add(ListValue.wrap(alternatives)); } } @@ -182,91 +166,75 @@ public class Inventories { recipeSpec = ListValue.of(new StringValue("custom")); } - recipesOutput.add(ListValue.of(ListValue.fromItemStack(result), ListValue.wrap(ingredientValue), recipeSpec)); + recipesOutput.add(ListValue.of(ValueConversions.of(result), ListValue.wrap(ingredientValue), recipeSpec)); } - Value ret = ListValue.wrap(recipesOutput); - return (_c, _t) -> ret; + return ListValue.wrap(recipesOutput); }); - expression.addLazyFunction("crafting_remaining_item", 1, (c, t, lv) -> + expression.addUnaryFunction("crafting_remaining_item", v -> { - String itemStr = lv.get(0).evalValue(c).getString(); + String itemStr = v.getString(); Item item; Identifier id = new Identifier(itemStr); item = Registry.ITEM.getOrEmpty(id).orElseThrow(() -> new ThrowStatement(itemStr, Throwables.UNKNOWN_ITEM)); - - if (!item.hasRecipeRemainder()) return LazyValue.NULL; - Value ret = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.ITEM.getId(item.getRecipeRemainder()))); - return (_c, _t ) -> ret; + if (!item.hasRecipeRemainder()) return Value.NULL; + return new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.ITEM.getId(item.getRecipeRemainder()))); }); - - expression.addLazyFunction("inventory_size", -1, (c, t, lv) -> + expression.addContextFunction("inventory_size", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) - return (_c, _t) -> Value.NULL; - Value res = new NumericValue(inventoryLocator.inventory.size()); - return (_c, _t) -> res; + if (inventoryLocator == null) return Value.NULL; + return new NumericValue(inventoryLocator.inventory.size()); }); - expression.addLazyFunction("inventory_has_items", -1, (c, t, lv) -> + expression.addContextFunction("inventory_has_items", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) - return (_c, _t) -> Value.NULL; - Value res = new NumericValue(!inventoryLocator.inventory.isEmpty()); - return (_c, _t) -> res; + if (inventoryLocator == null) return Value.NULL; + return new NumericValue(!inventoryLocator.inventory.isEmpty()); }); //inventory_get(, ) -> item_triple - expression.addLazyFunction("inventory_get", -1, (c, t, lv) -> + expression.addContextFunction("inventory_get", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) - return (_c, _t) -> Value.NULL; + if (inventoryLocator == null) return Value.NULL; if (lv.size() == inventoryLocator.offset) { List fullInventory = new ArrayList<>(); for (int i = 0, maxi = inventoryLocator.inventory.size(); i < maxi; i++) - { - fullInventory.add(ListValue.fromItemStack(inventoryLocator.inventory.getStack(i))); - } - Value res = ListValue.wrap(fullInventory); - return (_c, _t) -> res; + fullInventory.add(ValueConversions.of(inventoryLocator.inventory.getStack(i))); + return ListValue.wrap(fullInventory); } - int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset).evalValue(c)).getLong(); + int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset)).getLong(); slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory); - if (slot == inventoryLocator.inventory.size()) - return (_c, _t) -> Value.NULL; - Value res = ListValue.fromItemStack(inventoryLocator.inventory.getStack(slot)); - return (_c, _t) -> res; + if (slot == inventoryLocator.inventory.size()) return Value.NULL; + return ValueConversions.of(inventoryLocator.inventory.getStack(slot)); }); //inventory_set(, , , , ) - expression.addLazyFunction("inventory_set", -1, (c, t, lv) -> + expression.addContextFunction("inventory_set", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) - return (_c, _t) -> Value.NULL; + if (inventoryLocator == null) return Value.NULL; if (lv.size() < inventoryLocator.offset+2) throw new InternalExpressionException("'inventory_set' requires at least slot number and new stack size, and optional new item"); - int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+0).evalValue(c)).getLong(); + int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+0)).getLong(); slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory); - if (slot == inventoryLocator.inventory.size()) - return (_c, _t) -> Value.NULL; - int count = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+1).evalValue(c)).getLong(); + if (slot == inventoryLocator.inventory.size()) return Value.NULL; + int count = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+1)).getLong(); if (count == 0) { // clear slot ItemStack removedStack = inventoryLocator.inventory.removeStack(slot); syncPlayerInventory(inventoryLocator, slot); //Value res = ListValue.fromItemStack(removedStack); // that tuple will be read only but cheaper if noone cares - return (_c, _t) -> ListValue.fromItemStack(removedStack); + return ValueConversions.of(removedStack); } if (lv.size() < inventoryLocator.offset+3) { @@ -275,12 +243,12 @@ public class Inventories { newStack.setCount(count); inventoryLocator.inventory.setStack(slot, newStack); syncPlayerInventory(inventoryLocator, slot); - return (_c, _t) -> ListValue.fromItemStack(previousStack); + return ValueConversions.of(previousStack); } CompoundTag nbt = null; // skipping one argument if (lv.size() > inventoryLocator.offset+3) { - Value nbtValue = lv.get(inventoryLocator.offset+3).evalValue(c); + Value nbtValue = lv.get(inventoryLocator.offset+3); if (nbtValue instanceof NBTSerializableValue) nbt = ((NBTSerializableValue)nbtValue).getCompoundTag(); else if (nbtValue instanceof NullValue) @@ -288,11 +256,7 @@ public class Inventories { else nbt = new NBTSerializableValue(nbtValue.getString()).getCompoundTag(); } - ItemStackArgument newitem = NBTSerializableValue.parseItem( - lv.get(inventoryLocator.offset+2).evalValue(c).getString(), - nbt - ); - + ItemStackArgument newitem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset+2).getString(), nbt); ItemStack previousStack = inventoryLocator.inventory.getStack(slot); try { @@ -303,62 +267,52 @@ public class Inventories { { throw new InternalExpressionException(e.getMessage()); } - return (_c, _t) -> ListValue.fromItemStack(previousStack); + return ValueConversions.of(previousStack); }); //inventory_find(, or null (first empty slot), ) -> or null - expression.addLazyFunction("inventory_find", -1, (c, t, lv) -> + expression.addContextFunction("inventory_find", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) - return (_c, _t) -> Value.NULL; + if (inventoryLocator == null) return Value.NULL; ItemStackArgument itemArg = null; if (lv.size() > inventoryLocator.offset) { - Value secondArg = lv.get(inventoryLocator.offset+0).evalValue(c); + Value secondArg = lv.get(inventoryLocator.offset+0); if (!(secondArg instanceof NullValue)) itemArg = NBTSerializableValue.parseItem(secondArg.getString()); } int startIndex = 0; if (lv.size() > inventoryLocator.offset+1) { - startIndex = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+1).evalValue(c)).getLong(); + startIndex = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+1)).getLong(); } startIndex = NBTSerializableValue.validateSlot(startIndex, inventoryLocator.inventory); for (int i = startIndex, maxi = inventoryLocator.inventory.size(); i < maxi; i++) { ItemStack stack = inventoryLocator.inventory.getStack(i); if ( (itemArg == null && stack.isEmpty()) || (itemArg != null && itemArg.getItem().equals(stack.getItem())) ) - { - Value res = new NumericValue(i); - return (_c, _t) -> res; - } + return new NumericValue(i); } - return (_c, _t) -> Value.NULL; + return Value.NULL; }); //inventory_remove(, , ) -> bool - expression.addLazyFunction("inventory_remove", -1, (c, t, lv) -> + expression.addContextFunction("inventory_remove", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) - return (_c, _t) -> Value.NULL; + if (inventoryLocator == null) return Value.NULL; if (lv.size() <= inventoryLocator.offset) throw new InternalExpressionException("'inventory_remove' requires at least an item to be removed"); - ItemStackArgument searchItem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset).evalValue(c).getString()); + ItemStackArgument searchItem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset).getString()); int amount = 1; if (lv.size() > inventoryLocator.offset+1) - { - amount = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset+1).evalValue(c)).getLong(); - } + amount = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset+1)).getLong(); // not enough if (((amount == 1) && (!inventoryLocator.inventory.containsAny(Sets.newHashSet(searchItem.getItem())))) - || (inventoryLocator.inventory.count(searchItem.getItem()) < amount)) - { - return (_c, _t) -> Value.FALSE; - } + || (inventoryLocator.inventory.count(searchItem.getItem()) < amount)) return Value.FALSE; for (int i = 0, maxi = inventoryLocator.inventory.size(); i < maxi; i++) { ItemStack stack = inventoryLocator.inventory.getStack(i); @@ -372,7 +326,7 @@ public class Inventories { stack.setCount(left); inventoryLocator.inventory.setStack(i, stack); syncPlayerInventory(inventoryLocator, i); - return (_c, _t) -> Value.TRUE; + return Value.TRUE; } else { @@ -383,37 +337,30 @@ public class Inventories { } if (amount > 0) throw new InternalExpressionException("Something bad happened - cannot pull all items from inventory"); - return (_c, _t) -> Value.TRUE; + return Value.TRUE; }); //inventory_drop(, , ) -> entity_item (and sets slot) or null if cannot - expression.addLazyFunction("drop_item", -1, (c, t, lv) -> + expression.addContextFunction("drop_item", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) - return (_c, _t) -> Value.NULL; + if (inventoryLocator == null) return Value.NULL; if (lv.size() == inventoryLocator.offset) throw new InternalExpressionException("Slot number is required for inventory_drop"); - int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset).evalValue(c)).getLong(); + int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset)).getLong(); slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory); - if (slot == inventoryLocator.inventory.size()) - return (_c, _t) -> Value.NULL; + if (slot == inventoryLocator.inventory.size()) return Value.NULL; int amount = 0; if (lv.size() > inventoryLocator.offset+1) - amount = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset+1).evalValue(c)).getLong(); + amount = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset+1)).getLong(); if (amount < 0) throw new InternalExpressionException("Cannot throw negative number of items"); ItemStack stack = inventoryLocator.inventory.getStack(slot); - if (stack == null || stack.isEmpty()) - return (_c, _t) -> Value.ZERO; - if (amount == 0) - amount = stack.getCount(); + if (stack == null || stack.isEmpty()) return Value.ZERO; + if (amount == 0) amount = stack.getCount(); ItemStack droppedStack = inventoryLocator.inventory.removeStack(slot, amount); - if (droppedStack.isEmpty()) - { - return (_c, _t) -> Value.ZERO; - } + if (droppedStack.isEmpty()) return Value.ZERO; Object owner = inventoryLocator.owner; ItemEntity item; if (owner instanceof PlayerEntity) @@ -438,8 +385,7 @@ public class Inventories { item.setToDefaultPickupDelay(); cc.s.getWorld().spawnEntity(item); } - Value res = new NumericValue(item.getStack().getCount()); - return (_c, _t) -> res; + return new NumericValue(item.getStack().getCount()); }); } diff --git a/src/main/java/carpet/script/api/Monitoring.java b/src/main/java/carpet/script/api/Monitoring.java index a3b97b9b..fac14276 100644 --- a/src/main/java/carpet/script/api/Monitoring.java +++ b/src/main/java/carpet/script/api/Monitoring.java @@ -25,31 +25,29 @@ public class Monitoring { public static void apply(Expression expression) { - expression.addLazyFunction("system_info", -1, (c, t, lv) -> + expression.addContextFunction("system_info", -1, (c, t, lv) -> { if (lv.size() == 0) { - Value ret = SystemInfo.getAll((CarpetContext) c); - return (cc, tt) -> ret; + return SystemInfo.getAll((CarpetContext) c); } if (lv.size() == 1) { - String what = lv.get(0).evalValue(c).getString(); + String what = lv.get(0).getString(); Value res = SystemInfo.get(what, (CarpetContext) c); if (res == null) throw new InternalExpressionException("Unknown option for 'system_info': " + what); - return (cc, tt) -> res; + return res; } throw new InternalExpressionException("'system_info' requires one or no parameters"); }); // game processed snooper functions - expression.addLazyFunction("get_mob_counts", -1, (c, t, lv) -> + expression.addContextFunction("get_mob_counts", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); SpawnHelper.Info info = world.getChunkManager().getSpawnInfo(); - if (info == null) return LazyValue.NULL; + if (info == null) return Value.NULL; Object2IntMap mobcounts = info.getGroupToCount(); int chunks = ((SpawnHelperInnerInterface)info).cmGetChunkCount(); - Value retVal; if (lv.size() == 0) { Map retDict = new HashMap<>(); @@ -63,19 +61,15 @@ public class Monitoring { new NumericValue(currentCap)) ); } - retVal = MapValue.wrap(retDict); + return MapValue.wrap(retDict); } - else - { - String catString = lv.get(0).evalValue(c).getString(); - SpawnGroup cat = SpawnGroup.byName(catString.toLowerCase(Locale.ROOT)); - if (cat == null) throw new InternalExpressionException("Unreconized mob category: "+catString); - retVal = ListValue.of( - new NumericValue(mobcounts.getInt(cat)), - new NumericValue((int)(cat.getCapacity() * chunks / SpawnReporter.currentMagicNumber())) - ); - } - return (_c, _t) -> retVal; + String catString = lv.get(0).getString(); + SpawnGroup cat = SpawnGroup.byName(catString.toLowerCase(Locale.ROOT)); + if (cat == null) throw new InternalExpressionException("Unreconized mob category: "+catString); + return ListValue.of( + new NumericValue(mobcounts.getInt(cat)), + new NumericValue((int)(cat.getCapacity() * chunks / SpawnReporter.currentMagicNumber())) + ); }); } } diff --git a/src/main/java/carpet/script/api/Scoreboards.java b/src/main/java/carpet/script/api/Scoreboards.java index a83812cf..c81128a1 100644 --- a/src/main/java/carpet/script/api/Scoreboards.java +++ b/src/main/java/carpet/script/api/Scoreboards.java @@ -64,77 +64,68 @@ public class Scoreboards { { // scoreboard(player,'objective') // scoreboard(player, objective, newValue) - expression.addLazyFunction("scoreboard", -1, (c, t, lv) -> + expression.addContextFunction("scoreboard", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); if (lv.size()==0) - { - Value ret = ListValue.wrap(scoreboard.getObjectiveNames().stream().map(StringValue::new).collect(Collectors.toList())); - return (_c, _t) -> ret; - } - String objectiveName = lv.get(0).evalValue(c).getString(); + return ListValue.wrap(scoreboard.getObjectiveNames().stream().map(StringValue::new).collect(Collectors.toList())); + String objectiveName = lv.get(0).getString(); ScoreboardObjective objective = scoreboard.getObjective(objectiveName); - if (objective == null) return LazyValue.NULL; + if (objective == null) return Value.NULL; if (lv.size()==1) + return ListValue.wrap(scoreboard.getAllPlayerScores(objective).stream().map(s -> new StringValue(s.getPlayerName())).collect(Collectors.toList())); + String key = getScoreboardKeyFromValue(lv.get(1)); + if(lv.size()==2) { - Value ret = ListValue.wrap(scoreboard.getAllPlayerScores(objective).stream().map(s -> new StringValue(s.getPlayerName())).collect(Collectors.toList())); - return (_c, _t) -> ret; + if(!scoreboard.playerHasObjective(key, objective)) return Value.NULL; + return NumericValue.of(scoreboard.getPlayerScore(key,objective).getScore()); } - String key = getScoreboardKeyFromValue(lv.get(1).evalValue(c)); - if(lv.size()==2) { - if(scoreboard.playerHasObjective(key, objective)) { - return (_c,_t) -> NumericValue.of(scoreboard.getPlayerScore(key,objective).getScore()); - } - return LazyValue.NULL; - } - - Value value = lv.get(2).evalValue(c); + Value value = lv.get(2); if(value.isNull()) { ScoreboardPlayerScore score = scoreboard.getPlayerScore(key, objective); scoreboard.resetPlayerScore(key,objective); - return (_c,_t) -> NumericValue.of(score.getScore()); + return NumericValue.of(score.getScore()); } if (value instanceof NumericValue) { ScoreboardPlayerScore score = scoreboard.getPlayerScore(key, objective); score.setScore(NumericValue.asNumber(value).getInt()); - return (_c,_t) -> NumericValue.of(score.getScore()); + return NumericValue.of(score.getScore()); } throw new InternalExpressionException("'scoreboard' requires a number or null as the third parameter"); }); - expression.addLazyFunction("scoreboard_remove", -1, (c, t, lv)-> + expression.addContextFunction("scoreboard_remove", -1, (c, t, lv)-> { if (lv.size()==0) throw new InternalExpressionException("'scoreboard_remove' requires at least one parameter"); CarpetContext cc = (CarpetContext)c; Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); - String objectiveName = lv.get(0).evalValue(c).getString(); + String objectiveName = lv.get(0).getString(); ScoreboardObjective objective = scoreboard.getObjective(objectiveName); - if (objective == null) - return LazyValue.FALSE; + if (objective == null) return Value.FALSE; if (lv.size() == 1) { scoreboard.removeObjective(objective); - return LazyValue.TRUE; + return Value.TRUE; } - String key = getScoreboardKeyFromValue(lv.get(1).evalValue(c)); - if (!scoreboard.playerHasObjective(key, objective)) return LazyValue.NULL; + String key = getScoreboardKeyFromValue(lv.get(1)); + if (!scoreboard.playerHasObjective(key, objective)) return Value.NULL; ScoreboardPlayerScore scoreboardPlayerScore = scoreboard.getPlayerScore(key, objective); Value previous = new NumericValue(scoreboardPlayerScore.getScore()); scoreboard.resetPlayerScore(key, objective); - return (c_, t_) -> previous; + return previous; }); // objective_add('lvl','level') // objective_add('counter') - expression.addLazyFunction("scoreboard_add", -1, (c, t, lv)-> + expression.addContextFunction("scoreboard_add", -1, (c, t, lv)-> { CarpetContext cc = (CarpetContext)c; Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); if (lv.size() == 0 || lv.size()>2) throw new InternalExpressionException("'scoreboard_add' should have one or two parameters"); - String objectiveName = lv.get(0).evalValue(c).getString(); + String objectiveName = lv.get(0).getString(); ScoreboardCriterion criterion; if (lv.size() == 1 ) { @@ -142,7 +133,7 @@ public class Scoreboards { } else { - String critetionName = lv.get(1).evalValue(c).getString(); + String critetionName = lv.get(1).getString(); criterion = ScoreboardCriterion.createStatCriterion(critetionName).orElse(null); if (criterion==null) { @@ -153,62 +144,62 @@ public class Scoreboards { ScoreboardObjective objective = scoreboard.getObjective(objectiveName); if (objective != null) { c.host.issueDeprecation("reading or modifying an objective's criterion with scoreboard_add"); - if(lv.size() == 1) return (_c, _t) -> StringValue.of(objective.getCriterion().getName()); - if(objective.getCriterion().equals(criterion) || lv.size() == 1) return LazyValue.NULL; + if(lv.size() == 1) return StringValue.of(objective.getCriterion().getName()); + if(objective.getCriterion().equals(criterion) || lv.size() == 1) return Value.NULL; ((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().get(objective.getCriterion()).remove(objective); ((ScoreboardObjective_scarpetMixin) objective).setCriterion(criterion); (((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().computeIfAbsent(criterion, (criterion1) -> Lists.newArrayList())).add(objective); scoreboard.updateObjective(objective); - return LazyValue.FALSE; + return Value.FALSE; } scoreboard.addObjective(objectiveName, criterion, new LiteralText(objectiveName), criterion.getCriterionType()); - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("scoreboard_property", -1, (c, t, lv) -> + expression.addContextFunction("scoreboard_property", -1, (c, t, lv) -> { if(lv.size() < 2) throw new InternalExpressionException("'scoreboard_property' requires at least two parameters"); CarpetContext cc = (CarpetContext)c; Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); - ScoreboardObjective objective = scoreboard.getObjective(lv.get(0).evalValue(c).getString()); - if(objective == null) return LazyValue.NULL; + ScoreboardObjective objective = scoreboard.getObjective(lv.get(0).getString()); + if(objective == null) return Value.NULL; boolean modify = lv.size() > 2; Value setValue = null; if(modify) { - setValue = lv.get(2).evalValue(c); + setValue = lv.get(2); } - String property = lv.get(1).evalValue(c).getString(); + String property = lv.get(1).getString(); switch (property) { case "criterion": if(modify) { ScoreboardCriterion criterion = ScoreboardCriterion.createStatCriterion(setValue.getString()).orElse(null); if (criterion==null) throw new InternalExpressionException("Unknown scoreboard criterion: "+ setValue.getString()); - if(objective.getCriterion().equals(criterion) || lv.size() == 1) return LazyValue.FALSE; + if(objective.getCriterion().equals(criterion) || lv.size() == 1) return Value.FALSE; ((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().get(objective.getCriterion()).remove(objective); ((ScoreboardObjective_scarpetMixin) objective).setCriterion(criterion); (((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().computeIfAbsent(criterion, (criterion1) -> Lists.newArrayList())).add(objective); scoreboard.updateObjective(objective); - return LazyValue.TRUE; + return Value.TRUE; } - return (_c, _t) -> StringValue.of(objective.getCriterion().getName()); + return StringValue.of(objective.getCriterion().getName()); case "display_name": if(modify) { Text text = FormattedTextValue.getTextByValue(setValue); objective.setDisplayName(text); - return LazyValue.TRUE; + return Value.TRUE; } - return (_c, _t) -> new FormattedTextValue(objective.getDisplayName()); + return new FormattedTextValue(objective.getDisplayName()); case "display_slot": if(modify) { int slotId = Scoreboard.getDisplaySlotId(setValue.getString()); if(slotId == -1) throw new InternalExpressionException("Unknown scoreboard display slot: " + setValue.getString()); if(objective.equals(scoreboard.getObjectiveForSlot(slotId))) { - return LazyValue.FALSE; + return Value.FALSE; } scoreboard.setObjectiveSlot(slotId,objective); - return LazyValue.TRUE; + return Value.TRUE; } List slots = new ArrayList<>(); @@ -218,325 +209,247 @@ public class Scoreboards { slots.add(StringValue.of(slotName)); } } - return (_c, _t) -> ListValue.wrap(slots); + return ListValue.wrap(slots); case "render_type": if(modify) { ScoreboardCriterion.RenderType renderType = ScoreboardCriterion.RenderType.getType(setValue.getString().toLowerCase()); - if(objective.getRenderType().equals(renderType)) return LazyValue.FALSE; + if(objective.getRenderType().equals(renderType)) return Value.FALSE; objective.setRenderType(renderType); - return LazyValue.TRUE; + return Value.TRUE; } - return (_c, _t) -> StringValue.of(objective.getRenderType().getName()); + return StringValue.of(objective.getRenderType().getName()); default: throw new InternalExpressionException("scoreboard property '" + property + "' is not a valid property"); } }); - expression.addLazyFunction("scoreboard_display", 2, (c, t, lv) -> + expression.addContextFunction("scoreboard_display", 2, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); - String location = lv.get(0).evalValue(c).getString(); + String location = lv.get(0).getString(); int slot = Scoreboard.getDisplaySlotId(location); if (slot < 0) throw new InternalExpressionException("Invalid objective slot: "+location); - Value target = lv.get(1).evalValue(c); + Value target = lv.get(1); if (target instanceof NullValue) { scoreboard.setObjectiveSlot(slot, null); - return (_c, _t) -> new NumericValue(slot); + return new NumericValue(slot); } String objectiveString = target.getString(); ScoreboardObjective objective = scoreboard.getObjective(objectiveString); - if (objective == null) return LazyValue.NULL; + if (objective == null) return Value.NULL; scoreboard.setObjectiveSlot(slot, objective); - return (_c, _t) -> new NumericValue(slot); + return new NumericValue(slot); }); - expression.addLazyFunction("team_list", -1, (c, t, lv) -> + expression.addContextFunction("team_list", -1, (c, t, lv) -> { if(lv.size() > 1) throw new InternalExpressionException("'team_list' requires zero or one parameters"); CarpetContext cc = (CarpetContext)c; ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); - if(lv.size() == 0) { - Value ret = ListValue.wrap(scoreboard.getTeamNames().stream().map(StringValue::of).collect(Collectors.toList())); - return (_c, _t) -> ret; - } else if(lv.size() == 1) { - Team team = scoreboard.getTeam(lv.get(0).evalValue(c).getString()); - if(team == null) return LazyValue.NULL; - Value ret = ListValue.wrap(team.getPlayerList().stream().map(StringValue::of).collect(Collectors.toList())); - return (_c, _t) -> ret; - } else { - return LazyValue.NULL; - } + if(lv.size() == 0) + return ListValue.wrap(scoreboard.getTeamNames().stream().map(StringValue::of).collect(Collectors.toList())); + if (lv.size() != 1) return Value.NULL; + Team team = scoreboard.getTeam(lv.get(0).getString()); + if(team == null) return Value.NULL; + return ListValue.wrap(team.getPlayerList().stream().map(StringValue::of).collect(Collectors.toList())); }); - expression.addLazyFunction("team_add", -1, (c, t, lv) -> + expression.addContextFunction("team_add", -1, (c, t, lv) -> { if(!(lv.size() < 3 && lv.size() > 0)) throw new InternalExpressionException("'team_add' requires one or two parameters"); CarpetContext cc = (CarpetContext)c; ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); - String teamName = lv.get(0).evalValue(c).getString(); + String teamName = lv.get(0).getString(); - if(lv.size() == 1) { - if(scoreboard.getTeam(teamName) == null) { - scoreboard.addTeam(teamName); - Value ret = new StringValue(teamName); - return (_c, _t) -> ret; - } else { - return LazyValue.NULL; - } - } else if(lv.size() == 2) { - Value playerVal = lv.get(1).evalValue(c); - - String player = EntityValue.getPlayerNameByValue(playerVal); - if(player == null) return LazyValue.NULL; - - Team team = scoreboard.getTeam(teamName); - if(team == null) return LazyValue.NULL; - - if(team.isEqual(scoreboard.getPlayerTeam(player))) { - return LazyValue.FALSE; - } else { - scoreboard.addPlayerToTeam(player,scoreboard.getTeam(teamName)); - return LazyValue.TRUE; - } - } else { - return LazyValue.NULL; + if(lv.size() == 1) + { + if (scoreboard.getTeam(teamName) != null) return Value.NULL; + scoreboard.addTeam(teamName); + return new StringValue(teamName); } - }); - - expression.addLazyFunction("team_remove", 1, (c, t, lv) -> - { - CarpetContext cc = (CarpetContext)c; - ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); - Value teamVal = lv.get(0).evalValue(c); - - String team = teamVal.getString(); - - if(scoreboard.getTeam(team) != null) { - scoreboard.removeTeam(scoreboard.getTeam(team)); - return LazyValue.TRUE; - } else { - return LazyValue.NULL; - } - }); - - - expression.addLazyFunction("team_leave", 1, (c, t, lv) -> - { - CarpetContext cc = (CarpetContext)c; - ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); - Value playerVal = lv.get(0).evalValue(c); - + if(lv.size() != 2) return Value.NULL; + Value playerVal = lv.get(1); String player = EntityValue.getPlayerNameByValue(playerVal); - if(player == null) return LazyValue.NULL; - - Value ret = new NumericValue(scoreboard.clearPlayerTeam(player)); - return (_c, _t) -> ret; + if(player == null) return Value.NULL; + Team team = scoreboard.getTeam(teamName); + if(team == null) return Value.NULL; + if(team.isEqual(scoreboard.getPlayerTeam(player))) return Value.FALSE; + scoreboard.addPlayerToTeam(player,scoreboard.getTeam(teamName)); + return Value.TRUE; }); - expression.addLazyFunction("team_property", -1, (c, t, lv) -> + expression.addContextFunction("team_remove", 1, (c, t, lv) -> + { + CarpetContext cc = (CarpetContext)c; + ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); + Value teamVal = lv.get(0); + String team = teamVal.getString(); + if(scoreboard.getTeam(team) == null) return Value.NULL; + scoreboard.removeTeam(scoreboard.getTeam(team)); + return Value.TRUE; + }); + + + expression.addContextFunction("team_leave", 1, (c, t, lv) -> + { + CarpetContext cc = (CarpetContext)c; + ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); + Value playerVal = lv.get(0); + String player = EntityValue.getPlayerNameByValue(playerVal); + if(player == null) return Value.NULL; + return new NumericValue(scoreboard.clearPlayerTeam(player)); + }); + + expression.addContextFunction("team_property", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); if(lv.size() < 2 || lv.size() > 3) throw new InternalExpressionException("'team_property' requires two or three arguments"); - Value teamVal = lv.get(0).evalValue(c); - Value propertyVal = lv.get(1).evalValue(c); + Value teamVal = lv.get(0); + Value propertyVal = lv.get(1); Value settingVal = null; boolean modifying = false; - if(lv.size() == 3) { + if(lv.size() == 3) + { modifying = true; - settingVal = lv.get(2).evalValue(c); + settingVal = lv.get(2); } Team team = scoreboard.getTeam(teamVal.getString()); - if(team == null) return LazyValue.NULL; + if(team == null) return Value.NULL; if(!(propertyVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the second argument"); switch (propertyVal.getString()) { case "collisionRule": - if(!modifying) { - Value ret = new StringValue(team.getCollisionRule().name); - return (_c, _t) -> ret; - } - + if(!modifying) return new StringValue(team.getCollisionRule().name); if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); - AbstractTeam.CollisionRule collisionRule = AbstractTeam.CollisionRule.getRule(settingVal.getString()); if(collisionRule == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); team.setCollisionRule(collisionRule); break; case "color": - if(!modifying) { - Value ret = new StringValue(team.getColor().getName()); - return (_c, _t) -> ret; - } - + if(!modifying) return new StringValue(team.getColor().getName()); if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); - Formatting color = Formatting.byName(settingVal.getString().toUpperCase()); if(color == null || !color.isColor()) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); team.setColor(color); - break; case "deathMessageVisibility": - if(!modifying) { - Value ret = new StringValue(team.getDeathMessageVisibilityRule().name); - return (_c, _t) -> ret; - } - + if(!modifying) return new StringValue(team.getDeathMessageVisibilityRule().name); if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); - AbstractTeam.VisibilityRule deathMessageVisibility = AbstractTeam.VisibilityRule.getRule(settingVal.getString()); if(deathMessageVisibility == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); team.setDeathMessageVisibilityRule(deathMessageVisibility); - break; case "displayName": - if(!modifying) { - Value ret = new FormattedTextValue(team.getDisplayName()); - return (_c, _t) -> ret; - } - + if(!modifying) return new FormattedTextValue(team.getDisplayName()); if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string or formatted text as the third argument for the property " + propertyVal.getString()); - Text displayName; - displayName = FormattedTextValue.getTextByValue(settingVal); - team.setDisplayName(displayName); - break; case "friendlyFire": - if(!modifying) { - Value ret = new NumericValue(team.isFriendlyFireAllowed()); - return (_c, _t) -> ret; - } - + if(!modifying) return new NumericValue(team.isFriendlyFireAllowed()); if(!(settingVal instanceof NumericValue)) throw new InternalExpressionException("'team_property' requires a boolean as the third argument for the property " + propertyVal.getString()); - boolean friendlyFire = settingVal.getBoolean(); team.setFriendlyFireAllowed(friendlyFire); break; case "nametagVisibility": - if(!modifying) { - Value ret = new StringValue(team.getNameTagVisibilityRule().name); - return (_c, _t) -> ret; - } - + if(!modifying) return new StringValue(team.getNameTagVisibilityRule().name); if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); - AbstractTeam.VisibilityRule nametagVisibility = AbstractTeam.VisibilityRule.getRule(settingVal.getString()); if(nametagVisibility == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); team.setNameTagVisibilityRule(nametagVisibility); break; case "prefix": - if(!modifying) { - Value ret = new FormattedTextValue(team.getPrefix()); - return (_c, _t) -> ret; - } - + if(!modifying) return new FormattedTextValue(team.getPrefix()); if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property ' requires a string or formatted text as the third argument for the property " + propertyVal.getString()); - Text prefix; - prefix = FormattedTextValue.getTextByValue(settingVal); - team.setPrefix(prefix); break; case "seeFriendlyInvisibles": - if(!modifying) { - Value ret = new NumericValue(team.shouldShowFriendlyInvisibles()); - return (_c, _t) -> ret; - } - + if(!modifying) return new NumericValue(team.shouldShowFriendlyInvisibles()); if(!(settingVal instanceof NumericValue)) throw new InternalExpressionException("'team_property' requires a boolean as the third argument for the property " + propertyVal.getString()); - boolean seeFriendlyInvisibles = settingVal.getBoolean(); team.setShowFriendlyInvisibles(seeFriendlyInvisibles); - break; case "suffix": - if(!modifying) { - Value ret = new FormattedTextValue(team.getSuffix()); - return (_c, _t) -> ret; - } - + if(!modifying) return new FormattedTextValue(team.getSuffix()); if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string or formatted text as the third argument for the property " + propertyVal.getString()); - Text suffix; - suffix = FormattedTextValue.getTextByValue(settingVal); - team.setSuffix(suffix); break; default: throw new InternalExpressionException("team property '" + propertyVal.getString() + "' is not a valid property"); } - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("bossbar", -1, (c, t, lv) -> + expression.addContextFunction("bossbar", -1, (c, t, lv) -> { BossBarManager bossBarManager = ((CarpetContext)c).s.getMinecraftServer().getBossBarManager(); if(lv.size() > 3) throw new InternalExpressionException("'bossbar' accepts max three arguments"); - if(lv.size() == 0) { - Value ret = ListValue.wrap(bossBarManager.getAll().stream().map(CommandBossBar::getId).map(Identifier::toString).map(StringValue::of).collect(Collectors.toList())); - return (_c, _t) -> ret; - } + if(lv.size() == 0) return ListValue.wrap(bossBarManager.getAll().stream().map(CommandBossBar::getId).map(Identifier::toString).map(StringValue::of).collect(Collectors.toList())); - String id = lv.get(0).evalValue(c).getString(); + String id = lv.get(0).getString(); Identifier identifier; - try { + try + { identifier = new Identifier(id); - } catch (InvalidIdentifierException invalidIdentifierException) { - return LazyValue.NULL; + } + catch (InvalidIdentifierException invalidIdentifierException) + { + return Value.NULL; } - if(lv.size() == 1) { - if(bossBarManager.get(identifier) != null) return LazyValue.FALSE; - Value ret = StringValue.of(bossBarManager.add(identifier,new LiteralText(id)).getId().toString()); - return (_c, _t) -> ret; + if(lv.size() == 1) + { + if(bossBarManager.get(identifier) != null) return Value.FALSE; + return StringValue.of(bossBarManager.add(identifier,new LiteralText(id)).getId().toString()); } - String property = lv.get(1).evalValue(c).getString(); + String property = lv.get(1).getString(); CommandBossBar bossBar = bossBarManager.get(identifier); - if(bossBar == null) return LazyValue.NULL; + if(bossBar == null) return Value.NULL; - Value propertyValue = (lv.size() == 3)?lv.get(2).evalValue(c):null; + Value propertyValue = (lv.size() == 3)?lv.get(2):null; switch (property) { case "color": if(propertyValue == null) { BossBar.Color color = (bossBar).getColor(); - if(color == null) return LazyValue.NULL; - return (_c, _t) -> StringValue.of(color.getName()); + if(color == null) return Value.NULL; + return StringValue.of(color.getName()); } BossBar.Color color = BossBar.Color.byName(propertyValue.getString()); - if(color == null) return LazyValue.NULL; + if(color == null) return Value.NULL; bossBar.setColor(BossBar.Color.byName(propertyValue.getString())); - return LazyValue.TRUE; + return Value.TRUE; case "max": - if(propertyValue == null) return (_c, _t) -> NumericValue.of(bossBar.getMaxValue()); + if(propertyValue == null) return NumericValue.of(bossBar.getMaxValue()); if(!(propertyValue instanceof NumericValue)) throw new InternalExpressionException("'bossbar' requires a number as the value for the property " + property); bossBar.setMaxValue(((NumericValue) propertyValue).getInt()); - return LazyValue.TRUE; + return Value.TRUE; case "name": - if(propertyValue == null) return (_c, _t) -> new FormattedTextValue(bossBar.getName()); + if(propertyValue == null) return new FormattedTextValue(bossBar.getName()); bossBar.setName(FormattedTextValue.getTextByValue(propertyValue)); - return LazyValue.TRUE; + return Value.TRUE; case "add_player": if(propertyValue == null) throw new InternalExpressionException("Bossbar property " + property + " can't be queried, add a third parameter"); @@ -545,27 +458,25 @@ public class Scoreboards { ServerPlayerEntity player = EntityValue.getPlayerByValue(((CarpetContext)c).s.getMinecraftServer(),propertyValue); if(player != null) bossBar.addPlayer(player); }); - return LazyValue.TRUE; + return Value.TRUE; } ServerPlayerEntity player = EntityValue.getPlayerByValue(((CarpetContext) c).s.getMinecraftServer(), propertyValue); if(player != null) { bossBar.addPlayer(player); - return LazyValue.TRUE; + return Value.TRUE; } - return LazyValue.FALSE; + return Value.FALSE; case "players": - if(propertyValue == null) { - return (_c, _t) -> ListValue.wrap(bossBar.getPlayers().stream().map(EntityValue::new).collect(Collectors.toList())); - } - - if(propertyValue instanceof ListValue) { + if (propertyValue == null) return ListValue.wrap(bossBar.getPlayers().stream().map(EntityValue::new).collect(Collectors.toList())); + if(propertyValue instanceof ListValue) + { bossBar.clearPlayers(); ((ListValue) propertyValue).getItems().forEach((v) -> { ServerPlayerEntity p = EntityValue.getPlayerByValue(((CarpetContext) c).s.getMinecraftServer(), v); if (p != null) bossBar.addPlayer(p); }); - return LazyValue.TRUE; + return Value.TRUE; } @@ -573,32 +484,29 @@ public class Scoreboards { bossBar.clearPlayers(); if (p != null) { bossBar.addPlayer(p); - return LazyValue.TRUE; + return Value.TRUE; } - return LazyValue.FALSE; + return Value.FALSE; case "style": - if(propertyValue == null) { - return (_c, _t) -> StringValue.of(bossBar.getOverlay().getName()); - } - + if(propertyValue == null) return StringValue.of(bossBar.getOverlay().getName()); BossBar.Style style = BossBar.Style.byName(propertyValue.getString()); if(style == null) throw new InternalExpressionException("'" + propertyValue.getString() + "' is not a valid value for property " + property); bossBar.setOverlay(style); - return LazyValue.TRUE; + return Value.TRUE; case "value": - if(propertyValue == null) return (_c, _t) -> NumericValue.of(bossBar.getValue()); + if(propertyValue == null) return NumericValue.of(bossBar.getValue()); if(!(propertyValue instanceof NumericValue)) throw new InternalExpressionException("'bossbar' requires a number as the value for the property " + property); bossBar.setValue(((NumericValue) propertyValue).getInt()); - return LazyValue.TRUE; + return Value.TRUE; case "visible": - if(propertyValue == null) return (_c, _t) -> new NumericValue(bossBar.isVisible()); + if(propertyValue == null) return new NumericValue(bossBar.isVisible()); bossBar.setVisible(propertyValue.getBoolean()); - return LazyValue.TRUE; + return Value.TRUE; case "remove": bossBarManager.remove(bossBar); - return LazyValue.TRUE; + return Value.TRUE; default: throw new InternalExpressionException("Unknown bossbar property " + property); } diff --git a/src/main/java/carpet/script/api/Threading.java b/src/main/java/carpet/script/api/Threading.java index c17a3ad0..206977c5 100644 --- a/src/main/java/carpet/script/api/Threading.java +++ b/src/main/java/carpet/script/api/Threading.java @@ -15,16 +15,16 @@ public class Threading public static void apply(Expression expression) { //"overidden" native call to cancel if on main thread - expression.addLazyFunction("task_join", 1, (c, t, lv) -> { + expression.addContextFunction("task_join", 1, (c, t, lv) -> { if (((CarpetContext)c).s.getMinecraftServer().isOnThread()) throw new InternalExpressionException("'task_join' cannot be called from main thread to avoid deadlocks"); - Value v = lv.get(0).evalValue(c); + Value v = lv.get(0); if (!(v instanceof ThreadValue)) throw new InternalExpressionException("'task_join' could only be used with a task value"); - Value ret = ((ThreadValue) v).join(); - return (_c, _t) -> ret; + return ((ThreadValue) v).join(); }); + // has to be lazy due to deferred execution of the expression expression.addLazyFunctionWithDelegation("task_dock", 1, (c, t, expr, tok, lv) -> { CarpetContext cc = (CarpetContext)c; MinecraftServer server = cc.s.getMinecraftServer(); diff --git a/src/main/java/carpet/script/api/WorldAccess.java b/src/main/java/carpet/script/api/WorldAccess.java index 40f9c3ce..fcab18ee 100644 --- a/src/main/java/carpet/script/api/WorldAccess.java +++ b/src/main/java/carpet/script/api/WorldAccess.java @@ -24,6 +24,7 @@ import carpet.script.exception.Throwables; import carpet.script.utils.BiomeInfo; import carpet.script.utils.WorldTools; import carpet.script.value.BlockValue; +import carpet.script.value.BooleanValue; import carpet.script.value.EntityValue; import carpet.script.value.ListValue; import carpet.script.value.MapValue; @@ -127,33 +128,27 @@ public class WorldAccess { }}; // dummy entity for dummy requirements in the loot tables (see snowball) private static FallingBlockEntity DUMMY_ENTITY = null; - private static LazyValue booleanStateTest( + private static Value booleanStateTest( Context c, String name, - List params, + List params, BiFunction test ) { CarpetContext cc = (CarpetContext) c; if (params.size() == 0) - { throw new InternalExpressionException("'" + name + "' requires at least one parameter"); - } - Value v0 = params.get(0).evalValue(c); + Value v0 = params.get(0); if (v0 instanceof BlockValue) - { - Value retval = test.apply(((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos()) ? Value.TRUE : Value.FALSE; - return (c_, t_) -> retval; - } + return BooleanValue.of(test.apply(((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos())); BlockValue block = BlockArgument.findIn(cc, params, 0).block; - Value retval = test.apply(block.getBlockState(), block.getPos()) ? Value.TRUE : Value.FALSE; - return (c_, t_) -> retval; + return BooleanValue.of(test.apply(block.getBlockState(), block.getPos())); } - private static LazyValue stateStringQuery( + private static Value stateStringQuery( Context c, String name, - List params, + List params, BiFunction test ) { @@ -163,38 +158,32 @@ public class WorldAccess { throw new InternalExpressionException("'" + name + "' requires at least one parameter"); } - Value v0 = params.get(0).evalValue(c); + Value v0 = params.get(0); if (v0 instanceof BlockValue) { String strVal = test.apply( ((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos()); - Value retval = strVal != null ? new StringValue(strVal) : Value.NULL; - return (c_, t_) -> retval; + return StringValue.of(strVal); } BlockValue block = BlockArgument.findIn(cc, params, 0).block; - String strVal = test.apply(block.getBlockState(), block.getPos()); - Value retval = strVal != null ? new StringValue(strVal) : Value.NULL; - return (c_, t_) -> retval; + return StringValue.of(test.apply(block.getBlockState(), block.getPos())); } - private static LazyValue genericStateTest( + private static Value genericStateTest( Context c, String name, - List params, + List params, Fluff.TriFunction test ) { CarpetContext cc = (CarpetContext) c; if (params.size() == 0) - { throw new InternalExpressionException("'" + name + "' requires at least one parameter"); - } - Value v0 = params.get(0).evalValue(c); + Value v0 = params.get(0); if (v0 instanceof BlockValue) { try { - Value retval = test.apply(((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos(), cc.s.getWorld()); - return (_c, _t) -> retval; + return test.apply(((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos(), cc.s.getWorld()); } catch (NullPointerException ignored) { @@ -202,8 +191,7 @@ public class WorldAccess { } } BlockValue block = BlockArgument.findIn(cc, params, 0).block; - Value retval = test.apply(block.getBlockState(), block.getPos(), cc.s.getWorld()); - return (c_, t_) -> retval; + return test.apply(block.getBlockState(), block.getPos(), cc.s.getWorld()); } private static > BlockState setProperty(Property property, String name, String value, @@ -272,7 +260,7 @@ public class WorldAccess { public static void apply(Expression expression) { - expression.addLazyFunction("block", -1, (c, t, lv) -> + expression.addContextFunction("block", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; if (lv.size() == 0) @@ -283,25 +271,19 @@ public class WorldAccess { // fixing block state and data retval.getBlockState(); retval.getData(); - return (c_, t_) -> retval; + return retval; }); - expression.addLazyFunction("block_data", -1, (c, t, lv) -> + expression.addContextFunction("block_data", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; if (lv.size() == 0) - { throw new InternalExpressionException("Block requires at least one parameter"); - } - CompoundTag tag = BlockArgument.findIn(cc, lv, 0, true).block.getData(); - if (tag == null) - return (c_, t_) -> Value.NULL; - Value retval = new NBTSerializableValue(tag); - return (c_, t_) -> retval; + CompoundTag tag = BlockArgument.findIn( (CarpetContext) c, lv, 0, true).block.getData(); + return NBTSerializableValue.of(tag); }); // poi_get(pos, radius?, type?, occupation?, column_mode?) - expression.addLazyFunction("poi", -1, (c, t, lv) -> + expression.addContextFunction("poi", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; if (lv.size() == 0) throw new InternalExpressionException("'poi' requires at least one parameter"); @@ -311,7 +293,7 @@ public class WorldAccess { if (lv.size() == locator.offset) { PointOfInterestType poiType = store.getType(pos).orElse(null); - if (poiType == null) return LazyValue.NULL; + if (poiType == null) return Value.NULL; // this feels wrong, but I don't want to mix-in more than I really need to. // also distance adds 0.5 to each point which screws up accurate distance calculations @@ -323,21 +305,20 @@ public class WorldAccess { PointOfInterestStorage.OccupationStatus.ANY ).filter(p -> p.getPos().equals(pos)).findFirst().orElse(null); if (poi == null) - return LazyValue.NULL; - Value ret = ListValue.of( + return Value.NULL; + return ListValue.of( new StringValue(poi.getType().toString()), new NumericValue(poiType.getTicketCount() - ((PointOfInterest_scarpetMixin)poi).getFreeTickets()) ); - return (_c, _t) -> ret; } - int radius = NumericValue.asNumber(lv.get(locator.offset+0).evalValue(c)).getInt(); - if (radius < 0) return ListValue.lazyEmpty(); + int radius = NumericValue.asNumber(lv.get(locator.offset+0)).getInt(); + if (radius < 0) return ListValue.of(); Predicate condition = PointOfInterestType.ALWAYS_TRUE; PointOfInterestStorage.OccupationStatus status = PointOfInterestStorage.OccupationStatus.ANY; boolean inColumn = false; if (locator.offset + 1 < lv.size()) { - String poiType = lv.get(locator.offset+1).evalValue(c).getString().toLowerCase(Locale.ROOT); + String poiType = lv.get(locator.offset+1).getString().toLowerCase(Locale.ROOT); if (!"any".equals(poiType)) { PointOfInterestType type = Registry.POINT_OF_INTEREST_TYPE.getOrEmpty(new Identifier(poiType)) @@ -346,7 +327,7 @@ public class WorldAccess { } if (locator.offset + 2 < lv.size()) { - String statusString = lv.get(locator.offset+2).evalValue(c).getString().toLowerCase(Locale.ROOT); + String statusString = lv.get(locator.offset+2).getString().toLowerCase(Locale.ROOT); if ("occupied".equals(statusString)) status = PointOfInterestStorage.OccupationStatus.IS_OCCUPIED; else if ("available".equals(statusString)) @@ -357,42 +338,37 @@ public class WorldAccess { ); if (locator.offset + 3 < lv.size()) { - inColumn = lv.get(locator.offset+3).evalValue(c, Context.BOOLEAN).getBoolean(); + inColumn = lv.get(locator.offset+3).getBoolean(); } } } Stream pois = inColumn? store.getInSquare(condition, pos, radius, status): store.getInCircle(condition, pos, radius, status); - Value ret = ListValue.wrap(pois.sorted(Comparator.comparingDouble(p -> p.getPos().getSquaredDistance(pos))).map(p -> + return ListValue.wrap(pois.sorted(Comparator.comparingDouble(p -> p.getPos().getSquaredDistance(pos))).map(p -> ListValue.of( new StringValue(p.getType().toString()), new NumericValue(p.getType().getTicketCount() - ((PointOfInterest_scarpetMixin)p).getFreeTickets()), ListValue.of(new NumericValue(p.getPos().getX()), new NumericValue(p.getPos().getY()), new NumericValue(p.getPos().getZ())) ) ).collect(Collectors.toList())); - - return (c_, t_) -> ret; }); //poi_set(pos, null) poi_set(pos, type, occupied?, - expression.addLazyFunction("set_poi", -1, (c, t, lv) -> + expression.addContextFunction("set_poi", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext) c; if (lv.size() == 0) throw new InternalExpressionException("'set_poi' requires at least one parameter"); BlockArgument locator = BlockArgument.findIn(cc, lv, 0, false); BlockPos pos = locator.block.getPos(); if (lv.size() < locator.offset) throw new InternalExpressionException("'set_poi' requires the new poi type or null, after position argument"); - Value poi = lv.get(locator.offset+0).evalValue(c); + Value poi = lv.get(locator.offset+0); PointOfInterestStorage store = cc.s.getWorld().getPointOfInterestStorage(); if (poi.isNull()) { // clear poi information - if (store.getType(pos).isPresent()) - { - store.remove(pos); - return LazyValue.TRUE; - } - return LazyValue.FALSE; + if (!store.getType(pos).isPresent()) return Value.FALSE; + store.remove(pos); + return Value.TRUE; } String poiTypeString = poi.getString().toLowerCase(Locale.ROOT); PointOfInterestType type = Registry.POINT_OF_INTEREST_TYPE.getOrEmpty(new Identifier(poiTypeString)) @@ -400,7 +376,7 @@ public class WorldAccess { int occupancy = 0; if (locator.offset + 1 < lv.size()) { - occupancy = (int)NumericValue.asNumber(lv.get(locator.offset + 1).evalValue(c)).getLong(); + occupancy = (int)NumericValue.asNumber(lv.get(locator.offset + 1)).getLong(); if (occupancy < 0) throw new InternalExpressionException("Occupancy cannot be negative"); } if (store.getType(pos).isPresent()) store.remove(pos); @@ -415,20 +391,17 @@ public class WorldAccess { for (int i=0; i < finalO; i++) ((PointOfInterest_scarpetMixin)p).callReserveTicket(); }); } - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("weather",-1,(c, t, lv) -> { + expression.addContextFunction("weather",-1,(c, t, lv) -> { ServerWorld world = ((CarpetContext) c).s.getWorld(); if(lv.size()==0)//cos it can thunder when raining or when clear. - { - Value ret = new StringValue(world.isThundering() ? "thunder" : (world.isRaining() ? "rain" : "clear")); - return (_c, _t) -> ret; - } + return new StringValue(world.isThundering() ? "thunder" : (world.isRaining() ? "rain" : "clear")); - Value weather = lv.get(0).evalValue(c); + Value weather = lv.get(0); ServerWorldProperties worldProperties = ((ServerWorldInterface) world).getWorldPropertiesCM(); if(lv.size()==1) { @@ -446,12 +419,11 @@ public class WorldAccess { default: throw new InternalExpressionException("Weather can only be 'clear', 'rain' or 'thunder'"); } - Value ret = new NumericValue(ticks); - return (_c,_t) -> ret; + return new NumericValue(ticks); } if(lv.size()==2) { - int ticks = NumericValue.asNumber(lv.get(1).evalValue(c), "tick_time in 'weather'").getInt(); + int ticks = NumericValue.asNumber(lv.get(1), "tick_time in 'weather'").getInt(); switch (weather.getString().toLowerCase(Locale.ROOT)) { case "clear": @@ -474,30 +446,26 @@ public class WorldAccess { default: throw new InternalExpressionException("Weather can only be 'clear', 'rain' or 'thunder'"); } - Value ret = NumericValue.of(ticks); - return (_c, _t) -> ret; + return NumericValue.of(ticks); } throw new InternalExpressionException("'weather' requires 0, 1 or 2 arguments"); }); - expression.addLazyFunction("pos", 1, (c, t, lv) -> + expression.addUnaryFunction("pos", v -> { - Value arg = lv.get(0).evalValue(c); - if (arg instanceof BlockValue) + if (v instanceof BlockValue) { - BlockPos pos = ((BlockValue) arg).getPos(); + BlockPos pos = ((BlockValue) v).getPos(); if (pos == null) throw new InternalExpressionException("Cannot fetch position of an unrealized block"); - Value retval = ListValue.of(new NumericValue(pos.getX()), new NumericValue(pos.getY()), new NumericValue(pos.getZ())); - return (c_, t_) -> retval; + return ListValue.of(new NumericValue(pos.getX()), new NumericValue(pos.getY()), new NumericValue(pos.getZ())); } - else if (arg instanceof EntityValue) + else if (v instanceof EntityValue) { - Entity e = ((EntityValue) arg).getEntity(); + Entity e = ((EntityValue) v).getEntity(); if (e == null) throw new InternalExpressionException("Null entity"); - Value retval = ListValue.of(new NumericValue(e.getX()), new NumericValue(e.getY()), new NumericValue(e.getZ())); - return (c_, t_) -> retval; + return ListValue.of(new NumericValue(e.getX()), new NumericValue(e.getY()), new NumericValue(e.getZ())); } else { @@ -505,85 +473,82 @@ public class WorldAccess { } }); - expression.addLazyFunction("pos_offset", -1, (c, t, lv) -> + expression.addContextFunction("pos_offset", -1, (c, t, lv) -> { BlockArgument locator = BlockArgument.findIn((CarpetContext)c, lv, 0); BlockPos pos = locator.block.getPos(); if (lv.size() <= locator.offset) throw new InternalExpressionException("'pos_offset' needs at least position, and direction"); - String directionString = lv.get(locator.offset).evalValue(c).getString(); + String directionString = lv.get(locator.offset).getString(); Direction dir = DIRECTION_MAP.get(directionString); if (dir == null) throw new InternalExpressionException("Unknown direction: "+directionString); int howMuch = 1; if (lv.size() > locator.offset+1) - howMuch = (int) NumericValue.asNumber(lv.get(locator.offset+1).evalValue(c)).getLong(); + howMuch = (int) NumericValue.asNumber(lv.get(locator.offset+1)).getLong(); BlockPos retpos = pos.offset(dir, howMuch); - Value ret = ListValue.of(new NumericValue(retpos.getX()), new NumericValue(retpos.getY()), new NumericValue(retpos.getZ())); - return (cc, tt) -> ret; + return ListValue.of(new NumericValue(retpos.getX()), new NumericValue(retpos.getY()), new NumericValue(retpos.getZ())); }); - expression.addLazyFunction("solid", -1, (c, t, lv) -> + expression.addContextFunction("solid", -1, (c, t, lv) -> genericStateTest(c, "solid", lv, (s, p, w) -> new NumericValue(s.isSolidBlock(w, p)))); // isSimpleFullBlock - expression.addLazyFunction("air", -1, (c, t, lv) -> + expression.addContextFunction("air", -1, (c, t, lv) -> booleanStateTest(c, "air", lv, (s, p) -> s.isAir())); - expression.addLazyFunction("liquid", -1, (c, t, lv) -> + expression.addContextFunction("liquid", -1, (c, t, lv) -> booleanStateTest(c, "liquid", lv, (s, p) -> !s.getFluidState().isEmpty())); - expression.addLazyFunction("flammable", -1, (c, t, lv) -> + expression.addContextFunction("flammable", -1, (c, t, lv) -> booleanStateTest(c, "flammable", lv, (s, p) -> s.getMaterial().isBurnable())); - expression.addLazyFunction("transparent", -1, (c, t, lv) -> + expression.addContextFunction("transparent", -1, (c, t, lv) -> booleanStateTest(c, "transparent", lv, (s, p) -> !s.getMaterial().isSolid())); - /*this.expr.addLazyFunction("opacity", -1, (c, t, lv) -> + /*this.expr.addContextFunction("opacity", -1, (c, t, lv) -> genericStateTest(c, "opacity", lv, (s, p, w) -> new NumericValue(s.getOpacity(w, p)))); - this.expr.addLazyFunction("blocks_daylight", -1, (c, t, lv) -> + this.expr.addContextFunction("blocks_daylight", -1, (c, t, lv) -> genericStateTest(c, "blocks_daylight", lv, (s, p, w) -> new NumericValue(s.propagatesSkylightDown(w, p))));*/ // investigate - expression.addLazyFunction("emitted_light", -1, (c, t, lv) -> + expression.addContextFunction("emitted_light", -1, (c, t, lv) -> genericStateTest(c, "emitted_light", lv, (s, p, w) -> new NumericValue(s.getLuminance()))); - expression.addLazyFunction("light", -1, (c, t, lv) -> + expression.addContextFunction("light", -1, (c, t, lv) -> genericStateTest(c, "light", lv, (s, p, w) -> new NumericValue(Math.max(w.getLightLevel(LightType.BLOCK, p), w.getLightLevel(LightType.SKY, p))))); - expression.addLazyFunction("block_light", -1, (c, t, lv) -> + expression.addContextFunction("block_light", -1, (c, t, lv) -> genericStateTest(c, "block_light", lv, (s, p, w) -> new NumericValue(w.getLightLevel(LightType.BLOCK, p)))); - expression.addLazyFunction("sky_light", -1, (c, t, lv) -> + expression.addContextFunction("sky_light", -1, (c, t, lv) -> genericStateTest(c, "sky_light", lv, (s, p, w) -> new NumericValue(w.getLightLevel(LightType.SKY, p)))); - expression.addLazyFunction("see_sky", -1, (c, t, lv) -> + expression.addContextFunction("see_sky", -1, (c, t, lv) -> genericStateTest(c, "see_sky", lv, (s, p, w) -> new NumericValue(w.isSkyVisible(p)))); - expression.addLazyFunction("brightness", -1, (c, t, lv) -> + expression.addContextFunction("brightness", -1, (c, t, lv) -> genericStateTest(c, "brightness", lv, (s, p, w) -> new NumericValue(w.getBrightness(p)))); - expression.addLazyFunction("hardness", -1, (c, t, lv) -> + expression.addContextFunction("hardness", -1, (c, t, lv) -> genericStateTest(c, "hardness", lv, (s, p, w) -> new NumericValue(s.getHardness(w, p)))); - expression.addLazyFunction("blast_resistance", -1, (c, t, lv) -> + expression.addContextFunction("blast_resistance", -1, (c, t, lv) -> genericStateTest(c, "blast_resistance", lv, (s, p, w) -> new NumericValue(s.getBlock().getBlastResistance()))); - expression.addLazyFunction("in_slime_chunk", -1, (c, t, lv) -> + expression.addContextFunction("in_slime_chunk", -1, (c, t, lv) -> { BlockPos pos = BlockArgument.findIn((CarpetContext)c, lv, 0).block.getPos(); ChunkPos chunkPos = new ChunkPos(pos); - Value ret = new NumericValue(ChunkRandom.getSlimeRandom( + return new NumericValue(ChunkRandom.getSlimeRandom( chunkPos.x, chunkPos.z, ((CarpetContext)c).s.getWorld().getSeed(), 987234911L ).nextInt(10) == 0); - return (_c, _t) -> ret; }); - - expression.addLazyFunction("top", -1, (c, t, lv) -> + expression.addContextFunction("top", -1, (c, t, lv) -> { - String type = lv.get(0).evalValue(c).getString().toLowerCase(Locale.ROOT); + String type = lv.get(0).getString().toLowerCase(Locale.ROOT); Heightmap.Type htype; switch (type) { @@ -598,63 +563,51 @@ public class WorldAccess { BlockPos pos = locator.block.getPos(); int x = pos.getX(); int z = pos.getZ(); - Value retval = new NumericValue(((CarpetContext)c).s.getWorld().getChunk(x >> 4, z >> 4).sampleHeightmap(htype, x & 15, z & 15) + 1); - return (c_, t_) -> retval; - //BlockPos pos = new BlockPos(x,y,z); - //return new BlockValue(source.getWorld().getBlockState(pos), pos); + return new NumericValue(((CarpetContext)c).s.getWorld().getChunk(x >> 4, z >> 4).sampleHeightmap(htype, x & 15, z & 15) + 1); }); - expression.addLazyFunction("loaded", -1, (c, t, lv) -> - { - Value retval = ((CarpetContext) c).s.getWorld().isChunkLoaded(BlockArgument.findIn((CarpetContext) c, lv, 0).block.getPos()) ? Value.TRUE : Value.FALSE; - return (c_, t_) -> retval; - }); + expression.addContextFunction("loaded", -1, (c, t, lv) -> + BooleanValue.of((((CarpetContext) c).s.getWorld().isChunkLoaded(BlockArgument.findIn((CarpetContext) c, lv, 0).block.getPos())))); // Deprecated, use loaded_status as more indicative - expression.addLazyFunction("loaded_ep", -1, (c, t, lv) -> + expression.addContextFunction("loaded_ep", -1, (c, t, lv) -> { c.host.issueDeprecation("loaded_ep(...)"); BlockPos pos = BlockArgument.findIn((CarpetContext)c, lv, 0).block.getPos(); - Value retval = ((CarpetContext)c).s.getWorld().getChunkManager().shouldTickChunk(new ChunkPos(pos))?Value.TRUE : Value.FALSE; - return (c_, t_) -> retval; + return BooleanValue.of(((CarpetContext)c).s.getWorld().getChunkManager().shouldTickChunk(new ChunkPos(pos))); }); - expression.addLazyFunction("loaded_status", -1, (c, t, lv) -> + expression.addContextFunction("loaded_status", -1, (c, t, lv) -> { BlockPos pos = BlockArgument.findIn((CarpetContext)c, lv, 0).block.getPos(); WorldChunk chunk = ((CarpetContext)c).s.getWorld().getChunkManager().getWorldChunk(pos.getX()>>4, pos.getZ()>>4, false); - if (chunk == null) - return LazyValue.ZERO; - Value retval = new NumericValue(chunk.getLevelType().ordinal()); - return (c_, t_) -> retval; + if (chunk == null) return Value.ZERO; + return new NumericValue(chunk.getLevelType().ordinal()); }); - expression.addLazyFunction("is_chunk_generated", -1, (c, t, lv) -> + expression.addContextFunction("is_chunk_generated", -1, (c, t, lv) -> { BlockArgument locator = BlockArgument.findIn((CarpetContext)c, lv, 0); BlockPos pos = locator.block.getPos(); boolean force = false; if (lv.size() > locator.offset) - force = lv.get(locator.offset).evalValue(c, Context.BOOLEAN).getBoolean(); - Value retval = new NumericValue(canHasChunk(((CarpetContext)c).s.getWorld(), new ChunkPos(pos), null, force)); - return (c_, t_) -> retval; + force = lv.get(locator.offset).getBoolean(); + return new NumericValue(canHasChunk(((CarpetContext)c).s.getWorld(), new ChunkPos(pos), null, force)); }); - expression.addLazyFunction("generation_status", -1, (c, t, lv) -> + expression.addContextFunction("generation_status", -1, (c, t, lv) -> { BlockArgument blockArgument = BlockArgument.findIn((CarpetContext)c, lv, 0); BlockPos pos = blockArgument.block.getPos(); boolean forceLoad = false; if (lv.size() > blockArgument.offset) - forceLoad = lv.get(blockArgument.offset).evalValue(c, Context.BOOLEAN).getBoolean(); + forceLoad = lv.get(blockArgument.offset).getBoolean(); Chunk chunk = ((CarpetContext)c).s.getWorld().getChunk(pos.getX()>>4, pos.getZ()>>4, ChunkStatus.EMPTY, forceLoad); - if (chunk == null) - return LazyValue.NULL; - Value retval = new StringValue(chunk.getStatus().getId()); - return (c_, t_) -> retval; + if (chunk == null) return Value.NULL; + return new StringValue(chunk.getStatus().getId()); }); - expression.addLazyFunction("chunk_tickets", -1, (c, t, lv) -> + expression.addContextFunction("chunk_tickets", -1, (c, t, lv) -> { ServerWorld world = ((CarpetContext) c).s.getWorld(); Long2ObjectOpenHashMap>> levelTickets = ( @@ -695,27 +648,26 @@ public class WorldAccess { } } res.sort(Comparator.comparing(e -> ((ListValue) e).getItems().get(1)).reversed()); - Value returnValue = ListValue.wrap(res); - return (_c, _t) -> returnValue; + return ListValue.wrap(res); }); - expression.addLazyFunction("suffocates", -1, (c, t, lv) -> + expression.addContextFunction("suffocates", -1, (c, t, lv) -> genericStateTest(c, "suffocates", lv, (s, p, w) -> new NumericValue(s.shouldSuffocate(w, p)))); // canSuffocate - expression.addLazyFunction("power", -1, (c, t, lv) -> + expression.addContextFunction("power", -1, (c, t, lv) -> genericStateTest(c, "power", lv, (s, p, w) -> new NumericValue(w.getReceivedRedstonePower(p)))); - expression.addLazyFunction("ticks_randomly", -1, (c, t, lv) -> + expression.addContextFunction("ticks_randomly", -1, (c, t, lv) -> booleanStateTest(c, "ticks_randomly", lv, (s, p) -> s.hasRandomTicks())); - expression.addLazyFunction("update", -1, (c, t, lv) -> + expression.addContextFunction("update", -1, (c, t, lv) -> booleanStateTest(c, "update", lv, (s, p) -> { ((CarpetContext) c).s.getWorld().updateNeighbor(p, s.getBlock(), p); return true; })); - expression.addLazyFunction("block_tick", -1, (c, t, lv) -> + expression.addContextFunction("block_tick", -1, (c, t, lv) -> booleanStateTest(c, "block_tick", lv, (s, p) -> { ServerWorld w = ((CarpetContext)c).s.getWorld(); @@ -723,7 +675,7 @@ public class WorldAccess { return true; })); - expression.addLazyFunction("random_tick", -1, (c, t, lv) -> + expression.addContextFunction("random_tick", -1, (c, t, lv) -> booleanStateTest(c, "random_tick", lv, (s, p) -> { ServerWorld w = ((CarpetContext)c).s.getWorld(); @@ -732,6 +684,7 @@ public class WorldAccess { return true; })); + // lazy cause its parked execution expression.addLazyFunction("without_updates", 1, (c, t, lv) -> { boolean previous = CarpetSettings.impendingFillSkipUpdates; @@ -752,7 +705,7 @@ public class WorldAccess { return (cc, tt) -> result[0]; }); - expression.addLazyFunction("set", -1, (c, t, lv) -> + expression.addContextFunction("set", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); @@ -766,7 +719,7 @@ public class WorldAccess { List args = new ArrayList<>(); for (int i = sourceLocator.offset, m = lv.size(); i < m; i++) { - args.add(lv.get(i).evalValue(c)); + args.add(lv.get(i)); } if (args.get(0) instanceof ListValue) { @@ -822,7 +775,7 @@ public class WorldAccess { CompoundTag finalData = data; if (sourceBlockState == targetBlockState && data == null) - return (c_, t_) -> Value.FALSE; + return Value.FALSE; BlockState finalSourceBlockState = sourceBlockState; BlockPos targetPos = targetLocator.block.getPos(); Boolean[] result = new Boolean[]{true}; @@ -846,19 +799,17 @@ public class WorldAccess { } result[0] = success; }); - if (!result[0]) return LazyValue.FALSE; - Value retval = new BlockValue(finalSourceBlockState, world, targetLocator.block.getPos()); - return (c_, t_) -> retval; + if (!result[0]) return Value.FALSE; + return new BlockValue(finalSourceBlockState, world, targetLocator.block.getPos()); }); - expression.addLazyFunction("destroy", -1, (c, t, lv) -> + expression.addContextFunction("destroy", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); BlockArgument locator = BlockArgument.findIn(cc, lv, 0); BlockState state = locator.block.getBlockState(); - if (state.isAir()) - return (c_, t_) -> Value.FALSE; + if (state.isAir()) return Value.FALSE; BlockPos where = locator.block.getPos(); BlockEntity be = world.getBlockEntity(where); long how = 0; @@ -866,7 +817,7 @@ public class WorldAccess { boolean playerBreak = false; if (lv.size() > locator.offset) { - Value val = lv.get(locator.offset).evalValue(c); + Value val = lv.get(locator.offset); if (val instanceof NumericValue) { how = ((NumericValue) val).getLong(); @@ -883,7 +834,7 @@ public class WorldAccess { if (lv.size() > locator.offset+1) { if (!playerBreak) throw new InternalExpressionException("tag is not necessary with 'destroy' with no item"); - Value tagValue = lv.get(locator.offset+1).evalValue(c); + Value tagValue = lv.get(locator.offset+1); if (tagValue instanceof NullValue) tag = null; else if (tagValue instanceof NBTSerializableValue) @@ -898,9 +849,9 @@ public class WorldAccess { ItemStack tool = new ItemStack(item, 1); if (tag != null) tool.setTag(tag); - if (playerBreak && state.getHardness(world, where) < 0.0) return LazyValue.FALSE; + if (playerBreak && state.getHardness(world, where) < 0.0) return Value.FALSE; boolean removed = world.removeBlock(where, false); - if (!removed) return LazyValue.FALSE; + if (!removed) return Value.FALSE; world.syncWorldEvent(null, 2001, where, Block.getRawIdFromState(state)); boolean toolBroke = false; @@ -939,29 +890,28 @@ public class WorldAccess { } } if (!playerBreak) // no tool info - block brokwn - return (c_, t_) -> Value.TRUE; + return Value.TRUE; if (toolBroke) - return LazyValue.NULL; + return Value.NULL; Tag outtag = tool.getTag(); if (outtag == null) - return LazyValue.TRUE; - Value ret = new NBTSerializableValue(() -> outtag); - return (_c, _t) -> ret; + return Value.TRUE; + return new NBTSerializableValue(() -> outtag); }); - expression.addLazyFunction("harvest", -1, (c, t, lv) -> + expression.addContextFunction("harvest", -1, (c, t, lv) -> { if (lv.size()<2) throw new InternalExpressionException("'harvest' takes at least 2 parameters: entity and block, or position, to harvest"); CarpetContext cc = (CarpetContext)c; World world = cc.s.getWorld(); - Value entityValue = lv.get(0).evalValue(cc); + Value entityValue = lv.get(0); if (!(entityValue instanceof EntityValue)) - return (c_, t_) -> Value.FALSE; + return Value.FALSE; Entity e = ((EntityValue) entityValue).getEntity(); if (!(e instanceof ServerPlayerEntity)) - return (c_, t_) -> Value.FALSE; + return Value.FALSE; ServerPlayerEntity player = (ServerPlayerEntity)e; BlockArgument locator = BlockArgument.findIn(cc, lv, 1); BlockPos where = locator.block.getPos(); @@ -972,10 +922,10 @@ public class WorldAccess { success = tryBreakBlock_copy_from_ServerPlayerInteractionManager(player, where); if (success) world.syncWorldEvent(null, 2001, where, Block.getRawIdFromState(state)); - return success ? LazyValue.TRUE : LazyValue.FALSE; + return BooleanValue.of(success); }); - expression.addLazyFunction("create_explosion", -1, (c, t, lv) -> + expression.addContextFunction("create_explosion", -1, (c, t, lv) -> { if (lv.isEmpty()) throw new InternalExpressionException("'create_explosion' requires at least a position to explode"); @@ -985,25 +935,25 @@ public class WorldAccess { boolean createFire = false; Entity source = null; LivingEntity attacker = null; - Vector3Argument location = Vector3Argument.findIn(cc, lv, 0, false, true); + Vector3Argument location = Vector3Argument.findIn(lv, 0, false, true); Vec3d pos = location.vec; if (lv.size() > location.offset) { - powah = NumericValue.asNumber(lv.get(location.offset).evalValue(c), "explosion power").getFloat(); + powah = NumericValue.asNumber(lv.get(location.offset), "explosion power").getFloat(); if (powah < 0) throw new InternalExpressionException("Explosion power cannot be negative"); if (lv.size() > location.offset+1) { - String strval = lv.get(location.offset+1).evalValue(c).getString(); + String strval = lv.get(location.offset+1).getString(); try { mode = Explosion.DestructionType.valueOf(strval.toUpperCase(Locale.ROOT)); } catch (IllegalArgumentException ile) { throw new InternalExpressionException("Illegal explosions block behaviour: "+strval); } if (lv.size() > location.offset+2) { - createFire = lv.get(location.offset+2).evalValue(c, Context.BOOLEAN).getBoolean(); + createFire = lv.get(location.offset+2).getBoolean(); if (lv.size() > location.offset+3) { - Value enVal= lv.get(location.offset+3).evalValue(c); + Value enVal= lv.get(location.offset+3); if (enVal.isNull()) {} // is null already else if (enVal instanceof EntityValue) { @@ -1015,7 +965,7 @@ public class WorldAccess { } if (lv.size() > location.offset+4) { - enVal = lv.get(location.offset+4).evalValue(c); + enVal = lv.get(location.offset+4); if (enVal.isNull()) {} // is null already else if (enVal instanceof EntityValue) { @@ -1054,25 +1004,25 @@ public class WorldAccess { if (spe.squaredDistanceTo(pos) < 4096.0D) spe.networkHandler.sendPacket(new ExplosionS2CPacket(pos.x, pos.y, pos.z, thePowah, explosion.getAffectedBlocks(), explosion.getAffectedPlayers().get(spe))); }); - return LazyValue.TRUE; + return Value.TRUE; }); // TODO rename to use_item - expression.addLazyFunction("place_item", -1, (c, t, lv) -> + expression.addContextFunction("place_item", -1, (c, t, lv) -> { if (lv.size()<2) throw new InternalExpressionException("'place_item' takes at least 2 parameters: item and block, or position, to place onto"); CarpetContext cc = (CarpetContext) c; - String itemString = lv.get(0).evalValue(c).getString(); - Vector3Argument locator = Vector3Argument.findIn(cc, lv, 1); + String itemString = lv.get(0).getString(); + Vector3Argument locator = Vector3Argument.findIn(lv, 1); ItemStackArgument stackArg = NBTSerializableValue.parseItem(itemString); BlockPos where = new BlockPos(locator.vec); String facing = "up"; if (lv.size() > locator.offset) - facing = lv.get(locator.offset).evalValue(c).getString(); + facing = lv.get(locator.offset).getString(); boolean sneakPlace = false; if (lv.size() > locator.offset+1) - sneakPlace = lv.get(locator.offset+1).evalValue(c).getBoolean(); + sneakPlace = lv.get(locator.offset+1).getBoolean(); BlockValue.PlacementContext ctx; try @@ -1089,14 +1039,13 @@ public class WorldAccess { ActionResult useResult = ctx.getStack().useOnBlock(ctx); if (useResult == ActionResult.CONSUME || useResult == ActionResult.SUCCESS) { - return LazyValue.TRUE; + return Value.TRUE; } } else { // not sure we need special case for block items, since useOnBlock can do that as well BlockItem blockItem = (BlockItem) stackArg.getItem(); - if (!ctx.canPlace()) - return (_c, _t) -> Value.FALSE; + if (!ctx.canPlace()) return Value.FALSE; BlockState placementState = blockItem.getBlock().getPlacementState(ctx); if (placementState != null) { @@ -1105,63 +1054,60 @@ public class WorldAccess { cc.s.getWorld().setBlockState(where, placementState, 2); BlockSoundGroup blockSoundGroup = placementState.getSoundGroup(); cc.s.getWorld().playSound(null, where, blockSoundGroup.getPlaceSound(), SoundCategory.BLOCKS, (blockSoundGroup.getVolume() + 1.0F) / 2.0F, blockSoundGroup.getPitch() * 0.8F); - return (_c, _t) -> Value.TRUE; + return Value.TRUE; } } } - return (_c, _t) -> Value.FALSE; + return Value.FALSE; }); - expression.addLazyFunction("blocks_movement", -1, (c, t, lv) -> + expression.addContextFunction("blocks_movement", -1, (c, t, lv) -> booleanStateTest(c, "blocks_movement", lv, (s, p) -> !s.canPathfindThrough(((CarpetContext) c).s.getWorld(), p, NavigationType.LAND))); - expression.addLazyFunction("block_sound", -1, (c, t, lv) -> + expression.addContextFunction("block_sound", -1, (c, t, lv) -> stateStringQuery(c, "block_sound", lv, (s, p) -> BlockInfo.soundName.get(s.getSoundGroup()))); - expression.addLazyFunction("material", -1, (c, t, lv) -> + expression.addContextFunction("material", -1, (c, t, lv) -> stateStringQuery(c, "material", lv, (s, p) -> BlockInfo.materialName.get(s.getMaterial()))); - expression.addLazyFunction("map_colour", -1, (c, t, lv) -> + expression.addContextFunction("map_colour", -1, (c, t, lv) -> stateStringQuery(c, "map_colour", lv, (s, p) -> BlockInfo.mapColourName.get(s.getTopMaterialColor(((CarpetContext)c).s.getWorld(), p)))); // Deprecated for block_state() - expression.addLazyFunction("property", -1, (c, t, lv) -> + expression.addContextFunction("property", -1, (c, t, lv) -> { c.host.issueDeprecation("property(...)"); BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); BlockState state = locator.block.getBlockState(); if (lv.size() <= locator.offset) throw new InternalExpressionException("'property' requires to specify a property to query"); - String tag = lv.get(locator.offset).evalValue(c).getString(); + String tag = lv.get(locator.offset).getString(); StateManager states = state.getBlock().getStateManager(); Property property = states.getProperty(tag); - if (property == null) - return LazyValue.NULL; - Value retval = new StringValue(state.get(property).toString().toLowerCase(Locale.ROOT)); - return (_c, _t) -> retval; + if (property == null) return Value.NULL; + return new StringValue(state.get(property).toString().toLowerCase(Locale.ROOT)); }); // Deprecated for block_state() - expression.addLazyFunction("block_properties", -1, (c, t, lv) -> + expression.addContextFunction("block_properties", -1, (c, t, lv) -> { c.host.issueDeprecation("block_properties(...)"); BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); BlockState state = locator.block.getBlockState(); StateManager states = state.getBlock().getStateManager(); - Value res = ListValue.wrap(states.getProperties().stream().map( + return ListValue.wrap(states.getProperties().stream().map( p -> new StringValue(p.getName())).collect(Collectors.toList()) ); - return (_c, _t) -> res; }); // block_state(block) // block_state(block, property) - expression.addLazyFunction("block_state", -1, (c, t, lv) -> + expression.addContextFunction("block_state", -1, (c, t, lv) -> { BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0, true); BlockState state = locator.block.getBlockState(); @@ -1173,64 +1119,51 @@ public class WorldAccess { { properties.put(StringValue.of(p.getName()), ValueConversions.fromProperty(state, p));// ValueConversions.fromObject(state.get(p), false)); } - Value ret = MapValue.wrap(properties); - return (_c, _t) -> ret; + return MapValue.wrap(properties); } - String tag = lv.get(locator.offset).evalValue(c).getString(); + String tag = lv.get(locator.offset).getString(); Property property = states.getProperty(tag); if (property == null) - return LazyValue.NULL; - Value retval = ValueConversions.fromProperty(state, property); - return (_c, _t) -> retval; + return Value.NULL; + return ValueConversions.fromProperty(state, property); }); - expression.addLazyFunction("block_list", -1, (c, t, lv) -> + expression.addContextFunction("block_list", -1, (c, t, lv) -> { if (lv.size() == 0) - { - Value ret = ListValue.wrap(Registry.BLOCK.getIds().stream().map(ValueConversions::of).collect(Collectors.toList())); - return (_c, _t) -> ret; - } + return ListValue.wrap(Registry.BLOCK.getIds().stream().map(ValueConversions::of).collect(Collectors.toList())); CarpetContext cc = (CarpetContext)c; TagManager tagManager = cc.s.getMinecraftServer().getTagManager(); - String tag = lv.get(0).evalValue(c).getString(); + String tag = lv.get(0).getString(); net.minecraft.tag.Tag blockTag = tagManager.getBlocks().getTag(new Identifier(tag)); - if (blockTag == null) return LazyValue.NULL; - Value ret = ListValue.wrap(blockTag.values().stream().map(b -> ValueConversions.of(Registry.BLOCK.getId(b))).collect(Collectors.toList())); - return (_c, _t) -> ret; + if (blockTag == null) return Value.NULL; + return ListValue.wrap(blockTag.values().stream().map(b -> ValueConversions.of(Registry.BLOCK.getId(b))).collect(Collectors.toList())); }); - expression.addLazyFunction("block_tags", -1, (c, t, lv) -> + expression.addContextFunction("block_tags", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; TagManager tagManager = cc.s.getMinecraftServer().getTagManager(); if (lv.size() == 0) - { - Value ret = ListValue.wrap(tagManager.getBlocks().getTagIds().stream().map(ValueConversions::of).collect(Collectors.toList())); - return (_c, _t) -> ret; - } + return ListValue.wrap(tagManager.getBlocks().getTagIds().stream().map(ValueConversions::of).collect(Collectors.toList())); BlockArgument blockLocator = BlockArgument.findIn(cc, lv, 0, true); if (blockLocator.offset == lv.size()) { Block target = blockLocator.block.getBlockState().getBlock(); - Value ret = ListValue.wrap(tagManager.getBlocks().getTags().entrySet().stream().filter(e -> e.getValue().contains(target)).map(e -> ValueConversions.of(e.getKey())).collect(Collectors.toList())); - return (_c, _t) -> ret; + return ListValue.wrap(tagManager.getBlocks().getTags().entrySet().stream().filter(e -> e.getValue().contains(target)).map(e -> ValueConversions.of(e.getKey())).collect(Collectors.toList())); } - String tag = lv.get(blockLocator.offset).evalValue(c).getString(); + String tag = lv.get(blockLocator.offset).getString(); net.minecraft.tag.Tag blockTag = tagManager.getBlocks().getTag(new Identifier(tag)); - if (blockTag == null) return LazyValue.NULL; - return blockLocator.block.getBlockState().isIn(blockTag)?LazyValue.TRUE:LazyValue.FALSE; + if (blockTag == null) return Value.NULL; + return BooleanValue.of(blockLocator.block.getBlockState().isIn(blockTag)); }); - expression.addLazyFunction("biome", -1, (c, t, lv) -> { + expression.addContextFunction("biome", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); if (lv.size() == 0) - { - Value ret = ListValue.wrap(world.getRegistryManager().get(Registry.BIOME_KEY).getIds().stream().map(ValueConversions::of)); - return (_c, _t) -> ret; - } + return ListValue.wrap(world.getRegistryManager().get(Registry.BIOME_KEY).getIds().stream().map(ValueConversions::of)); BlockArgument locator = BlockArgument.findIn(cc, lv, 0, false, false, true); Biome biome; @@ -1248,76 +1181,70 @@ public class WorldAccess { if (locator.offset == lv.size()) { Identifier biomeId = cc.s.getMinecraftServer().getRegistryManager().get(Registry.BIOME_KEY).getId(biome); - Value res = new StringValue(NBTSerializableValue.nameFromRegistryId(biomeId)); - return (_c, _t) -> res; + return new StringValue(NBTSerializableValue.nameFromRegistryId(biomeId)); } - String biomeFeature = lv.get(locator.offset).evalValue(c).getString(); + String biomeFeature = lv.get(locator.offset).getString(); BiFunction featureProvider = BiomeInfo.biomeFeatures.get(biomeFeature); if (featureProvider == null) throw new InternalExpressionException("Unknown biome feature: "+biomeFeature); - Value ret = featureProvider.apply(world, biome); - return (_c, _t) -> ret; + return featureProvider.apply(world, biome); }); - expression.addLazyFunction("set_biome", -1, (c, t, lv) -> + expression.addContextFunction("set_biome", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); if (lv.size() == locator.offset) throw new InternalExpressionException("'set_biome' needs a biome name as an argument"); - String biomeName = lv.get(locator.offset+0).evalValue(c).getString(); + String biomeName = lv.get(locator.offset+0).getString(); // from locatebiome command code Biome biome = cc.s.getMinecraftServer().getRegistryManager().get(Registry.BIOME_KEY).getOrEmpty(new Identifier(biomeName)) .orElseThrow(() -> new ThrowStatement(biomeName, Throwables.UNKNOWN_BIOME)); boolean doImmediateUpdate = true; if (lv.size() > locator.offset+1) { - doImmediateUpdate = lv.get(locator.offset+1).evalValue(c).getBoolean(); + doImmediateUpdate = lv.get(locator.offset+1).getBoolean(); } ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); Chunk chunk = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.BIOMES); ((BiomeArrayInterface)chunk.getBiomeArray()).setBiomeAtIndex(pos, world, biome); if (doImmediateUpdate) WorldTools.forceChunkUpdate(pos, world); - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("reload_chunk", -1, (c, t, lv) -> { + expression.addContextFunction("reload_chunk", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockPos pos = BlockArgument.findIn(cc, lv, 0).block.getPos(); ServerWorld world = cc.s.getWorld(); cc.s.getMinecraftServer().submitAndJoin( () -> WorldTools.forceChunkUpdate(pos, world)); - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("structure_references", -1, (c, t, lv) -> { + expression.addContextFunction("structure_references", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); Map, LongSet> references = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.STRUCTURE_REFERENCES).getStructureReferences(); if (lv.size() == locator.offset) - { - //CarpetSettings.LOG.error(references.keySet().stream().collect(Collectors.joining(","))); - List referenceList = references.entrySet().stream(). + return ListValue.wrap(references.entrySet().stream(). filter(e -> e.getValue()!= null && !e.getValue().isEmpty()). - map(e -> new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_FEATURE.getId(e.getKey())))).collect(Collectors.toList()); - return (_c, _t ) -> ListValue.wrap(referenceList); - } - String simpleStructureName = lv.get(locator.offset).evalValue(c).getString().toLowerCase(Locale.ROOT); + map(e -> new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_FEATURE.getId(e.getKey())))).collect(Collectors.toList()) + ); + String simpleStructureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); //CarpetSettings.LOG.error(FeatureGenerator.featureToStructure.keySet().stream().collect(Collectors.joining(","))); //CarpetSettings.LOG.error(FeatureGenerator.featureToStructure.values().stream().collect(Collectors.joining(","))); StructureFeature structureName = Registry.STRUCTURE_FEATURE.get(new Identifier(simpleStructureName)); - if (structureName == null) return LazyValue.NULL; + if (structureName == null) return Value.NULL; LongSet structureReferences = references.get(structureName); - if (structureReferences == null || structureReferences.isEmpty()) return ListValue.lazyEmpty(); - Value ret = ListValue.wrap(structureReferences.stream().map(l -> ListValue.of( + if (structureReferences == null || structureReferences.isEmpty()) return ListValue.of(); + return ListValue.wrap(structureReferences.stream().map(l -> ListValue.of( new NumericValue(16*ChunkPos.getPackedX(l)), Value.ZERO, new NumericValue(16*ChunkPos.getPackedZ(l)))).collect(Collectors.toList())); - return (_c, _t) -> ret; }); - expression.addLazyFunction("structure_eligibility", -1, (c, t, lv) -> + expression.addContextFunction("structure_eligibility", -1, (c, t, lv) -> {// TODO rename structureName to class CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); @@ -1332,7 +1259,7 @@ public class WorldAccess { boolean needSize = false; if (lv.size() > locator.offset) { - Value requested = lv.get(locator.offset+0).evalValue(c); + Value requested = lv.get(locator.offset+0); if (!(requested instanceof NullValue)) { String reqString = requested.getString(); @@ -1341,16 +1268,15 @@ public class WorldAccess { } if (lv.size() > locator.offset+1) { - needSize = lv.get(locator.offset+1).evalValue(c).getBoolean(); + needSize = lv.get(locator.offset+1).getBoolean(); } } if (structure != null) { StructureStart start = FeatureGenerator.shouldStructureStartAt(world, pos, structure, needSize); - if (start == null) return LazyValue.NULL; - if (!needSize) return LazyValue.TRUE; - Value ret = ValueConversions.of(start); - return (_c, _t) -> ret; + if (start == null) return Value.NULL; + if (!needSize) return Value.TRUE; + return ValueConversions.of(start); } Map ret = new HashMap<>(); for(StructureFeature str : StructureFeature.STRUCTURES.values()) @@ -1371,11 +1297,10 @@ public class WorldAccess { Value key = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_FEATURE.getId(str))); ret.put(key, (!needSize)?Value.NULL: ValueConversions.of(start)); } - Value retMap = MapValue.wrap(ret); - return (_c, _t) -> retMap; + return MapValue.wrap(ret); }); - expression.addLazyFunction("structures", -1, (c, t, lv) -> { + expression.addContextFunction("structures", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); @@ -1396,16 +1321,13 @@ public class WorldAccess { ListValue.of(ListValue.fromTriple(box.minX, box.minY, box.minZ), ListValue.fromTriple(box.maxX, box.maxY, box.maxZ)) ); } - Value ret = MapValue.wrap(structureList); - return (_c, _t) -> ret; + return MapValue.wrap(structureList); } - String structureName = lv.get(locator.offset).evalValue(c).getString().toLowerCase(Locale.ROOT); - StructureStart start = structures.get(Registry.STRUCTURE_FEATURE.get(new Identifier(structureName))); - Value ret = ValueConversions.of(start); - return (_c, _t) -> ret; + String structureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); + return ValueConversions.of(structures.get(Registry.STRUCTURE_FEATURE.get(new Identifier(structureName)))); }); - expression.addLazyFunction("set_structure", -1, (c, t, lv) -> + expression.addContextFunction("set_structure", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); @@ -1415,7 +1337,7 @@ public class WorldAccess { if (lv.size() == locator.offset) throw new InternalExpressionException("'set_structure requires at least position and a structure name"); - String structureName = lv.get(locator.offset).evalValue(c).getString().toLowerCase(Locale.ROOT); + String structureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); ConfiguredStructureFeature configuredStructure = FeatureGenerator.resolveConfiguredStructure(structureName, world, pos); if (configuredStructure == null) throw new ThrowStatement(structureName, Throwables.UNKNOWN_STRUCTURE); // good 'ol pointer @@ -1432,7 +1354,7 @@ public class WorldAccess { result[0] = res?Value.TRUE:Value.FALSE; return; } - Value newValue = lv.get(locator.offset+1).evalValue(c); + Value newValue = lv.get(locator.offset+1); if (newValue instanceof NullValue) // remove structure { StructureFeature structure = configuredStructure.feature; @@ -1459,21 +1381,20 @@ public class WorldAccess { result[0] = Value.TRUE; } }); - Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later - return (_c, _t) -> ret; + return result[0]; // preventing from lazy evaluating of the result in case a future completes later }); - expression.addLazyFunction("custom_dimension", -1, (c, t, lv) -> + expression.addContextFunction("custom_dimension", -1, (c, t, lv) -> { if (lv.size() == 0) throw new InternalExpressionException("'custom_dimension' requires at least one argument"); CarpetContext cc = (CarpetContext)c; cc.host.issueDeprecation("custom_dimension()"); - String worldKey = lv.get(0).evalValue(c).getString(); + String worldKey = lv.get(0).getString(); Long seed = null; if (lv.size() > 1) { - String seedKey = lv.get(1).evalValue(c).getString(); + String seedKey = lv.get(1).getString(); try { seed = Long.parseLong(seedKey); @@ -1485,35 +1406,35 @@ public class WorldAccess { } boolean success = WorldTools.createWorld(cc.s.getMinecraftServer(), worldKey, seed); - if (!success) return LazyValue.FALSE; + if (!success) return Value.FALSE; CarpetServer.settingsManager.notifyPlayersCommandsChanged(); - return LazyValue.TRUE; + return Value.TRUE; }); - expression.addLazyFunction("reset_chunk", -1, (c, t, lv) -> + expression.addContextFunction("reset_chunk", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; List requestedChunks = new ArrayList<>(); if (lv.size() == 1) { //either one block or list of chunks - Value first = lv.get(0).evalValue(c); + Value first = lv.get(0); if (first instanceof ListValue) { List listVal = ((ListValue) first).getItems(); int offset = 0; - BlockArgument locator = BlockArgument.findInValues(cc, listVal, 0, false, false); + BlockArgument locator = BlockArgument.findIn(cc, listVal, 0); requestedChunks.add(new ChunkPos(locator.block.getPos())); while (listVal.size() > locator.offset) { - locator = BlockArgument.findInValues(cc, listVal, locator.offset, false, false); + locator = BlockArgument.findIn(cc, listVal, locator.offset); requestedChunks.add(new ChunkPos(locator.block.getPos())); } } else { - BlockArgument locator = BlockArgument.findInValues(cc, Collections.singletonList(first), 0, false, false); + BlockArgument locator = BlockArgument.findIn(cc, Collections.singletonList(first), 0); requestedChunks.add(new ChunkPos(locator.block.getPos())); } } @@ -1531,7 +1452,6 @@ public class WorldAccess { { requestedChunks.add(new ChunkPos(x,z)); } - //CarpetSettings.LOG.error("Regenerating from "+Math.min(from.x, to.x)+", "+Math.min(from.z, to.z)+" to "+Math.max(from.x, to.x)+", "+Math.max(from.z, to.z)); } else { @@ -1559,45 +1479,43 @@ public class WorldAccess { e -> new NumericValue((Integer)((Map.Entry) e).getValue()) ))); }); - return (_c, _t) -> result[0]; + return result[0]; }); - expression.addLazyFunction("inhabited_time", -1, (c, t, lv) -> + expression.addContextFunction("inhabited_time", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); BlockPos pos = locator.block.getPos(); - Value ret = new NumericValue(cc.s.getWorld().getChunk(pos).getInhabitedTime()); - return (_c, _t) -> ret; + return new NumericValue(cc.s.getWorld().getChunk(pos).getInhabitedTime()); }); - expression.addLazyFunction("spawn_potential", -1, (c, t, lv) -> + expression.addContextFunction("spawn_potential", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); BlockPos pos = locator.block.getPos(); double required_charge = 1; if (lv.size() > locator.offset) - required_charge = NumericValue.asNumber(lv.get(locator.offset).evalValue(c)).getDouble(); + required_charge = NumericValue.asNumber(lv.get(locator.offset)).getDouble(); SpawnHelper.Info charger = cc.s.getWorld().getChunkManager().getSpawnInfo(); - if (charger == null) return LazyValue.NULL; - Value ret = new NumericValue( + if (charger == null) return Value.NULL; + return new NumericValue( ((SpawnHelperInnerInterface)charger).getPotentialCalculator(). calculate(pos, required_charge ) ); - return (_c, _t) -> ret; }); - expression.addLazyFunction("add_chunk_ticket", -1, (c, t, lv) -> + expression.addContextFunction("add_chunk_ticket", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); BlockPos pos = locator.block.getPos(); if (lv.size() != locator.offset+2) throw new InternalExpressionException("'add_chunk_ticket' requires block position, ticket type and radius"); - String type = lv.get(locator.offset).evalValue(c).getString(); + String type = lv.get(locator.offset).getString(); ChunkTicketType ticket = ticketTypes.get(type.toLowerCase(Locale.ROOT)); if (ticket == null) throw new InternalExpressionException("Unknown ticket type: "+type); - int radius = NumericValue.asNumber(lv.get(locator.offset+1).evalValue(c)).getInt(); + int radius = NumericValue.asNumber(lv.get(locator.offset+1)).getInt(); if (radius < 1 || radius > 32) throw new InternalExpressionException("Ticket radius should be between 1 and 32 chunks"); // due to types we will wing it: ChunkPos target = new ChunkPos(pos); @@ -1607,8 +1525,7 @@ public class WorldAccess { cc.s.getWorld().getChunkManager().addTicket(ChunkTicketType.POST_TELEPORT, target, radius, 1); else cc.s.getWorld().getChunkManager().addTicket(ChunkTicketType.UNKNOWN, target, radius, target); - Value ret = new NumericValue(ticket.getExpiryTicks()); - return (_c, _t) -> ret; + return new NumericValue(ticket.getExpiryTicks()); }); } diff --git a/src/main/java/carpet/script/argument/BlockArgument.java b/src/main/java/carpet/script/argument/BlockArgument.java index 5a0f236f..97f3ffd2 100644 --- a/src/main/java/carpet/script/argument/BlockArgument.java +++ b/src/main/java/carpet/script/argument/BlockArgument.java @@ -29,21 +29,22 @@ public class BlockArgument extends Argument block = b; this.replacement = replacement; } - public static BlockArgument findIn(CarpetContext c, List params, int offset) + + public static BlockArgument findIn(CarpetContext c, List params, int offset) { return findIn(c, params,offset, false, false, false); } - public static BlockArgument findIn(CarpetContext c, List params, int offset, boolean acceptString) + public static BlockArgument findIn(CarpetContext c, List params, int offset, boolean acceptString) { return findIn(c, params,offset, acceptString, false, false); } - public static BlockArgument findIn(CarpetContext c, List params, int offset, boolean acceptString, boolean optional, boolean anyString) + public static BlockArgument findIn(CarpetContext c, List params, int offset, boolean acceptString, boolean optional, boolean anyString) { try { - Value v1 = params.get(0 + offset).evalValue(c); + Value v1 = params.get(0 + offset); //add conditional from string name if (optional && v1 instanceof NullValue) { @@ -76,8 +77,8 @@ public class BlockArgument extends Argument 1+offset); } int xpos = (int) NumericValue.asNumber(v1).getLong(); - int ypos = (int) NumericValue.asNumber( params.get(1 + offset).evalValue(c)).getLong(); - int zpos = (int) NumericValue.asNumber( params.get(2 + offset).evalValue(c)).getLong(); + int ypos = (int) NumericValue.asNumber( params.get(1 + offset)).getLong(); + int zpos = (int) NumericValue.asNumber( params.get(2 + offset)).getLong(); return new BlockArgument( new BlockValue( null, diff --git a/src/main/java/carpet/script/argument/FileArgument.java b/src/main/java/carpet/script/argument/FileArgument.java index 104f04f1..fa4cbed3 100644 --- a/src/main/java/carpet/script/argument/FileArgument.java +++ b/src/main/java/carpet/script/argument/FileArgument.java @@ -117,11 +117,11 @@ public class FileArgument return "path: "+resource+" zip: "+zipContainer+" type: "+type.id+" folder: "+isFolder+" shared: "+isShared+" reason: "+reason.toString(); } - public static FileArgument from(List lv, Context c, boolean isFolder, Reason reason) + public static FileArgument from(List lv, boolean isFolder, Reason reason) { if (lv.size() < 2) throw new InternalExpressionException("File functions require path and type as first two arguments"); - Pair resource = recognizeResource(lv.get(0).evalValue(c), isFolder); - String origtype = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT); + Pair resource = recognizeResource(lv.get(0), isFolder); + String origtype = lv.get(1).getString().toLowerCase(Locale.ROOT); boolean shared = origtype.startsWith("shared_"); String typeString = shared ? origtype.substring(7) : origtype; //len(shared_) Type type = Type.of.get(typeString); diff --git a/src/main/java/carpet/script/argument/FunctionArgument.java b/src/main/java/carpet/script/argument/FunctionArgument.java index ecd09034..64fc1587 100644 --- a/src/main/java/carpet/script/argument/FunctionArgument.java +++ b/src/main/java/carpet/script/argument/FunctionArgument.java @@ -16,12 +16,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -public class FunctionArgument extends Argument +public class FunctionArgument extends Argument { public FunctionValue function; - public List args; + public List args; - private FunctionArgument(FunctionValue function, int offset, List args) + private FunctionArgument(FunctionValue function, int offset, List args) { super(offset); this.function = function; @@ -39,18 +39,18 @@ public class FunctionArgument extends Argument * if the number of supplied arguments is right * @return argument data */ - public static FunctionArgument findIn( + public static FunctionArgument findIn( Context c, Module module, - List params, + List params, int offset, boolean allowNone, boolean checkArgs) { - Value functionValue = params.get(offset).evalValue(c); + Value functionValue = params.get(offset); if (functionValue.isNull()) { - if (allowNone) return new FunctionArgument<>(null, offset+1, Collections.emptyList()); + if (allowNone) return new FunctionArgument(null, offset+1, Collections.emptyList()); throw new InternalExpressionException("function argument cannot be null"); } if (!(functionValue instanceof FunctionValue)) @@ -68,12 +68,12 @@ public class FunctionArgument extends Argument if (extraargs > 0 && fun.getVarArgs() == null) throw new InternalExpressionException("Function " + fun.getPrettyString() + " requires " + fun.getArguments().size() + " arguments"); } - List lvargs = new ArrayList<>(); + List lvargs = new ArrayList<>(); for (int i = offset+1, mx = params.size(); i < mx; i++) lvargs.add(params.get(i)); - return new FunctionArgument<>(fun, offset + 1 + argsize, lvargs); + return new FunctionArgument(fun, offset + 1 + argsize, lvargs); } - public static FunctionArgument fromCommandSpec(ScriptHost host, Value funSpec) throws CommandSyntaxException { + public static FunctionArgument fromCommandSpec(ScriptHost host, Value funSpec) throws CommandSyntaxException { FunctionValue function; List args = Collections.emptyList(); if (!(funSpec instanceof ListValue)) @@ -93,16 +93,11 @@ public class FunctionArgument extends Argument } if (params.size() > 1) args = params.subList(1,params.size()); - return new FunctionArgument<>(function, 0, args); + return new FunctionArgument(function, 0, args); } - public void checkArgs() { + public List checkedArgs() { function.checkArgs(args.size()); - } - - public List unpackArgs(Context c) { - List unpackedArgs = Fluff.AbstractFunction.unpackArgs((List) args, c); - function.checkArgs(unpackedArgs.size()); - return unpackedArgs; + return args; } } diff --git a/src/main/java/carpet/script/argument/Vector3Argument.java b/src/main/java/carpet/script/argument/Vector3Argument.java index 003ffc4c..1dc440f1 100644 --- a/src/main/java/carpet/script/argument/Vector3Argument.java +++ b/src/main/java/carpet/script/argument/Vector3Argument.java @@ -47,66 +47,12 @@ public class Vector3Argument extends Argument return this; } - - public static Vector3Argument findIn(CarpetContext c, List params, int offset) + public static Vector3Argument findIn(List params, int offset) { - return findIn(c,params, offset, false, false); + return findIn(params, offset, false, false); } - public static Vector3Argument findIn(CarpetContext c, List params, int offset, boolean optionalDirection, boolean optionalEntity) - { - try - { - Value v1 = params.get(0 + offset).evalValue(c); - if (v1 instanceof BlockValue) - { - // pos + 0.5v - return (new Vector3Argument(Vec3d.ofCenter(((BlockValue) v1).getPos()), 1+offset)).fromBlock(); - } - if (optionalEntity && v1 instanceof EntityValue) - { - Entity e = ((EntityValue) v1).getEntity(); - return new Vector3Argument(e.getPos(), 1+offset).withEntity(e); - } - if (v1 instanceof ListValue) - { - List args = ((ListValue) v1).getItems(); - Vec3d pos = new Vec3d( - NumericValue.asNumber(args.get(0)).getDouble(), - NumericValue.asNumber(args.get(1)).getDouble(), - NumericValue.asNumber(args.get(2)).getDouble()); - double yaw = 0.0D; - double pitch = 0.0D; - if (args.size()>3 && optionalDirection) - { - yaw = NumericValue.asNumber(args.get(3)).getDouble(); - pitch = NumericValue.asNumber(args.get(4)).getDouble(); - } - return new Vector3Argument(pos,offset+1, yaw, pitch); - } - Vec3d pos = new Vec3d( - NumericValue.asNumber(v1).getDouble(), - NumericValue.asNumber(params.get(1 + offset).evalValue(c)).getDouble(), - NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble()); - double yaw = 0.0D; - double pitch = 0.0D; - int eatenLength = 3; - if (params.size()>3+offset && optionalDirection) - { - yaw = NumericValue.asNumber(params.get(3 + offset).evalValue(c)).getDouble(); - pitch = NumericValue.asNumber(params.get(4 + offset).evalValue(c)).getDouble(); - eatenLength = 5; - } - - return new Vector3Argument(pos,offset+eatenLength, yaw, pitch); - } - catch (IndexOutOfBoundsException e) - { - throw new InternalExpressionException("Position argument should be defined either by three coordinates (a triple or by three arguments), or a positioned block value"); - } - } - - public static Vector3Argument findIn(List params, int offset, boolean optionalDirection) + public static Vector3Argument findIn(List params, int offset, boolean optionalDirection, boolean optionalEntity) { try { @@ -115,6 +61,11 @@ public class Vector3Argument extends Argument { return (new Vector3Argument(Vec3d.ofCenter(((BlockValue) v1).getPos()), 1+offset)).fromBlock(); } + if (optionalEntity && v1 instanceof EntityValue) + { + Entity e = ((EntityValue) v1).getEntity(); + return new Vector3Argument(e.getPos(), 1+offset).withEntity(e); + } if (v1 instanceof ListValue) { List args = ((ListValue) v1).getItems(); diff --git a/src/main/java/carpet/script/command/CommandArgument.java b/src/main/java/carpet/script/command/CommandArgument.java index 5ca2f191..367558bc 100644 --- a/src/main/java/carpet/script/command/CommandArgument.java +++ b/src/main/java/carpet/script/command/CommandArgument.java @@ -291,7 +291,7 @@ public abstract class CommandArgument protected boolean needsMatching; protected boolean caseSensitive = true; protected SuggestionProvider suggestionProvider; - protected FunctionArgument customSuggester; + protected FunctionArgument customSuggester; protected CommandArgument( diff --git a/src/main/java/carpet/script/language/Arithmetic.java b/src/main/java/carpet/script/language/Arithmetic.java index c5e64034..8bdb3c94 100644 --- a/src/main/java/carpet/script/language/Arithmetic.java +++ b/src/main/java/carpet/script/language/Arithmetic.java @@ -64,10 +64,10 @@ public class Arithmetic { expression.addMathematicalUnaryIntFunction("floor", n -> (long)Math.floor(n)); expression.addMathematicalUnaryIntFunction("ceil", n -> (long)Math.ceil(n)); - expression.addLazyFunction("mandelbrot", 3, (c, t, lv) -> { - double a0 = NumericValue.asNumber(lv.get(0).evalValue(c)).getDouble(); - double b0 = NumericValue.asNumber(lv.get(1).evalValue(c)).getDouble(); - long maxiter = NumericValue.asNumber(lv.get(2).evalValue(c)).getLong(); + expression.addContextFunction("mandelbrot", 3, (c, t, lv) -> { + double a0 = NumericValue.asNumber(lv.get(0)).getDouble(); + double b0 = NumericValue.asNumber(lv.get(1)).getDouble(); + long maxiter = NumericValue.asNumber(lv.get(2)).getLong(); double a = 0.0D; double b = 0.0D; long iter = 0; @@ -79,7 +79,7 @@ public class Arithmetic { iter++; } long iFinal = iter; - return (cc, tt) -> new NumericValue(iFinal); + return new NumericValue(iFinal); }); expression.addFunction("max", (lv) -> diff --git a/src/main/java/carpet/script/language/ControlFlow.java b/src/main/java/carpet/script/language/ControlFlow.java index e094309e..cfb78fed 100644 --- a/src/main/java/carpet/script/language/ControlFlow.java +++ b/src/main/java/carpet/script/language/ControlFlow.java @@ -20,6 +20,7 @@ import java.util.stream.Collectors; public class ControlFlow { public static void apply(Expression expression) // public just to get the javadoc right { + // needs to be lazy cause of custom contextualization expression.addLazyBinaryOperator(";", Operators.precedence.get("nextop;"), true, (c, t, lv1, lv2) -> { lv1.evalValue(c, Context.VOID); @@ -27,7 +28,7 @@ public class ControlFlow { return (cc, tt) -> v2; }); - // if(cond1, expr1, cond2, expr2, ..., ?default) => value + // obvious lazy due to conditional evaluation of arguments expression.addLazyFunction("if", -1, (c, t, lv) -> { if ( lv.size() < 2 ) @@ -51,23 +52,24 @@ public class ControlFlow { expression.addFunction("exit", (lv) -> { throw new ExitStatement(lv.size()==0?Value.NULL:lv.get(0)); }); - expression.addLazyFunction("throw", -1, (c, t, lv)-> + expression.addFunction("throw", lv-> { switch (lv.size()) { case 0: throw new ThrowStatement(Value.NULL, Throwables.USER_DEFINED); case 1: - throw new ThrowStatement(lv.get(0).evalValue(c), Throwables.USER_DEFINED ); + throw new ThrowStatement(lv.get(0), Throwables.USER_DEFINED ); case 2: - throw new ThrowStatement(lv.get(1).evalValue(c), Throwables.getTypeForException(lv.get(0).evalValue(c).getString())); + throw new ThrowStatement(lv.get(1), Throwables.getTypeForException(lv.get(0).getString())); case 3: - throw new ThrowStatement(lv.get(2).evalValue(c), Throwables.getTypeForException(lv.get(1).evalValue(c).getString()), lv.get(0).evalValue(c).getString()); + throw new ThrowStatement(lv.get(2), Throwables.getTypeForException(lv.get(1).getString()), lv.get(0).getString()); default: throw new InternalExpressionException("throw() can't accept more than 3 parameters"); } }); + // needs to be lazy since execution of parameters but first one are conditional expression.addLazyFunction("try", -1, (c, t, lv) -> { if (lv.size()==0) diff --git a/src/main/java/carpet/script/language/DataStructures.java b/src/main/java/carpet/script/language/DataStructures.java index 59418de5..b97d3b49 100644 --- a/src/main/java/carpet/script/language/DataStructures.java +++ b/src/main/java/carpet/script/language/DataStructures.java @@ -95,6 +95,7 @@ public class DataStructures { return ListValue.wrap(toSort); }); + // needs lazy cause sort function is reused expression.addLazyFunction("sort_key", -1, (c, t, lv) -> //get working with iterators { if (lv.size() == 0) @@ -121,7 +122,8 @@ public class DataStructures { }); //revering scope c.setVariable("_", __); - return (cc, tt) -> ListValue.wrap(toSort); + Value ret = ListValue.wrap(toSort); + return (cc, tt) -> ret; }); expression.addFunction("range", (lv) -> @@ -147,18 +149,14 @@ public class DataStructures { : LazyListValue.rangeDouble(from.getDouble(), to.getDouble(), step.getDouble()); }); - expression.addLazyFunction("m", -1, (c, t, llv) -> + expression.addTypedContextFunction("m", -1, Context.MAPDEF, (c, t, lv) -> { - List lv = new ArrayList<>(); - for (LazyValue lazyParam : llv) { - lv.add(lazyParam.evalValue(c, Context.MAPDEF)); // none type default by design - } Value ret; if (lv.size() == 1 && lv.get(0) instanceof LazyListValue) ret = new MapValue(((LazyListValue) lv.get(0)).unroll()); else ret = new MapValue(lv); - return (cc, tt) -> ret; + return ret; }); expression.addUnaryFunction("keys", v -> @@ -184,41 +182,23 @@ public class DataStructures { return Value.NULL; }); - expression.addLazyBinaryOperator(":", Operators.precedence.get("attribute~:"),true, (c, t, container_lv, key_lv) -> + expression.addBinaryContextOperator(":", Operators.precedence.get("attribute~:"),true, (c, t, container, address) -> { - Value container = container_lv.evalValue(c); if (container instanceof LContainerValue) { ContainerValueInterface outerContainer = ((LContainerValue) container).getContainer(); - if (outerContainer == null) - { - Value innerLValue = new LContainerValue(null, null); - return (cc, tt) -> innerLValue; - } + if (outerContainer == null) return LContainerValue.NULL_CONTAINER; Value innerContainer = outerContainer.get(((LContainerValue) container).getAddress()); - if (!(innerContainer instanceof ContainerValueInterface)) - { - Value innerLValue = new LContainerValue(null, null); - return (cc, tt) -> innerLValue; - } - Value innerLValue = new LContainerValue((ContainerValueInterface) innerContainer, key_lv.evalValue(c)); - return (cc, tt) -> innerLValue; + if (!(innerContainer instanceof ContainerValueInterface)) return LContainerValue.NULL_CONTAINER; + return new LContainerValue((ContainerValueInterface) innerContainer, address); } if (!(container instanceof ContainerValueInterface)) - if (t == Context.LVALUE) - return (cc, tt) -> new LContainerValue(null, null); - else - return (cc, tt) -> Value.NULL; - Value address = key_lv.evalValue(c); - if (t != Context.LVALUE) - { - Value retVal = ((ContainerValueInterface) container).get(address); - return (cc, ct) -> retVal; - } - Value retVal = new LContainerValue((ContainerValueInterface) container, address); - return (cc, ct) -> retVal; + return t == Context.LVALUE ? LContainerValue.NULL_CONTAINER : Value.NULL; + if (t != Context.LVALUE) return ((ContainerValueInterface) container).get(address); + return new LContainerValue((ContainerValueInterface) container, address); }); + // lazy cause conditional typing - questionable expression.addLazyFunction("get", -1, (c, t, lv) -> { if (lv.size() == 0) @@ -227,10 +207,10 @@ public class DataStructures { { Value v = lv.get(0).evalValue(c, Context.LVALUE); if (!(v instanceof LContainerValue)) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; ContainerValueInterface container = ((LContainerValue) v).getContainer(); if (container == null) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; Value ret = container.get(((LContainerValue) v).getAddress()); return (cc, tt) -> ret; } @@ -246,6 +226,7 @@ public class DataStructures { return (cc, tt) -> finalContainer; }); + // same as `get` expression.addLazyFunction("has", -1, (c, t, lv) -> { if (lv.size() == 0) @@ -254,25 +235,26 @@ public class DataStructures { { Value v = lv.get(0).evalValue(c, Context.LVALUE); if (!(v instanceof LContainerValue)) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; ContainerValueInterface container = ((LContainerValue) v).getContainer(); if (container == null) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; Value ret = new NumericValue(container.has(((LContainerValue) v).getAddress())); return (cc, tt) -> ret; } Value container = lv.get(0).evalValue(c); for (int i = 1; i < lv.size()-1; i++) { - if (!(container instanceof ContainerValueInterface)) return (cc, tt) -> Value.NULL; + if (!(container instanceof ContainerValueInterface)) return LazyValue.NULL; container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c)); } if (!(container instanceof ContainerValueInterface)) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; Value ret = new NumericValue(((ContainerValueInterface) container).has(lv.get(lv.size()-1).evalValue(c))); return (cc, tt) -> ret; }); + // same as `get` expression.addLazyFunction("put", -1, (c, t, lv) -> { if(lv.size()<2) @@ -285,7 +267,7 @@ public class DataStructures { ContainerValueInterface internalContainer = ((LContainerValue) container).getContainer(); if (internalContainer == null) { - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; } Value address = ((LContainerValue) container).getAddress(); Value what = lv.get(1).evalValue(c); @@ -301,7 +283,7 @@ public class DataStructures { } if (!(container instanceof ContainerValueInterface)) { - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; } Value where = lv.get(1).evalValue(c); Value what = lv.get(2).evalValue(c); @@ -311,6 +293,7 @@ public class DataStructures { return (cc, tt) -> retVal; }); + // same as `get` expression.addLazyFunction("delete", -1, (c, t, lv) -> { if (lv.size() == 0) @@ -319,21 +302,21 @@ public class DataStructures { { Value v = lv.get(0).evalValue(c, Context.LVALUE); if (!(v instanceof LContainerValue)) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; ContainerValueInterface container = ((LContainerValue) v).getContainer(); if (container == null) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; Value ret = new NumericValue(container.delete(((LContainerValue) v).getAddress())); return (cc, tt) -> ret; } Value container = lv.get(0).evalValue(c); for (int i = 1; i < lv.size()-1; i++) { - if (!(container instanceof ContainerValueInterface)) return (cc, tt) -> Value.NULL; + if (!(container instanceof ContainerValueInterface)) return LazyValue.NULL; container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c)); } if (!(container instanceof ContainerValueInterface)) - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; Value ret = new NumericValue(((ContainerValueInterface) container).delete(lv.get(lv.size()-1).evalValue(c))); return (cc, tt) -> ret; }); diff --git a/src/main/java/carpet/script/language/Functions.java b/src/main/java/carpet/script/language/Functions.java index 5c03dd13..25fa7825 100644 --- a/src/main/java/carpet/script/language/Functions.java +++ b/src/main/java/carpet/script/language/Functions.java @@ -2,12 +2,13 @@ package carpet.script.language; import carpet.script.Context; import carpet.script.Expression; -import carpet.script.LazyValue; +import carpet.script.Fluff; import carpet.script.argument.FunctionArgument; import carpet.script.exception.InternalExpressionException; import carpet.script.exception.ReturnStatement; import carpet.script.value.AbstractListValue; import carpet.script.value.FunctionSignatureValue; +import carpet.script.value.FunctionUnpackedArgumentsValue; import carpet.script.value.FunctionValue; import carpet.script.value.FunctionAnnotationValue; import carpet.script.value.ListValue; @@ -24,20 +25,20 @@ public class Functions { public static void apply(Expression expression) // public just to get the javadoc right { // artificial construct to handle user defined functions and function definitions - expression.addLazyFunction("import", -1, (c, t, lv) -> + expression.addContextFunction("import", -1, (c, t, lv) -> { if (lv.size() < 1) throw new InternalExpressionException("'import' needs at least a module name to import, and list of values to import"); - String moduleName = lv.get(0).evalValue(c).getString(); + String moduleName = lv.get(0).getString(); c.host.importModule(c, moduleName); moduleName = moduleName.toLowerCase(Locale.ROOT); if (lv.size() > 1) - c.host.importNames(c, expression.module, moduleName, lv.subList(1, lv.size()).stream().map((l) -> l.evalValue(c).getString()).collect(Collectors.toList())); + c.host.importNames(c, expression.module, moduleName, lv.subList(1, lv.size()).stream().map(Value::getString).collect(Collectors.toList())); if (t == Context.VOID) - return LazyValue.NULL; - ListValue list = ListValue.wrap(c.host.availableImports(moduleName).map(StringValue::new).collect(Collectors.toList())); - return (cc, tt) -> list; + return Value.NULL; + return ListValue.wrap(c.host.availableImports(moduleName).map(StringValue::new).collect(Collectors.toList())); }); + // needs to be lazy because of custom context of execution of arguments as a signature expression.addLazyFunctionWithDelegation("call",-1, (c, t, expr, tok, lv) -> { // adjust based on c if (lv.size() == 0) @@ -45,7 +46,8 @@ public class Functions { //lv.remove(lv.size()-1); // aint gonna cut it // maybe it will because of the eager eval changes if (t != Context.SIGNATURE) // just call the function { - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, false, true); + List args = Fluff.AbstractFunction.unpackLazy(lv, c, Context.NONE); + FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, args, 0, false, true); FunctionValue fun = functionArgument.function; return fun.callInContext(c, t, functionArgument.args); } @@ -63,7 +65,7 @@ public class Functions { } if (v instanceof FunctionAnnotationValue) { - if (((FunctionAnnotationValue) v).type == 0) + if (((FunctionAnnotationValue) v).type == FunctionAnnotationValue.Type.GLOBAL) { globals.add(v.boundVariable); } @@ -83,32 +85,37 @@ public class Functions { return (cc, tt) -> retval; }); - expression.addLazyFunction("outer", 1, (c, t, lv) -> + expression.addContextFunction("outer", 1, (c, t, lv) -> { if (t != Context.LOCALIZATION) throw new InternalExpressionException("Outer scoping of variables is only possible in function signatures."); - return (cc, tt) -> new FunctionAnnotationValue(lv.get(0).evalValue(c), 0); + return new FunctionAnnotationValue(lv.get(0), FunctionAnnotationValue.Type.GLOBAL); }); + // lazy because of typed evaluation of the argument expression.addLazyUnaryOperator("...", Operators.precedence.get("def->..."), false, (c, t, lv) -> { if (t == Context.LOCALIZATION) - return (cc, tt) -> new FunctionAnnotationValue(lv.evalValue(c), 1); - if (t == Context.CALLARGS) - { - Value params = lv.evalValue(c, Context.NONE); - if (params instanceof ListValue) - return (cc, tt) -> params; - if (!(params instanceof AbstractListValue)) - throw new InternalExpressionException("Unable to unpack a non-list"); - Value unpacked = ListValue.wrap(ImmutableList.copyOf(((AbstractListValue) params).iterator())); - return (cc, tt) -> unpacked; - } - throw new InternalExpressionException("That functionality has not been implemented yet."); + return (cc, tt) -> new FunctionAnnotationValue(lv.evalValue(c), FunctionAnnotationValue.Type.VARARG); + Value params = lv.evalValue(c, t); + FunctionUnpackedArgumentsValue fuaval; + if (params instanceof ListValue) + { + fuaval = new FunctionUnpackedArgumentsValue(((ListValue) params).getItems()); + return (cc, tt) -> fuaval; + } + if (!(params instanceof AbstractListValue)) + throw new InternalExpressionException("Unable to unpack a non-list"); + fuaval = new FunctionUnpackedArgumentsValue( + ImmutableList.copyOf(((AbstractListValue) params).iterator()) + ); + return (cc, tt) -> fuaval; + //throw new InternalExpressionException("That functionality has not been implemented yet."); }); //assigns const procedure to the lhs, returning its previous value + // must be lazy due to RHS being an expression to save to execute expression.addLazyBinaryOperatorWithDelegation("->", Operators.precedence.get("def->..."), false, (c, type, e, t, lv1, lv2) -> { if (type == Context.MAPDEF) diff --git a/src/main/java/carpet/script/language/Loops.java b/src/main/java/carpet/script/language/Loops.java index ad041cd2..4a566b07 100644 --- a/src/main/java/carpet/script/language/Loops.java +++ b/src/main/java/carpet/script/language/Loops.java @@ -35,6 +35,7 @@ public class Loops { throw new InternalExpressionException("'continue' can only be called with zero or one argument"); }); + // lazy expression.addLazyFunction("while", 3, (c, t, lv) -> { long limit = NumericValue.asNumber(lv.get(1).evalValue(c)).getLong(); diff --git a/src/main/java/carpet/script/language/Operators.java b/src/main/java/carpet/script/language/Operators.java index b3548992..389623e1 100644 --- a/src/main/java/carpet/script/language/Operators.java +++ b/src/main/java/carpet/script/language/Operators.java @@ -44,6 +44,7 @@ public class Operators { expression.addBinaryOperator("^", precedence.get("exponent^"), false, (v1, v2) -> new NumericValue(java.lang.Math.pow(NumericValue.asNumber(v1).getDouble(), NumericValue.asNumber(v2).getDouble()))); + // lazy cause RHS is only conditional expression.addLazyBinaryOperator("&&", precedence.get("and&&"), false, (c, t, lv1, lv2) -> { Value v1 = lv1.evalValue(c, Context.BOOLEAN); @@ -51,6 +52,7 @@ public class Operators { return lv2; }); + // lazy cause RHS is only conditional expression.addLazyBinaryOperator("||", precedence.get("or||"), false, (c, t, lv1, lv2) -> { Value v1 = lv1.evalValue(c, Context.BOOLEAN); @@ -73,6 +75,7 @@ public class Operators { expression.addBinaryOperator("!=", precedence.get("equal==!="), false, (v1, v2) -> v1.equals(v2) ? Value.FALSE : Value.TRUE); + // lazy cause of assignment which is non-trivial expression.addLazyBinaryOperator("=", precedence.get("assign=<>"), false, (c, t, lv1, lv2) -> { Value v1 = lv1.evalValue(c, Context.LVALUE); @@ -111,6 +114,7 @@ public class Operators { return boundedLHS; }); + // lazy due to assignment expression.addLazyBinaryOperator("+=", precedence.get("assign=<>"), false, (c, t, lv1, lv2) -> { Value v1 = lv1.evalValue(c, Context.LVALUE); @@ -171,10 +175,8 @@ public class Operators { return boundedLHS; }); - expression.addLazyBinaryOperator("<>", precedence.get("assign=<>"), false, (c, t, lv1, lv2) -> + expression.addBinaryContextOperator("<>", precedence.get("assign=<>"), false, (c, t, v1, v2) -> { - Value v1 = lv1.evalValue(c); - Value v2 = lv2.evalValue(c); if (v1 instanceof ListValue.ListConstructorValue && v2 instanceof ListValue.ListConstructorValue) { List ll = ((ListValue)v1).getItems(); @@ -196,7 +198,7 @@ public class Operators { expression.setAnyVariable(c, lname, (cc, tt) -> rval); expression.setAnyVariable(c, rname, (cc, tt) -> lval); } - return (cc, tt) -> Value.TRUE; + return Value.TRUE; } v1.assertAssignable(); v2.assertAssignable(); @@ -206,13 +208,14 @@ public class Operators { Value rval = v1.reboundedTo(rvalvar); expression.setAnyVariable(c, lvalvar, (cc, tt) -> lval); expression.setAnyVariable(c, rvalvar, (cc, tt) -> rval); - return (cc, tt) -> lval; + return lval; }); expression.addUnaryOperator("-", false, v -> NumericValue.asNumber(v).opposite()); expression.addUnaryOperator("+", false, NumericValue::asNumber); + // could be non-lazy, but who cares - its a small one. expression.addLazyUnaryOperator("!", precedence.get("unary+-!"), false, (c, t, lv)-> lv.evalValue(c, Context.BOOLEAN).getBoolean() ? (cc, tt)-> Value.FALSE : (cc, tt) -> Value.TRUE); // might need context boolean } diff --git a/src/main/java/carpet/script/language/Sys.java b/src/main/java/carpet/script/language/Sys.java index dc2a75df..c9481537 100644 --- a/src/main/java/carpet/script/language/Sys.java +++ b/src/main/java/carpet/script/language/Sys.java @@ -7,6 +7,7 @@ import carpet.script.ScriptHost; import carpet.script.exception.InternalExpressionException; import carpet.script.utils.PerlinNoiseSampler; import carpet.script.utils.SimplexNoiseSampler; +import carpet.script.value.BooleanValue; import carpet.script.value.FunctionValue; import carpet.script.value.ListValue; import carpet.script.value.NullValue; @@ -37,19 +38,15 @@ public class Sys { expression.addUnaryFunction("copy", Value::deepcopy); - expression.addLazyFunction("bool", 1, (c, t, lv) -> + expression.addTypedContextFunction("bool", 1, Context.BOOLEAN, (c, t, lv) -> { - Value v = lv.get(0).evalValue(c, Context.BOOLEAN); + Value v = lv.get(0); if (v instanceof StringValue) { - String str = v.getString(); - if ("false".equalsIgnoreCase(str) || "null".equalsIgnoreCase(str)) - { - return (cc, tt) -> Value.FALSE; - } + String str = v.getString().toLowerCase(Locale.ROOT); + if ("false".equals(str) || "null".equals(str)) return Value.FALSE; } - Value retval = v.getBoolean()?Value.TRUE:Value.FALSE; - return (cc, tt) -> retval; + return BooleanValue.of(v.getBoolean()); }); expression.addUnaryFunction("number", v -> @@ -187,45 +184,40 @@ public class Sys { expression.addUnaryFunction("type", v -> new StringValue(v.getTypeString())); expression.addUnaryFunction("length", v -> new NumericValue(v.length())); - expression.addLazyFunction("rand", -1, (c, t, lv) -> + expression.addContextFunction("rand", -1, (c, t, lv) -> { int argsize = lv.size(); Random randomizer = Sys.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 (argsize == 2) randomizer = c.host.getRandom(NumericValue.asNumber(lv.get(1)).getLong()); + Value argument = lv.get(0); if (argument instanceof ListValue) { List list = ((ListValue) argument).getItems(); - Value retval = list.get(randomizer.nextInt(list.size())); - return (cc, tt) -> retval; + return list.get(randomizer.nextInt(list.size())); } + double value = NumericValue.asNumber(argument).getDouble()*randomizer.nextDouble(); if (t == Context.BOOLEAN) - { - double rv = NumericValue.asNumber(argument).getDouble()*randomizer.nextFloat(); - Value retval = rv<1.0D?Value.FALSE:Value.TRUE; - return (cc, tt) -> retval; - } - Value retval = new NumericValue(NumericValue.asNumber(argument).getDouble()*randomizer.nextDouble()); - return (cc, tt) -> retval; + return BooleanValue.of(value >= 1.0D); + return new NumericValue(value); }); - expression.addLazyFunction("reset_seed", 1, (c, t, lv) -> { - boolean gotIt = c.host.resetRandom(NumericValue.asNumber(lv.get(0).evalValue(c)).getLong()); - return gotIt?LazyValue.TRUE:LazyValue.FALSE; + expression.addContextFunction("reset_seed", 1, (c, t, lv) -> { + boolean gotIt = c.host.resetRandom(NumericValue.asNumber(lv.get(0)).getLong()); + return BooleanValue.of(gotIt); }); - expression.addLazyFunction("perlin", -1, (c, t, lv) -> + expression.addFunction("perlin", lv -> { PerlinNoiseSampler sampler; Value x, y, z; if (lv.size() >= 4) { - x = lv.get(0).evalValue(c); - y = lv.get(1).evalValue(c); - z = lv.get(2).evalValue(c); - sampler = PerlinNoiseSampler.getPerlin(NumericValue.asNumber(lv.get(3).evalValue(c)).getLong()); + x = lv.get(0); + y = lv.get(1); + z = lv.get(2); + sampler = PerlinNoiseSampler.getPerlin(NumericValue.asNumber(lv.get(3)).getLong()); } else { @@ -234,12 +226,12 @@ public class Sys { z = Value.NULL; if (lv.size() == 0 ) throw new InternalExpressionException("'perlin' requires at least one dimension to sample from"); - x = NumericValue.asNumber(lv.get(0).evalValue(c)); + x = NumericValue.asNumber(lv.get(0)); if (lv.size() > 1) { - y = NumericValue.asNumber(lv.get(1).evalValue(c)); + y = NumericValue.asNumber(lv.get(1)); if (lv.size() > 2) - z = NumericValue.asNumber(lv.get(2).evalValue(c)); + z = NumericValue.asNumber(lv.get(2)); } } @@ -255,21 +247,20 @@ public class Sys { NumericValue.asNumber(x).getDouble(), NumericValue.asNumber(y).getDouble(), NumericValue.asNumber(z).getDouble()); - Value ret = new NumericValue(result); - return (cc, tt) -> ret; + return new NumericValue(result); }); - expression.addLazyFunction("simplex", -1, (c, t, lv) -> + expression.addFunction("simplex", lv -> { SimplexNoiseSampler sampler; Value x, y, z; if (lv.size() >= 4) { - x = lv.get(0).evalValue(c); - y = lv.get(1).evalValue(c); - z = lv.get(2).evalValue(c); - sampler = SimplexNoiseSampler.getSimplex(NumericValue.asNumber(lv.get(3).evalValue(c)).getLong()); + x = lv.get(0); + y = lv.get(1); + z = lv.get(2); + sampler = SimplexNoiseSampler.getSimplex(NumericValue.asNumber(lv.get(3)).getLong()); } else { @@ -277,10 +268,10 @@ public class Sys { z = Value.NULL; if (lv.size() < 2 ) throw new InternalExpressionException("'simplex' requires at least two dimensions to sample from"); - x = NumericValue.asNumber(lv.get(0).evalValue(c)); - y = NumericValue.asNumber(lv.get(1).evalValue(c)); + x = NumericValue.asNumber(lv.get(0)); + y = NumericValue.asNumber(lv.get(1)); if (lv.size() > 2) - z = NumericValue.asNumber(lv.get(2).evalValue(c)); + z = NumericValue.asNumber(lv.get(2)); } double result; @@ -291,8 +282,7 @@ public class Sys { NumericValue.asNumber(x).getDouble(), NumericValue.asNumber(y).getDouble(), NumericValue.asNumber(z).getDouble()); - Value ret = new NumericValue(result); - return (cc, tt) -> ret; + return new NumericValue(result); }); expression.addUnaryFunction("print", (v) -> @@ -301,17 +291,11 @@ public class Sys { return v; // pass through for variables }); - expression.addLazyFunction("time", 0, (c, t, lv) -> - { - Value time = new NumericValue((System.nanoTime() / 1000) / 1000.0); - return (cc, tt) -> time; - }); + expression.addContextFunction("time", 0, (c, t, lv) -> + new NumericValue((System.nanoTime() / 1000.0) / 1000.0)); - expression.addLazyFunction("unix_time", 0, (c, t, lv) -> - { - Value time = new NumericValue(System.currentTimeMillis()); - return (cc, tt) -> time; - }); + expression.addContextFunction("unix_time", 0, (c, t, lv) -> + new NumericValue(System.currentTimeMillis())); expression.addFunction("convert_date", lv -> { @@ -324,7 +308,7 @@ public class Sys { cal.setTimeInMillis(NumericValue.asNumber(value, "timestamp").getLong()); int weekday = cal.get(Calendar.DAY_OF_WEEK)-1; if (weekday == 0) weekday = 7; - Value retVal = ListValue.ofNums( + return ListValue.ofNums( cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH), @@ -335,7 +319,6 @@ public class Sys { cal.get(Calendar.DAY_OF_YEAR), cal.get(Calendar.WEEK_OF_YEAR) ); - return retVal; } else if(value instanceof ListValue) { @@ -367,6 +350,7 @@ public class Sys { return new NumericValue(cal.getTimeInMillis()); }); + // lazy cause evaluates expression multiple times expression.addLazyFunction("profile_expr", 1, (c, t, lv) -> { LazyValue lazy = lv.get(0); @@ -381,19 +365,16 @@ public class Sys { return (cc, tt) -> res; }); - expression.addLazyFunction("var", 1, (c, t, lv) -> - { - String varname = lv.get(0).evalValue(c).getString(); - return expression.getOrSetAnyVariable(c, varname); - }); + expression.addContextFunction("var", 1, (c, t, lv) -> + expression.getOrSetAnyVariable(c, lv.get(0).getString()).evalValue(c)); - expression.addLazyFunction("undef", 1, (c, t, lv) -> + expression.addContextFunction("undef", 1, (c, t, lv) -> { - Value remove = lv.get(0).evalValue(c); + Value remove = lv.get(0); if (remove instanceof FunctionValue) { c.host.delFunction(expression.module, remove.getString()); - return (cc, tt) -> Value.NULL; + return Value.NULL; } String varname = remove.getString(); boolean isPrefix = varname.endsWith("*"); @@ -423,13 +404,13 @@ public class Sys { c.delVariable(varname); } } - return (cc, tt) -> Value.NULL; + return Value.NULL; }); //deprecate - expression.addLazyFunction("vars", 1, (c, t, lv) -> + expression.addContextFunction("vars", 1, (c, t, lv) -> { - String prefix = lv.get(0).evalValue(c).getString(); + String prefix = lv.get(0).getString(); List values = new ArrayList<>(); if (prefix.startsWith("global")) { @@ -439,30 +420,25 @@ public class Sys { { c.getAllVariableNames().stream().filter(s -> s.startsWith(prefix)).forEach(s -> values.add(new StringValue(s))); } - Value retval = ListValue.wrap(values); - return (cc, tt) -> retval; + return ListValue.wrap(values); }); + // lazy cause default expression may not be executed if not needed expression.addLazyFunction("system_variable_get", -1, (c, t, lv) -> { if (lv.size() == 0) throw new InternalExpressionException("'system_variable_get' expects at least a key to be fetched"); Value key = lv.get(0).evalValue(c); - if (lv.size() > 1) - { - ScriptHost.systemGlobals.computeIfAbsent(key, k -> lv.get(1).evalValue(c)); - } + if (lv.size() > 1) ScriptHost.systemGlobals.computeIfAbsent(key, k -> lv.get(1).evalValue(c)); Value res = ScriptHost.systemGlobals.get(key); if (res!=null) return (cc, tt) -> res; - return (cc, tt) -> Value.NULL; + return LazyValue.NULL; }); - expression.addLazyFunction("system_variable_set", 2, (c, t, lv) -> + expression.addBinaryFunction("system_variable_set", (key, value) -> { - Value key = lv.get(0).evalValue(c); - Value value = lv.get(1).evalValue(c); Value res = ScriptHost.systemGlobals.put(key, value); - if (res!=null) return (cc, tt) -> res; - return (cc, tt) -> Value.NULL; + if (res!=null) return res; + return Value.NULL; }); } } diff --git a/src/main/java/carpet/script/language/Threading.java b/src/main/java/carpet/script/language/Threading.java index f7dd0389..ed2691eb 100644 --- a/src/main/java/carpet/script/language/Threading.java +++ b/src/main/java/carpet/script/language/Threading.java @@ -1,11 +1,9 @@ package carpet.script.language; import carpet.script.Expression; -import carpet.script.LazyValue; import carpet.script.argument.FunctionArgument; import carpet.script.exception.ExitStatement; import carpet.script.exception.InternalExpressionException; -import carpet.script.value.FunctionValue; import carpet.script.value.NumericValue; import carpet.script.value.ThreadValue; import carpet.script.value.Value; @@ -14,35 +12,30 @@ public class Threading { public static void apply(Expression expression) { - expression.addLazyFunctionWithDelegation("task", -1, (c, t, expr, tok, lv) -> + expression.addFunctionWithDelegation("task", -1, (c, t, expr, tok, lv) -> { if (lv.size() == 0) throw new InternalExpressionException("'task' requires at least function to call as a parameter"); - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, false, true); - ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, functionArgument.unpackArgs(c)); + FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, false, true); + ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, functionArgument.checkedArgs()); Thread.yield(); - return (cc, tt) -> thread; + return thread; }); - expression.addLazyFunctionWithDelegation("task_thread", -1, (c, t, expr, tok, lv) -> + expression.addFunctionWithDelegation("task_thread", -1, (c, t, expr, tok, lv) -> { if (lv.size() < 2) throw new InternalExpressionException("'task' requires at least function to call as a parameter"); - Value queue = lv.get(0).evalValue(c); - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, true); - ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.unpackArgs(c)); + Value queue = lv.get(0); + FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, true); + ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.checkedArgs()); Thread.yield(); - return (cc, tt) -> thread; + return thread; }); - expression.addLazyFunction("task_count", -1, (c, t, lv) -> - { - Value ret = (lv.size() > 0)? - new NumericValue(c.host.taskCount(lv.get(0).evalValue(c))): - new NumericValue(c.host.taskCount()); - return (cc, tt) -> ret; - }); + expression.addContextFunction("task_count", -1, (c, t, lv) -> + (lv.size() > 0)? new NumericValue(c.host.taskCount(lv.get(0))):new NumericValue(c.host.taskCount())); expression.addUnaryFunction("task_value", (v) -> { @@ -72,6 +65,7 @@ public class Threading return new NumericValue(((ThreadValue) v).isFinished()); }); + // lazy cause expr is evaluated in the same type expression.addLazyFunction("synchronize", -1, (c, t, lv) -> { if (lv.size() == 0) throw new InternalExpressionException("'synchronize' require at least an expression to synchronize"); @@ -89,6 +83,7 @@ public class Threading } }); + // lazy since exception expression is very conditional expression.addLazyFunction("sleep", -1, (c, t, lv) -> { long time = lv.isEmpty()?0L:NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index d2882c2e..3968d3a0 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -1208,7 +1208,7 @@ public class EntityValue extends Value else if (v instanceof ListValue) { List lv = ((ListValue) v).getItems(); - Vector3Argument locator = Vector3Argument.findIn(lv, 0, false); + Vector3Argument locator = Vector3Argument.findIn(lv, 0, false, false); pos = new BlockPos(locator.vec.x, locator.vec.y, locator.vec.z); if (lv.size() > locator.offset) { @@ -1237,7 +1237,7 @@ public class EntityValue extends Value else if (a instanceof ListValue) { List params= ((ListValue) a).getItems(); - Vector3Argument blockLocator = Vector3Argument.findIn(params, 0, false); + Vector3Argument blockLocator = Vector3Argument.findIn(params, 0, false, false); BlockPos pos = new BlockPos(blockLocator.vec); RegistryKey world = spe.getEntityWorld().getRegistryKey(); float angle = spe.getHeadYaw(); diff --git a/src/main/java/carpet/script/value/FunctionAnnotationValue.java b/src/main/java/carpet/script/value/FunctionAnnotationValue.java index c15ab396..41ba7914 100644 --- a/src/main/java/carpet/script/value/FunctionAnnotationValue.java +++ b/src/main/java/carpet/script/value/FunctionAnnotationValue.java @@ -5,10 +5,12 @@ import net.minecraft.nbt.Tag; public class FunctionAnnotationValue extends Value { - // 0 global - // 1 vararg - public int type; - public FunctionAnnotationValue(Value variable, int type) + public enum Type + { + GLOBAL, VARARG + } + public Type type; + public FunctionAnnotationValue(Value variable, Type type) { if (variable.boundVariable == null) throw new InternalExpressionException("You can only borrow variables from the outer scope"); diff --git a/src/main/java/carpet/script/value/FunctionValue.java b/src/main/java/carpet/script/value/FunctionValue.java index a05e87b1..b67a4211 100644 --- a/src/main/java/carpet/script/value/FunctionValue.java +++ b/src/main/java/carpet/script/value/FunctionValue.java @@ -1,5 +1,6 @@ package carpet.script.value; +import carpet.CarpetSettings; import carpet.script.Context; import carpet.script.Expression; import carpet.script.Fluff; @@ -149,11 +150,11 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction return varArgs != null; } - public LazyValue callInContext(Context c, Integer type, List lazyParams) + public LazyValue callInContext(Context c, Integer type, List args) { try { - return lazyEval(c, type, expression, token, lazyParams); + return execute(c, type, expression, token, args); } catch (ExpressionException exc) { @@ -182,10 +183,34 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction throw new InternalExpressionException("Function " + getPrettyString() + " requires " + actual + " arguments"); } + public static List unpackArgs(List lzargs, Context c) + { + // TODO we shoudn't need that if all fuctions are not lazy really + List args = new ArrayList<>(); + for (LazyValue lv : lzargs) + { + Value arg = lv.evalValue(c, Context.NONE); + if (arg instanceof FunctionUnpackedArgumentsValue) + { + CarpetSettings.LOG.error("How did we get here?"); + args.addAll(((ListValue) arg).getItems()); + } + else + { + args.add(arg); + } + } + return args; + } + @Override - public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lazyPrams) + public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lazyParams) { + List resolvedArgs = unpackArgs(lazyParams, c); + return execute(c, type, e, t, resolvedArgs); + } + + public LazyValue execute(Context c, Integer type, Expression e, Tokenizer.Token t, List resolvedArgs) { - List resolvedArgs = Fluff.AbstractFunction.unpackArgs(lazyPrams, c); assertArgsOk(resolvedArgs, (fixedArgs) ->{ if (fixedArgs) // wrong number of args for fixed args { @@ -275,12 +300,6 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction feedback.accept(false); } } - public static List resolveArgs(List lzargs, Context c, Integer t) - { - List args = new ArrayList<>(lzargs.size()); - lzargs.forEach( v -> args.add( v.evalValue(c, t))); - return args; - } public static List lazify(List args) { diff --git a/src/main/java/carpet/script/value/LContainerValue.java b/src/main/java/carpet/script/value/LContainerValue.java index b95ae723..2c46ee55 100644 --- a/src/main/java/carpet/script/value/LContainerValue.java +++ b/src/main/java/carpet/script/value/LContainerValue.java @@ -4,6 +4,7 @@ public class LContainerValue extends FrameworkValue { private ContainerValueInterface container; private Value address; + public static final LContainerValue NULL_CONTAINER = new LContainerValue(null, null); public LContainerValue(ContainerValueInterface c, Value v) { diff --git a/src/main/java/carpet/script/value/NBTSerializableValue.java b/src/main/java/carpet/script/value/NBTSerializableValue.java index 9c26f252..568cb7c8 100644 --- a/src/main/java/carpet/script/value/NBTSerializableValue.java +++ b/src/main/java/carpet/script/value/NBTSerializableValue.java @@ -81,6 +81,12 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa owned = true; } + public static Value of(Tag tag) + { + if (tag == null) return Value.NULL; + return new NBTSerializableValue(tag); + } + public NBTSerializableValue(Supplier tagSupplier) { nbtSupplier = tagSupplier; @@ -178,29 +184,29 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa return inventory; } - public static InventoryLocator locateInventory(CarpetContext c, List params, int offset) + public static InventoryLocator locateInventory(CarpetContext c, List params, int offset) { try { - Value v1 = params.get(offset).evalValue(c); + Value v1 = params.get(offset); if (v1.isNull()) { offset ++; - v1 = params.get(offset).evalValue(c); + v1 = params.get(offset); } else if (v1 instanceof StringValue) { String strVal = v1.getString().toLowerCase(Locale.ROOT); if (strVal.equals("enderchest")) { - Value v2 = params.get(1 + offset).evalValue(c); + Value v2 = params.get(1 + offset); ServerPlayerEntity player = EntityValue.getPlayerByValue(c.s.getMinecraftServer(), v2); if (player == null) throw new InternalExpressionException("enderchest inventory requires player argument"); return new InventoryLocator(player, player.getBlockPos(), player.getEnderChestInventory(), offset + 2, true); } if (strVal.equals("equipment")) { - Value v2 = params.get(1 + offset).evalValue(c); + Value v2 = params.get(1 + offset); if (!(v2 instanceof EntityValue)) throw new InternalExpressionException("Equipment inventory requires a living entity argument"); Entity e = ((EntityValue) v2).getEntity(); if (!(e instanceof LivingEntity)) throw new InternalExpressionException("Equipment inventory requires a living entity argument"); @@ -256,8 +262,8 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa } BlockPos pos = new BlockPos( NumericValue.asNumber(v1).getDouble(), - NumericValue.asNumber(params.get(1 + offset).evalValue(c)).getDouble(), - NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble()); + NumericValue.asNumber(params.get(1 + offset)).getDouble(), + NumericValue.asNumber(params.get(2 + offset)).getDouble()); Inventory inv = getInventoryAt(c.s.getWorld(), pos); if (inv == null) return null; diff --git a/src/main/java/carpet/script/value/ThreadValue.java b/src/main/java/carpet/script/value/ThreadValue.java index fd833bec..d3494ea1 100644 --- a/src/main/java/carpet/script/value/ThreadValue.java +++ b/src/main/java/carpet/script/value/ThreadValue.java @@ -35,7 +35,7 @@ public class ThreadValue extends Value { try { - return function.lazyEval(ctx, Context.NONE, expr, token, FunctionValue.lazify(args)).evalValue(ctx); + return function.execute(ctx, Context.NONE, expr, token, args).evalValue(ctx); } catch (ExitStatement exit) { From 5edbbe3fe2213c5fccd4c2ff1546e2321ea72d0b Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 22 Apr 2021 22:25:46 -0300 Subject: [PATCH 4/8] remane --- .../carpet/script/value/FunctionValue.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/main/java/carpet/script/value/FunctionValue.java b/src/main/java/carpet/script/value/FunctionValue.java index b67a4211..588b755c 100644 --- a/src/main/java/carpet/script/value/FunctionValue.java +++ b/src/main/java/carpet/script/value/FunctionValue.java @@ -150,11 +150,11 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction return varArgs != null; } - public LazyValue callInContext(Context c, Integer type, List args) + public LazyValue callInContext(Context c, Integer type, List params) { try { - return execute(c, type, expression, token, args); + return execute(c, type, expression, token, params); } catch (ExpressionException exc) { @@ -183,40 +183,40 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction throw new InternalExpressionException("Function " + getPrettyString() + " requires " + actual + " arguments"); } - public static List unpackArgs(List lzargs, Context c) + public static List unpackArgs(List lazyParams, Context c) { // TODO we shoudn't need that if all fuctions are not lazy really - List args = new ArrayList<>(); - for (LazyValue lv : lzargs) + List params = new ArrayList<>(); + for (LazyValue lv : lazyParams) { - Value arg = lv.evalValue(c, Context.NONE); - if (arg instanceof FunctionUnpackedArgumentsValue) + Value param = lv.evalValue(c, Context.NONE); + if (param instanceof FunctionUnpackedArgumentsValue) { CarpetSettings.LOG.error("How did we get here?"); - args.addAll(((ListValue) arg).getItems()); + params.addAll(((ListValue) param).getItems()); } else { - args.add(arg); + params.add(param); } } - return args; + return params; } @Override public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lazyParams) { - List resolvedArgs = unpackArgs(lazyParams, c); - return execute(c, type, e, t, resolvedArgs); + List resolvedParams = unpackArgs(lazyParams, c); + return execute(c, type, e, t, resolvedParams); } - public LazyValue execute(Context c, Integer type, Expression e, Tokenizer.Token t, List resolvedArgs) + public LazyValue execute(Context c, Integer type, Expression e, Tokenizer.Token t, List params) { - assertArgsOk(resolvedArgs, (fixedArgs) ->{ + assertArgsOk(params, (fixedArgs) ->{ if (fixedArgs) // wrong number of args for fixed args { throw new ExpressionException(c, e, t, "Incorrect number of arguments for function "+name+ - ". Should be "+args.size()+", not "+resolvedArgs.size()+" like "+args + ". Should be "+args.size()+", not "+params.size()+" like "+args ); } else // too few args for varargs @@ -225,7 +225,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction argList.add("... "+varArgs); throw new ExpressionException(c, e, t, "Incorrect number of arguments for function "+name+ - ". Should be at least "+args.size()+", not "+resolvedArgs.size()+" like "+argList + ". Should be at least "+args.size()+", not "+params.size()+" like "+argList ); } }); @@ -235,15 +235,15 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction for (int i=0; i val); } if (varArgs != null) { List extraParams = new ArrayList<>(); - for (int i = args.size(), mx = resolvedArgs.size(); i < mx; i++) + for (int i = args.size(), mx = params.size(); i < mx; i++) { - extraParams.add(resolvedArgs.get(i).reboundedTo(null)); // copy by value I guess + extraParams.add(params.get(i).reboundedTo(null)); // copy by value I guess } Value rest = ListValue.wrap(extraParams).bindTo(varArgs); // didn't we just copied that? newFrame.setVariable(varArgs, (cc, tt) -> rest); From a6f39e2d22d5ee327e0d1d5725318cc107228975 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 22 Apr 2021 22:26:07 -0300 Subject: [PATCH 5/8] scarpet LOG --- src/main/java/carpet/CarpetServer.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index ae9e4dce..f175e1a2 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -36,10 +36,13 @@ import net.fabricmc.loader.api.FabricLoader; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; public class CarpetServer implements ClientModInitializer,DedicatedServerModInitializer // static for now - easier to handle all around the code, its one anyways { public static final Random rand = new Random(); + public static final Logger LOG = LogManager.getLogger("scarpet"); public static MinecraftServer minecraft_server; private static CommandDispatcher currentCommandDispatcher; public static CarpetScriptServer scriptServer; From d072ec90c3e0ab6c30dbc34604f3fe319d06d3bc Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 22 Apr 2021 22:26:35 -0300 Subject: [PATCH 6/8] hold your horses --- .../java/carpet/script/value/EntityValue.java | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 3968d3a0..e8e55c3f 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -1,5 +1,6 @@ package carpet.script.value; +import carpet.CarpetServer; import carpet.fakes.BrainInterface; import carpet.fakes.EntityInterface; import carpet.fakes.ItemEntityInterface; @@ -917,9 +918,11 @@ public class EntityValue extends Value } } - private static void updateVelocity(Entity e) + private static void updateVelocity(Entity e, double scale) { e.velocityModified = true; + if (Math.abs(scale) > 10000) + CarpetServer.LOG.warn("Moved entity "+e.getEntityName()+" "+e.getName()+" at " +e.getPos()+" extremly fast: "+e.getVelocity()); //((ServerWorld)e.getEntityWorld()).method_14178().sendToNearbyPlayers(e, new EntityVelocityUpdateS2CPacket(e)); } @@ -1051,30 +1054,32 @@ public class EntityValue extends Value throw new InternalExpressionException("Expected a list of 3 parameters as a second argument"); } List coords = ((ListValue) v).getItems(); - e.setVelocity( - NumericValue.asNumber(coords.get(0)).getDouble(), - NumericValue.asNumber(coords.get(1)).getDouble(), - NumericValue.asNumber(coords.get(2)).getDouble() - ); - updateVelocity(e); + double dx = NumericValue.asNumber(coords.get(0)).getDouble(); + double dy = NumericValue.asNumber(coords.get(0)).getDouble(); + double dz = NumericValue.asNumber(coords.get(2)).getDouble(); + e.setVelocity(dx, dy, dz); + updateVelocity(e, MathHelper.absMax(MathHelper.absMax(dx, dy), dz)); }); put("motion_x", (e, v) -> { Vec3d velocity = e.getVelocity(); - e.setVelocity(NumericValue.asNumber(v).getDouble(), velocity.y, velocity.z); - updateVelocity(e); + double dv = NumericValue.asNumber(v).getDouble(); + e.setVelocity(dv, velocity.y, velocity.z); + updateVelocity(e, dv); }); put("motion_y", (e, v) -> { Vec3d velocity = e.getVelocity(); - e.setVelocity(velocity.x, NumericValue.asNumber(v).getDouble(), velocity.z); - updateVelocity(e); + double dv = NumericValue.asNumber(v).getDouble(); + e.setVelocity(velocity.x, dv, velocity.z); + updateVelocity(e, dv); }); put("motion_z", (e, v) -> { Vec3d velocity = e.getVelocity(); - e.setVelocity(velocity.x, velocity.y, NumericValue.asNumber(v).getDouble()); - updateVelocity(e); + double dv = NumericValue.asNumber(v).getDouble(); + e.setVelocity(velocity.x, velocity.y, dv); + updateVelocity(e, dv); }); put("accelerate", (e, v) -> @@ -1089,7 +1094,7 @@ public class EntityValue extends Value NumericValue.asNumber(coords.get(1)).getDouble(), NumericValue.asNumber(coords.get(2)).getDouble() ); - updateVelocity(e); + updateVelocity(e, e.getVelocity().length()); }); put("custom_name", (e, v) -> { From edca3fb131ce3b14630471d3994fc031e4e47932 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 22 Apr 2021 22:30:45 -0300 Subject: [PATCH 7/8] using proper logger now --- src/main/java/carpet/CarpetServer.java | 3 --- .../java/carpet/script/CarpetScriptServer.java | 3 +++ src/main/java/carpet/script/api/Auxiliary.java | 16 +++++++--------- .../java/carpet/script/value/EntityValue.java | 3 ++- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index f175e1a2..ae9e4dce 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -36,13 +36,10 @@ import net.fabricmc.loader.api.FabricLoader; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; public class CarpetServer implements ClientModInitializer,DedicatedServerModInitializer // static for now - easier to handle all around the code, its one anyways { public static final Random rand = new Random(); - public static final Logger LOG = LogManager.getLogger("scarpet"); public static MinecraftServer minecraft_server; private static CommandDispatcher currentCommandDispatcher; public static CarpetScriptServer scriptServer; diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index 10faab8f..01048258 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -20,6 +20,8 @@ import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.WorldSavePath; import net.minecraft.util.math.BlockPos; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.io.IOException; import java.nio.file.FileVisitOption; @@ -43,6 +45,7 @@ import static net.minecraft.server.command.CommandManager.literal; public class CarpetScriptServer { //make static for now, but will change that later: + public static final Logger LOG = LogManager.getLogger("scarpet"); public final MinecraftServer server; public CarpetScriptHost globalHost; public Map modules; diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java index 0db652ca..f3b02aac 100644 --- a/src/main/java/carpet/script/api/Auxiliary.java +++ b/src/main/java/carpet/script/api/Auxiliary.java @@ -1,7 +1,6 @@ package carpet.script.api; import carpet.CarpetServer; -import carpet.CarpetSettings; import carpet.fakes.MinecraftServerInterface; import carpet.fakes.ServerWorldInterface; import carpet.fakes.StatTypeInterface; @@ -628,7 +627,7 @@ public class Auxiliary { s.getMinecraftServer().getPlayerManager().saveAllPlayerData(); s.getMinecraftServer().save(true,true,true); s.getWorld().getChunkManager().tick(() -> true); - CarpetSettings.LOG.warn("Saved chunks"); + CarpetScriptServer.LOG.warn("Saved chunks"); return Value.TRUE; }); @@ -797,24 +796,23 @@ public class Auxiliary { expression.addFunction("logger", lv -> { - //CarpetSettings.LOG.error(Registry.ENTITY_TYPE.getIds().stream().sorted().map(ValueConversions::simplify).collect(Collectors.joining("`, `"))); Value res; if(lv.size()==1) { res = lv.get(0); - CarpetSettings.LOG.info(res.getString()); + CarpetScriptServer.LOG.info(res.getString()); } else if(lv.size()==2) { String level = lv.get(0).getString().toLowerCase(Locale.ROOT); res = lv.get(1); switch(level){ - case "error": CarpetSettings.LOG.error(res.getString()); break; - case "warn": CarpetSettings.LOG.warn(res.getString()); break; - case "debug": CarpetSettings.LOG.debug(res.getString()); break; - case "fatal": CarpetSettings.LOG.fatal(res.getString()); break; - case "info": CarpetSettings.LOG.info(res.getString()); break; + case "error": CarpetScriptServer.LOG.error(res.getString()); break; + case "warn": CarpetScriptServer.LOG.warn(res.getString()); break; + case "debug": CarpetScriptServer.LOG.debug(res.getString()); break; + case "fatal": CarpetScriptServer.LOG.fatal(res.getString()); break; + case "info": CarpetScriptServer.LOG.info(res.getString()); break; default: throw new InternalExpressionException("Unknown log level for 'logger': "+level); } } diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index e8e55c3f..500a1017 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -14,6 +14,7 @@ import carpet.helpers.Tracer; import carpet.network.ServerNetworkHandler; import carpet.patches.EntityPlayerMPFake; import carpet.script.CarpetContext; +import carpet.script.CarpetScriptServer; import carpet.script.EntityEventsGroup; import carpet.script.argument.Vector3Argument; import carpet.script.exception.InternalExpressionException; @@ -922,7 +923,7 @@ public class EntityValue extends Value { e.velocityModified = true; if (Math.abs(scale) > 10000) - CarpetServer.LOG.warn("Moved entity "+e.getEntityName()+" "+e.getName()+" at " +e.getPos()+" extremly fast: "+e.getVelocity()); + CarpetScriptServer.LOG.warn("Moved entity "+e.getEntityName()+" "+e.getName()+" at " +e.getPos()+" extremly fast: "+e.getVelocity()); //((ServerWorld)e.getEntityWorld()).method_14178().sendToNearbyPlayers(e, new EntityVelocityUpdateS2CPacket(e)); } From bed9e2c60a22dad3654bf03b1f56aa24e28b08de Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 23 Apr 2021 01:20:42 -0300 Subject: [PATCH 8/8] docs --- docs/scarpet/language/Operators.md | 25 +++++++++++++++++-- src/main/java/carpet/script/Expression.java | 18 ++++++------- src/main/java/carpet/script/Fluff.java | 9 +++---- .../carpet/script/language/Functions.java | 4 +-- .../carpet/script/language/Operators.java | 8 +++--- .../value/FunctionUnpackedArgumentsValue.java | 13 ++++++++++ 6 files changed, 56 insertions(+), 21 deletions(-) diff --git a/docs/scarpet/language/Operators.md b/docs/scarpet/language/Operators.md index 0024c4c1..ea59aa6e 100644 --- a/docs/scarpet/language/Operators.md +++ b/docs/scarpet/language/Operators.md @@ -29,11 +29,12 @@ Here is the complete list of operators in `scarpet` including control flow opera are not technically operators, but part of the language, even if they look like them: * Match, Get `~ :` -* Unary `+ - !` +* Unary `+ - ! ...` * Exponent `^` * Multiplication `* / %` * Addition `+ -` -* Comparison `== != > >= <= <` +* Comparison `> >= <= <` +* Equality `== !=` * Logical And`&&` * Logical Or `||` * Assignment `= += <>` @@ -234,3 +235,23 @@ flips boolean condition of the expression. Equivalent of `bool(expr)==false` !l() => true !l(null) => false + +### `Unpacking Operator ...` + +Unpacks elements of a list of an iterator into a sequence of arguments in a function making so that `fun(...[1, 2, 3])` is +identical with `fun(1, 2, 3)`. + +In function signatures it identifies a vararg parameter. + +`fun(a, b, ... rest) -> [a, b, rest]; fun(1, 2, 3, 4)` => `[1, 2, [3, 4]]` + +Effects of `...` can be surprisingly lasting. It is kept through the use of variables and function calls. + +`fun(a, b, ... rest) -> [a, b, ... rest]; fun(1, 2, 3, 4)` => `[1, 2, 3, 4]` +`args() -> ... [1, 2, 3]; sum(a, b, c) -> a+b+c; sum(args())` => `6` +`a = ... [1, 2, 3]; sum(a, b, c) -> a+b+c; sum(a)` => `6` + +Unpacking mechanics can be used for list and map constriction, not just for function calls. + +`[...range(5), pi, ...range(5,-1,-1)]` => `[0, 1, 2, 3, 4, 3.14159265359, 5, 4, 3, 2, 1, 0]` +`{ ... map(range(5), _ -> _*_ )}` => `{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}` diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 28b6a2fa..770b64d2 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -188,7 +188,7 @@ public class Expression public void addLazyFunctionWithDelegation(String name, int numpar, QuinnFunction, LazyValue> lazyfun) { - functions.put(name, new AbstractLazyFunction(numpar) + functions.put(name, new AbstractLazyFunction(numpar, name) { @Override public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lv) @@ -208,7 +208,7 @@ public class Expression public void addFunctionWithDelegation(String name, int numpar, QuinnFunction, Value> fun) { - functions.put(name, new AbstractLazyFunction(numpar) + functions.put(name, new AbstractLazyFunction(numpar, name) { @Override public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List lv) @@ -286,7 +286,7 @@ public class Expression public void addUnaryOperator(String surface, boolean leftAssoc, Function fun) { - operators.put(surface+"u", new AbstractUnaryOperator(Operators.precedence.get("unary+-!"), leftAssoc) + operators.put(surface+"u", new AbstractUnaryOperator(Operators.precedence.get("unary+-!..."), leftAssoc) { @Override public Value evalUnary(Value v1) @@ -312,7 +312,7 @@ public class Expression public void addUnaryFunction(String name, Function fun) { - functions.put(name, new AbstractFunction(1) + functions.put(name, new AbstractFunction(1, name) { @Override public Value eval(List parameters) @@ -324,7 +324,7 @@ public class Expression public void addBinaryFunction(String name, BiFunction fun) { - functions.put(name, new AbstractFunction(2) + functions.put(name, new AbstractFunction(2, name) { @Override public Value eval(List parameters) @@ -339,7 +339,7 @@ public class Expression public void addFunction(String name, Function, Value> fun) { - functions.put(name, new AbstractFunction(-1) + functions.put(name, new AbstractFunction(-1, name) { @Override public Value eval(List parameters) @@ -370,7 +370,7 @@ public class Expression public void addLazyFunction(String name, int num_params, TriFunction, LazyValue> fun) { - functions.put(name, new AbstractLazyFunction(num_params) + functions.put(name, new AbstractLazyFunction(num_params, name) { @Override public LazyValue lazyEval(Context c, Integer i, Expression e, Tokenizer.Token t, List lazyParams) @@ -389,7 +389,7 @@ public class Expression public void addContextFunction(String name, int num_params, TriFunction, Value> fun) { - functions.put(name, new AbstractLazyFunction(num_params) + functions.put(name, new AbstractLazyFunction(num_params, name) { @Override public LazyValue lazyEval(Context c, Integer i, Expression e, Tokenizer.Token t, List lazyParams) @@ -409,7 +409,7 @@ public class Expression public void addTypedContextFunction(String name, int num_params, int reqType, TriFunction, Value> fun) { - functions.put(name, new AbstractLazyFunction(num_params) + functions.put(name, new AbstractLazyFunction(num_params, name) { @Override public LazyValue lazyEval(Context c, Integer i, Expression e, Tokenizer.Token t, List lazyParams) diff --git a/src/main/java/carpet/script/Fluff.java b/src/main/java/carpet/script/Fluff.java index dc41d936..122d75c5 100644 --- a/src/main/java/carpet/script/Fluff.java +++ b/src/main/java/carpet/script/Fluff.java @@ -64,9 +64,10 @@ public abstract class Fluff protected String name; int numParams; - AbstractLazyFunction(int numParams) + AbstractLazyFunction(int numParams, String name) { this.numParams = numParams; + this.name = name; } @@ -115,12 +116,10 @@ public abstract class Fluff public abstract static class AbstractFunction extends AbstractLazyFunction implements IFunction { - AbstractFunction(int numParams) { - super(numParams); + AbstractFunction(int numParams, String name) { + super(numParams, name); } - - @Override public LazyValue lazyEval(Context cc, Integer type, Expression e, Tokenizer.Token t, final List lazyParams) { diff --git a/src/main/java/carpet/script/language/Functions.java b/src/main/java/carpet/script/language/Functions.java index 25fa7825..54d43629 100644 --- a/src/main/java/carpet/script/language/Functions.java +++ b/src/main/java/carpet/script/language/Functions.java @@ -93,7 +93,7 @@ public class Functions { }); // lazy because of typed evaluation of the argument - expression.addLazyUnaryOperator("...", Operators.precedence.get("def->..."), false, (c, t, lv) -> + expression.addLazyUnaryOperator("...", Operators.precedence.get("unary+-!..."), false, (c, t, lv) -> { if (t == Context.LOCALIZATION) return (cc, tt) -> new FunctionAnnotationValue(lv.evalValue(c), FunctionAnnotationValue.Type.VARARG); @@ -116,7 +116,7 @@ public class Functions { //assigns const procedure to the lhs, returning its previous value // must be lazy due to RHS being an expression to save to execute - expression.addLazyBinaryOperatorWithDelegation("->", Operators.precedence.get("def->..."), false, (c, type, e, t, lv1, lv2) -> + expression.addLazyBinaryOperatorWithDelegation("->", Operators.precedence.get("def->"), false, (c, type, e, t, lv1, lv2) -> { if (type == Context.MAPDEF) { diff --git a/src/main/java/carpet/script/language/Operators.java b/src/main/java/carpet/script/language/Operators.java index 389623e1..56a92184 100644 --- a/src/main/java/carpet/script/language/Operators.java +++ b/src/main/java/carpet/script/language/Operators.java @@ -20,7 +20,7 @@ import java.util.Map; public class Operators { public static final Map precedence = new HashMap() {{ put("attribute~:", 80); - put("unary+-!", 60); + put("unary+-!...", 60); put("exponent^", 40); put("multiplication*/%", 30); put("addition+-", 20); @@ -29,7 +29,7 @@ public class Operators { put("and&&", 5); put("or||", 4); put("assign=<>", 3); - put("def->...", 2); + put("def->", 2); put("nextop;", 1); }}; @@ -216,7 +216,9 @@ public class Operators { expression.addUnaryOperator("+", false, NumericValue::asNumber); // could be non-lazy, but who cares - its a small one. - expression.addLazyUnaryOperator("!", precedence.get("unary+-!"), false, (c, t, lv)-> lv.evalValue(c, Context.BOOLEAN).getBoolean() ? (cc, tt)-> Value.FALSE : (cc, tt) -> Value.TRUE); // might need context boolean + expression.addLazyUnaryOperator("!", precedence.get("unary+-!..."), false, (c, t, lv) -> + lv.evalValue(c, Context.BOOLEAN).getBoolean() ? (cc, tt)-> Value.FALSE : (cc, tt) -> Value.TRUE + ); // might need context boolean } } diff --git a/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java b/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java index 8c053e7b..e33a64eb 100644 --- a/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java +++ b/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java @@ -7,4 +7,17 @@ public class FunctionUnpackedArgumentsValue extends ListValue public FunctionUnpackedArgumentsValue(List list) { super(list); } + + @Override + public Value clone() + { + return new FunctionUnpackedArgumentsValue(items); + } + + @Override + public Value deepcopy() + { + ListValue copy = (ListValue)super.deepcopy(); + return new FunctionUnpackedArgumentsValue(copy.items); + } }