Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,49 +24,49 @@ public interface Arithmetic {

// Below are some common Operator patterns that you can make use of in your Arithmetic:

HexPattern ADD = HexPattern.fromAngles("waaw", HexDir.NORTH_EAST);
HexPattern SUB = HexPattern.fromAngles("wddw", HexDir.NORTH_WEST);
HexPattern MUL = HexPattern.fromAngles("waqaw", HexDir.SOUTH_EAST);
HexPattern DIV = HexPattern.fromAngles("wdedw", HexDir.NORTH_EAST);
HexPattern ABS = HexPattern.fromAngles("wqaqw", HexDir.NORTH_EAST);
HexPattern POW = HexPattern.fromAngles("wedew", HexDir.NORTH_WEST);
HexPattern FLOOR = HexPattern.fromAngles("ewq", HexDir.EAST);
HexPattern CEIL = HexPattern.fromAngles("qwe", HexDir.EAST);
HexPattern SIN = HexPattern.fromAngles("qqqqqaa", HexDir.SOUTH_EAST);
HexPattern COS = HexPattern.fromAngles("qqqqqad", HexDir.SOUTH_EAST);
HexPattern TAN = HexPattern.fromAngles("wqqqqqadq", HexDir.SOUTH_WEST);
HexPattern ARCSIN = HexPattern.fromAngles("ddeeeee", HexDir.SOUTH_EAST);
HexPattern ARCCOS = HexPattern.fromAngles("adeeeee", HexDir.NORTH_EAST);
HexPattern ARCTAN = HexPattern.fromAngles("eadeeeeew", HexDir.NORTH_EAST);
HexPattern ARCTAN2 = HexPattern.fromAngles("deadeeeeewd", HexDir.WEST);
HexPattern LOG = HexPattern.fromAngles("eqaqe", HexDir.NORTH_WEST);
HexPattern MOD = HexPattern.fromAngles("addwaad", HexDir.NORTH_EAST);
HexPattern ADD = HexPattern.fromAngleString("waaw", HexDir.NORTH_EAST);
HexPattern SUB = HexPattern.fromAngleString("wddw", HexDir.NORTH_WEST);
HexPattern MUL = HexPattern.fromAngleString("waqaw", HexDir.SOUTH_EAST);
HexPattern DIV = HexPattern.fromAngleString("wdedw", HexDir.NORTH_EAST);
HexPattern ABS = HexPattern.fromAngleString("wqaqw", HexDir.NORTH_EAST);
HexPattern POW = HexPattern.fromAngleString("wedew", HexDir.NORTH_WEST);
HexPattern FLOOR = HexPattern.fromAngleString("ewq", HexDir.EAST);
HexPattern CEIL = HexPattern.fromAngleString("qwe", HexDir.EAST);
HexPattern SIN = HexPattern.fromAngleString("qqqqqaa", HexDir.SOUTH_EAST);
HexPattern COS = HexPattern.fromAngleString("qqqqqad", HexDir.SOUTH_EAST);
HexPattern TAN = HexPattern.fromAngleString("wqqqqqadq", HexDir.SOUTH_WEST);
HexPattern ARCSIN = HexPattern.fromAngleString("ddeeeee", HexDir.SOUTH_EAST);
HexPattern ARCCOS = HexPattern.fromAngleString("adeeeee", HexDir.NORTH_EAST);
HexPattern ARCTAN = HexPattern.fromAngleString("eadeeeeew", HexDir.NORTH_EAST);
HexPattern ARCTAN2 = HexPattern.fromAngleString("deadeeeeewd", HexDir.WEST);
HexPattern LOG = HexPattern.fromAngleString("eqaqe", HexDir.NORTH_WEST);
HexPattern MOD = HexPattern.fromAngleString("addwaad", HexDir.NORTH_EAST);


// Vecs
HexPattern PACK = HexPattern.fromAngles("eqqqqq", HexDir.EAST);
HexPattern UNPACK = HexPattern.fromAngles("qeeeee", HexDir.EAST);
HexPattern PACK = HexPattern.fromAngleString("eqqqqq", HexDir.EAST);
HexPattern UNPACK = HexPattern.fromAngleString("qeeeee", HexDir.EAST);

// Lists
HexPattern INDEX = HexPattern.fromAngles("deeed", HexDir.NORTH_WEST);
HexPattern SLICE = HexPattern.fromAngles("qaeaqwded", HexDir.NORTH_WEST);
HexPattern APPEND = HexPattern.fromAngles("edqde", HexDir.SOUTH_WEST);
HexPattern UNAPPEND = HexPattern.fromAngles("qaeaq", HexDir.NORTH_WEST);
HexPattern REV = HexPattern.fromAngles("qqqaede", HexDir.EAST);
HexPattern INDEX_OF = HexPattern.fromAngles("dedqde", HexDir.EAST);
HexPattern REMOVE = HexPattern.fromAngles("edqdewaqa", HexDir.SOUTH_WEST);
HexPattern REPLACE = HexPattern.fromAngles("wqaeaqw", HexDir.NORTH_WEST);
HexPattern CONS = HexPattern.fromAngles("ddewedd", HexDir.SOUTH_EAST);
HexPattern UNCONS = HexPattern.fromAngles("aaqwqaa", HexDir.SOUTH_WEST);
HexPattern INDEX = HexPattern.fromAngleString("deeed", HexDir.NORTH_WEST);
HexPattern SLICE = HexPattern.fromAngleString("qaeaqwded", HexDir.NORTH_WEST);
HexPattern APPEND = HexPattern.fromAngleString("edqde", HexDir.SOUTH_WEST);
HexPattern UNAPPEND = HexPattern.fromAngleString("qaeaq", HexDir.NORTH_WEST);
HexPattern REV = HexPattern.fromAngleString("qqqaede", HexDir.EAST);
HexPattern INDEX_OF = HexPattern.fromAngleString("dedqde", HexDir.EAST);
HexPattern REMOVE = HexPattern.fromAngleString("edqdewaqa", HexDir.SOUTH_WEST);
HexPattern REPLACE = HexPattern.fromAngleString("wqaeaqw", HexDir.NORTH_WEST);
HexPattern CONS = HexPattern.fromAngleString("ddewedd", HexDir.SOUTH_EAST);
HexPattern UNCONS = HexPattern.fromAngleString("aaqwqaa", HexDir.SOUTH_WEST);

// Boolean Logic, Comparisons, & Sets
HexPattern AND = HexPattern.fromAngles("wdw", HexDir.NORTH_EAST);
HexPattern OR = HexPattern.fromAngles("waw", HexDir.SOUTH_EAST);
HexPattern XOR = HexPattern.fromAngles("dwa", HexDir.NORTH_WEST);
HexPattern GREATER = HexPattern.fromAngles("e", HexDir.SOUTH_EAST);
HexPattern LESS = HexPattern.fromAngles("q", HexDir.SOUTH_WEST);
HexPattern GREATER_EQ = HexPattern.fromAngles("ee", HexDir.SOUTH_EAST);
HexPattern LESS_EQ = HexPattern.fromAngles("qq", HexDir.SOUTH_WEST);
HexPattern NOT = HexPattern.fromAngles("dw", HexDir.NORTH_WEST);
HexPattern UNIQUE = HexPattern.fromAngles("aweaqa", HexDir.NORTH_EAST);
HexPattern AND = HexPattern.fromAngleString("wdw", HexDir.NORTH_EAST);
HexPattern OR = HexPattern.fromAngleString("waw", HexDir.SOUTH_EAST);
HexPattern XOR = HexPattern.fromAngleString("dwa", HexDir.NORTH_WEST);
HexPattern GREATER = HexPattern.fromAngleString("e", HexDir.SOUTH_EAST);
HexPattern LESS = HexPattern.fromAngleString("q", HexDir.SOUTH_WEST);
HexPattern GREATER_EQ = HexPattern.fromAngleString("ee", HexDir.SOUTH_EAST);
HexPattern LESS_EQ = HexPattern.fromAngleString("qq", HexDir.SOUTH_WEST);
HexPattern NOT = HexPattern.fromAngleString("dw", HexDir.NORTH_WEST);
HexPattern UNIQUE = HexPattern.fromAngleString("aweaqa", HexDir.NORTH_EAST);
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) {
OperatorSideEffect.DoMishap(
MishapInternalException(exception),
Mishap.Context(
(iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST),
(iota as? PatternIota)?.pattern,
null
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ protected Iota(@NotNull Supplier<IotaType<? extends Iota>> type) {
List.of(
new OperatorSideEffect.DoMishap(
new MishapUnescapedValue(this),
new Mishap.Context(new HexPattern(HexDir.WEST, List.of()), null)
new Mishap.Context(null, null)
)
),
ResolvedPatternType.INVALID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public boolean isTruthy() {
public boolean toleratesOther(Iota that) {
return typesMatch(this, that)
&& that instanceof PatternIota piota
&& this.getPattern().getAngles().equals(piota.getPattern().getAngles());
&& this.getPattern().getSignature().equals(piota.getPattern().getSignature());
}

@Override
Expand Down Expand Up @@ -224,12 +224,12 @@ public static Component display(HexPattern pat) {
// keep around just in case it's needed.
public static Component displayNonInline(HexPattern pat){
var bob = new StringBuilder();
bob.append(pat.getStartDir());
bob.append(pat.getOrientation());

var sig = pat.anglesSignature();
if (!sig.isEmpty()) {
var sig = pat.getSignature();
if (sig.sizeUpperBound() > 0) {
bob.append(" ");
bob.append(sig);
bob.append(sig.toAnglesString());
}
return Component.translatable("hexcasting.tooltip.pattern_iota",
Component.literal(bob.toString()).withStyle(ChatFormatting.WHITE))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,17 @@ object EulerPathFinder {
out.add(current)

val dirs = out.zipWithNext { a, b -> a.immediateDelta(b)!! }
val angles = dirs.zipWithNext { a, b -> b.angleFrom(a) }
return HexPattern(dirs[0], angles.toMutableList())
val signatureBuilder = HexSignature.Builder(false)
dirs.zipWithNext().forEach { (a, b) -> signatureBuilder.addAngle(b.angleFrom(a)) }
return HexPattern(dirs[0], signatureBuilder.build())
}

private fun toGraph(pat: HexPattern): HashMap<HexCoord, EnumSet<HexDir>> {
val graph = HashMap<HexCoord, EnumSet<HexDir>>()

var compass: HexDir = pat.startDir
var compass: HexDir = pat.orientation
var cursor = HexCoord.Origin
for (a in pat.angles) {
for (a in pat.signature) {
// i hate kotlin
graph.getOrPut(cursor) { EnumSet.noneOf(HexDir::class.java) }.add(compass)
graph.getOrPut(cursor + compass) { EnumSet.noneOf(HexDir::class.java) }.add(compass * HexAngle.BACK)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,24 @@ package at.petrak.hexcasting.api.casting.math
enum class HexAngle {
FORWARD, RIGHT, RIGHT_BACK, BACK, LEFT_BACK, LEFT;

fun rotatedBy(a: HexAngle) = values()[(this.ordinal + a.ordinal) % values().size]
fun rotatedBy(a: HexAngle) = entries[(this.ordinal + a.ordinal) % entries.size]
operator fun times(a: HexAngle) = this.rotatedBy(a)

fun inverse() = entries[(entries.size - this.ordinal) % entries.size]

fun toChar(): Char {
return when (this) {
FORWARD -> 'w'
RIGHT -> 'e'
RIGHT_BACK -> 'd'
BACK -> 's'
LEFT_BACK -> 'a'
LEFT -> 'q'
}
}

companion object {
@JvmStatic
fun fromChar(c: Char): HexAngle? {
return when (c) {
'w' -> FORWARD
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ enum class HexDir {
}

companion object {
@JvmField
val CODEC: Codec<HexDir> = Codec.STRING.xmap(
HexDir::fromString,
HexDir::name
)
@JvmField
val STREAM_CODEC: StreamCodec<ByteBuf, HexDir> = ByteBufCodecs.STRING_UTF8.map(
HexDir::fromString,
HexDir::name
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package at.petrak.hexcasting.api.casting.math;

import at.petrak.hexcasting.api.utils.HexUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.world.phys.Vec2;

/**
* Sequence of angles to define a pattern traced.
*/
public final class HexPattern {
private final HexDir orientation;
private final HexSignature signature;

public HexPattern(HexDir orientation, HexSignature signature) {
this.orientation = orientation;
this.signature = signature;
}

public HexDir getOrientation() {
return orientation;
}

public HexSignature getSignature() {
return signature;
}

public Vec2 getCenter(float hexRadius) {
return this.getCenter(hexRadius, HexCoord.getOrigin());
}

public Vec2 getCenter(float hexRadius, HexCoord origin) {
Vec2 originPx = HexUtils.coordToPx(origin, hexRadius, Vec2.ZERO);
List<Vec2> points = this.toLines(hexRadius, originPx);
return HexUtils.findCenter(points);
}

/**
* Convert a hex pattern into a sequence of straight linePoints spanning its points.
*/
public List<Vec2> toLines(float hexSize, Vec2 origin) {
return this.positions().stream().map(it -> HexUtils.coordToPx(it, hexSize, origin)).toList();
}

public List<HexCoord> positions() {
return this.positions(HexCoord.getOrigin());
}

public List<HexCoord> positions(HexCoord start) {
ArrayList<HexCoord> out = new ArrayList<>(this.signature.sizeUpperBound() + 2);
out.add(start);
HexDir compass = this.orientation;
HexCoord cursor = start;
for (HexAngle a : this.signature) {
cursor = cursor.plus(compass);
out.add(cursor);
compass = compass.times(a);
}
out.add(cursor.plus(compass));
return out;
}

@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
HexPattern that = (HexPattern) o;
return Objects.equals(signature, that.signature) && orientation == that.orientation;
}

@Override
public int hashCode() {
return Objects.hash(signature, orientation);
}

@Override
public String toString() {
return "HexPattern[" +
"orientation=" + orientation +
", signature=" + signature +
']';
}

public String toChatString() {
return "HexPattern[" + orientation + ", " + signature.toAnglesString() + ']';
}

public static final Codec<HexPattern> CODEC = RecordCodecBuilder.create(instance -> instance.group(
HexDir.CODEC.fieldOf("orientation").forGetter(HexPattern::getOrientation),
HexSignature.CODEC.fieldOf("signature").forGetter(HexPattern::getSignature)
).apply(instance, HexPattern::new));

public static final StreamCodec<RegistryFriendlyByteBuf, HexPattern> STREAM_CODEC = StreamCodec.composite(
HexDir.STREAM_CODEC, HexPattern::getOrientation,
HexSignature.STREAM_CODEC, HexPattern::getSignature,
HexPattern::new
);

public static HexPattern fromAngleString(String angleString, HexDir startDir) {
return fromAngleString(angleString, startDir, true);
}

public static HexPattern fromAngleString(String angleString, HexDir startDir, boolean rejectOverlap) {
HexSignature.Builder signature = new HexSignature.Builder(rejectOverlap);

for (int i = 0; i < angleString.length(); i++) {
char c = angleString.charAt(i);

HexAngle angle = HexAngle.fromChar(c);
if(angle == null) throw new IllegalArgumentException("Cannot match %c at idx %d to a direction".formatted(c, i));

signature.addAngle(angle);
}

return new HexPattern(startDir, signature.build());
}
}
Loading
Loading