Merge branch 'master' into 1.17

# Conflicts:
#	src/main/java/carpet/script/api/Auxiliary.java
#	src/main/java/carpet/script/api/Entities.java
#	src/main/java/carpet/script/api/Inventories.java
#	src/main/java/carpet/script/api/Scoreboards.java
#	src/main/java/carpet/script/api/WorldAccess.java
#	src/main/java/carpet/script/value/FunctionValue.java
#	src/main/java/carpet/script/value/NBTSerializableValue.java
This commit is contained in:
gnembon committed 2021-04-23 01:46:11 -03:00
commit 5e3812e1f0
35 files changed
+1226 -1392

No files matched your search

+39 -17
View File
@@ -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
</pre>
### `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
+23 -2
View File
@@ -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
</pre>
### `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}`
@@ -134,7 +134,7 @@ public class CarpetScriptHost extends ScriptHost
return host;
}
private static int execute(CommandContext<ServerCommandSource> ctx, String hostName, FunctionArgument<Value> funcSpec, List<String> paramNames) throws CommandSyntaxException
private static int execute(CommandContext<ServerCommandSource> ctx, String hostName, FunctionArgument funcSpec, List<String> 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<ServerCommandSource> addPathToCommand(
LiteralArgumentBuilder<ServerCommandSource> command,
List<CommandToken> path,
FunctionArgument<Value> functionSpec
FunctionArgument functionSpec
) throws CommandSyntaxException
{
String hostName = main.getName();
@@ -180,14 +180,14 @@ public class CarpetScriptHost extends ScriptHost
}
public LiteralArgumentBuilder<ServerCommandSource> getNewCommandTree(
List<Pair<List<CommandToken>,FunctionArgument<Value>>> entries, Function<ServerCommandSource, Boolean> useValidator
List<Pair<List<CommandToken>,FunctionArgument>> entries, Function<ServerCommandSource, Boolean> useValidator
) throws CommandSyntaxException
{
String hostName = main.getName();
Function<ServerCommandSource, Boolean> configValidator = getCommandConfigPermissions();
LiteralArgumentBuilder<ServerCommandSource> command = literal(hostName).
requires((player) -> CarpetServer.scriptServer.modules.containsKey(hostName) && useValidator.apply(player) && configValidator.apply(player));
for (Pair<List<CommandToken>,FunctionArgument<Value>> commandData : entries)
for (Pair<List<CommandToken>,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<Pair<List<CommandToken>,FunctionArgument<Value>>> commandEntries = new ArrayList<>();
List<Pair<List<CommandToken>,FunctionArgument>> commandEntries = new ArrayList<>();
for (Map.Entry<Value, Value> commandsData : ((MapValue)commands).getMap().entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toList()))
{
List<CommandToken> elements = CommandToken.parseSpec(commandsData.getKey().getString(), this);
FunctionArgument<Value> 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<Value> suppliedArgs)
public Value call(ServerCommandSource source, FunctionValue function, List<Value> argv)
{
if (CarpetServer.scriptServer.stopAll)
throw new CarpetExpressionException("SCARPET PAUSED", null);
List<LazyValue> argv = FunctionValue.lazify(suppliedArgs);
List<String> 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<args.size()?args.get(i):"??")+" => "+(i<argv.size()?argv.get(i).evalValue(null).getString():"??")+"\n";
error += (i<args.size()?args.get(i):"??")+" => "+(i<argv.size()?argv.get(i).getString():"??")+"\n";
}
throw new CarpetExpressionException(error, null);
}
@@ -828,7 +826,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, BlockPos.ORIGIN);
return function.getExpression().evalValue(
() -> 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);
}
@@ -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<String, CarpetScriptHost> modules;
+100 -12
View File
@@ -188,7 +188,7 @@ public class Expression
public void addLazyFunctionWithDelegation(String name, int numpar,
QuinnFunction<Context, Integer, Expression, Tokenizer.Token, List<LazyValue>, 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<LazyValue> lv)
@@ -205,6 +205,27 @@ public class Expression
});
}
public void addFunctionWithDelegation(String name, int numpar,
QuinnFunction<Context, Integer, Expression, Tokenizer.Token, List<Value>, Value> fun)
{
functions.put(name, new AbstractLazyFunction(numpar, name)
{
@Override
public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List<LazyValue> 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<Context, Integer, LazyValue, LazyValue, LazyValue> lazyfun)
{
@@ -226,6 +247,28 @@ public class Expression
});
}
public void addBinaryContextOperator(String surface, int precedence, boolean leftAssoc,
QuadFunction<Context, Integer, Value, Value, Value> 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)
@@ -243,7 +286,7 @@ public class Expression
public void addUnaryOperator(String surface, boolean leftAssoc, Function<Value, Value> 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)
@@ -269,7 +312,7 @@ public class Expression
public void addUnaryFunction(String name, Function<Value, Value> fun)
{
functions.put(name, new AbstractFunction(1)
functions.put(name, new AbstractFunction(1, name)
{
@Override
public Value eval(List<Value> parameters)
@@ -281,7 +324,7 @@ public class Expression
public void addBinaryFunction(String name, BiFunction<Value, Value, Value> fun)
{
functions.put(name, new AbstractFunction(2)
functions.put(name, new AbstractFunction(2, name)
{
@Override
public Value eval(List<Value> parameters)
@@ -296,7 +339,7 @@ public class Expression
public void addFunction(String name, Function<List<Value>, Value> fun)
{
functions.put(name, new AbstractFunction(-1)
functions.put(name, new AbstractFunction(-1, name)
{
@Override
public Value eval(List<Value> parameters)
@@ -327,7 +370,7 @@ public class Expression
public void addLazyFunction(String name, int num_params, TriFunction<Context, Integer, List<LazyValue>, 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<LazyValue> lazyParams)
@@ -343,6 +386,47 @@ public class Expression
}
});
}
public void addContextFunction(String name, int num_params, TriFunction<Context, Integer, List<Value>, Value> fun)
{
functions.put(name, new AbstractLazyFunction(num_params, name)
{
@Override
public LazyValue lazyEval(Context c, Integer i, Expression e, Tokenizer.Token t, List<LazyValue> 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<Context, Integer, List<Value>, Value> fun)
{
functions.put(name, new AbstractLazyFunction(num_params, name)
{
@Override
public LazyValue lazyEval(Context c, Integer i, Expression e, Tokenizer.Token t, List<LazyValue> 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<String> arguments, String varArgs, List<String> outers, LazyValue code)
{
if (functions.containsKey(name))
@@ -773,12 +857,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");
+43 -6
View File
@@ -1,6 +1,10 @@
package carpet.script;
import carpet.CarpetSettings;
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;
@@ -60,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;
}
@@ -77,12 +82,42 @@ public abstract class Fluff
public boolean numParamsVaries() {
return numParams < 0;
}
public static List<Value> unpackLazy(List<LazyValue> lzargs, Context c, int contextType)
{
List<Value> 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<Value> unpackArgs(List<LazyValue> lzargs, Context c, int contextType)
{
List<Value> 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
{
AbstractFunction(int numParams) {
super(numParams);
AbstractFunction(int numParams, String name) {
super(numParams, name);
}
@Override
@@ -100,10 +135,12 @@ public abstract class Fluff
private List<Value> 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, Context.NONE);
}
else
{
CarpetSettings.LOG.error("How did we get here 1");
}
return params;
}
+184 -265
View File
@@ -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;
@@ -15,7 +14,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 +26,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;
@@ -155,16 +153,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;
@@ -172,13 +169,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");
}
@@ -192,39 +189,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());
}
}
}
@@ -246,29 +237,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();
@@ -282,34 +273,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();
@@ -330,13 +320,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();
@@ -345,7 +335,7 @@ public class Auxiliary {
List<Pair<ShapeDispatcher.ExpiringShape, Map<String,Value>>> 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())
{
@@ -355,19 +345,17 @@ public class Auxiliary {
}
else
{
List<Value> 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;
@@ -375,16 +363,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();
}
}
}
@@ -437,11 +425,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());
@@ -450,34 +437,18 @@ public class Auxiliary {
total ++;
e.discard(); // discard // 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(NbtString.escape(string));
return (cc, tt) -> ret;
});
expression.addUnaryFunction("escape_nbt", v -> new StringValue(NbtString.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) -> {
@@ -490,11 +461,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();
NbtElement tag;
try
{
@@ -504,17 +475,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<ServerPlayerEntity> targets = null;
if (lv.size() == 2)
{
@@ -526,7 +496,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)
@@ -537,13 +507,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<ServerPlayerEntity> targets = ((ListValue) pVal).getItems().stream().map(v ->
@@ -554,7 +523,7 @@ public class Auxiliary {
});
Function<Text, Packet<?>> packetGetter = null;
//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":
@@ -594,7 +563,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();
}
@@ -620,15 +589,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());
}
TitleFadeS2CPacket timesPacket; // 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 TitleFadeS2CPacket(in, stay, out);
//timesPacket = new TitleS2CPacket(Action.TIMES, null, in, stay, out);
}
@@ -642,20 +611,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<Value> 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;
@@ -665,56 +631,48 @@ public class Auxiliary {
List<Text> 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;
CarpetScriptServer.LOG.warn("Saved chunks");
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.
@@ -725,12 +683,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");
@@ -741,7 +698,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)
@@ -764,17 +721,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);
@@ -782,21 +738,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);
@@ -810,7 +761,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<Value, Value> plopData = new HashMap<>();
@@ -831,13 +782,12 @@ public class Auxiliary {
plopData.put(StringValue.of("configured_structures"),
ListValue.wrap(registryManager.get(Registry.CONFIGURED_STRUCTURE_FEATURE_KEY).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( () ->
{
@@ -849,71 +799,67 @@ 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<LazyValue> functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, true);
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,
FunctionValue.resolveArgs(functionArgument.args, c, t),
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);
CarpetSettings.LOG.info(res.getString());
res = lv.get(0);
CarpetScriptServer.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;
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);
}
}
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<String> 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)
{
NbtElement 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)
@@ -929,25 +875,23 @@ public class Auxiliary {
else
{
List<String> 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());
@@ -956,7 +900,7 @@ public class Auxiliary {
}
else if (fdesc.type == FileArgument.Type.JSON)
{
List<String> data = Collections.singletonList(GSON.toJson(lv.get(2).evalValue(c).toJson()));
List<String> data = Collections.singletonList(GSON.toJson(lv.get(2).toJson()));
((CarpetScriptHost) c.host).removeResourceFile(fdesc);
success = ((CarpetScriptHost) c.host).appendLogFile(fdesc, data);
}
@@ -965,7 +909,7 @@ public class Auxiliary {
List<String> data = new ArrayList<>();
if (lv.size()==3)
{
Value val = lv.get(2).evalValue(c);
Value val = lv.get(2);
if (val instanceof ListValue)
{
List<Value> lval = ((ListValue) val).getItems();
@@ -980,166 +924,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);
}
NbtElement 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());
NbtElement 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<LazyValue> 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, FunctionValue.resolveArgs(callback.args, c, t) )?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<Value> 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();
NbtCompound 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( () ->
{
@@ -1184,10 +1106,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();
@@ -1207,7 +1129,7 @@ public class Auxiliary {
RegistryOps<NbtElement> 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
@@ -1232,8 +1154,7 @@ public class Auxiliary {
existing_worlds.put(registryKey2, serverWorld2);
}
}
Value ret = ListValue.wrap(addeds);
return (_c, _t) -> ret;
return ListValue.wrap(addeds);
});
}
@@ -1290,8 +1211,6 @@ public class Auxiliary {
}
}
private static <T> Stat<T> getStat(StatType<T> type, Identifier id)
{
T key = type.getRegistry().get(id);
@@ -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<Value> 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<Value> 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;
+55 -86
View File
@@ -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 EntityValue.of(closestPlayer);
}
return (_c, _t) -> Value.NULL;
}
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<? extends Entity> 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);
NbtCompound tag = new NbtCompound();
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<? extends Entity> 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<? extends Entity> 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<Value> 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<String> descriptors = (entityValue instanceof ListValue)
? ((ListValue) entityValue).getItems().stream().map(Value::getString).collect(Collectors.toList())
: Collections.singletonList(entityValue.getString());
Set<EntityType<? extends Entity>> types = new HashSet<>();
descriptors.forEach(s -> types.addAll(EntityValue.getEntityDescriptor(s, ((CarpetContext) c).s.getMinecraftServer()).typeList));
FunctionArgument<LazyValue> 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, FunctionValue.resolveArgs(funArg.args, c, t)));
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<LazyValue> 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, FunctionValue.resolveArgs(funArg.args, c, t));
((EntityValue) v).setEvent((CarpetContext)c, what, funArg.function, funArg.args);
return LazyValue.NULL;
return Value.NULL;
});
}
}
+75 -129
View File
@@ -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;
@@ -50,68 +50,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<Item> itemTag = tagManager.getOrCreateTagGroup(Registry.ITEM_KEY).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.getOrCreateTagGroup(Registry.ITEM_KEY).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.getOrCreateTagGroup(Registry.ITEM_KEY).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.getOrCreateTagGroup(Registry.ITEM_KEY).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();
Tag<Item> itemTag = tagManager.getOrCreateTagGroup(Registry.ITEM_KEY).getTag(new Identifier(tag));
if (itemTag == null) return LazyValue.NULL;
return itemTag.contains(item)?LazyValue.TRUE:LazyValue.FALSE;
return ListValue.wrap(tagManager.getOrCreateTagGroup(Registry.ITEM_KEY).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<Item> itemTag = tagManager.getOrCreateTagGroup(Registry.ITEM_KEY).getTag(new Identifier(tag));
if (itemTag == null) return Value.NULL;
return BooleanValue.of(itemTag.contains(item));
});
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));
@@ -124,7 +108,7 @@ public class Inventories {
List<Recipe<?>> recipes;
recipes = ((RecipeManagerInterface) cc.s.getMinecraftServer().getRecipeManager()).getAllMatching(type, new Identifier(recipeName));
if (recipes.isEmpty())
return LazyValue.NULL;
return Value.NULL;
List<Value> recipesOutput = new ArrayList<>();
for (Recipe<?> recipe: recipes)
{
@@ -144,7 +128,7 @@ public class Inventories {
else
{
List<Value> 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));
}
}
@@ -183,91 +167,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(<b, e>, <n>) -> 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<Value> fullInventory = new ArrayList<>();
for (int i = 0, maxi = inventoryLocator.inventory.size(); i < maxi; i++)
{
fullInventory.add(ListValue.fromItemStack(inventoryLocator.inventory.getStack(i)));
fullInventory.add(ValueConversions.of(inventoryLocator.inventory.getStack(i)));
return ListValue.wrap(fullInventory);
}
Value res = ListValue.wrap(fullInventory);
return (_c, _t) -> res;
}
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(<b,e>, <n>, <count>, <item>, <nbt>)
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)
{
@@ -276,12 +244,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);
}
NbtCompound 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)
@@ -289,11 +257,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
{
@@ -304,62 +268,52 @@ public class Inventories {
{
throw new InternalExpressionException(e.getMessage());
}
return (_c, _t) -> ListValue.fromItemStack(previousStack);
return ValueConversions.of(previousStack);
});
//inventory_find(<b, e>, <item> or null (first empty slot), <start_from=0> ) -> <N> 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(<b, e>, <item>, <amount=1>) -> 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);
@@ -373,7 +327,7 @@ public class Inventories {
stack.setCount(left);
inventoryLocator.inventory.setStack(i, stack);
syncPlayerInventory(inventoryLocator, i);
return (_c, _t) -> Value.TRUE;
return Value.TRUE;
}
else
{
@@ -384,37 +338,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(<b, e>, <n>, <amount=1, 0-whatever's there>) -> 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)
@@ -439,8 +386,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());
});
}
@@ -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<SpawnGroup> mobcounts = info.getGroupToCount();
int chunks = ((SpawnHelperInnerInterface)info).cmGetChunkCount();
Value retVal;
if (lv.size() == 0)
{
Map<Value, Value> 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();
String catString = lv.get(0).getString();
SpawnGroup cat = SpawnGroup.byName(catString.toLowerCase(Locale.ROOT));
if (cat == null) throw new InternalExpressionException("Unreconized mob category: "+catString);
retVal = ListValue.of(
return ListValue.of(
new NumericValue(mobcounts.getInt(cat)),
new NumericValue((int)(cat.getCapacity() * chunks / SpawnReporter.currentMagicNumber()))
);
}
return (_c, _t) -> retVal;
});
}
}
+132 -224
View File
@@ -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.getOrCreateStatCriterion(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.getDefaultRenderType());
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.getOrCreateStatCriterion(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<Value> 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) {
if(lv.size() == 1)
{
if (scoreboard.getTeam(teamName) != null) return Value.NULL;
scoreboard.addTeam(teamName);
Value ret = new StringValue(teamName);
return (_c, _t) -> ret;
} else {
return LazyValue.NULL;
return new StringValue(teamName);
}
} else if(lv.size() == 2) {
Value playerVal = lv.get(1).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;
if(player == null) return Value.NULL;
Team team = scoreboard.getTeam(teamName);
if(team == null) return LazyValue.NULL;
if(team.isEqual(scoreboard.getPlayerTeam(player))) {
return LazyValue.FALSE;
} else {
if(team == null) return Value.NULL;
if(team.isEqual(scoreboard.getPlayerTeam(player))) return Value.FALSE;
scoreboard.addPlayerToTeam(player,scoreboard.getTeam(teamName));
return LazyValue.TRUE;
}
} else {
return LazyValue.NULL;
}
return Value.TRUE;
});
expression.addLazyFunction("team_remove", 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).evalValue(c);
Value teamVal = lv.get(0);
String team = teamVal.getString();
if(scoreboard.getTeam(team) != null) {
if(scoreboard.getTeam(team) == null) return Value.NULL;
scoreboard.removeTeam(scoreboard.getTeam(team));
return LazyValue.TRUE;
} else {
return LazyValue.NULL;
}
return Value.TRUE;
});
expression.addLazyFunction("team_leave", 1, (c, t, lv) ->
expression.addContextFunction("team_leave", 1, (c, t, lv) ->
{
CarpetContext cc = (CarpetContext)c;
ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard();
Value playerVal = lv.get(0).evalValue(c);
Value playerVal = lv.get(0);
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;
return new NumericValue(scoreboard.clearPlayerTeam(player));
});
expression.addLazyFunction("team_property", -1, (c, t, lv) ->
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.getStyle().getName());
}
if(propertyValue == null) return StringValue.of(bossBar.getStyle().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.setStyle(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);
}
@@ -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();
File diff suppressed because it is too large. Load diff
@@ -29,21 +29,22 @@ public class BlockArgument extends Argument
block = b;
this.replacement = replacement;
}
public static BlockArgument findIn(CarpetContext c, List<LazyValue> params, int offset)
public static BlockArgument findIn(CarpetContext c, List<Value> params, int offset)
{
return findIn(c, params,offset, false, false, false);
}
public static BlockArgument findIn(CarpetContext c, List<LazyValue> params, int offset, boolean acceptString)
public static BlockArgument findIn(CarpetContext c, List<Value> params, int offset, boolean acceptString)
{
return findIn(c, params,offset, acceptString, false, false);
}
public static BlockArgument findIn(CarpetContext c, List<LazyValue> params, int offset, boolean acceptString, boolean optional, boolean anyString)
public static BlockArgument findIn(CarpetContext c, List<Value> 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,
@@ -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<LazyValue> lv, Context c, boolean isFolder, Reason reason)
public static FileArgument from(List<Value> lv, boolean isFolder, Reason reason)
{
if (lv.size() < 2) throw new InternalExpressionException("File functions require path and type as first two arguments");
Pair<String, String> resource = recognizeResource(lv.get(0).evalValue(c), isFolder);
String origtype = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT);
Pair<String, String> 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);
@@ -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;
@@ -15,12 +16,12 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class FunctionArgument<T> extends Argument
public class FunctionArgument extends Argument
{
public FunctionValue function;
public List<T> args;
public List<Value> args;
private FunctionArgument(FunctionValue function, int offset, List<T> args)
private FunctionArgument(FunctionValue function, int offset, List<Value> args)
{
super(offset);
this.function = function;
@@ -38,18 +39,18 @@ public class FunctionArgument<T> extends Argument
* if the number of supplied arguments is right
* @return argument data
*/
public static FunctionArgument<LazyValue> findIn(
public static FunctionArgument findIn(
Context c,
Module module,
List<LazyValue> params,
List<Value> 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))
@@ -67,12 +68,12 @@ public class FunctionArgument<T> extends Argument
if (extraargs > 0 && fun.getVarArgs() == null)
throw new InternalExpressionException("Function " + fun.getPrettyString() + " requires " + fun.getArguments().size() + " arguments");
}
List<LazyValue> lvargs = new ArrayList<>();
List<Value> 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<Value> fromCommandSpec(ScriptHost host, Value funSpec) throws CommandSyntaxException {
public static FunctionArgument fromCommandSpec(ScriptHost host, Value funSpec) throws CommandSyntaxException {
FunctionValue function;
List<Value> args = Collections.emptyList();
if (!(funSpec instanceof ListValue))
@@ -92,6 +93,11 @@ public class FunctionArgument<T> 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 List<Value> checkedArgs() {
function.checkArgs(args.size());
return args;
}
}
@@ -47,66 +47,12 @@ public class Vector3Argument extends Argument
return this;
}
public static Vector3Argument findIn(CarpetContext c, List<LazyValue> params, int offset)
public static Vector3Argument findIn(List<Value> params, int offset)
{
return findIn(c,params, offset, false, false);
return findIn(params, offset, false, false);
}
public static Vector3Argument findIn(CarpetContext c, List<LazyValue> 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<Value> 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<Value> params, int offset, boolean optionalDirection)
public static Vector3Argument findIn(List<Value> 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<Value> args = ((ListValue) v1).getItems();
@@ -291,7 +291,7 @@ public abstract class CommandArgument
protected boolean needsMatching;
protected boolean caseSensitive = true;
protected SuggestionProvider<ServerCommandSource> suggestionProvider;
protected FunctionArgument<Value> customSuggester;
protected FunctionArgument customSuggester;
protected CommandArgument(
@@ -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) ->
@@ -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)
@@ -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<Value> 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;
});
@@ -2,16 +2,19 @@ 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;
import carpet.script.value.StringValue;
import carpet.script.value.Value;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
@@ -22,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)
@@ -43,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<LazyValue> functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, false, true);
List<Value> 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);
}
@@ -61,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);
}
@@ -81,22 +85,38 @@ 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);
});
expression.addLazyUnaryOperator("...", Operators.precedence.get("def->..."), false, (c, t, lv) ->
// lazy because of typed evaluation of the argument
expression.addLazyUnaryOperator("...", Operators.precedence.get("unary+-!..."), 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), 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
expression.addLazyBinaryOperatorWithDelegation("->", Operators.precedence.get("def->..."), false, (c, type, e, t, lv1, lv2) ->
// 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)
{
@@ -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();
@@ -20,7 +20,7 @@ import java.util.Map;
public class Operators {
public static final Map<String, Integer> precedence = new HashMap<String,Integer>() {{
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);
}};
@@ -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<Value> 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,14 +208,17 @@ 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);
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
// 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
}
}
+55 -79
View File
@@ -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<Value> 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<Value> 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;
});
}
}
@@ -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<LazyValue> 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));
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<LazyValue> 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));
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();
@@ -1,5 +1,6 @@
package carpet.script.value;
import carpet.CarpetServer;
import carpet.fakes.BrainInterface;
import carpet.fakes.EntityInterface;
import carpet.fakes.ItemEntityInterface;
@@ -13,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;
@@ -933,9 +935,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)
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));
}
@@ -1067,30 +1071,32 @@ public class EntityValue extends Value
throw new InternalExpressionException("Expected a list of 3 parameters as a second argument");
}
List<Value> 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) ->
@@ -1105,7 +1111,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) -> {
@@ -1224,7 +1230,7 @@ public class EntityValue extends Value
else if (v instanceof ListValue)
{
List<Value> 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)
{
@@ -1253,7 +1259,7 @@ public class EntityValue extends Value
else if (a instanceof ListValue)
{
List<Value> 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> world = spe.getEntityWorld().getRegistryKey();
float angle = spe.getHeadYaw();
@@ -5,10 +5,12 @@ import net.minecraft.nbt.NbtElement;
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");
@@ -0,0 +1,23 @@
package carpet.script.value;
import java.util.List;
public class FunctionUnpackedArgumentsValue extends ListValue
{
public FunctionUnpackedArgumentsValue(List<Value> 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);
}
}
@@ -1,5 +1,6 @@
package carpet.script.value;
import carpet.CarpetSettings;
import carpet.script.Context;
import carpet.script.Expression;
import carpet.script.Fluff;
@@ -11,7 +12,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.NbtString;
import net.minecraft.nbt.NbtElement;
@@ -150,11 +150,11 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
return varArgs != null;
}
public LazyValue callInContext(Context c, Integer type, List<LazyValue> lazyParams)
public LazyValue callInContext(Context c, Integer type, List<Value> params)
{
try
{
return lazyEval(c, type, expression, token, lazyParams);
return execute(c, type, expression, token, params);
}
catch (ExpressionException exc)
{
@@ -173,15 +173,50 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
}
}
@Override
public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List<LazyValue> 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");
}
public static List<Value> unpackArgs(List<LazyValue> lazyParams, Context c)
{
// TODO we shoudn't need that if all fuctions are not lazy really
List<Value> params = new ArrayList<>();
for (LazyValue lv : lazyParams)
{
Value param = lv.evalValue(c, Context.NONE);
if (param instanceof FunctionUnpackedArgumentsValue)
{
CarpetSettings.LOG.error("How did we get here?");
params.addAll(((ListValue) param).getItems());
}
else
{
params.add(param);
}
}
return params;
}
@Override
public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List<LazyValue> lazyParams) {
List<Value> resolvedParams = unpackArgs(lazyParams, c);
return execute(c, type, e, t, resolvedParams);
}
public LazyValue execute(Context c, Integer type, Expression e, Tokenizer.Token t, List<Value> params)
{
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 "+lazyParams.size()+" like "+args
". Should be "+args.size()+", not "+params.size()+" like "+args
);
}
else // too few args for varargs
@@ -190,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 "+lazyParams.size()+" like "+argList
". Should be at least "+args.size()+", not "+params.size()+" like "+argList
);
}
});
@@ -200,15 +235,15 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
for (int i=0; i<args.size(); i++)
{
String arg = args.get(i);
Value val = lazyParams.get(i).evalValue(c).reboundedTo(arg); // todo check if we need to copy that
Value val = params.get(i).reboundedTo(arg); // todo check if we need to copy that
newFrame.setVariable(arg, (cc, tt) -> val);
}
if (varArgs != null)
{
List<Value> extraParams = new ArrayList<>();
for (int i = args.size(), mx = lazyParams.size(); i < mx; i++)
for (int i = args.size(), mx = params.size(); i < mx; i++)
{
extraParams.add(lazyParams.get(i).evalValue(c).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);
@@ -265,12 +300,6 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
feedback.accept(false);
}
}
public static List<Value> resolveArgs(List<LazyValue> lzargs, Context c, Integer t)
{
List<Value> args = new ArrayList<>(lzargs.size());
lzargs.forEach( v -> args.add( v.evalValue(c, t)));
return args;
}
public static List<LazyValue> lazify(List<Value> args)
{
@@ -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)
{
@@ -70,7 +70,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
items.addAll(list);
}
private ListValue(List<Value> list)
protected ListValue(List<Value> list)
{
items = list;
}
@@ -83,6 +83,12 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
owned = true;
}
public static Value of(NbtElement tag)
{
if (tag == null) return Value.NULL;
return new NBTSerializableValue(tag);
}
public NBTSerializableValue(Supplier<NbtElement> tagSupplier)
{
nbtSupplier = tagSupplier;
@@ -180,29 +186,29 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
return inventory;
}
public static InventoryLocator locateInventory(CarpetContext c, List<LazyValue> params, int offset)
public static InventoryLocator locateInventory(CarpetContext c, List<Value> 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");
@@ -258,8 +264,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;
@@ -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)
{