added registry for ContinuationFrame types!

This commit is contained in:
Talia-12 2023-07-20 22:38:21 +10:00
parent a1cb9f7fab
commit 4a1e4c3269
12 changed files with 193 additions and 32 deletions

View file

@ -3,14 +3,12 @@ package at.petrak.hexcasting.api.casting.eval.vm
import at.petrak.hexcasting.api.casting.SpellList
import at.petrak.hexcasting.api.casting.eval.CastResult
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.utils.getList
import at.petrak.hexcasting.api.utils.hasList
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes
import at.petrak.hexcasting.common.lib.hex.HexContinuationTypes
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel
// TODO this should probably be a registry too
/**
* A single frame of evaluation during the execution of a spell.
*
@ -49,34 +47,62 @@ sealed interface ContinuationFrame {
*/
fun size(): Int
val type: Type<*>
interface Type<U : ContinuationFrame> {
fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): U?
}
companion object {
/**
* Takes a tag containing the ContinuationFrame.Type resourcelocation and the serialized continuation frame, and returns
* the deserialized continuation frame.
*/
@JvmStatic
fun fromNBT(tag: CompoundTag, world: ServerLevel): ContinuationFrame {
return when (tag.getString("type")) {
"evaluate" -> FrameEvaluate(
HexIotaTypes.LIST.deserialize(
tag.getList("patterns", Tag.TAG_COMPOUND),
world
)!!.list,
tag.getBoolean("isMetacasting")
)
val type = getTypeFromTag(tag) ?: return FrameEvaluate(SpellList.LList(0, listOf()), false)
"end" -> FrameFinishEval
"foreach" -> 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()
)
else -> 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)
}
/**
* Takes a continuation frame and serializes it along with its type.
*/
@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]
}
}
}

View file

@ -6,8 +6,12 @@ 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.common.lib.hex.HexEvalSounds
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
import net.minecraft.server.level.ServerLevel
/**
@ -45,10 +49,26 @@ data class FrameEvaluate(val list: SpellList, val isMetacasting: Boolean) : Cont
}
override fun serializeToNBT() = NBTBuilder {
"type" %= "evaluate"
"patterns" %= list.serializeToNBT()
"isMetacasting" %= isMetacasting
}
override fun size() = list.size()
override val type: ContinuationFrame.Type<*> = TYPE
companion object {
@JvmField
val TYPE: ContinuationFrame.Type<FrameEvaluate> = object : ContinuationFrame.Type<FrameEvaluate> {
override fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): FrameEvaluate {
return FrameEvaluate(
HexIotaTypes.LIST.deserialize(
tag.getList("patterns", Tag.TAG_COMPOUND),
world
)!!.list,
tag.getBoolean("isMetacasting"))
}
}
}
}

View file

@ -6,6 +6,7 @@ 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.common.lib.hex.HexEvalSounds
import net.minecraft.nbt.CompoundTag
import net.minecraft.server.level.ServerLevel
/**
@ -32,9 +33,14 @@ object FrameFinishEval : ContinuationFrame {
)
}
override fun serializeToNBT() = NBTBuilder {
"type" %= "end"
}
override fun serializeToNBT() = CompoundTag()
override fun size() = 0
@JvmField
val TYPE: ContinuationFrame.Type<FrameFinishEval> = object : ContinuationFrame.Type<FrameFinishEval> {
override fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel) = FrameFinishEval
}
override val type = TYPE
}

View file

@ -6,8 +6,13 @@ 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.hasList
import at.petrak.hexcasting.api.utils.serializeToNBT
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
import net.minecraft.server.level.ServerLevel
/**
@ -76,7 +81,6 @@ data class FrameForEach(
}
override fun serializeToNBT() = NBTBuilder {
"type" %= "foreach"
"data" %= data.serializeToNBT()
"code" %= code.serializeToNBT()
if (baseStack != null)
@ -85,4 +89,27 @@ data class FrameForEach(
}
override fun size() = data.size() + code.size() + acc.size + (baseStack?.size ?: 0)
override val type: ContinuationFrame.Type<*> = TYPE
companion object {
@JvmField
val TYPE: ContinuationFrame.Type<FrameForEach> = object : ContinuationFrame.Type<FrameForEach> {
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()
)
}
}
}
}

View file

@ -23,7 +23,7 @@ sealed interface SpellContinuation {
var self = this
val frames = mutableListOf<CompoundTag>()
while (self is NotDone) {
frames.add(self.frame.serializeToNBT())
frames.add(ContinuationFrame.toNBT(self.frame))
self = self.next
}
return frames

View file

@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.ActionRegistryEntry;
import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic;
import at.petrak.hexcasting.api.casting.castables.SpecialHandler;
import at.petrak.hexcasting.api.casting.eval.sideeffects.EvalSound;
import at.petrak.hexcasting.api.casting.eval.vm.ContinuationFrame;
import at.petrak.hexcasting.api.casting.iota.IotaType;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
@ -15,5 +16,6 @@ public class HexRegistries {
public static final ResourceKey<Registry<SpecialHandler.Factory<?>>> SPECIAL_HANDLER = ResourceKey.createRegistryKey(modLoc("special_handler"));
public static final ResourceKey<Registry<IotaType<?>>> IOTA_TYPE = ResourceKey.createRegistryKey(modLoc("iota_type"));
public static final ResourceKey<Registry<Arithmetic>> ARITHMETIC = ResourceKey.createRegistryKey(modLoc("arithmetic"));
public static final ResourceKey<Registry<ContinuationFrame.Type<?>>> CONTINUATION_TYPE = ResourceKey.createRegistryKey(modLoc("continuation_type"));
public static final ResourceKey<Registry<EvalSound>> EVAL_SOUND = ResourceKey.createRegistryKey(modLoc("eval_sound"));
}

View file

@ -0,0 +1,49 @@
package at.petrak.hexcasting.common.lib.hex;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.api.casting.eval.vm.ContinuationFrame;
import at.petrak.hexcasting.api.casting.eval.vm.FrameEvaluate;
import at.petrak.hexcasting.api.casting.eval.vm.FrameFinishEval;
import at.petrak.hexcasting.api.casting.eval.vm.FrameForEach;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
/**
* Stores the registry for continuation frame types, some utility methods, and all the types Hexcasting itself defines.
*/
@ParametersAreNonnullByDefault
public class HexContinuationTypes {
public static final Registry<ContinuationFrame.Type<?>> REGISTRY = IXplatAbstractions.INSTANCE.getContinuationTypeRegistry();
public static final String
KEY_TYPE = HexAPI.MOD_ID + ":type",
KEY_DATA = HexAPI.MOD_ID + ":data";
public static void registerContinuations(BiConsumer<ContinuationFrame.Type<?>, ResourceLocation> r) {
for (var e : CONTINUATIONS.entrySet()) {
r.accept(e.getValue(), e.getKey());
}
}
private static final Map<ResourceLocation, ContinuationFrame.Type<?>> CONTINUATIONS = new LinkedHashMap<>();
public static final ContinuationFrame.Type<FrameEvaluate> EVALUATE = continuation("evaluate", FrameEvaluate.TYPE);
public static final ContinuationFrame.Type<FrameForEach> FOREACH = continuation("foreach", FrameForEach.TYPE);
public static final ContinuationFrame.Type<FrameFinishEval> END = continuation("end", FrameFinishEval.TYPE);
private static <U extends ContinuationFrame, T extends ContinuationFrame.Type<U>> T continuation(String name, T continuation) {
var old = CONTINUATIONS.put(modLoc(name), continuation);
if (old != null) {
throw new IllegalArgumentException("Typo? Duplicate id " + name);
}
return continuation;
}
}

