Merge pull request #755 from OneShotMC/master
fix //calc still being able to crash servers
This commit is contained in:
commit
3babe53f91
|
@ -116,6 +116,7 @@ import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||||
import com.sk89q.worldedit.internal.command.WorldEditBinding;
|
import com.sk89q.worldedit.internal.command.WorldEditBinding;
|
||||||
import com.sk89q.worldedit.internal.expression.Expression;
|
import com.sk89q.worldedit.internal.expression.Expression;
|
||||||
import com.sk89q.worldedit.internal.expression.runtime.ExpressionEnvironment;
|
import com.sk89q.worldedit.internal.expression.runtime.ExpressionEnvironment;
|
||||||
|
import com.sk89q.worldedit.internal.expression.runtime.For;
|
||||||
import com.sk89q.worldedit.internal.expression.runtime.Functions;
|
import com.sk89q.worldedit.internal.expression.runtime.Functions;
|
||||||
import com.sk89q.worldedit.math.convolution.HeightMap;
|
import com.sk89q.worldedit.math.convolution.HeightMap;
|
||||||
import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation;
|
import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation;
|
||||||
|
@ -645,6 +646,7 @@ public class Fawe {
|
||||||
WorldEditExpressionEnvironment.inject(); // Optimizations + features
|
WorldEditExpressionEnvironment.inject(); // Optimizations + features
|
||||||
Expression.inject(); // Optimizations
|
Expression.inject(); // Optimizations
|
||||||
Functions.inject(); // Optimizations
|
Functions.inject(); // Optimizations
|
||||||
|
For.inject(); // Fixes
|
||||||
// BlockData
|
// BlockData
|
||||||
BlockData.inject(); // Temporary fix for 1.9.4
|
BlockData.inject(); // Temporary fix for 1.9.4
|
||||||
BundledBlockData.inject(); // Add custom rotation
|
BundledBlockData.inject(); // Add custom rotation
|
||||||
|
|
|
@ -87,10 +87,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
|
@ -552,21 +549,30 @@ public class UtilityCommands extends MethodCommands {
|
||||||
try {
|
try {
|
||||||
FaweLimit limit = FawePlayer.wrap(actor).getLimit();
|
FaweLimit limit = FawePlayer.wrap(actor).getLimit();
|
||||||
final Expression expression = Expression.compile(input);
|
final Expression expression = Expression.compile(input);
|
||||||
double[] result = new double[] { Double.NaN };
|
|
||||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||||
|
Future<Double> futureResult = executor.submit(new Callable<Double>() {
|
||||||
|
@Override
|
||||||
|
public Double call() throws Exception {
|
||||||
|
|
||||||
|
return expression.evaluate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Double result = Double.NaN;
|
||||||
try {
|
try {
|
||||||
executor.invokeAll(Arrays.asList(new Callable<Object>() {
|
result = futureResult.get(limit.MAX_EXPRESSION_MS, TimeUnit.MILLISECONDS);
|
||||||
@Override
|
|
||||||
public Object call() throws Exception {
|
|
||||||
result[0] = expression.evaluate();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}), limit.MAX_EXPRESSION_MS, TimeUnit.MILLISECONDS); // Default timeout of 50 milliseconds to prevent abuse.
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
throw new RuntimeException(e);
|
e.printStackTrace();
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
futureResult.cancel(true);
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
executor.shutdown();
|
|
||||||
actor.print(BBC.getPrefix() + "= " + result[0]);
|
executor.shutdownNow();
|
||||||
|
actor.print(BBC.getPrefix() + "= " + result);
|
||||||
} catch (EvaluationException e) {
|
} catch (EvaluationException e) {
|
||||||
actor.printError(String.format(
|
actor.printError(String.format(
|
||||||
"'%s' could not be parsed as a valid expression", input));
|
"'%s' could not be parsed as a valid expression", input));
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.sk89q.worldedit.internal.expression.runtime;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.command.UtilityCommands;
|
||||||
|
import com.sk89q.worldedit.internal.expression.Expression;
|
||||||
|
import com.sk89q.worldedit.internal.expression.parser.ParserException;
|
||||||
|
|
||||||
|
public class For extends Node {
|
||||||
|
RValue init;
|
||||||
|
RValue condition;
|
||||||
|
RValue increment;
|
||||||
|
RValue body;
|
||||||
|
|
||||||
|
public For(int position, RValue init, RValue condition, RValue increment, RValue body) {
|
||||||
|
super(position);
|
||||||
|
this.init = init;
|
||||||
|
this.condition = condition;
|
||||||
|
this.increment = increment;
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() throws EvaluationException {
|
||||||
|
|
||||||
|
int iterations = 0;
|
||||||
|
double ret = 0.0D;
|
||||||
|
this.init.getValue();
|
||||||
|
|
||||||
|
for(; this.condition.getValue() > 0.0D; this.increment.getValue()) {
|
||||||
|
|
||||||
|
if(iterations > 256) {
|
||||||
|
throw new EvaluationException(this.getPosition(), "Loop exceeded 256 iterations.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Thread.currentThread().isInterrupted()){
|
||||||
|
throw new EvaluationException(this.getPosition(), "Thread has been interuppted.");
|
||||||
|
}
|
||||||
|
|
||||||
|
++iterations;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ret = this.body.getValue();
|
||||||
|
} catch (BreakException var5) {
|
||||||
|
if(!var5.doContinue) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char id() {
|
||||||
|
return 'F';
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "for (" + this.init + "; " + this.condition + "; " + this.increment + ") { " + this.body + " }";
|
||||||
|
}
|
||||||
|
|
||||||
|
public RValue optimize() throws EvaluationException {
|
||||||
|
RValue newCondition = this.condition.optimize();
|
||||||
|
return (RValue)(newCondition instanceof Constant && newCondition.getValue() <= 0.0D?(new Sequence(this.getPosition(), new RValue[]{this.init, new Constant(this.getPosition(), 0.0D)})).optimize():new For(this.getPosition(), this.init.optimize(), newCondition, this.increment.optimize(), this.body.optimize()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public RValue bindVariables(Expression expression, boolean preferLValue) throws ParserException {
|
||||||
|
this.init = this.init.bindVariables(expression, false);
|
||||||
|
this.condition = this.condition.bindVariables(expression, false);
|
||||||
|
this.increment = this.increment.bindVariables(expression, false);
|
||||||
|
this.body = this.body.bindVariables(expression, false);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class<For> inject() {
|
||||||
|
return For.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue