From 674ebfd4711d788e4e2771aaad6d9331f4be0900 Mon Sep 17 00:00:00 2001 From: Aly Date: Mon, 27 Apr 2026 20:59:06 -0600 Subject: [PATCH 1/8] replace potentially mutable list with treelist in stack ops --- .../arithmetic/operator/OperatorBasic.kt | 10 ++++----- .../api/casting/castables/ConstMediaAction.kt | 10 ++++----- .../api/casting/castables/SpellAction.kt | 8 +++---- .../eval/sideeffects/OperatorSideEffect.kt | 2 +- .../api/casting/eval/vm/CastingImage.kt | 21 +++++++++---------- .../api/casting/eval/vm/CastingVM.kt | 6 ++---- .../api/casting/eval/vm/ContinuationFrame.kt | 2 +- .../api/casting/eval/vm/FrameEvaluate.kt | 2 +- .../api/casting/eval/vm/FrameFinishEval.kt | 3 ++- .../api/casting/eval/vm/FrameForEach.kt | 18 +++++++--------- .../hexcasting/api/casting/mishaps/Mishap.kt | 8 ++----- .../mishaps/MishapAlreadyBrainswept.kt | 4 +++- .../api/casting/mishaps/MishapBadBlock.kt | 4 +++- .../casting/mishaps/MishapBadBrainsweep.kt | 4 +++- .../api/casting/mishaps/MishapBadCaster.kt | 4 +++- .../api/casting/mishaps/MishapBadEntity.kt | 4 +++- .../api/casting/mishaps/MishapBadItem.kt | 4 +++- .../api/casting/mishaps/MishapBadLocation.kt | 4 +++- .../casting/mishaps/MishapBadOffhandItem.kt | 4 +++- .../casting/mishaps/MishapDisallowedSpell.kt | 4 +++- .../api/casting/mishaps/MishapDivideByZero.kt | 5 +++-- .../casting/mishaps/MishapEntityNotFound.kt | 4 +++- .../casting/mishaps/MishapEntityTooFarAway.kt | 5 +++-- .../api/casting/mishaps/MishapEvalTooMuch.kt | 4 +++- .../api/casting/mishaps/MishapImmuneEntity.kt | 4 +++- .../mishaps/MishapInternalException.kt | 4 +++- .../api/casting/mishaps/MishapInvalidIota.kt | 5 +++-- .../mishaps/MishapInvalidOperatorArgs.kt | 7 +++++-- .../casting/mishaps/MishapInvalidPattern.kt | 5 +++-- .../mishaps/MishapInvalidSpellDatumType.kt | 4 +++- .../mishaps/MishapLackingHotbarItem.kt | 4 +++- .../mishaps/MishapLocationInWrongDimension.kt | 5 +++-- .../api/casting/mishaps/MishapNeedsParens.kt | 8 ++++--- .../casting/mishaps/MishapNoAkashicRecord.kt | 4 +++- .../casting/mishaps/MishapNotEnoughArgs.kt | 5 +++-- .../casting/mishaps/MishapNotEnoughMedia.kt | 4 +++- .../api/casting/mishaps/MishapOthersName.kt | 4 +++- .../api/casting/mishaps/MishapStackSize.kt | 6 +++--- .../casting/mishaps/MishapUnenlightened.kt | 4 +++- .../casting/mishaps/MishapUnescapedValue.kt | 4 +++- .../circle/MishapBoolDirectrixEmptyStack.kt | 4 +++- .../circle/MishapBoolDirectrixNotBool.kt | 4 +++- .../mishaps/circle/MishapNoSpellCircle.kt | 4 +++- .../petrak/hexcasting/api/utils/HexUtils.kt | 2 +- .../directrix/BlockBooleanDirectrix.java | 7 ++++--- .../casting/actions/escaping/OpCloseParen.kt | 9 ++++---- .../casting/actions/escaping/OpOpenParen.kt | 3 +-- .../common/casting/actions/escaping/OpUndo.kt | 7 +++++-- .../common/casting/actions/eval/OpEval.kt | 8 +++---- .../casting/actions/eval/OpEvalBreakable.kt | 7 +++---- .../common/casting/actions/eval/OpForEach.kt | 7 +++---- .../common/casting/actions/eval/OpHalt.kt | 5 +++-- .../common/casting/actions/eval/OpThanos.kt | 3 +-- .../casting/actions/lists/OpLastNToList.kt | 18 +++++++--------- .../casting/actions/local/OpPeekLocal.kt | 7 +++---- .../casting/actions/local/OpPushLocal.kt | 6 +++--- .../common/casting/actions/spells/OpPrint.kt | 2 +- .../OpAlwinfyHasAscendedToABeingOfPureMath.kt | 5 ++++- .../casting/actions/stack/OpFisherman.kt | 12 +++++------ .../actions/stack/OpFishermanButItCopies.kt | 8 +++---- .../casting/actions/stack/OpStackSize.kt | 2 +- 61 files changed, 200 insertions(+), 151 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorBasic.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorBasic.kt index 1d43c890ce..0bcb9c6683 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorBasic.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/arithmetic/operator/OperatorBasic.kt @@ -14,14 +14,14 @@ abstract class OperatorBasic(arity: Int, accepts: IotaMultiPredicate) : Operator @Throws(Mishap::class) override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() - val args = stack.takeLast(arity) - repeat(arity) { stack.removeLast() } + val stack = image.stack + val args = stack.takeRight(arity) + val stackWithoutArgs = stack.dropRight(arity) val ret = apply(args, env) - ret.forEach(Consumer { e: Iota -> stack.add(e) }) + val stackWithResult = stackWithoutArgs.appendedAll(ret) - val image2 = image.copy(stack = stack, opsConsumed = image.opsConsumed + 1) + val image2 = image.copy(stack = stackWithResult, opsConsumed = image.opsConsumed + 1) return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/ConstMediaAction.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/ConstMediaAction.kt index 7586d07bd5..74f3a0f602 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/ConstMediaAction.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/ConstMediaAction.kt @@ -29,21 +29,21 @@ interface ConstMediaAction : Action { } override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + val stack = image.stack if (this.argc > stack.size) throw MishapNotEnoughArgs(this.argc, stack.size) - val args = stack.takeLast(this.argc) - repeat(this.argc) { stack.removeLast() } + val args = stack.takeRight(this.argc) + val stackWithoutArgs = stack.dropRight(this.argc) val result = this.executeWithOpCount(args, env) - stack.addAll(result.resultStack) + val stackWithResult = stackWithoutArgs.appendedAll(result.resultStack) if (env.extractMedia(this.mediaCost, true) > 0) throw MishapNotEnoughMedia(this.mediaCost) val sideEffects = mutableListOf(OperatorSideEffect.ConsumeMedia(this.mediaCost)) - val image2 = image.copy(stack = stack, opsConsumed = image.opsConsumed + result.opCount) + val image2 = image.copy(stack = stackWithResult, opsConsumed = image.opsConsumed + result.opCount) return OperationResult(image2, sideEffects, continuation, HexEvalSounds.NORMAL_EXECUTE) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/SpellAction.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/SpellAction.kt index 87a3bb3bcc..53f1756863 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/SpellAction.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/SpellAction.kt @@ -36,12 +36,12 @@ interface SpellAction : Action { } override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + val stack = image.stack if (this.argc > stack.size) throw MishapNotEnoughArgs(this.argc, stack.size) - val args = stack.takeLast(this.argc) - for (_i in 0 until this.argc) stack.removeLast() + val args = stack.takeRight(this.argc) + val stackWithoutArgs = stack.dropRight(this.argc) // execute! val userDataMut = image.userData.copy() @@ -65,7 +65,7 @@ interface SpellAction : Action { for (spray in result.particles) sideEffects.add(OperatorSideEffect.Particles(spray)) - val image2 = image.copy(stack = stack, opsConsumed = image.opsConsumed + result.opCount, userData = userDataMut) + val image2 = image.copy(stack = stackWithoutArgs, opsConsumed = image.opsConsumed + result.opCount, userData = userDataMut) val sound = if (this.hasCastingSound(env)) HexEvalSounds.SPELL else HexEvalSounds.MUTE return OperationResult(image2, sideEffects, continuation, sound) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/sideeffects/OperatorSideEffect.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/sideeffects/OperatorSideEffect.kt index 72226fe291..48d497f87b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/sideeffects/OperatorSideEffect.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/sideeffects/OperatorSideEffect.kt @@ -66,7 +66,7 @@ sealed class OperatorSideEffect { ) ) - harness.image = harness.image.copy(stack = mishap.executeReturnStack(harness.env, errorCtx, harness.image.stack.toMutableList())) + harness.image = harness.image.copy(stack = mishap.execute(harness.env, errorCtx, harness.image.stack)) } } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt index 89d0f003a3..e247ed82db 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt @@ -3,6 +3,7 @@ package at.petrak.hexcasting.api.casting.eval.vm import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.IotaType +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.getOrCreateCompound import at.petrak.hexcasting.api.utils.putCompound import at.petrak.hexcasting.api.utils.compositeCodecSeven @@ -18,16 +19,15 @@ import java.util.Optional * The state of a casting VM, containing the stack and all */ data class CastingImage( - val stack: List, - + val stack: TreeList, val parenCount: Int, - val parenthesized: List, + val parenthesized: TreeList, val escapeNext: Boolean, val simulateNext: Boolean, val opsConsumed: Long, val userData: CompoundTag ) { - constructor() : this(listOf(), 0, listOf(), false, false, 0, CompoundTag()) + constructor() : this(TreeList.empty(), 0, TreeList.empty(), false, false, 0, CompoundTag()) /** * `escaped` is used by [OpUndo][at.petrak.hexcasting.common.casting.actions.escaping.OpUndo] to determine whether the paren count @@ -67,14 +67,13 @@ data class CastingImage( /** * Returns a copy of this with escape/paren-related fields cleared. */ - fun withResetEscape() = this.copy(parenCount = 0, parenthesized = listOf(), escapeNext = false) + fun withResetEscape() = this.copy(parenCount = 0, parenthesized = TreeList.empty(), escapeNext = false) /** * Returns a copy of this with the provided iota added to the parenthesized list. */ fun withNewParenthesized(iota: Iota): CastingImage { - val newParens = this.parenthesized.toMutableList() - newParens.add(ParenthesizedIota(iota, false)) + val newParens = this.parenthesized.appended(ParenthesizedIota(iota, false)) return this.copy(parenthesized = newParens) } @@ -93,9 +92,9 @@ data class CastingImage( @JvmStatic val CODEC = RecordCodecBuilder.create { inst -> inst.group( - IotaType.TYPED_CODEC.listOf().fieldOf("stack").forGetter { it.stack }, + TreeList.codecOf(IotaType.TYPED_CODEC).fieldOf("stack").forGetter { it.stack }, Codec.INT.fieldOf("open_parens").forGetter { it.parenCount }, - ParenthesizedIota.CODEC.listOf().fieldOf("parenthesized").forGetter { it.parenthesized }, + TreeList.codecOf(ParenthesizedIota.CODEC).fieldOf("parenthesized").forGetter { it.parenthesized }, Codec.BOOL.fieldOf("escape_next").forGetter { it.escapeNext }, Codec.BOOL.fieldOf("simulate_next").forGetter { it.simulateNext }, Codec.LONG.fieldOf("ops_consumed").forGetter { it.opsConsumed }, @@ -106,9 +105,9 @@ data class CastingImage( }.orElseGet(::CastingImage) @JvmStatic val STREAM_CODEC = compositeCodecSeven( - IotaType.TYPED_STREAM_CODEC.apply(ByteBufCodecs.list()), CastingImage::stack, + IotaType.TYPED_STREAM_CODEC.apply(TreeList.streamCodecOp()), CastingImage::stack, ByteBufCodecs.VAR_INT, CastingImage::parenCount, - ParenthesizedIota.STREAM_CODEC.apply(ByteBufCodecs.list()), CastingImage::parenthesized, + ParenthesizedIota.STREAM_CODEC.apply(TreeList.streamCodecOp()), CastingImage::parenthesized, ByteBufCodecs.BOOL, CastingImage::escapeNext, ByteBufCodecs.BOOL, CastingImage::simulateNext, ByteBufCodecs.VAR_LONG, CastingImage::opsConsumed, diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt index e6c70a292b..aa744aa3fd 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt @@ -138,16 +138,14 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { val newImage: CastingImage if (this.image.parenCount > 0) { // if we're inside parentheses, add the iota to the list with escaped set to true - val newParens = this.image.parenthesized.toMutableList() - newParens.add(ParenthesizedIota(iota, true)) + val newParens = this.image.parenthesized.appended(ParenthesizedIota(iota, true)) newImage = this.image.copy( escapeNext = false, parenthesized = newParens ) } else { // if we're not in parentheses, just push the iota to the stack - val newStack = this.image.stack.toMutableList() - newStack.add(iota) + val newStack = this.image.stack.appended(iota) newImage = this.image.copy( stack = newStack, escapeNext = false, diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt index 476cd22a56..f38400142d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt @@ -41,7 +41,7 @@ interface ContinuationFrame { * In other words, we should consume Evaluate frames until we hit a FinishEval or Thoth frame. * @return whether the break should stop here, alongside the new stack state (e.g. for finalizing a Thoth) */ - fun breakDownwards(stack: List): Pair> + fun breakDownwards(stack: TreeList): Pair> /** * Return the number of iotas contained inside this frame, used for determining whether it is valid to serialise. diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt index bbcc6c29ec..10abd624ae 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt @@ -22,7 +22,7 @@ import net.minecraft.server.level.ServerLevel */ data class FrameEvaluate(val list: TreeList, val isMetacasting: Boolean) : ContinuationFrame { // Discard this frame and keep discarding frames. - override fun breakDownwards(stack: List) = false to stack + override fun breakDownwards(stack: TreeList) = false to stack // Step the list of patterns, evaluating a single one. override fun evaluate( diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt index 00b387d487..31b8a31a0d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.eval.CastResult import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.NullIota +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.common.lib.hex.HexEvalSounds import com.mojang.serialization.MapCodec import net.minecraft.network.RegistryFriendlyByteBuf @@ -16,7 +17,7 @@ import net.minecraft.server.level.ServerLevel */ object FrameFinishEval : ContinuationFrame { // Don't do anything else to the stack, just finish the halt statement. - override fun breakDownwards(stack: List) = true to stack + override fun breakDownwards(stack: TreeList) = true to stack // Evaluating it does nothing; it's only a boundary condition. override fun evaluate( diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt index c8eef17d65..3ef9c443f4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt @@ -28,15 +28,14 @@ import kotlin.jvm.optionals.getOrNull data class FrameForEach( val data: TreeList, val code: TreeList, - val baseStack: List?, + val baseStack: TreeList?, val acc: TreeList ) : ContinuationFrame { /** When halting, we add the stack state at halt to the stack accumulator, then return the original pre-Thoth stack, plus the accumulator. */ - override fun breakDownwards(stack: List): Pair> { - val newStack = baseStack?.toMutableList() ?: mutableListOf() - newStack.add(ListIota(acc.appendedAll(stack))) - return true to newStack + override fun breakDownwards(stack: TreeList): Pair> { + val newStack = baseStack ?: TreeList.empty() + return true to newStack.appended(ListIota(acc.appendedAll(stack))) } /** Step the Thoth computation, enqueueing one code evaluation. */ @@ -48,7 +47,7 @@ data class FrameForEach( // If this is the very first Thoth step (i.e. no Thoth computations run yet)... val (stack, newAcc) = if (baseStack == null) { // init stack to the harness stack... - harness.image.stack.toList() to acc + harness.image.stack to acc } else { // else save the stack to the accumulator and reuse the saved base stack. baseStack to acc.appendedAll(harness.image.stack) @@ -67,8 +66,7 @@ data class FrameForEach( // Else, dump our final list onto the stack. Triple(ListIota(newAcc), harness.image, continuation) } - val tStack = stack.toMutableList() - tStack.add(stackTop) + val tStack = stack.appended(stackTop) return CastResult( ListIota(code), newCont, @@ -91,7 +89,7 @@ data class FrameForEach( inst.group( TreeList.codecOf(IotaType.TYPED_CODEC).fieldOf("data").forGetter { it.data }, TreeList.codecOf(IotaType.TYPED_CODEC).fieldOf("code").forGetter { it.code }, - IotaType.TYPED_CODEC.listOf().optionalFieldOf("base").forGetter { Optional.ofNullable(it.baseStack) }, + TreeList.codecOf(IotaType.TYPED_CODEC).optionalFieldOf("base").forGetter { Optional.ofNullable(it.baseStack) }, TreeList.codecOf(IotaType.TYPED_CODEC).fieldOf("accumulator").forGetter { it.acc } ).apply(inst) { a, b, c, d -> FrameForEach(a, b, c.getOrNull(), d) @@ -101,7 +99,7 @@ data class FrameForEach( IotaType.TYPED_STREAM_CODEC.apply(TreeList.streamCodecOp()), FrameForEach::data, IotaType.TYPED_STREAM_CODEC.apply(TreeList.streamCodecOp()), FrameForEach::code, ByteBufCodecs.optional(IotaType.TYPED_STREAM_CODEC - .apply(ByteBufCodecs.list())), { Optional.ofNullable(it.baseStack) }, + .apply(TreeList.streamCodecOp())), { Optional.ofNullable(it.baseStack) }, IotaType.TYPED_STREAM_CODEC .apply(TreeList.streamCodecOp()), FrameForEach::acc ) { a, b, c, d -> diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/Mishap.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/Mishap.kt index 54f7e94c14..f32f921d19 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/Mishap.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/Mishap.kt @@ -6,6 +6,7 @@ import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.math.HexPattern import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.asTranslatedComponent import at.petrak.hexcasting.api.utils.lightPurple import at.petrak.hexcasting.common.lib.HexItems @@ -37,15 +38,10 @@ abstract class Mishap : RuntimeException() { * * You can also mess up the stack with this. */ - abstract fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) + abstract fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList protected abstract fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component? - fun executeReturnStack(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList): List { - execute(ctx, errorCtx, stack) - return stack - } - /** * Every error message should be prefixed with the name of the action... */ diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapAlreadyBrainswept.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapAlreadyBrainswept.kt index fcfe86b2d7..f863407c12 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapAlreadyBrainswept.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapAlreadyBrainswept.kt @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.ParticleSpray import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.common.lib.HexDamageTypes import net.minecraft.world.entity.Mob import net.minecraft.world.item.DyeColor @@ -12,8 +13,9 @@ class MishapAlreadyBrainswept(val mob: Mob) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.GREEN) - override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { mob.hurt(mob.damageSources().source(HexDamageTypes.OVERCAST, ctx.castingEntity), mob.health) + return stack } override fun particleSpray(ctx: CastingEnvironment) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBlock.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBlock.kt index 349e8f64cf..b0b8bb95c0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBlock.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBlock.kt @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.ParticleSpray import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.asTranslatedComponent import net.minecraft.core.BlockPos import net.minecraft.network.chat.Component @@ -15,8 +16,9 @@ class MishapBadBlock(val pos: BlockPos, val expected: Component) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.LIME) - override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { ctx.world.explode(null, pos.x + 0.5, pos.y + 0.5, pos.z + 0.5, 0.25f, Level.ExplosionInteraction.NONE) + return stack } override fun particleSpray(ctx: CastingEnvironment) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBrainsweep.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBrainsweep.kt index 601273fbb0..1f488834e0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBrainsweep.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBrainsweep.kt @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.ParticleSpray import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.common.lib.HexDamageTypes import net.minecraft.core.BlockPos import net.minecraft.world.entity.Mob @@ -14,8 +15,9 @@ class MishapBadBrainsweep(val mob: Mob, val pos: BlockPos) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.GREEN) - override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { trulyHurt(mob, mob.damageSources().source(HexDamageTypes.OVERCAST, ctx.castingEntity), 1f) + return stack } override fun particleSpray(ctx: CastingEnvironment): ParticleSpray { diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadCaster.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadCaster.kt index 99199f9561..32b0110cd7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadCaster.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadCaster.kt @@ -3,13 +3,15 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.world.item.DyeColor class MishapBadCaster: Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.RED) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadEntity.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadEntity.kt index 3ea3971c7c..b06797c3d1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadEntity.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadEntity.kt @@ -3,6 +3,7 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.aqua import at.petrak.hexcasting.api.utils.asTranslatedComponent import net.minecraft.network.chat.Component @@ -14,8 +15,9 @@ class MishapBadEntity(val entity: Entity, val wanted: Component) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.BROWN) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { env.mishapEnvironment.yeetHeldItemsTowards(entity.position()) + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadItem.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadItem.kt index d41cc88f32..77e9ed7313 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadItem.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadItem.kt @@ -3,6 +3,7 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.asTranslatedComponent import net.minecraft.network.chat.Component import net.minecraft.world.entity.item.ItemEntity @@ -12,8 +13,9 @@ class MishapBadItem(val item: ItemEntity, val wanted: Component) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.BROWN) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { item.deltaMovement = item.deltaMovement.add((Math.random() - 0.5) * 0.05, 0.75, (Math.random() - 0.5) * 0.05) + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = if (item.item.isEmpty) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadLocation.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadLocation.kt index 06955885a0..bd19aa42f3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadLocation.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadLocation.kt @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.Vec3Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.network.chat.Component import net.minecraft.world.item.DyeColor import net.minecraft.world.phys.Vec3 @@ -12,8 +13,9 @@ class MishapBadLocation(val location: Vec3, val type: String = "too_far") : Mish override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.MAGENTA) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { env.mishapEnvironment.yeetHeldItemsTowards(this.location) + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt index 6a9e0dafa3..a514c566a6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt @@ -3,6 +3,7 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.asTranslatedComponent import net.minecraft.network.chat.Component import net.minecraft.world.item.DyeColor @@ -12,8 +13,9 @@ class MishapBadOffhandItem(val item: ItemStack?, val wanted: Component) : Mishap override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.BROWN) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { env.mishapEnvironment.dropHeldItems() + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = if (item?.isEmpty == false) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDisallowedSpell.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDisallowedSpell.kt index e60dc5b6bc..5eafa7dc2f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDisallowedSpell.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDisallowedSpell.kt @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.asTranslatedComponent import net.minecraft.network.chat.Component import net.minecraft.resources.ResourceLocation @@ -18,8 +19,9 @@ class MishapDisallowedSpell(val type: String, val actionKey: ResourceLocation?) override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.INVALID - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { // NO-OP + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component? { diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDivideByZero.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDivideByZero.kt index 98050ee244..60704fe8f6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDivideByZero.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDivideByZero.kt @@ -6,6 +6,7 @@ import at.petrak.hexcasting.api.casting.iota.GarbageIota import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.Vec3Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.asTranslatedComponent import net.minecraft.network.chat.Component import net.minecraft.world.item.DyeColor @@ -16,9 +17,9 @@ class MishapDivideByZero(val operand1: Component, val operand2: Component, val s override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.RED) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { - stack.add(GarbageIota()) + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { env.mishapEnvironment.damage(0.5f) + return stack.appended(GarbageIota()) } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityNotFound.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityNotFound.kt index 7ec95d15a3..a66675d18e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityNotFound.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityNotFound.kt @@ -3,6 +3,7 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.aqua import net.minecraft.ChatFormatting import net.minecraft.network.chat.Component @@ -13,8 +14,9 @@ class MishapEntityNotFound(val entityId: UUID, val entityName: Component?) : Mis override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.BROWN) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { env.mishapEnvironment.nauseate(3 * 20) + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityTooFarAway.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityTooFarAway.kt index 232a5a0ef1..98e042df4e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityTooFarAway.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityTooFarAway.kt @@ -3,7 +3,7 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment -import at.petrak.hexcasting.api.utils.aqua +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.network.chat.Component import net.minecraft.world.entity.Entity import net.minecraft.world.item.DyeColor @@ -12,8 +12,9 @@ class MishapEntityTooFarAway(val entity: Entity) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.PINK) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { env.mishapEnvironment.yeetHeldItemsTowards(entity.position()) + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEvalTooMuch.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEvalTooMuch.kt index 1634cd63e1..b136030422 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEvalTooMuch.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEvalTooMuch.kt @@ -3,14 +3,16 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.world.item.DyeColor class MishapEvalTooMuch : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.BLUE) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { env.mishapEnvironment.drown() + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapImmuneEntity.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapImmuneEntity.kt index e0438a895b..28a91e347f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapImmuneEntity.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapImmuneEntity.kt @@ -3,6 +3,7 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.aqua import net.minecraft.world.entity.Entity import net.minecraft.world.item.DyeColor @@ -11,8 +12,9 @@ class MishapImmuneEntity(val entity: Entity) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.BLUE) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { env.mishapEnvironment.yeetHeldItemsTowards(entity.position()) + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInternalException.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInternalException.kt index 7301c01127..573b5cbb95 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInternalException.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInternalException.kt @@ -3,14 +3,16 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.world.item.DyeColor class MishapInternalException(val exception: Exception) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.BLACK) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { // NO-OP + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidIota.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidIota.kt index 0ec26d781b..5637971559 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidIota.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidIota.kt @@ -4,6 +4,7 @@ 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.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.asTranslatedComponent import at.petrak.hexcasting.common.lib.hex.HexIotaTypes import net.minecraft.network.chat.Component @@ -20,8 +21,8 @@ class MishapInvalidIota( override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.GRAY) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { - stack[stack.size - 1 - reverseIdx] = GarbageIota(); + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { + return stack.updated(stack.size - 1 - reverseIdx, GarbageIota()) } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component? { diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidOperatorArgs.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidOperatorArgs.kt index a16c083f4c..78c09ab5b6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidOperatorArgs.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidOperatorArgs.kt @@ -4,6 +4,7 @@ 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.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.asTextComponent import net.minecraft.network.chat.Component import net.minecraft.network.chat.ComponentUtils @@ -16,10 +17,12 @@ class MishapInvalidOperatorArgs(val perpetrators: List) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.GRAY) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { + var newStack = stack for (i in perpetrators.indices) { - stack[stack.size - 1 - i] = GarbageIota() + newStack = newStack.updated(stack.size - 1 - i, GarbageIota()) } + return newStack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component { diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidPattern.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidPattern.kt index 4e9f9a18df..5f16258d00 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidPattern.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidPattern.kt @@ -7,6 +7,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.PatternIota import at.petrak.hexcasting.api.casting.math.HexPattern import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.network.chat.Component import net.minecraft.world.item.DyeColor @@ -19,8 +20,8 @@ class MishapInvalidPattern(val pattern: HexPattern?) : Mishap() { override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.INVALID - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { - stack.add(GarbageIota()) + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { + return stack.appended(GarbageIota()) } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component? { diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidSpellDatumType.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidSpellDatumType.kt index 92384b0792..a8ab545c6b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidSpellDatumType.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidSpellDatumType.kt @@ -3,6 +3,7 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.world.item.DyeColor /** @@ -12,8 +13,9 @@ class MishapInvalidSpellDatumType(val perpetrator: Any) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.BLACK) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { // NO-OP + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLackingHotbarItem.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLackingHotbarItem.kt index cd26153399..a2cc93b771 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLackingHotbarItem.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLackingHotbarItem.kt @@ -3,6 +3,7 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.asTranslatedComponent import net.minecraft.network.chat.Component import net.minecraft.world.item.DyeColor @@ -16,8 +17,9 @@ class MishapLackingHotbarItem(val wanted: Component) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.BROWN) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { env.mishapEnvironment.dropHeldItems() + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = error("bad_item.hotbar", wanted) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLocationInWrongDimension.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLocationInWrongDimension.kt index 2d0e721838..830a24c424 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLocationInWrongDimension.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLocationInWrongDimension.kt @@ -4,6 +4,7 @@ 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.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.network.chat.Component import net.minecraft.resources.ResourceLocation import net.minecraft.world.item.DyeColor @@ -12,8 +13,8 @@ class MishapLocationInWrongDimension(val properDimension: ResourceLocation) : Mi override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.MAGENTA) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { - stack.add(GarbageIota()) + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { + return stack.appended(GarbageIota()) } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNeedsParens.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNeedsParens.kt index e6ec2a5053..11588ce410 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNeedsParens.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNeedsParens.kt @@ -4,16 +4,18 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.PatternIota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.world.item.DyeColor class MishapNeedsParens : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.ORANGE) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { // TODO this is a kinda shitty mishap - if (errorCtx.pattern != null) - stack.add(PatternIota(errorCtx.pattern)) + return if (errorCtx.pattern != null) + stack.appended(PatternIota(errorCtx.pattern)) + else stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNoAkashicRecord.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNoAkashicRecord.kt index 05eb6f5837..43cc02764a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNoAkashicRecord.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNoAkashicRecord.kt @@ -3,6 +3,7 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.core.BlockPos import net.minecraft.world.item.DyeColor @@ -10,8 +11,9 @@ class MishapNoAkashicRecord(val pos: BlockPos) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.PURPLE) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { env.mishapEnvironment.removeXp(100) + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughArgs.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughArgs.kt index 646f42c927..adb38bcc25 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughArgs.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughArgs.kt @@ -4,14 +4,15 @@ 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.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.world.item.DyeColor class MishapNotEnoughArgs(val expected: Int, val got: Int) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.LIGHT_GRAY) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { - repeat(expected - got) { stack.add(GarbageIota()) } + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { + return stack.appendedAll(List(expected - got) { GarbageIota() }) } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughMedia.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughMedia.kt index 07d686b56e..9b7deacaba 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughMedia.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNotEnoughMedia.kt @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.asTranslatedComponent import net.minecraft.world.item.DyeColor @@ -13,8 +14,9 @@ class MishapNotEnoughMedia(private val cost: Long) : Mishap() { override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.ERRORED - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { env.extractMedia(cost, false) + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = "hexcasting.message.cant_overcast".asTranslatedComponent diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt index 3a08ff5f33..9b65d63479 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt @@ -5,6 +5,7 @@ import at.petrak.hexcasting.api.casting.iota.EntityIota import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment import net.minecraft.server.level.ServerLevel +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.world.entity.player.Player import net.minecraft.world.item.DyeColor @@ -15,9 +16,10 @@ class MishapOthersName(val confidant: Player) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.BLACK) - override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { val seconds = if (this.confidant == ctx.castingEntity) 5 else 60 ctx.mishapEnvironment.blind(seconds * 20) + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt index 9c8a93eb4c..dcde708e97 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt @@ -5,6 +5,7 @@ import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType import at.petrak.hexcasting.api.casting.iota.GarbageIota import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.world.item.DyeColor class MishapStackSize() : Mishap() { @@ -13,9 +14,8 @@ class MishapStackSize() : Mishap() { override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.ERRORED - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { - stack.clear() - stack.add(GarbageIota()) + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { + return TreeList.from(listOf(GarbageIota())) } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnenlightened.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnenlightened.kt index e0dde2150b..e0eb08f2ea 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnenlightened.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnenlightened.kt @@ -5,6 +5,7 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.api.utils.asTranslatedComponent import net.minecraft.server.level.ServerPlayer import net.minecraft.sounds.SoundEvents @@ -17,7 +18,7 @@ class MishapUnenlightened : Mishap() { override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.INVALID - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { env.mishapEnvironment.dropHeldItems() env.castingEntity?.sendSystemMessage("hexcasting.message.cant_great_spell".asTranslatedComponent) @@ -29,6 +30,7 @@ class MishapUnenlightened : Mishap() { if (castingPlayer != null) { HexAdvancementTriggers.FAIL_GREAT_SPELL_TRIGGER.trigger(castingPlayer) } + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = null diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnescapedValue.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnescapedValue.kt index 6a30a8221e..d54a9c9583 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnescapedValue.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapUnescapedValue.kt @@ -3,6 +3,7 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.world.item.DyeColor /** @@ -14,7 +15,7 @@ class MishapUnescapedValue( override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.GRAY) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { // TODO /* val idx = stack.indexOfLast { it.getType() == DatumType.LIST } @@ -28,6 +29,7 @@ class MishapUnescapedValue( } } */ + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixEmptyStack.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixEmptyStack.kt index ae27403f23..b06cd7ad39 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixEmptyStack.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixEmptyStack.kt @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.mishaps.Mishap import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.core.BlockPos import net.minecraft.network.chat.Component import net.minecraft.world.item.DyeColor @@ -15,8 +16,9 @@ class MishapBoolDirectrixEmptyStack( override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.GRAY) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { env.world.destroyBlock(this.pos, true) + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixNotBool.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixNotBool.kt index e4975f59a8..cd298fe21c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixNotBool.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapBoolDirectrixNotBool.kt @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.mishaps.Mishap import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.core.BlockPos import net.minecraft.network.chat.Component import net.minecraft.world.item.DyeColor @@ -16,8 +17,9 @@ class MishapBoolDirectrixNotBool( override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.GRAY) - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { env.world.destroyBlock(this.pos, true) + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapNoSpellCircle.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapNoSpellCircle.kt index 459f9e3dd8..0a8177947b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapNoSpellCircle.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/circle/MishapNoSpellCircle.kt @@ -5,6 +5,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.mishaps.Mishap import at.petrak.hexcasting.api.pigment.FrozenPigment import net.minecraft.core.component.DataComponents +import at.petrak.hexcasting.api.utils.TreeList import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.player.Player import net.minecraft.world.item.DyeColor @@ -26,7 +27,7 @@ class MishapNoSpellCircle : Mishap() { } } - override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: TreeList): TreeList { val caster = env.castingEntity as? ServerPlayer if (caster != null) { // FIXME: handle null caster case @@ -36,6 +37,7 @@ class MishapNoSpellCircle : Mishap() { it.get(DataComponents.ENCHANTMENTS)?.keySet()?.any { e -> e.`is`(Enchantments.BINDING_CURSE) } != true } } + return stack } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt b/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt index 715e16b5e2..fdd0e828ba 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt @@ -329,7 +329,7 @@ fun validateIota(iota: T, serverLevel: ServerLevel): Iota { } } -fun validateIotaList(iotaList: List, serverLevel: ServerLevel): List { +fun validateIotaList(iotaList: TreeList, serverLevel: ServerLevel): TreeList { return iotaList.map { validateIota(it, serverLevel) } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockBooleanDirectrix.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockBooleanDirectrix.java index 76f2971f19..57e274337e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockBooleanDirectrix.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/directrix/BlockBooleanDirectrix.java @@ -6,6 +6,7 @@ import at.petrak.hexcasting.api.casting.iota.BooleanIota; import at.petrak.hexcasting.api.casting.mishaps.circle.MishapBoolDirectrixEmptyStack; import at.petrak.hexcasting.api.casting.mishaps.circle.MishapBoolDirectrixNotBool; +import at.petrak.hexcasting.api.utils.TreeList; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; @@ -42,13 +43,13 @@ public BlockBooleanDirectrix(Properties properties) { @Override public ControlFlow acceptControlFlow(CastingImage imageIn, CircleCastEnv env, Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world) { - var stack = new ArrayList<>(imageIn.getStack()); + var stack = imageIn.getStack(); if (stack.isEmpty()) { this.fakeThrowMishap(pos, bs, imageIn, env, new MishapBoolDirectrixEmptyStack(pos)); return new ControlFlow.Stop(); } - var last = stack.remove(stack.size() - 1); + var last = stack.last(); if (!(last instanceof BooleanIota biota)) { this.fakeThrowMishap(pos, bs, imageIn, env, @@ -61,7 +62,7 @@ public ControlFlow acceptControlFlow(CastingImage imageIn, CircleCastEnv env, Di var outputDir = biota.getBool() ? bs.getValue(FACING).getOpposite() : bs.getValue(FACING); - var imageOut = imageIn.copy(stack, imageIn.getParenCount(), imageIn.getParenthesized(), + var imageOut = imageIn.copy(stack.init(), imageIn.getParenCount(), imageIn.getParenthesized(), imageIn.getEscapeNext(), imageIn.getSimulateNext(), imageIn.getOpsConsumed(), imageIn.getUserData()); return new ControlFlow.Continue(imageOut, List.of(this.exitPositionFromDirection(pos, outputDir))); diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/escaping/OpCloseParen.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/escaping/OpCloseParen.kt index 066632cff7..98316b8aca 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/escaping/OpCloseParen.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/escaping/OpCloseParen.kt @@ -11,6 +11,7 @@ import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.ListIota import at.petrak.hexcasting.api.casting.mishaps.MishapNeedsParens +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpCloseParen : Action { @@ -21,19 +22,17 @@ object OpCloseParen : Action { override fun operateInParens(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation, thisIota: Iota): ParenthesizedOperationResult { val newParenCount = image.parenCount - 1 if (newParenCount == 0) { - val newStack = image.stack.toMutableList() - newStack.add(ListIota(image.parenthesized.toList().map { it.iota })) + val newStack = image.stack.appended(ListIota(image.parenthesized.map { it.iota })) val image2 = image.copy( stack = newStack, parenCount = newParenCount, - parenthesized = listOf() + parenthesized = TreeList.empty() ) return ParenthesizedOperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE, ResolvedPatternType.EVALUATED) } else { // we have this situation: "(()" // we need to add the close paren - val newParens = image.parenthesized.toMutableList() - newParens.add(ParenthesizedIota(thisIota, false)) + val newParens = image.parenthesized.appended(ParenthesizedIota(thisIota, false)) val image2 = image.copy( parenCount = newParenCount, parenthesized = newParens diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/escaping/OpOpenParen.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/escaping/OpOpenParen.kt index 87fddccdb2..b5a50925d8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/escaping/OpOpenParen.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/escaping/OpOpenParen.kt @@ -20,8 +20,7 @@ object OpOpenParen : Action { override fun operateInParens(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation, thisIota: Iota): ParenthesizedOperationResult { // we have escaped the parens onto the stack; we just also record our count. - val newParens = image.parenthesized.toMutableList() - newParens.add(CastingImage.ParenthesizedIota(thisIota, false)) + val newParens = image.parenthesized.appended(CastingImage.ParenthesizedIota(thisIota, false)) val image2 = image.copy( parenthesized = newParens, parenCount = image.parenCount + 1 diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/escaping/OpUndo.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/escaping/OpUndo.kt index c8f1b3aed3..9c31eac8f8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/escaping/OpUndo.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/escaping/OpUndo.kt @@ -19,8 +19,11 @@ object OpUndo : Action { } override fun operateInParens(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation, thisIota: Iota): ParenthesizedOperationResult { - val newParens = image.parenthesized.toMutableList() - val last = newParens.removeLastOrNull() + val (newParens, last) = if(image.parenthesized.isEmpty()) { + (image.parenthesized to null) + } else { + (image.parenthesized.init() to image.parenthesized.last()) + } var newParenCount = image.parenCount if (last == null) { // if there was nothing in the parenthesized list, undo the initial open paren diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEval.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEval.kt index 1b00f68453..9403204239 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEval.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEval.kt @@ -15,12 +15,12 @@ import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpEval : Action { override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() - val iota = stack.removeLastOrNull() ?: throw MishapNotEnoughArgs(1, 0) - return exec(env, image, continuation, stack, iota) + val stack = image.stack + val iota = stack.lastOrNull() ?: throw MishapNotEnoughArgs(1, 0) + return exec(env, image, continuation, stack.init(), iota) } - fun exec(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation, newStack: MutableList, iota: Iota): OperationResult { + fun exec(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation, newStack: TreeList, iota: Iota): OperationResult { // also, never make a break boundary when evaluating just one pattern val instrs = evaluatable(iota, 0) val newCont = diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEvalBreakable.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEvalBreakable.kt index f778d87356..0646c3ea0a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEvalBreakable.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpEvalBreakable.kt @@ -12,9 +12,8 @@ object OpEvalBreakable : Action { override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() - val iota = stack.removeLastOrNull() ?: throw MishapNotEnoughArgs(1, 0) - stack.add(ContinuationIota(continuation)) - return OpEval.exec(env, image, continuation, stack, iota) + val stack = image.stack + val iota = stack.lastOrNull() ?: throw MishapNotEnoughArgs(1, 0) + return OpEval.exec(env, image, continuation, stack.init().appended(ContinuationIota(continuation)), iota) } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpForEach.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpForEach.kt index 926bce1d82..e3100fb1bf 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpForEach.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpForEach.kt @@ -13,18 +13,17 @@ import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpForEach : Action { override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + val stack = image.stack if (stack.size < 2) throw MishapNotEnoughArgs(2, stack.size) val instrs = stack.getList(stack.lastIndex - 1, stack.size) val datums = stack.getList(stack.lastIndex, stack.size) - stack.removeLastOrNull() - stack.removeLastOrNull() + val newStack = stack.dropRight(2) val frame = FrameForEach(datums, instrs, null, TreeList.empty()) - val image2 = image.withUsedOp().copy(stack = stack) + val image2 = image.withUsedOp().copy(stack = newStack) return OperationResult(image2, listOf(), continuation.pushFrame(frame), HexEvalSounds.THOTH) } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpHalt.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpHalt.kt index 7436c26a0c..f4e4908b2c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpHalt.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpHalt.kt @@ -5,11 +5,12 @@ 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.utils.TreeList import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpHalt : Action { override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - var newStack = image.stack.toList() + var newStack = image.stack var done = false var newCont = continuation @@ -23,7 +24,7 @@ object OpHalt : Action { // if we hit no continuation boundaries (i.e. thoth/hermes exits), we've TOTALLY cleared the itinerary... if (!done) { // bomb the stack so we exit - newStack = listOf() + newStack = TreeList.empty() } val image2 = image.withUsedOp().copy(stack = newStack) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpThanos.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpThanos.kt index 47373eb9f1..8215acfc92 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpThanos.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpThanos.kt @@ -11,8 +11,7 @@ import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpThanos : Action { override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { val opsLeft = env.maxOpCount() - image.opsConsumed - val stack = image.stack.toMutableList() - stack.add(DoubleIota(opsLeft.toDouble())) + val stack = image.stack.appended(DoubleIota(opsLeft.toDouble())) val image2 = image.withUsedOp().copy(stack = stack) return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpLastNToList.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpLastNToList.kt index ffd4e3c10a..13dfa9a305 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpLastNToList.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/lists/OpLastNToList.kt @@ -9,24 +9,22 @@ import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation import at.petrak.hexcasting.api.casting.getPositiveIntUnderInclusive import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpLastNToList : Action { override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + val stack = image.stack if (stack.isEmpty()) throw MishapNotEnoughArgs(1, 0) - val yoinkCount = stack.takeLast(1).getPositiveIntUnderInclusive(0, stack.size - 1) - stack.removeLast() - val output = mutableListOf() - output.addAll(stack.takeLast(yoinkCount)) - for (i in 0 until yoinkCount) { - stack.removeLast() - } - stack.addAll(output.asActionResult) + val yoinkCount = stack.takeRight(1).getPositiveIntUnderInclusive(0, stack.size - 1) + val stackWithoutArg = stack.init() + val output = TreeList.from(stackWithoutArg.takeRight(yoinkCount)) + val stackWithoutContents = stackWithoutArg.dropRight(yoinkCount) + val stackWithResult = stackWithoutContents.appendedAll(output.asActionResult) - val image2 = image.withUsedOp().copy(stack = stack) + val image2 = image.withUsedOp().copy(stack = stackWithResult) return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPeekLocal.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPeekLocal.kt index bbf1fc83d5..fca277c4d8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPeekLocal.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPeekLocal.kt @@ -15,19 +15,18 @@ import kotlin.jvm.optionals.getOrElse object OpPeekLocal : Action { override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() val ravenmind = image.ravenmind() + val stack = image.stack val rm = if (ravenmind.isPresent) { IotaType.TYPED_CODEC.parse(NbtOps.INSTANCE, ravenmind.get()).orThrow } else { NullIota() } - - stack.add(rm) + val newStack = stack.appended(rm) // does not mutate userdata - val image2 = image.withUsedOp().copy(stack = stack) + val image2 = image.withUsedOp().copy(stack = newStack) return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPushLocal.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPushLocal.kt index 74061a5b53..edaeef11cc 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPushLocal.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/local/OpPushLocal.kt @@ -16,18 +16,18 @@ import kotlin.jvm.optionals.getOrElse object OpPushLocal : Action { override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + val stack = image.stack if (stack.isEmpty()) throw MishapNotEnoughArgs(1, 0) - val newLocal = stack.removeLast() + val newLocal = stack.last() if (newLocal.type == HexIotaTypes.NULL) image.userData.remove(HexAPI.RAVENMIND_USERDATA) else image.userData.put(HexAPI.RAVENMIND_USERDATA, IotaType.TYPED_CODEC.encodeStart(NbtOps.INSTANCE, newLocal).orThrow) - val image2 = image.withUsedOp().copy(stack = stack) + val image2 = image.withUsedOp().copy(stack = stack.init()) return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPrint.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPrint.kt index 4fc5e565ca..d2f33a8499 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPrint.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPrint.kt @@ -14,7 +14,7 @@ import at.petrak.hexcasting.common.lib.hex.HexEvalSounds // TODO should this dump the whole stack object OpPrint : Action { override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + val stack = image.stack if (stack.isEmpty()) { throw MishapNotEnoughArgs(1, 0) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt index da6757147d..d065527d09 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt @@ -7,6 +7,7 @@ import at.petrak.hexcasting.api.casting.eval.vm.CastingImage import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation import at.petrak.hexcasting.api.casting.getPositiveLong import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.common.lib.hex.HexEvalSounds import it.unimi.dsi.fastutil.longs.LongArrayList @@ -42,7 +43,9 @@ object OpAlwinfyHasAscendedToABeingOfPureMath : Action { editTarget = editTarget.subList(1, editTarget.size) } - val image2 = image.withUsedOp().copy(stack = stack) + // FIXME this is expensive if the stack is incredibly large + // someone should rewrite this op to cut and replace a `slice` of the `TreeList` stack + val image2 = image.withUsedOp().copy(stack = TreeList.from(stack)) return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFisherman.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFisherman.kt index c2c8874f28..5f53dfa950 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFisherman.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFisherman.kt @@ -14,14 +14,14 @@ import kotlin.math.roundToInt object OpFisherman : Action { override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + var stack = image.stack if (stack.size < 2) throw MishapNotEnoughArgs(2, stack.size) val depth = let { val x = stack.last() - stack.removeLast() + stack = stack.init() val maxIdx = stack.size - 1 if (x is DoubleIota) { val double = x.double @@ -34,11 +34,11 @@ object OpFisherman : Action { } if (depth >= 0) { - val fish = stack.removeAt(stack.size - 1 - depth) - stack.add(fish) + val fish = stack[stack.size - 1 - depth] + stack = stack.dropRight(depth + 1).appendedAll(stack.takeRight(depth)).appended(fish) } else { - val lure = stack.removeLast() - stack.add(stack.size + depth, lure) + val lure = stack.last() + stack = stack.dropRight(1 - depth).appended(lure).appendedAll(stack.takeRight(1 - depth).init()) } val image2 = image.withUsedOp().copy(stack = stack) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFishermanButItCopies.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFishermanButItCopies.kt index 91ed5b94a3..e9999abaff 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFishermanButItCopies.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpFishermanButItCopies.kt @@ -11,20 +11,20 @@ import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpFishermanButItCopies : Action { override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + var stack = image.stack if (stack.size < 2) throw MishapNotEnoughArgs(2, stack.size) val depth = stack.getIntBetween(stack.lastIndex, -(stack.size - 2), stack.size - 2) - stack.removeLast() + stack = stack.init() if (depth >= 0) { val fish = stack[stack.size - 1 - depth] - stack.add(fish) + stack = stack.appended(fish) } else { val lure = stack.last() - stack.add(stack.size - 1 + depth, lure) + stack = stack.dropRight(1 - depth).appended(lure).appendedAll(stack.takeRight(1 - depth)) } val image2 = image.withUsedOp().copy(stack = stack) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpStackSize.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpStackSize.kt index eeec0f572b..6124cac40b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpStackSize.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpStackSize.kt @@ -10,7 +10,7 @@ import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpStackSize : Action { override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + val stack = image.stack stack.add(DoubleIota(stack.size.toDouble())) val image2 = image.withUsedOp().copy(stack = stack) return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) From 3eb2dcb5edbfea904f0df6aae7f5f180b532cec3 Mon Sep 17 00:00:00 2001 From: Aly Date: Sun, 10 May 2026 13:25:40 -0600 Subject: [PATCH 2/8] fix OpStackSize --- .../hexcasting/common/casting/actions/stack/OpStackSize.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpStackSize.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpStackSize.kt index 6124cac40b..42dcd19dac 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpStackSize.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpStackSize.kt @@ -10,8 +10,7 @@ import at.petrak.hexcasting.common.lib.hex.HexEvalSounds object OpStackSize : Action { override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack - stack.add(DoubleIota(stack.size.toDouble())) + val stack = image.stack.appended(DoubleIota(image.stack.size.toDouble())) val image2 = image.withUsedOp().copy(stack = stack) return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) } From a09a1f3b73da13f5f9785264ef514e319309b9a1 Mon Sep 17 00:00:00 2001 From: Aly Date: Thu, 11 Jun 2026 19:59:11 -0600 Subject: [PATCH 3/8] add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32b75efe60..fa47266602 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - Removed APIs deprecated in `0.11.4` ([#1126](https://github.com/FallingColors/HexMod/pull/1126), [#1127](https://github.com/FallingColors/HexMod/pull/1127) [#1129](https://github.com/FallingColors/HexMod/pull/1129), [#1137](https://github.com/FallingColors/HexMod/pull/1137), [#1142](https://github.com/FallingColors/HexMod/pull/1142)) @s5bug - ListIota now uses the asymptotically-efficient TreeList internally ([#1032](https://github.com/FallingColors/HexMod/pull/1032)) @s5bug +- SpellList has been removed, the Casting Image and Casting Frames now store iotas in a TreeList ([#1033](https://github.com/FallingColors/HexMod/pull/1033)) @s5bug ## `0.11.3` - 2025-11-22 From 11854724522427e6e02850bbcdc3967da7f47b4e Mon Sep 17 00:00:00 2001 From: Aly Date: Wed, 15 Jul 2026 18:11:04 -0600 Subject: [PATCH 4/8] fix type mismatch in CastingVM --- .../java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt index aa744aa3fd..a66ac79030 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt @@ -165,8 +165,7 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { // if simulating, push a bool for whether the cast would have succeeded; do not perform any side effects if (this.image.simulateNext) { val tooBig = result.newData != null && IotaType.isTooLargeToSerialize(result.newData.stack) - val newStack = this.image.stack.toMutableList() - newStack.add(BooleanIota(result.resolutionType.success && !tooBig)) + val newStack = this.image.stack.appended(BooleanIota(result.resolutionType.success && !tooBig)) val newImage = this.image.copy( stack = newStack, simulateNext = false From e3ad3dfb4421b0af67bfbc532a8295d32f271928 Mon Sep 17 00:00:00 2001 From: Robotgiggle <88736742+Robotgiggle@users.noreply.github.com> Date: Wed, 15 Jul 2026 21:31:57 -0400 Subject: [PATCH 5/8] Add missing import statement --- .../petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt index f38400142d..c3077c40f6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt @@ -2,6 +2,7 @@ package at.petrak.hexcasting.api.casting.eval.vm import at.petrak.hexcasting.api.casting.eval.CastResult import at.petrak.hexcasting.api.casting.iota.Iota +import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.common.lib.HexRegistries import at.petrak.hexcasting.common.lib.hex.HexContinuationTypes import at.petrak.hexcasting.xplat.IXplatAbstractions From e0772639eb478e619e2d4e40542e507e10333db8 Mon Sep 17 00:00:00 2001 From: Robotgiggle <88736742+Robotgiggle@users.noreply.github.com> Date: Wed, 15 Jul 2026 23:07:16 -0400 Subject: [PATCH 6/8] Improve swindler implementation --- .../OpAlwinfyHasAscendedToABeingOfPureMath.kt | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt index d065527d09..0c6cb285d1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt @@ -6,6 +6,7 @@ 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.getPositiveLong +import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs import at.petrak.hexcasting.api.utils.TreeList import at.petrak.hexcasting.common.lib.hex.HexEvalSounds @@ -14,13 +15,13 @@ import it.unimi.dsi.fastutil.longs.LongArrayList // "lehmer code" object OpAlwinfyHasAscendedToABeingOfPureMath : Action { override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult { - val stack = image.stack.toMutableList() + var stack = image.stack if (stack.isEmpty()) throw MishapNotEnoughArgs(1, 0) val code = stack.getPositiveLong(stack.lastIndex) - stack.removeLast() + stack = stack.init() val strides = LongArrayList() for (f in FactorialIter()) { @@ -32,20 +33,16 @@ object OpAlwinfyHasAscendedToABeingOfPureMath : Action { if (strides.size > stack.size) throw MishapNotEnoughArgs(strides.size + 1, stack.size + 1) - var editTarget = stack.subList(stack.size - strides.size, stack.size) - val swap = editTarget.toMutableList() + var newOrder = TreeList.empty() + val oldOrder = stack.slice(stack.size - strides.size, stack.size).toMutableList() var radix = code for (divisor in strides.asReversed()) { val index = radix / divisor radix %= divisor - editTarget[0] = swap.removeAt(index.toInt()) - // i hope this isn't O(n) - editTarget = editTarget.subList(1, editTarget.size) + newOrder = newOrder.appended(oldOrder.removeAt(index.toInt())) } - // FIXME this is expensive if the stack is incredibly large - // someone should rewrite this op to cut and replace a `slice` of the `TreeList` stack - val image2 = image.withUsedOp().copy(stack = TreeList.from(stack)) + val image2 = image.withUsedOp().copy(stack = stack.dropRight(strides.size).appendedAll(newOrder)) return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) } From 3f1bff9a975fd9216a886661bc16879925a39af5 Mon Sep 17 00:00:00 2001 From: Aly Date: Wed, 15 Jul 2026 22:39:12 -0600 Subject: [PATCH 7/8] revise changelog entries to be more correct --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa47266602..3a88d65fb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - Removed APIs deprecated in `0.11.4` ([#1126](https://github.com/FallingColors/HexMod/pull/1126), [#1127](https://github.com/FallingColors/HexMod/pull/1127) [#1129](https://github.com/FallingColors/HexMod/pull/1129), [#1137](https://github.com/FallingColors/HexMod/pull/1137), [#1142](https://github.com/FallingColors/HexMod/pull/1142)) @s5bug - ListIota now uses the asymptotically-efficient TreeList internally ([#1032](https://github.com/FallingColors/HexMod/pull/1032)) @s5bug -- SpellList has been removed, the Casting Image and Casting Frames now store iotas in a TreeList ([#1033](https://github.com/FallingColors/HexMod/pull/1033)) @s5bug +- SpellList has been removed ([#1032](https://github.com/FallingColors/HexMod/pull/1032)) @s5bug +- Casting Image and Casting Frames now store iotas in a TreeList ([#1033](https://github.com/FallingColors/HexMod/pull/1033)) @s5bug ## `0.11.3` - 2025-11-22 From 3855d7826b40d2d2c9923ca62ac7400f3cc7b51b Mon Sep 17 00:00:00 2001 From: Aly Date: Wed, 15 Jul 2026 22:42:17 -0600 Subject: [PATCH 8/8] make Swindler's use a builder for efficiency --- .../actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt index 0c6cb285d1..5a2530b4b5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpAlwinfyHasAscendedToABeingOfPureMath.kt @@ -33,16 +33,16 @@ object OpAlwinfyHasAscendedToABeingOfPureMath : Action { if (strides.size > stack.size) throw MishapNotEnoughArgs(strides.size + 1, stack.size + 1) - var newOrder = TreeList.empty() + val newOrder = TreeList.TreeListBuilder() val oldOrder = stack.slice(stack.size - strides.size, stack.size).toMutableList() var radix = code for (divisor in strides.asReversed()) { val index = radix / divisor radix %= divisor - newOrder = newOrder.appended(oldOrder.removeAt(index.toInt())) + newOrder.addOne(oldOrder.removeAt(index.toInt())) } - val image2 = image.withUsedOp().copy(stack = stack.dropRight(strides.size).appendedAll(newOrder)) + val image2 = image.withUsedOp().copy(stack = stack.dropRight(strides.size).appendedAll(newOrder.result())) return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE) }