Skip to content

Commit

Permalink
feat: config
Browse files Browse the repository at this point in the history
  • Loading branch information
andantet committed Dec 31, 2024
1 parent 9b67b0a commit 6584143
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 28 deletions.
50 changes: 45 additions & 5 deletions src/main/kotlin/dev/hybridlabs/aquatic/HybridAquatic.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package dev.hybridlabs.aquatic

//import dev.hybridlabs.aquatic.world.biome.HybridAquaticBiomes
import dev.hybridlabs.aquatic.block.HybridAquaticBlocks
import dev.hybridlabs.aquatic.block.PlushieBlock
import dev.hybridlabs.aquatic.block.SeaMessage
import dev.hybridlabs.aquatic.block.entity.HybridAquaticBlockEntityTypes
import dev.hybridlabs.aquatic.config.HybridAquaticConfigHandler
import dev.hybridlabs.aquatic.effect.HybridAquaticStatusEffects
import dev.hybridlabs.aquatic.enchantment.HybridAquaticEnchantments
import dev.hybridlabs.aquatic.entity.HybridAquaticEntityTypes
Expand All @@ -19,28 +19,38 @@ import dev.hybridlabs.aquatic.potions.HybridAquaticPotions
import dev.hybridlabs.aquatic.registry.HybridAquaticRegistryKeys
import dev.hybridlabs.aquatic.tag.HybridAquaticBiomeTags
import dev.hybridlabs.aquatic.utils.HybridAquaticCustomTrades.registerCustomTrades
import dev.hybridlabs.aquatic.world.EntityBiomeModifications
import dev.hybridlabs.aquatic.world.gen.feature.FeatureBiomeModifications
import dev.hybridlabs.aquatic.world.gen.feature.HybridAquaticConfiguredFeatures
import dev.hybridlabs.aquatic.world.gen.feature.HybridAquaticFeatures
import dev.hybridlabs.aquatic.world.gen.feature.HybridAquaticPlacedFeatures
import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.biome.v1.BiomeModifications
import net.fabricmc.fabric.api.biome.v1.BiomeSelectors
import net.fabricmc.fabric.api.event.registry.DynamicRegistries
import net.fabricmc.fabric.api.`object`.builder.v1.trade.TradeOfferHelper
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry
import net.fabricmc.fabric.api.registry.StrippableBlockRegistry
import net.fabricmc.loader.api.FabricLoader
import net.minecraft.item.BlockItem
import net.minecraft.registry.Registries
import net.minecraft.village.TradeOffers.SellItemFactory
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.nio.file.Path
import kotlin.collections.forEach
import kotlin.io.path.notExists

