Add a dedicated SpellList perst. data type for efficiency of ops
This commit is contained in:
parent
8241c351ce
commit
f893fe2a69
17 changed files with 116 additions and 45 deletions
|
@ -24,7 +24,7 @@ import java.util.*
|
|||
* * [Double]
|
||||
* * [Vec3][net.minecraft.world.phys.Vec3] as both position and (when normalized) direction
|
||||
* * [Widget]; [Widget.NULL] is used as our null value
|
||||
* * [List<SpellDatum<*>>][List]
|
||||
* * [SpellList]
|
||||
* * [HexPattern]! Yes, we have meta-evaluation everyone.
|
||||
* The constructor guarantees we won't pass a type that isn't one of those types.
|
||||
*
|
||||
|
@ -50,7 +50,7 @@ class SpellDatum<T : Any> private constructor(val payload: T) {
|
|||
is Vec3 -> out.put(
|
||||
TAG_VEC3, pl.serializeToNBT()
|
||||
)
|
||||
is ArrayList<*> -> {
|
||||
is SpellList -> {
|
||||
val subtag = ListTag()
|
||||
for (elt in pl)
|
||||
subtag.add((elt as SpellDatum<*>).serializeToNBT())
|
||||
|
@ -92,7 +92,7 @@ class SpellDatum<T : Any> private constructor(val payload: T) {
|
|||
when (this.payload) {
|
||||
is Entity -> DatumType.ENTITY
|
||||
is Widget -> DatumType.WIDGET
|
||||
is List<*> -> DatumType.LIST
|
||||
is SpellList -> DatumType.LIST
|
||||
is HexPattern -> DatumType.PATTERN
|
||||
is Double -> DatumType.DOUBLE
|
||||
is Vec3 -> DatumType.VEC
|
||||
|
@ -102,15 +102,7 @@ class SpellDatum<T : Any> private constructor(val payload: T) {
|
|||
companion object {
|
||||
@JvmStatic
|
||||
fun make(payload: Any): SpellDatum<*> =
|
||||
if (payload is List<*>) {
|
||||
SpellDatum(payload.map {
|
||||
when (it) {
|
||||
null -> make(Widget.NULL)
|
||||
is SpellDatum<*> -> it
|
||||
else -> make(it)
|
||||
}
|
||||
})
|
||||
} else if (payload is Vec3) {
|
||||
if (payload is Vec3) {
|
||||
SpellDatum(
|
||||
Vec3(
|
||||
HexUtils.FixNANs(payload.x),
|
||||
|
@ -151,7 +143,7 @@ class SpellDatum<T : Any> private constructor(val payload: T) {
|
|||
// this is safe because otherwise we wouldn't have been able to get the list before
|
||||
out.add(DeserializeFromNBT(subtag as CompoundTag, world))
|
||||
}
|
||||
SpellDatum(out)
|
||||
SpellDatum(SpellList.LList(0, out))
|
||||
}
|
||||
TAG_WIDGET -> {
|
||||
SpellDatum(Widget.valueOf(nbt.getString(key)))
|
||||
|
@ -234,7 +226,7 @@ class SpellDatum<T : Any> private constructor(val payload: T) {
|
|||
Entity::class.java,
|
||||
Double::class.java,
|
||||
Vec3::class.java,
|
||||
List::class.java,
|
||||
SpellList::class.java,
|
||||
Widget::class.java,
|
||||
HexPattern::class.java,
|
||||
)
|
||||
|
@ -252,10 +244,10 @@ class SpellDatum<T : Any> private constructor(val payload: T) {
|
|||
const val TAG_ENTITY_NAME_CHEATY = "name"
|
||||
|
||||
fun <T : Any> IsValidType(checkee: T): Boolean =
|
||||
if (checkee is List<*>) {
|
||||
// note it should be impossible to pass a spell datum that doesn't contain a valid type,
|
||||
if (checkee is SpellList) {
|
||||
// note it should be impossible to pass a spelllist that doesn't contain a valid type,
|
||||
// but we best make sure.
|
||||
checkee.all { it is SpellDatum<*> && IsValidType(it.payload) }
|
||||
checkee.all { IsValidType(it.payload) }
|
||||
} else {
|
||||
ValidTypes.any { clazz -> clazz.isAssignableFrom(checkee.javaClass) }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package at.petrak.hexcasting.api.spell
|
||||
|
||||
/**
|
||||
* Restricted interface for functional lists.
|
||||
*
|
||||
* ...Surely this won't have any performance implications.
|
||||
*/
|
||||
sealed class SpellList: Iterable<SpellDatum<*>> {
|
||||
|
||||
abstract val nonEmpty: Boolean
|
||||
abstract val car: SpellDatum<*>
|
||||
abstract val cdr: SpellList
|
||||
|
||||
class LPair(override val car: SpellDatum<*>, override val cdr: SpellList): SpellList() {
|
||||
override val nonEmpty = true
|
||||
}
|
||||
|
||||
class LList(val idx: Int, val list: List<SpellDatum<*>>): SpellList() {
|
||||
override val nonEmpty: Boolean
|
||||
get() = idx < list.size
|
||||
override val car: SpellDatum<*>
|
||||
get() = list[idx]
|
||||
override val cdr: SpellList
|
||||
get() = LList(idx + 1, list)
|
||||
}
|
||||
|
||||
fun modifyAt(startIdx: Int, modify: (SpellList) -> SpellList): SpellList {
|
||||
val stack = mutableListOf<SpellDatum<*>>()
|
||||
val ptr = iterator()
|
||||
var idx = startIdx
|
||||
if (idx < 0) {
|
||||
return this
|
||||
}
|
||||
while (idx > 0) {
|
||||
if (ptr.hasNext()) {
|
||||
return this
|
||||
}
|
||||
idx--
|
||||
stack.add(ptr.next())
|
||||
}
|
||||
var value = modify(ptr.list)
|
||||
for (datum in stack.asReversed()) {
|
||||
value = LPair(datum, value)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
fun getAt(startIdx: Int): SpellDatum<*> {
|
||||
var ptr = this
|
||||
var idx = startIdx
|
||||
if (idx < 0) {
|
||||
throw ArrayIndexOutOfBoundsException()
|
||||
}
|
||||
while (idx > 0) {
|
||||
when (ptr) {
|
||||
is LPair -> ptr = ptr.cdr
|
||||
is LList -> return ptr.list[ptr.idx + idx]
|
||||
}
|
||||
idx--
|
||||
}
|
||||
return ptr.car
|
||||
}
|
||||
|
||||
|
||||
override fun iterator() = Iterator(this)
|
||||
|
||||
class Iterator(var list: SpellList): kotlin.collections.Iterator<SpellDatum<*>> {
|
||||
override fun hasNext() = list.nonEmpty
|
||||
override operator fun next(): SpellDatum<*> {
|
||||
val car = list.car
|
||||
list = list.cdr
|
||||
return car
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,12 +4,13 @@ import at.petrak.hexcasting.api.spell.ConstManaOperator
|
|||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
|
||||
object OpAppend : ConstManaOperator {
|
||||
override val argc = 2
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
val list = args.getChecked<List<SpellDatum<*>>>(0).toMutableList()
|
||||
val list = args.getChecked<SpellList>(0).toMutableList()
|
||||
val datum = args[1]
|
||||
list.add(datum)
|
||||
return spellListOf(list)
|
||||
|
|
|
@ -4,13 +4,14 @@ import at.petrak.hexcasting.api.spell.ConstManaOperator
|
|||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
|
||||
object OpConcat : ConstManaOperator {
|
||||
override val argc = 2
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
val lhs = args.getChecked<List<SpellDatum<*>>>(0).toMutableList()
|
||||
val rhs = args.getChecked<List<SpellDatum<*>>>(1)
|
||||
val lhs = args.getChecked<SpellList>(0).toMutableList()
|
||||
val rhs = args.getChecked<SpellList>(1)
|
||||
lhs.addAll(rhs)
|
||||
return spellListOf(lhs)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package at.petrak.hexcasting.common.casting.operators.lists
|
|||
import at.petrak.hexcasting.api.spell.ConstManaOperator
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.Widget
|
||||
import kotlin.math.roundToInt
|
||||
|
@ -10,7 +11,7 @@ import kotlin.math.roundToInt
|
|||
object OpIndex : ConstManaOperator {
|
||||
override val argc = 2
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
val list = args.getChecked<List<SpellDatum<*>>>(0).toMutableList()
|
||||
val list = args.getChecked<SpellList>(0).toMutableList()
|
||||
val index = args.getChecked<Double>(1)
|
||||
val x = list.getOrElse(index.roundToInt()) { SpellDatum.make(Widget.NULL) }
|
||||
return listOf(x)
|
||||
|
|
|
@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.spell.ConstManaOperator
|
|||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
|
||||
object OpIndexOf : ConstManaOperator {
|
||||
|
@ -11,7 +12,7 @@ object OpIndexOf : ConstManaOperator {
|
|||
get() = 2
|
||||
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
val list = args.getChecked<List<SpellDatum<*>>>(0).toMutableList()
|
||||
val list = args.getChecked<SpellList>(0).toMutableList()
|
||||
val value = args[1]
|
||||
return spellListOf(list.indexOf(value).toDouble())
|
||||
}
|
||||
|
|
|
@ -4,12 +4,13 @@ import at.petrak.hexcasting.api.spell.ConstManaOperator
|
|||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
|
||||
// it's still called beancounter's distillation in my heart
|
||||
object OpListSize : ConstManaOperator {
|
||||
override val argc = 1
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
return spellListOf(args.getChecked<List<SpellDatum<*>>>(0).toList().size.toDouble()) // mmm one-liner
|
||||
return spellListOf(args.getChecked<SpellList>(0).toList().size.toDouble()) // mmm one-liner
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,26 +4,16 @@ import at.petrak.hexcasting.api.spell.ConstManaOperator
|
|||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object OpModifyInPlace : ConstManaOperator {
|
||||
override val argc = 3
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
val list = args.getChecked<List<SpellDatum<*>>>(0)
|
||||
val list = args.getChecked<SpellList>(0)
|
||||
val index = args.getChecked<Double>(1).roundToInt()
|
||||
val iota = args[2]
|
||||
|
||||
if (0 > index || index > list.size)
|
||||
return spellListOf(list)
|
||||
|
||||
|
||||
val newList = list.toMutableList()
|
||||
if (index == list.size)
|
||||
newList.add(iota)
|
||||
else
|
||||
newList[index] = iota
|
||||
|
||||
return spellListOf(newList)
|
||||
return spellListOf(list.modifyAt(index) { SpellList.LPair(iota, it.cdr) })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.spell.ConstManaOperator
|
|||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
|
||||
object OpRemove : ConstManaOperator {
|
||||
|
@ -11,7 +12,7 @@ object OpRemove : ConstManaOperator {
|
|||
get() = 2
|
||||
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
val list = args.getChecked<List<SpellDatum<*>>>(0).toMutableList()
|
||||
val list = args.getChecked<SpellList>(0).toMutableList()
|
||||
val index = args.getChecked<Double>(1).toInt()
|
||||
if (index < 0 || index >= list.size)
|
||||
return list
|
||||
|
|
|
@ -4,11 +4,12 @@ import at.petrak.hexcasting.api.spell.ConstManaOperator
|
|||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
|
||||
object OpReverski : ConstManaOperator {
|
||||
override val argc = 1
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
return spellListOf(args.getChecked<List<SpellDatum<*>>>(0).asReversed()) // okay kotlin kinda pogged for this
|
||||
return spellListOf(args.getChecked<SpellList>(0).toList().asReversed()) // okay kotlin kinda pogged for this
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.spell.ConstManaOperator
|
|||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import net.minecraft.util.Mth
|
||||
import kotlin.math.max
|
||||
|
@ -13,7 +14,7 @@ import kotlin.math.roundToInt
|
|||
object OpSlice : ConstManaOperator {
|
||||
override val argc = 3
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
val list = args.getChecked<List<SpellDatum<*>>>(0)
|
||||
val list = args.getChecked<SpellList>(0).toList()
|
||||
val index1 = Mth.clamp(args.getChecked<Double>(1).roundToInt(), 0, list.size)
|
||||
val index2 = Mth.clamp(args.getChecked<Double>(2).roundToInt(), 0, list.size)
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package at.petrak.hexcasting.common.casting.operators.lists
|
|||
import at.petrak.hexcasting.api.spell.ConstManaOperator
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
|
||||
object OpSplat : ConstManaOperator {
|
||||
|
@ -10,5 +11,5 @@ object OpSplat : ConstManaOperator {
|
|||
get() = 1
|
||||
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> =
|
||||
args.getChecked<List<SpellDatum<*>>>(0).toMutableList()
|
||||
args.getChecked<SpellList>(0).toMutableList()
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.spell.ConstManaOperator
|
|||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.common.casting.operators.math.MathOpUtils
|
||||
import kotlin.math.roundToInt
|
||||
|
@ -16,7 +17,7 @@ object OpAnd : ConstManaOperator {
|
|||
|
||||
if (firstParam.right().isPresent) {
|
||||
val list1 = firstParam.right().get()
|
||||
val list2 = args.getChecked<List<SpellDatum<*>>>(1)
|
||||
val list2 = args.getChecked<SpellList>(1)
|
||||
return spellListOf(list1.filter { it in list2 })
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.spell.ConstManaOperator
|
|||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.common.casting.operators.math.MathOpUtils
|
||||
import kotlin.math.roundToInt
|
||||
|
@ -16,7 +17,7 @@ object OpOr : ConstManaOperator {
|
|||
|
||||
if (firstParam.right().isPresent) {
|
||||
val list1 = firstParam.right().get()
|
||||
val list2 = args.getChecked<List<SpellDatum<*>>>(1)
|
||||
val list2 = args.getChecked<SpellList>(1)
|
||||
return spellListOf(list1 + list2.filter { it !in list1 })
|
||||
}
|
||||
|
||||
|
|
|
@ -4,13 +4,14 @@ import at.petrak.hexcasting.api.spell.ConstManaOperator
|
|||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
|
||||
object OpToSet : ConstManaOperator {
|
||||
override val argc = 1
|
||||
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
val payload = args.getChecked<List<SpellDatum<*>>>(0)
|
||||
val payload = args.getChecked<SpellList>(0)
|
||||
return spellListOf(payload.toSet().toList())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.spell.ConstManaOperator
|
|||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.common.casting.operators.math.MathOpUtils
|
||||
import kotlin.math.roundToInt
|
||||
|
@ -16,7 +17,7 @@ object OpXor : ConstManaOperator {
|
|||
|
||||
if (firstParam.right().isPresent) {
|
||||
val list1 = firstParam.right().get()
|
||||
val list2 = args.getChecked<List<SpellDatum<*>>>(1)
|
||||
val list2 = args.getChecked<SpellList>(1)
|
||||
return spellListOf(list1.filter { it !in list2 } + list2.filter { it !in list1 })
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
|||
import at.petrak.hexcasting.api.spell.ParticleSpray
|
||||
import at.petrak.hexcasting.api.spell.RenderedSpell
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.SpellOperator
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapBadItem
|
||||
|
@ -21,7 +22,7 @@ class OpMakePackagedSpell<T : ItemPackagedHex>(val itemType: T, val cost: Int) :
|
|||
ctx: CastingContext
|
||||
): Triple<RenderedSpell, Int, List<ParticleSpray>> {
|
||||
val entity = args.getChecked<ItemEntity>(0)
|
||||
val patterns = args.getChecked<List<SpellDatum<*>>>(1)
|
||||
val patterns = args.getChecked<SpellList>(1)
|
||||
|
||||
val (handStack, hand) = ctx.getHeldItemToOperateOn {
|
||||
val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(it)
|
||||
|
|
Loading…
Reference in a new issue