View file

@ -12,6 +12,7 @@ import at.petrak.hexcasting.api.casting.eval.ResolvedPattern;
import at.petrak.hexcasting.api.casting.eval.sideeffects.EvalSound;
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage;
import at.petrak.hexcasting.api.casting.eval.vm.CastingVM;
import at.petrak.hexcasting.api.casting.eval.vm.ContinuationFrame;
import at.petrak.hexcasting.api.casting.iota.IotaType;
import at.petrak.hexcasting.api.pigment.ColorProvider;
import at.petrak.hexcasting.api.pigment.FrozenPigment;
@ -175,6 +176,7 @@ public interface IXplatAbstractions {
Registry<IotaType<?>> getIotaTypeRegistry();
Registry<Arithmetic> getArithmeticRegistry();
Registry<ContinuationFrame.Type<?>> getContinuationTypeRegistry();
Registry<EvalSound> getEvalSoundRegistry();

View file

@ -145,6 +145,7 @@ object FabricHexInitializer : ModInitializer {
HexActions.register(bind(IXplatAbstractions.INSTANCE.actionRegistry))
HexSpecialHandlers.register(bind(IXplatAbstractions.INSTANCE.specialHandlerRegistry))
HexArithmetics.register(bind(IXplatAbstractions.INSTANCE.arithmeticRegistry))
HexContinuationTypes.registerContinuations(bind(IXplatAbstractions.INSTANCE.continuationTypeRegistry))
HexEvalSounds.register(bind(IXplatAbstractions.INSTANCE.evalSoundRegistry))
// Because of Java's lazy-loading of classes, can't use Kotlin static initialization for

View file

@ -12,6 +12,7 @@ import at.petrak.hexcasting.api.casting.eval.ResolvedPattern;
import at.petrak.hexcasting.api.casting.eval.sideeffects.EvalSound;
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage;
import at.petrak.hexcasting.api.casting.eval.vm.CastingVM;
import at.petrak.hexcasting.api.casting.eval.vm.ContinuationFrame;
import at.petrak.hexcasting.api.casting.iota.IotaType;
import at.petrak.hexcasting.api.mod.HexConfig;
import at.petrak.hexcasting.api.mod.HexTags;
@ -435,6 +436,14 @@ public class FabricXplatImpl implements IXplatAbstractions {
Lifecycle.stable()))
.buildAndRegister()
);
private static final Supplier<Registry<ContinuationFrame.Type<?>>> CONTINUATION_TYPE_REGISTRY = Suppliers.memoize(() ->
FabricRegistryBuilder.from(new DefaultedMappedRegistry<>(
HexAPI.MOD_ID + ":end", HexRegistries.CONTINUATION_TYPE,
Lifecycle.stable(), false))
.buildAndRegister()
);
private static final Supplier<Registry<EvalSound>> EVAL_SOUNDS_REGISTRY = Suppliers.memoize(() ->
FabricRegistryBuilder.from(new DefaultedMappedRegistry<>(
HexAPI.MOD_ID + ":nothing", HexRegistries.EVAL_SOUND,
@ -462,6 +471,11 @@ public class FabricXplatImpl implements IXplatAbstractions {
return ARITHMETIC_REGISTRY.get();
}
@Override
public Registry<ContinuationFrame.Type<?>> getContinuationTypeRegistry() {
return CONTINUATION_TYPE_REGISTRY.get();
}
@Override
public Registry<EvalSound> getEvalSoundRegistry() {
return EVAL_SOUNDS_REGISTRY.get();

View file

@ -106,6 +106,7 @@ public class ForgeHexInitializer {
IXplatAbstractions.INSTANCE.getSpecialHandlerRegistry();
IXplatAbstractions.INSTANCE.getIotaTypeRegistry();
IXplatAbstractions.INSTANCE.getArithmeticRegistry();
IXplatAbstractions.INSTANCE.getContinuationTypeRegistry();
IXplatAbstractions.INSTANCE.getEvalSoundRegistry();
rootRegistry.freeze();
@ -138,6 +139,7 @@ public class ForgeHexInitializer {
bind(HexRegistries.ACTION, HexActions::register);
bind(HexRegistries.SPECIAL_HANDLER, HexSpecialHandlers::register);
bind(HexRegistries.ARITHMETIC, HexArithmetics::register);
bind(HexRegistries.CONTINUATION_TYPE, HexContinuationTypes::registerContinuations);
bind(HexRegistries.EVAL_SOUND, HexEvalSounds::register);
ForgeHexArgumentTypeRegistry.ARGUMENT_TYPES.register(getModEventBus());

View file

@ -12,6 +12,7 @@ import at.petrak.hexcasting.api.casting.eval.env.StaffCastEnv;
import at.petrak.hexcasting.api.casting.eval.sideeffects.EvalSound;
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage;
import at.petrak.hexcasting.api.casting.eval.vm.CastingVM;
import at.petrak.hexcasting.api.casting.eval.vm.ContinuationFrame;
import at.petrak.hexcasting.api.casting.iota.IotaType;
import at.petrak.hexcasting.api.mod.HexTags;
import at.petrak.hexcasting.api.pigment.ColorProvider;
@ -21,6 +22,7 @@ import at.petrak.hexcasting.api.player.FlightAbility;
import at.petrak.hexcasting.api.player.Sentinel;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.HexRegistries;
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 at.petrak.hexcasting.common.msgs.IMessage;
@ -479,6 +481,11 @@ public class ForgeXplatImpl implements IXplatAbstractions {
ForgeAccessorBuiltInRegistries.hex$registerSimple(
HexRegistries.ARITHMETIC, null)
);
private static final Supplier<Registry<ContinuationFrame.Type<?>>> CONTINUATION_TYPE_REGISTRY = Suppliers.memoize(() ->
ForgeAccessorBuiltInRegistries.hex$registerDefaulted(
HexRegistries.CONTINUATION_TYPE,
modLoc("end").toString(), registry -> HexContinuationTypes.END)
);
private static final Supplier<Registry<EvalSound>> EVAL_SOUND_REGISTRY = Suppliers.memoize(() ->
ForgeAccessorBuiltInRegistries.hex$registerDefaulted(
HexRegistries.EVAL_SOUND,
@ -505,6 +512,11 @@ public class ForgeXplatImpl implements IXplatAbstractions {
return ARITHMETIC_REGISTRY.get();
}
@Override
public Registry<ContinuationFrame.Type<?>> getContinuationTypeRegistry() {
return CONTINUATION_TYPE_REGISTRY.get();
}
@Override
public Registry<EvalSound> getEvalSoundRegistry() {
return EVAL_SOUND_REGISTRY.get();