reworked container access (never throw, multi-field access, return values, operator), added package storage
This commit is contained in:
1 parent
8b531834d0
commit
701a717135
12 files changed
+369
-114
No files matched your search
@@ -111,6 +111,7 @@ public class CarpetServer // static for now - easier to handle all around the co
|
|||||||
|
|
||||||
public static void onServerClosed(MinecraftServer server)
|
public static void onServerClosed(MinecraftServer server)
|
||||||
{
|
{
|
||||||
|
scriptServer.onClose();
|
||||||
LoggerRegistry.stopLoggers();
|
LoggerRegistry.stopLoggers();
|
||||||
extensions.forEach(e -> e.onServerClosed(server));
|
extensions.forEach(e -> e.onServerClosed(server));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import net.minecraft.item.BlockItem;
|
|||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.particle.ParticleEffect;
|
import net.minecraft.particle.ParticleEffect;
|
||||||
import net.minecraft.predicate.entity.EntityPredicates;
|
import net.minecraft.predicate.entity.EntityPredicates;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
@@ -2873,6 +2874,34 @@ public class CarpetExpression
|
|||||||
CarpetServer.scriptServer.events.scheduleCall(cc, funname, args, delay);
|
CarpetServer.scriptServer.events.scheduleCall(cc, funname, args, delay);
|
||||||
return (c_, t_) -> Value.TRUE;
|
return (c_, t_) -> Value.TRUE;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.expr.addLazyFunction("get_global_state", -1, (c, t, lv) ->
|
||||||
|
{
|
||||||
|
String file = null;
|
||||||
|
if (lv.size()>0)
|
||||||
|
file = lv.get(0).evalValue(c).getString();
|
||||||
|
Tag state = ((CarpetContext)c).host.getGlobalState(file);
|
||||||
|
if (state == null)
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value retVal = new NBTSerializableValue(state);
|
||||||
|
return (cc, tt) -> retVal;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.expr.addLazyFunction("set_global_state", -1, (c, t, lv) ->
|
||||||
|
{
|
||||||
|
if (lv.size() == 0)
|
||||||
|
throw new InternalExpressionException("save_state needs nbt tag and optional file");
|
||||||
|
Value val = lv.get(0).evalValue(c);
|
||||||
|
String file = null;
|
||||||
|
if (lv.size()>1)
|
||||||
|
file = lv.get(1).evalValue(c).getString();
|
||||||
|
NBTSerializableValue tagValue = (val instanceof NBTSerializableValue)
|
||||||
|
? (NBTSerializableValue) val
|
||||||
|
: new NBTSerializableValue(val.getString());
|
||||||
|
Tag tag = tagValue.getTag();
|
||||||
|
((CarpetContext)c).host.setGlobalState(tag, file);
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ public class CarpetScriptServer
|
|||||||
|
|
||||||
private ScriptHost createMinecraftScriptHost(String name, ModuleInterface module, boolean perPlayer, ServerCommandSource source)
|
private ScriptHost createMinecraftScriptHost(String name, ModuleInterface module, boolean perPlayer, ServerCommandSource source)
|
||||||
{
|
{
|
||||||
ScriptHost host = new ScriptHost(name, module, perPlayer );
|
ScriptHost host = new ScriptHost(name, module, perPlayer, null );
|
||||||
host.globalVariables.put("_x", (c, t) -> Value.ZERO);
|
host.globalVariables.put("_x", (c, t) -> Value.ZERO);
|
||||||
host.globalVariables.put("_y", (c, t) -> Value.ZERO);
|
host.globalVariables.put("_y", (c, t) -> Value.ZERO);
|
||||||
host.globalVariables.put("_z", (c, t) -> Value.ZERO);
|
host.globalVariables.put("_z", (c, t) -> Value.ZERO);
|
||||||
@@ -360,5 +360,17 @@ public class CarpetScriptServer
|
|||||||
public void tick()
|
public void tick()
|
||||||
{
|
{
|
||||||
events.tick();
|
events.tick();
|
||||||
|
for (ScriptHost host : modules.values())
|
||||||
|
{
|
||||||
|
host.tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClose()
|
||||||
|
{
|
||||||
|
for (ScriptHost host : modules.values())
|
||||||
|
{
|
||||||
|
host.onClose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1243,29 +1243,6 @@ public class Expression implements Cloneable
|
|||||||
*/
|
*/
|
||||||
public void Operators()
|
public void Operators()
|
||||||
{
|
{
|
||||||
addLazyBinaryOperator(":", precedence.get("attribute~:"),true, (c, t, container_lv, key_lv) ->
|
|
||||||
{
|
|
||||||
Value container = container_lv.evalValue(c);
|
|
||||||
if (container instanceof LContainerValue)
|
|
||||||
{
|
|
||||||
ContainerValueInterface outerContainer = ((LContainerValue) container).getContainer();
|
|
||||||
Value outerAddress = ((LContainerValue) container).getAddress();
|
|
||||||
Value innerContainer = outerContainer.get(outerAddress);
|
|
||||||
if (!(innerContainer instanceof ContainerValueInterface))
|
|
||||||
throw new InternalExpressionException("Cannot access elements of a non-container");
|
|
||||||
Value innerLValue = new LContainerValue((ContainerValueInterface) innerContainer, key_lv.evalValue(c));
|
|
||||||
return (cc, tt) -> innerLValue;
|
|
||||||
}
|
|
||||||
if (!(container instanceof ContainerValueInterface))
|
|
||||||
throw new InternalExpressionException("Cannot access elements of a non-container");
|
|
||||||
Value address = key_lv.evalValue(c);
|
|
||||||
if (t != Context.LVALUE)
|
|
||||||
{
|
|
||||||
Value retVal = ((ContainerValueInterface) container).get(address);
|
|
||||||
return (cc, ct) -> retVal;
|
|
||||||
}
|
|
||||||
return (cc, ct) -> new LContainerValue((ContainerValueInterface) container, address);
|
|
||||||
});
|
|
||||||
addBinaryOperator("+", precedence.get("addition+-"), true, Value::add);
|
addBinaryOperator("+", precedence.get("addition+-"), true, Value::add);
|
||||||
addBinaryOperator("-", precedence.get("addition+-"), true, Value::subtract);
|
addBinaryOperator("-", precedence.get("addition+-"), true, Value::subtract);
|
||||||
addBinaryOperator("*", precedence.get("multiplication*/%"), true, Value::multiply);
|
addBinaryOperator("*", precedence.get("multiplication*/%"), true, Value::multiply);
|
||||||
@@ -1329,8 +1306,12 @@ public class Expression implements Cloneable
|
|||||||
}
|
}
|
||||||
if (v1 instanceof LContainerValue)
|
if (v1 instanceof LContainerValue)
|
||||||
{
|
{
|
||||||
Value ret = ((LContainerValue) v1).getContainer().put(((LContainerValue) v1).getAddress(), v2);
|
ContainerValueInterface container = ((LContainerValue) v1).getContainer();
|
||||||
return (cc, tt) -> ret;
|
if (container == null)
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value address = ((LContainerValue) v1).getAddress();
|
||||||
|
if (!(container.put(address, v2))) return (cc, tt) -> Value.NULL;
|
||||||
|
return (cc, tt) -> v2;
|
||||||
}
|
}
|
||||||
v1.assertAssignable();
|
v1.assertAssignable();
|
||||||
String varname = v1.getVariable();
|
String varname = v1.getVariable();
|
||||||
@@ -2341,13 +2322,13 @@ public class Expression implements Cloneable
|
|||||||
addUnaryFunction("keys", v -> {
|
addUnaryFunction("keys", v -> {
|
||||||
if (v instanceof MapValue)
|
if (v instanceof MapValue)
|
||||||
return new ListValue(((MapValue) v).getMap().keySet());
|
return new ListValue(((MapValue) v).getMap().keySet());
|
||||||
throw new InternalExpressionException("keys applies only to maps");
|
return Value.NULL;
|
||||||
});
|
});
|
||||||
|
|
||||||
addUnaryFunction("values", v -> {
|
addUnaryFunction("values", v -> {
|
||||||
if (v instanceof MapValue)
|
if (v instanceof MapValue)
|
||||||
return new ListValue(((MapValue) v).getMap().values());
|
return new ListValue(((MapValue) v).getMap().values());
|
||||||
throw new InternalExpressionException("keys applies only to maps");
|
return Value.NULL;
|
||||||
});
|
});
|
||||||
|
|
||||||
addUnaryFunction("pairs", v -> {
|
addUnaryFunction("pairs", v -> {
|
||||||
@@ -2355,21 +2336,93 @@ public class Expression implements Cloneable
|
|||||||
return ListValue.wrap(((MapValue) v).getMap().entrySet().stream().map(
|
return ListValue.wrap(((MapValue) v).getMap().entrySet().stream().map(
|
||||||
(p) -> ListValue.of(p.getKey(), p.getValue())
|
(p) -> ListValue.of(p.getKey(), p.getValue())
|
||||||
).collect(Collectors.toList()));
|
).collect(Collectors.toList()));
|
||||||
throw new InternalExpressionException("pairs applies only to maps");
|
return Value.NULL;
|
||||||
});
|
});
|
||||||
|
|
||||||
addBinaryFunction("get", (container, key) ->
|
addLazyBinaryOperator(":", precedence.get("attribute~:"),true, (c, t, container_lv, key_lv) ->
|
||||||
{
|
{
|
||||||
if (container instanceof ContainerValueInterface)
|
Value container = container_lv.evalValue(c);
|
||||||
return ((ContainerValueInterface) container).get(key);
|
if (container instanceof LContainerValue)
|
||||||
throw new InternalExpressionException("Cannot access elements of a non-container");
|
{
|
||||||
|
ContainerValueInterface outerContainer = ((LContainerValue) container).getContainer();
|
||||||
|
if (outerContainer == null)
|
||||||
|
{
|
||||||
|
Value innerLValue = new LContainerValue(null, null);
|
||||||
|
return (cc, tt) -> innerLValue;
|
||||||
|
}
|
||||||
|
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 (!(container instanceof ContainerValueInterface))
|
||||||
|
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;
|
||||||
});
|
});
|
||||||
|
|
||||||
addBinaryFunction("has", (container, key) ->
|
addLazyFunction("get", -1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
if (container instanceof ContainerValueInterface)
|
if (lv.size() == 0)
|
||||||
return new NumericValue(((ContainerValueInterface) container).has(key));
|
throw new InternalExpressionException("get requires parameters");
|
||||||
throw new InternalExpressionException("Cannot access elements of a non-container");
|
if (lv.size() == 1)
|
||||||
|
{
|
||||||
|
Value v = lv.get(0).evalValue(c, Context.LVALUE);
|
||||||
|
if (!(v instanceof LContainerValue))
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
ContainerValueInterface container = ((LContainerValue) v).getContainer();
|
||||||
|
if (container == null)
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value ret = container.get(((LContainerValue) v).getAddress());
|
||||||
|
return (cc, tt) -> ret;
|
||||||
|
}
|
||||||
|
Value container = lv.get(0).evalValue(c);
|
||||||
|
for (int i = 1; i < lv.size(); i++)
|
||||||
|
{
|
||||||
|
if (!(container instanceof ContainerValueInterface)) return (cc, tt) -> Value.NULL;
|
||||||
|
container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c));
|
||||||
|
}
|
||||||
|
if (container == null)
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value finalContainer = container;
|
||||||
|
return (cc, tt) -> finalContainer;
|
||||||
|
});
|
||||||
|
|
||||||
|
addLazyFunction("has", -1, (c, t, lv) ->
|
||||||
|
{
|
||||||
|
if (lv.size() == 0)
|
||||||
|
throw new InternalExpressionException("get requires parameters");
|
||||||
|
if (lv.size() == 1)
|
||||||
|
{
|
||||||
|
Value v = lv.get(0).evalValue(c, Context.LVALUE);
|
||||||
|
if (!(v instanceof LContainerValue))
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
ContainerValueInterface container = ((LContainerValue) v).getContainer();
|
||||||
|
if (container == null)
|
||||||
|
return (cc, tt) -> Value.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;
|
||||||
|
container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c));
|
||||||
|
}
|
||||||
|
if (!(container instanceof ContainerValueInterface))
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value ret = new NumericValue(((ContainerValueInterface) container).has(lv.get(lv.size()-1).evalValue(c)));
|
||||||
|
return (cc, tt) -> ret;
|
||||||
});
|
});
|
||||||
|
|
||||||
//Deprecated, use "get" instead, or . operator
|
//Deprecated, use "get" instead, or . operator
|
||||||
@@ -2386,53 +2439,68 @@ public class Expression implements Cloneable
|
|||||||
return items.get((int)index);
|
return items.get((int)index);
|
||||||
});
|
});
|
||||||
|
|
||||||
addFunction("put", (lv) ->
|
addLazyFunction("put", -1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
|
if(lv.size()<2)
|
||||||
|
{
|
||||||
|
throw new InternalExpressionException("put takes at least three arguments, a container, address, and values to insert at that index");
|
||||||
|
}
|
||||||
|
Value container = lv.get(0).evalValue(c, Context.LVALUE);
|
||||||
|
if (container instanceof LContainerValue)
|
||||||
|
{
|
||||||
|
ContainerValueInterface internalContainer = ((LContainerValue) container).getContainer();
|
||||||
|
if (internalContainer == null)
|
||||||
|
{
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
}
|
||||||
|
Value address = ((LContainerValue) container).getAddress();
|
||||||
|
Value what = lv.get(1).evalValue(c);
|
||||||
|
Value retVal = new NumericValue( (lv.size() > 2)
|
||||||
|
? internalContainer.put(address, what, lv.get(3).evalValue(c))
|
||||||
|
: internalContainer.put(address, what));
|
||||||
|
return (cc, tt) -> retVal;
|
||||||
|
|
||||||
|
}
|
||||||
if(lv.size()<3)
|
if(lv.size()<3)
|
||||||
{
|
{
|
||||||
throw new InternalExpressionException("put takes at least three arguments, a container, address, and values to insert at that index");
|
throw new InternalExpressionException("put takes at least three arguments, a container, address, and values to insert at that index");
|
||||||
}
|
}
|
||||||
Value container = lv.get(0);
|
|
||||||
if (!(container instanceof ContainerValueInterface))
|
if (!(container instanceof ContainerValueInterface))
|
||||||
{
|
{
|
||||||
throw new InternalExpressionException("First argument of put should be a container: list, map or nbt");
|
return (cc, tt) -> Value.NULL;
|
||||||
}
|
|
||||||
Value where = lv.get(1);
|
|
||||||
Value what = lv.get(2);
|
|
||||||
if (lv.size()>3)
|
|
||||||
{
|
|
||||||
return ((ContainerValueInterface) container).put(where, what, lv.get(3));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return ((ContainerValueInterface) container).put(where, what);
|
|
||||||
}
|
}
|
||||||
|
Value where = lv.get(1).evalValue(c);
|
||||||
|
Value what = lv.get(2).evalValue(c);
|
||||||
|
Value retVal = new NumericValue( (lv.size()>3)
|
||||||
|
? ((ContainerValueInterface) container).put(where, what, lv.get(3).evalValue(c))
|
||||||
|
: ((ContainerValueInterface) container).put(where, what));
|
||||||
|
return (cc, tt) -> retVal;
|
||||||
});
|
});
|
||||||
|
|
||||||
addLazyFunction("delete", -1, (c, t, lv) ->
|
addLazyFunction("delete", -1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
if (lv.size() < 1)
|
if (lv.size() == 0)
|
||||||
throw new InternalExpressionException("delete requires arguments");
|
throw new InternalExpressionException("delete requires parameters");
|
||||||
Value containerOrLValue = lv.get(0).evalValue(c, Context.LVALUE);
|
if (lv.size() == 1)
|
||||||
ContainerValueInterface container;
|
|
||||||
Value address;
|
|
||||||
if (containerOrLValue instanceof LContainerValue)
|
|
||||||
{
|
{
|
||||||
container = ((LContainerValue) containerOrLValue).getContainer();
|
Value v = lv.get(0).evalValue(c, Context.LVALUE);
|
||||||
address = ((LContainerValue) containerOrLValue).getAddress();
|
if (!(v instanceof LContainerValue))
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
ContainerValueInterface container = ((LContainerValue) v).getContainer();
|
||||||
|
if (container == null)
|
||||||
|
return (cc, tt) -> Value.NULL;
|
||||||
|
Value ret = new NumericValue(container.delete(((LContainerValue) v).getAddress()));
|
||||||
|
return (cc, tt) -> ret;
|
||||||
}
|
}
|
||||||
else if (containerOrLValue instanceof ContainerValueInterface)
|
Value container = lv.get(0).evalValue(c);
|
||||||
|
for (int i = 1; i < lv.size()-1; i++)
|
||||||
{
|
{
|
||||||
container = (ContainerValueInterface) containerOrLValue;
|
if (!(container instanceof ContainerValueInterface)) return (cc, tt) -> Value.NULL;
|
||||||
if (lv.size() < 2)
|
container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c));
|
||||||
throw new InternalExpressionException("delete requires two arguments, container (list, map) and address");
|
|
||||||
address = lv.get(1).evalValue(c);
|
|
||||||
}
|
}
|
||||||
else
|
if (!(container instanceof ContainerValueInterface))
|
||||||
{
|
return (cc, tt) -> Value.NULL;
|
||||||
throw new InternalExpressionException("First argument of delete should be a container: list, map or nbt");
|
Value ret = new NumericValue(((ContainerValueInterface) container).delete(lv.get(lv.size()-1).evalValue(c)));
|
||||||
}
|
|
||||||
Value ret = container.delete(address);
|
|
||||||
return (cc, tt) -> ret;
|
return (cc, tt) -> ret;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import carpet.script.value.NumericValue;
|
|||||||
import carpet.script.value.StringValue;
|
import carpet.script.value.StringValue;
|
||||||
import carpet.script.value.Value;
|
import carpet.script.value.Value;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
@@ -25,18 +26,25 @@ import static java.lang.Math.max;
|
|||||||
|
|
||||||
public class ScriptHost
|
public class ScriptHost
|
||||||
{
|
{
|
||||||
public final Map<String, ScriptHost> userHosts = new HashMap<>();
|
private final Map<String, ScriptHost> userHosts = new HashMap<>();
|
||||||
public Map<String, UserDefinedFunction> globalFunctions = new HashMap<>();
|
public Map<String, UserDefinedFunction> globalFunctions = new HashMap<>();
|
||||||
public Map<String, LazyValue> globalVariables = new HashMap<>();
|
public Map<String, LazyValue> globalVariables = new HashMap<>();
|
||||||
|
|
||||||
|
private Tag globalState;
|
||||||
|
private int saveTimeout;
|
||||||
|
|
||||||
|
private ScriptHost parent;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
public String getName() {return name;}
|
public String getName() {return name;}
|
||||||
|
|
||||||
private final ModuleInterface myCode;
|
private final ModuleInterface myCode;
|
||||||
public final boolean perUser;
|
private final boolean perUser;
|
||||||
|
|
||||||
ScriptHost(String name, ModuleInterface code, boolean perUser)
|
ScriptHost(String name, ModuleInterface code, boolean perUser, ScriptHost parent)
|
||||||
{
|
{
|
||||||
|
this.saveTimeout = 0;
|
||||||
|
this.parent = parent;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.myCode = code;
|
this.myCode = code;
|
||||||
this.perUser = perUser;
|
this.perUser = perUser;
|
||||||
@@ -50,16 +58,19 @@ public class ScriptHost
|
|||||||
globalVariables.put("_", (c, t) -> Value.ZERO);
|
globalVariables.put("_", (c, t) -> Value.ZERO);
|
||||||
globalVariables.put("_i", (c, t) -> Value.ZERO);
|
globalVariables.put("_i", (c, t) -> Value.ZERO);
|
||||||
globalVariables.put("_a", (c, t) -> Value.ZERO);
|
globalVariables.put("_a", (c, t) -> Value.ZERO);
|
||||||
|
|
||||||
|
if (parent == null && name != null)
|
||||||
|
globalState = loadState();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScriptHost retrieveForExecution(String /*Nullable*/ user)
|
private ScriptHost retrieveForExecution(String /*Nullable*/ user)
|
||||||
{
|
{
|
||||||
if (!perUser)
|
if (!perUser)
|
||||||
return this;
|
return this;
|
||||||
ScriptHost userHost = userHosts.get(user);
|
ScriptHost userHost = userHosts.get(user);
|
||||||
if (userHost != null)
|
if (userHost != null)
|
||||||
return userHost;
|
return userHost;
|
||||||
userHost = new ScriptHost(this.name, myCode, false);
|
userHost = new ScriptHost(this.name, myCode, false, this);
|
||||||
userHost.globalVariables.putAll(this.globalVariables);
|
userHost.globalVariables.putAll(this.globalVariables);
|
||||||
userHost.globalFunctions.putAll(this.globalFunctions);
|
userHost.globalFunctions.putAll(this.globalFunctions);
|
||||||
userHosts.put(user, userHost);
|
userHosts.put(user, userHost);
|
||||||
@@ -221,5 +232,60 @@ public class ScriptHost
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void dumpState()
|
||||||
|
{
|
||||||
|
myCode.saveData(null, globalState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Tag loadState()
|
||||||
|
{
|
||||||
|
return myCode.getData(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tag getGlobalState(String file)
|
||||||
|
{
|
||||||
|
if (name == null || myCode.isInternal()) return null;
|
||||||
|
if (file != null)
|
||||||
|
myCode.getData(file);
|
||||||
|
if (parent == null)
|
||||||
|
return globalState;
|
||||||
|
return parent.globalState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGlobalState(Tag tag, String file)
|
||||||
|
{
|
||||||
|
if (name == null || myCode.isInternal()) return;
|
||||||
|
|
||||||
|
if (file!= null)
|
||||||
|
{
|
||||||
|
myCode.saveData(file, tag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptHost responsibleHost = (parent != null)?parent:this;
|
||||||
|
responsibleHost.globalState = tag;
|
||||||
|
if (responsibleHost.saveTimeout == 0)
|
||||||
|
{
|
||||||
|
responsibleHost.dumpState();
|
||||||
|
responsibleHost.saveTimeout = 200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick()
|
||||||
|
{
|
||||||
|
if (this.saveTimeout > 0)
|
||||||
|
{
|
||||||
|
this.saveTimeout --;
|
||||||
|
if (this.saveTimeout == 0)
|
||||||
|
{
|
||||||
|
dumpState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClose()
|
||||||
|
{
|
||||||
|
if (this.saveTimeout > 0)
|
||||||
|
dumpState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
package carpet.script.bundled;
|
package carpet.script.bundled;
|
||||||
|
|
||||||
import carpet.CarpetServer;
|
import carpet.CarpetServer;
|
||||||
|
import net.minecraft.nbt.EndTag;
|
||||||
|
import net.minecraft.nbt.PositionTracker;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -42,4 +48,76 @@ public class FileModule implements ModuleInterface
|
|||||||
{
|
{
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInternal()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//copied private method from net.minecraft.nbt.NbtIo.read()
|
||||||
|
private static Tag read(File file)
|
||||||
|
{
|
||||||
|
try (DataInputStream dataInput_1 = new DataInputStream(new FileInputStream(file)))
|
||||||
|
{
|
||||||
|
byte byte_1 = dataInput_1.readByte();
|
||||||
|
if (byte_1 == 0)
|
||||||
|
{
|
||||||
|
return new EndTag();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dataInput_1.readUTF();
|
||||||
|
Tag tag_1 = Tag.createTag(byte_1);
|
||||||
|
tag_1.read(dataInput_1, 0, PositionTracker.DEFAULT);
|
||||||
|
return tag_1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ignored)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//copied private method from net.minecraft.nbt.NbtIo.write() and client method safe_write
|
||||||
|
private static void write(Tag tag_1, File file)
|
||||||
|
{
|
||||||
|
File file_2 = new File(file.getAbsolutePath() + "_tmp");
|
||||||
|
if (file_2.exists()) file_2.delete();
|
||||||
|
|
||||||
|
try(DataOutputStream dataOutputStream_1 = new DataOutputStream(new FileOutputStream(file_2)))
|
||||||
|
{
|
||||||
|
dataOutputStream_1.writeByte(tag_1.getType());
|
||||||
|
if (tag_1.getType() != 0)
|
||||||
|
{
|
||||||
|
dataOutputStream_1.writeUTF("");
|
||||||
|
tag_1.write(dataOutputStream_1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (file.exists()) file.delete();
|
||||||
|
if (!file.exists()) file_2.renameTo(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Tag getData(String file)
|
||||||
|
{
|
||||||
|
File dataFile =CarpetServer.minecraft_server.getLevelStorage().resolveFile(
|
||||||
|
CarpetServer.minecraft_server.getLevelName(), "scripts/"+name+".data"+(file==null?"":"."+file)+".nbt");
|
||||||
|
if (!(dataFile.isFile()))
|
||||||
|
return null;
|
||||||
|
return read(dataFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveData(String file, Tag globalState)
|
||||||
|
{
|
||||||
|
File dataFile =CarpetServer.minecraft_server.getLevelStorage().resolveFile(
|
||||||
|
CarpetServer.minecraft_server.getLevelName(), "scripts/"+name+".data"+(file==null?"":"."+file)+".nbt");
|
||||||
|
write(globalState, dataFile);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
package carpet.script.bundled;
|
package carpet.script.bundled;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
|
||||||
public interface ModuleInterface
|
public interface ModuleInterface
|
||||||
{
|
{
|
||||||
String getName();
|
String getName();
|
||||||
String getCode();
|
String getCode();
|
||||||
|
default boolean isInternal() {return true; }
|
||||||
|
default Tag getData(String file) {return null; }
|
||||||
|
default void saveData(String file, Tag globalState) {}
|
||||||
}
|
}
|
||||||
@@ -2,12 +2,12 @@ package carpet.script.value;
|
|||||||
|
|
||||||
public interface ContainerValueInterface
|
public interface ContainerValueInterface
|
||||||
{
|
{
|
||||||
public Value put(Value where, Value value);
|
boolean put(Value where, Value value);
|
||||||
default Value put(Value where, Value value, Value conditions)
|
default boolean put(Value where, Value value, Value conditions)
|
||||||
{
|
{
|
||||||
return put(where, value);
|
return put(where, value);
|
||||||
}
|
}
|
||||||
public Value get(Value where);
|
Value get(Value where);
|
||||||
public boolean has(Value where);
|
boolean has(Value where);
|
||||||
public Value delete(Value where);
|
boolean delete(Value where);
|
||||||
}
|
}
|
||||||
@@ -306,7 +306,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value put(Value where, Value value, Value conditionValue)
|
public boolean put(Value where, Value value, Value conditionValue)
|
||||||
{
|
{
|
||||||
String condition = conditionValue.getString();
|
String condition = conditionValue.getString();
|
||||||
if (condition.equalsIgnoreCase("insert"))
|
if (condition.equalsIgnoreCase("insert"))
|
||||||
@@ -319,11 +319,12 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value put(Value ind, Value value)
|
public boolean put(Value ind, Value value)
|
||||||
{
|
{
|
||||||
return put(ind, value, true, false);
|
return put(ind, value, true, false);
|
||||||
}
|
}
|
||||||
private Value put(Value ind, Value value, boolean replace, boolean extend)
|
|
||||||
|
private boolean put(Value ind, Value value, boolean replace, boolean extend)
|
||||||
{
|
{
|
||||||
if (ind == Value.NULL)
|
if (ind == Value.NULL)
|
||||||
{
|
{
|
||||||
@@ -335,12 +336,14 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
{
|
{
|
||||||
items.add(value);
|
items.add(value);
|
||||||
}
|
}
|
||||||
return items.get(items.size()-1);
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int numitems = items.size();
|
int numitems = items.size();
|
||||||
int index = (int) NumericValue.asNumber(ind).getLong();
|
if (!(ind instanceof NumericValue))
|
||||||
|
return false;
|
||||||
|
int index = (int)((NumericValue) ind).getLong();
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
{
|
{
|
||||||
long range = abs(index) / numitems;
|
long range = abs(index) / numitems;
|
||||||
@@ -350,7 +353,8 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
if (replace)
|
if (replace)
|
||||||
{
|
{
|
||||||
while (index >= items.size()) items.add(Value.NULL);
|
while (index >= items.size()) items.add(Value.NULL);
|
||||||
return items.set(index, value);
|
items.set(index, value);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
while (index > items.size()) items.add(Value.NULL);
|
while (index > items.size()) items.add(Value.NULL);
|
||||||
|
|
||||||
@@ -359,11 +363,10 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
Iterable<Value> iterable = ((AbstractListValue) value)::iterator;
|
Iterable<Value> iterable = ((AbstractListValue) value)::iterator;
|
||||||
List<Value> appendix = StreamSupport.stream( iterable.spliterator(), false).collect(Collectors.toList());
|
List<Value> appendix = StreamSupport.stream( iterable.spliterator(), false).collect(Collectors.toList());
|
||||||
items.addAll(index, appendix );
|
items.addAll(index, appendix );
|
||||||
return items.get(index+appendix.size()-1);
|
return true;
|
||||||
}
|
}
|
||||||
items.add(index, value);
|
items.add(index, value);
|
||||||
return value;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,14 +389,16 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value delete(Value where)
|
public boolean delete(Value where)
|
||||||
{
|
{
|
||||||
long index = NumericValue.asNumber(where).getLong();
|
if (!(where instanceof NumericValue) || items.isEmpty()) return false;
|
||||||
|
long index = ((NumericValue) where).getLong();
|
||||||
int numitems = items.size();
|
int numitems = items.size();
|
||||||
long range = abs(index)/numitems;
|
long range = abs(index)/numitems;
|
||||||
index += (range+2)*numitems;
|
index += (range+2)*numitems;
|
||||||
index = index % numitems;
|
index = index % numitems;
|
||||||
return items.remove((int)index);
|
items.remove((int)index);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -177,21 +177,17 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value delete(Value where)
|
public boolean delete(Value where)
|
||||||
{
|
{
|
||||||
Value ret = map.remove(where);
|
Value ret = map.remove(where);
|
||||||
if (ret == null)
|
return ret != null;
|
||||||
return Value.NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value put(Value key, Value value)
|
public boolean put(Value key, Value value)
|
||||||
{
|
{
|
||||||
Value ret = map.put(key, value);
|
Value ret = map.put(key, value);
|
||||||
if (ret == null)
|
return ret != null;
|
||||||
return Value.NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
|||||||
return new StringValue(t.asString());
|
return new StringValue(t.asString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tag getTag()
|
public Tag getTag()
|
||||||
{
|
{
|
||||||
if (nbtTag == null)
|
if (nbtTag == null)
|
||||||
nbtTag = nbtSupplier.get();
|
nbtTag = nbtSupplier.get();
|
||||||
@@ -210,7 +210,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
|||||||
{
|
{
|
||||||
if (o instanceof NBTSerializableValue)
|
if (o instanceof NBTSerializableValue)
|
||||||
return getTag().equals(((NBTSerializableValue) o).getTag());
|
return getTag().equals(((NBTSerializableValue) o).getTag());
|
||||||
return super.equals((Value)o);
|
return super.equals(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -240,13 +240,13 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value put(Value where, Value value)
|
public boolean put(Value where, Value value)
|
||||||
{
|
{
|
||||||
return put(where, value, new StringValue("replace"));
|
return put(where, value, new StringValue("replace"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value put(Value where, Value value, Value conditions)
|
public boolean put(Value where, Value value, Value conditions)
|
||||||
{
|
{
|
||||||
/// WIP
|
/// WIP
|
||||||
|
|
||||||
@@ -272,14 +272,15 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return this;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (modifiedTag != null)
|
if (modifiedTag != null)
|
||||||
{
|
{
|
||||||
replaceTag(modifiedTag);
|
replaceTag(modifiedTag);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return this;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -412,13 +413,13 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value delete(Value where)
|
public boolean delete(Value where)
|
||||||
{
|
{
|
||||||
NbtPathArgumentType.NbtPath path = cachePath(where.getString());
|
NbtPathArgumentType.NbtPath path = cachePath(where.getString());
|
||||||
Tag tag = getTag().copy();
|
Tag tag = getTag().copy();
|
||||||
int removed = path.remove(tag);
|
int removed = path.remove(tag);
|
||||||
if (removed > 0) replaceTag(tag);
|
if (removed > 0) replaceTag(tag);
|
||||||
return new NumericValue(removed);
|
return removed > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class InventoryLocator
|
public static class InventoryLocator
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ public abstract class Value implements Comparable<Value>, Cloneable
|
|||||||
return getString().compareTo(o.getString());
|
return getString().compareTo(o.getString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // for hashmap key access
|
@Override // for hashmap key access, and == operator
|
||||||
public boolean equals(final Object o)
|
public boolean equals(final Object o)
|
||||||
{
|
{
|
||||||
if (o instanceof Value)
|
if (o instanceof Value)
|
||||||
@@ -124,12 +124,6 @@ public abstract class Value implements Comparable<Value>, Cloneable
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for general use
|
|
||||||
public boolean equals(final Value o)
|
|
||||||
{
|
|
||||||
return this.compareTo(o)==0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void assertAssignable()
|
public void assertAssignable()
|
||||||
{
|
{
|
||||||
if (boundVariable == null || boundVariable.startsWith("_"))
|
if (boundVariable == null || boundVariable.startsWith("_"))
|
||||||
|
|||||||
Reference in new issue
Block a user