Bring down the error count hopefully
This commit is contained in:
parent
7b0813d1b6
commit
a7a5073a74
23 changed files with 179 additions and 115 deletions
|
@ -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,
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) =
|
||||
|
|
|
@ -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) =
|
||||
|
|
|
@ -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) =
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) =
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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...
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue