and now for the part of the show where we refactor every single operator
This commit is contained in:
parent
8261063208
commit
71c3cade9b
20 changed files with 275 additions and 147 deletions
|
@ -5,10 +5,10 @@ import at.petrak.hexcasting.api.misc.FrozenColorizer;
|
|||
import at.petrak.hexcasting.api.misc.ManaConstants;
|
||||
import at.petrak.hexcasting.api.mod.HexConfig;
|
||||
import at.petrak.hexcasting.api.spell.ParticleSpray;
|
||||
import at.petrak.hexcasting.api.spell.iota.Iota;
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext;
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingHarness;
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellCircleContext;
|
||||
import at.petrak.hexcasting.api.spell.iota.PatternIota;
|
||||
import at.petrak.hexcasting.api.utils.ManaHelper;
|
||||
import at.petrak.hexcasting.common.lib.HexItems;
|
||||
import at.petrak.hexcasting.common.lib.HexSounds;
|
||||
|
@ -287,7 +287,7 @@ public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implemen
|
|||
if (bs.getBlock() instanceof BlockCircleComponent cc) {
|
||||
var newPattern = cc.getPattern(tracked, bs, this.level);
|
||||
if (newPattern != null) {
|
||||
var info = harness.executeIota(LegacySpellDatum.make(newPattern), splayer.getLevel());
|
||||
var info = harness.executeIota(new PatternIota(newPattern), splayer.getLevel());
|
||||
if (info.getMakesCastSound()) {
|
||||
makeSound = true;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package at.petrak.hexcasting.api.spell
|
||||
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import at.petrak.hexcasting.api.spell.iota.Iota
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
||||
|
||||
/**
|
||||
|
@ -15,7 +16,12 @@ interface ConstManaOperator : Operator {
|
|||
|
||||
fun execute(args: List<Iota>, ctx: CastingContext): List<Iota>
|
||||
|
||||
override fun operate(continuation: SpellContinuation, stack: MutableList<Iota>, local: Iota, ctx: CastingContext): OperationResult {
|
||||
override fun operate(
|
||||
continuation: SpellContinuation,
|
||||
stack: MutableList<Iota>,
|
||||
local: Iota,
|
||||
ctx: CastingContext
|
||||
): OperationResult {
|
||||
if (this.argc > stack.size)
|
||||
throw MishapNotEnoughArgs(this.argc, stack.size)
|
||||
val args = stack.takeLast(this.argc)
|
||||
|
|
|
@ -2,6 +2,7 @@ package at.petrak.hexcasting.api.spell
|
|||
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import at.petrak.hexcasting.api.spell.iota.Iota
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
|
@ -21,7 +22,12 @@ interface Operator {
|
|||
*
|
||||
* A particle effect at the cast site and various messages and advancements are done automagically.
|
||||
*/
|
||||
fun operate(continuation: SpellContinuation, stack: MutableList<Iota>, local: Iota, ctx: CastingContext): OperationResult
|
||||
fun operate(
|
||||
continuation: SpellContinuation,
|
||||
stack: MutableList<Iota>,
|
||||
local: Iota,
|
||||
ctx: CastingContext
|
||||
): OperationResult
|
||||
|
||||
/**
|
||||
* Do you need to be enlightened to use this operator? (i.e. is this operator a Great Pattern)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
package at.petrak.hexcasting.api.spell
|
||||
|
||||
import at.petrak.hexcasting.api.spell.iota.*
|
||||
import at.petrak.hexcasting.api.spell.math.HexPattern
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidIota
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
||||
|
@ -9,14 +10,20 @@ import at.petrak.hexcasting.api.utils.asTranslatedComponent
|
|||
import com.mojang.datafixers.util.Either
|
||||
import com.mojang.math.Vector3f
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.item.ItemEntity
|
||||
import net.minecraft.world.entity.npc.Villager
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.math.roundToLong
|
||||
|
||||
fun numOrVec(datum: Iota, reverseIdx: Int): Either<Double, Vec3> =
|
||||
when (datum.payload) {
|
||||
is Double -> Either.left(datum.payload)
|
||||
is Vec3 -> Either.right(datum.payload)
|
||||
when (datum) {
|
||||
is DoubleIota -> Either.left(datum.double)
|
||||
is Vec3Iota -> Either.right(datum.vec3)
|
||||
else -> throw MishapInvalidIota(
|
||||
datum,
|
||||
reverseIdx,
|
||||
|
@ -25,9 +32,9 @@ fun numOrVec(datum: Iota, reverseIdx: Int): Either<Double, Vec3> =
|
|||
}
|
||||
|
||||
fun numOrList(datum: Iota, reverseIdx: Int): Either<Double, SpellList> =
|
||||
when (datum.payload) {
|
||||
is Double -> Either.left(datum.payload)
|
||||
is SpellList -> Either.right(datum.payload)
|
||||
when (datum) {
|
||||
is DoubleIota -> Either.left(datum.double)
|
||||
is ListIota -> Either.right(datum.list)
|
||||
else -> throw MishapInvalidIota(
|
||||
datum,
|
||||
reverseIdx,
|
||||
|
@ -35,38 +42,176 @@ fun numOrList(datum: Iota, reverseIdx: Int): Either<Double, SpellList> =
|
|||
)
|
||||
}
|
||||
|
||||
fun spellListOf(vararg vs: Any): List<Iota> {
|
||||
val out = ArrayList<Iota>(vs.size)
|
||||
for (v in vs) {
|
||||
out.add(LegacySpellDatum.make(v))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
inline fun <reified T : Any> List<Iota>.getChecked(idx: Int, argc: Int = 0): T {
|
||||
fun List<Iota>.getDouble(idx: Int, argc: Int = 0): Double {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x.payload is T)
|
||||
return x.payload
|
||||
else
|
||||
throw MishapInvalidIota.ofClass(x, if (argc == 0) idx else argc - (idx + 1), T::class.java)
|
||||
if (x is DoubleIota) {
|
||||
return x.double
|
||||
} else {
|
||||
throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "double")
|
||||
}
|
||||
}
|
||||
|
||||
fun List<Iota>.getEntity(idx: Int, argc: Int = 0): Entity {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x is EntityIota) {
|
||||
return x.entity
|
||||
} else {
|
||||
throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity")
|
||||
}
|
||||
}
|
||||
|
||||
inline val Boolean.asSpellResult get() = spellListOf(if (this) 1.0 else 0.0)
|
||||
inline val Double.asSpellResult get() = spellListOf(this)
|
||||
inline val Number.asSpellResult get() = spellListOf(this.toDouble())
|
||||
fun List<Iota>.getList(idx: Int, argc: Int = 0): SpellList {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x is ListIota) {
|
||||
return x.list
|
||||
} else {
|
||||
throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "list")
|
||||
}
|
||||
}
|
||||
|
||||
inline val SpellList.asSpellResult get() = spellListOf(this)
|
||||
inline val List<Iota>.asSpellResult get() = spellListOf(this)
|
||||
fun List<Iota>.getPattern(idx: Int, argc: Int = 0): HexPattern {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x is PatternIota) {
|
||||
return x.pattern
|
||||
} else {
|
||||
throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "pattern")
|
||||
}
|
||||
}
|
||||
|
||||
inline val Widget.asSpellResult get() = spellListOf(this)
|
||||
fun List<Iota>.getVec3(idx: Int, argc: Int = 0): Vec3 {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x is Vec3Iota) {
|
||||
return x.vec3
|
||||
} else {
|
||||
throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "vector")
|
||||
}
|
||||
}
|
||||
|
||||
inline val BlockPos.asSpellResult get() = spellListOf(Vec3.atCenterOf(this))
|
||||
inline val Vector3f.asSpellResult get() = spellListOf(Vec3(this))
|
||||
inline val Vec3.asSpellResult get() = spellListOf(this)
|
||||
// Helpers
|
||||
|
||||
inline val Entity?.asSpellResult get() = spellListOf(this ?: Widget.NULL)
|
||||
inline val HexPattern.asSpellResult get() = spellListOf(this)
|
||||
fun List<Iota>.getItemEntity(idx: Int, argc: Int = 0): ItemEntity {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x is EntityIota) {
|
||||
val e = x.entity
|
||||
if (e is ItemEntity)
|
||||
return e
|
||||
}
|
||||
throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.item")
|
||||
}
|
||||
|
||||
fun List<Iota>.getPlayer(idx: Int, argc: Int = 0): ServerPlayer {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x is EntityIota) {
|
||||
val e = x.entity
|
||||
if (e is ServerPlayer)
|
||||
return e
|
||||
}
|
||||
throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.player")
|
||||
}
|
||||
|
||||
fun List<Iota>.getVillager(idx: Int, argc: Int = 0): Villager {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x is EntityIota) {
|
||||
val e = x.entity
|
||||
if (e is Villager)
|
||||
return e
|
||||
}
|
||||
throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.villager")
|
||||
}
|
||||
|
||||
fun List<Iota>.getLivingEntity(idx: Int, argc: Int = 0): LivingEntity {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x is EntityIota) {
|
||||
val e = x.entity
|
||||
if (e is LivingEntity)
|
||||
return e
|
||||
}
|
||||
throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.living")
|
||||
}
|
||||
|
||||
fun List<Iota>.getPositiveDoubleB(idx: Int, argc: Int = 0): Double {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x is DoubleIota) {
|
||||
val double = x.double
|
||||
if (0 <= double) {
|
||||
return double
|
||||
}
|
||||
}
|
||||
throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "double.positive")
|
||||
}
|
||||
|
||||
fun List<Iota>.getDoubleBetween(idx: Int, min: Double, max: Double, argc: Int = 0): Double {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x is DoubleIota) {
|
||||
val double = x.double
|
||||
if (double in min..max) {
|
||||
return double
|
||||
}
|
||||
}
|
||||
throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "double.between", min, max)
|
||||
}
|
||||
|
||||
fun List<Iota>.getInt(idx: Int, argc: Int = 0): Int {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x is DoubleIota) {
|
||||
val double = x.double
|
||||
val rounded = double.roundToInt()
|
||||
if (abs(double - rounded) <= DoubleIota.TOLERANCE) {
|
||||
return rounded
|
||||
}
|
||||
}
|
||||
throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "int")
|
||||
}
|
||||
|
||||
fun List<Iota>.getLong(idx: Int, argc: Int = 0): Long {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x is DoubleIota) {
|
||||
val double = x.double
|
||||
val rounded = double.roundToLong()
|
||||
if (abs(double - rounded) <= DoubleIota.TOLERANCE) {
|
||||
return rounded
|
||||
}
|
||||
}
|
||||
throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "int") // shh we're lying
|
||||
}
|
||||
|
||||
fun List<Iota>.getPositiveInt(idx: Int, argc: Int = 0): Int {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x is DoubleIota) {
|
||||
val double = x.double
|
||||
val rounded = double.roundToInt()
|
||||
if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded > 0) {
|
||||
return rounded
|
||||
}
|
||||
}
|
||||
throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "int.positive")
|
||||
}
|
||||
|
||||
fun List<Iota>.getIntBetween(idx: Int, min: Int, max: Int, argc: Int = 0): Int {
|
||||
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
|
||||
if (x is DoubleIota) {
|
||||
val double = x.double
|
||||
val rounded = double.roundToInt()
|
||||
if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in min..max) {
|
||||
return rounded
|
||||
}
|
||||
}
|
||||
throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "double.between", min, max)
|
||||
}
|
||||
|
||||
inline val Boolean.asSpellResult get() = listOf(DoubleIota(if (this) 1.0 else 0.0))
|
||||
inline val Double.asSpellResult get() = listOf(DoubleIota(this))
|
||||
inline val Number.asSpellResult get() = listOf(DoubleIota(this.toDouble()))
|
||||
|
||||
inline val SpellList.asSpellResult get() = listOf(ListIota(this))
|
||||
inline val List<Iota>.asSpellResult get() = listOf(ListIota(this))
|
||||
|
||||
inline val BlockPos.asSpellResult get() = listOf(Vec3Iota(Vec3.atCenterOf(this)))
|
||||
inline val Vector3f.asSpellResult get() = listOf(Vec3Iota(Vec3(this)))
|
||||
inline val Vec3.asSpellResult get() = listOf(Vec3Iota(this))
|
||||
|
||||
inline val Entity?.asSpellResult get() = listOf(if (this == null) NullIota.INSTANCE else EntityIota(this))
|
||||
inline val HexPattern.asSpellResult get() = listOf(PatternIota(this))
|
||||
|
||||
private const val TOLERANCE = 0.0001
|
||||
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
package at.petrak.hexcasting.api.spell
|
||||
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Miscellaneous spell datums used as markers, etc.
|
||||
*
|
||||
* They act as operators that push themselves.
|
||||
*/
|
||||
enum class Widget : ConstManaOperator {
|
||||
NULL,
|
||||
OPEN_PAREN, CLOSE_PAREN, ESCAPE,
|
||||
GARBAGE;
|
||||
|
||||
override val argc: Int
|
||||
get() = 0
|
||||
|
||||
override fun execute(args: List<Iota>, ctx: CastingContext): List<Iota> =
|
||||
this.asSpellResult
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun fromString(key: String): Widget {
|
||||
val lowercaseKey = key.lowercase(Locale.ROOT)
|
||||
return values().firstOrNull { it.name.lowercase(Locale.ROOT) == lowercaseKey } ?: GARBAGE
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,8 +8,12 @@ import at.petrak.hexcasting.api.misc.HexDamageSources
|
|||
import at.petrak.hexcasting.api.mod.HexConfig
|
||||
import at.petrak.hexcasting.api.mod.HexItemTags
|
||||
import at.petrak.hexcasting.api.mod.HexStatistics
|
||||
import at.petrak.hexcasting.api.spell.*
|
||||
import at.petrak.hexcasting.api.spell.Operator
|
||||
import at.petrak.hexcasting.api.spell.ParticleSpray
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.Widget
|
||||
import at.petrak.hexcasting.api.spell.iota.Iota
|
||||
import at.petrak.hexcasting.api.spell.iota.ListIota
|
||||
import at.petrak.hexcasting.api.spell.iota.NullIota
|
||||
import at.petrak.hexcasting.api.spell.iota.PatternIota
|
||||
import at.petrak.hexcasting.api.spell.math.HexDir
|
||||
|
@ -17,6 +21,7 @@ import at.petrak.hexcasting.api.spell.math.HexPattern
|
|||
import at.petrak.hexcasting.api.spell.mishaps.*
|
||||
import at.petrak.hexcasting.api.utils.*
|
||||
import at.petrak.hexcasting.common.items.magic.ItemCreativeUnlocker
|
||||
import at.petrak.hexcasting.common.lib.HexIotaTypes
|
||||
import at.petrak.hexcasting.xplat.IXplatAbstractions
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.Tag
|
||||
|
@ -240,7 +245,7 @@ class CastingHarness private constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun generateDescs() = stack.map { it.type.display(it) }
|
||||
fun generateDescs() = stack.map(Iota::display)
|
||||
|
||||
/**
|
||||
* Return the functional update represented by the current state (for use with `copy`)
|
||||
|
@ -300,7 +305,7 @@ class CastingHarness private constructor(
|
|||
val newParenCount = this.parenCount - 1
|
||||
if (newParenCount == 0) {
|
||||
val newStack = this.stack.toMutableList()
|
||||
newStack.add(LegacySpellDatum.make(this.parenthesized.toList()))
|
||||
newStack.add(ListIota(this.parenthesized.toList()))
|
||||
this.getFunctionalData().copy(
|
||||
stack = newStack,
|
||||
parenCount = newParenCount,
|
||||
|
@ -438,7 +443,7 @@ class CastingHarness private constructor(
|
|||
fun serializeToNBT() = NBTBuilder {
|
||||
TAG_STACK %= stack.serializeToNBT()
|
||||
|
||||
TAG_LOCAL %= ravenmind.serializeToNBT()
|
||||
TAG_LOCAL %= HexIotaTypes.serialize(ravenmind)
|
||||
TAG_PAREN_COUNT %= parenCount
|
||||
TAG_ESCAPE_NEXT %= escapeNext
|
||||
|
||||
|
@ -463,23 +468,16 @@ class CastingHarness private constructor(
|
|||
val stack = mutableListOf<Iota>()
|
||||
val stackTag = nbt.getList(TAG_STACK, Tag.TAG_COMPOUND)
|
||||
for (subtag in stackTag) {
|
||||
val datum = LegacySpellDatum.fromNBT(subtag.asCompound, ctx.world)
|
||||
val datum = HexIotaTypes.deserialize(subtag.asCompound, ctx.world)
|
||||
stack.add(datum)
|
||||
}
|
||||
|
||||
val localTag = nbt.getCompound(TAG_LOCAL)
|
||||
val localIota =
|
||||
if (localTag.size() == 1) LegacySpellDatum.fromNBT(localTag, ctx.world) else LegacySpellDatum.make(
|
||||
Widget.NULL
|
||||
)
|
||||
val localIota = HexIotaTypes.deserialize(nbt.getCompound(TAG_LOCAL), ctx.world)
|
||||
|
||||
val parenthesized = mutableListOf<Iota>()
|
||||
val parenTag = nbt.getList(TAG_PARENTHESIZED, Tag.TAG_COMPOUND)
|
||||
for (subtag in parenTag) {
|
||||
if (subtag.asCompound.size() != 1)
|
||||
parenthesized.add(LegacySpellDatum.make(HexPattern.fromNBT(subtag.asCompound)))
|
||||
else
|
||||
parenthesized.add(LegacySpellDatum.fromNBT(subtag.asCompound, ctx.world))
|
||||
parenthesized.add(HexIotaTypes.deserialize(nbt.getCompound(TAG_LOCAL), ctx.world))
|
||||
}
|
||||
|
||||
val parenCount = nbt.getInt(TAG_PAREN_COUNT)
|
||||
|
|
|
@ -127,7 +127,7 @@ sealed interface ContinuationFrame {
|
|||
override fun breakDownwards(stack: List<Iota>): Pair<Boolean, List<Iota>> {
|
||||
val newStack = baseStack?.toMutableList() ?: mutableListOf()
|
||||
acc.addAll(stack)
|
||||
newStack.add(ListIota(SpellList.LList(acc)))
|
||||
newStack.add(ListIota(acc))
|
||||
return true to newStack
|
||||
}
|
||||
|
||||
|
@ -157,7 +157,7 @@ sealed interface ContinuationFrame {
|
|||
.pushFrame(Evaluate(code))
|
||||
} else {
|
||||
// Else, dump our final list onto the stack.
|
||||
ListIota(SpellList.LList(acc)) to continuation
|
||||
ListIota(acc) to continuation
|
||||
}
|
||||
val tStack = stack.toMutableList()
|
||||
tStack.add(stackTop)
|
||||
|
|
|
@ -13,7 +13,7 @@ import org.jetbrains.annotations.NotNull;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class EntityIota extends Iota {
|
||||
protected EntityIota(@NotNull Entity e) {
|
||||
public EntityIota(@NotNull Entity e) {
|
||||
super(HexIotaTypes.ENTITY, e);
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,11 @@ public class EntityIota extends Iota {
|
|||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component display() {
|
||||
return this.getEntity().getName();
|
||||
}
|
||||
|
||||
public static IotaType<EntityIota> TYPE = new IotaType<>() {
|
||||
@Nullable
|
||||
@Override
|
||||
|
@ -65,11 +70,6 @@ public class EntityIota extends Iota {
|
|||
return Component.Serializer.fromJsonLenient(nameJson);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component display(EntityIota iota) {
|
||||
return iota.getEntity().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int color() {
|
||||
return 0;
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
public class GarbageIota extends Iota {
|
||||
private static final Object NULL_SUBSTITUTE = new Object();
|
||||
|
||||
public static final GarbageIota INSTANCE = new GarbageIota();
|
||||
|
||||
public GarbageIota() {
|
||||
// We have to pass *something* here, but there's nothing that actually needs to go there,
|
||||
|
|
|
@ -2,13 +2,14 @@ package at.petrak.hexcasting.api.spell.iota;
|
|||
|
||||
import at.petrak.hexcasting.common.lib.HexIotaTypes;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class Iota {
|
||||
@NotNull
|
||||
protected final Object payload;
|
||||
@NotNull
|
||||
private final IotaType<?> type;
|
||||
protected final IotaType<?> type;
|
||||
|
||||
protected Iota(@NotNull IotaType<?> type, @NotNull Object payload) {
|
||||
this.type = type;
|
||||
|
@ -37,6 +38,10 @@ public abstract class Iota {
|
|||
*/
|
||||
abstract public @NotNull Tag serialize();
|
||||
|
||||
public Component display() {
|
||||
return this.type.display(this.serialize());
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to see if two iotas have the same type.
|
||||
*/
|
||||
|
|
|
@ -26,10 +26,6 @@ public abstract class IotaType<T extends Iota> {
|
|||
*/
|
||||
public abstract Component display(Tag tag);
|
||||
|
||||
public Component display(T iota) {
|
||||
return this.display(iota.serialize());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the color associated with this datum type.
|
||||
*/
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.jetbrains.annotations.NotNull;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This is a <i>wrapper</i> for {@link SpellList}.
|
||||
|
@ -21,6 +22,10 @@ public class ListIota extends Iota {
|
|||
super(HexIotaTypes.LIST, list);
|
||||
}
|
||||
|
||||
public ListIota(@NotNull List<Iota> list) {
|
||||
this(new SpellList.LList(list));
|
||||
}
|
||||
|
||||
public SpellList getList() {
|
||||
return (SpellList) this.payload;
|
||||
}
|
||||
|
@ -78,7 +83,7 @@ public class ListIota extends Iota {
|
|||
out.add(subiota);
|
||||
}
|
||||
|
||||
return new ListIota(new SpellList.LList(out));
|
||||
return new ListIota(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -14,6 +14,8 @@ import org.jetbrains.annotations.Nullable;
|
|||
public class NullIota extends Iota {
|
||||
private static final Object NULL_SUBSTITUTE = new Object();
|
||||
|
||||
public static final NullIota INSTANCE = new NullIota();
|
||||
|
||||
public NullIota() {
|
||||
// We have to pass *something* here, but there's nothing that actually needs to go there,
|
||||
// so we just do this i guess
|
||||
|
|
|
@ -2,9 +2,11 @@ package at.petrak.hexcasting.api.spell.mishaps
|
|||
|
||||
import at.petrak.hexcasting.api.misc.FrozenColorizer
|
||||
import at.petrak.hexcasting.api.misc.HexDamageSources
|
||||
import at.petrak.hexcasting.api.spell.iota.Iota
|
||||
import at.petrak.hexcasting.api.spell.Widget
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.iota.DoubleIota
|
||||
import at.petrak.hexcasting.api.spell.iota.GarbageIota
|
||||
import at.petrak.hexcasting.api.spell.iota.Iota
|
||||
import at.petrak.hexcasting.api.spell.iota.Vec3Iota
|
||||
import at.petrak.hexcasting.api.utils.asTranslatedComponent
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.item.DyeColor
|
||||
|
@ -16,7 +18,7 @@ class MishapDivideByZero(val operand1: Component, val operand2: Component, val s
|
|||
dyeColor(DyeColor.RED)
|
||||
|
||||
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<Iota>) {
|
||||
stack.add(LegacySpellDatum.make(Widget.GARBAGE))
|
||||
stack.add(GarbageIota.INSTANCE)
|
||||
trulyHurt(ctx.caster, HexDamageSources.OVERCAST, ctx.caster.health / 2)
|
||||
}
|
||||
|
||||
|
@ -27,14 +29,14 @@ class MishapDivideByZero(val operand1: Component, val operand2: Component, val s
|
|||
private const val PREFIX = "hexcasting.mishap.divide_by_zero"
|
||||
|
||||
@JvmStatic
|
||||
fun of(operand1: Any, operand2: Any, suffix: String = "divide"): MishapDivideByZero {
|
||||
fun of(operand1: Iota, operand2: Iota, suffix: String = "divide"): MishapDivideByZero {
|
||||
if (suffix == "exponent")
|
||||
return MishapDivideByZero(translate(operand1), powerOf(operand2), suffix)
|
||||
return MishapDivideByZero(translate(operand1), translate(operand2), suffix)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun tan(angle: Double): MishapDivideByZero {
|
||||
fun tan(angle: DoubleIota): MishapDivideByZero {
|
||||
val translatedAngle = translate(angle)
|
||||
return MishapDivideByZero(
|
||||
"$PREFIX.sin".asTranslatedComponent(translatedAngle),
|
||||
|
@ -58,16 +60,16 @@ class MishapDivideByZero(val operand1: Component, val operand2: Component, val s
|
|||
fun powerOf(power: Component) = "$PREFIX.power".asTranslatedComponent(power)
|
||||
|
||||
@JvmStatic
|
||||
fun powerOf(datum: Any) = when (datum) {
|
||||
0.0 -> zerothPower
|
||||
else -> powerOf(LegacySpellDatum.make(datum).display())
|
||||
fun powerOf(datum: Iota): Component = when {
|
||||
datum is DoubleIota && datum.double == 0.0 -> zerothPower
|
||||
else -> datum.display()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun translate(datum: Any): Component = when (datum) {
|
||||
0.0 -> zero
|
||||
Vec3.ZERO -> zeroVector
|
||||
else -> LegacySpellDatum.make(datum).display()
|
||||
fun translate(datum: Iota): Component = when {
|
||||
datum is DoubleIota && datum.double == 0.0 -> zero
|
||||
datum is Vec3Iota && datum.vec3 == Vec3.ZERO -> zeroVector
|
||||
else -> datum.display()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,12 @@
|
|||
package at.petrak.hexcasting.api.spell.mishaps
|
||||
|
||||
import at.petrak.hexcasting.api.misc.FrozenColorizer
|
||||
import at.petrak.hexcasting.api.spell.iota.Iota
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.Widget
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.math.HexPattern
|
||||
import at.petrak.hexcasting.api.spell.iota.GarbageIota
|
||||
import at.petrak.hexcasting.api.spell.iota.Iota
|
||||
import at.petrak.hexcasting.api.utils.asTranslatedComponent
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.item.ItemEntity
|
||||
import net.minecraft.world.entity.npc.Villager
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.DyeColor
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* The value failed some kind of predicate.
|
||||
|
@ -30,32 +22,25 @@ class MishapInvalidIota(
|
|||
dyeColor(DyeColor.GRAY)
|
||||
|
||||
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<Iota>) {
|
||||
stack[stack.size - 1 - reverseIdx] = LegacySpellDatum.make(Widget.GARBAGE)
|
||||
stack[stack.size - 1 - reverseIdx] = GarbageIota.INSTANCE;
|
||||
}
|
||||
|
||||
override fun errorMessage(ctx: CastingContext, errorCtx: Context) =
|
||||
error("invalid_value", actionName(errorCtx.action), expected, reverseIdx,
|
||||
perpetrator.display())
|
||||
error(
|
||||
"invalid_value", actionName(errorCtx.action), expected, reverseIdx,
|
||||
perpetrator.display()
|
||||
)
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun ofClass(perpetrator: Iota, reverseIdx: Int, cls: Class<*>): MishapInvalidIota {
|
||||
val key = "hexcasting.mishap.invalid_value.class." + when {
|
||||
Double::class.java.isAssignableFrom(cls) || Double::class.javaObjectType.isAssignableFrom(cls) -> "double"
|
||||
Vec3::class.java.isAssignableFrom(cls) -> "vector"
|
||||
SpellList::class.java.isAssignableFrom(cls) -> "list"
|
||||
Widget::class.java.isAssignableFrom(cls) -> "widget"
|
||||
HexPattern::class.java.isAssignableFrom(cls) -> "pattern"
|
||||
fun ofType(perpetrator: Iota, reverseIdx: Int, name: String): MishapInvalidIota {
|
||||
return of(perpetrator, reverseIdx, "class.$name")
|
||||
}
|
||||
|
||||
ItemEntity::class.java.isAssignableFrom(cls) -> "entity.item"
|
||||
Player::class.java.isAssignableFrom(cls) -> "entity.player"
|
||||
Villager::class.java.isAssignableFrom(cls) -> "entity.villager"
|
||||
LivingEntity::class.java.isAssignableFrom(cls) -> "entity.living"
|
||||
Entity::class.java.isAssignableFrom(cls) -> "entity"
|
||||
|
||||
else -> "unknown"
|
||||
}
|
||||
return MishapInvalidIota(perpetrator, reverseIdx, key.asTranslatedComponent)
|
||||
@JvmStatic
|
||||
fun of(perpetrator: Iota, reverseIdx: Int, name: String, vararg translations: Any): MishapInvalidIota {
|
||||
val key = "hexcasting.mishap.invalid_value.$name"
|
||||
return MishapInvalidIota(perpetrator, reverseIdx, key.asTranslatedComponent(*translations))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
package at.petrak.hexcasting.api.utils
|
||||
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.iota.Iota
|
||||
import at.petrak.hexcasting.api.spell.iota.ListIota
|
||||
import at.petrak.hexcasting.api.spell.math.HexCoord
|
||||
|
@ -237,7 +236,7 @@ fun Iterable<Iota>.serializeToNBT() =
|
|||
if (HexIotaTypes.isTooLargeToSerialize(this))
|
||||
ListTag()
|
||||
else
|
||||
ListIota(SpellList.LList(this.toList())).serialize()
|
||||
ListIota(this.toList()).serialize()
|
||||
|
||||
// Copy the impl from forge
|
||||
fun ItemStack.serializeToNBT(): CompoundTag {
|
||||
|
|
|
@ -25,7 +25,7 @@ class OpPotionEffect(
|
|||
): Triple<RenderedSpell, Int, List<ParticleSpray>> {
|
||||
val target = args.getChecked<LivingEntity>(0, argc)
|
||||
if (target is ArmorStand)
|
||||
throw MishapInvalidIota.ofClass(LegacySpellDatum.make(target), 0, LivingEntity::class.java)
|
||||
throw MishapInvalidIota.ofType(LegacySpellDatum.make(target), 0, LivingEntity::class.java)
|
||||
val duration = max(args.getChecked(1, argc), 0.0)
|
||||
ctx.assertEntityInRange(target)
|
||||
val potency = if (this.allowPotency)
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package at.petrak.hexcasting.common.items;
|
||||
|
||||
import at.petrak.hexcasting.api.item.IotaHolderItem;
|
||||
import at.petrak.hexcasting.api.spell.DatumType;
|
||||
import at.petrak.hexcasting.api.spell.iota.Iota;
|
||||
import at.petrak.hexcasting.api.spell.iota.PatternIota;
|
||||
import at.petrak.hexcasting.api.spell.math.HexPattern;
|
||||
import at.petrak.hexcasting.api.utils.NBTHelper;
|
||||
import at.petrak.hexcasting.client.gui.PatternTooltipGreeble;
|
||||
import at.petrak.hexcasting.common.entities.EntityWallScroll;
|
||||
import at.petrak.hexcasting.common.lib.HexIotaTypes;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
@ -54,14 +55,16 @@ public class ItemScroll extends Item implements IotaHolderItem {
|
|||
if (pattern == null) {
|
||||
return null;
|
||||
}
|
||||
// We store only the data part of the iota; pretend the rest of it's there
|
||||
var out = new CompoundTag();
|
||||
out.put(LegacySpellDatum.TAG_PATTERN, pattern);
|
||||
out.putString(HexIotaTypes.KEY_TYPE, "hexcasting:pattern");
|
||||
out.put(HexIotaTypes.KEY_DATA, pattern);
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite(ItemStack stack, Iota datum) {
|
||||
return datum != null && datum.getType() == DatumType.PATTERN && !NBTHelper.hasCompound(stack, TAG_PATTERN);
|
||||
return datum instanceof PatternIota && !NBTHelper.hasCompound(stack, TAG_PATTERN);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -14,10 +14,7 @@ import net.minecraft.server.level.ServerLevel;
|
|||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
@ -112,7 +109,6 @@ public class HexIotaTypes {
|
|||
* }
|
||||
* </code>
|
||||
*/
|
||||
@Nullable
|
||||
public static Iota deserialize(CompoundTag tag, ServerLevel world) {
|
||||
var type = getTypeFromTag(tag);
|
||||
if (type == null) {
|
||||
|
@ -122,10 +118,16 @@ public class HexIotaTypes {
|
|||
if (dataKey == null) {
|
||||
return null;
|
||||
}
|
||||
return type.deserialize(tag, world);
|
||||
Iota deserialized;
|
||||
try {
|
||||
deserialized = Objects.requireNonNullElse(type.deserialize(tag, world), NullIota.INSTANCE);
|
||||
} catch (IllegalArgumentException exn) {
|
||||
HexAPI.LOGGER.warn("Caught an exception deserializing an iota", exn);
|
||||
deserialized = GarbageIota.INSTANCE;
|
||||
}
|
||||
return deserialized;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Component getDisplay(CompoundTag tag) {
|
||||
var type = getTypeFromTag(tag);
|
||||
if (type == null) {
|
||||
|
|
|
@ -386,8 +386,10 @@
|
|||
"hexcasting.mishap.invalid_value.numvec": "a number or vector",
|
||||
"hexcasting.mishap.invalid_value.numlist": "a number or list",
|
||||
"hexcasting.mishap.invalid_value.list.pattern": "a list of patterns",
|
||||
"hexcasting.mishap.invalid_value.int": "an integer",
|
||||
"hexcasting.mishap.invalid_value.double.positive": "a positive number",
|
||||
"hexcasting.mishap.invalid_value.double.between": "a number between %d and %d",
|
||||
"hexcasting.mishap.invalid_value.int": "an integer",
|
||||
"hexcasting.mishap.invalid_value.int.positive": "a positive integer",
|
||||
"hexcasting.mishap.invalid_value.int.between": "an integer between %d and %d",
|
||||
"hexcasting.mishap.not_enough_args": "%s expected %s or more arguments but the stack was only %s tall",
|
||||
"hexcasting.mishap.too_many_close_parens": "Used Retrospection without first using Introspection",
|
||||
|
|
Loading…
Reference in a new issue