made Evanition interact properly with unescaped and escaped introspection/retrospections.
This commit is contained in:
parent
798bb79acb
commit
e50f233176
|
@ -1,10 +1,14 @@
|
|||
package at.petrak.hexcasting.api.casting.eval.vm
|
||||
|
||||
import at.petrak.hexcasting.api.HexAPI
|
||||
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage.ParenthesizedIota.Companion.TAG_ESCAPED
|
||||
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage.ParenthesizedIota.Companion.TAG_IOTAS
|
||||
import at.petrak.hexcasting.api.casting.iota.Iota
|
||||
import at.petrak.hexcasting.api.casting.iota.IotaType
|
||||
import at.petrak.hexcasting.api.casting.iota.ListIota
|
||||
import at.petrak.hexcasting.api.utils.*
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.nbt.Tag
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.Entity
|
||||
|
@ -16,7 +20,7 @@ data class CastingImage private constructor(
|
|||
val stack: List<Iota>,
|
||||
|
||||
val parenCount: Int,
|
||||
val parenthesized: List<Iota>,
|
||||
val parenthesized: List<ParenthesizedIota>,
|
||||
val escapeNext: Boolean,
|
||||
val opsConsumed: Long,
|
||||
|
||||
|
@ -24,6 +28,30 @@ data class CastingImage private constructor(
|
|||
) {
|
||||
constructor() : this(listOf(), 0, listOf(), false, 0, CompoundTag())
|
||||
|
||||
data class ParenthesizedIota(val iota: Iota, val escaped: Boolean) {
|
||||
companion object {
|
||||
const val TAG_IOTAS = "iotas"
|
||||
const val TAG_ESCAPED = "escaped"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty list if it's too complicated.
|
||||
*/
|
||||
private fun Iterable<ParenthesizedIota>.serializeToNBT(): CompoundTag {
|
||||
val tag = CompoundTag()
|
||||
|
||||
if (IotaType.isTooLargeToSerialize(this.map { it.iota })) {
|
||||
tag.put(TAG_IOTAS, ListTag())
|
||||
tag.put(TAG_ESCAPED, ListTag())
|
||||
} else {
|
||||
tag.put(TAG_IOTAS, ListIota(this.map { it.iota }).serialize())
|
||||
tag.put(TAG_ESCAPED, this.map { it.escaped }.serializeToNBT())
|
||||
}
|
||||
|
||||
return tag
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a copy of this with the given number of ops additionally exhausted
|
||||
*/
|
||||
|
@ -74,10 +102,13 @@ data class CastingImage private constructor(
|
|||
CompoundTag()
|
||||
}
|
||||
|
||||
val parenthesized = mutableListOf<Iota>()
|
||||
val parenTag = tag.getList(TAG_PARENTHESIZED, Tag.TAG_COMPOUND)
|
||||
for (subtag in parenTag) {
|
||||
parenthesized.add(IotaType.deserialize(subtag.downcast(CompoundTag.TYPE), world))
|
||||
val parenthesized = mutableListOf<ParenthesizedIota>()
|
||||
val parenTag = tag.getCompound(TAG_PARENTHESIZED)
|
||||
val parenIotasTag = parenTag.getList(TAG_IOTAS, Tag.TAG_COMPOUND)
|
||||
val parenEscapedTag = parenTag.getByteArray(TAG_ESCAPED)
|
||||
|
||||
for ((subtag, isEscapedByte) in parenIotasTag.zipWithDefault(parenEscapedTag) { _ -> 0 }) {
|
||||
parenthesized.add(ParenthesizedIota(IotaType.deserialize(subtag.downcast(CompoundTag.TYPE), world), isEscapedByte != 0.toByte()))
|
||||
}
|
||||
|
||||
val parenCount = tag.getInt(TAG_PAREN_COUNT)
|
||||
|
|
|
@ -5,6 +5,7 @@ import at.petrak.hexcasting.api.casting.PatternShapeMatch.*
|
|||
import at.petrak.hexcasting.api.casting.SpellList
|
||||
import at.petrak.hexcasting.api.casting.eval.*
|
||||
import at.petrak.hexcasting.api.casting.eval.sideeffects.OperatorSideEffect
|
||||
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage.ParenthesizedIota
|
||||
import at.petrak.hexcasting.api.casting.iota.Iota
|
||||
import at.petrak.hexcasting.api.casting.iota.IotaType
|
||||
import at.petrak.hexcasting.api.casting.iota.ListIota
|
||||
|
@ -156,7 +157,7 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) {
|
|||
val out = if (displayDepth > 0) {
|
||||
if (this.image.escapeNext) {
|
||||
val newParens = this.image.parenthesized.toMutableList()
|
||||
newParens.add(iota)
|
||||
newParens.add(ParenthesizedIota(iota, true))
|
||||
this.image.copy(
|
||||
escapeNext = false,
|
||||
parenthesized = newParens
|
||||
|
@ -173,13 +174,18 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) {
|
|||
SpecialPatterns.EVANITION.anglesSignature() -> {
|
||||
val newParens = this.image.parenthesized.toMutableList()
|
||||
val last = newParens.removeLastOrNull()
|
||||
this.image.copy(parenthesized = newParens) to if (last == null) ResolvedPatternType.ERRORED else ResolvedPatternType.UNDONE
|
||||
val newParenCount = this.image.parenCount + if (last == null || last.escaped || last.iota !is PatternIota) 0 else when (last.iota.pattern) {
|
||||
SpecialPatterns.INTROSPECTION -> -1
|
||||
SpecialPatterns.RETROSPECTION -> 1
|
||||
else -> -1
|
||||
}
|
||||
this.image.copy(parenthesized = newParens, parenCount = newParenCount) to if (last == null) ResolvedPatternType.ERRORED else ResolvedPatternType.UNDONE
|
||||
}
|
||||
|
||||
SpecialPatterns.INTROSPECTION.anglesSignature() -> {
|
||||
// we have escaped the parens onto the stack; we just also record our count.
|
||||
val newParens = this.image.parenthesized.toMutableList()
|
||||
newParens.add(iota)
|
||||
newParens.add(ParenthesizedIota(iota, false))
|
||||
this.image.copy(
|
||||
parenthesized = newParens,
|
||||
parenCount = this.image.parenCount + 1
|
||||
|
@ -191,7 +197,7 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) {
|
|||
displayDepth--
|
||||
if (newParenCount == 0) {
|
||||
val newStack = this.image.stack.toMutableList()
|
||||
newStack.add(ListIota(this.image.parenthesized.toList()))
|
||||
newStack.add(ListIota(this.image.parenthesized.toList().map { it.iota }))
|
||||
this.image.copy(
|
||||
stack = newStack,
|
||||
parenCount = newParenCount,
|
||||
|
@ -203,7 +209,7 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) {
|
|||
// we have this situation: "(()"
|
||||
// we need to add the close paren
|
||||
val newParens = this.image.parenthesized.toMutableList()
|
||||
newParens.add(iota)
|
||||
newParens.add(ParenthesizedIota(iota, false))
|
||||
this.image.copy(
|
||||
parenCount = newParenCount,
|
||||
parenthesized = newParens
|
||||
|
@ -213,7 +219,7 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) {
|
|||
|
||||
else -> {
|
||||
val newParens = this.image.parenthesized.toMutableList()
|
||||
newParens.add(iota)
|
||||
newParens.add(ParenthesizedIota(iota, false))
|
||||
this.image.copy(
|
||||
parenthesized = newParens
|
||||
) to ResolvedPatternType.ESCAPED
|
||||
|
|
|
@ -267,6 +267,22 @@ fun Iterable<Iota>.serializeToNBT() =
|
|||
else
|
||||
ListIota(this.toList()).serialize()
|
||||
|
||||
fun Iterable<Boolean>.serializeToNBT(): ByteArrayTag {
|
||||
val out = ByteArray(if (this is Collection<*>) this.size else 10)
|
||||
for ((i, b) in this.withIndex()) {
|
||||
out[i] = if (b) 1 else 0
|
||||
}
|
||||
return ByteArrayTag(out)
|
||||
}
|
||||
|
||||
fun <A> List<A>.zipWithDefault(array: ByteArray, default: (idx: Int) -> Byte): List<Pair<A, Byte>> {
|
||||
val list = ArrayList<Pair<A, Byte>>(this.size)
|
||||
var i = 0
|
||||
for (element in this) list.add(element to array.getOrElse(i++, default))
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
// Copy the impl from forge
|
||||
fun ItemStack.serializeToNBT(): CompoundTag {
|
||||
val out = CompoundTag()
|
||||
|
|
|
@ -69,7 +69,7 @@ class GuiSpellcasting constructor(
|
|||
|
||||
// TODO this is the kinda hacky bit
|
||||
if (info.resolutionType == ResolvedPatternType.UNDONE) {
|
||||
this.patterns.getOrNull(index - 1)?.let { it.type = ResolvedPatternType.UNDONE }
|
||||
this.patterns.reversed().drop(1).firstOrNull { it.type == ResolvedPatternType.ESCAPED }?.let { it.type = ResolvedPatternType.UNDONE }
|
||||
this.patterns.getOrNull(index)?.let { it.type = ResolvedPatternType.EVALUATED }
|
||||
} else this.patterns.getOrNull(index)?.let {
|
||||
it.type = info.resolutionType
|
||||
|
|
Loading…
Reference in a new issue