object HybridAquatic : ModInitializer {
const val MOD_ID: String = "hybrid-aquatic"
private val logger: Logger = LoggerFactory.getLogger(MOD_ID)
const val MOD_NAME: String = "Hybrid Aquatic"

private val logger: Logger = LoggerFactory.getLogger(MOD_NAME)

val configFile: Path = FabricLoader.getInstance().configDir.resolve("$MOD_ID.json")
val configHandler = HybridAquaticConfigHandler(configFile.toFile())

override fun onInitialize() {
logger.info("Initializing $MOD_ID")
logger.info("Initializing $MOD_NAME")

HybridAquaticFluids
HybridAquaticBlocks
Expand Down Expand Up @@ -82,13 +92,43 @@ object HybridAquatic : ModInitializer {
LootTableModifications

FeatureBiomeModifications
EntityBiomeModifications

SpawnRestrictionRegistry

registerDynamicRegistries()
registerWanderingTraderTrades()
registerCustomTrades()
initializeConfig()

// entity spawn modifications
val config = configHandler.config
config.entitySpawnConfig.forEach { config ->
BiomeModifications.addSpawn(BiomeSelectors.tag(config.biomes), config.group, config.type, config.weight, config.minGroupSize, config.maxGroupSize)
}
}

private fun initializeConfig() {
if (configFile.notExists()) {
logger.info("$MOD_NAME config file did not exist, creating one")
configHandler.save()
} else {
logger.info("Loading $MOD_NAME config file")
configHandler.load()

// check config data version, if updated then reset
val defaultConfig = configHandler.defaultConfig
val config = configHandler.config
if (config.dataVersion < defaultConfig.dataVersion) {
logger.info("Old $MOD_NAME config file found, upgrading")

configHandler.backup()

configHandler.config = defaultConfig
configHandler.save()

logger.info("$MOD_NAME config reset, the old config has been backed up to \"${configHandler.backupFile}\"")
}
}
}

private fun registerDynamicRegistries() {
Expand Down
32 changes: 32 additions & 0 deletions src/main/kotlin/dev/hybridlabs/aquatic/config/EntitySpawnConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package dev.hybridlabs.aquatic.config

import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.entity.EntityType
import net.minecraft.entity.SpawnGroup
import net.minecraft.registry.Registries
import net.minecraft.registry.RegistryKeys
import net.minecraft.registry.tag.TagKey
import net.minecraft.world.biome.Biome

data class EntitySpawnConfig(
val type: EntityType<*>,
val biomes: TagKey<Biome>,
val group: SpawnGroup,
val weight: Int,
val minGroupSize: Int,
val maxGroupSize: Int,
) {
companion object {
val CODEC: Codec<EntitySpawnConfig> = RecordCodecBuilder.create { instance ->
instance.group(
Registries.ENTITY_TYPE.codec.fieldOf("type").forGetter(EntitySpawnConfig::type),
TagKey.codec(RegistryKeys.BIOME).fieldOf("biomes").forGetter(EntitySpawnConfig::biomes),
SpawnGroup.CODEC.fieldOf("group").forGetter(EntitySpawnConfig::group),
Codec.INT.fieldOf("weight").forGetter(EntitySpawnConfig::weight),
Codec.INT.fieldOf("min_group_size").forGetter(EntitySpawnConfig::minGroupSize),
Codec.INT.fieldOf("max_group_size").forGetter(EntitySpawnConfig::maxGroupSize),
).apply(instance, ::EntitySpawnConfig)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
@file:Suppress("SameParameterValue")

package dev.hybridlabs.aquatic.world
package dev.hybridlabs.aquatic.config

import dev.hybridlabs.aquatic.entity.HybridAquaticEntityTypes
import dev.hybridlabs.aquatic.tag.HybridAquaticBiomeTags
import dev.hybridlabs.aquatic.utils.HybridAquaticSpawnGroup
import net.fabricmc.fabric.api.biome.v1.BiomeModifications
import net.minecraft.entity.EntityType
import net.minecraft.entity.SpawnGroup
import net.minecraft.registry.tag.BiomeTags
import net.minecraft.registry.tag.TagKey
import net.minecraft.world.biome.Biome

/**
* Applies biome modifications for entities when initialised.
*/
object EntityBiomeModifications {
init {
class EntitySpawnConfigGenerator {
private val list: MutableList<EntitySpawnConfig> = mutableListOf()

fun initialize() {
//#region Fish
addFish(HybridAquaticEntityTypes.AFRICAN_BUTTERFLY, listOf(HybridAquaticBiomeTags.JUNGLE, HybridAquaticBiomeTags.MARSHES, HybridAquaticBiomeTags.MANGROVES), 2, 1, 1)
addFish(HybridAquaticEntityTypes.GOLDEN_DORADO, listOf(HybridAquaticBiomeTags.TROPICAL_RIVERS, HybridAquaticBiomeTags.RIVERS, HybridAquaticBiomeTags.JUNGLE), 1, 1, 1)
Expand Down Expand Up @@ -218,56 +216,64 @@ object EntityBiomeModifications {

private fun addUndergroundJelly(
entityType: EntityType<*>,
spawnTags: List<TagKey<Biome>>,
spawnTags: List<net.minecraft.registry.tag.TagKey<net.minecraft.world.biome.Biome>>,
weight: Int,
minGroup: Int,
maxGroup: Int
) {
add(entityType, spawnTags, HybridAquaticSpawnGroup.JELLY_UNDERGROUND.spawnGroup, weight, minGroup, maxGroup)
add(entityType, spawnTags, dev.hybridlabs.aquatic.utils.HybridAquaticSpawnGroup.JELLY_UNDERGROUND.spawnGroup, weight, minGroup, maxGroup)
}

private fun addCrustacean(
entityType: EntityType<*>,
spawnTags: List<TagKey<Biome>>,
entityType: net.minecraft.entity.EntityType<*>,
spawnTags: List<net.minecraft.registry.tag.TagKey<net.minecraft.world.biome.Biome>>,
weight: Int,
minGroup: Int,
maxGroup: Int
) {
add(entityType, spawnTags, HybridAquaticSpawnGroup.CRUSTACEAN.spawnGroup, weight, minGroup, maxGroup)
add(entityType, spawnTags, dev.hybridlabs.aquatic.utils.HybridAquaticSpawnGroup.CRUSTACEAN.spawnGroup, weight, minGroup, maxGroup)
}

private fun addUndergroundCrustacean(
entityType: EntityType<*>,
spawnTags: List<TagKey<Biome>>,
entityType: net.minecraft.entity.EntityType<*>,
spawnTags: List<net.minecraft.registry.tag.TagKey<net.minecraft.world.biome.Biome>>,
weight: Int,
minGroup: Int,
maxGroup: Int
) {
add(
entityType, spawnTags, HybridAquaticSpawnGroup.CRUSTACEAN_UNDERGROUND.spawnGroup, weight, minGroup, maxGroup
entityType, spawnTags, dev.hybridlabs.aquatic.utils.HybridAquaticSpawnGroup.CRUSTACEAN_UNDERGROUND.spawnGroup, weight, minGroup, maxGroup
)
}

private fun addCritter(
entityType: EntityType<*>,
spawnTags: List<TagKey<Biome>>,
entityType: net.minecraft.entity.EntityType<*>,
spawnTags: List<net.minecraft.registry.tag.TagKey<net.minecraft.world.biome.Biome>>,
weight: Int,
minGroup: Int,
maxGroup: Int
) {
add(entityType, spawnTags, HybridAquaticSpawnGroup.CRITTER.spawnGroup, weight, minGroup, maxGroup)
add(entityType, spawnTags, dev.hybridlabs.aquatic.utils.HybridAquaticSpawnGroup.CRITTER.spawnGroup, weight, minGroup, maxGroup)
}

private fun add(
entityType: EntityType<*>,
spawnTags: List<TagKey<Biome>>,
spawnGroup: SpawnGroup,
entityType: net.minecraft.entity.EntityType<*>,
spawnTags: List<net.minecraft.registry.tag.TagKey<net.minecraft.world.biome.Biome>>,
spawnGroup: net.minecraft.entity.SpawnGroup,
weight: Int,
minGroup: Int,
maxGroup: Int
) {
spawnTags.forEach { spawnTag ->
BiomeModifications.addSpawn({ it.hasTag(spawnTag) }, spawnGroup, entityType, weight, minGroup, maxGroup)
list.add(EntitySpawnConfig(entityType, spawnTag, spawnGroup, weight, minGroup, maxGroup))
}
}

companion object {
fun generate(): List<EntitySpawnConfig> {
val generator = EntitySpawnConfigGenerator()
generator.initialize()
return generator.list
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package dev.hybridlabs.aquatic.config

import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder

data class HybridAquaticConfig(
/**
* The version of the data stored.
* Increase when the config needs to be reset, i.e. when new entity spawn configs are added.
*/
val dataVersion: Int = 0,

val entitySpawnConfig: List<EntitySpawnConfig> = EntitySpawnConfigGenerator.generate(),
) {
companion object {
val CODEC: Codec<HybridAquaticConfig> = RecordCodecBuilder.create { instance ->
instance.group(
Codec.INT.fieldOf("data_version").forGetter(HybridAquaticConfig::dataVersion),
EntitySpawnConfig.CODEC.listOf().fieldOf("spawn_configuration").forGetter(HybridAquaticConfig::entitySpawnConfig),
).apply(instance, ::HybridAquaticConfig)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package dev.hybridlabs.aquatic.config

import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonElement
import com.google.gson.JsonParser
import com.mojang.datafixers.util.Pair
import com.mojang.serialization.DataResult
import com.mojang.serialization.JsonOps
import java.io.File

class HybridAquaticConfigHandler(val file: File, val defaultConfig: HybridAquaticConfig = HybridAquaticConfig()) {
val backupFile = file.parentFile.resolve("${file.name}-backup")

var config: HybridAquaticConfig = defaultConfig

/**
* Reads the config from the config file.
* @return a data result of the config
*/
fun read(): DataResult<Pair<HybridAquaticConfig, JsonElement>> {
val json = file.reader().use(JsonParser::parseReader)
return HybridAquaticConfig.CODEC.decode(JsonOps.INSTANCE, json)
}

/**
* Reads and saves to memory the current config from its file.
* @return whether the config was loaded successfully
*/
fun load(): Boolean {
val dataResult = read()
val result = dataResult.result()

if (!result.isPresent) {
return false
}

config = result.get().first
return true
}

fun save(): Boolean {
val dataResult = HybridAquaticConfig.CODEC.encodeStart(JsonOps.INSTANCE, config)
val result = dataResult.result()

if (!result.isPresent) {
return false
}

val json = result.get()
val text = GSON.toJson(json)
file.writeText(text)
return true
}

/**
* Backs up the config file.
* @return whether the backup was successful
*/
fun backup(): Boolean {
return runCatching {
backupFile.writeBytes(file.readBytes())
}.getOrNull() != null
}

companion object {
val GSON: Gson = GsonBuilder().setPrettyPrinting().create()
}
}

0 comments on commit 6584143

Please sign in to comment.