diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaCastRegistry.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaCastRegistry.kt new file mode 100644 index 000000000..98db65c28 --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaCastRegistry.kt @@ -0,0 +1,51 @@ +package at.petrak.hexcasting.api.casting.iota + +import at.petrak.hexcasting.common.lib.hex.HexIotaTypes +import net.minecraft.resources.ResourceLocation +import java.util.* +import java.util.function.Function + +object IotaCastRegistry { + private val REGISTRY: HashMap>>> = HashMap() + @Suppress("UNCHECKED_CAST") + fun registerIotaConverter(input: IotaType, output: IotaType, converter: Function>) { + val inputId = HexIotaTypes.REGISTRY.getKey(input) + ?: throw IllegalArgumentException("Input IotaType must be registered with HexIotaTypes registry") + val outputId = HexIotaTypes.REGISTRY.getKey(output) + ?: throw IllegalArgumentException("Output IotaType mst be registered with HexIotaTypes registry") + + val converters = REGISTRY.getOrPut( + inputId + ) { HashMap() } + + if (converters.containsKey(outputId)) { + throw IllegalArgumentException("Input IotaType (%s) already has a converter registered for Output IotaType (%s), This is a conflict.".format(inputId,outputId)) + } + + converters[outputId] = converter as Function>//there is an unchecked cast here. but we already know A and B extend Iota, so it is fair game + } + + fun tryIotaConversion(inputT: IotaType<*>, outputT: IotaType<*>, input: Iota): Optional { + if (input.type != inputT) { + throw IllegalArgumentException("Input IotaType and Input Iota have different types") + } + + val inputId = HexIotaTypes.REGISTRY.getKey(inputT) + ?: throw IllegalArgumentException("Input IotaType must be registered with HexIotaTypes registry") + val outputId = HexIotaTypes.REGISTRY.getKey(outputT) + ?: throw IllegalArgumentException("Output IotaType mst be registered with HexIotaTypes registry") + + val converters = REGISTRY[inputId] + ?: throw IllegalArgumentException("Input IotaType (%s) has no converters to any other iota type".format(inputId)) + val converter = converters[outputId] + ?: throw IllegalArgumentException("Input IotaType (%s) has no converter to IotaType (%s)".format(inputId,outputId)) + + return converter.apply(input) + } +} + +@Suppress("UNCHECKED_CAST") +fun Iota.into(other: IotaType): Optional = IotaCastRegistry.tryIotaConversion(this.type,other,this) as Optional + +@Suppress("UNCHECKED_CAST") +fun IotaType.from(other: I): Optional = IotaCastRegistry.tryIotaConversion(other.type,this,other) as Optional