ArithmeticEngine successfully working!
This commit is contained in:
parent
c276d4c600
commit
6f5c652554
16 changed files with 305 additions and 80 deletions
|
@ -0,0 +1,43 @@
|
||||||
|
package at.petrak.hexcasting.api.casting.arithmetic;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.function.TriFunction;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public class TripleIterable<A,B,C,D> implements Iterable<D> {
|
||||||
|
private final Iterable<A> iterableA;
|
||||||
|
private final Iterable<B> iterableB;
|
||||||
|
private final Iterable<C> iterableC;
|
||||||
|
|
||||||
|
private final TriFunction<A, B, C, D> map;
|
||||||
|
|
||||||
|
public TripleIterable(Iterable<A> iterableA, Iterable<B> iterableB, Iterable<C> iterableC, TriFunction<A, B, C, D> map) {
|
||||||
|
this.iterableA = iterableA;
|
||||||
|
this.iterableB = iterableB;
|
||||||
|
this.iterableC = iterableC;
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Iterator<D> iterator() {
|
||||||
|
return new TripleIterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
class TripleIterator implements Iterator<D> {
|
||||||
|
private final Iterator<A> iteratorA = iterableA.iterator();
|
||||||
|
private final Iterator<B> iteratorB = iterableB.iterator();
|
||||||
|
private final Iterator<C> iteratorC = iterableC.iterator();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return iteratorA.hasNext() && iteratorB.hasNext() && iteratorC.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public D next() {
|
||||||
|
return map.apply(iteratorA.next(), iteratorB.next(), iteratorC.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,8 +2,17 @@ package at.petrak.hexcasting.api.casting.arithmetic.engine;
|
||||||
|
|
||||||
import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic;
|
import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic;
|
||||||
import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator;
|
import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator;
|
||||||
|
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment;
|
||||||
|
import at.petrak.hexcasting.api.casting.eval.OperationResult;
|
||||||
|
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage;
|
||||||
|
import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation;
|
||||||
import at.petrak.hexcasting.api.casting.iota.Iota;
|
import at.petrak.hexcasting.api.casting.iota.Iota;
|
||||||
import at.petrak.hexcasting.api.casting.math.HexPattern;
|
import at.petrak.hexcasting.api.casting.math.HexPattern;
|
||||||
|
import at.petrak.hexcasting.api.casting.mishaps.Mishap;
|
||||||
|
import at.petrak.hexcasting.api.casting.mishaps.MishapInvalidOperatorArgs;
|
||||||
|
import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs;
|
||||||
|
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -42,15 +51,33 @@ public class ArithmeticEngine {
|
||||||
return operators.keySet();
|
return operators.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable Iota run(HexPattern operator, Stack<Iota> iotas) {
|
@Nullable
|
||||||
|
public OperationResult operate(@NotNull HexPattern operator, @NotNull CastingEnvironment env, @NotNull CastingImage image, @NotNull SpellContinuation continuation) throws Mishap {
|
||||||
|
var stackList = image.getStack();
|
||||||
|
var stack = new Stack<Iota>();
|
||||||
|
stack.addAll(stackList);
|
||||||
|
var startingLength = stackList.size();
|
||||||
|
try {
|
||||||
|
var ret = run(operator, stack, startingLength);
|
||||||
|
ret.forEach(stack::add);
|
||||||
|
var image2 = image.copy(stack, image.getParenCount(), image.getParenthesized(), image.getEscapeNext(), image.getOpsConsumed() + 1, image.getUserData());
|
||||||
|
return new OperationResult(image2, List.of(), continuation, HexEvalSounds.NORMAL_EXECUTE);
|
||||||
|
} catch (InvalidOperatorException e) {
|
||||||
|
return null;
|
||||||
|
} catch (NoOperatorCandidatesException e) {
|
||||||
|
throw new MishapInvalidOperatorArgs(e.args, e.pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterable<Iota> run(HexPattern operator, Stack<Iota> iotas, int startingLength) throws Mishap {
|
||||||
var candidates = operators.get(operator);
|
var candidates = operators.get(operator);
|
||||||
if (candidates == null)
|
if (candidates == null)
|
||||||
return null; // not an operator
|
throw new InvalidOperatorException("the pattern " + operator + " is not an operator."); //
|
||||||
HashCons hash = new HashCons.Pattern(operator);
|
HashCons hash = new HashCons.Pattern(operator);
|
||||||
var args = new ArrayList<Iota>(candidates.arity());
|
var args = new ArrayList<Iota>(candidates.arity());
|
||||||
for (var i = 0; i < candidates.arity(); i++) {
|
for (var i = 0; i < candidates.arity(); i++) {
|
||||||
if (iotas.isEmpty()) {
|
if (iotas.isEmpty()) {
|
||||||
throw new IllegalStateException("Not enough args on stack for operator: " + operator);
|
throw new MishapNotEnoughArgs(candidates.arity, startingLength);
|
||||||
}
|
}
|
||||||
var iota = iotas.pop();
|
var iota = iotas.pop();
|
||||||
hash = new HashCons.Pair(iota.getType(), hash);
|
hash = new HashCons.Pair(iota.getType(), hash);
|
||||||
|
@ -68,7 +95,7 @@ public class ArithmeticEngine {
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("No implementation candidates for op " + candidates.pattern() + " on args: " + args);
|
throw new NoOperatorCandidatesException(candidates.pattern(), args, "No implementation candidates for op " + candidates.pattern() + " on args: " + args);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package at.petrak.hexcasting.api.casting.arithmetic.engine;
|
||||||
|
|
||||||
|
public class InvalidOperatorException extends RuntimeException {
|
||||||
|
public InvalidOperatorException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvalidOperatorException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvalidOperatorException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvalidOperatorException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package at.petrak.hexcasting.api.casting.arithmetic.engine;
|
||||||
|
|
||||||
|
import at.petrak.hexcasting.api.casting.iota.Iota;
|
||||||
|
import at.petrak.hexcasting.api.casting.math.HexPattern;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class NoOperatorCandidatesException extends RuntimeException {
|
||||||
|
HexPattern pattern;
|
||||||
|
List<Iota> args;
|
||||||
|
|
||||||
|
public NoOperatorCandidatesException(HexPattern pattern, List<Iota> args) {
|
||||||
|
this.pattern = pattern;
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NoOperatorCandidatesException(HexPattern pattern, List<Iota> args, String s) {
|
||||||
|
super(s);
|
||||||
|
this.pattern = pattern;
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,16 +7,14 @@ import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator;
|
||||||
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBinary;
|
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBinary;
|
||||||
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorUnary;
|
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorUnary;
|
||||||
import at.petrak.hexcasting.api.casting.iota.DoubleIota;
|
import at.petrak.hexcasting.api.casting.iota.DoubleIota;
|
||||||
import at.petrak.hexcasting.api.casting.iota.Iota;
|
|
||||||
import at.petrak.hexcasting.api.casting.math.HexPattern;
|
import at.petrak.hexcasting.api.casting.math.HexPattern;
|
||||||
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.DoubleBinaryOperator;
|
import java.util.function.DoubleBinaryOperator;
|
||||||
import java.util.function.DoubleUnaryOperator;
|
import java.util.function.DoubleUnaryOperator;
|
||||||
|
|
||||||
import static at.petrak.hexcasting.api.casting.arithmetic.operator.Operator.downcast;
|
import static at.petrak.hexcasting.api.casting.arithmetic.operator.Operator.downcast;
|
||||||
import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.*;
|
import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.DOUBLE;
|
||||||
|
|
||||||
public enum DoubleArithmetic implements Arithmetic {
|
public enum DoubleArithmetic implements Arithmetic {
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
@ -47,16 +45,24 @@ public enum DoubleArithmetic implements Arithmetic {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Operator getOperator(HexPattern pattern) {
|
public Operator getOperator(HexPattern pattern) {
|
||||||
switch (pattern) {
|
if (pattern.equals(ADD)) {
|
||||||
case ADD: return make2(Double::sum);
|
return make2(Double::sum);
|
||||||
case SUB: return make2((p, q) -> p - q);
|
} else if (pattern.equals(SUB)) {
|
||||||
case MUL: return make2((p, q) -> p * q);
|
return make2((p, q) -> p - q);
|
||||||
case DIV: return make2((p, q) -> p / q);
|
} else if (pattern.equals(MUL)) {
|
||||||
case ABS: return make1(Math::abs);
|
return make2((p, q) -> p * q);
|
||||||
case POW: return make2(Math::pow);
|
} else if (pattern.equals(DIV)) {
|
||||||
case FLOOR: return make1(Math::floor);
|
return make2((p, q) -> p / q);
|
||||||
case CEIL: return make1(Math::ceil);
|
} else if (pattern.equals(ABS)) {
|
||||||
case MOD: return make2((p, q) -> p % q);
|
return make1(Math::abs);
|
||||||
|
} else if (pattern.equals(POW)) {
|
||||||
|
return make2(Math::pow);
|
||||||
|
} else if (pattern.equals(FLOOR)) {
|
||||||
|
return make1(Math::floor);
|
||||||
|
} else if (pattern.equals(CEIL)) {
|
||||||
|
return make1(Math::ceil);
|
||||||
|
} else if (pattern.equals(MOD)) {
|
||||||
|
return make2((p, q) -> p % q);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,18 @@ package at.petrak.hexcasting.api.casting.arithmetic.impls;
|
||||||
import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic;
|
import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic;
|
||||||
import at.petrak.hexcasting.api.casting.arithmetic.IotaMultiPredicate;
|
import at.petrak.hexcasting.api.casting.arithmetic.IotaMultiPredicate;
|
||||||
import at.petrak.hexcasting.api.casting.arithmetic.IotaPredicate;
|
import at.petrak.hexcasting.api.casting.arithmetic.IotaPredicate;
|
||||||
|
import at.petrak.hexcasting.api.casting.arithmetic.operator.*;
|
||||||
|
import at.petrak.hexcasting.api.casting.iota.DoubleIota;
|
||||||
|
import at.petrak.hexcasting.api.casting.iota.Vec3Iota;
|
||||||
import at.petrak.hexcasting.api.casting.math.HexPattern;
|
import at.petrak.hexcasting.api.casting.math.HexPattern;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static at.petrak.hexcasting.api.casting.arithmetic.operator.Operator.downcast;
|
||||||
import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.*;
|
import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.*;
|
||||||
|
|
||||||
public enum Vec3Arithmetic implements Arithmetic {
|
public enum Vec3Arithmetic implements Arithmetic {
|
||||||
|
@ -31,28 +38,43 @@ public enum Vec3Arithmetic implements Arithmetic {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<Symbol> opTypes() {
|
public Iterable<HexPattern> opTypes() {
|
||||||
return OPS;
|
return OPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Operator getOperator(Symbol name) {
|
public Operator getOperator(HexPattern pattern) {
|
||||||
switch (name.inner()) {
|
if (pattern.equals(PACK)) {
|
||||||
case "pack": return OperatorPack.INSTANCE;
|
return OperatorPack.INSTANCE;
|
||||||
case "add": return make2(name, null);
|
} else if (pattern.equals(UNPACK)) {
|
||||||
case "sub": return make2(name, null);
|
return OperatorUnpack.INSTANCE;
|
||||||
case "mul": return make2(name, Vec3::dot);
|
} else if (pattern.equals(ADD)) {
|
||||||
case "div": return make2(name, Vec3::cross);
|
return make2Fallback(pattern);
|
||||||
case "abs": return make1(Vec3::len);
|
} else if (pattern.equals(SUB)) {
|
||||||
case "pow": return make2(name, Vec3::proj);
|
return make2Fallback(pattern);
|
||||||
case "mod": return make2(name, null);
|
} else if (pattern.equals(MUL)) {
|
||||||
|
return make2Double(pattern, Vec3::dot);
|
||||||
|
} else if (pattern.equals(DIV)) {
|
||||||
|
return make2Vec(pattern, Vec3::cross);
|
||||||
|
} else if (pattern.equals(ABS)) {
|
||||||
|
return make1Double(Vec3::length);
|
||||||
|
} else if (pattern.equals(POW)) {
|
||||||
|
return make2Vec(pattern, (u, v) -> v.normalize().scale(u.dot(v.normalize())));
|
||||||
|
} else if (pattern.equals(MOD)) {
|
||||||
|
return make2Fallback(pattern);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public static OperatorUnary make1(Function<Vec3, Object> op) {
|
public static OperatorUnary make1Double(Function<Vec3, Double> op) {
|
||||||
return new OperatorUnary(ACCEPTS, i -> new Iota(op.apply(i.downcast(Vec3.class))));
|
return new OperatorUnary(ACCEPTS, i -> new DoubleIota(op.apply(downcast(i, VEC3).getVec3())));
|
||||||
}
|
}
|
||||||
public static OperatorVec3Delegating make2(Symbol name, BiFunction<Vec3, Vec3, Object> op) {
|
public static OperatorVec3Delegating make2Fallback(HexPattern pattern) {
|
||||||
return new OperatorVec3Delegating(op, name);
|
return new OperatorVec3Delegating(null, pattern);
|
||||||
|
}
|
||||||
|
public static OperatorVec3Delegating make2Double(HexPattern pattern, BiFunction<Vec3, Vec3, Double> op) {
|
||||||
|
return new OperatorVec3Delegating(op.andThen(DoubleIota::new), pattern);
|
||||||
|
}
|
||||||
|
public static OperatorVec3Delegating make2Vec(HexPattern pattern, BiFunction<Vec3, Vec3, Vec3> op) {
|
||||||
|
return new OperatorVec3Delegating(op.andThen(Vec3Iota::new), pattern);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package at.petrak.hexcasting.api.casting.arithmetic.operator;
|
||||||
import at.petrak.hexcasting.api.casting.arithmetic.IotaMultiPredicate;
|
import at.petrak.hexcasting.api.casting.arithmetic.IotaMultiPredicate;
|
||||||
import at.petrak.hexcasting.api.casting.iota.Iota;
|
import at.petrak.hexcasting.api.casting.iota.Iota;
|
||||||
import at.petrak.hexcasting.api.casting.iota.IotaType;
|
import at.petrak.hexcasting.api.casting.iota.IotaType;
|
||||||
import at.petrak.hexcasting.api.casting.mishaps.MishapInvalidIota;
|
|
||||||
|
|
||||||
public abstract class Operator {
|
public abstract class Operator {
|
||||||
public final int arity;
|
public final int arity;
|
||||||
|
@ -15,7 +14,7 @@ public abstract class Operator {
|
||||||
this.accepts = accepts;
|
this.accepts = accepts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Iota apply(Iterable<Iota> iotas);
|
public abstract Iterable<Iota> apply(Iterable<Iota> iotas);
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T extends Iota> T downcast(Iota iota, IotaType<T> iotaType) {
|
public static <T extends Iota> T downcast(Iota iota, IotaType<T> iotaType) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ package at.petrak.hexcasting.api.casting.arithmetic.operator;
|
||||||
import at.petrak.hexcasting.api.casting.arithmetic.IotaMultiPredicate;
|
import at.petrak.hexcasting.api.casting.arithmetic.IotaMultiPredicate;
|
||||||
import at.petrak.hexcasting.api.casting.iota.Iota;
|
import at.petrak.hexcasting.api.casting.iota.Iota;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.BinaryOperator;
|
import java.util.function.BinaryOperator;
|
||||||
|
|
||||||
public class OperatorBinary extends Operator {
|
public class OperatorBinary extends Operator {
|
||||||
|
@ -15,8 +16,8 @@ public class OperatorBinary extends Operator {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iota apply(Iterable<Iota> iotas) {
|
public Iterable<Iota> apply(Iterable<Iota> iotas) {
|
||||||
var it = iotas.iterator();
|
var it = iotas.iterator();
|
||||||
return inner.apply(it.next(), it.next());
|
return List.of(inner.apply(it.next(), it.next()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ import at.petrak.hexcasting.api.casting.iota.Vec3Iota;
|
||||||
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
|
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class OperatorPack extends Operator {
|
public class OperatorPack extends Operator {
|
||||||
private OperatorPack() {
|
private OperatorPack() {
|
||||||
super(3, IotaMultiPredicate.all(IotaPredicate.ofType(HexIotaTypes.DOUBLE)));
|
super(3, IotaMultiPredicate.all(IotaPredicate.ofType(HexIotaTypes.DOUBLE)));
|
||||||
|
@ -16,12 +18,12 @@ public class OperatorPack extends Operator {
|
||||||
public static OperatorPack INSTANCE = new OperatorPack();
|
public static OperatorPack INSTANCE = new OperatorPack();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iota apply(Iterable<Iota> iotas) {
|
public Iterable<Iota> apply(Iterable<Iota> iotas) {
|
||||||
var it = iotas.iterator();
|
var it = iotas.iterator();
|
||||||
return new Vec3Iota(new Vec3(
|
return List.of(new Vec3Iota(new Vec3(
|
||||||
downcast(it.next(), HexIotaTypes.DOUBLE).getDouble(),
|
downcast(it.next(), HexIotaTypes.DOUBLE).getDouble(),
|
||||||
downcast(it.next(), HexIotaTypes.DOUBLE).getDouble(),
|
downcast(it.next(), HexIotaTypes.DOUBLE).getDouble(),
|
||||||
downcast(it.next(), HexIotaTypes.DOUBLE).getDouble()
|
downcast(it.next(), HexIotaTypes.DOUBLE).getDouble()
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ package at.petrak.hexcasting.api.casting.arithmetic.operator;
|
||||||
import at.petrak.hexcasting.api.casting.arithmetic.IotaMultiPredicate;
|
import at.petrak.hexcasting.api.casting.arithmetic.IotaMultiPredicate;
|
||||||
import at.petrak.hexcasting.api.casting.iota.Iota;
|
import at.petrak.hexcasting.api.casting.iota.Iota;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
public class OperatorUnary extends Operator {
|
public class OperatorUnary extends Operator {
|
||||||
|
@ -15,7 +16,7 @@ public class OperatorUnary extends Operator {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iota apply(Iterable<Iota> iotas) {
|
public Iterable<Iota> apply(Iterable<Iota> iotas) {
|
||||||
return inner.apply(iotas.iterator().next());
|
return List.of(inner.apply(iotas.iterator().next()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package at.petrak.hexcasting.api.casting.arithmetic.operator;
|
||||||
|
|
||||||
|
|
||||||
|
import at.petrak.hexcasting.api.casting.arithmetic.IotaMultiPredicate;
|
||||||
|
import at.petrak.hexcasting.api.casting.arithmetic.IotaPredicate;
|
||||||
|
import at.petrak.hexcasting.api.casting.iota.DoubleIota;
|
||||||
|
import at.petrak.hexcasting.api.casting.iota.Iota;
|
||||||
|
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.VEC3;
|
||||||
|
|
||||||
|
public class OperatorUnpack extends Operator {
|
||||||
|
private OperatorUnpack() {
|
||||||
|
super(1, IotaMultiPredicate.all(IotaPredicate.ofType(HexIotaTypes.DOUBLE)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OperatorUnpack INSTANCE = new OperatorUnpack();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<Iota> apply(Iterable<Iota> iotas) {
|
||||||
|
var it = iotas.iterator();
|
||||||
|
var vec = downcast(it.next(), VEC3).getVec3();
|
||||||
|
return List.of(new DoubleIota(vec.x), new DoubleIota(vec.y), new DoubleIota(vec.z));
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,42 +3,46 @@ package at.petrak.hexcasting.api.casting.arithmetic.operator;
|
||||||
import at.petrak.hexcasting.api.casting.arithmetic.IotaMultiPredicate;
|
import at.petrak.hexcasting.api.casting.arithmetic.IotaMultiPredicate;
|
||||||
import at.petrak.hexcasting.api.casting.arithmetic.IotaPredicate;
|
import at.petrak.hexcasting.api.casting.arithmetic.IotaPredicate;
|
||||||
import at.petrak.hexcasting.api.casting.arithmetic.IterPair;
|
import at.petrak.hexcasting.api.casting.arithmetic.IterPair;
|
||||||
|
import at.petrak.hexcasting.api.casting.arithmetic.TripleIterable;
|
||||||
import at.petrak.hexcasting.api.casting.arithmetic.impls.DoubleArithmetic;
|
import at.petrak.hexcasting.api.casting.arithmetic.impls.DoubleArithmetic;
|
||||||
import at.petrak.hexcasting.api.casting.iota.DoubleIota;
|
import at.petrak.hexcasting.api.casting.iota.DoubleIota;
|
||||||
import at.petrak.hexcasting.api.casting.iota.Iota;
|
import at.petrak.hexcasting.api.casting.iota.Iota;
|
||||||
import at.petrak.hexcasting.api.casting.iota.Vec3Iota;
|
import at.petrak.hexcasting.api.casting.iota.Vec3Iota;
|
||||||
import at.petrak.hexcasting.api.casting.math.HexPattern;
|
import at.petrak.hexcasting.api.casting.math.HexPattern;
|
||||||
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
|
|
||||||
import kotlin.Pair;
|
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.DOUBLE;
|
||||||
|
import static at.petrak.hexcasting.common.lib.hex.HexIotaTypes.VEC3;
|
||||||
|
|
||||||
public class OperatorVec3Delegating extends Operator {
|
public class OperatorVec3Delegating extends Operator {
|
||||||
private final BiFunction<Vec3, Vec3, Iota> op;
|
private final BiFunction<Vec3, Vec3, Iota> op;
|
||||||
private final Operator fb;
|
private final Operator fb;
|
||||||
public OperatorVec3Delegating(BiFunction<Vec3, Vec3, Iota> core, HexPattern fallback) {
|
public OperatorVec3Delegating(BiFunction<Vec3, Vec3, Iota> core, HexPattern fallback) {
|
||||||
super(2, IotaMultiPredicate.any(IotaPredicate.ofType(HexIotaTypes.VEC3), IotaPredicate.ofType(HexIotaTypes.DOUBLE)));
|
super(2, IotaMultiPredicate.any(IotaPredicate.ofType(VEC3), IotaPredicate.ofType(DOUBLE)));
|
||||||
op = core;
|
op = core;
|
||||||
fb = Objects.requireNonNull(DoubleArithmetic.INSTANCE.getOperator(fallback));
|
fb = Objects.requireNonNull(DoubleArithmetic.INSTANCE.getOperator(fallback));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iota apply(Iterable<Iota> iotas) {
|
public Iterable<Iota> apply(Iterable<Iota> iotas) {
|
||||||
var it = iotas.iterator();
|
var it = iotas.iterator();
|
||||||
var left = it.next();
|
var left = it.next();
|
||||||
var right = it.next();
|
var right = it.next();
|
||||||
if (op != null && left instanceof Vec3Iota lh && right instanceof Vec3Iota rh) {
|
if (op != null && left instanceof Vec3Iota lh && right instanceof Vec3Iota rh) {
|
||||||
return op.apply(lh.getVec3(), rh.getVec3());
|
return List.of(op.apply(lh.getVec3(), rh.getVec3()));
|
||||||
}
|
}
|
||||||
var lh = left instanceof Vec3Iota l ? l.getVec3() : triplicate(downcast(left, HexIotaTypes.DOUBLE).getDouble());
|
var lh = left instanceof Vec3Iota l ? l.getVec3() : triplicate(downcast(left, DOUBLE).getDouble());
|
||||||
var rh = right instanceof Vec3Iota r ? r.getVec3() : triplicate(downcast(right, HexIotaTypes.DOUBLE).getDouble());
|
var rh = right instanceof Vec3Iota r ? r.getVec3() : triplicate(downcast(right, DOUBLE).getDouble());
|
||||||
return new Vec3Iota(new Vec3(
|
return new TripleIterable<>(
|
||||||
downcast(fb.apply(new IterPair<>(new DoubleIota(lh.x()), new DoubleIota(rh.x()))), HexIotaTypes.DOUBLE).getDouble(),
|
fb.apply(new IterPair<>(new DoubleIota(lh.x()), new DoubleIota(rh.x()))),
|
||||||
downcast(fb.apply(new IterPair<>(new DoubleIota(lh.y()), new DoubleIota(rh.y()))), HexIotaTypes.DOUBLE).getDouble(),
|
fb.apply(new IterPair<>(new DoubleIota(lh.y()), new DoubleIota(rh.y()))),
|
||||||
downcast(fb.apply(new IterPair<>(new DoubleIota(lh.z()), new DoubleIota(rh.z()))), HexIotaTypes.DOUBLE).getDouble()
|
fb.apply(new IterPair<>(new DoubleIota(lh.z()), new DoubleIota(rh.z()))),
|
||||||
));
|
(x, y, z) -> new Vec3Iota(new Vec3(downcast(x, DOUBLE).getDouble(), downcast(y, DOUBLE).getDouble(), downcast(y, DOUBLE).getDouble()))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vec3 triplicate(double in) {
|
public static Vec3 triplicate(double in) {
|
||||||
|
|
|
@ -97,4 +97,9 @@ public abstract class Iota {
|
||||||
public static boolean tolerates(Iota a, Iota b) {
|
public static boolean tolerates(Iota a, Iota b) {
|
||||||
return a.toleratesOther(b) || b.toleratesOther(a);
|
return a.toleratesOther(b) || b.toleratesOther(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return payload.hashCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import at.petrak.hexcasting.api.mod.HexConfig;
|
||||||
import at.petrak.hexcasting.api.mod.HexTags;
|
import at.petrak.hexcasting.api.mod.HexTags;
|
||||||
import at.petrak.hexcasting.api.utils.HexUtils;
|
import at.petrak.hexcasting.api.utils.HexUtils;
|
||||||
import at.petrak.hexcasting.common.casting.PatternRegistryManifest;
|
import at.petrak.hexcasting.common.casting.PatternRegistryManifest;
|
||||||
|
import at.petrak.hexcasting.common.lib.hex.HexArithmetics;
|
||||||
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds;
|
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds;
|
||||||
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
|
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
|
||||||
import at.petrak.hexcasting.xplat.IXplatAbstractions;
|
import at.petrak.hexcasting.xplat.IXplatAbstractions;
|
||||||
|
@ -68,38 +69,43 @@ public class PatternIota extends Iota {
|
||||||
public @NotNull CastResult execute(CastingVM vm, ServerLevel world, SpellContinuation continuation) {
|
public @NotNull CastResult execute(CastingVM vm, ServerLevel world, SpellContinuation continuation) {
|
||||||
@Nullable Component castedName = null;
|
@Nullable Component castedName = null;
|
||||||
try {
|
try {
|
||||||
var lookup = PatternRegistryManifest.matchPattern(this.getPattern(), world, false);
|
var result = HexArithmetics.ENGINE.operate(this.getPattern(), vm.getEnv(), vm.getImage(), continuation);
|
||||||
vm.getEnv().precheckAction(lookup);
|
|
||||||
|
|
||||||
Action action;
|
if (result == null) {
|
||||||
if (lookup instanceof PatternShapeMatch.Normal || lookup instanceof PatternShapeMatch.PerWorld) {
|
var lookup = PatternRegistryManifest.matchPattern(this.getPattern(), world, false);
|
||||||
ResourceKey<ActionRegistryEntry> key;
|
vm.getEnv().precheckAction(lookup);
|
||||||
if (lookup instanceof PatternShapeMatch.Normal normal) {
|
|
||||||
key = normal.key;
|
|
||||||
} else {
|
|
||||||
PatternShapeMatch.PerWorld perWorld = (PatternShapeMatch.PerWorld) lookup;
|
|
||||||
key = perWorld.key;
|
|
||||||
}
|
|
||||||
|
|
||||||
var reqsEnlightenment = isOfTag(IXplatAbstractions.INSTANCE.getActionRegistry(), key,
|
Action action;
|
||||||
HexTags.Actions.REQUIRES_ENLIGHTENMENT);
|
if (lookup instanceof PatternShapeMatch.Normal || lookup instanceof PatternShapeMatch.PerWorld) {
|
||||||
|
ResourceKey<ActionRegistryEntry> key;
|
||||||
|
if (lookup instanceof PatternShapeMatch.Normal normal) {
|
||||||
|
key = normal.key;
|
||||||
|
} else {
|
||||||
|
PatternShapeMatch.PerWorld perWorld = (PatternShapeMatch.PerWorld) lookup;
|
||||||
|
key = perWorld.key;
|
||||||
|
}
|
||||||
|
|
||||||
castedName = HexAPI.instance().getActionI18n(key, reqsEnlightenment);
|
var reqsEnlightenment = isOfTag(IXplatAbstractions.INSTANCE.getActionRegistry(), key,
|
||||||
|
HexTags.Actions.REQUIRES_ENLIGHTENMENT);
|
||||||
|
|
||||||
action = Objects.requireNonNull(IXplatAbstractions.INSTANCE.getActionRegistry().get(key)).action();
|
castedName = HexAPI.instance().getActionI18n(key, reqsEnlightenment);
|
||||||
} else if (lookup instanceof PatternShapeMatch.Special special) {
|
|
||||||
castedName = special.handler.getName();
|
action = Objects.requireNonNull(IXplatAbstractions.INSTANCE.getActionRegistry().get(key)).action();
|
||||||
action = special.handler.act();
|
} else if (lookup instanceof PatternShapeMatch.Special special) {
|
||||||
} else if (lookup instanceof PatternShapeMatch.Nothing) {
|
castedName = special.handler.getName();
|
||||||
throw new MishapInvalidPattern();
|
action = special.handler.act();
|
||||||
} else throw new IllegalStateException();
|
} else if (lookup instanceof PatternShapeMatch.Nothing) {
|
||||||
|
throw new MishapInvalidPattern();
|
||||||
|
} else throw new IllegalStateException();
|
||||||
|
|
||||||
|
// do the actual calculation!!
|
||||||
|
result = action.operate(
|
||||||
|
vm.getEnv(),
|
||||||
|
vm.getImage(),
|
||||||
|
continuation
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// do the actual calculation!!
|
|
||||||
var result = action.operate(
|
|
||||||
vm.getEnv(),
|
|
||||||
vm.getImage(),
|
|
||||||
continuation
|
|
||||||
);
|
|
||||||
if (result.getNewImage().getOpsConsumed() > HexConfig.server().maxOpCount()) {
|
if (result.getNewImage().getOpsConsumed() > HexConfig.server().maxOpCount()) {
|
||||||
throw new MishapEvalTooMuch();
|
throw new MishapEvalTooMuch();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package at.petrak.hexcasting.api.casting.mishaps
|
||||||
|
|
||||||
|
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
|
||||||
|
import at.petrak.hexcasting.api.casting.iota.GarbageIota
|
||||||
|
import at.petrak.hexcasting.api.casting.iota.Iota
|
||||||
|
import at.petrak.hexcasting.api.casting.math.HexPattern
|
||||||
|
import at.petrak.hexcasting.api.pigment.FrozenPigment
|
||||||
|
import net.minecraft.network.chat.ComponentContents
|
||||||
|
import net.minecraft.network.chat.MutableComponent
|
||||||
|
import net.minecraft.world.item.DyeColor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value failed some kind of predicate.
|
||||||
|
*/
|
||||||
|
class MishapInvalidOperatorArgs(
|
||||||
|
val perpetrators: List<Iota>,
|
||||||
|
val operator: HexPattern
|
||||||
|
) : Mishap() {
|
||||||
|
override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment =
|
||||||
|
dyeColor(DyeColor.GRAY)
|
||||||
|
|
||||||
|
override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) {
|
||||||
|
for (i in perpetrators.indices) {
|
||||||
|
stack[stack.size - 1 - i] = GarbageIota()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) =
|
||||||
|
error(
|
||||||
|
"invalid_operator_args", operator, perpetrators.fold(MutableComponent.create(ComponentContents.EMPTY)) { mc, iota -> mc.append(iota.display()) }
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package at.petrak.hexcasting.common.lib.hex;
|
||||||
|
|
||||||
|
import at.petrak.hexcasting.api.casting.arithmetic.engine.ArithmeticEngine;
|
||||||
|
import at.petrak.hexcasting.api.casting.arithmetic.impls.DoubleArithmetic;
|
||||||
|
import at.petrak.hexcasting.api.casting.arithmetic.impls.Vec3Arithmetic;
|
||||||
|
|
||||||
|
public class HexArithmetics {
|
||||||
|
public static ArithmeticEngine ENGINE = new ArithmeticEngine(DoubleArithmetic.INSTANCE, Vec3Arithmetic.INSTANCE);
|
||||||
|
}
|
Loading…
Reference in a new issue