diff --git a/src/main/java/at/petrak/hexcasting/HexMod.kt b/src/main/java/at/petrak/hexcasting/HexMod.kt index 3062e576..74e02272 100644 --- a/src/main/java/at/petrak/hexcasting/HexMod.kt +++ b/src/main/java/at/petrak/hexcasting/HexMod.kt @@ -1,5 +1,6 @@ package at.petrak.hexcasting +import at.petrak.hexcasting.api.PatternRegistry import at.petrak.hexcasting.client.* import at.petrak.hexcasting.common.blocks.HexBlocks import at.petrak.hexcasting.common.casting.RegisterPatterns @@ -58,6 +59,7 @@ object HexMod { // gotta do it at *some* point modBus.register(RegisterPatterns::class.java) modBus.register(HexDataGenerators::class.java) + modBus.register(PatternRegistry) HexItems.ITEMS.register(modBus) HexBlocks.BLOCKS.register(modBus) diff --git a/src/main/java/at/petrak/hexcasting/api/PatternRegistry.kt b/src/main/java/at/petrak/hexcasting/api/PatternRegistry.kt index f8373cbf..7b78fac9 100644 --- a/src/main/java/at/petrak/hexcasting/api/PatternRegistry.kt +++ b/src/main/java/at/petrak/hexcasting/api/PatternRegistry.kt @@ -1,5 +1,6 @@ package at.petrak.hexcasting.api +import at.petrak.hexcasting.HexMod import at.petrak.hexcasting.api.spell.Operator import at.petrak.hexcasting.common.casting.mishaps.MishapInvalidPattern import at.petrak.hexcasting.hexmath.EulerPathFinder @@ -9,6 +10,8 @@ import net.minecraft.nbt.CompoundTag import net.minecraft.resources.ResourceLocation import net.minecraft.server.level.ServerLevel import net.minecraft.world.level.saveddata.SavedData +import net.minecraftforge.eventbus.api.SubscribeEvent +import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentLinkedDeque import java.util.concurrent.ConcurrentMap @@ -64,6 +67,11 @@ object PatternRegistry { this.specialHandlers.add(handler) } + @JvmStatic + fun addSpecialHandler(id: ResourceLocation, handler: SpecialHandler) { + this.addSpecialHandler(SpecialHandlerEntry(id, handler)) + } + /** * Internal use only. */ @@ -198,4 +206,13 @@ object PatternRegistry { const val TAG_SAVED_DATA = "hex.per-world-patterns" private const val TAG_OP_ID = "op_id" private const val TAG_START_DIR = "start_dir" + + @SubscribeEvent + fun printPatternCount(evt: FMLLoadCompleteEvent) { + HexMod.getLogger().info( + "Loaded ${this.regularPatternLookup.size} regular patterns, " + + "${this.perWorldPatternLookup.size} per-world patterns, and " + + "${this.specialHandlers.size} special handlers." + ) + } } \ No newline at end of file diff --git a/src/main/java/at/petrak/hexcasting/common/casting/RegisterPatterns.java b/src/main/java/at/petrak/hexcasting/common/casting/RegisterPatterns.java index d03f8f41..5764bf6d 100644 --- a/src/main/java/at/petrak/hexcasting/common/casting/RegisterPatterns.java +++ b/src/main/java/at/petrak/hexcasting/common/casting/RegisterPatterns.java @@ -23,8 +23,10 @@ import at.petrak.hexcasting.common.casting.operators.spells.sentinel.OpDestroySe import at.petrak.hexcasting.common.casting.operators.spells.sentinel.OpGetSentinelPos; import at.petrak.hexcasting.common.casting.operators.spells.sentinel.OpGetSentinelWayfind; import at.petrak.hexcasting.common.items.HexItems; +import at.petrak.hexcasting.hexmath.HexAngle; import at.petrak.hexcasting.hexmath.HexDir; import at.petrak.hexcasting.hexmath.HexPattern; +import it.unimi.dsi.fastutil.booleans.BooleanArrayList; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.phys.Vec3; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -69,7 +71,7 @@ public class RegisterPatterns { // == Modify Stack == - PatternRegistry.mapPattern(HexPattern.FromAnglesSig("a", HexDir.EAST), prefix("undo"), OpUndo.INSTANCE); + // PatternRegistry.mapPattern(HexPattern.FromAnglesSig("a", HexDir.EAST), prefix("undo"), OpUndo.INSTANCE); PatternRegistry.mapPattern(HexPattern.FromAnglesSig("d", HexDir.EAST), prefix("const/null"), Widget.NULL); PatternRegistry.mapPattern(HexPattern.FromAnglesSig("aadaa", HexDir.EAST), prefix("duplicate"), OpDuplicate.INSTANCE); @@ -363,7 +365,7 @@ public class RegisterPatterns { } // Add zilde->number - PatternRegistry.addSpecialHandler(new PatternRegistry.SpecialHandlerEntry(prefix("number"), pat -> { + PatternRegistry.addSpecialHandler(prefix("number"), pat -> { var sig = pat.anglesSignature(); if (sig.startsWith("aqaa") || sig.startsWith("dedd")) { var negate = sig.startsWith("dedd"); @@ -388,6 +390,44 @@ public class RegisterPatterns { } else { return null; } - })); + }); + + // and swizzles + PatternRegistry.addSpecialHandler(prefix("swizzle"), pat -> { + var directions = pat.directions(); + + HexDir flatDir; + if (pat.angles().isEmpty()) { + return null; + } else if (pat.angles().get(0) == HexAngle.LEFT_BACK) { + flatDir = directions.get(0).rotatedBy(HexAngle.LEFT); + } else { + flatDir = pat.startDir(); + } + + var mask = new BooleanArrayList(); + for (int i = 0; i < directions.size(); i++) { + // Angle with respect to the *start direction* + var angle = directions.get(i).angleFrom(flatDir); + if (angle == HexAngle.FORWARD) { + mask.add(true); + continue; + } + if (i >= directions.size() - 1) { + // then we're out of angles! + return null; + } + var angle2 = directions.get(i + 1).angleFrom(flatDir); + if (angle == HexAngle.RIGHT && angle2 == HexAngle.LEFT) { + mask.add(false); + i++; + continue; + } + + return null; + } + + return new OpSwizzle(mask); + }); } } diff --git a/src/main/java/at/petrak/hexcasting/common/casting/operators/OpSwizzle.kt b/src/main/java/at/petrak/hexcasting/common/casting/operators/OpSwizzle.kt new file mode 100644 index 00000000..f98d06d8 --- /dev/null +++ b/src/main/java/at/petrak/hexcasting/common/casting/operators/OpSwizzle.kt @@ -0,0 +1,20 @@ +package at.petrak.hexcasting.common.casting.operators + +import at.petrak.hexcasting.api.spell.ConstManaOperator +import at.petrak.hexcasting.api.spell.SpellDatum +import at.petrak.hexcasting.common.casting.CastingContext +import it.unimi.dsi.fastutil.booleans.BooleanList + +class OpSwizzle(val mask: BooleanList) : ConstManaOperator { + override val argc: Int + get() = mask.size + + override fun execute(args: List>, ctx: CastingContext): List> { + val out = ArrayList>(this.mask.size) + for ((i, include) in this.mask.withIndex()) { + if (include) + out.add(args[i]) + } + return out + } +} \ No newline at end of file diff --git a/src/main/java/at/petrak/hexcasting/hexmath/HexPattern.kt b/src/main/java/at/petrak/hexcasting/hexmath/HexPattern.kt index 0c284574..5b76542e 100644 --- a/src/main/java/at/petrak/hexcasting/hexmath/HexPattern.kt +++ b/src/main/java/at/petrak/hexcasting/hexmath/HexPattern.kt @@ -57,6 +57,18 @@ data class HexPattern(val startDir: HexDir, val angles: MutableList = return out } + fun directions(): List { + val out = ArrayList(this.angles.size + 1) + out.add(this.startDir) + + var compass: HexDir = this.startDir + for (a in this.angles) { + compass *= a + out.add(compass) + } + return out + } + fun finalDir(): HexDir = this.angles.fold(this.startDir) { acc, angle -> acc * angle } diff --git a/src/main/resources/assets/hexcasting/lang/en_us.json b/src/main/resources/assets/hexcasting/lang/en_us.json index e4d298b3..a7fd7a3e 100644 --- a/src/main/resources/assets/hexcasting/lang/en_us.json +++ b/src/main/resources/assets/hexcasting/lang/en_us.json @@ -252,6 +252,7 @@ "hexcasting.spell.hexcasting:const/vec/nz": "Vector Reflection -Z", "hexcasting.spell.hexcasting:const/vec/0": "Vector Reflection Zero", "hexcasting.spell.hexcasting:number": "Numerical Reflection", + "hexcasting.spell.hexcasting:swizzle": "Swindler's Gambit", "hexcasting.spell.unknown": "Special Handler", "hexcasting.mishap.invalid_pattern": "That pattern isn't associated with any action",