20 files changed
+366
-229
No files matched your search
+1
-1
@@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G
|
||||
loader_version=0.6.4+build.169
|
||||
|
||||
# Mod Properties
|
||||
mod_version = 1.2.3+v191113
|
||||
mod_version = 1.2.3+v191114
|
||||
maven_group = carpet
|
||||
archives_base_name = fabric-carpet
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package carpet.fakes;
|
||||
|
||||
import carpet.script.CarpetContext;
|
||||
import carpet.script.CarpetEventServer;
|
||||
import carpet.script.ScriptHost;
|
||||
import carpet.script.value.FunctionValue;
|
||||
import carpet.script.value.Value;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
|
||||
@@ -13,10 +13,10 @@ public interface EntityInterface
|
||||
float getMainYaw(float partialTicks);
|
||||
//scarpet part
|
||||
void onDeathCallback(String reason);
|
||||
void setDeathCallback(CarpetContext cc, String function, List<Value> extraArgs);
|
||||
void setDeathCallback(CarpetContext cc, FunctionValue function, List<Value> extraArgs);
|
||||
void onDamageCallback(float amount, DamageSource source);
|
||||
void setDamageCallback(CarpetContext cc, String function, List<Value> extraArgs);
|
||||
void setRemovedCallback(CarpetContext cc, String function, List<Value> extraArgs);
|
||||
void setTickCallback(CarpetContext cc, String function, List<Value> extraArgs);
|
||||
void setDamageCallback(CarpetContext cc, FunctionValue function, List<Value> extraArgs);
|
||||
void setRemovedCallback(CarpetContext cc, FunctionValue function, List<Value> extraArgs);
|
||||
void setTickCallback(CarpetContext cc, FunctionValue function, List<Value> extraArgs);
|
||||
CarpetEventServer.ScheduledCall getTickCallback();
|
||||
}
|
||||
@@ -4,12 +4,10 @@ import carpet.CarpetServer;
|
||||
import carpet.fakes.EntityInterface;
|
||||
import carpet.script.CarpetContext;
|
||||
import carpet.script.CarpetEventServer;
|
||||
import carpet.script.ScriptHost;
|
||||
import carpet.script.value.FunctionValue;
|
||||
import carpet.script.value.Value;
|
||||
import carpet.settings.CarpetSettings;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import org.lwjgl.system.CallbackI;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -27,23 +25,20 @@ public abstract class Entity_scarpetEventsMixin implements EntityInterface
|
||||
private CarpetEventServer.ScheduledCall tickCall;
|
||||
private CarpetEventServer.ScheduledCall damageCall;
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setDeathCallback(CarpetContext cc, String function, List<Value> extraArgs)
|
||||
public void setDeathCallback(CarpetContext cc, FunctionValue function, List<Value> extraArgs)
|
||||
{
|
||||
deathCall = CarpetServer.scriptServer.events.makeDeathCall(cc, function, extraArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemovedCallback(CarpetContext cc, String function, List<Value> extraArgs)
|
||||
public void setRemovedCallback(CarpetContext cc, FunctionValue function, List<Value> extraArgs)
|
||||
{
|
||||
removeCall = CarpetServer.scriptServer.events.makeRemovedCall(cc, function, extraArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTickCallback(CarpetContext cc, String function, List<Value> extraArgs)
|
||||
public void setTickCallback(CarpetContext cc, FunctionValue function, List<Value> extraArgs)
|
||||
{
|
||||
tickCall = CarpetServer.scriptServer.events.makeTickCall(cc, function, extraArgs);
|
||||
}
|
||||
@@ -55,7 +50,7 @@ public abstract class Entity_scarpetEventsMixin implements EntityInterface
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDamageCallback(CarpetContext cc, String function, List<Value> extraArgs)
|
||||
public void setDamageCallback(CarpetContext cc, FunctionValue function, List<Value> extraArgs)
|
||||
{
|
||||
damageCall = CarpetServer.scriptServer.events.makeDamageCall(cc, function, extraArgs);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package carpet.script;
|
||||
import carpet.CarpetServer;
|
||||
import carpet.script.value.BlockValue;
|
||||
import carpet.script.value.EntityValue;
|
||||
import carpet.script.value.FunctionValue;
|
||||
import carpet.script.value.ListValue;
|
||||
import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.StringValue;
|
||||
@@ -19,6 +20,7 @@ import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -39,9 +41,9 @@ public class CarpetEventServer
|
||||
public static class Callback
|
||||
{
|
||||
public String host;
|
||||
public String udf;
|
||||
public FunctionValue udf;
|
||||
|
||||
public Callback(String host, String udf)
|
||||
public Callback(String host, FunctionValue udf)
|
||||
{
|
||||
this.host = host;
|
||||
this.udf = udf;
|
||||
@@ -50,7 +52,7 @@ public class CarpetEventServer
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return udf+((host==null)?"":"(from "+host+")");
|
||||
return udf.getString()+((host==null)?"":"(from "+host+")");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +63,7 @@ public class CarpetEventServer
|
||||
public BlockPos context_origin;
|
||||
public long dueTime;
|
||||
|
||||
public ScheduledCall(CarpetContext context, String udf, List<LazyValue> args, long dueTime)
|
||||
public ScheduledCall(CarpetContext context, FunctionValue udf, List<LazyValue> args, long dueTime)
|
||||
{
|
||||
super(context.host.getName(), udf);
|
||||
this.args = args;
|
||||
@@ -119,7 +121,7 @@ public class CarpetEventServer
|
||||
// impossible call to add
|
||||
return false;
|
||||
}
|
||||
UserDefinedFunction udf = host.globalFunctions.get(funName);
|
||||
FunctionValue udf = host.globalFunctions.get(funName);
|
||||
if (udf == null || udf.getArguments().size() != reqArgs)
|
||||
{
|
||||
// call won't match arguments
|
||||
@@ -127,13 +129,13 @@ public class CarpetEventServer
|
||||
}
|
||||
//all clear
|
||||
//remove duplicates
|
||||
removeEventCall(hostName, funName);
|
||||
callList.add(new Callback(hostName, funName));
|
||||
removeEventCall(hostName, udf.getString());
|
||||
callList.add(new Callback(hostName, udf));
|
||||
return true;
|
||||
}
|
||||
public void removeEventCall(String hostName, String callName)
|
||||
public void removeEventCall(String hostName, String funName)
|
||||
{
|
||||
callList.removeIf((c)-> c.udf.equalsIgnoreCase(callName) && ( hostName == null || c.host.equalsIgnoreCase(hostName) ) );
|
||||
callList.removeIf((c)-> c.udf.getString().equals(funName) && ( hostName == null || c.host.equalsIgnoreCase(hostName) ) );
|
||||
}
|
||||
|
||||
public void removeAllCalls(String hostName)
|
||||
@@ -445,7 +447,7 @@ public class CarpetEventServer
|
||||
}
|
||||
|
||||
}
|
||||
public void scheduleCall(CarpetContext context, String function, List<LazyValue> args, long due)
|
||||
public void scheduleCall(CarpetContext context, FunctionValue function, List<LazyValue> args, long due)
|
||||
{
|
||||
scheduledCalls.add(new ScheduledCall(context, function, args, due));
|
||||
}
|
||||
@@ -464,8 +466,8 @@ public class CarpetEventServer
|
||||
|
||||
if (!Event.byName.containsKey(event))
|
||||
return false;
|
||||
Callback callback= decodeCallback(funName);
|
||||
Event.byName.get(event).handler.removeEventCall(callback.host, callback.udf);
|
||||
Pair<String,String> call = decodeCallback(funName);
|
||||
Event.byName.get(event).handler.removeEventCall(call.getLeft(), call.getRight());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -474,21 +476,20 @@ public class CarpetEventServer
|
||||
Event.byName.values().forEach((e) -> e.handler.removeAllCalls(hostName));
|
||||
}
|
||||
|
||||
private Callback decodeCallback(String funName)
|
||||
private Pair<String,String> decodeCallback(String funName)
|
||||
{
|
||||
Pattern find = Pattern.compile("(\\w+)\\(from (\\w+)\\)");
|
||||
Matcher matcher = find.matcher(funName);
|
||||
if(matcher.matches())
|
||||
{
|
||||
return new Callback(matcher.group(2), matcher.group(1));
|
||||
return Pair.of(matcher.group(2), matcher.group(1));
|
||||
}
|
||||
return new Callback(null, funName);
|
||||
return Pair.of(null, funName);
|
||||
}
|
||||
|
||||
private ScheduledCall makeEventCall(CarpetContext cc, String function, List<Value> extraArgs, int argCount)
|
||||
private ScheduledCall makeEventCall(CarpetContext cc, FunctionValue function, List<Value> extraArgs, int argCount)
|
||||
{
|
||||
UserDefinedFunction udf = cc.host.globalFunctions.get(function);
|
||||
if (udf == null || (udf.getArguments().size()-(extraArgs == null ? 0 : extraArgs.size())) != argCount)
|
||||
if (function == null || (function.getArguments().size()-(extraArgs == null ? 0 : extraArgs.size())) != argCount)
|
||||
{
|
||||
// call won't match arguments
|
||||
return null;
|
||||
@@ -503,19 +504,19 @@ public class CarpetEventServer
|
||||
return new ScheduledCall(cc, function, lazyArgs, 0);
|
||||
}
|
||||
|
||||
public ScheduledCall makeDeathCall(CarpetContext cc, String function, List<Value> extraArgs)
|
||||
public ScheduledCall makeDeathCall(CarpetContext cc, FunctionValue function, List<Value> extraArgs)
|
||||
{
|
||||
return makeEventCall(cc, function, extraArgs, 2);
|
||||
}
|
||||
public ScheduledCall makeRemovedCall(CarpetContext cc, String function, List<Value> extraArgs)
|
||||
public ScheduledCall makeRemovedCall(CarpetContext cc, FunctionValue function, List<Value> extraArgs)
|
||||
{
|
||||
return makeEventCall(cc, function, extraArgs, 1);
|
||||
}
|
||||
public ScheduledCall makeTickCall(CarpetContext cc, String function, List<Value> extraArgs)
|
||||
public ScheduledCall makeTickCall(CarpetContext cc, FunctionValue function, List<Value> extraArgs)
|
||||
{
|
||||
return makeEventCall(cc, function, extraArgs, 1);
|
||||
}
|
||||
public ScheduledCall makeDamageCall(CarpetContext cc, String function, List<Value> extraArgs)
|
||||
public ScheduledCall makeDamageCall(CarpetContext cc, FunctionValue function, List<Value> extraArgs)
|
||||
{
|
||||
return makeEventCall(cc, function, extraArgs, 4);
|
||||
}
|
||||
|
||||
@@ -5,10 +5,12 @@ import carpet.fakes.MinecraftServerInterface;
|
||||
import carpet.helpers.FeatureGenerator;
|
||||
import carpet.script.Fluff.TriFunction;
|
||||
import carpet.script.exception.CarpetExpressionException;
|
||||
import carpet.script.exception.ExitStatement;
|
||||
import carpet.script.exception.ExpressionException;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import carpet.script.value.BlockValue;
|
||||
import carpet.script.value.EntityValue;
|
||||
import carpet.script.value.FunctionValue;
|
||||
import carpet.script.value.LazyListValue;
|
||||
import carpet.script.value.ListValue;
|
||||
import carpet.script.value.NBTSerializableValue;
|
||||
@@ -2012,9 +2014,16 @@ public class CarpetExpression
|
||||
throw new InternalExpressionException("First argument to entity_event should be an entity");
|
||||
String what = lv.get(1).evalValue(c).getString();
|
||||
Value functionValue = lv.get(2).evalValue(c);
|
||||
String function = null;
|
||||
if (!(functionValue instanceof NullValue))
|
||||
function = functionValue.getString();
|
||||
if (functionValue instanceof NullValue)
|
||||
functionValue = null;
|
||||
else if (!(functionValue instanceof FunctionValue))
|
||||
{
|
||||
String name = functionValue.getString();
|
||||
functionValue = c.host.globalFunctions.get(name);
|
||||
if (functionValue == null)
|
||||
throw new InternalExpressionException("Function "+name+" is not defined yet");
|
||||
}
|
||||
FunctionValue function = (FunctionValue)functionValue;
|
||||
List<Value> args = null;
|
||||
if (lv.size()==4)
|
||||
args = Collections.singletonList(lv.get(3).evalValue(c));
|
||||
@@ -2928,7 +2937,7 @@ public class CarpetExpression
|
||||
CarpetServer.scriptServer.tickStart = System.nanoTime(); // for the next tick
|
||||
Thread.yield();
|
||||
if(CarpetServer.scriptServer.stopAll)
|
||||
throw new Expression.ExitStatement(Value.NULL);
|
||||
throw new ExitStatement(Value.NULL);
|
||||
return (cc, tt) -> Value.TRUE;
|
||||
});
|
||||
|
||||
@@ -3002,20 +3011,28 @@ public class CarpetExpression
|
||||
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();
|
||||
String funname = lv.get(1).evalValue(c).getString();
|
||||
|
||||
Value functionValue = lv.get(1).evalValue(c);
|
||||
if (!(functionValue instanceof FunctionValue))
|
||||
{
|
||||
String name = functionValue.getString();
|
||||
functionValue = c.host.globalFunctions.get(name);
|
||||
if (functionValue == null)
|
||||
throw new InternalExpressionException("Function "+name+" is not defined yet");
|
||||
}
|
||||
FunctionValue function = (FunctionValue)functionValue;
|
||||
|
||||
CarpetContext cc = (CarpetContext)c;
|
||||
if (!cc.host.globalFunctions.containsKey(funname))
|
||||
throw new InternalExpressionException("Function "+funname+" is not defined");
|
||||
List<LazyValue> args = new ArrayList<>();
|
||||
for (int i=2; i < lv.size(); i++)
|
||||
{
|
||||
Value arg = lv.get(i).evalValue(cc);
|
||||
args.add( (_c, _t) -> arg);
|
||||
}
|
||||
if (cc.host.globalFunctions.get(funname).getArguments().size() != args.size())
|
||||
throw new InternalExpressionException("Function "+funname+" takes "+
|
||||
cc.host.globalFunctions.get(funname).getArguments().size()+" arguments, "+args.size()+" provided.");
|
||||
CarpetServer.scriptServer.events.scheduleCall(cc, funname, args, delay);
|
||||
if (function.getArguments().size() != args.size())
|
||||
throw new InternalExpressionException("Function "+function.getString()+" takes "+
|
||||
function.getArguments().size()+" arguments, "+args.size()+" provided.");
|
||||
CarpetServer.scriptServer.events.scheduleCall(cc, function, args, delay);
|
||||
return (c_, t_) -> Value.TRUE;
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package carpet.script;
|
||||
|
||||
import carpet.script.bundled.BundledModule;
|
||||
import carpet.script.value.FunctionValue;
|
||||
import carpet.script.value.MapValue;
|
||||
import carpet.script.value.StringValue;
|
||||
import carpet.settings.CarpetSettings;
|
||||
@@ -365,19 +366,19 @@ public class CarpetScriptServer
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean runas(ServerCommandSource source, String hostname, String udf_name, List<LazyValue> argv)
|
||||
public boolean runas(ServerCommandSource source, String hostname, FunctionValue udf, List<LazyValue> argv)
|
||||
{
|
||||
return runas(BlockPos.ORIGIN, source, hostname, udf_name, argv);
|
||||
return runas(BlockPos.ORIGIN, source, hostname, udf, argv);
|
||||
}
|
||||
|
||||
public boolean runas(BlockPos origin, ServerCommandSource source, String hostname, String udf_name, List<LazyValue> argv)
|
||||
public boolean runas(BlockPos origin, ServerCommandSource source, String hostname, FunctionValue udf, List<LazyValue> argv)
|
||||
{
|
||||
ScriptHost host = globalHost;
|
||||
try
|
||||
{
|
||||
if (hostname != null)
|
||||
host = modules.get(hostname).retrieveForExecution(source);
|
||||
host.callUDF(origin, source, host.globalFunctions.get(udf_name), argv);
|
||||
host.callUDF(origin, source, udf, argv);
|
||||
}
|
||||
catch (NullPointerException | InvalidCallbackException npe)
|
||||
{
|
||||
|
||||
@@ -37,7 +37,7 @@ public class Context
|
||||
return host.globalVariables.get(name);
|
||||
}
|
||||
|
||||
void setVariable(String name, LazyValue lv)
|
||||
public void setVariable(String name, LazyValue lv)
|
||||
{
|
||||
if (name.startsWith("global_"))
|
||||
{
|
||||
|
||||
@@ -11,11 +11,15 @@ import carpet.script.Fluff.QuadFunction;
|
||||
import carpet.script.Fluff.QuinnFunction;
|
||||
import carpet.script.Fluff.SexFunction;
|
||||
import carpet.script.Fluff.TriFunction;
|
||||
import carpet.script.exception.ExitStatement;
|
||||
import carpet.script.exception.ExpressionException;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import carpet.script.exception.ReturnStatement;
|
||||
import carpet.script.exception.ThrowStatement;
|
||||
import carpet.script.value.AbstractListValue;
|
||||
import carpet.script.value.ContainerValueInterface;
|
||||
import carpet.script.value.FunctionSignatureValue;
|
||||
import carpet.script.value.FunctionValue;
|
||||
import carpet.script.value.GlobalValue;
|
||||
import carpet.script.value.LContainerValue;
|
||||
import carpet.script.value.LazyListValue;
|
||||
@@ -389,31 +393,6 @@ public class Expression implements Cloneable
|
||||
return copy;
|
||||
}
|
||||
|
||||
/* Exception thrown to terminate execution mid expression (aka return statement) */
|
||||
static class ExitStatement extends RuntimeException
|
||||
{
|
||||
Value retval;
|
||||
ExitStatement(Value value)
|
||||
{
|
||||
retval = value;
|
||||
}
|
||||
}
|
||||
static class ReturnStatement extends ExitStatement
|
||||
{
|
||||
|
||||
ReturnStatement(Value value)
|
||||
{
|
||||
super(value);
|
||||
}
|
||||
}
|
||||
static class ThrowStatement extends ExitStatement
|
||||
{
|
||||
ThrowStatement(Value value)
|
||||
{
|
||||
super(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static List<String> getExpressionSnippet(Tokenizer.Token token, Expression expr)
|
||||
{
|
||||
@@ -679,22 +658,11 @@ public class Expression implements Cloneable
|
||||
}
|
||||
});
|
||||
}
|
||||
private void addContextFunction(Context context, String name, Expression expr, Tokenizer.Token token, List<String> arguments, List<String> globals, LazyValue code)
|
||||
private FunctionValue addContextFunction(Context context, String name, Expression expr, Tokenizer.Token token, List<String> arguments, List<String> globals, LazyValue code)
|
||||
{
|
||||
name = name.toLowerCase(Locale.ROOT);
|
||||
if (functions.containsKey(name))
|
||||
throw new ExpressionException(expr, token, "Function "+name+" would mask a built-in function");
|
||||
Expression function_context;
|
||||
try
|
||||
{
|
||||
function_context = expr.clone();
|
||||
function_context.name = name;
|
||||
}
|
||||
catch (CloneNotSupportedException e)
|
||||
{
|
||||
throw new ExpressionException(expr, token, "Problems in allocating global function "+name);
|
||||
}
|
||||
|
||||
Map<String, LazyValue> contextValues = new HashMap<>();
|
||||
for (String global : globals)
|
||||
{
|
||||
@@ -708,67 +676,12 @@ public class Expression implements Cloneable
|
||||
contextValues.put(global, lv);
|
||||
}
|
||||
}
|
||||
if (contextValues.isEmpty()) contextValues = null;
|
||||
|
||||
context.host.globalFunctions.put(name, new UserDefinedFunction(arguments, function_context, token)
|
||||
{
|
||||
@Override
|
||||
public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List<LazyValue> lazyParams)
|
||||
{
|
||||
if (arguments.size() != lazyParams.size()) // something that might be subject to change in the future
|
||||
{
|
||||
throw new ExpressionException(e, t,
|
||||
"Incorrect number of arguments for function "+name+
|
||||
". Should be "+arguments.size()+", not "+lazyParams.size()+" like "+arguments
|
||||
);
|
||||
}
|
||||
Context newFrame = c.recreate();
|
||||
|
||||
contextValues.forEach(newFrame::setVariable);
|
||||
for (int i=0; i<arguments.size(); i++)
|
||||
{
|
||||
String arg = arguments.get(i);
|
||||
Value val = lazyParams.get(i).evalValue(c).reboundedTo(arg);
|
||||
newFrame.setVariable(arg, (cc, tt) -> val);
|
||||
}
|
||||
Value retVal;
|
||||
boolean rethrow = false;
|
||||
try
|
||||
{
|
||||
retVal = code.evalValue(newFrame, type); // todo not sure if we need to propagete type / consider boolean context in defined functions - answer seems ye
|
||||
}
|
||||
catch (ReturnStatement returnStatement)
|
||||
{
|
||||
retVal = returnStatement.retval;
|
||||
}
|
||||
catch (ThrowStatement throwStatement) // might not be really necessary
|
||||
{
|
||||
retVal = throwStatement.retval;
|
||||
rethrow = true;
|
||||
}
|
||||
catch (InternalExpressionException exc)
|
||||
{
|
||||
throw new ExpressionException(function_context, t, exc.getMessage());
|
||||
}
|
||||
catch (ArithmeticException exc)
|
||||
{
|
||||
throw new ExpressionException(function_context, t, "Your math is wrong, "+exc.getMessage());
|
||||
}
|
||||
catch (ExitStatement | ExpressionException exit)
|
||||
{
|
||||
throw exit;
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
throw new ExpressionException(e, t, "Error while evaluating expression: "+exc.getMessage());
|
||||
}
|
||||
if (rethrow)
|
||||
{
|
||||
throw new ThrowStatement(retVal);
|
||||
}
|
||||
Value otherRetVal = retVal;
|
||||
return (cc, tt) -> otherRetVal;
|
||||
}
|
||||
});
|
||||
FunctionValue result = new FunctionValue(expr, token, name, code, arguments, contextValues);
|
||||
// do not store lambda definitions
|
||||
if (!name.equals("_")) context.host.globalFunctions.put(name, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -944,25 +857,28 @@ public class Expression implements Cloneable
|
||||
addLazyFunctionWithDelegation("call",-1, (c, t, expr, tok, lv) -> { // adjust based on c
|
||||
if (lv.size() == 0)
|
||||
throw new InternalExpressionException("'call' expects at least function name to call");
|
||||
String name = lv.get(0).evalValue(c).getString();
|
||||
//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
|
||||
{
|
||||
if (!c.host.globalFunctions.containsKey(name))
|
||||
Value functionValue = lv.get(0).evalValue(c);
|
||||
if (!(functionValue instanceof FunctionValue))
|
||||
{
|
||||
throw new InternalExpressionException("Function "+name+" is not defined yet");
|
||||
String name = functionValue.getString();
|
||||
functionValue = c.host.globalFunctions.get(name);
|
||||
if (functionValue == null)
|
||||
throw new InternalExpressionException("Function "+name+" is not defined yet");
|
||||
}
|
||||
List<LazyValue> lvargs = new ArrayList<>(lv.size()-1);
|
||||
for (int i=1; i< lv.size(); i++)
|
||||
{
|
||||
lvargs.add(lv.get(i));
|
||||
}
|
||||
UserDefinedFunction acf = c.host.globalFunctions.get(name);
|
||||
Value retval = acf.lazyEval(c, t, acf.expression, acf.token, lvargs).evalValue(c);
|
||||
FunctionValue fun = (FunctionValue)functionValue;
|
||||
Value retval = fun.callInContext(expr, c, t, fun.getExpression(), fun.getToken(), lvargs).evalValue(c);
|
||||
return (cc, tt) -> retval; ///!!!! dono might need to store expr and token in statics? (e? t?)
|
||||
}
|
||||
|
||||
// gimme signature
|
||||
String name = lv.get(0).evalValue(c).getString();
|
||||
List<String> args = new ArrayList<>();
|
||||
List<String> globals = new ArrayList<>();
|
||||
for (int i = 1; i < lv.size(); i++)
|
||||
@@ -981,8 +897,6 @@ public class Expression implements Cloneable
|
||||
args.add(v.boundVariable);
|
||||
}
|
||||
}
|
||||
if (name.equals("_"))
|
||||
name = "__lambda_"+tok.lineno+"_"+tok.linepos;
|
||||
Value retval = new FunctionSignatureValue(name, args, globals);
|
||||
return (cc, tt) -> retval;
|
||||
});
|
||||
@@ -1003,20 +917,11 @@ public class Expression implements Cloneable
|
||||
addLazyBinaryOperatorWithDelegation("->", precedence.get("def->"), false, (c, type, e, t, lv1, lv2) ->
|
||||
{
|
||||
Value v1 = lv1.evalValue(c, Context.SIGNATURE);
|
||||
String result;
|
||||
if (v1 instanceof FunctionSignatureValue)
|
||||
{
|
||||
FunctionSignatureValue sign = (FunctionSignatureValue) v1;
|
||||
addContextFunction(c, sign.getName(), e, t, sign.getArgs(), sign.getGlobals(), lv2);
|
||||
result = sign.getName();
|
||||
}
|
||||
else
|
||||
{
|
||||
v1.assertAssignable();
|
||||
c.setVariable(v1.getVariable(), lv2);
|
||||
result = v1.getVariable();
|
||||
}
|
||||
return (cc, tt) -> new StringValue(result);
|
||||
if (!(v1 instanceof FunctionSignatureValue))
|
||||
throw new InternalExpressionException("'->' operator requires a function signature on the LHS");
|
||||
FunctionSignatureValue sign = (FunctionSignatureValue) v1;
|
||||
Value result = addContextFunction(c, sign.getName(), e, t, sign.getArgs(), sign.getGlobals(), lv2);
|
||||
return (cc, tt) -> result;
|
||||
});
|
||||
|
||||
addFunction("exit", (lv) -> { throw new ExitStatement(lv.size()==0?Value.NULL:lv.get(0)); });
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package carpet.script;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import carpet.script.exception.ExpressionException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -26,6 +26,20 @@ public class ExpressionInspector
|
||||
return e.getName();
|
||||
}
|
||||
|
||||
public static Expression Expression_cloneWithName(Expression e, String name, Tokenizer.Token token)
|
||||
{
|
||||
Expression copy = null;
|
||||
try
|
||||
{
|
||||
copy = e.clone();
|
||||
}
|
||||
catch (CloneNotSupportedException ex)
|
||||
{
|
||||
throw new ExpressionException(e, token, "Problems in allocating global function "+name);
|
||||
}
|
||||
return copy.withName(name);
|
||||
}
|
||||
|
||||
private static TreeSet<String> scarpetFunctions;
|
||||
private static TreeSet<String> APIFunctions;
|
||||
static
|
||||
|
||||
@@ -2,6 +2,7 @@ package carpet.script;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import carpet.script.bundled.ModuleInterface;
|
||||
import carpet.script.value.FunctionValue;
|
||||
import carpet.settings.CarpetSettings;
|
||||
import carpet.script.exception.ExpressionException;
|
||||
import carpet.script.exception.InvalidCallbackException;
|
||||
@@ -20,7 +21,6 @@ import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -31,7 +31,7 @@ import static java.lang.Math.max;
|
||||
public class ScriptHost
|
||||
{
|
||||
private final Map<String, ScriptHost> userHosts = new Object2ObjectOpenHashMap<>();
|
||||
public Map<String, UserDefinedFunction> globalFunctions = new Object2ObjectOpenHashMap<>();
|
||||
public Map<String, FunctionValue> globalFunctions = new Object2ObjectOpenHashMap<>();
|
||||
public Map<String, LazyValue> globalVariables = new Object2ObjectOpenHashMap<>();
|
||||
|
||||
private Tag globalState;
|
||||
@@ -118,8 +118,8 @@ public class ScriptHost
|
||||
{
|
||||
if (CarpetServer.scriptServer.stopAll)
|
||||
return "SCARPET PAUSED";
|
||||
UserDefinedFunction acf = globalFunctions.get(call);
|
||||
if (acf == null)
|
||||
FunctionValue function = globalFunctions.get(call);
|
||||
if (function == null)
|
||||
return "UNDEFINED";
|
||||
List<LazyValue> argv = new ArrayList<>();
|
||||
if (coords != null)
|
||||
@@ -185,7 +185,7 @@ public class ScriptHost
|
||||
return "Fail: "+tok.surface+" is not allowed in invoke";
|
||||
}
|
||||
}
|
||||
List<String> args = acf.getArguments();
|
||||
List<String> args = function.getArguments();
|
||||
if (argv.size() != args.size())
|
||||
{
|
||||
String error = "Fail: stored function "+call+" takes "+args.size()+" arguments, not "+argv.size()+ ":\n";
|
||||
@@ -200,7 +200,7 @@ public class 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 Expression.evalValue(
|
||||
() -> acf.lazyEval(context, Context.VOID, acf.expression, acf.token, argv),
|
||||
() -> function.lazyEval(context, Context.VOID, function.getExpression(), function.getToken(), argv),
|
||||
context,
|
||||
Context.VOID
|
||||
).getString();
|
||||
@@ -211,13 +211,11 @@ public class ScriptHost
|
||||
}
|
||||
}
|
||||
|
||||
public Value callUDF(BlockPos pos, ServerCommandSource source, UserDefinedFunction acf, List<LazyValue> argv) throws InvalidCallbackException
|
||||
public Value callUDF(BlockPos pos, ServerCommandSource source, FunctionValue fun, List<LazyValue> argv) throws InvalidCallbackException
|
||||
{
|
||||
if (CarpetServer.scriptServer.stopAll)
|
||||
return Value.NULL;
|
||||
|
||||
List<String> args = acf.getArguments();
|
||||
if (argv.size() != args.size())
|
||||
if (argv.size() != fun.getArguments().size())
|
||||
{
|
||||
throw new InvalidCallbackException();
|
||||
}
|
||||
@@ -226,7 +224,7 @@ public class ScriptHost
|
||||
// TODO: this is just for now - invoke would be able to invoke other hosts scripts
|
||||
Context context = new CarpetContext(this, source, pos);
|
||||
return Expression.evalValue(
|
||||
() -> acf.lazyEval(context, Context.VOID, acf.expression, acf.token, argv),
|
||||
() -> fun.lazyEval(context, Context.VOID, fun.getExpression(), fun.getToken(), argv),
|
||||
context,
|
||||
Context.VOID);
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package carpet.script;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class UserDefinedFunction extends Fluff.AbstractLazyFunction implements Fluff.ILazyFunction
|
||||
{
|
||||
protected List<String> arguments;
|
||||
protected Expression expression;
|
||||
protected Tokenizer.Token token;
|
||||
UserDefinedFunction(List<String> args, Expression expr, Tokenizer.Token t)
|
||||
{
|
||||
super(args.size());
|
||||
arguments = args;
|
||||
expression = expr;
|
||||
token = t;
|
||||
}
|
||||
public List<String> getArguments()
|
||||
{
|
||||
return arguments;
|
||||
}
|
||||
public Expression getExpression()
|
||||
{
|
||||
return expression;
|
||||
}
|
||||
public Tokenizer.Token getToken()
|
||||
{
|
||||
return token;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package carpet.script.exception;
|
||||
|
||||
import carpet.script.value.Value;
|
||||
|
||||
/* Exception thrown to terminate execution mid expression (aka return statement) */
|
||||
public class ExitStatement extends RuntimeException
|
||||
{
|
||||
public Value retval;
|
||||
public ExitStatement(Value value)
|
||||
{
|
||||
retval = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package carpet.script.exception;
|
||||
|
||||
import carpet.script.value.Value;
|
||||
|
||||
public class ReturnStatement extends ExitStatement
|
||||
{
|
||||
|
||||
public ReturnStatement(Value value)
|
||||
{
|
||||
super(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package carpet.script.exception;
|
||||
|
||||
import carpet.script.value.Value;
|
||||
|
||||
public class ThrowStatement extends ExitStatement
|
||||
{
|
||||
public ThrowStatement(Value value)
|
||||
{
|
||||
super(value);
|
||||
}
|
||||
}
|
||||
@@ -775,14 +775,14 @@ public class EntityValue extends Value
|
||||
// "nbt" <-big one, for now use run('data merge entity ...
|
||||
}};
|
||||
|
||||
public void setEvent(CarpetContext cc, String event, String fun, List<Value> args)
|
||||
public void setEvent(CarpetContext cc, String event, FunctionValue fun, List<Value> args)
|
||||
{
|
||||
if (!(events.containsKey(event)))
|
||||
throw new InternalExpressionException("Unknown entity event: " + event);
|
||||
events.get(event).accept(cc, entity, fun, args);
|
||||
}
|
||||
|
||||
private static Map<String, Fluff.QuadConsumer<CarpetContext, Entity, String, List<Value>>> events = new HashMap<String, Fluff.QuadConsumer<CarpetContext, Entity, String, List<Value>>>() {{
|
||||
private static Map<String, Fluff.QuadConsumer<CarpetContext, Entity, FunctionValue, List<Value>>> events = new HashMap<String, Fluff.QuadConsumer<CarpetContext, Entity, FunctionValue, List<Value>>>() {{
|
||||
put("on_death", (c, e, f, l) -> ((EntityInterface)e).setDeathCallback(c, f, l));
|
||||
put("on_removed", (c, e, f, l) -> ((EntityInterface)e).setRemovedCallback(c, f, l));
|
||||
put("on_tick", (c, e, f, l) -> ((EntityInterface)e).setTickCallback(c, f, l));
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.exception.ExpressionException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FunctionSignatureValue extends FrameworkValue
|
||||
@@ -10,7 +8,6 @@ public class FunctionSignatureValue extends FrameworkValue
|
||||
private List<String> arguments;
|
||||
private List<String> globals;
|
||||
|
||||
|
||||
public FunctionSignatureValue(String name, List<String> args, List<String> globals)
|
||||
{
|
||||
this.identifier = name;
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.Context;
|
||||
import carpet.script.Expression;
|
||||
import carpet.script.ExpressionInspector;
|
||||
import carpet.script.Fluff;
|
||||
import carpet.script.LazyValue;
|
||||
import carpet.script.Tokenizer;
|
||||
import carpet.script.exception.ExitStatement;
|
||||
import carpet.script.exception.ExpressionException;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import carpet.script.exception.ReturnStatement;
|
||||
import carpet.script.exception.ThrowStatement;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class FunctionValue extends Value implements Fluff.ILazyFunction
|
||||
{
|
||||
private Expression expression;
|
||||
private Tokenizer.Token token;
|
||||
private String name;
|
||||
private LazyValue body;
|
||||
private Map<String, LazyValue> outerState;
|
||||
private List<String> args;
|
||||
private static long variantCounter = 1;
|
||||
private long variant;
|
||||
|
||||
public FunctionValue(Expression expression, Tokenizer.Token token, String name, LazyValue body, List<String> args)
|
||||
{
|
||||
this.expression = expression;
|
||||
this.token = token;
|
||||
this.name = name;
|
||||
this.body = body;
|
||||
this.args = args;
|
||||
this.outerState = null;
|
||||
variant = 0L;
|
||||
}
|
||||
|
||||
public FunctionValue(Expression expression, Tokenizer.Token token, String name, LazyValue body, List<String> args, Map<String, LazyValue> outerState)
|
||||
{
|
||||
this.expression = expression;
|
||||
this.token = token;
|
||||
this.name = name;
|
||||
this.body = body;
|
||||
this.args = args;
|
||||
this.outerState = outerState;
|
||||
variant = variantCounter++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Value clone()
|
||||
{
|
||||
FunctionValue ret = new FunctionValue(expression, token, name, body, args);
|
||||
ret.outerState = this.outerState;
|
||||
ret.variant = this.variant;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return name.hashCode()+(int)variant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (o instanceof FunctionValue)
|
||||
return name.equals(((FunctionValue) o).name) && variant == ((FunctionValue) o).variant;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final Value o)
|
||||
{
|
||||
if (o instanceof FunctionValue)
|
||||
{
|
||||
int nameSame = this.name.compareTo(((FunctionValue) o).name);
|
||||
if (nameSame != 0)
|
||||
return nameSame;
|
||||
return (int) (variant-((FunctionValue) o).variant);
|
||||
}
|
||||
return getString().compareTo(o.getString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double readNumber()
|
||||
{
|
||||
throw new InternalExpressionException("Function value has no numeric value");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value slice(long from, long to)
|
||||
{
|
||||
throw new InternalExpressionException("Cannot slice a function");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumParams()
|
||||
{
|
||||
return args.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean numParamsVaries()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public LazyValue callInContext(Expression callingExpression, Context c, Integer type, Expression e, Tokenizer.Token t, List<LazyValue> lazyParams)
|
||||
{
|
||||
// this hole thing might not be really needed
|
||||
Expression callContext = ExpressionInspector.Expression_cloneWithName(callingExpression, name, t);
|
||||
try
|
||||
{
|
||||
return lazyEval(c, type, e, t, lazyParams);
|
||||
}
|
||||
catch (InternalExpressionException exc)
|
||||
{
|
||||
throw new ExpressionException(callContext, t, exc.getMessage());
|
||||
}
|
||||
catch (ArithmeticException exc)
|
||||
{
|
||||
throw new ExpressionException(callContext, t, "Your math is wrong, "+exc.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LazyValue lazyEval(Context c, Integer type, Expression e, Tokenizer.Token t, List<LazyValue> lazyParams)
|
||||
{
|
||||
if (args.size() != lazyParams.size()) // something that might be subject to change in the future
|
||||
// in case we add variable arguments
|
||||
{
|
||||
throw new ExpressionException(e, t,
|
||||
"Incorrect number of arguments for function "+name+
|
||||
". Should be "+args.size()+", not "+lazyParams.size()+" like "+args
|
||||
);
|
||||
}
|
||||
Context newFrame = c.recreate();
|
||||
|
||||
if (outerState != null) outerState.forEach(newFrame::setVariable);
|
||||
for (int i=0; i<args.size(); i++)
|
||||
{
|
||||
String arg = args.get(i);
|
||||
Value val = lazyParams.get(i).evalValue(c).reboundedTo(arg);
|
||||
newFrame.setVariable(arg, (cc, tt) -> val);
|
||||
}
|
||||
Value retVal;
|
||||
boolean rethrow = false;
|
||||
try
|
||||
{
|
||||
retVal = body.evalValue(newFrame, type); // todo not sure if we need to propagete type / consider boolean context in defined functions - answer seems ye
|
||||
}
|
||||
catch (ReturnStatement returnStatement)
|
||||
{
|
||||
retVal = returnStatement.retval;
|
||||
}
|
||||
catch (ThrowStatement throwStatement) // might not be really necessary
|
||||
{
|
||||
retVal = throwStatement.retval;
|
||||
rethrow = true;
|
||||
}
|
||||
catch (ArithmeticException | ExitStatement | ExpressionException exc)
|
||||
{
|
||||
throw exc; // rethrow so could be contextualized if needed
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
throw new ExpressionException(e, t, "Error while evaluating expression: "+exc.getMessage());
|
||||
}
|
||||
if (rethrow)
|
||||
{
|
||||
throw new ThrowStatement(retVal);
|
||||
}
|
||||
Value otherRetVal = retVal;
|
||||
return (cc, tt) -> otherRetVal;
|
||||
}
|
||||
|
||||
public Expression getExpression()
|
||||
{
|
||||
return expression;
|
||||
}
|
||||
public Tokenizer.Token getToken()
|
||||
{
|
||||
return token;
|
||||
}
|
||||
public List<String> getArguments()
|
||||
{
|
||||
return args;
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import static carpet.settings.RuleCategory.TNT;
|
||||
|
||||
public class CarpetSettings
|
||||
{
|
||||
public static final String carpetVersion = "1.2.3+v191113";
|
||||
public static final String carpetVersion = "1.2.3+v191114";
|
||||
public static final Logger LOG = LogManager.getLogger();
|
||||
public static boolean skipGenerationChecks = false;
|
||||
public static boolean impendingFillSkipUpdates = false;
|
||||
|
||||
@@ -3,6 +3,7 @@ package carpet.settings;
|
||||
import carpet.CarpetServer;
|
||||
import carpet.utils.Messenger;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
@@ -264,8 +265,10 @@ public class SettingsManager
|
||||
String lcSearch = search.toLowerCase(Locale.ROOT);
|
||||
return rules.values().stream().filter(rule ->
|
||||
{
|
||||
if (rule.name.toLowerCase(Locale.ROOT).contains(lcSearch)) return true;
|
||||
for (String c : rule.categories) if (c.toLowerCase(Locale.ROOT).equals(search)) return true;
|
||||
if (rule.name.toLowerCase(Locale.ROOT).contains(lcSearch)) return true; // substring match, case insensitive
|
||||
for (String c : rule.categories) if (c.equals(search)) return true; // category exactly, case sensitive
|
||||
if (Sets.newHashSet(rule.description.toLowerCase(Locale.ROOT).split("\\W+")).contains(lcSearch))
|
||||
return true; // contains full term in description, but case insensitive
|
||||
return false;
|
||||
}).collect(ImmutableList.toImmutableList());
|
||||
}
|
||||
|
||||
@@ -53,11 +53,6 @@ public class CarpetProfiler
|
||||
}
|
||||
}
|
||||
|
||||
private static String getWorldString(World world)
|
||||
{
|
||||
return world.getDimension().getType().toString().replaceFirst("minecraft:", "") + (world.isClient ? "(Client)" : "");
|
||||
}
|
||||
|
||||
private static String getSectionString(World world, String section)
|
||||
{
|
||||
return String.format("%s.%s%s",
|
||||
@@ -136,7 +131,7 @@ public class CarpetProfiler
|
||||
|
||||
public static void end_current_section(ProfilerToken tok)
|
||||
{
|
||||
if (tick_health_requested == 0L || test_type != TYPE.GENERAL || current_tick_start == 0)
|
||||
if (tick_health_requested == 0L || test_type != TYPE.GENERAL || current_tick_start == 0 || tok == null)
|
||||
return;
|
||||
long end_time = System.nanoTime();
|
||||
if (tok.type == TYPE.GENERAL)
|
||||
@@ -154,7 +149,7 @@ public class CarpetProfiler
|
||||
|
||||
public static void end_current_entity_section(ProfilerToken tok)
|
||||
{
|
||||
if (tick_health_requested == 0L || test_type != TYPE.ENTITY || current_tick_start == 0)
|
||||
if (tick_health_requested == 0L || test_type != TYPE.ENTITY || current_tick_start == 0 || tok == null)
|
||||
return;
|
||||
long end_time = System.nanoTime();
|
||||
String section;
|
||||
|
||||
Reference in new issue
Block a user