diff --git a/common/build.gradle b/common/build.gradle index da22eac..5a6f082 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -6,6 +6,24 @@ loom { accessWidenerPath = file("src/main/resources/kelvin.accesswidener") } +repositories { + maven { + // location of the maven that hosts JEI files before January 2023 + name = "Progwml6's maven" + url = "https://dvs1.progwml6.com/files/maven/" + } + maven { + // location of the maven that hosts JEI files since January 2023 + name = "Jared's maven" + url = "https://maven.blamejared.com/" + } + maven { + // location of a maven mirror for JEI files, as a fallback + name = "ModMaven" + url = "https://modmaven.dev" + } +} + dependencies { // We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies // Do NOT use other classes from fabric loader @@ -14,6 +32,9 @@ dependencies { // Architectury API modApi "dev.architectury:architectury:${rootProject.architectury_version}" + // JEI + modCompileOnly "mezz.jei:jei-${rootProject.minecraft_version}-common-api:${jei_version}" + api "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.10" api "org.jetbrains.kotlin:kotlin-reflect:1.9.10" } diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/KelvinMod.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/KelvinMod.kt index 332a646..7c139f2 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/KelvinMod.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/KelvinMod.kt @@ -5,27 +5,31 @@ import dev.architectury.event.events.client.ClientPlayerEvent import dev.architectury.event.events.client.ClientTickEvent import dev.architectury.event.events.common.ChunkEvent import dev.architectury.event.events.common.LifecycleEvent -import dev.architectury.event.events.common.PlayerEvent import dev.architectury.event.events.common.TickEvent import dev.architectury.networking.simple.SimpleNetworkManager import dev.architectury.platform.Platform import dev.architectury.utils.Env import net.minecraft.client.multiplayer.ClientLevel import net.minecraft.nbt.CompoundTag +import net.minecraft.resources.ResourceLocation import net.minecraft.server.level.ServerLevel import net.minecraft.world.level.chunk.ChunkAccess import org.valkyrienskies.kelvin.api.DuctNetwork import org.valkyrienskies.kelvin.api.DuctNodePos +import org.valkyrienskies.kelvin.debug.KelvinBlocks import org.valkyrienskies.kelvin.impl.DuctNetworkServer -import org.valkyrienskies.kelvin.impl.GasTypeRegistry import org.valkyrienskies.kelvin.impl.client.DuctNetworkClient import org.valkyrienskies.kelvin.impl.logger +import org.valkyrienskies.kelvin.impl.registry.GasParticlePickerRegistry +import org.valkyrienskies.kelvin.impl.registry.GasTypeRegistry +import org.valkyrienskies.kelvin.impl.registry.ReactionRequirementRegistry import org.valkyrienskies.kelvin.networking.KelvinNetworking import org.valkyrienskies.kelvin.serialization.SerializableDuctNetwork import org.valkyrienskies.kelvin.util.KelvinChunkPos import org.valkyrienskies.kelvin.util.KelvinDamageSources import org.valkyrienskies.kelvin.util.KelvinJacksonUtil + object KelvinMod { const val MOD_ID = "kelvin" @@ -38,11 +42,14 @@ object KelvinMod { val Kelvin: DuctNetworkServer = DuctNetworkServer() val KelvinClient: DuctNetworkClient = DuctNetworkClient() + @JvmStatic fun init() { KELVINLOGGER.info("Initializing Kelvin...") networkManager = SimpleNetworkManager.create(MOD_ID) + + LifecycleEvent.SERVER_BEFORE_START.register { Kelvin.disabled = false KELVINLOGGER.info("Enabling Kelvin...") @@ -105,12 +112,16 @@ object KelvinMod { } - + KelvinParticles.init() KelvinNetworking.init() KelvinDamageSources.init() + KelvinBlocks.init() + KELVINLOGGER.info("Registering gas types...") GasTypeRegistry.init() + ReactionRequirementRegistry.init() + GasParticlePickerRegistry.init() KELVINLOGGER.info("--- --- ---") KELVINLOGGER.info("Finished registering gas types. We have ${GasTypeRegistry.GAS_TYPES.size} gasses registered!") @@ -119,6 +130,8 @@ object KelvinMod { @JvmStatic fun initClient() { + + ClientPlayerEvent.CLIENT_PLAYER_JOIN.register { if (Platform.getEnvironment() == Env.CLIENT) KelvinClient.disabled = false } @@ -130,6 +143,8 @@ object KelvinMod { ClientTickEvent.CLIENT_LEVEL_POST.register { KelvinClient.tick(it, 10) //todo substeps config } + + } fun getKelvin(): DuctNetwork { @@ -149,4 +164,8 @@ object KelvinMod { } return KelvinClient } + + fun asResouceLocation(string: String): ResourceLocation { + return ResourceLocation("${MOD_ID}:$string") + } } diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/KelvinParticles.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/KelvinParticles.kt new file mode 100644 index 0000000..445176b --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/KelvinParticles.kt @@ -0,0 +1,47 @@ +package org.valkyrienskies.kelvin + +import dev.architectury.registry.client.particle.ParticleProviderRegistry +import dev.architectury.registry.registries.DeferredRegister +import dev.architectury.registry.registries.RegistrySupplier +import net.minecraft.core.registries.Registries +import org.valkyrienskies.kelvin.impl.client.particle.DefaultGasParticle.DefaultGasParticleType +import org.valkyrienskies.kelvin.impl.client.particle.DefaultGasParticleProvider + + + +object KelvinParticles { + + val ALL: HashSet> = HashSet() + val PARTICLES = DeferredRegister.create(KelvinMod.MOD_ID, Registries.PARTICLE_TYPE) + + fun registerDefaultParticle(name: String): RegistrySupplier { + val supplier = PARTICLES.register(name) { DefaultGasParticleType() } + ALL.add(supplier) + KelvinMod.KELVINLOGGER.info("Registered particle: ${supplier.id}") + return supplier + } + + fun init() { + KelvinMod.KELVINLOGGER.info("Registering Kelvin default gas particles...") + PARTICLES.register() + + } + + object KelvinClientParticles { + + fun registerDefaultParticle(supplier: RegistrySupplier) { + KelvinMod.KELVINLOGGER.info("Registered particle provider: ${supplier.id}") + ParticleProviderRegistry.register(supplier.get(), ::DefaultGasParticleProvider) + } + + fun init() { + KelvinMod.KELVINLOGGER.info("Registering Kelvin default particle providers...") + ALL.forEach { entry -> + registerDefaultParticle(entry) + KelvinMod.KELVINLOGGER.info("Registered particle provider: ${entry.id}") + } + + } + + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/DuctNetwork.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/DuctNetwork.kt index d2daddd..47bce73 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/DuctNetwork.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/DuctNetwork.kt @@ -1,16 +1,12 @@ package org.valkyrienskies.kelvin.api -import net.minecraft.resources.ResourceKey import net.minecraft.resources.ResourceLocation -import net.minecraft.server.level.ServerLevel import net.minecraft.world.entity.player.Player import net.minecraft.world.level.Level import org.valkyrienskies.kelvin.KelvinMod.KELVINLOGGER import org.valkyrienskies.kelvin.impl.DuctNodeInfo import org.valkyrienskies.kelvin.impl.client.ClientKelvinInfo import org.valkyrienskies.kelvin.util.KelvinChunkPos -import java.util.EnumMap -import java.util.logging.Logger /** * The main class representing the Duct Network. @@ -73,7 +69,6 @@ interface DuctNetwork { fun removeEdge(posA: DuctNodePos, posB: DuctNodePos) { KELVINLOGGER.warn("You can't modify this from here. Called: removeEdge") } - fun modTemperature(pos: DuctNodePos, deltaTemperature: Double) { KELVINLOGGER.warn("You can't modify this from here. Called: modTemperature") } @@ -90,6 +85,8 @@ interface DuctNetwork { KELVINLOGGER.warn("You can't modify this from here. Called: modHeatEnergy") } + fun createGasParticle(level: T, gasType: GasType, pos: DuctNodePos, x: Double, y: Double, z: Double, xSpeed: Double, ySpeed: Double, zSpeed: Double) + // the real meat fun tick(level: T, subSteps: Int = 1) diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/GasReaction.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/GasReaction.kt new file mode 100644 index 0000000..8de2d34 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/GasReaction.kt @@ -0,0 +1,6 @@ +package org.valkyrienskies.kelvin.api + +import com.google.gson.JsonElement + +data class GasReaction(val gasses : HashMap, val requirements: HashMap, val energy: Double = 0.0, val result: HashMap) + diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/GasReactionRequirement.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/GasReactionRequirement.kt new file mode 100644 index 0000000..aea8499 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/GasReactionRequirement.kt @@ -0,0 +1,17 @@ +package org.valkyrienskies.kelvin.api + +import com.google.gson.JsonElement +import net.minecraft.network.chat.Component +import net.minecraft.resources.ResourceLocation +import net.minecraft.world.level.Level + + +abstract class GasReactionRequirement(val resourceLocation: ResourceLocation) { + + abstract fun apply_requirement(level: Level, ductNode: DuctNodePos, network: DuctNetwork<*>, value: JsonElement): Boolean + + open fun get_text(value: JsonElement): Component { + return Component.literal("Empty Component") + } + +} \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/GasType.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/GasType.kt index 7e27a59..db42ac6 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/GasType.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/GasType.kt @@ -3,6 +3,7 @@ package org.valkyrienskies.kelvin.api import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.databind.annotation.JsonSerialize import net.minecraft.resources.ResourceLocation +import org.valkyrienskies.kelvin.KelvinMod import org.valkyrienskies.kelvin.util.KelvinKeyMapper @JsonSerialize(using = KelvinKeyMapper.GasTypeSerializer::class) @@ -16,12 +17,16 @@ data class GasType( val thermalConductivity: Double, // (W / (m * K)) val sutherlandConstant: Double = 111.0, // (dimensionless) (see https://en.wikipedia.org/wiki/Viscosity#Temperature_dependence) val adiabaticIndex: Double = 1.4, // (dimensionless) (see https://en.wikipedia.org/wiki/Adiabatic_index) Not required, 1.4 is air's. Technically an approximation, only useful for pockets, but oh well. - val combustible: Boolean = false, // Whether the gas can be used as fuel - val calorificValue: Double = 0.0, // (J / kg) (see https://en.wikipedia.org/wiki/Energy_density), only use if [combustible] is true - val iconLocation: ResourceLocation? = null + val iconLocation: ResourceLocation = PLACEHOLDER_ICON ) { + override fun toString(): String { - val iconLoc = iconLocation?.toString() ?: "null" - return "$name, $density, $viscosity, $specificHeatCapacity, $thermalConductivity, $sutherlandConstant, $adiabaticIndex, $combustible, $calorificValue, $iconLoc" + val iconLoc = iconLocation.toString() + return "{$name, $density, $viscosity, $specificHeatCapacity, $thermalConductivity, $sutherlandConstant, $adiabaticIndex, $iconLoc}" + } + + + companion object { + val PLACEHOLDER_ICON = KelvinMod.asResouceLocation("textures/icons/placeholder.png") } } diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/KelvinParticlePicker.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/KelvinParticlePicker.kt new file mode 100644 index 0000000..524ffae --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/KelvinParticlePicker.kt @@ -0,0 +1,12 @@ +package org.valkyrienskies.kelvin.api + +import net.minecraft.core.particles.ParticleOptions +import net.minecraft.world.level.Level + +/* +A class for defining a ParticleTypePicker, which kelvin uses to pick out a ParticleType for anything it uses Particles for + */ +abstract class KelvinParticlePicker { + abstract fun chooseParticleOptions(level: Level, ductNodePos: DuctNodePos): ParticleOptions +} + diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/AllInOneDuctEdge.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/AllInOneDuctEdge.kt index 12f08aa..96f4283 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/AllInOneDuctEdge.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/AllInOneDuctEdge.kt @@ -16,5 +16,4 @@ class AllInOneDuctEdge( override var aperture: Double = 0.0, override var reversed: Boolean = false, override val filter: HashSet = HashSet(), override var blacklist: Boolean = false, override var unloaded: Boolean = false -) : DuctEdge, ApertureEdge, OneWayEdge, FilteredEdge { -} \ No newline at end of file +) : DuctEdge, ApertureEdge, OneWayEdge, FilteredEdge \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/ApertureDuctEdge.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/ApertureDuctEdge.kt index 24892af..28ba34c 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/ApertureDuctEdge.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/ApertureDuctEdge.kt @@ -14,5 +14,4 @@ class ApertureDuctEdge( override var radius: Double = 0.125, override var length: Double = 0.5, override var currentFlowRate: Double = 0.0, override var aperture: Double = 0.0, override var unloaded: Boolean = false -) : DuctEdge, ApertureEdge { -} \ No newline at end of file +) : DuctEdge, ApertureEdge \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/ApertureFilteredDuctEdge.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/ApertureFilteredDuctEdge.kt index 48e8767..1106ef0 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/ApertureFilteredDuctEdge.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/ApertureFilteredDuctEdge.kt @@ -1,7 +1,6 @@ package org.valkyrienskies.kelvin.api.edges import org.valkyrienskies.kelvin.api.ConnectionType -import org.valkyrienskies.kelvin.api.DuctEdge import org.valkyrienskies.kelvin.api.DuctNodePos import org.valkyrienskies.kelvin.api.GasType @@ -17,7 +16,4 @@ class ApertureFilteredDuctEdge( override var blacklist: Boolean = false, override var aperture: Double = 0.0, override var unloaded: Boolean = false -) : ApertureEdge, FilteredEdge { - - -} \ No newline at end of file +) : ApertureEdge, FilteredEdge \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/ApertureOneWayDuctEdge.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/ApertureOneWayDuctEdge.kt index ea311f3..d22076e 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/ApertureOneWayDuctEdge.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/ApertureOneWayDuctEdge.kt @@ -15,5 +15,4 @@ class ApertureOneWayDuctEdge( override var aperture: Double = 0.0, override var reversed: Boolean = false, override var unloaded: Boolean = false -) : DuctEdge, ApertureEdge, OneWayEdge { -} \ No newline at end of file +) : DuctEdge, ApertureEdge, OneWayEdge \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/FilteredDuctEdge.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/FilteredDuctEdge.kt index 84c480f..526188b 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/FilteredDuctEdge.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/FilteredDuctEdge.kt @@ -1,6 +1,8 @@ package org.valkyrienskies.kelvin.api.edges -import org.valkyrienskies.kelvin.api.* +import org.valkyrienskies.kelvin.api.ConnectionType +import org.valkyrienskies.kelvin.api.DuctNodePos +import org.valkyrienskies.kelvin.api.GasType /** * A default edge type that has a filter which only allows certain gas types to flow through it. Its filter can either be a Whitelist or a Blacklist. @@ -13,6 +15,4 @@ class FilteredDuctEdge( override val filter: HashSet = HashSet(), override var blacklist: Boolean = false, override var unloaded: Boolean = false -) : FilteredEdge { - -} \ No newline at end of file +) : FilteredEdge \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/PipeDuctEdge.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/PipeDuctEdge.kt index 3228d64..08ffc1a 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/PipeDuctEdge.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/api/edges/PipeDuctEdge.kt @@ -10,5 +10,4 @@ class PipeDuctEdge( override val nodeB: DuctNodePos, override var radius: Double = 0.125, override var length: Double = 0.5, override var currentFlowRate: Double = 0.0, override var unloaded: Boolean = false -) : DuctEdge { -} \ No newline at end of file +) : DuctEdge \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/debug/KelvinBlocks.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/debug/KelvinBlocks.kt new file mode 100644 index 0000000..c585f6b --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/debug/KelvinBlocks.kt @@ -0,0 +1,19 @@ +package org.valkyrienskies.kelvin.debug + +import dev.architectury.registry.registries.DeferredRegister +import net.minecraft.core.registries.Registries +import net.minecraft.world.level.block.Blocks +import net.minecraft.world.level.block.state.BlockBehaviour +import org.valkyrienskies.kelvin.KelvinMod + +object KelvinBlocks { + val BLOCKS = DeferredRegister.create(KelvinMod.MOD_ID, Registries.BLOCK) + + val particleSpawner = + BLOCKS.register("particle_spawner") { ParticleSpawnerBlock(BlockBehaviour.Properties.of()) } + + fun init() { + BLOCKS.register() + Blocks.HAY_BLOCK + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/debug/ParticleSpawnerBlock.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/debug/ParticleSpawnerBlock.kt new file mode 100644 index 0000000..17c25f4 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/debug/ParticleSpawnerBlock.kt @@ -0,0 +1,33 @@ +package org.valkyrienskies.kelvin.debug + +import net.minecraft.client.multiplayer.ClientLevel +import net.minecraft.core.BlockPos +import net.minecraft.util.RandomSource +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.state.BlockState +import org.valkyrienskies.kelvin.KelvinMod +import org.valkyrienskies.kelvin.impl.registry.GasTypeRegistry +import org.valkyrienskies.kelvin.util.KelvinExtensions.toDuctNodePos +import java.util.* + +class ParticleSpawnerBlock(properties: Properties) : Block(properties) { + override fun animateTick(state: BlockState, level: Level, pos: BlockPos, random: RandomSource) { + val kelvin = KelvinMod.KelvinClient + + + kelvin.createGasParticle( + level as ClientLevel, + GasTypeRegistry.GAS_TYPES.values.shuffled().first(), + pos.toDuctNodePos(level.dimension().location()), + pos.x.toDouble(), + pos.y.toDouble() + 1.0, + pos.z.toDouble(), + 0.0, + 1.0, + 0.0 + ) + + super.animateTick(state, level, pos, random) + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/DefaultKelvinRequirements.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/DefaultKelvinRequirements.kt new file mode 100644 index 0000000..ee859c2 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/DefaultKelvinRequirements.kt @@ -0,0 +1,77 @@ +package org.valkyrienskies.kelvin.impl + +import com.google.gson.JsonElement +import net.minecraft.network.chat.Component +import net.minecraft.world.level.Level +import org.valkyrienskies.kelvin.KelvinMod +import org.valkyrienskies.kelvin.api.DuctNetwork +import org.valkyrienskies.kelvin.api.DuctNodePos +import org.valkyrienskies.kelvin.api.GasReactionRequirement + +object DefaultKelvinRequirements { + val defaultRequirements = listOf(minTemperature, maxTemperature, minPressure, maxPressure) + + object minTemperature: GasReactionRequirement(KelvinMod.asResouceLocation("min_temperature")) { + override fun apply_requirement(level: Level, ductNode: DuctNodePos, network: DuctNetwork<*>, value: JsonElement): Boolean { + val doubleValue = value.asDouble + + val temperature = network.getTemperatureAt(ductNode) + return temperature >= doubleValue + } + + override fun get_text(value: JsonElement): Component { + val doubleValue = value.asDouble + + return Component.literal("Minimum Temperature: $doubleValue K") + } + + } + + object maxTemperature: GasReactionRequirement(KelvinMod.asResouceLocation("max_temperature")) { + override fun apply_requirement(level: Level, ductNode: DuctNodePos, network: DuctNetwork<*>, value: JsonElement): Boolean { + val doubleValue = value.asDouble + + val temperature = network.getTemperatureAt(ductNode) + return temperature <= doubleValue + } + + override fun get_text(value: JsonElement): Component { + val doubleValue = value.asDouble + + return Component.literal("Maximum Temperature: $doubleValue K") + } + } + + object minPressure: GasReactionRequirement(KelvinMod.asResouceLocation("min_pressure")) { + override fun apply_requirement(level: Level, ductNode: DuctNodePos, network: DuctNetwork<*>, value: JsonElement): Boolean { + val doubleValue = value.asDouble + + val pressure = network.getPressureAt(ductNode) + return pressure >= doubleValue + } + + override fun get_text(value: JsonElement): Component { + val doubleValue = value.asDouble + + return Component.literal("Minimum Pressure: $doubleValue Pa") + } + } + + object maxPressure: GasReactionRequirement(KelvinMod.asResouceLocation("max_pressure")) { + override fun apply_requirement(level: Level, ductNode: DuctNodePos, network: DuctNetwork<*>, value: JsonElement): Boolean { + val doubleValue = value.asDouble + + val pressure = network.getPressureAt(ductNode) + return pressure <= doubleValue + } + + override fun get_text(value: JsonElement): Component { + val doubleValue = value.asDouble + + return Component.literal("Maximum Pressure: $doubleValue Pa") + } + } +} + + + diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/DuctNetworkServer.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/DuctNetworkServer.kt index dfdc40f..64f53ab 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/DuctNetworkServer.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/DuctNetworkServer.kt @@ -1,29 +1,27 @@ package org.valkyrienskies.kelvin.impl import net.minecraft.core.BlockPos -import net.minecraft.resources.ResourceKey import net.minecraft.resources.ResourceLocation import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerPlayer import net.minecraft.util.Mth import net.minecraft.world.entity.player.Player -import net.minecraft.world.level.Explosion import net.minecraft.world.level.Level import org.valkyrienskies.kelvin.KelvinMod.KELVINLOGGER import org.valkyrienskies.kelvin.api.* import org.valkyrienskies.kelvin.api.DuctNetwork.Companion.idealGasConstant -import org.valkyrienskies.kelvin.api.edges.* +import org.valkyrienskies.kelvin.api.edges.ApertureEdge +import org.valkyrienskies.kelvin.api.edges.FilteredEdge +import org.valkyrienskies.kelvin.api.edges.OneWayEdge +import org.valkyrienskies.kelvin.api.edges.PumpEdge import org.valkyrienskies.kelvin.api.nodes.TankDuctNode import org.valkyrienskies.kelvin.impl.client.ClientKelvinInfo -import org.valkyrienskies.kelvin.networking.KelvinNetworking +import org.valkyrienskies.kelvin.impl.registry.GasTypeRegistry import org.valkyrienskies.kelvin.networking.KelvinSyncPacket -import org.valkyrienskies.kelvin.serialization.SerializableDuctNetwork import org.valkyrienskies.kelvin.util.* import org.valkyrienskies.kelvin.util.KelvinExtensions.toChunkPos import org.valkyrienskies.kelvin.util.KelvinExtensions.toMinecraft import java.util.concurrent.ConcurrentLinkedQueue -import kotlin.collections.HashMap -import kotlin.collections.HashSet import kotlin.math.* class DuctNetworkServer( @@ -224,6 +222,20 @@ class DuctNetworkServer( } + override fun createGasParticle( + level: ServerLevel, + gasType: GasType, + pos: DuctNodePos, + x: Double, + y: Double, + z: Double, + xSpeed: Double, + ySpeed: Double, + zSpeed: Double + ) { + KELVINLOGGER.warn("Server can't add Particles.") + } + override fun tick(level: ServerLevel, subSteps: Int) { if (disabled) return @@ -569,6 +581,46 @@ class DuctNetworkServer( val info = ClientKelvinInfo(HashMap(nodeInfo.filter { it.key.toChunkPos() == request.second })) sync(level, info, true, request.first) } + + + val reactions = KelvinReactionDataLoader.gas_reactions + // Process recipes + for (node in dimensionNodes) { + val gasMasses = getGasMassAt(node) + if (gasMasses.size == 0) continue + + for (reaction in reactions.values) { + var con = false + reaction.requirements.forEach {if (!it.key.apply_requirement(level, node, this, it.value)) { con = true; return@forEach }} + if (con) continue + + + calcReaction(node, gasMasses, reaction.gasses, reaction.result, reaction.energy) + } + } + } + + private fun calcReaction(ductNodePos: DuctNodePos, gasMasses: HashMap, inputGasses: HashMap, outputGasses: HashMap, deltaEnergy: Double) { + val gasMoles = HashMap() + + for (gas in gasMasses) gasMoles[gas.key] = (gas.value/gas.key.density)/22.4 + + var reactionMoles = Double.MAX_VALUE + + + for (gas in inputGasses) { + if (gas.key !in gasMoles || gasMoles[gas.key]!! < 0.001) return + + val thisOutput = gasMoles[gas.key]!! / gas.value + if (thisOutput < reactionMoles) reactionMoles = thisOutput + } + + for (gas in inputGasses) modGasMass(ductNodePos,gas.key,-reactionMoles * gas.value * gas.key.density * 22.4) + + for (gas in outputGasses) modGasMass(ductNodePos,gas.key,reactionMoles * gas.value * gas.key.density * 22.4) + + modHeatEnergy(ductNodePos, deltaEnergy * reactionMoles) + } /** diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/KelvinReactionDataLoader.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/KelvinReactionDataLoader.kt new file mode 100644 index 0000000..ce56450 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/KelvinReactionDataLoader.kt @@ -0,0 +1,90 @@ +package org.valkyrienskies.kelvin.impl + +import com.google.gson.Gson +import com.google.gson.JsonElement +import net.minecraft.resources.ResourceLocation +import net.minecraft.server.packs.resources.ResourceManager +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener +import net.minecraft.util.profiling.ProfilerFiller +import org.valkyrienskies.kelvin.KelvinMod.KELVINLOGGER +import org.valkyrienskies.kelvin.api.GasReaction +import org.valkyrienskies.kelvin.api.GasReactionRequirement +import org.valkyrienskies.kelvin.api.GasType +import org.valkyrienskies.kelvin.impl.registry.GasTypeRegistry +import org.valkyrienskies.kelvin.impl.registry.ReactionRequirementRegistry + +object KelvinReactionDataLoader { + val gas_reactions = hashMapOf() + val loader get() = KelvinReactionDataLoader() + + class KelvinReactionDataLoader : SimpleJsonResourceReloadListener(Gson(), "kelvin_reactions") { + + override fun apply( + objects: MutableMap, + resourceManager: ResourceManager, + profiler: ProfilerFiller + ) { + gas_reactions.clear() + objects.forEach { (location, element) -> + try { + if (element.isJsonArray) { + element.asJsonArray.forEach { element1: JsonElement -> + parse(element1, location) + } + } else if (element.isJsonObject) { + parse(element, location) + } else throw IllegalArgumentException() + } catch (e: Exception) { + KELVINLOGGER.error(e) + } + } + } + + private fun parse(element: JsonElement, origin: ResourceLocation) { + val jObject = element.asJsonObject + + val gasses = HashMap() + val requirements = HashMap() + val result = HashMap() + + for (entry in jObject["gasses"].asJsonObject.entrySet()) { + val gasType = GasTypeRegistry.getGasType(ResourceLocation(entry.key)) ?: return KELVINLOGGER.error("Invalid gasType '${entry.key}' in gas reaction in file '$origin'. Ignoring reaction") + val gasParts: Int + try { + gasParts = entry.value.asInt + } catch (e: Exception) { + return KELVINLOGGER.error("Invalid gasType Int '${entry.value}' in gas reaction in file '$origin'. Ignoring reaction") + } + + gasses[gasType] = gasParts + } + + for (entry in jObject["requirements"].asJsonObject.entrySet()) { + val reactionRequirement = ReactionRequirementRegistry.getReactionRequirement(ResourceLocation(entry.key)) ?: return KELVINLOGGER.error("Invalid reaction requirement '${entry.key}' in in file '$origin'. Ignoring reaction") + + requirements[reactionRequirement] = entry.value + } + + for (entry in jObject["result"].asJsonObject.entrySet()) { + val gasType = GasTypeRegistry.getGasType(ResourceLocation(entry.key)) ?: return KELVINLOGGER.error("Invalid gasType result'${entry.key}' in gas reaction in file '$origin'. Ignoring reaction") + val gasParts: Int + try { + gasParts = entry.value.asInt + } catch (e: Exception) { + return KELVINLOGGER.error("Invalid gasType result Int '${entry.value}' in gas reaction in file '$origin'. Ignoring reaction") + } + + result[gasType] = gasParts + } + + + val energy = if (jObject.has("energy")) jObject["energy"].asDouble else 0.0 + + val parsedReaction = GasReaction(gasses = gasses, requirements = requirements, energy = energy, result = result) + gas_reactions[origin] = parsedReaction + + } + } + + +} \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/ClientKelvinInfo.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/ClientKelvinInfo.kt index bd4073d..10594cd 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/ClientKelvinInfo.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/ClientKelvinInfo.kt @@ -3,5 +3,4 @@ package org.valkyrienskies.kelvin.impl.client import org.valkyrienskies.kelvin.api.DuctNodePos import org.valkyrienskies.kelvin.impl.DuctNodeInfo -data class ClientKelvinInfo(val nodes: HashMap) { -} +data class ClientKelvinInfo(val nodes: HashMap) diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/DuctNetworkClient.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/DuctNetworkClient.kt index a6cae33..5f9adf1 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/DuctNetworkClient.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/DuctNetworkClient.kt @@ -6,12 +6,11 @@ import net.minecraft.world.entity.player.Player import org.valkyrienskies.kelvin.KelvinMod.KELVINLOGGER import org.valkyrienskies.kelvin.api.* import org.valkyrienskies.kelvin.impl.DuctNodeInfo +import org.valkyrienskies.kelvin.impl.registry.GasParticlePickerRegistry import org.valkyrienskies.kelvin.networking.KelvinRequestChunkSyncPacket import org.valkyrienskies.kelvin.util.KelvinChunkPos import org.valkyrienskies.kelvin.util.KelvinExtensions.toChunkPos -import java.util.* -import kotlin.collections.HashMap -import kotlin.collections.HashSet +import kotlin.math.abs class DuctNetworkClient: DuctNetwork { @@ -37,6 +36,13 @@ class DuctNetworkClient: DuctNetwork { override fun tick(level: ClientLevel, subSteps: Int) { if (disabled) return + nodeInfo.forEach { pos, node -> + if (abs(node.currentPressure - node.previousPressure) > 1) { + val largestGas = node.currentGasMasses.maxBy { (_, amount) -> amount }.key + createGasParticle(level, largestGas, pos, pos.x, pos.y, pos.z, 0.0, 0.0, 0.0) + } + } + ticksSinceLastSync++ } @@ -110,6 +116,16 @@ class DuctNetworkClient: DuctNetwork { nodeInfo.remove(pos) } + override fun createGasParticle( + level: ClientLevel, gasType: GasType, pos: DuctNodePos, + x: Double, y: Double, z: Double, + xSpeed: Double, ySpeed: Double, zSpeed: Double + ) { + val particleTypePicker = GasParticlePickerRegistry.getParticlePicker(gasType) ?: return KELVINLOGGER.error("${gasType.resourceLocation} lacks a ParticlePicker") + val particleOptions = particleTypePicker.chooseParticleOptions(level, pos) + level.addParticle(particleOptions, x, y, z, xSpeed, ySpeed, zSpeed) + } + override fun getHeatEnergy(pos: DuctNodePos): Double { return getTemperatureAt(pos) * specificHeatAverage(getGasMassAt(pos)) * getGasMassAt(pos).values.sum() } diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/particle/DefaultGasParticle.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/particle/DefaultGasParticle.kt new file mode 100644 index 0000000..76bf115 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/particle/DefaultGasParticle.kt @@ -0,0 +1,22 @@ +package org.valkyrienskies.kelvin.impl.client.particle + +import net.minecraft.client.multiplayer.ClientLevel +import net.minecraft.client.particle.ParticleRenderType +import net.minecraft.client.particle.TextureSheetParticle +import net.minecraft.core.particles.SimpleParticleType + +class DefaultGasParticle(level: ClientLevel, x: Double, y: Double, z: Double, xSpeed: Double, ySpeed: Double, zSpeed: Double): TextureSheetParticle(level, x, y, z, xSpeed, ySpeed, zSpeed) { + + init { + this.gravity = 0f + this.xd = xSpeed + this.yd = ySpeed + this.zd = zSpeed + } + + override fun getRenderType(): ParticleRenderType { + return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT + } + + class DefaultGasParticleType : SimpleParticleType(false) +} \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/particle/DefaultGasParticlePicker.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/particle/DefaultGasParticlePicker.kt new file mode 100644 index 0000000..9ee96de --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/particle/DefaultGasParticlePicker.kt @@ -0,0 +1,21 @@ +package org.valkyrienskies.kelvin.impl.client.particle + +import net.minecraft.core.particles.ParticleOptions +import net.minecraft.core.particles.SimpleParticleType +import net.minecraft.world.level.Level +import org.valkyrienskies.kelvin.api.DuctNodePos +import org.valkyrienskies.kelvin.api.KelvinParticlePicker + +/* +The default ParticlePicker. Allows you to make a ParticlePicker which always returns a single ParticleType + */ +class DefaultGasParticlePicker(val particleOptions: ParticleOptions) : KelvinParticlePicker() { + + override fun chooseParticleOptions( + level: Level, + ductNodePos: DuctNodePos + ): ParticleOptions { + return particleOptions + } + +} \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/particle/DefaultGasParticleProvider.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/particle/DefaultGasParticleProvider.kt new file mode 100644 index 0000000..eb0fcdb --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/client/particle/DefaultGasParticleProvider.kt @@ -0,0 +1,28 @@ +package org.valkyrienskies.kelvin.impl.client.particle + +import net.minecraft.client.multiplayer.ClientLevel +import net.minecraft.client.particle.Particle +import net.minecraft.client.particle.ParticleProvider +import net.minecraft.client.particle.SpriteSet +import net.minecraft.core.particles.SimpleParticleType + +class DefaultGasParticleProvider(private val sprite: SpriteSet): ParticleProvider { + + override fun createParticle( + type: SimpleParticleType, + level: ClientLevel, + x: Double, + y: Double, + z: Double, + xSpeed: Double, + ySpeed: Double, + zSpeed: Double + ): Particle { + val particle = DefaultGasParticle(level,x,y,z,xSpeed,ySpeed,zSpeed) + particle.setSpriteFromAge(sprite) + return particle + } + + +} + diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/registry/GasParticlePickerRegistry.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/registry/GasParticlePickerRegistry.kt new file mode 100644 index 0000000..6f70e62 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/registry/GasParticlePickerRegistry.kt @@ -0,0 +1,43 @@ +package org.valkyrienskies.kelvin.impl.registry + +import net.minecraft.resources.ResourceLocation +import org.valkyrienskies.kelvin.KelvinParticles +import org.valkyrienskies.kelvin.api.GasType +import org.valkyrienskies.kelvin.api.KelvinParticlePicker +import org.valkyrienskies.kelvin.impl.client.particle.DefaultGasParticlePicker + + +object GasParticlePickerRegistry { + //TODO Make this datapack-compatible (so that GAS_PARTICLE_PICKERS and PARTICLE_PICKERS got synced to client) + val PARTICLE_PICKERS = HashMap() + val GAS_PARTICLE_PICKERS = HashMap() + + fun registerParticlePicker(resourceLocation: ResourceLocation, particlePicker: KelvinParticlePicker) { + PARTICLE_PICKERS[resourceLocation] = particlePicker + } + + fun registerGasToParticlePicker(resourceLocation: ResourceLocation, gasType: GasType) { + GAS_PARTICLE_PICKERS[gasType] = resourceLocation + } + + fun register(resourceLocation: ResourceLocation, gasType: GasType, particlePicker: KelvinParticlePicker) { + registerParticlePicker(resourceLocation, particlePicker) + registerGasToParticlePicker(resourceLocation, gasType) + } + + fun registerWithDefaultParticlePicker(gasType: GasType) { + KelvinParticles.registerDefaultParticle(gasType.resourceLocation.path).listen { + register(gasType.resourceLocation, gasType, DefaultGasParticlePicker(it.type)) + } + } + + fun getParticlePicker(resourceLocation: ResourceLocation): KelvinParticlePicker? { + return PARTICLE_PICKERS[resourceLocation] + } + + fun getParticlePicker(gasType: GasType): KelvinParticlePicker? { + return PARTICLE_PICKERS[GAS_PARTICLE_PICKERS[gasType] ?: return null] + } + + fun init () {} +} \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/GasTypeRegistry.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/registry/GasTypeRegistry.kt similarity index 54% rename from common/src/main/kotlin/org/valkyrienskies/kelvin/impl/GasTypeRegistry.kt rename to common/src/main/kotlin/org/valkyrienskies/kelvin/impl/registry/GasTypeRegistry.kt index a22ff80..1ded6f6 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/GasTypeRegistry.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/registry/GasTypeRegistry.kt @@ -1,9 +1,10 @@ -package org.valkyrienskies.kelvin.impl +package org.valkyrienskies.kelvin.impl.registry import net.minecraft.resources.ResourceLocation import org.valkyrienskies.kelvin.KelvinMod import org.valkyrienskies.kelvin.KelvinMod.KELVINLOGGER import org.valkyrienskies.kelvin.api.GasType +import org.valkyrienskies.kelvin.api.KelvinParticlePicker object GasTypeRegistry { val GAS_TYPES = mutableMapOf() @@ -18,10 +19,20 @@ object GasTypeRegistry { KELVINLOGGER.info("Registered gas type ${gasType.resourceLocation}, with properties:") KELVINLOGGER.info("Density: ${gasType.density} | Viscosity: ${gasType.viscosity} | Specific Heat Capacity: ${gasType.specificHeatCapacity} | Thermal Conductivity: ${gasType.thermalConductivity}") KELVINLOGGER.info("Sutherland Constant: ${gasType.sutherlandConstant} | Adiabatic Index: ${gasType.adiabaticIndex}") - KELVINLOGGER.info("Is it combustible?: ${gasType.combustible} | if so, it's Calorific Value is: ${gasType.calorificValue}") KELVINLOGGER.info("Icon Location: ${gasType.iconLocation}") } + fun register(gasType: GasType, particlePicker: KelvinParticlePicker) { + GasParticlePickerRegistry.registerParticlePicker(gasType.resourceLocation, particlePicker) + GasParticlePickerRegistry.registerGasToParticlePicker(gasType.resourceLocation, gasType) + registerGasType(gasType) + } + + fun register(gasType: GasType) { + GasParticlePickerRegistry.registerWithDefaultParticlePicker(gasType) + registerGasType(gasType) + } + fun getGasType(resourceLocation: ResourceLocation): GasType? { return GAS_TYPES[resourceLocation] } @@ -30,17 +41,28 @@ object GasTypeRegistry { return getGasType(ResourceLocation(modid, name)) } + private fun getIcon(name: String): ResourceLocation { + return KelvinMod.asResouceLocation("textures/icons/$name.png") + } + fun init () { - val air = GasType("Air",ResourceLocation(KelvinMod.MOD_ID, "air"), 1.293, 1.716e-5, 1.005, 0.026) - val phlogiston = GasType("Phlogiston",ResourceLocation(KelvinMod.MOD_ID, "phlogiston"), 3.0, 2.0e-5, 14.30, 0.240, 150.0, 1.008, true, 3.5e+8) - val helium = GasType("Helium",ResourceLocation(KelvinMod.MOD_ID, "helium"),0.166, 1.96e-5, 5.1832, 0.151, 79.4, 1.66) - val hydrogen = GasType("Hydrogen",ResourceLocation(KelvinMod.MOD_ID, "hydrogen"), 0.08988, 0.88e-5, 14.30, 0.18, 72.0, 1.4, true, 1.418e+8) - val methane = GasType("Methane",ResourceLocation(KelvinMod.MOD_ID, "methane"), 0.657, 1.10e-5, 2.2, 0.031, 90.0, 16.0, true, 5.55e+7) - - registerGasType(air) - registerGasType(phlogiston) - registerGasType(helium) - registerGasType(hydrogen) - registerGasType(methane) + val air = GasType("Air",ResourceLocation(KelvinMod.MOD_ID, "air"), 1.293, 1.716e-5, 1.005, 0.026, iconLocation = getIcon("air")) + val exhaust = GasType("Exhaust", ResourceLocation(KelvinMod.MOD_ID, "exhaust"), 1.98, 1.10e-5, 2.2, 0.031, iconLocation = getIcon("exhaust")) + val steam = GasType("Steam", ResourceLocation(KelvinMod.MOD_ID, "steam"), 1.98, 1.716e-5, 2.2, 0.031, iconLocation = getIcon("steam")) + + + val phlogiston = GasType("Phlogiston",ResourceLocation(KelvinMod.MOD_ID, "phlogiston"), 3.0, 2.0e-5, 14.30, 0.240, 150.0, 1.008, iconLocation = getIcon("phlogiston")) + val helium = GasType("Helium",ResourceLocation(KelvinMod.MOD_ID, "helium"),0.166, 1.96e-5, 5.1832, 0.151, 79.4, 1.66, iconLocation = getIcon("helium")) + val hydrogen = GasType("Hydrogen",ResourceLocation(KelvinMod.MOD_ID, "hydrogen"), 0.08988, 0.88e-5, 14.30, 0.18, 72.0, 1.4, iconLocation = getIcon("hydrogen")) + val methane = GasType("Methane",ResourceLocation(KelvinMod.MOD_ID, "methane"), 0.657, 1.10e-5, 2.2, 0.031, 90.0, 16.0, iconLocation = getIcon("methane")) + + + register(air) + register(exhaust) + register(steam) + register(phlogiston) + register(helium) + register(hydrogen) + register(methane) } } \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/registry/ReactionRequirementRegistry.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/registry/ReactionRequirementRegistry.kt new file mode 100644 index 0000000..a027b0e --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/impl/registry/ReactionRequirementRegistry.kt @@ -0,0 +1,31 @@ +package org.valkyrienskies.kelvin.impl.registry + +import net.minecraft.resources.ResourceLocation +import org.valkyrienskies.kelvin.KelvinMod.KELVINLOGGER +import org.valkyrienskies.kelvin.api.GasReactionRequirement +import org.valkyrienskies.kelvin.impl.DefaultKelvinRequirements + +object ReactionRequirementRegistry { + val REACTION_REQUIREMENTS = HashMap() + + fun registerReactionRequirement(resourceLocation: ResourceLocation, reactionRequirement: GasReactionRequirement) { + REACTION_REQUIREMENTS[resourceLocation] = reactionRequirement + } + + fun registerReactionRequirement(reactionRequirement: GasReactionRequirement) { + KELVINLOGGER.info("Registering reaction requirement ${reactionRequirement.resourceLocation}") + registerReactionRequirement(reactionRequirement.resourceLocation, reactionRequirement) + } + + fun getReactionRequirement(resourceLocation: ResourceLocation): GasReactionRequirement? { + return REACTION_REQUIREMENTS[resourceLocation] + } + + fun getReactionRequirement(modid: String, name: String): GasReactionRequirement? { + return getReactionRequirement(ResourceLocation(modid, name)) + } + + fun init () { + for (requirement in DefaultKelvinRequirements.defaultRequirements) registerReactionRequirement(requirement) + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/integration/jei/ImageDrawable.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/integration/jei/ImageDrawable.kt new file mode 100644 index 0000000..6f6e3b1 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/integration/jei/ImageDrawable.kt @@ -0,0 +1,22 @@ +package org.valkyrienskies.kelvin.integration.jei + +import mezz.jei.api.gui.drawable.IDrawable +import net.minecraft.client.gui.GuiGraphics +import net.minecraft.resources.ResourceLocation + + +class ImageDrawable(private val width: Int, private val height: Int, private val location: ResourceLocation) : IDrawable { + + override fun getWidth(): Int { + return width + } + + override fun getHeight(): Int { + return height + } + + override fun draw(guiGraphics: GuiGraphics, xOffset: Int, yOffset: Int) { + guiGraphics.blit(location, xOffset, yOffset, 0, 0f, 0f, width, height, height, width) + } + +} \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/integration/jei/KelvinGasIngredient.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/integration/jei/KelvinGasIngredient.kt new file mode 100644 index 0000000..db52481 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/integration/jei/KelvinGasIngredient.kt @@ -0,0 +1,59 @@ +package org.valkyrienskies.kelvin.integration.jei + +import mezz.jei.api.ingredients.IIngredientHelper +import mezz.jei.api.ingredients.IIngredientRenderer +import mezz.jei.api.ingredients.IIngredientType +import mezz.jei.api.ingredients.subtypes.UidContext +import net.minecraft.ChatFormatting +import net.minecraft.client.gui.GuiGraphics +import net.minecraft.network.chat.Component +import net.minecraft.resources.ResourceLocation +import net.minecraft.world.item.TooltipFlag +import org.valkyrienskies.kelvin.api.GasType + +data class KelvinGasIngredient(val gasType: GasType, val moles: Int) + +class GasIngredientType: IIngredientType { + override fun getIngredientClass(): Class { + return KelvinGasIngredient::class.java + } +} + +class GasIngredientHelper: IIngredientHelper { + override fun getIngredientType(): IIngredientType { + return GasIngredientType() + } + + override fun getResourceLocation(ingredient: KelvinGasIngredient): ResourceLocation { + return ingredient.gasType.resourceLocation + } + + override fun getErrorInfo(ingredient: KelvinGasIngredient?): String { + return ingredient?.gasType.toString() + } + + override fun copyIngredient(ingredient: KelvinGasIngredient): KelvinGasIngredient { + return ingredient + } + + override fun getUniqueId(ingredient: KelvinGasIngredient, context: UidContext): String { + return ingredient.gasType.resourceLocation.toString() + } + + // TODO: Make this get lang + override fun getDisplayName(ingredient: KelvinGasIngredient): String { + return ingredient.gasType.name + } + +} + +class GasIngredientRenderer: IIngredientRenderer { + override fun getTooltip(ingredient: KelvinGasIngredient, tooltipFlag: TooltipFlag): MutableList { + return mutableListOf(Component.literal(ingredient.gasType.name).withStyle(ChatFormatting.GOLD)) + } + + override fun render(guiGraphics: GuiGraphics, ingredient: KelvinGasIngredient) { + guiGraphics.blit(ingredient.gasType.iconLocation, 0, 0, 0, 0f, 0f, 16, 16, 16, 16) + } + +} diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/integration/jei/KelvinJeiPlugin.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/integration/jei/KelvinJeiPlugin.kt new file mode 100644 index 0000000..4021c7a --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/integration/jei/KelvinJeiPlugin.kt @@ -0,0 +1,48 @@ +package org.valkyrienskies.kelvin.integration.jei + +import mezz.jei.api.IModPlugin +import mezz.jei.api.JeiPlugin +import mezz.jei.api.recipe.RecipeType +import mezz.jei.api.registration.IModIngredientRegistration +import mezz.jei.api.registration.IRecipeCategoryRegistration +import mezz.jei.api.registration.IRecipeRegistration +import net.minecraft.resources.ResourceLocation +import org.valkyrienskies.kelvin.KelvinMod +import org.valkyrienskies.kelvin.KelvinMod.MOD_ID +import org.valkyrienskies.kelvin.api.GasReaction +import org.valkyrienskies.kelvin.impl.KelvinReactionDataLoader +import org.valkyrienskies.kelvin.impl.registry.GasTypeRegistry + + +@JeiPlugin +class KelvinJeiPlugin: IModPlugin { + override fun getPluginUid(): ResourceLocation { + return KelvinMod.asResouceLocation("jei_plugin") + } + + override fun registerIngredients(registration: IModIngredientRegistration) { + val recipes = HashSet() + GasTypeRegistry.GAS_TYPES.values.forEach {type -> recipes.add(KelvinGasIngredient(type, 1))} + registration.register(GAS_INGREDIENT_TYPE, recipes, GasIngredientHelper(), GasIngredientRenderer()) + } + + override fun registerCategories(registration: IRecipeCategoryRegistration) { + super.registerCategories(registration) + + registration.addRecipeCategories(KelvinReactionRecipeCategory()) + } + + override fun registerRecipes(registration: IRecipeRegistration) { + super.registerRecipes(registration) + val recipes = KelvinReactionDataLoader.gas_reactions.values + registration.addRecipes(GAS_REACTION_RECIPE_TYPE, recipes.toList()) + } + + + + companion object { + val GAS_REACTION_RECIPE_TYPE: RecipeType = RecipeType.create(MOD_ID, "gas_reaction_recipe", GasReaction::class.java) + val GAS_INGREDIENT_TYPE = GasIngredientType() + } +} + diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/integration/jei/KelvinReactionRecipeCategory.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/integration/jei/KelvinReactionRecipeCategory.kt new file mode 100644 index 0000000..e7d27b0 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/integration/jei/KelvinReactionRecipeCategory.kt @@ -0,0 +1,89 @@ +package org.valkyrienskies.kelvin.integration.jei + +import mezz.jei.api.gui.builder.IRecipeLayoutBuilder +import mezz.jei.api.gui.drawable.IDrawable +import mezz.jei.api.gui.ingredient.IRecipeSlotsView +import mezz.jei.api.recipe.IFocusGroup +import mezz.jei.api.recipe.RecipeIngredientRole +import mezz.jei.api.recipe.RecipeType +import mezz.jei.api.recipe.category.IRecipeCategory +import net.minecraft.client.Minecraft +import net.minecraft.client.gui.GuiGraphics +import net.minecraft.network.chat.Component +import org.valkyrienskies.kelvin.KelvinMod +import org.valkyrienskies.kelvin.api.GasReaction +import org.valkyrienskies.kelvin.api.GasType +import org.valkyrienskies.kelvin.integration.jei.KelvinJeiPlugin.Companion.GAS_INGREDIENT_TYPE + +class KelvinReactionRecipeCategory : IRecipeCategory { + + override fun getBackground(): IDrawable { + return ImageDrawable(150, 150, KelvinMod.asResouceLocation("textures/gui/gas_reaction_recipe_background.png")) + } + + override fun getRecipeType(): RecipeType { + return KelvinJeiPlugin.GAS_REACTION_RECIPE_TYPE + } + + override fun getTitle(): Component { + + return Component.literal("Gas Reaction") + } + + override fun getIcon(): IDrawable { + return ImageDrawable(16,16, GasType.PLACEHOLDER_ICON) + } + + + override fun setRecipe(builder: IRecipeLayoutBuilder, recipe: GasReaction, focuses: IFocusGroup) { + + var i = 0 + recipe.gasses.forEach { (type, moles) -> + val slot = builder.addSlot(RecipeIngredientRole.INPUT, 0, i*17) + slot.addIngredient(GAS_INGREDIENT_TYPE, KelvinGasIngredient(type,moles)) + i++ + } + + i = 0 + recipe.result.forEach { (type, moles) -> + val slot = builder.addSlot(RecipeIngredientRole.OUTPUT, 84, i*17) + slot.addIngredient(GAS_INGREDIENT_TYPE, KelvinGasIngredient(type,moles)) + i++ + } + } + + override fun draw( + recipe: GasReaction, + recipeSlotsView: IRecipeSlotsView, + guiGraphics: GuiGraphics, + mouseX: Double, + mouseY: Double + ) { + var maxI = 0 + var i = 0 + recipeSlotsView.getSlotViews(RecipeIngredientRole.INPUT).forEach { slot -> + val ingredient = slot.displayedIngredient.get().ingredient as KelvinGasIngredient + // TODO: USE LANG + guiGraphics.drawString(Minecraft.getInstance().font, "${ingredient.moles} Moles", 17, i * 17, 5592405) + i++ + if (i >= maxI) maxI = i + } + + i = 0 + recipeSlotsView.getSlotViews(RecipeIngredientRole.OUTPUT).forEach { slot -> + val ingredient = slot.displayedIngredient.get().ingredient as KelvinGasIngredient + // TODO: USE LANG + guiGraphics.drawString(Minecraft.getInstance().font, "${ingredient.moles} Moles", 101, i * 17, 5592405) + i++ + if (i >= maxI) maxI = i + } + + i = maxI + 2 + recipe.requirements.forEach { (requirement, value) -> + guiGraphics.drawString(Minecraft.getInstance().font, requirement.get_text(value).string, 0, i * 17, 5592405) + i++ + } + } + +} + diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/serialization/NodeNBTUtil.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/serialization/NodeNBTUtil.kt index 7a86fd1..984750d 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/serialization/NodeNBTUtil.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/serialization/NodeNBTUtil.kt @@ -6,7 +6,7 @@ import net.minecraft.world.level.Level import org.valkyrienskies.kelvin.KelvinMod import org.valkyrienskies.kelvin.api.DuctNetwork import org.valkyrienskies.kelvin.api.DuctNodePos -import org.valkyrienskies.kelvin.impl.GasTypeRegistry +import org.valkyrienskies.kelvin.impl.registry.GasTypeRegistry object NodeNBTUtil { fun serializeNode(pos: DuctNodePos, network: DuctNetwork, tag: CompoundTag) { @@ -28,7 +28,6 @@ object NodeNBTUtil { if (gasResourceLocation == "KelvinTemperature") continue val gasType = GasTypeRegistry.GAS_TYPES[ResourceLocation(gasResourceLocation)] ?: continue - println("$gasResourceLocation $gasType ${tag.getDouble(gasResourceLocation)}") network.modGasMass(pos,gasType,tag.getDouble(gasResourceLocation)) } network.modTemperature(pos, temperature) diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/util/GasHeatLevel.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/util/GasHeatLevel.kt index e5567c6..efff846 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/util/GasHeatLevel.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/util/GasHeatLevel.kt @@ -16,12 +16,12 @@ enum class GasHeatLevel: StringRepresentable { } override fun getSerializedName(): String { - return name.toLowerCase(Locale.ROOT) + return name.lowercase(Locale.ROOT) } companion object { fun byIndex(index: Int): GasHeatLevel { - return values()[index] + return entries[index] } } } \ No newline at end of file diff --git a/common/src/main/kotlin/org/valkyrienskies/kelvin/util/KelvinKeyMapper.kt b/common/src/main/kotlin/org/valkyrienskies/kelvin/util/KelvinKeyMapper.kt index e64cc01..b73eacb 100644 --- a/common/src/main/kotlin/org/valkyrienskies/kelvin/util/KelvinKeyMapper.kt +++ b/common/src/main/kotlin/org/valkyrienskies/kelvin/util/KelvinKeyMapper.kt @@ -8,7 +8,6 @@ import com.fasterxml.jackson.databind.JsonSerializer import com.fasterxml.jackson.databind.KeyDeserializer import com.fasterxml.jackson.databind.SerializerProvider import net.minecraft.resources.ResourceLocation -import org.valkyrienskies.kelvin.api.DuctNode import org.valkyrienskies.kelvin.api.DuctNodePos import org.valkyrienskies.kelvin.api.GasType @@ -76,11 +75,10 @@ object KelvinKeyMapper { val thermalConductivity = parts[5].toDoubleOrNull() val sutherlandConstant = parts[6].toDoubleOrNull() val adiabaticIndex = parts[7].toDoubleOrNull() - val combustible = parts[8].toBoolean() - val calorificValue = parts[9].toDoubleOrNull() - val iconLocation = if (parts[10] == "null") null else ResourceLocation(parts[10]) - if (density != null && viscosity != null && specificHeatCapacity != null && thermalConductivity != null && sutherlandConstant != null && adiabaticIndex != null && calorificValue != null) { - return GasType(name, resourceLocation, density, viscosity, specificHeatCapacity, thermalConductivity, sutherlandConstant, adiabaticIndex, combustible, calorificValue, iconLocation) + val iconLocation = ResourceLocation(parts[8]) + if (density != null && viscosity != null && specificHeatCapacity != null && thermalConductivity != null && sutherlandConstant != null && adiabaticIndex != null) { + //TODO: SERIALIZE PARTICLE PICKER + return GasType(name, resourceLocation, density, viscosity, specificHeatCapacity, thermalConductivity, sutherlandConstant, adiabaticIndex, iconLocation) } else throw IllegalArgumentException("Invalid GasType string") } } @@ -137,12 +135,11 @@ object KelvinKeyMapper { val thermalConductivity = parts[5].toDoubleOrNull() val sutherlandConstant = parts[6].toDoubleOrNull() val adiabaticIndex = parts[7].toDoubleOrNull() - val combustible = parts[8].toBoolean() - val calorificValue = parts[9].toDoubleOrNull() - val iconLocation = if (parts[10] == "null") null else ResourceLocation(parts[10]) + val iconLocation = ResourceLocation(parts[8]) - if (density != null && viscosity != null && specificHeatCapacity != null && thermalConductivity != null && sutherlandConstant != null && adiabaticIndex != null && calorificValue != null) { - return GasType(name, resourceLocation, density, viscosity, specificHeatCapacity, thermalConductivity, sutherlandConstant, adiabaticIndex, combustible, calorificValue, iconLocation) + if (density != null && viscosity != null && specificHeatCapacity != null && thermalConductivity != null && sutherlandConstant != null && adiabaticIndex != null) { + //TODO: SERIALIZE PARTICLE PICKER + return GasType(name, resourceLocation, density, viscosity, specificHeatCapacity, thermalConductivity, sutherlandConstant, adiabaticIndex, iconLocation) } } } diff --git a/common/src/main/resources/assets/kelvin/particles/air.json b/common/src/main/resources/assets/kelvin/particles/air.json new file mode 100644 index 0000000..2712610 --- /dev/null +++ b/common/src/main/resources/assets/kelvin/particles/air.json @@ -0,0 +1,12 @@ +{ + "textures": [ + "minecraft:generic_7", + "minecraft:generic_6", + "minecraft:generic_5", + "minecraft:generic_4", + "minecraft:generic_3", + "minecraft:generic_2", + "minecraft:generic_1", + "minecraft:generic_0" + ] +} \ No newline at end of file diff --git a/common/src/main/resources/assets/kelvin/particles/exhaust.json b/common/src/main/resources/assets/kelvin/particles/exhaust.json new file mode 100644 index 0000000..2712610 --- /dev/null +++ b/common/src/main/resources/assets/kelvin/particles/exhaust.json @@ -0,0 +1,12 @@ +{ + "textures": [ + "minecraft:generic_7", + "minecraft:generic_6", + "minecraft:generic_5", + "minecraft:generic_4", + "minecraft:generic_3", + "minecraft:generic_2", + "minecraft:generic_1", + "minecraft:generic_0" + ] +} \ No newline at end of file diff --git a/common/src/main/resources/assets/kelvin/particles/helium.json b/common/src/main/resources/assets/kelvin/particles/helium.json new file mode 100644 index 0000000..2712610 --- /dev/null +++ b/common/src/main/resources/assets/kelvin/particles/helium.json @@ -0,0 +1,12 @@ +{ + "textures": [ + "minecraft:generic_7", + "minecraft:generic_6", + "minecraft:generic_5", + "minecraft:generic_4", + "minecraft:generic_3", + "minecraft:generic_2", + "minecraft:generic_1", + "minecraft:generic_0" + ] +} \ No newline at end of file diff --git a/common/src/main/resources/assets/kelvin/particles/hydrogen.json b/common/src/main/resources/assets/kelvin/particles/hydrogen.json new file mode 100644 index 0000000..2712610 --- /dev/null +++ b/common/src/main/resources/assets/kelvin/particles/hydrogen.json @@ -0,0 +1,12 @@ +{ + "textures": [ + "minecraft:generic_7", + "minecraft:generic_6", + "minecraft:generic_5", + "minecraft:generic_4", + "minecraft:generic_3", + "minecraft:generic_2", + "minecraft:generic_1", + "minecraft:generic_0" + ] +} \ No newline at end of file diff --git a/common/src/main/resources/assets/kelvin/particles/methane.json b/common/src/main/resources/assets/kelvin/particles/methane.json new file mode 100644 index 0000000..2712610 --- /dev/null +++ b/common/src/main/resources/assets/kelvin/particles/methane.json @@ -0,0 +1,12 @@ +{ + "textures": [ + "minecraft:generic_7", + "minecraft:generic_6", + "minecraft:generic_5", + "minecraft:generic_4", + "minecraft:generic_3", + "minecraft:generic_2", + "minecraft:generic_1", + "minecraft:generic_0" + ] +} \ No newline at end of file diff --git a/common/src/main/resources/assets/kelvin/particles/phlogiston.json b/common/src/main/resources/assets/kelvin/particles/phlogiston.json new file mode 100644 index 0000000..2712610 --- /dev/null +++ b/common/src/main/resources/assets/kelvin/particles/phlogiston.json @@ -0,0 +1,12 @@ +{ + "textures": [ + "minecraft:generic_7", + "minecraft:generic_6", + "minecraft:generic_5", + "minecraft:generic_4", + "minecraft:generic_3", + "minecraft:generic_2", + "minecraft:generic_1", + "minecraft:generic_0" + ] +} \ No newline at end of file diff --git a/common/src/main/resources/assets/kelvin/particles/steam.json b/common/src/main/resources/assets/kelvin/particles/steam.json new file mode 100644 index 0000000..2712610 --- /dev/null +++ b/common/src/main/resources/assets/kelvin/particles/steam.json @@ -0,0 +1,12 @@ +{ + "textures": [ + "minecraft:generic_7", + "minecraft:generic_6", + "minecraft:generic_5", + "minecraft:generic_4", + "minecraft:generic_3", + "minecraft:generic_2", + "minecraft:generic_1", + "minecraft:generic_0" + ] +} \ No newline at end of file diff --git a/common/src/main/resources/assets/kelvin/textures/gui/gas_reaction_recipe_background.png b/common/src/main/resources/assets/kelvin/textures/gui/gas_reaction_recipe_background.png new file mode 100644 index 0000000..ff1ba10 Binary files /dev/null and b/common/src/main/resources/assets/kelvin/textures/gui/gas_reaction_recipe_background.png differ diff --git a/common/src/main/resources/assets/kelvin/textures/icons/air.png b/common/src/main/resources/assets/kelvin/textures/icons/air.png new file mode 100644 index 0000000..dc33886 Binary files /dev/null and b/common/src/main/resources/assets/kelvin/textures/icons/air.png differ diff --git a/common/src/main/resources/assets/kelvin/textures/icons/exhaust.png b/common/src/main/resources/assets/kelvin/textures/icons/exhaust.png new file mode 100644 index 0000000..2e2e94a Binary files /dev/null and b/common/src/main/resources/assets/kelvin/textures/icons/exhaust.png differ diff --git a/common/src/main/resources/assets/kelvin/textures/icons/helium.png b/common/src/main/resources/assets/kelvin/textures/icons/helium.png new file mode 100644 index 0000000..4b9a892 Binary files /dev/null and b/common/src/main/resources/assets/kelvin/textures/icons/helium.png differ diff --git a/common/src/main/resources/assets/kelvin/textures/icons/hydrogen.png b/common/src/main/resources/assets/kelvin/textures/icons/hydrogen.png new file mode 100644 index 0000000..3603273 Binary files /dev/null and b/common/src/main/resources/assets/kelvin/textures/icons/hydrogen.png differ diff --git a/common/src/main/resources/assets/kelvin/textures/icons/methane.png b/common/src/main/resources/assets/kelvin/textures/icons/methane.png new file mode 100644 index 0000000..821e86f Binary files /dev/null and b/common/src/main/resources/assets/kelvin/textures/icons/methane.png differ diff --git a/common/src/main/resources/assets/kelvin/textures/icons/phlogiston.png b/common/src/main/resources/assets/kelvin/textures/icons/phlogiston.png new file mode 100644 index 0000000..10a21a6 Binary files /dev/null and b/common/src/main/resources/assets/kelvin/textures/icons/phlogiston.png differ diff --git a/common/src/main/resources/assets/kelvin/textures/icons/placeholder.png b/common/src/main/resources/assets/kelvin/textures/icons/placeholder.png new file mode 100644 index 0000000..391cdad Binary files /dev/null and b/common/src/main/resources/assets/kelvin/textures/icons/placeholder.png differ diff --git a/common/src/main/resources/assets/kelvin/textures/icons/steam.png b/common/src/main/resources/assets/kelvin/textures/icons/steam.png new file mode 100644 index 0000000..f2a4486 Binary files /dev/null and b/common/src/main/resources/assets/kelvin/textures/icons/steam.png differ diff --git a/common/src/main/resources/data/kelvin/kelvin_reactions/test_recipe.json b/common/src/main/resources/data/kelvin/kelvin_reactions/test_recipe.json new file mode 100644 index 0000000..61c3e4b --- /dev/null +++ b/common/src/main/resources/data/kelvin/kelvin_reactions/test_recipe.json @@ -0,0 +1,15 @@ +{ + "gasses": { + "kelvin:methane": 1, + "kelvin:air": 2 + }, + "requirements": { + "kelvin:min_temperature": 800, + "kelvin:min_pressure": 1000 + }, + "energy": 890400, + "result": { + "kelvin:exhaust": 1, + "kelvin:steam": 2 + } +} \ No newline at end of file diff --git a/common/src/main/resources/data/kelvin/kelvin_reactions/test_recipe_2.json b/common/src/main/resources/data/kelvin/kelvin_reactions/test_recipe_2.json new file mode 100644 index 0000000..660f0da --- /dev/null +++ b/common/src/main/resources/data/kelvin/kelvin_reactions/test_recipe_2.json @@ -0,0 +1,14 @@ +{ + "gasses": { + "kelvin:methane": 1, + "kelvin:air": 3, + "kelvin:hydrogen": 2 + }, + "requirements": { + "kelvin:max_temperature": 1200, + "kelvin:max_pressure": 50000 + }, + "result": { + "kelvin:phlogiston": 10 + } +} \ No newline at end of file diff --git a/fabric/build.gradle b/fabric/build.gradle index 53a755d..730e9a6 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -23,6 +23,24 @@ configurations { developmentFabric.extendsFrom common } +repositories { + maven { + // location of the maven that hosts JEI files before January 2023 + name = "Progwml6's maven" + url = "https://dvs1.progwml6.com/files/maven/" + } + maven { + // location of the maven that hosts JEI files since January 2023 + name = "Jared's maven" + url = "https://maven.blamejared.com/" + } + maven { + // location of a maven mirror for JEI files, as a fallback + name = "ModMaven" + url = "https://modmaven.dev" + } +} + dependencies { modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" @@ -37,6 +55,9 @@ dependencies { // Architectury API include(modApi "dev.architectury:architectury-fabric:${rootProject.architectury_version}") + //JEI + modCompileOnly "mezz.jei:jei-${rootProject.minecraft_version}-fabric-api:${rootProject.jei_version}" + // Mod menu modImplementation("com.terraformersmc:modmenu:7.2.2") modImplementation("me.shedaniel.cloth:cloth-config:${cloth_config_version}") { diff --git a/fabric/src/main/kotlin/org/valkyrienskies/kelvin/fabric/KelvinModFabric.kt b/fabric/src/main/kotlin/org/valkyrienskies/kelvin/fabric/KelvinModFabric.kt index 3516a76..0da0331 100644 --- a/fabric/src/main/kotlin/org/valkyrienskies/kelvin/fabric/KelvinModFabric.kt +++ b/fabric/src/main/kotlin/org/valkyrienskies/kelvin/fabric/KelvinModFabric.kt @@ -7,14 +7,27 @@ import net.fabricmc.api.EnvType import net.fabricmc.api.Environment import net.fabricmc.api.ModInitializer import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents +import net.fabricmc.fabric.api.resource.ResourceManagerHelper +import net.minecraft.resources.ResourceLocation import org.valkyrienskies.kelvin.KelvinMod +import org.valkyrienskies.kelvin.impl.KelvinReactionDataLoader import org.valkyrienskies.kelvin.util.KelvinChunkPos +import net.minecraft.server.packs.PackType.SERVER_DATA +import net.minecraft.server.packs.resources.PreparableReloadListener +import java.util.concurrent.CompletableFuture +import net.minecraft.server.packs.resources.ResourceManager +import net.minecraft.util.profiling.ProfilerFiller +import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener +import org.valkyrienskies.kelvin.KelvinParticles +import java.util.concurrent.Executor + object KelvinModFabric: ModInitializer { override fun onInitialize() { init() + ServerChunkEvents.CHUNK_LOAD.register { serverWorld, chunk -> try { KelvinMod.getKelvin().markChunkLoaded(KelvinChunkPos(chunk.pos.x, chunk.pos.z, serverWorld.dimension().location())) @@ -32,12 +45,37 @@ object KelvinModFabric: ModInitializer { KelvinMod.KELVINLOGGER.error(e.stackTrace) } } + + + val loader = KelvinReactionDataLoader.loader // the get makes a new instance so get it only once + ResourceManagerHelper.get(SERVER_DATA) + .registerReloadListener(object : IdentifiableResourceReloadListener { + override fun getFabricId(): ResourceLocation { + return ResourceLocation(KelvinMod.MOD_ID, "kelvin_reactions") + } + + override fun reload( + stage: PreparableReloadListener.PreparationBarrier, + resourceManager: ResourceManager, + preparationsProfiler: ProfilerFiller, + reloadProfiler: ProfilerFiller, + backgroundExecutor: Executor, + gameExecutor: Executor + ): CompletableFuture { + return loader.reload( + stage, resourceManager, preparationsProfiler, reloadProfiler, + backgroundExecutor, gameExecutor + ) + } + }) } + @Environment(EnvType.CLIENT) class Client : ClientModInitializer { override fun onInitializeClient() { initClient() + KelvinParticles.KelvinClientParticles.init() } } } diff --git a/forge/build.gradle b/forge/build.gradle index 861138a..c038387 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -48,6 +48,10 @@ dependencies { // Architectury API include(modApi "dev.architectury:architectury-forge:${rootProject.architectury_version}") + //JEI + modCompileOnly "mezz.jei:jei-${rootProject.minecraft_version}-forge-api:${rootProject.jei_version}" + modRuntimeOnly "mezz.jei:jei-${rootProject.minecraft_version}-forge:${rootProject.jei_version}" + common(project(path: ":common", configuration: "namedElements")) { transitive false } shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive = false } @@ -55,6 +59,24 @@ dependencies { implementation "thedarkcolour:kotlinforforge:$forge_kotlin_version" } +repositories { + maven { + // location of the maven that hosts JEI files before January 2023 + name = "Progwml6's maven" + url = "https://dvs1.progwml6.com/files/maven/" + } + maven { + // location of the maven that hosts JEI files since January 2023 + name = "Jared's maven" + url = "https://maven.blamejared.com/" + } + maven { + // location of a maven mirror for JEI files, as a fallback + name = "ModMaven" + url = "https://modmaven.dev" + } +} + processResources { inputs.property "version", project.version diff --git a/forge/src/main/kotlin/org/valkyrienskies/kelvin/forge/KelvinModForge.kt b/forge/src/main/kotlin/org/valkyrienskies/kelvin/forge/KelvinModForge.kt index 60a1601..c8353c2 100644 --- a/forge/src/main/kotlin/org/valkyrienskies/kelvin/forge/KelvinModForge.kt +++ b/forge/src/main/kotlin/org/valkyrienskies/kelvin/forge/KelvinModForge.kt @@ -1,7 +1,9 @@ package org.valkyrienskies.kelvin.forge +import dev.architectury.platform.forge.EventBuses import net.minecraft.server.level.ServerLevel -import net.minecraftforge.common.MinecraftForge +import net.minecraftforge.client.event.RegisterParticleProvidersEvent +import net.minecraftforge.event.AddReloadListenerEvent import net.minecraftforge.event.level.ChunkEvent import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.fml.common.Mod @@ -9,7 +11,10 @@ import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent import org.valkyrienskies.kelvin.KelvinMod import org.valkyrienskies.kelvin.KelvinMod.init import org.valkyrienskies.kelvin.KelvinMod.initClient +import org.valkyrienskies.kelvin.KelvinParticles +import org.valkyrienskies.kelvin.impl.KelvinReactionDataLoader import org.valkyrienskies.kelvin.util.KelvinChunkPos +import thedarkcolour.kotlinforforge.forge.FORGE_BUS import thedarkcolour.kotlinforforge.forge.MOD_BUS @Mod(KelvinMod.MOD_ID) @@ -20,28 +25,29 @@ class KelvinModForge { event ) } + + EventBuses.registerModEventBus(KelvinMod.MOD_ID, getModBus()) init() - MinecraftForge.EVENT_BUS.addListener { event: ChunkEvent.Load -> - val level = event.chunk.worldForge - if (level is ServerLevel && !level.isClientSide) { + FORGE_BUS.addListener { event: ChunkEvent.Load -> + if (!event.level.isClientSide) { try { KelvinMod.getKelvin().markChunkLoaded( KelvinChunkPos( event.chunk.pos.x, event.chunk.pos.z, - level.dimension().location() + (event.level as ServerLevel).dimension().location() ) ) } catch (e: IllegalStateException) { - KelvinMod.KELVINLOGGER.error("Failed to mark chunk as loaded. Stack Trace:", e) + KelvinMod.KELVINLOGGER.error("Failed to mark chunk as loaded. Stack Trace:") + KelvinMod.KELVINLOGGER.error(e.stackTrace) } } } - MinecraftForge.EVENT_BUS.addListener { event: ChunkEvent.Unload -> - val level = event.chunk.worldForge - if (level is ServerLevel && !level.isClientSide) { + FORGE_BUS.addListener { event: ChunkEvent.Unload -> + if (!event.level.isClientSide) { try { KelvinMod.getKelvin().markChunkUnloaded( KelvinChunkPos( @@ -56,6 +62,17 @@ class KelvinModForge { } } } + + FORGE_BUS.addListener(::registerResourceManagers) + + MOD_BUS.addListener { event: RegisterParticleProvidersEvent -> + KelvinParticles.KelvinClientParticles.init() + } + } + + private fun registerResourceManagers(event: AddReloadListenerEvent) { + event.addListener(KelvinReactionDataLoader.loader) + } private fun clientSetup(event: FMLClientSetupEvent?) { diff --git a/gradle.properties b/gradle.properties index 1256c21..7060cac 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx4096M # Identity mod_name=Kelvin mod_id=kelvin -mod_version=0.1.1 +mod_version=0.1.6 mod_description=A dynamic gas framework for Minecraft. mod_license=Apache-2.0 mod_author=ThePlasticPotato, PriestOfFern @@ -23,7 +23,8 @@ fabric_api_version=0.90.7+1.20.1 forge_version=1.20.1-47.2.0 forge_kotlin_version=4.10.0 kotlin_version=1.9.10 -cloth_config_version=4.14.64 +cloth_config_version=6.4.90 +jei_version=15.20.0.112 # Maven publishing vs_maven_url= vs_maven_username=