diff --git a/src/main/java/carpet/commands/ScriptCommand.java b/src/main/java/carpet/commands/ScriptCommand.java index dd9034bf..b38efe75 100644 --- a/src/main/java/carpet/commands/ScriptCommand.java +++ b/src/main/java/carpet/commands/ScriptCommand.java @@ -14,6 +14,7 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.minecraft.block.Block; @@ -24,6 +25,7 @@ import net.minecraft.command.arguments.BlockStateArgument; import net.minecraft.command.arguments.BlockStateArgumentType; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.block.entity.BlockEntity; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Clearable; import net.minecraft.util.math.BlockPos; import net.minecraft.server.world.ServerWorld; @@ -206,9 +208,17 @@ public class ScriptCommand suggests( (cc, bb) -> suggestMatching(CarpetServer.scriptServer.listAvailableModules(),bb)). executes((cc) -> { - boolean success = CarpetServer.scriptServer.addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "package"), false); + boolean success = CarpetServer.scriptServer.addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "package"), true); return success?1:0; - }) + }). + then(literal("global"). + executes((cc) -> + { + boolean success = CarpetServer.scriptServer.addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "package"), false); + return success?1:0; + } + ) + ) ); LiteralArgumentBuilder f = literal("unload").requires( (player) -> player.hasPermissionLevel(2) ). then(argument("package", StringArgumentType.word()). @@ -267,8 +277,8 @@ public class ScriptCommand try { String name = StringArgumentType.getString(context, "package").toLowerCase(Locale.ROOT); - return CarpetServer.scriptServer.modules.getOrDefault(name, CarpetServer.scriptServer.globalHost); - + ScriptHost parentHost = CarpetServer.scriptServer.modules.getOrDefault(name, CarpetServer.scriptServer.globalHost); + return parentHost.retrieveForExecution(context.getSource()); } catch (IllegalArgumentException ignored) { @@ -277,7 +287,6 @@ public class ScriptCommand } private static Collection suggestFunctionCalls(CommandContext c) { - ServerCommandSource s = c.getSource(); ScriptHost host = getHost(c); return host.getPublicFunctions(); } diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java index 52145df9..4fcf43d4 100644 --- a/src/main/java/carpet/script/CarpetEventServer.java +++ b/src/main/java/carpet/script/CarpetEventServer.java @@ -122,6 +122,11 @@ public class CarpetEventServer { callList.removeIf((c)-> c.udf.equalsIgnoreCase(callName) && ( hostName == null || c.host.equalsIgnoreCase(hostName) ) ); } + + public void removeAllCalls(String hostName) + { + callList.removeIf((c)-> c.host.equals(hostName)); + } } public Map eventHandlers = new HashMap<>(); @@ -194,6 +199,11 @@ public class CarpetEventServer return true; } + public void removeAllHostEvents(String hostName) + { + eventHandlers.forEach((e, a) -> a.removeAllCalls(hostName)); + } + private Callback decodeCallback(String funName) { Pattern find = Pattern.compile("(\\w+)\\(from (\\w+)\\)"); diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 71f6aa01..3fc0300c 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -45,6 +45,7 @@ import net.minecraft.item.BlockItem; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; import net.minecraft.particle.ParticleEffect; import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.server.MinecraftServer; diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index b736b15a..716870a2 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -44,7 +44,7 @@ public class CarpetScriptServer public CarpetScriptServer() { - globalHost = createMinecraftScriptHost(null, null); + globalHost = createMinecraftScriptHost(null, null, false, null); events = new CarpetEventServer(); modules = new HashMap<>(); tickStart = 0L; @@ -112,12 +112,35 @@ public class CarpetScriptServer } - private static ScriptHost createMinecraftScriptHost(String name, ModuleInterface code) + private ScriptHost createMinecraftScriptHost(String name, ModuleInterface module, boolean perPlayer, ServerCommandSource source) { - ScriptHost host = new ScriptHost(name); + ScriptHost host = new ScriptHost(name, module, perPlayer ); host.globalVariables.put("_x", (c, t) -> Value.ZERO); host.globalVariables.put("_y", (c, t) -> Value.ZERO); host.globalVariables.put("_z", (c, t) -> Value.ZERO); + // parse code and convert to expression + if (module != null) + { + try + { + String code = module.getCode(); + if (code == null) + { + Messenger.m(source, "r Unable to load the package - not found"); + return null; + } + setChatErrorSnooper(source); + CarpetExpression ex = new CarpetExpression(code, source, new BlockPos(0, 0, 0)); + ex.getExpr().asAModule(); + ex.scriptRunCommand(host, new BlockPos(source.getPosition())); + } + catch (CarpetExpressionException e) + { + Messenger.m(source, "r Exception white evaluating expression at " + new BlockPos(source.getPosition()) + ": " + e.getMessage()); + resetErrorSnooper(); + return null; + } + } return host; } @@ -126,7 +149,12 @@ public class CarpetScriptServer //TODO add per player modules to support player actions better on a server name = name.toLowerCase(Locale.ROOT); ModuleInterface module = getModule(name); - ScriptHost newHost = createMinecraftScriptHost(name, module); + ScriptHost newHost = createMinecraftScriptHost(name, module, perPlayer, source); + if (newHost == null) + { + Messenger.m(source, "r Failed to add a module"); + return false; + } if (module == null) { Messenger.m(source, "r Unable to locate the package, but created empty host "+name+" instead"); @@ -134,27 +162,12 @@ public class CarpetScriptServer return true; } String code = module.getCode(); - if (code == null) + if (module.getCode() == null) { Messenger.m(source, "r Unable to load the package - not found"); return false; } - // parse code and convert to expression - // fill functions etc. - // possibly add a command - try - { - setChatErrorSnooper(source); - CarpetExpression ex = new CarpetExpression(module.getCode(), source, new BlockPos(0, 0, 0)); - ex.getExpr().asAModule(); - ex.scriptRunCommand(newHost, new BlockPos(source.getPosition())); - } - catch (CarpetExpressionException e) - { - Messenger.m(source, "r Exception white evaluating expression at "+new BlockPos(source.getPosition())+": "+e.getMessage()); - resetErrorSnooper(); - return false; - } + modules.put(name, newHost); addEvents(source, name); @@ -206,7 +219,7 @@ public class CarpetScriptServer requires((player) -> modules.containsKey(hostName)). executes( (c) -> { - Messenger.m(c.getSource(), "gi "+modules.get(hostName).call(c.getSource(),"__command", null, "")); + Messenger.m(c.getSource(), "gi "+modules.get(hostName).retrieveForExecution(c.getSource()).call(c.getSource(),"__command", null, "")); return 1; }); @@ -218,7 +231,7 @@ public class CarpetScriptServer executes( (c) -> { Messenger.m( c.getSource(), - "gi "+modules.get(hostName).call( + "gi "+modules.get(hostName).retrieveForExecution(c.getSource()).call( c.getSource(), function, null, @@ -231,7 +244,7 @@ public class CarpetScriptServer executes( (c) -> { Messenger.m( c.getSource(), - "gi "+modules.get(hostName).call( + "gi "+modules.get(hostName).retrieveForExecution(c.getSource()).call( c.getSource(), function, null, @@ -304,6 +317,7 @@ public class CarpetScriptServer return false; } // stop all events associated with name + events.removeAllHostEvents(name); modules.remove(name); CarpetServer.settingsManager.notifyPlayersCommandsChanged(); Messenger.m(source, "w Removed host "+name); @@ -319,7 +333,7 @@ public class CarpetScriptServer { ScriptHost host = globalHost; if (hostname != null) - host = modules.get(hostname); + host = modules.get(hostname).retrieveForExecution(source); try { host.callUDF(origin, source, host.globalFunctions.get(udf_name), argv); diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 2d2f01fb..a6f24aee 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -1894,15 +1894,7 @@ public class Expression implements Cloneable addBinaryFunction("get", (v1, v2) -> { - if (v1 instanceof LazyListValue || !(v1 instanceof ListValue)) - throw new InternalExpressionException("First argument of get should be a list"); - List items = ((ListValue)v1).getItems(); - long index = NumericValue.asNumber(v2).getLong(); - int numitems = items.size(); - long range = abs(index)/numitems; - index += (range+2)*numitems; - index = index % numitems; - return items.get((int)index); + return v1.getElementAt(v2); }); //Deprecated, use "get" instead diff --git a/src/main/java/carpet/script/ScriptHost.java b/src/main/java/carpet/script/ScriptHost.java index 58651f55..b032bae4 100644 --- a/src/main/java/carpet/script/ScriptHost.java +++ b/src/main/java/carpet/script/ScriptHost.java @@ -8,7 +8,9 @@ import carpet.script.exception.InvalidCallbackException; import carpet.script.value.NumericValue; import carpet.script.value.StringValue; import carpet.script.value.Value; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.math.BlockPos; import java.math.BigInteger; @@ -23,22 +25,21 @@ import static java.lang.Math.max; public class ScriptHost { - - public final Map globalFunctions = new HashMap<>(); - - public final Map globalVariables = new HashMap<>(); + public final Map userHosts = new HashMap<>(); + public Map globalFunctions = new HashMap<>(); + public Map globalVariables = new HashMap<>(); private String name; public String getName() {return name;} - private ModuleInterface myCode; + private final ModuleInterface myCode; + public final boolean perUser; - ScriptHost(String name) { this(name, null);} - - ScriptHost(String name, ModuleInterface code) + ScriptHost(String name, ModuleInterface code, boolean perUser) { this.name = name; this.myCode = code; + this.perUser = perUser; globalVariables.put("euler", (c, t) -> Expression.euler); globalVariables.put("pi", (c, t) -> Expression.PI); globalVariables.put("null", (c, t) -> Value.NULL); @@ -51,6 +52,37 @@ public class ScriptHost globalVariables.put("_a", (c, t) -> Value.ZERO); } + public ScriptHost retrieveForExecution(String /*Nullable*/ user) + { + if (!perUser) + return this; + ScriptHost userHost = userHosts.get(user); + if (userHost != null) + return userHost; + userHost = new ScriptHost(this.name, myCode, false); + userHost.globalVariables.putAll(this.globalVariables); + userHost.globalFunctions.putAll(this.globalFunctions); + userHosts.put(user, userHost); + return userHost; + } + + public ScriptHost retrieveForExecution(ServerCommandSource source) + { + if (!perUser) + return this; + try + { + ServerPlayerEntity player = source.getPlayer(); + CarpetSettings.LOG.error("Retrieving "+player.getName().getString()+" host for "+getName()); + return retrieveForExecution(player.getName().getString()); + } + catch (CommandSyntaxException e) + { + CarpetSettings.LOG.error("Retrieving global host for "+getName()); + return retrieveForExecution((String)null); + } + } + public Expression getExpressionForFunction(String name) { return globalFunctions.get(name).getExpression(); @@ -190,4 +222,6 @@ public class ScriptHost CarpetSettings.LOG.error("Callback failed: "+e.getMessage()); } } + + } diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index a0ea7f9e..235203fe 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -313,7 +313,7 @@ public class EntityValue extends Value put("nbt",(e, a) -> { CompoundTag nbttagcompound = e.toTag((new CompoundTag())); if (a==null) - return new StringValue(nbttagcompound.toString()); + return new NBTSerializableValue(nbttagcompound);//StringValue(nbttagcompound.toString()); NbtPathArgumentType.NbtPath path; try { @@ -330,11 +330,11 @@ public class EntityValue extends Value if (tags.size()==0) return Value.NULL; if (tags.size()==1) - return new StringValue(tags.get(0).toText().getString()); - return ListValue.wrap(tags.stream().map((t) -> new StringValue(t.toText().getString())).collect(Collectors.toList())); + return new NBTSerializableValue((CompoundTag) tags.get(0)); + return ListValue.wrap(tags.stream().map(t -> new NBTSerializableValue((CompoundTag) t)).collect(Collectors.toList())); } catch (CommandSyntaxException ignored) { } - return new StringValue(res); + return Value.NULL; }); }}; private static Req assertEntityArgType(Class klass, Value arg) diff --git a/src/main/java/carpet/script/value/LazyListValue.java b/src/main/java/carpet/script/value/LazyListValue.java index be416f18..8bf16cc2 100644 --- a/src/main/java/carpet/script/value/LazyListValue.java +++ b/src/main/java/carpet/script/value/LazyListValue.java @@ -106,4 +106,10 @@ public abstract class LazyListValue extends ListValue implements Iterator return false; } + @Override + public Value getElementAt(Value v2) + { + throw new InternalExpressionException("get element can only be obtained for regular lists"); + } + } diff --git a/src/main/java/carpet/script/value/ListValue.java b/src/main/java/carpet/script/value/ListValue.java index fefb8a7f..ab7a47f6 100644 --- a/src/main/java/carpet/script/value/ListValue.java +++ b/src/main/java/carpet/script/value/ListValue.java @@ -316,6 +316,17 @@ public class ListValue extends Value return (double)items.size(); } + @Override + public Value getElementAt(Value value) + { + long index = NumericValue.asNumber(value).getLong(); + int numitems = items.size(); + long range = abs(index)/numitems; + index += (range+2)*numitems; + index = index % numitems; + return items.get((int)index); + } + } diff --git a/src/main/java/carpet/script/value/NBTSerializableValue.java b/src/main/java/carpet/script/value/NBTSerializableValue.java index 14d72f80..2abf9e45 100644 --- a/src/main/java/carpet/script/value/NBTSerializableValue.java +++ b/src/main/java/carpet/script/value/NBTSerializableValue.java @@ -15,6 +15,7 @@ import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.StringNbtReader; +import net.minecraft.nbt.Tag; import net.minecraft.util.math.BlockPos; import java.util.HashMap; @@ -22,6 +23,8 @@ import java.util.List; import java.util.Map; import java.util.function.Supplier; +import static java.lang.Math.abs; + public class NBTSerializableValue extends Value { private String nbtString = null; @@ -195,4 +198,43 @@ public class NBTSerializableValue extends Value offset = o; } } + + @Override + public Value getElementAt(Value value) + { + String path = value.getString(); + + return Value.NULL; + /* + CompoundTag nbttagcompound = e.toTag((new CompoundTag())); + if (a==null) + return new NBTSerializableValue(nbttagcompound);//StringValue(nbttagcompound.toString()); + NbtPathArgumentType.NbtPath path; + try + { + path = NbtPathArgumentType.nbtPath().method_9362(new StringReader(a.getString())); + } + catch (CommandSyntaxException exc) + { + throw new InternalExpressionException("Incorrect path: "+a.getString()); + } + String res = null; + try + { + List tags = path.get(nbttagcompound); + if (tags.size()==0) + return Value.NULL; + if (tags.size()==1) + return new NBTSerializableValue(tags.get(0)); + return ListValue.wrap(tags.stream().map(NBTSerializableValue::new).collect(Collectors.toList())); + } + catch (CommandSyntaxException ignored) { } + return Value.NULL; + */ + /*int numitems = items.size(); + long range = abs(index)/numitems; + index += (range+2)*numitems; + index = index % numitems; + return items.get((int)index); */ + } } diff --git a/src/main/java/carpet/script/value/Value.java b/src/main/java/carpet/script/value/Value.java index 24a3d26c..454b5871 100644 --- a/src/main/java/carpet/script/value/Value.java +++ b/src/main/java/carpet/script/value/Value.java @@ -172,4 +172,9 @@ public abstract class Value implements Comparable, Cloneable { return (long)readNumber(); } + + public Value getElementAt(Value v2) + { + throw new InternalExpressionException("get element can only be obtained for lists and nbt values"); + } }