Bring down the error count hopefully

This commit is contained in:
Alwinfy 2023-02-07 21:57:52 -05:00
parent 7b0813d1b6
commit a7a5073a74
No known key found for this signature in database
GPG key ID: 2CCB99445F0C949E
23 changed files with 179 additions and 115 deletions

View file

@ -2,7 +2,7 @@ package at.petrak.hexcasting.api.casting.eval
import at.petrak.hexcasting.api.casting.eval.sideeffects.EvalSound
import at.petrak.hexcasting.api.casting.eval.sideeffects.OperatorSideEffect
import at.petrak.hexcasting.api.casting.eval.vm.FunctionalData
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage
import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation
/**
@ -13,8 +13,8 @@ import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation
*/
data class CastResult(
val continuation: SpellContinuation,
val newData: FunctionalData?,
val newData: CastingImage?,
val sideEffects: List<OperatorSideEffect>,
val resolutionType: ResolvedPatternType,
val sound: EvalSound,
)
)

View file

@ -2,16 +2,20 @@ package at.petrak.hexcasting.api.casting.eval;
import at.petrak.hexcasting.api.casting.ParticleSpray;
import at.petrak.hexcasting.api.casting.PatternShapeMatch;
import at.petrak.hexcasting.api.casting.eval.SpellCircleContext;
import at.petrak.hexcasting.api.casting.eval.sideeffects.EvalSound;
import at.petrak.hexcasting.api.casting.mishaps.Mishap;
import at.petrak.hexcasting.api.casting.mishaps.MishapDisallowedSpell;
import at.petrak.hexcasting.api.casting.mishaps.MishapEntityTooFarAway;
import at.petrak.hexcasting.api.casting.mishaps.MishapLocationTooFarAway;
import at.petrak.hexcasting.api.misc.FrozenColorizer;
import at.petrak.hexcasting.api.mod.HexConfig;
import com.mojang.datafixers.util.Pair;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3;
@ -51,6 +55,17 @@ public abstract class CastingEnvironment {
@Nullable
public abstract ServerPlayer getCaster();
/**
* Get the sound that this I/O module makes.
* <p>
*/
public abstract EvalSound getSoundType();
/**
* Get the spell circle running this cast. Might be null if not casting from a spell circle!
*/
@Nullable
public abstract SpellCircleContext getSpellCircle();
/**
* If something about this ARE itself is invalid, mishap.
@ -106,24 +121,31 @@ public abstract class CastingEnvironment {
return this.isVecInRange(vec) && this.isVecInWorld(vec);
}
public final boolean isEntityInAmbit(Entity e) {
public final boolean isEntityInRange(Entity e) {
return this.isVecInRange(e.position());
}
/**
* Convenience function to throw if the vec is out of the caster's range or the world
*/
public final void assertVecInAmbit(Vec3 vec) throws MishapLocationTooFarAway {
public final void assertVecInRange(Vec3 vec) throws MishapLocationTooFarAway {
this.assertVecInWorld(vec);
if (this.isVecInRange(vec)) {
throw new MishapLocationTooFarAway(vec, "too_far");
}
}
public final void assertVecInRange(BlockPos vec) throws MishapLocationTooFarAway {
this.assertVecInRange(new Vec3(vec.x(), vec.y(), vec.z()));
}
public final boolean canEditBlockAt(BlockPos vec) {
// TODO winfy: fill this in
return false;
}
/**
* Convenience function to throw if the entity is out of the caster's range or the world
*/
public final void assertEntityInAmbit(Entity e) throws MishapEntityTooFarAway {
public final void assertEntityInRange(Entity e) throws MishapEntityTooFarAway {
if (!this.isVecInWorld(e.position())) {
throw new MishapEntityTooFarAway(e);
}
@ -145,7 +167,7 @@ public abstract class CastingEnvironment {
this.entitiesGivenMotion.add(e);
}
public boolean hasEntityBeenImpulsed(Entity e) {
public boolean hasBeenGivenMotion(Entity e) {
return this.entitiesGivenMotion.contains(e);
}
@ -177,6 +199,20 @@ public abstract class CastingEnvironment {
return null;
}
public static record HeldItemInfo(ItemStack stack, InteractionHand hand) {
public ItemStack component1() { return stack; }
public InteractionHand component2() { return hand; }
}
/**
* Return the slot from which to take blocks and items.
*/
// TODO winfy: resolve the null here
// @Nullable
public HeldItemInfo getHeldItemToOperateOn(Predicate<ItemStack> stackOk) {
// TODO winfy: return something properly
return null;
}
/**
* Attempt to withdraw some number of items from stacks available.
* <p>

View file

@ -22,10 +22,10 @@ sealed class OperatorSideEffect {
data class RequiredEnlightenment(val awardStat: Boolean) : OperatorSideEffect() {
override fun performEffect(harness: CastingVM): Boolean {
harness.ctx.caster?.sendSystemMessage("hexcasting.message.cant_great_spell".asTranslatedComponent)
harness.env.caster?.sendSystemMessage("hexcasting.message.cant_great_spell".asTranslatedComponent)
if (awardStat)
HexAdvancementTriggers.FAIL_GREAT_SPELL_TRIGGER.trigger(harness.ctx.caster)
HexAdvancementTriggers.FAIL_GREAT_SPELL_TRIGGER.trigger(harness.env.caster)
return true
}
@ -39,9 +39,9 @@ sealed class OperatorSideEffect {
) :
OperatorSideEffect() {
override fun performEffect(harness: CastingVM): Boolean {
this.spell.cast(harness.ctx)
this.spell.cast(harness.env)
if (awardStat)
harness.ctx.caster?.awardStat(HexStatistics.SPELLS_CAST)
harness.env.caster?.awardStat(HexStatistics.SPELLS_CAST)
return false
}
@ -49,15 +49,15 @@ sealed class OperatorSideEffect {
data class ConsumeMedia(val amount: Int) : OperatorSideEffect() {
override fun performEffect(harness: CastingVM): Boolean {
val leftoverMedia = harness.ctx.extractMedia(this.amount.toLong())
val leftoverMedia = harness.env.extractMedia(this.amount.toLong())
return leftoverMedia > 0
}
}
data class Particles(val spray: ParticleSpray) : OperatorSideEffect() {
override fun performEffect(harness: CastingVM): Boolean {
harness.ctx.produceParticles(this.spray, harness.ctx.colorizer)
this.spray.sprayParticles(harness.ctx.world, harness.getColorizer())
harness.env.produceParticles(this.spray, harness.env.colorizer)
this.spray.sprayParticles(harness.env.world, harness.env.colorizer)
return false
}
@ -65,18 +65,18 @@ sealed class OperatorSideEffect {
data class DoMishap(val mishap: Mishap, val errorCtx: Mishap.Context) : OperatorSideEffect() {
override fun performEffect(harness: CastingVM): Boolean {
val spray = mishap.particleSpray(harness.ctx)
val color = mishap.accentColor(harness.ctx, errorCtx)
spray.sprayParticles(harness.ctx.world, color)
val spray = mishap.particleSpray(harness.env)
val color = mishap.accentColor(harness.env, errorCtx)
spray.sprayParticles(harness.env.world, color)
spray.sprayParticles(
harness.ctx.world,
harness.env.world,
FrozenColorizer(
ItemStack(HexItems.DYE_COLORIZERS[DyeColor.RED]!!),
Util.NIL_UUID
)
)
mishap.execute(harness.ctx, errorCtx, harness.stack)
mishap.execute(harness.env, errorCtx, harness.image.stack.toMutableList())
return true
}

View file

@ -18,6 +18,7 @@ data class CastingImage private constructor(
val parenthesized: List<Iota>,
val escapeNext: Boolean,
val iterationSteps: Int,
val userData: CompoundTag
) {
public constructor() : this(listOf(), 0, listOf(), false, CompoundTag())
@ -32,12 +33,24 @@ data class CastingImage private constructor(
TAG_USERDATA %= userData
}
/**
* Throws if we get too deep.
*/
fun incDepth(): CastingImage {
val maxAllowedDepth = HexConfig.server().maxRecurseDepth()
if (this.iterationSteps + 1 > maxAllowedDepth) {
throw MishapEvalTooDeep()
}
return copy(iterationSteps = iterationSteps + 1)
}
companion object {
const val TAG_STACK = "stack"
const val TAG_PAREN_COUNT = "open_parens"
const val TAG_PARENTHESIZED = "parenthesized"
const val TAG_ESCAPE_NEXT = "escape_next"
const val TAG_USERDATA = "userdata"
const val TAG_RAVENMIND = "ravenmind"
@JvmStatic
public fun loadFromNbt(tag: CompoundTag, world: ServerLevel): CastingImage {
@ -65,8 +78,8 @@ data class CastingImage private constructor(
parenthesized.add(IotaType.deserialize(subtag.downcast(CompoundTag.TYPE), world))
}
val parenCount = tag.getInt(CastingVM.TAG_PAREN_COUNT)
val escapeNext = tag.getBoolean(CastingVM.TAG_ESCAPE_NEXT)
val parenCount = tag.getInt(TAG_PAREN_COUNT)
val escapeNext = tag.getBoolean(TAG_ESCAPE_NEXT)
CastingImage(stack, parenCount, parenthesized, escapeNext, userData)
} catch (exn: Exception) {
@ -75,4 +88,4 @@ data class CastingImage private constructor(
}
}
}
}
}

View file

@ -25,7 +25,7 @@ import net.minecraft.server.level.ServerLevel
* The virtual machine! This is the glue that determines the next iteration of a [CastingImage], using a
* [CastingEnvironment] to affect the world.
*/
class CastingVM(val image: CastingImage, val env: CastingEnvironment) {
class CastingVM(var image: CastingImage, val env: CastingEnvironment) {
/**
* Execute a single iota.
@ -51,7 +51,7 @@ class CastingVM(val image: CastingImage, val env: CastingEnvironment) {
val image2 = next.evaluate(continuation.next, world, this)
// Then write all pertinent data back to the harness for the next iteration.
if (image2.newData != null) {
this.applyFunctionalData(image2.newData)
this.image = image2.newData
}
this.env.postExecution(image2)
@ -172,25 +172,25 @@ class CastingVM(val image: CastingImage, val env: CastingEnvironment) {
val sideEffects = mutableListOf<OperatorSideEffect>()
var stack2: List<Iota>? = null
var cont2 = continuation
var ravenmind2: Iota? = null
var userData2: CompoundTag? = null
val result = action.operate(
this.ctx,
this.stack.toMutableList(),
this.ravenmind,
this.env,
this.image.stack.toMutableList(),
this.image.userData,
continuation
)
cont2 = result.newContinuation
stack2 = result.newStack
ravenmind2 = result.newRavenmind
userData2 = result.newUserdata
// TODO parens also break prescience
sideEffects.addAll(result.sideEffects)
val hereFd = this.getFunctionalData()
val hereFd = this.image
val fd = if (stack2 != null) {
hereFd.copy(
stack = stack2,
ravenmind = ravenmind2
userData = userData2,
)
} else {
hereFd
@ -201,7 +201,7 @@ class CastingVM(val image: CastingImage, val env: CastingEnvironment) {
fd,
sideEffects,
ResolvedPatternType.EVALUATED,
soundType,
env.soundType,
)
} catch (mishap: Mishap) {
@ -209,7 +209,7 @@ class CastingVM(val image: CastingImage, val env: CastingEnvironment) {
continuation,
null,
listOf(OperatorSideEffect.DoMishap(mishap, Mishap.Context(newPat, castedName))),
mishap.resolutionType(ctx),
mishap.resolutionType(env),
HexEvalSounds.MISHAP
)
}
@ -237,44 +237,21 @@ class CastingVM(val image: CastingImage, val env: CastingEnvironment) {
return Pair(stackDescs, ravenmind)
}
/**
* Return the functional update represented by the current state (for use with `copy`)
*/
fun getFunctionalData() = FunctionalData(
this.stack.toList(),
this.parenCount,
this.parenthesized.toList(),
this.escapeNext,
this.ravenmind,
)
/**
* Apply the functional update.
*/
fun applyFunctionalData(data: FunctionalData) {
this.stack.clear()
this.stack.addAll(data.stack)
this.parenCount = data.parenCount
this.parenthesized = data.parenthesized
this.escapeNext = data.escapeNext
this.ravenmind = data.ravenmind
}
/**
* Return a non-null value if we handled this in some sort of parenthesey way,
* either escaping it onto the stack or changing the parenthese-handling state.
*/
@Throws(MishapTooManyCloseParens::class)
private fun handleParentheses(iota: Iota): Pair<FunctionalData, ResolvedPatternType>? {
private fun handleParentheses(iota: Iota): Pair<CastingImage, ResolvedPatternType>? {
val sig = (iota as? PatternIota)?.pattern?.anglesSignature()
var displayDepth = this.parenCount
var displayDepth = this.image.parenCount
val out = if (this.parenCount > 0) {
if (this.escapeNext) {
val newParens = this.parenthesized.toMutableList()
val out = if (displayDepth > 0) {
if (this.image.escapeNext) {
val newParens = this.image.parenthesized.toMutableList()
newParens.add(iota)
this.getFunctionalData().copy(
this.image.copy(
escapeNext = false,
parenthesized = newParens
) to ResolvedPatternType.ESCAPED
@ -282,28 +259,28 @@ class CastingVM(val image: CastingImage, val env: CastingEnvironment) {
when (sig) {
SpecialPatterns.CONSIDERATION.anglesSignature() -> {
this.getFunctionalData().copy(
this.image.copy(
escapeNext = true,
) to ResolvedPatternType.EVALUATED
}
SpecialPatterns.INTROSPECTION.anglesSignature() -> {
// we have escaped the parens onto the stack; we just also record our count.
val newParens = this.parenthesized.toMutableList()
val newParens = this.image.parenthesized.toMutableList()
newParens.add(iota)
this.getFunctionalData().copy(
this.image.copy(
parenthesized = newParens,
parenCount = this.parenCount + 1
) to if (this.parenCount == 0) ResolvedPatternType.EVALUATED else ResolvedPatternType.ESCAPED
parenCount = this.image.parenCount + 1
) to if (this.image.parenCount == 0) ResolvedPatternType.EVALUATED else ResolvedPatternType.ESCAPED
}
SpecialPatterns.RETROSPECTION.anglesSignature() -> {
val newParenCount = this.parenCount - 1
val newParenCount = this.image.parenCount - 1
displayDepth--
if (newParenCount == 0) {
val newStack = this.stack.toMutableList()
newStack.add(ListIota(this.parenthesized.toList()))
this.getFunctionalData().copy(
val newStack = this.image.stack.toMutableList()
newStack.add(ListIota(this.image.parenthesized.toList()))
this.image.copy(
stack = newStack,
parenCount = newParenCount,
parenthesized = listOf()
@ -313,9 +290,9 @@ class CastingVM(val image: CastingImage, val env: CastingEnvironment) {
} else {
// we have this situation: "(()"
// we need to add the close paren
val newParens = this.parenthesized.toMutableList()
val newParens = this.image.parenthesized.toMutableList()
newParens.add(iota)
this.getFunctionalData().copy(
this.image.copy(
parenCount = newParenCount,
parenthesized = newParens
) to ResolvedPatternType.ESCAPED
@ -323,32 +300,32 @@ class CastingVM(val image: CastingImage, val env: CastingEnvironment) {
}
else -> {
val newParens = this.parenthesized.toMutableList()
val newParens = this.image.parenthesized.toMutableList()
newParens.add(iota)
this.getFunctionalData().copy(
this.image.copy(
parenthesized = newParens
) to ResolvedPatternType.ESCAPED
}
}
}
} else if (this.escapeNext) {
val newStack = this.stack.toMutableList()
} else if (this.image.escapeNext) {
val newStack = this.image.stack.toMutableList()
newStack.add(iota)
this.getFunctionalData().copy(
this.image.copy(
stack = newStack,
escapeNext = false,
) to ResolvedPatternType.ESCAPED
} else {
when (sig) {
SpecialPatterns.CONSIDERATION.anglesSignature() -> {
this.getFunctionalData().copy(
this.image.copy(
escapeNext = true
) to ResolvedPatternType.EVALUATED
}
SpecialPatterns.INTROSPECTION.anglesSignature() -> {
this.getFunctionalData().copy(
parenCount = this.parenCount + 1
this.image.copy(
parenCount = this.image.parenCount + 1
) to ResolvedPatternType.EVALUATED
}

View file

@ -23,7 +23,7 @@ object FrameFinishEval : ContinuationFrame {
): CastResult {
return CastResult(
continuation,
FunctionalData(harness.stack.toList(), 0, listOf(), false, harness.ravenmind),
null,
listOf(),
ResolvedPatternType.EVALUATED,
HexEvalSounds.NOTHING,
@ -33,4 +33,4 @@ object FrameFinishEval : ContinuationFrame {
override fun serializeToNBT() = NBTBuilder {
"type" %= "end"
}
}
}

View file

@ -43,33 +43,32 @@ data class FrameForEach(
// If this isn't the very first Thoth step (i.e. no Thoth computations run yet)...
val stack = if (baseStack == null) {
// init stack to the harness stack...
harness.stack.toList()
harness.image.stack.toList()
} else {
// else save the stack to the accumulator and reuse the saved base stack.
acc.addAll(harness.stack)
acc.addAll(harness.image.stack)
baseStack
}
// If we still have data to process...
val (stackTop, newCont) = if (data.nonEmpty) {
val (stackTop, newImage, newCont) = if (data.nonEmpty) {
// Increment the evaluation depth,
harness.ctx.incDepth()
// push the next datum to the top of the stack,
data.car to continuation
Triple(data.car, harness.image.incDepth(), continuation
// put the next Thoth object back on the stack for the next Thoth cycle,
.pushFrame(FrameForEach(data.cdr, code, stack, acc))
// and prep the Thoth'd code block for evaluation.
.pushFrame(FrameEvaluate(code, true))
.pushFrame(FrameEvaluate(code, true)))
} else {
// Else, dump our final list onto the stack.
ListIota(acc) to continuation
Triple(ListIota(acc), harness.image, continuation)
}
val tStack = stack.toMutableList()
tStack.add(stackTop)
// TODO: this means we could have Thoth casting do a different sound
return CastResult(
newCont,
FunctionalData(tStack, 0, listOf(), false, harness.ravenmind),
newImage.copy(stack = tStack),
listOf(),
ResolvedPatternType.EVALUATED,
HexEvalSounds.THOTH,
@ -84,4 +83,4 @@ data class FrameForEach(
"base" %= baseStack.serializeToNBT()
"accumulator" %= acc.serializeToNBT()
}
}
}

View file

@ -69,9 +69,14 @@ abstract class Mishap : Throwable() {
protected fun actionName(name: Component?): Component =
name ?: "hexcasting.spell.null".asTranslatedComponent.lightPurple
protected fun yeetHeldItemsTowards(env: CastingEnvironment, caster: ServerPlayer, targetPos: Vec3) {
protected fun yeetHeldItemsTowards(env: CastingEnvironment, targetPos: Vec3) {
// Knock the player's items out of their hands
val items = mutableListOf<ItemStack>()
val caster = env.caster
if (caster != null) {
// FIXME: handle null caster case
return
}
for (hand in InteractionHand.values()) {
items.add(caster.getItemInHand(hand).copy())
caster.setItemInHand(hand, ItemStack.EMPTY)

View file

@ -14,7 +14,8 @@ class MishapBadOffhandItem(val item: ItemStack, val hand: InteractionHand, val w
dyeColor(DyeColor.BROWN)
override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) {
yeetHeldItem(ctx, hand)
// FIXME: Missing implementation in mishap
//yeetHeldItem(ctx, hand)
}
override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = if (item.isEmpty)

View file

@ -19,7 +19,11 @@ class MishapDivideByZero(val operand1: Component, val operand2: Component, val s
override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) {
stack.add(GarbageIota())
trulyHurt(ctx.caster, HexDamageSources.OVERCAST, ctx.caster.health / 2)
val caster = ctx.caster
if (caster != null) {
// FIXME case where caster is null
trulyHurt(caster, HexDamageSources.OVERCAST, caster.health / 2)
}
}
override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) =

View file

@ -10,7 +10,11 @@ class MishapEvalTooDeep : Mishap() {
dyeColor(DyeColor.BLUE)
override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) {
ctx.caster.airSupply -= 290
// FIXME what if caster is null
val caster = ctx.caster
if (caster != null) {
caster.airSupply -= 290
}
}
override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) =

View file

@ -11,7 +11,11 @@ class MishapNoAkashicRecord(val pos: BlockPos) : Mishap() {
dyeColor(DyeColor.PURPLE)
override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) {
ctx.caster.giveExperiencePoints(-100)
val caster = ctx.caster
if (caster != null) {
// FIXME: handle null case
caster.giveExperiencePoints(-100)
}
}
override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) =

View file

@ -23,10 +23,14 @@ class MishapNoSpellCircle : Mishap() {
}
override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) {
dropAll(ctx.caster, ctx.caster.inventory.items)
dropAll(ctx.caster, ctx.caster.inventory.offhand)
dropAll(ctx.caster, ctx.caster.inventory.armor) {
!EnchantmentHelper.hasBindingCurse(it)
val caster = ctx.caster
if (caster != null) {
// FIXME: handle null caster case
dropAll(caster, caster.inventory.items)
dropAll(caster, caster.inventory.offhand)
dropAll(caster, caster.inventory.armor) {
!EnchantmentHelper.hasBindingCurse(it)
}
}
}

View file

@ -19,7 +19,11 @@ class MishapOthersName(val confidant: Player) : Mishap() {
override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) {
val seconds = if (this.confidant == ctx.caster) 5 else 60;
ctx.caster.addEffect(MobEffectInstance(MobEffects.BLINDNESS, seconds * 20))
val caster = ctx.caster
if (caster != null) {
// FIXME: handle null caster case
caster.addEffect(MobEffectInstance(MobEffects.BLINDNESS, seconds * 20))
}
}
override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) =

View file

@ -11,7 +11,11 @@ class MishapShameOnYou() : Mishap() {
dyeColor(DyeColor.BLACK)
override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList<Iota>) {
Mishap.trulyHurt(ctx.caster, HexDamageSources.SHAME, 69420f)
val caster = ctx.caster
if (caster != null) {
// FIXME: handle null caster case
Mishap.trulyHurt(caster, HexDamageSources.SHAME, 69420f)
}
}
override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = error("shame")

View file

@ -33,6 +33,7 @@ import net.minecraft.world.InteractionHand
import net.minecraft.world.phys.Vec2
import kotlin.math.*
// TODO winfy: fix this class to use ExecutionClientView
class GuiSpellcasting constructor(
private val handOpenedWith: InteractionHand,
private var patterns: MutableList<ResolvedPattern>,

View file

@ -11,10 +11,11 @@ class OpCircleBounds(val max: Boolean) : ConstMediaAction {
override val argc = 0
override fun execute(args: List<Iota>, ctx: CastingEnvironment): List<Iota> {
if (ctx.spellCircle == null)
val circle = ctx.spellCircle
if (circle == null)
throw MishapNoSpellCircle()
val aabb = ctx.spellCircle.aabb
val aabb = circle.aabb
return if (max)
Vec3(aabb.maxX - 0.5, aabb.maxY - 0.5, aabb.maxZ - 0.5).asActionResult

View file

@ -11,10 +11,11 @@ object OpImpetusDir : ConstMediaAction {
override val argc = 0
override fun execute(args: List<Iota>, ctx: CastingEnvironment): List<Iota> {
if (ctx.spellCircle == null)
val circle = ctx.spellCircle
if (circle == null)
throw MishapNoSpellCircle()
val pos = ctx.spellCircle.impetusPos
val pos = circle.impetusPos
val bs = ctx.world.getBlockState(pos)
val dir = bs.getValue(BlockAbstractImpetus.FACING)
return dir.step().asActionResult

View file

@ -10,9 +10,10 @@ object OpImpetusPos : ConstMediaAction {
override val argc = 0
override fun execute(args: List<Iota>, ctx: CastingEnvironment): List<Iota> {
if (ctx.spellCircle == null)
val circle = ctx.spellCircle
if (circle == null)
throw MishapNoSpellCircle()
return ctx.spellCircle.impetusPos.asActionResult
return circle.impetusPos.asActionResult
}
}

View file

@ -23,8 +23,9 @@ object OpEval : Action {
val datum = stack.removeLastOrNull() ?: throw MishapNotEnoughArgs(1, 0)
val instrs = evaluatable(datum, 0)
instrs.ifRight {
env.incDepth()
val stack = instrs.ifRight {
// FIXME: Casting depth increment not implemented yet
//env.incDepth()
}
// if not installed already...

View file

@ -15,7 +15,9 @@ object OpPeekLocal : Action {
userData: CompoundTag,
continuation: SpellContinuation
): OperationResult {
stack.add(userData.orNull())
// TODO winfy: figure out ravenmind semantics
stack.add(userData.getCompound(CastingEnvironment.TAG_RAVENMIND))
//IotaType.deserialize(subtag.downcast(CompoundTag.TYPE), world)
return OperationResult(stack, userData, listOf(), continuation)
}
}

View file

@ -15,9 +15,10 @@ object OpPushLocal : Action {
userData: CompoundTag,
continuation: SpellContinuation
): OperationResult {
// TODO winfy: figure out ravenmind semantics
if (stack.isEmpty())
throw MishapNotEnoughArgs(1, 0)
val newLocal = stack.removeLast()
val newLocal = stack.removeLast().serialize()
return OperationResult(stack, newLocal, listOf(), continuation)
}
}

View file

@ -36,10 +36,11 @@ object OpColorize : SpellAction {
private data class Spell(val stack: ItemStack) : RenderedSpell {
override fun cast(ctx: CastingEnvironment) {
val copy = stack.copy()
if (ctx.withdrawItem(copy, 1, true)) {
val caster = ctx.caster
if (caster != null && ctx.withdrawItem(copy::equals, 1, true)) {
IXplatAbstractions.INSTANCE.setColorizer(
ctx.caster,
FrozenColorizer(copy, ctx.caster.uuid)
FrozenColorizer(copy, caster.uuid)
)
}
}