From 5148240d3ccd31702bfc5f83ab2a6d29ccd074bb Mon Sep 17 00:00:00 2001 From: Master-Bw3 Date: Sun, 11 Aug 2024 21:26:33 -0500 Subject: [PATCH] implement codecs on serializable classes --- .../hexcasting/api/addldata/ADIotaHolder.java | 3 +- .../hexcasting/api/casting/ActionUtils.kt | 22 ++-- .../hexcasting/api/casting/SpellList.kt | 11 ++ .../api/casting/eval/ResolvedPattern.kt | 28 +++++ .../api/casting/eval/vm/ContinuationFrame.kt | 92 +++++++-------- .../api/casting/eval/vm/FrameEvaluate.kt | 46 +++++--- .../api/casting/eval/vm/FrameFinishEval.kt | 18 ++- .../api/casting/eval/vm/FrameForEach.kt | 56 +++++---- .../api/casting/eval/vm/SpellContinuation.kt | 48 ++++++-- .../api/casting/iota/BooleanIota.java | 33 ++++-- .../api/casting/iota/ContinuationIota.java | 40 ++++++- .../api/casting/iota/DoubleIota.java | 29 +++-- .../api/casting/iota/EntityIota.java | 106 +++++++++++++----- .../api/casting/iota/GarbageIota.java | 18 ++- .../hexcasting/api/casting/iota/Iota.java | 53 +++++++-- .../hexcasting/api/casting/iota/IotaType.java | 84 ++++++++------ .../hexcasting/api/casting/iota/ListIota.java | 44 +++++--- .../hexcasting/api/casting/iota/NullIota.java | 24 +++- .../api/casting/iota/PatternIota.java | 30 +++-- .../hexcasting/api/casting/iota/Vec3Iota.java | 81 ++++++++++--- .../hexcasting/api/casting/math/HexAngle.kt | 7 ++ .../hexcasting/api/casting/math/HexDir.kt | 5 + .../hexcasting/api/casting/math/HexPattern.kt | 7 +- .../casting/mishaps/MishapEntityNotFound.kt | 22 ++++ .../api/casting/mishaps/MishapOthersName.kt | 14 ++- .../hexcasting/api/item/IotaHolderItem.java | 2 +- .../petrak/hexcasting/api/utils/HexUtils.kt | 20 ++++ .../blocks/akashic/BlockAkashicRecord.java | 3 +- .../akashic/BlockEntityAkashicBookshelf.java | 3 +- .../common/casting/actions/OpEntityHeight.kt | 2 +- .../common/casting/actions/OpEntityLook.kt | 2 +- .../common/casting/actions/OpEntityPos.kt | 2 +- .../casting/actions/OpEntityVelocity.kt | 2 +- .../casting/actions/akashic/OpAkashicWrite.kt | 2 +- .../casting/actions/rw/OpTheCoolerRead.kt | 2 +- .../casting/actions/rw/OpTheCoolerReadable.kt | 2 +- .../casting/actions/rw/OpTheCoolerWritable.kt | 2 +- .../casting/actions/rw/OpTheCoolerWrite.kt | 4 +- .../common/casting/actions/rw/OpWrite.kt | 2 +- .../casting/actions/spells/OpAddMotion.kt | 2 +- .../common/casting/actions/spells/OpBlink.kt | 2 +- .../common/casting/actions/spells/OpFlight.kt | 2 +- .../casting/actions/spells/OpMakeBattery.kt | 2 +- .../actions/spells/OpMakePackagedSpell.kt | 4 +- .../casting/actions/spells/OpPotionEffect.kt | 2 +- .../casting/actions/spells/OpRecharge.kt | 2 +- .../casting/actions/spells/great/OpAltiora.kt | 2 +- .../actions/spells/great/OpBrainsweep.kt | 2 +- .../actions/spells/great/OpTeleport.kt | 2 +- .../common/items/magic/ItemPackagedHex.java | 5 +- .../common/items/storage/ItemAbacus.java | 3 +- .../common/items/storage/ItemFocus.java | 3 +- .../common/items/storage/ItemSpellbook.java | 5 +- .../common/items/storage/ItemThoughtKnot.java | 3 +- .../hexcasting/interop/pehkui/OpGetScale.kt | 2 +- .../hexcasting/interop/pehkui/OpSetScale.kt | 2 +- .../fabric/cc/adimpl/CCItemIotaHolder.java | 3 +- 57 files changed, 723 insertions(+), 296 deletions(-) create mode 100644 Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityNotFound.kt diff --git a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADIotaHolder.java b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADIotaHolder.java index 7b8fcc1c95..3c74745928 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADIotaHolder.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADIotaHolder.java @@ -2,6 +2,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; +import at.petrak.hexcasting.api.utils.HexUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import org.jetbrains.annotations.Nullable; @@ -14,7 +15,7 @@ public interface ADIotaHolder { default Iota readIota(ServerLevel world) { var tag = readIotaTag(); if (tag != null) { - return IotaType.deserialize(tag, world); + return HexUtils.deserializeWithCodec(tag, Iota.getCodec(world)); } else { return null; } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt index 26f39da2f3..2610cd2219 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt @@ -4,11 +4,13 @@ package at.petrak.hexcasting.api.casting import at.petrak.hexcasting.api.casting.iota.* import at.petrak.hexcasting.api.casting.math.HexPattern +import at.petrak.hexcasting.api.casting.mishaps.MishapEntityNotFound import at.petrak.hexcasting.api.casting.mishaps.MishapInvalidIota import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs import at.petrak.hexcasting.api.utils.asTranslatedComponent import com.mojang.datafixers.util.Either import net.minecraft.core.BlockPos +import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.Entity import net.minecraft.world.entity.LivingEntity @@ -32,10 +34,10 @@ fun List.getDouble(idx: Int, argc: Int = 0): Double { } } -fun List.getEntity(idx: Int, argc: Int = 0): Entity { +fun List.getEntity(idx: Int, argc: Int = 0, world: ServerLevel): Entity { val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } if (x is EntityIota) { - return x.entity + return x.getEntity(world)?: throw MishapEntityNotFound(x, if (argc == 0) idx else argc - (idx + 1)) } else { throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity") } @@ -79,40 +81,40 @@ fun List.getBool(idx: Int, argc: Int = 0): Boolean { // Helpers -fun List.getItemEntity(idx: Int, argc: Int = 0): ItemEntity { +fun List.getItemEntity(idx: Int, argc: Int = 0, world: ServerLevel): ItemEntity { val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } if (x is EntityIota) { - val e = x.entity + val e = x.getEntity(world)?: throw MishapEntityNotFound(x, if (argc == 0) idx else argc - (idx + 1)) if (e is ItemEntity) return e } throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.item") } -fun List.getPlayer(idx: Int, argc: Int = 0): ServerPlayer { +fun List.getPlayer(idx: Int, argc: Int = 0, world: ServerLevel): ServerPlayer { val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } if (x is EntityIota) { - val e = x.entity + val e = x.getEntity(world)?: throw MishapEntityNotFound(x, if (argc == 0) idx else argc - (idx + 1)) if (e is ServerPlayer) return e } throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.player") } -fun List.getMob(idx: Int, argc: Int = 0): Mob { +fun List.getMob(idx: Int, argc: Int = 0, world: ServerLevel): Mob { val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } if (x is EntityIota) { - val e = x.entity + val e = x.getEntity(world)?: throw MishapEntityNotFound(x, if (argc == 0) idx else argc - (idx + 1)) if (e is Mob) return e } throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.mob") } -fun List.getLivingEntityButNotArmorStand(idx: Int, argc: Int = 0): LivingEntity { +fun List.getLivingEntityButNotArmorStand(idx: Int, argc: Int = 0, world: ServerLevel): LivingEntity { val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } if (x is EntityIota) { - val e = x.entity + val e = x.getEntity(world)?: throw MishapEntityNotFound(x, if (argc == 0) idx else argc - (idx + 1)) if (e is LivingEntity && e !is ArmorStand) return e } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/SpellList.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/SpellList.kt index 2e76c18c76..d4684c0f08 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/SpellList.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/SpellList.kt @@ -1,6 +1,9 @@ package at.petrak.hexcasting.api.casting import at.petrak.hexcasting.api.casting.iota.Iota +import com.mojang.serialization.Codec +import net.minecraft.server.level.ServerLevel +import java.util.Collections /** * Restricted interface for functional lists. @@ -90,4 +93,12 @@ sealed class SpellList : Iterable { return car } } + + companion object { + @JvmStatic + fun getCodec(): Codec = Iota.getCodec().listOf().xmap(SpellList::LList, SpellList::toMutableList) + + @JvmStatic + fun getCodec(world: ServerLevel): Codec = Iota.getCodec(world).listOf().xmap(SpellList::LList, SpellList::toMutableList) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPattern.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPattern.kt index 6108850727..99941a1d6b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPattern.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPattern.kt @@ -3,11 +3,26 @@ package at.petrak.hexcasting.api.casting.eval import at.petrak.hexcasting.api.casting.math.HexCoord import at.petrak.hexcasting.api.casting.math.HexPattern import at.petrak.hexcasting.api.utils.NBTBuilder +import com.mojang.serialization.Codec +import com.mojang.serialization.codecs.RecordCodecBuilder import net.minecraft.nbt.CompoundTag import java.util.* data class ResolvedPattern(val pattern: HexPattern, val origin: HexCoord, var type: ResolvedPatternType) { + constructor(pattern: HexPattern, originQ: Int, originR: Int, type: ResolvedPatternType) : this( + pattern, + HexCoord(originQ, originR), + type + ) + + val originQ: Int + get() = origin.q + + val originR: Int + get() = origin.r + + @Deprecated("Use the CODEC instead.") fun serializeToNBT() = NBTBuilder { "Pattern" %= pattern.serializeToNBT() "OriginQ" %= origin.q @@ -16,6 +31,19 @@ data class ResolvedPattern(val pattern: HexPattern, val origin: HexCoord, var ty } companion object { + @JvmField + val CODEC: Codec = RecordCodecBuilder.create { + it.group( + HexPattern.CODEC.fieldOf("Pattern").forGetter(ResolvedPattern::pattern), + Codec.INT.fieldOf("OriginQ").forGetter(ResolvedPattern::originQ), + Codec.INT.fieldOf("OriginR").forGetter(ResolvedPattern::originR), + Codec.STRING.fieldOf("Valid") + .xmap(ResolvedPatternType::fromString) { type -> type.name.lowercase(Locale.ROOT) } + .forGetter(ResolvedPattern::type) + ).apply(it, ::ResolvedPattern) + } + + @Deprecated("Use the CODEC instead.") @JvmStatic fun fromNBT(tag: CompoundTag): ResolvedPattern { val pattern = HexPattern.fromNBT(tag.getCompound("Pattern")) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt index 8000ec09aa..364657567b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt @@ -1,13 +1,17 @@ package at.petrak.hexcasting.api.casting.eval.vm -import at.petrak.hexcasting.api.casting.SpellList +import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.casting.eval.CastResult import at.petrak.hexcasting.api.casting.iota.Iota +import at.petrak.hexcasting.api.utils.deserializeWithCodec import at.petrak.hexcasting.common.lib.hex.HexContinuationTypes +import com.google.common.base.Suppliers +import com.mojang.serialization.Codec +import com.mojang.serialization.MapCodec import net.minecraft.nbt.CompoundTag -import net.minecraft.nbt.Tag -import net.minecraft.resources.ResourceLocation +import net.minecraft.nbt.NbtOps import net.minecraft.server.level.ServerLevel +import java.util.function.Supplier /** * A single frame of evaluation during the execution of a spell. @@ -50,59 +54,59 @@ interface ContinuationFrame { val type: Type<*> interface Type { - fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): U? + fun getCodec(): Codec + + fun getCodec(world: ServerLevel): Codec + + @Deprecated( + "Use the CODEC instead.", + replaceWith = ReplaceWith("tag.deserializeWithCodec(getCodec())") + ) + fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): U? = + tag.deserializeWithCodec(getCodec()) } companion object { + @JvmStatic + fun getCodec(): Codec = + HexContinuationTypes.REGISTRY.byNameCodec().dispatchMap( + HexContinuationTypes.KEY_TYPE, + ContinuationFrame::type + ) { continuationType -> + continuationType.getCodec().fieldOf(HexContinuationTypes.KEY_DATA).codec() + }.codec() + + @JvmStatic + fun getCodec(world: ServerLevel): Codec = + HexContinuationTypes.REGISTRY.byNameCodec().dispatchMap( + HexContinuationTypes.KEY_TYPE, + ContinuationFrame::type + ) { continuationType -> + continuationType.getCodec(world).fieldOf(HexContinuationTypes.KEY_DATA).codec() + }.codec() + /** * Takes a tag containing the ContinuationFrame.Type resourcelocation and the serialized continuation frame, and returns * the deserialized continuation frame. */ + @Deprecated( + "Use the codec instead.", + replaceWith = ReplaceWith("tag.deserializeWithCodec(ContinuationFrame.getCodec(world))") + ) @JvmStatic - fun fromNBT(tag: CompoundTag, world: ServerLevel): ContinuationFrame { - val type = getTypeFromTag(tag) ?: return FrameEvaluate(SpellList.LList(0, listOf()), false) - - return (tag.get(HexContinuationTypes.KEY_DATA) as? CompoundTag)?.let { type.deserializeFromNBT(it, world) } - ?: FrameEvaluate(SpellList.LList(0, listOf()), false) - } + fun fromNBT(tag: CompoundTag, world: ServerLevel): ContinuationFrame = + getCodec(world).parse(NbtOps.INSTANCE, tag).resultOrPartial(HexAPI.LOGGER::error).orElseThrow() /** * Takes a continuation frame and serializes it along with its type. */ + @Deprecated( + "Use the codec instead.", + replaceWith = ReplaceWith("serializeWithCodec(ContinuationFrame.getCodec())") + ) @JvmStatic - fun toNBT(frame: ContinuationFrame): CompoundTag { - val type = frame.type - val typeId = HexContinuationTypes.REGISTRY.getKey(type) - ?: throw IllegalStateException( - "Tried to serialize an unregistered continuation type. Continuation: " + frame - + " ; Type" + type.javaClass.typeName) - - val data = frame.serializeToNBT() - - val out = CompoundTag() - out.putString(HexContinuationTypes.KEY_TYPE, typeId.toString()) - out.put(HexContinuationTypes.KEY_DATA, data) - return out - } - - /** - * This method attempts to find the type from the `type` key. - * See [ContinuationFrame.serializeToNBT] for the storage format. - * - * @return `null` if it cannot get the type. - */ - private fun getTypeFromTag(tag: CompoundTag): Type<*>? { - if (!tag.contains(HexContinuationTypes.KEY_TYPE, Tag.TAG_STRING.toInt())) { - return null - } - - val typeKey = tag.getString(HexContinuationTypes.KEY_TYPE) - if (!ResourceLocation.isValidResourceLocation(typeKey)) { - return null - } - - val typeLoc = ResourceLocation(typeKey) - return HexContinuationTypes.REGISTRY[typeLoc] - } + fun toNBT(frame: ContinuationFrame): CompoundTag = + getCodec().encodeStart(NbtOps.INSTANCE, frame).resultOrPartial(HexAPI.LOGGER::error) + .orElseThrow() as CompoundTag } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt index 141148dfdc..1405aa7f05 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt @@ -1,16 +1,18 @@ package at.petrak.hexcasting.api.casting.eval.vm +import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.casting.SpellList import at.petrak.hexcasting.api.casting.eval.CastResult import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.ListIota -import at.petrak.hexcasting.api.utils.NBTBuilder -import at.petrak.hexcasting.api.utils.getList -import at.petrak.hexcasting.api.utils.serializeToNBT +import at.petrak.hexcasting.api.utils.* import at.petrak.hexcasting.common.lib.hex.HexEvalSounds import at.petrak.hexcasting.common.lib.hex.HexIotaTypes +import com.mojang.serialization.Codec +import com.mojang.serialization.codecs.RecordCodecBuilder import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.NbtOps import net.minecraft.nbt.Tag import net.minecraft.server.level.ServerLevel @@ -44,14 +46,24 @@ data class FrameEvaluate(val list: SpellList, val isMetacasting: Boolean) : Cont } } else { // If there are no patterns (e.g. empty Hermes), just return OK. - CastResult(ListIota(list), continuation, null, listOf(), ResolvedPatternType.EVALUATED, HexEvalSounds.HERMES) + CastResult( + ListIota(list), + continuation, + null, + listOf(), + ResolvedPatternType.EVALUATED, + HexEvalSounds.HERMES + ) } } - override fun serializeToNBT() = NBTBuilder { - "patterns" %= list.serializeToNBT() - "isMetacasting" %= isMetacasting - } + @Deprecated( + "Use the CODEC instead.", + replaceWith = ReplaceWith("serializeWithCodec(FrameEvaluate.TYPE.getCodec())") + ) + override fun serializeToNBT() = + TYPE.getCodec().encodeStart(NbtOps.INSTANCE, this).resultOrPartial(HexAPI.LOGGER::error) + .orElseThrow() as CompoundTag override fun size() = list.size() @@ -60,15 +72,19 @@ data class FrameEvaluate(val list: SpellList, val isMetacasting: Boolean) : Cont companion object { @JvmField val TYPE: ContinuationFrame.Type = object : ContinuationFrame.Type { - override fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): FrameEvaluate { - return FrameEvaluate( - HexIotaTypes.LIST.deserialize( - tag.getList("patterns", Tag.TAG_COMPOUND), - world - )!!.list, - tag.getBoolean("isMetacasting")) + override fun getCodec(): Codec = RecordCodecBuilder.create { + it.group( + SpellList.getCodec().fieldOf("patterns").forGetter(FrameEvaluate::list), + Codec.BOOL.fieldOf("isMetacasting").forGetter(FrameEvaluate::isMetacasting) + ).apply(it, ::FrameEvaluate) } + override fun getCodec(world: ServerLevel): Codec = RecordCodecBuilder.create { + it.group( + SpellList.getCodec(world).fieldOf("patterns").forGetter(FrameEvaluate::list), + Codec.BOOL.fieldOf("isMetacasting").forGetter(FrameEvaluate::isMetacasting) + ).apply(it, ::FrameEvaluate) + } } } } \ No newline at end of file diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt index 72bbb8c80c..0299b3a72e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt @@ -1,12 +1,17 @@ package at.petrak.hexcasting.api.casting.eval.vm +import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.casting.eval.CastResult import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.NullIota import at.petrak.hexcasting.api.utils.NBTBuilder +import at.petrak.hexcasting.api.utils.deserializeWithCodec +import at.petrak.hexcasting.api.utils.serializeWithCodec import at.petrak.hexcasting.common.lib.hex.HexEvalSounds +import com.mojang.serialization.Codec import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.NbtOps import net.minecraft.server.level.ServerLevel /** @@ -14,6 +19,7 @@ import net.minecraft.server.level.ServerLevel * so that we know when to stop removing frames during a Halt. */ object FrameFinishEval : ContinuationFrame { + // Don't do anything else to the stack, just finish the halt statement. override fun breakDownwards(stack: List) = true to stack @@ -33,13 +39,21 @@ object FrameFinishEval : ContinuationFrame { ) } - override fun serializeToNBT() = CompoundTag() + @Deprecated( + "Use the codec instead.", + replaceWith = ReplaceWith("serializeWithCodec(FrameFinishEval.TYPE.getCodec())") + ) + override fun serializeToNBT() = + this.serializeWithCodec(TYPE.getCodec()) as CompoundTag override fun size() = 0 @JvmField val TYPE: ContinuationFrame.Type = object : ContinuationFrame.Type { - override fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel) = FrameFinishEval + override fun getCodec(): Codec = Codec.unit { FrameFinishEval } + + override fun getCodec(world: ServerLevel): Codec = Codec.unit { FrameFinishEval } + } override val type = TYPE diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt index 0221c1f36d..0dc5a18bda 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt @@ -1,19 +1,22 @@ package at.petrak.hexcasting.api.casting.eval.vm +import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.casting.SpellList import at.petrak.hexcasting.api.casting.eval.CastResult import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType +import at.petrak.hexcasting.api.casting.eval.vm.FrameEvaluate.Companion import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.ListIota -import at.petrak.hexcasting.api.utils.NBTBuilder -import at.petrak.hexcasting.api.utils.getList -import at.petrak.hexcasting.api.utils.hasList -import at.petrak.hexcasting.api.utils.serializeToNBT +import at.petrak.hexcasting.api.utils.* import at.petrak.hexcasting.common.lib.hex.HexEvalSounds import at.petrak.hexcasting.common.lib.hex.HexIotaTypes +import com.mojang.serialization.Codec +import com.mojang.serialization.codecs.RecordCodecBuilder import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.NbtOps import net.minecraft.nbt.Tag import net.minecraft.server.level.ServerLevel +import java.util.Collections /** * A frame representing all the state for a Thoth evaluation. @@ -81,13 +84,13 @@ data class FrameForEach( ) } - override fun serializeToNBT() = NBTBuilder { - "data" %= data.serializeToNBT() - "code" %= code.serializeToNBT() - if (baseStack != null) - "base" %= baseStack.serializeToNBT() - "accumulator" %= acc.serializeToNBT() - } + @Deprecated( + "Use the codec instead.", + replaceWith = ReplaceWith("serializeWithCodec(FrameForEach.TYPE.getCodec())") + ) + override fun serializeToNBT() = + this.serializeWithCodec(TYPE.getCodec()) as CompoundTag + override fun size() = data.size() + code.size() + acc.size + (baseStack?.size ?: 0) @@ -96,21 +99,26 @@ data class FrameForEach( companion object { @JvmField val TYPE: ContinuationFrame.Type = object : ContinuationFrame.Type { - override fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): FrameForEach { - return FrameForEach( - HexIotaTypes.LIST.deserialize(tag.getList("data", Tag.TAG_COMPOUND), world)!!.list, - HexIotaTypes.LIST.deserialize(tag.getList("code", Tag.TAG_COMPOUND), world)!!.list, - if (tag.hasList("base", Tag.TAG_COMPOUND)) - HexIotaTypes.LIST.deserialize(tag.getList("base", Tag.TAG_COMPOUND), world)!!.list.toList() - else - null, - HexIotaTypes.LIST.deserialize( - tag.getList("accumulator", Tag.TAG_COMPOUND), - world - )!!.list.toMutableList() - ) + override fun getCodec(): Codec = RecordCodecBuilder.create { + it.group( + SpellList.getCodec().fieldOf("data").forGetter(FrameForEach::data), + SpellList.getCodec().fieldOf("code").forGetter(FrameForEach::code), + Iota.getCodec().listOf().nullableFieldOf("base").forGetter(FrameForEach::baseStack), + Iota.getCodec().listOf().xmap(List::toMutableList, Collections::unmodifiableList) + .fieldOf("acc").forGetter(FrameForEach::acc) + ).apply(it, ::FrameForEach) } + override fun getCodec(world: ServerLevel): Codec = + RecordCodecBuilder.create { + it.group( + SpellList.getCodec(world).fieldOf("data").forGetter(FrameForEach::data), + SpellList.getCodec(world).fieldOf("code").forGetter(FrameForEach::code), + Iota.getCodec(world).listOf().nullableFieldOf("base").forGetter(FrameForEach::baseStack), + Iota.getCodec(world).listOf().xmap(List::toMutableList, Collections::unmodifiableList) + .fieldOf("acc").forGetter(FrameForEach::acc) + ).apply(it, ::FrameForEach) + } } } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/SpellContinuation.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/SpellContinuation.kt index ec706c2858..9491011bc7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/SpellContinuation.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/SpellContinuation.kt @@ -1,8 +1,13 @@ package at.petrak.hexcasting.api.casting.eval.vm +import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.utils.NBTBuilder +import at.petrak.hexcasting.api.utils.deserializeWithCodec import at.petrak.hexcasting.api.utils.getList +import at.petrak.hexcasting.api.utils.serializeWithCodec +import com.mojang.serialization.Codec import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.NbtOps import net.minecraft.nbt.Tag import net.minecraft.server.level.ServerLevel @@ -16,28 +21,51 @@ sealed interface SpellContinuation { fun pushFrame(frame: ContinuationFrame): SpellContinuation = NotDone(frame, this) - fun serializeToNBT() = NBTBuilder { - TAG_FRAME %= list(getNBTFrames()) - } - fun getNBTFrames(): List { + @Deprecated( + "Use the codec instead.", + replaceWith = ReplaceWith("serializeWithCodec(SpellContinuation.getCodec())") + ) + fun serializeToNBT(): CompoundTag = this.serializeWithCodec(getCodec()) as CompoundTag + + private fun toList(): List { var self = this - val frames = mutableListOf() + val frames = mutableListOf() while (self is NotDone) { - frames.add(ContinuationFrame.toNBT(self.frame)) + frames.add(self.frame) self = self.next } return frames } + companion object { - const val TAG_FRAME = "frame" + @JvmStatic + fun getCodec(): Codec = ContinuationFrame.getCodec().listOf() + .xmap(SpellContinuation::fromList, SpellContinuation::toList) @JvmStatic - fun fromNBT(nbt: CompoundTag, world: ServerLevel): SpellContinuation { - val frames = nbt.getList(TAG_FRAME, Tag.TAG_COMPOUND) + fun getCodec(world: ServerLevel): Codec = ContinuationFrame.getCodec(world).listOf() + .xmap(SpellContinuation::fromList, SpellContinuation::toList) + + @JvmField + val TAG_FRAME = "frame" + + /** + * Takes a tag containing the ContinuationFrame.Type resourcelocation and the serialized continuation frame, and returns + * the deserialized continuation frame. + */ + @Deprecated( + "Use the codec instead.", + replaceWith = ReplaceWith("tag.deserializeWithCodec(SpellContinuation.getCodec(world))") + ) + @JvmStatic + fun fromNBT(nbt: CompoundTag, world: ServerLevel): SpellContinuation = + nbt.deserializeWithCodec(getCodec(world))!! + + private fun fromList(frames: List): SpellContinuation { var result: SpellContinuation = Done for (frame in frames.asReversed()) { if (frame is CompoundTag) { - result = result.pushFrame(ContinuationFrame.fromNBT(frame, world)) + result = result.pushFrame(frame) } } return result diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/BooleanIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/BooleanIota.java index 91cf0b339d..1fb1e3802b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/BooleanIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/BooleanIota.java @@ -1,9 +1,11 @@ package at.petrak.hexcasting.api.casting.iota; +import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.mojang.serialization.Codec; import net.minecraft.ChatFormatting; -import net.minecraft.nbt.ByteTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -31,22 +33,38 @@ public boolean toleratesOther(Iota that) { && this.getBool() == b.getBool(); } + /** + * @deprecated + * Use {@link BooleanIota#TYPE#getCodec} instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - // there is no boolean tag :( - return ByteTag.valueOf(this.getBool()); + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } public static IotaType TYPE = new IotaType<>() { + + @Override + public Codec getCodec() { + return Codec.BOOL.xmap(BooleanIota::new, BooleanIota::getBool); + } + + /** + * @deprecated + * Use {@link BooleanIota#TYPE#getCodec} instead. + */ + @Deprecated @Nullable @Override public BooleanIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return BooleanIota.deserialize(tag); + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } + @Override public Component display(Tag tag) { - return BooleanIota.display(BooleanIota.deserialize(tag).getBool()); + return BooleanIota.display(HexUtils.deserializeWithCodec(tag, getCodec()).getBool()); } @Override @@ -56,11 +74,6 @@ public int color() { } }; - public static BooleanIota deserialize(Tag tag) throws IllegalArgumentException { - var dtag = HexUtils.downcast(tag, ByteTag.TYPE); - return new BooleanIota(dtag.getAsByte() != 0); - } - public static Component display(boolean b) { return Component.translatable(b ? "hexcasting.tooltip.boolean_true" : "hexcasting.tooltip.boolean_false") .withStyle(b ? ChatFormatting.DARK_GREEN : ChatFormatting.DARK_RED); diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ContinuationIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ContinuationIota.java index 13764c4675..80a622bb60 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ContinuationIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ContinuationIota.java @@ -1,20 +1,29 @@ package at.petrak.hexcasting.api.casting.iota; +import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.casting.eval.CastResult; import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType; import at.petrak.hexcasting.api.casting.eval.vm.CastingVM; +import at.petrak.hexcasting.api.casting.eval.vm.ContinuationFrame; import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation; import at.petrak.hexcasting.api.utils.HexUtils; +import at.petrak.hexcasting.common.lib.hex.HexContinuationTypes; import at.petrak.hexcasting.common.lib.hex.HexEvalSounds; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.google.common.base.Suppliers; +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.function.Supplier; /** * An iota storing a continuation (in essence an execution state). @@ -40,10 +49,14 @@ public boolean toleratesOther(Iota that) { return typesMatch(this, that) && that instanceof ContinuationIota cont && cont.getContinuation().equals(getContinuation()); } + /** + * @deprecated + * Use {@link ContinuationIota#TYPE#getCodec} instead. + */ + @Deprecated @Override - public @NotNull - Tag serialize() { - return getContinuation().serializeToNBT(); + public @NotNull Tag serialize() { + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } @Override @@ -71,9 +84,24 @@ public int size() { public static IotaType TYPE = new IotaType<>() { @Override - public @NotNull ContinuationIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - var compoundTag = HexUtils.downcast(tag, CompoundTag.TYPE); - return new ContinuationIota(SpellContinuation.fromNBT(compoundTag, world)); + public Codec getCodec() { + return SpellContinuation.getCodec().xmap(ContinuationIota::new, ContinuationIota::getContinuation); + } + + @Override + public Codec getCodec(ServerLevel world) { + return SpellContinuation.getCodec(world).xmap(ContinuationIota::new, ContinuationIota::getContinuation); + } + + /** + * @deprecated + * Use {@link DoubleIota#TYPE#getCodec} instead. + */ + @Deprecated + @Nullable + @Override + public ContinuationIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + return HexUtils.deserializeWithCodec(tag, getCodec()); } @Override diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/DoubleIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/DoubleIota.java index e9ff20f57c..62ad1468c7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/DoubleIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/DoubleIota.java @@ -1,9 +1,12 @@ package at.petrak.hexcasting.api.casting.iota; +import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.mojang.serialization.Codec; import net.minecraft.ChatFormatting; import net.minecraft.nbt.DoubleTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -37,21 +40,37 @@ public static boolean tolerates(double a, double b) { return Math.abs(a - b) < TOLERANCE; } + /** + * @deprecated + * Use {@link DoubleIota#TYPE#getCodec()} instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - return DoubleTag.valueOf(this.getDouble()); + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } public static IotaType TYPE = new IotaType<>() { + + @Override + public Codec getCodec() { + return Codec.DOUBLE.xmap(DoubleIota::new, DoubleIota::getDouble); + } + + /** + * @deprecated + * Use {@link DoubleIota#TYPE#getCodec} instead. + */ + @Deprecated @Nullable @Override public DoubleIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return DoubleIota.deserialize(tag); + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } @Override public Component display(Tag tag) { - return DoubleIota.display(DoubleIota.deserialize(tag).getDouble()); + return DoubleIota.display(HexUtils.deserializeWithCodec(tag, getCodec()).getDouble()); } @Override @@ -60,10 +79,6 @@ public int color() { } }; - public static DoubleIota deserialize(Tag tag) throws IllegalArgumentException { - var dtag = HexUtils.downcast(tag, DoubleTag.TYPE); - return new DoubleIota(dtag.getAsDouble()); - } public static Component display(double d) { return Component.literal(String.format("%.2f", d)).withStyle(ChatFormatting.GREEN); diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/EntityIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/EntityIota.java index fe2ee51f45..19d979e810 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/EntityIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/EntityIota.java @@ -2,30 +2,63 @@ import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; +import net.minecraft.core.UUIDUtil; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.ExtraCodecs; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.UUID; + public class EntityIota extends Iota { + + + record Payload(UUID uuid, Component name) { + } + public EntityIota(@NotNull Entity e) { - super(HexIotaTypes.ENTITY, e); + this(e.getUUID(), e.getName()); + } + + private EntityIota(@NotNull UUID uuid, @NotNull Component name) { + this(new Payload(uuid, name)); + } + + private EntityIota(Payload payload) { + super(HexIotaTypes.ENTITY, payload); + } + + private Boolean isTrueName = false; + + public Boolean isTrueName() { + return isTrueName; + } + + public Component getName() { + return ((Payload) this.payload).name; + } + + public UUID getUUID() { + return ((Payload) this.payload).uuid; } - public Entity getEntity() { - return (Entity) this.payload; + @Nullable + public Entity getEntity(ServerLevel world) { + return world.getEntity(getUUID()); } @Override public boolean toleratesOther(Iota that) { return typesMatch(this, that) - && that instanceof EntityIota dent - && this.getEntity() == dent.getEntity(); + && that instanceof EntityIota dent + && this.getUUID() == dent.getUUID(); } @Override @@ -33,47 +66,58 @@ public boolean isTruthy() { return true; } + /** + * @deprecated Use {@link EntityIota#TYPE#getCodec) instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - var out = new CompoundTag(); - out.putUUID("uuid", this.getEntity().getUUID()); - out.putString("name", Component.Serializer.toJson(this.getEntity().getName())); - return out; + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } @Override public Component display() { - return this.getEntity().getName().copy().withStyle(ChatFormatting.AQUA); + return this.getName().copy().withStyle(ChatFormatting.AQUA); } public static IotaType TYPE = new IotaType<>() { - @Nullable + @Override - public EntityIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - var ctag = HexUtils.downcast(tag, CompoundTag.TYPE); - Tag uuidTag = ctag.get("uuid"); - if (uuidTag == null) { - return null; - } - var uuid = NbtUtils.loadUUID(uuidTag); - var entity = world.getEntity(uuid); + public Codec getCodec() { + return RecordCodecBuilder.create(instance -> instance.group( + UUIDUtil.CODEC.fieldOf("uuid").forGetter(Payload::uuid), + ExtraCodecs.COMPONENT.fieldOf("name").forGetter(Payload::name) + ).apply(instance, Payload::new)).xmap(EntityIota::new, iota -> (Payload) iota.payload); + } + + @Override + protected boolean validate(EntityIota iota, ServerLevel world) { + var entity = iota.getEntity(world); if (entity == null) { - return null; + return false; + } else { + iota.isTrueName = entity instanceof Player; + return true; } - return new EntityIota(entity); + } + + /** + * @deprecated + * Use {@link EntityIota#TYPE#getCodec} instead. + */ + @Deprecated + @Nullable + @Override + public EntityIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } @Override public Component display(Tag tag) { - if (!(tag instanceof CompoundTag ctag)) { - return Component.translatable("hexcasting.spelldata.entity.whoknows"); - } - if (!ctag.contains("name", Tag.TAG_STRING)) { - return Component.translatable("hexcasting.spelldata.entity.whoknows"); - } - var nameJson = ctag.getString("name"); - return Component.Serializer.fromJsonLenient(nameJson).withStyle(ChatFormatting.AQUA); + var data = HexUtils.deserializeWithCodec(tag, getCodec()); + + return data.getName().copy().withStyle(ChatFormatting.AQUA); } @Override diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/GarbageIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/GarbageIota.java index 0824985852..31f6970a89 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/GarbageIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/GarbageIota.java @@ -1,8 +1,12 @@ package at.petrak.hexcasting.api.casting.iota; +import at.petrak.hexcasting.api.HexAPI; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.mojang.serialization.Codec; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -38,16 +42,26 @@ public boolean toleratesOther(Iota that) { return typesMatch(this, that); } + /** + * @deprecated + * Use {@link GarbageIota#TYPE#getCodec} instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - return new CompoundTag(); + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } public static IotaType TYPE = new IotaType<>() { + @Override + public Codec getCodec() { + return Codec.unit(GarbageIota::new); + } + @Nullable @Override public GarbageIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return new GarbageIota(); + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } @Override diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Iota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Iota.java index 7f024abc94..178a93b0d4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Iota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Iota.java @@ -11,6 +11,9 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapUnescapedValue; import at.petrak.hexcasting.common.lib.hex.HexEvalSounds; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.google.common.base.Suppliers; +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -18,8 +21,32 @@ import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Optional; +import java.util.function.Supplier; public abstract class Iota { + + /** + * Get a generic Iota codec for encoding/decoding any Iota, without validating iotas. + * This codec is useful for serialization, and deserialization on the client side. + * @return an Iota codec. + */ + public static Codec getCodec() { + return HexIotaTypes.REGISTRY.byNameCodec().dispatchMap(HexIotaTypes.KEY_TYPE, Iota::getType, + iotaType -> iotaType.getCodec().fieldOf(HexIotaTypes.KEY_DATA).codec()).codec(); + } + + /** + * Get a generic Iota codec for encoding/decoding any Iota, validating iotas using the given world. + * This codec is useful for deserialization on the server side. + * @param world the world to be used for validation + * @return an Iota codec + */ + public static Codec getCodec(@Nullable ServerLevel world) { + return HexIotaTypes.REGISTRY.byNameCodec().dispatchMap(HexIotaTypes.KEY_TYPE, Iota::getType, + iotaType -> iotaType.getCodec(world).fieldOf(HexIotaTypes.KEY_DATA).codec()).codec().orElseGet(NullIota::new); + } + @NotNull protected final Object payload; @NotNull @@ -45,7 +72,11 @@ protected Iota(@NotNull IotaType type, @NotNull Object payload) { * Serialize this under the {@code data} tag. *

* You probably don't want to call this directly; use {@link IotaType#serialize}. + * + * @deprecated + * Use the Iota's {@code CODEC} instead. */ + @Deprecated abstract public @NotNull Tag serialize(); /** @@ -54,17 +85,17 @@ protected Iota(@NotNull IotaType type, @NotNull Object payload) { */ public @NotNull CastResult execute(CastingVM vm, ServerLevel world, SpellContinuation continuation) { return new CastResult( - this, - continuation, - null, // Should never matter - List.of( - new OperatorSideEffect.DoMishap( - new MishapUnescapedValue(this), - new Mishap.Context(new HexPattern(HexDir.WEST, List.of()), null) - ) - ), - ResolvedPatternType.INVALID, - HexEvalSounds.MISHAP); + this, + continuation, + null, // Should never matter + List.of( + new OperatorSideEffect.DoMishap( + new MishapUnescapedValue(this), + new Mishap.Context(new HexPattern(HexDir.WEST, List.of()), null) + ) + ), + ResolvedPatternType.INVALID, + HexEvalSounds.MISHAP); } /** diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaType.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaType.java index 4bcf9b4b1f..454b0dbfc0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaType.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaType.java @@ -4,9 +4,13 @@ import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.MapCodec; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.Font; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TextColor; @@ -19,10 +23,38 @@ import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.function.Function; +import java.util.function.Supplier; // Take notes from ForgeRegistryEntry public abstract class IotaType { + public abstract Codec getCodec(); + + public Codec getCodec(ServerLevel world) { + Function> validate = iota -> { + if (validate(iota, world)) { + return DataResult.success(iota); + } else { + return DataResult.error(() -> "iota validation failed"); + } + }; + + return getCodec().flatXmap(validate, validate); + } + + /** + * Validates an iota using the world. + * This can be used for iotas the reference things that may not currently be present in the world, like entities. + * + * @param iota the iota to validate + * @param world the world to use for validation + * @return true if the iota is valid. false if it is not. + */ + protected boolean validate(T iota, ServerLevel world) { + return true; + } + /** * Spell datums are stored as such: {@code { "type": "modid:type", "datum": a_tag }}. *

@@ -31,7 +63,10 @@ public abstract class IotaType { *

* Returning {@code null} makes the resulting datum be {@link NullIota}. * Throwing an exception raises a mishap. + * + * @deprecated use {@code Codec} from {@link IotaType#getCodec()} instead. */ + @Deprecated @Nullable public abstract T deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException; @@ -52,28 +87,15 @@ public abstract class IotaType { public Component typeName() { var key = HexIotaTypes.REGISTRY.getKey(this); return Component.translatable("hexcasting.iota." + key) - .withStyle(style -> style.withColor(TextColor.fromRgb(color()))); + .withStyle(style -> style.withColor(TextColor.fromRgb(color()))); } + /** + * @deprecated Use {@link Iota#getCodec()} instead. + */ + @Deprecated public static CompoundTag serialize(Iota iota) { - var type = iota.getType(); - var typeId = HexIotaTypes.REGISTRY.getKey(type); - if (typeId == null) { - throw new IllegalStateException( - "Tried to serialize an unregistered iota type. Iota: " + iota - + " ; Type" + type.getClass().getTypeName()); - } - - // We check if it's too big on serialization; if it is we just return a garbage. - if (isTooLargeToSerialize(List.of(iota), 0)) { - // Garbage will never be too large so we just recurse - return serialize(new GarbageIota()); - } - var dataTag = iota.serialize(); - var out = new CompoundTag(); - out.putString(HexIotaTypes.KEY_TYPE, typeId.toString()); - out.put(HexIotaTypes.KEY_DATA, dataTag); - return out; + return (CompoundTag) Iota.getCodec().encodeStart(NbtOps.INSTANCE, iota).resultOrPartial(HexAPI.LOGGER::error).orElseThrow(); } public static boolean isTooLargeToSerialize(Iterable examinee) { @@ -139,29 +161,17 @@ public static IotaType getTypeFromTag(CompoundTag tag) { * "data": {...} * } * + * + * @deprecated Use {@link Iota#getCodec()} instead. */ + @Deprecated public static Iota deserialize(CompoundTag tag, ServerLevel world) { - var type = getTypeFromTag(tag); - if (type == null) { - return new GarbageIota(); - } - var data = tag.get(HexIotaTypes.KEY_DATA); - if (data == null) { - return new GarbageIota(); - } - Iota deserialized; - try { - deserialized = Objects.requireNonNullElse(type.deserialize(data, world), new NullIota()); - } catch (IllegalArgumentException exn) { - HexAPI.LOGGER.warn("Caught an exception deserializing an iota", exn); - deserialized = new GarbageIota(); - } - return deserialized; + return Iota.getCodec(world).parse(NbtOps.INSTANCE, tag).resultOrPartial(HexAPI.LOGGER::error).orElseThrow(); } private static Component brokenIota() { return Component.translatable("hexcasting.spelldata.unknown") - .withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC); + .withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC); } public static Component getDisplay(CompoundTag tag) { @@ -194,7 +204,7 @@ else if (splitted.size() == 1) else { var first = splitted.get(0); return FormattedCharSequence.fromPair(first, - Component.literal("...").withStyle(ChatFormatting.GRAY).getVisualOrderText()); + Component.literal("...").withStyle(ChatFormatting.GRAY).getVisualOrderText()); } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ListIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ListIota.java index 255d54662f..cd1c9d17ef 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ListIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ListIota.java @@ -1,11 +1,14 @@ package at.petrak.hexcasting.api.casting.iota; +import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.casting.SpellList; import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.mojang.serialization.Codec; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -64,13 +67,14 @@ public boolean toleratesOther(Iota that) { } } + /** + * @deprecated + * use {@link ListIota#TYPE#getCodec} instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - var out = new ListTag(); - for (var subdatum : this.getList()) { - out.add(IotaType.serialize(subdatum)); - } - return out; + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } @Override @@ -79,27 +83,31 @@ public boolean toleratesOther(Iota that) { } public static IotaType TYPE = new IotaType<>() { - @Nullable @Override - public ListIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - var listTag = HexUtils.downcast(tag, ListTag.TYPE); - var out = new ArrayList(listTag.size()); + public Codec getCodec() { + return SpellList.getCodec().xmap(ListIota::new, ListIota::getList); + } - for (var sub : listTag) { - var csub = HexUtils.downcast(sub, CompoundTag.TYPE); - var subiota = IotaType.deserialize(csub, world); - if (subiota == null) { - return null; - } - out.add(subiota); - } + @Override + public Codec getCodec(ServerLevel world) { + return SpellList.getCodec(world).xmap(ListIota::new, ListIota::getList); + } - return new ListIota(out); + /** + * @deprecated + * use {@link ListIota#TYPE#getCodec} instead. + */ + @Deprecated + @Nullable + @Override + public ListIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } @Override public Component display(Tag tag) { var out = Component.empty(); + var list = HexUtils.downcast(tag, ListTag.TYPE); for (int i = 0; i < list.size(); i++) { Tag sub = list.get(i); diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/NullIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/NullIota.java index 525e6b22a9..f9f68ee4de 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/NullIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/NullIota.java @@ -1,8 +1,12 @@ package at.petrak.hexcasting.api.casting.iota; +import at.petrak.hexcasting.api.HexAPI; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.mojang.serialization.Codec; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -34,16 +38,32 @@ public boolean toleratesOther(Iota that) { return typesMatch(this, that); } + /** + * @deprecated + * use {@link NullIota#TYPE#getCodec} instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - return new CompoundTag(); + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } public static IotaType TYPE = new IotaType<>() { + + @Override + public Codec getCodec() { + return Codec.unit(NullIota::new); + } + + /** + * @deprecated + * use {@link NullIota#TYPE#getCodec} instead. + */ + @Deprecated @Nullable @Override public NullIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return new NullIota(); + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } @Override diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java index 6b52868ad6..aad20352eb 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java @@ -21,8 +21,10 @@ import at.petrak.hexcasting.common.lib.hex.HexEvalSounds; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import at.petrak.hexcasting.xplat.IXplatAbstractions; +import com.mojang.serialization.Codec; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; @@ -61,9 +63,14 @@ public boolean toleratesOther(Iota that) { && this.getPattern().getAngles().equals(piota.getPattern().getAngles()); } + /** + * @deprecated + * Use {@link PatternIota#TYPE#getCodec} instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - return this.getPattern().serializeToNBT(); + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } @Override @@ -140,14 +147,25 @@ public boolean executable() { } public static IotaType TYPE = new IotaType<>() { + + @Override + public Codec getCodec() { + return HexPattern.CODEC.xmap(PatternIota::new, PatternIota::getPattern); + } + + /** + * @deprecated + * Use {@link PatternIota#TYPE#getCodec} instead. + */ + @Deprecated @Override public PatternIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return PatternIota.deserialize(tag); + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } @Override public Component display(Tag tag) { - return PatternIota.display(PatternIota.deserialize(tag).getPattern()); + return PatternIota.display(HexUtils.deserializeWithCodec(tag, getCodec()).getPattern()); } @Override @@ -156,12 +174,6 @@ public int color() { } }; - public static PatternIota deserialize(Tag tag) throws IllegalArgumentException { - var patTag = HexUtils.downcast(tag, CompoundTag.TYPE); - HexPattern pat = HexPattern.fromNBT(patTag); - return new PatternIota(pat); - } - public static Component display(HexPattern pat) { var bob = new StringBuilder(); bob.append(pat.getStartDir()); diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Vec3Iota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Vec3Iota.java index 9d9d7fbf67..5396845d88 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Vec3Iota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Vec3Iota.java @@ -1,10 +1,16 @@ package at.petrak.hexcasting.api.casting.iota; +import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.LongArrayTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -12,18 +18,46 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; + public class Vec3Iota extends Iota { + + private record Vec3CompoundRepresentation(double x, double y, double z) { + static Codec CODEC = RecordCodecBuilder.create( + instance -> instance.group( + Codec.DOUBLE.fieldOf("x").forGetter(Vec3CompoundRepresentation::x), + Codec.DOUBLE.fieldOf("y").forGetter(Vec3CompoundRepresentation::y), + Codec.DOUBLE.fieldOf("z").forGetter(Vec3CompoundRepresentation::z) + ).apply(instance, Vec3CompoundRepresentation::new)) + .xmap(Vec3CompoundRepresentation::toVec3, Vec3CompoundRepresentation::fromVec3); + + static Vec3CompoundRepresentation fromVec3(Vec3 vec) { + return new Vec3CompoundRepresentation(vec.x, vec.y, vec.z); + } + + Vec3 toVec3() { + return new Vec3(x, y, z); + } + } + + private static final Codec Vec3CursedCodec = Codec.LONG.listOf().xmap( + list -> new Vec3( + Double.longBitsToDouble(list.get(0)), + Double.longBitsToDouble(list.get(1)), + Double.longBitsToDouble(list.get(2))), + vec -> List.of( + Double.doubleToLongBits(vec.x), + Double.doubleToLongBits(vec.y), + Double.doubleToLongBits(vec.z)) + ); + public Vec3Iota(@NotNull Vec3 datum) { super(HexIotaTypes.VEC3, datum); } public Vec3 getVec3() { var v = (Vec3) this.payload; - return new Vec3( - HexUtils.fixNAN(v.x), - HexUtils.fixNAN(v.y), - HexUtils.fixNAN(v.z) - ); + return new Vec3(HexUtils.fixNAN(v.x), HexUtils.fixNAN(v.y), HexUtils.fixNAN(v.z)); } @Override @@ -34,26 +68,45 @@ public boolean isTruthy() { @Override public boolean toleratesOther(Iota that) { - return typesMatch(this, that) - && that instanceof Vec3Iota viota - && this.getVec3().distanceToSqr(viota.getVec3()) < DoubleIota.TOLERANCE * DoubleIota.TOLERANCE; + return typesMatch(this, that) && that instanceof Vec3Iota viota && this.getVec3().distanceToSqr(viota.getVec3()) < DoubleIota.TOLERANCE * DoubleIota.TOLERANCE; } + /** + * @deprecated use {@link Vec3Iota#TYPE#getCodec} instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - return HexUtils.serializeToNBT(this.getVec3()); + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } public static IotaType TYPE = new IotaType<>() { + + @Override + public Codec getCodec() { + return Codec.either(Vec3CompoundRepresentation.CODEC, Vec3CursedCodec).flatXmap(either -> { + if (either.left().isPresent()) { + return DataResult.success(new Vec3Iota(either.left().get())); + } else if (either.right().isPresent()) { + return DataResult.success(new Vec3Iota(either.right().get())); + } else return DataResult.error(() -> "Not a valid Vec3 format: " + either); + }, iota -> DataResult.success(Either.left(iota.getVec3()))); + } + + /** + * @deprecated + * use {@link Vec3Iota#TYPE#getCodec} instead. + */ + @Deprecated @Nullable @Override public Vec3Iota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return Vec3Iota.deserialize(tag); + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } @Override public Component display(Tag tag) { - return Vec3Iota.display(Vec3Iota.deserialize(tag).getVec3()); + return Vec3Iota.display(HexUtils.deserializeWithCodec(tag, getCodec()).getVec3()); } @Override @@ -67,14 +120,12 @@ public static Vec3Iota deserialize(Tag tag) throws IllegalArgumentException { if (tag.getType() == LongArrayTag.TYPE) { var lat = HexUtils.downcast(tag, LongArrayTag.TYPE); vec = HexUtils.vecFromNBT(lat.getAsLongArray()); - } else - vec = HexUtils.vecFromNBT(HexUtils.downcast(tag, CompoundTag.TYPE)); + } else vec = HexUtils.vecFromNBT(HexUtils.downcast(tag, CompoundTag.TYPE)); return new Vec3Iota(vec); } public static Component display(double x, double y, double z) { - return Component.literal(String.format("(%.2f, %.2f, %.2f)", x, y, z)) - .withStyle(ChatFormatting.RED); + return Component.literal(String.format("(%.2f, %.2f, %.2f)", x, y, z)).withStyle(ChatFormatting.RED); } public static Component display(Vec3 v) { diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexAngle.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexAngle.kt index bca8b0b94b..505452f2be 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexAngle.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexAngle.kt @@ -1,8 +1,15 @@ package at.petrak.hexcasting.api.casting.math +import com.mojang.serialization.Codec + enum class HexAngle { FORWARD, RIGHT, RIGHT_BACK, BACK, LEFT_BACK, LEFT; fun rotatedBy(a: HexAngle) = values()[(this.ordinal + a.ordinal) % values().size] operator fun times(a: HexAngle) = this.rotatedBy(a) + + companion object { + val CODEC: Codec = + Codec.BYTE.xmap({ ordinal -> HexAngle.values()[ordinal.toInt()] }, { dir -> dir.ordinal.toByte() }) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexDir.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexDir.kt index 514cb0e467..75ec5eeba8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexDir.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexDir.kt @@ -1,6 +1,7 @@ package at.petrak.hexcasting.api.casting.math import at.petrak.hexcasting.api.utils.getSafe +import com.mojang.serialization.Codec enum class HexDir { NORTH_EAST, EAST, SOUTH_EAST, SOUTH_WEST, WEST, NORTH_WEST; @@ -26,6 +27,10 @@ enum class HexDir { } companion object { + @JvmStatic + val CODEC: Codec = + Codec.BYTE.xmap({ ordinal -> HexDir.values()[ordinal.toInt()] }, { dir -> dir.ordinal.toByte() }) + @JvmStatic fun fromString(key: String): HexDir { return values().getSafe(key, WEST) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexPattern.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexPattern.kt index ba34ef77b1..bd6eb505ee 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexPattern.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexPattern.kt @@ -1,7 +1,11 @@ package at.petrak.hexcasting.api.casting.math +import at.petrak.hexcasting.api.HexAPI +import at.petrak.hexcasting.api.utils.NBTBuilder import at.petrak.hexcasting.api.utils.coordToPx import at.petrak.hexcasting.api.utils.findCenter +import at.petrak.hexcasting.api.utils.getSafe +import com.google.common.collect.ImmutableList import com.mojang.serialization.Codec import com.mojang.serialization.codecs.RecordCodecBuilder import net.minecraft.nbt.CompoundTag @@ -9,7 +13,6 @@ import net.minecraft.nbt.NbtOps import net.minecraft.nbt.Tag import net.minecraft.world.phys.Vec2 import java.util.Collections -import at.petrak.hexcasting.api.HexAPI /** * Sequence of angles to define a pattern traced. @@ -143,7 +146,7 @@ data class HexPattern(public val startDir: HexDir, public val angles: MutableLis @JvmStatic fun isPattern(tag: CompoundTag): Boolean { return tag.contains(TAG_START_DIR, Tag.TAG_ANY_NUMERIC.toInt()) - && tag.contains(TAG_ANGLES, Tag.TAG_BYTE_ARRAY.toInt()) + && tag.contains(TAG_ANGLES, Tag.TAG_BYTE_ARRAY.toInt()) } @Deprecated( diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityNotFound.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityNotFound.kt new file mode 100644 index 0000000000..55f1a136e8 --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityNotFound.kt @@ -0,0 +1,22 @@ +package at.petrak.hexcasting.api.casting.mishaps + +import at.petrak.hexcasting.api.casting.eval.CastingEnvironment +import at.petrak.hexcasting.api.casting.iota.Iota +import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.api.utils.aqua +import at.petrak.hexcasting.api.utils.asTranslatedComponent +import net.minecraft.network.chat.Component +import net.minecraft.world.entity.Entity +import net.minecraft.world.entity.item.ItemEntity +import net.minecraft.world.item.DyeColor + +class MishapEntityNotFound : Mishap() { + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.BROWN) + + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + } + + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("entity_not_found") +} \ No newline at end of file diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt index e6ea0326ed..d916a4e1ba 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt @@ -5,6 +5,7 @@ import at.petrak.hexcasting.api.casting.iota.EntityIota import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.ListIota import at.petrak.hexcasting.api.pigment.FrozenPigment +import net.minecraft.server.level.ServerLevel import net.minecraft.world.entity.player.Player import net.minecraft.world.item.DyeColor @@ -33,14 +34,17 @@ class MishapOthersName(val confidant: Player) : Mishap() { * If `caster` is non-null, it will ignore that when checking. */ @JvmStatic - fun getTrueNameFromDatum(datum: Iota, caster: Player?): Player? { + fun getTrueNameFromDatum(datum: Iota, caster: Player?, world: ServerLevel): Player? { val poolToSearch = ArrayDeque() poolToSearch.addLast(datum) while (poolToSearch.isNotEmpty()) { val datumToCheck = poolToSearch.removeFirst() - if (datumToCheck is EntityIota && datumToCheck.entity is Player && datumToCheck.entity != caster) - return datumToCheck.entity as Player + if (datumToCheck is EntityIota && datumToCheck.isTrueName) { + val player = datumToCheck.getEntity(world) as Player + if (player != caster) + return player + } val datumSubIotas = datumToCheck.subIotas() if (datumSubIotas != null) poolToSearch.addAll(datumSubIotas) @@ -50,8 +54,8 @@ class MishapOthersName(val confidant: Player) : Mishap() { } @JvmStatic - fun getTrueNameFromArgs(datums: List, caster: Player?): Player? { - return datums.firstNotNullOfOrNull { getTrueNameFromDatum(it, caster) } + fun getTrueNameFromArgs(datums: List, caster: Player?, world: ServerLevel): Player? { + return datums.firstNotNullOfOrNull { getTrueNameFromDatum(it, caster, world) } } } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java b/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java index c312383129..b2fe3e5b58 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java @@ -46,7 +46,7 @@ default Iota readIota(ItemStack stack, ServerLevel world) { var tag = dh.readIotaTag(stack); if (tag != null) { - return IotaType.deserialize(tag, world); + return HexUtils.deserializeWithCodec(tag, Iota.getCodec(world)); } else { return null; } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt b/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt index 209297766a..fc428439c7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt @@ -2,10 +2,14 @@ package at.petrak.hexcasting.api.utils +import at.petrak.hexcasting.api.HexAPI 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.casting.math.HexCoord +import com.mojang.serialization.Codec +import com.mojang.serialization.MapCodec +import com.mojang.serialization.codecs.OptionalFieldCodec import net.minecraft.ChatFormatting import net.minecraft.core.Registry import net.minecraft.nbt.* @@ -44,6 +48,7 @@ fun vecFromNBT(tag: LongArray): Vec3 = if (tag.size != 3) Vec3.ZERO else Double.fromBits(tag[1]), Double.fromBits(tag[2]) ) + fun vecFromNBT(tag: CompoundTag): Vec3 { return if (!tag.contains("x") || !tag.contains("y") || !tag.contains("z")) Vec3.ZERO @@ -313,3 +318,18 @@ fun isOfTag(registry: Registry, loc: ResourceLocation, tag: TagKey): B val key = ResourceKey.create(registry.key(), loc); return isOfTag(registry, key, tag) } + +fun Codec.nullableFieldOf(name: String): MapCodec { + return OptionalFieldCodec(name, this).xmap( + { optional -> if (optional.isPresent) optional.get() else null }, + { obj -> Optional.ofNullable(obj) } + ) +} + +fun T.serializeWithCodec(codec: Codec): Tag? { + return codec.encodeStart(NbtOps.INSTANCE, this).resultOrPartial(HexAPI.LOGGER::error).orElse(null) +} + +fun Tag.deserializeWithCodec(codec: Codec): T? { + return codec.parse(NbtOps.INSTANCE, this).resultOrPartial(HexAPI.LOGGER::error).orElse(null) +} \ No newline at end of file diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicRecord.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicRecord.java index db3f96ac14..71cf6bae11 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicRecord.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicRecord.java @@ -3,6 +3,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.casting.math.HexPattern; +import at.petrak.hexcasting.api.utils.HexUtils; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.Level; @@ -57,7 +58,7 @@ Iota lookupPattern(BlockPos herePos, HexPattern key, ServerLevel slevel) { var tile = (BlockEntityAkashicBookshelf) slevel.getBlockEntity(foundPos); var tag = tile.getIotaTag(); - return tag == null ? null : IotaType.deserialize(tag, slevel); + return tag == null ? null : HexUtils.deserializeWithCodec(tag, Iota.getCodec()); } // TODO get comparators working again and also cache the number of iotas somehow? diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockEntityAkashicBookshelf.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockEntityAkashicBookshelf.java index d6e4cd8041..03b6a917f3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockEntityAkashicBookshelf.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockEntityAkashicBookshelf.java @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.casting.math.HexPattern; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.client.render.HexPatternPoints; import at.petrak.hexcasting.common.lib.HexBlockEntities; import net.minecraft.core.BlockPos; @@ -42,7 +43,7 @@ public CompoundTag getIotaTag() { public void setNewMapping(HexPattern pattern, Iota iota) { var previouslyEmpty = this.pattern == null; this.pattern = pattern; - this.iotaTag = IotaType.serialize(iota); + this.iotaTag = (CompoundTag) HexUtils.serializeWithCodec(iota, Iota.getCodec()); if (previouslyEmpty) { var oldBs = this.getBlockState(); diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityHeight.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityHeight.kt index eea382d0e4..f08b0ac545 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityHeight.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityHeight.kt @@ -10,7 +10,7 @@ object OpEntityHeight : ConstMediaAction { override val argc = 1 override fun execute(args: List, env: CastingEnvironment): List { - val e = args.getEntity(0, argc) + val e = args.getEntity(0, argc, env.world) env.assertEntityInRange(e) return e.bbHeight.asActionResult } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityLook.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityLook.kt index 14faec64eb..8846eea496 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityLook.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityLook.kt @@ -10,7 +10,7 @@ object OpEntityLook : ConstMediaAction { override val argc = 1 override fun execute(args: List, env: CastingEnvironment): List { - val e = args.getEntity(0, argc) + val e = args.getEntity(0, argc, env.world) env.assertEntityInRange(e) return e.lookAngle.asActionResult } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityPos.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityPos.kt index 80ab0e23f0..f92d9fd98a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityPos.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityPos.kt @@ -10,7 +10,7 @@ class OpEntityPos(val feet: Boolean) : ConstMediaAction { override val argc = 1 override fun execute(args: List, env: CastingEnvironment): List { - val e = args.getEntity(0, argc) + val e = args.getEntity(0, argc, env.world) env.assertEntityInRange(e) return (if (this.feet) e.position() else e.eyePosition).asActionResult } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityVelocity.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityVelocity.kt index b1b7330969..c6f6291c15 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityVelocity.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityVelocity.kt @@ -11,7 +11,7 @@ object OpEntityVelocity : ConstMediaAction { override val argc = 1 override fun execute(args: List, env: CastingEnvironment): List { - val e = args.getEntity(0, argc) + val e = args.getEntity(0, argc, env.world) env.assertEntityInRange(e) val vel = HexAPI.instance().getEntityVelocitySpecial(e) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicWrite.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicWrite.kt index 2089965835..9f57d88437 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicWrite.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicWrite.kt @@ -34,7 +34,7 @@ object OpAkashicWrite : SpellAction { throw MishapNoAkashicRecord(pos) } - val trueName = MishapOthersName.getTrueNameFromDatum(datum, env.castingEntity as? ServerPlayer) + val trueName = MishapOthersName.getTrueNameFromDatum(datum, env.castingEntity as? ServerPlayer, env.world) if (trueName != null) throw MishapOthersName(trueName) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerRead.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerRead.kt index 4fd4a69f8b..dfe8a2f511 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerRead.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerRead.kt @@ -14,7 +14,7 @@ object OpTheCoolerRead : ConstMediaAction { args: List, env: CastingEnvironment ): List { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) env.assertEntityInRange(target) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerReadable.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerReadable.kt index aa118182af..0db1a1b3f1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerReadable.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerReadable.kt @@ -14,7 +14,7 @@ object OpTheCoolerReadable : ConstMediaAction { args: List, env: CastingEnvironment ): List { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) env.assertEntityInRange(target) val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(target) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWritable.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWritable.kt index 598ae8b145..ce32790676 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWritable.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWritable.kt @@ -15,7 +15,7 @@ object OpTheCoolerWritable : ConstMediaAction { args: List, env: CastingEnvironment ): List { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) env.assertEntityInRange(target) val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(target) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWrite.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWrite.kt index 27e02a8f97..7124ed3738 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWrite.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWrite.kt @@ -19,7 +19,7 @@ object OpTheCoolerWrite : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) val datum = args[1] env.assertEntityInRange(target) @@ -32,7 +32,7 @@ object OpTheCoolerWrite : SpellAction { // We pass null here so that even the own caster won't be allowed into a focus. // Otherwise, you could sentinel scout to people and remotely write their names into things using a cleric circle. - val trueName = MishapOthersName.getTrueNameFromDatum(datum, null) + val trueName = MishapOthersName.getTrueNameFromDatum(datum, null, env.world) if (trueName != null) throw MishapOthersName(trueName) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt index 317dbc0453..47a349323a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt @@ -37,7 +37,7 @@ object OpWrite : SpellAction { if (!datumHolder.writeIota(datum, true)) throw MishapBadOffhandItem.of(handStack, "iota.readonly", datum.display()) - val trueName = MishapOthersName.getTrueNameFromDatum(datum, env.castingEntity as? ServerPlayer) + val trueName = MishapOthersName.getTrueNameFromDatum(datum, env.castingEntity as? ServerPlayer, env.world) if (trueName != null) throw MishapOthersName(trueName) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpAddMotion.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpAddMotion.kt index 7f45168f85..c96b1a08b6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpAddMotion.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpAddMotion.kt @@ -25,7 +25,7 @@ object OpAddMotion : SpellAction { env: CastingEnvironment, userData: CompoundTag ): SpellAction.Result { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) val motion = args.getVec3(1, argc) env.assertEntityInRange(target) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBlink.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBlink.kt index f7fd817308..6f0120e4d0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBlink.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBlink.kt @@ -23,7 +23,7 @@ object OpBlink : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) val delta = args.getDouble(1, argc) env.assertEntityInRange(target) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt index 9258cc059e..25a5ad908e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt @@ -31,7 +31,7 @@ class OpFlight(val type: Type) : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val target = args.getPlayer(0, argc) + val target = args.getPlayer(0, argc, env.world) val theArg = args.getPositiveDouble(1, argc) env.assertEntityInRange(target) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakeBattery.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakeBattery.kt index 5e86b23504..84d3e71e9d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakeBattery.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakeBattery.kt @@ -26,7 +26,7 @@ object OpMakeBattery : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val entity = args.getItemEntity(0, argc) + val entity = args.getItemEntity(0, argc, env.world) val (handStack, hand) = env.getHeldItemToOperateOn { it.`is`(HexTags.Items.PHIAL_BASE) } ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), "bottle") // TODO: hack diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakePackagedSpell.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakePackagedSpell.kt index 2601a70696..a4bc84f7c2 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakePackagedSpell.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakePackagedSpell.kt @@ -25,7 +25,7 @@ class OpMakePackagedSpell(val itemType: T, val cost: Long) args: List, env: CastingEnvironment ): SpellAction.Result { - val entity = args.getItemEntity(0, argc) + val entity = args.getItemEntity(0, argc, env.world) val patterns = args.getList(1, argc).toList() val (handStack) = env.getHeldItemToOperateOn { @@ -54,7 +54,7 @@ class OpMakePackagedSpell(val itemType: T, val cost: Long) ) } - val trueName = MishapOthersName.getTrueNameFromArgs(patterns, env.castingEntity as? ServerPlayer) + val trueName = MishapOthersName.getTrueNameFromArgs(patterns, env.castingEntity as? ServerPlayer, env.world) if (trueName != null) throw MishapOthersName(trueName) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPotionEffect.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPotionEffect.kt index 6f7dc5a05e..5cecc45f66 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPotionEffect.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPotionEffect.kt @@ -21,7 +21,7 @@ class OpPotionEffect( args: List, env: CastingEnvironment ): SpellAction.Result { - val target = args.getLivingEntityButNotArmorStand(0, argc) + val target = args.getLivingEntityButNotArmorStand(0, argc, env.world) val duration = args.getPositiveDouble(1, argc) val potency = if (this.allowPotency) args.getDoubleBetween(2, 1.0, 127.0, argc) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpRecharge.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpRecharge.kt index 0b7fcb6dfd..77fb953431 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpRecharge.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpRecharge.kt @@ -21,7 +21,7 @@ object OpRecharge : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val entity = args.getItemEntity(0, argc) + val entity = args.getItemEntity(0, argc, env.world) val (handStack) = env.getHeldItemToOperateOn { val media = IXplatAbstractions.INSTANCE.findMediaHolder(it) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpAltiora.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpAltiora.kt index 515518cadc..3e73b310b5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpAltiora.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpAltiora.kt @@ -20,7 +20,7 @@ object OpAltiora : SpellAction { override val argc = 1 override fun execute(args: List, env: CastingEnvironment): SpellAction.Result { - val target = args.getPlayer(0, argc) + val target = args.getPlayer(0, argc, env.world) env.assertEntityInRange(target) return SpellAction.Result( diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpBrainsweep.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpBrainsweep.kt index b6325f685a..4ce4dedf9a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpBrainsweep.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpBrainsweep.kt @@ -35,7 +35,7 @@ object OpBrainsweep : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val sacrifice = args.getMob(0, argc) + val sacrifice = args.getMob(0, argc, env.world) val vecPos = args.getVec3(1, argc) val pos = BlockPos.containing(vecPos) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpTeleport.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpTeleport.kt index abd39e52e1..2d2fefb06a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpTeleport.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpTeleport.kt @@ -32,7 +32,7 @@ object OpTeleport : SpellAction { env: CastingEnvironment ): SpellAction.Result { - val teleportee = args.getEntity(0, argc) + val teleportee = args.getEntity(0, argc, env.world) val delta = args.getVec3(1, argc) env.assertEntityInRange(teleportee) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemPackagedHex.java b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemPackagedHex.java index a189fd0703..27f238dda5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemPackagedHex.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemPackagedHex.java @@ -8,6 +8,7 @@ import at.petrak.hexcasting.api.casting.iota.PatternIota; import at.petrak.hexcasting.api.item.HexHolderItem; import at.petrak.hexcasting.api.pigment.FrozenPigment; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.NBTHelper; import at.petrak.hexcasting.common.msgs.MsgNewSpiralPatternsS2C; import at.petrak.hexcasting.xplat.IXplatAbstractions; @@ -76,7 +77,7 @@ public boolean hasHex(ItemStack stack) { var out = new ArrayList(); for (var patTag : patsTag) { CompoundTag tag = NBTHelper.getAsCompound(patTag); - out.add(IotaType.deserialize(tag, level)); + out.add(HexUtils.deserializeWithCodec(tag, Iota.getCodec(level))); } return out; } @@ -85,7 +86,7 @@ public boolean hasHex(ItemStack stack) { public void writeHex(ItemStack stack, List program, @Nullable FrozenPigment pigment, long media) { ListTag patsTag = new ListTag(); for (Iota pat : program) { - patsTag.add(IotaType.serialize(pat)); + patsTag.add(HexUtils.serializeWithCodec(pat, Iota.getCodec())); } NBTHelper.putList(stack, TAG_PROGRAM, patsTag); diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemAbacus.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemAbacus.java index ad8527581f..21e7e6ea56 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemAbacus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemAbacus.java @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.item.IotaHolderItem; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.NBTHelper; import at.petrak.hexcasting.common.lib.HexSounds; import net.minecraft.nbt.CompoundTag; @@ -30,7 +31,7 @@ public ItemAbacus(Properties pProperties) { public @Nullable CompoundTag readIotaTag(ItemStack stack) { var datum = new DoubleIota(NBTHelper.getDouble(stack, TAG_VALUE)); - return IotaType.serialize(datum); + return (CompoundTag) HexUtils.serializeWithCodec(datum, Iota.getCodec()); } @Override diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java index 8d08c9923f..304252a1d9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.item.IotaHolderItem; import at.petrak.hexcasting.api.item.VariantItem; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -59,7 +60,7 @@ public void writeDatum(ItemStack stack, Iota datum) { stack.removeTagKey(TAG_DATA); stack.removeTagKey(TAG_SEALED); } else if (!isSealed(stack)) { - NBTHelper.put(stack, TAG_DATA, IotaType.serialize(datum)); + NBTHelper.put(stack, TAG_DATA, HexUtils.serializeWithCodec(datum, Iota.getCodec())); } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java index b7521f7619..6618ec760f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.item.IotaHolderItem; import at.petrak.hexcasting.api.item.VariantItem; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.NBTHelper; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; @@ -152,14 +153,14 @@ public void writeDatum(ItemStack stack, Iota datum) { pages.remove(key); NBTHelper.remove(NBTHelper.getCompound(stack, TAG_SEALED), key); } else { - pages.put(key, IotaType.serialize(datum)); + pages.put(key, HexUtils.serializeWithCodec(datum, Iota.getCodec())); } if (pages.isEmpty()) { NBTHelper.remove(stack, TAG_PAGES); } } else if (datum != null) { - NBTHelper.getOrCreateCompound(stack, TAG_PAGES).put(key, IotaType.serialize(datum)); + NBTHelper.getOrCreateCompound(stack, TAG_PAGES).put(key, HexUtils.serializeWithCodec(datum, Iota.getCodec())); } else { NBTHelper.remove(NBTHelper.getCompound(stack, TAG_SEALED), key); } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java index 9e867cc250..2d5b7880f4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java @@ -3,6 +3,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.item.IotaHolderItem; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -45,7 +46,7 @@ public boolean canWrite(ItemStack stack, @Nullable Iota iota) { @Override public void writeDatum(ItemStack stack, @Nullable Iota iota) { if (iota != null) { - NBTHelper.putCompound(stack, TAG_DATA, IotaType.serialize(iota)); + NBTHelper.put(stack, TAG_DATA, HexUtils.serializeWithCodec(iota, Iota.getCodec())); } } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpGetScale.kt b/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpGetScale.kt index d1a9868c51..828f1e17a6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpGetScale.kt +++ b/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpGetScale.kt @@ -11,7 +11,7 @@ object OpGetScale : ConstMediaAction { override val argc = 1 override fun execute(args: List, env: CastingEnvironment): List { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) env.assertEntityInRange(target) return IXplatAbstractions.INSTANCE.pehkuiApi.getScale(target).toDouble().asActionResult } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpSetScale.kt b/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpSetScale.kt index 9c171c5784..aa5c40ced9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpSetScale.kt +++ b/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpSetScale.kt @@ -17,7 +17,7 @@ object OpSetScale : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) val scale = args.getDoubleBetween(1, 1.0 / 32.0, 8.0, argc) env.assertEntityInRange(target) diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCItemIotaHolder.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCItemIotaHolder.java index 10e9566594..0b94fa551a 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCItemIotaHolder.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCItemIotaHolder.java @@ -3,6 +3,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.item.IotaHolderItem; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.fabric.cc.HexCardinalComponents; import dev.onyxstudios.cca.api.v3.item.ItemComponent; import net.minecraft.nbt.CompoundTag; @@ -61,7 +62,7 @@ public Static(ItemStack stack, Function provider) { @Override public @Nullable CompoundTag readIotaTag() { var iota = this.provider.apply(this.stack); - return iota == null ? null : IotaType.serialize(iota); + return iota == null ? null : (CompoundTag) HexUtils.serializeWithCodec(iota, Iota.getCodec()); } @Override