Integrate ClothConfig for Forge
This commit is contained in:
@@ -6,9 +6,10 @@ plugins {
|
||||
apply(plugin = "org.spongepowered.mixin")
|
||||
|
||||
repositories {
|
||||
maven("http://files.minecraftforge.net/maven")
|
||||
maven("https://files.minecraftforge.net/maven")
|
||||
maven("https://repo.spongepowered.org/maven")
|
||||
maven("https://minecraft.curseforge.com/api/maven")
|
||||
maven("https://www.cursemaven.com")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -16,6 +17,8 @@ dependencies {
|
||||
|
||||
"implementation"("kottle:Kottle:${properties["kottleVersion"]}")
|
||||
"implementation"("org.spongepowered:mixin:0.8-SNAPSHOT")
|
||||
|
||||
"api"(fg.deobf("curse.maven:clothconfig-348521:2813656"))
|
||||
}
|
||||
|
||||
configurations["annotationProcessor"].extendsFrom(configurations["implementation"])
|
||||
@@ -45,6 +48,7 @@ java {
|
||||
kotlin {
|
||||
target.compilations.configureEach {
|
||||
kotlinOptions.freeCompilerArgs += listOf("-Xno-param-assertions", "-Xno-call-assertions")
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,33 +1,47 @@
|
||||
package mods.betterfoliage
|
||||
|
||||
import me.shedaniel.forge.clothconfig2.api.ConfigBuilder
|
||||
import mods.betterfoliage.client.Client
|
||||
import mods.betterfoliage.client.config.BlockConfig
|
||||
import mods.betterfoliage.client.config.Config
|
||||
import mods.octarinecore.client.resource.AsnycSpriteProviderManager
|
||||
import mods.octarinecore.client.resource.GeneratedBlockTexturePack
|
||||
import mods.betterfoliage.client.config.MainConfig
|
||||
import mods.octarinecore.common.config.clothGuiRoot
|
||||
import mods.octarinecore.common.config.forgeSpecRoot
|
||||
import net.alexwells.kottle.FMLKotlinModLoadingContext
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.particle.ParticleManager
|
||||
import net.minecraft.client.renderer.model.ModelBakery
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import net.minecraftforge.fml.ExtensionPoint.CONFIGGUIFACTORY
|
||||
import net.minecraftforge.fml.ModLoadingContext
|
||||
import net.minecraftforge.fml.common.Mod
|
||||
import net.minecraftforge.fml.config.ModConfig
|
||||
import org.apache.logging.log4j.Level.DEBUG
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.apache.logging.log4j.simple.SimpleLogger
|
||||
import org.apache.logging.log4j.util.PropertiesUtil
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
import java.util.*
|
||||
import org.apache.commons.lang3.tuple.Pair
|
||||
import java.util.function.BiFunction
|
||||
import java.util.function.BiPredicate
|
||||
import java.util.function.Supplier
|
||||
|
||||
@Mod(BetterFoliageMod.MOD_ID)
|
||||
object BetterFoliageMod {
|
||||
const val MOD_ID = "betterfoliage"
|
||||
|
||||
val bus = FMLKotlinModLoadingContext.get().modEventBus
|
||||
val config = MainConfig()
|
||||
|
||||
init {
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, Config.build())
|
||||
val ctx = ModLoadingContext.get()
|
||||
|
||||
// Config instance + GUI handler
|
||||
val configSpec = config.forgeSpecRoot()
|
||||
ctx.registerConfig(ModConfig.Type.CLIENT, configSpec)
|
||||
ctx.registerExtensionPoint(CONFIGGUIFACTORY) { BiFunction<Minecraft, Screen, Screen> { client, parent ->
|
||||
config.clothGuiRoot(
|
||||
parentScreen = parent,
|
||||
prefix = listOf(MOD_ID),
|
||||
background = ResourceLocation("minecraft:textures/block/spruce_wood.png"),
|
||||
saveAction = { configSpec.save() }
|
||||
)
|
||||
} }
|
||||
|
||||
|
||||
Minecraft.getInstance().resourcePackList.addPackFinder(BetterFoliage.asyncPack.finder)
|
||||
bus.register(BlockConfig)
|
||||
Client.init()
|
||||
|
||||
@@ -1,30 +1,38 @@
|
||||
package mods.betterfoliage.client
|
||||
|
||||
import mods.betterfoliage.BetterFoliageMod
|
||||
import mods.betterfoliage.client.chunk.ChunkOverlayManager
|
||||
import mods.betterfoliage.client.config.BlockConfig
|
||||
import mods.betterfoliage.client.integration.*
|
||||
import mods.betterfoliage.client.render.*
|
||||
import mods.betterfoliage.client.integration.OptifineCustomColors
|
||||
import mods.betterfoliage.client.integration.ShadersModIntegration
|
||||
import mods.betterfoliage.client.render.AsyncCactusDiscovery
|
||||
import mods.betterfoliage.client.render.AsyncLogDiscovery
|
||||
import mods.betterfoliage.client.render.LeafWindTracker
|
||||
import mods.betterfoliage.client.render.RenderAlgae
|
||||
import mods.betterfoliage.client.render.RenderCactus
|
||||
import mods.betterfoliage.client.render.RenderConnectedGrass
|
||||
import mods.betterfoliage.client.render.RenderConnectedGrassLog
|
||||
import mods.betterfoliage.client.render.RenderCoral
|
||||
import mods.betterfoliage.client.render.RenderGrass
|
||||
import mods.betterfoliage.client.render.RenderLeaves
|
||||
import mods.betterfoliage.client.render.RenderLilypad
|
||||
import mods.betterfoliage.client.render.RenderLog
|
||||
import mods.betterfoliage.client.render.RenderMycelium
|
||||
import mods.betterfoliage.client.render.RenderNetherrack
|
||||
import mods.betterfoliage.client.render.RenderReeds
|
||||
import mods.betterfoliage.client.render.RisingSoulTextures
|
||||
import mods.betterfoliage.client.texture.AsyncGrassDiscovery
|
||||
import mods.betterfoliage.client.texture.AsyncLeafDiscovery
|
||||
import mods.betterfoliage.client.texture.LeafParticleRegistry
|
||||
import mods.octarinecore.client.gui.textComponent
|
||||
import mods.octarinecore.client.render.RenderDecorator
|
||||
import mods.octarinecore.client.resource.IConfigChangeListener
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.text.TextFormatting
|
||||
import net.minecraft.util.text.TranslationTextComponent
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import org.apache.logging.log4j.Level
|
||||
|
||||
/**
|
||||
* Object responsible for initializing (and holding a reference to) all the infrastructure of the mod
|
||||
* except for the call hooks.
|
||||
*/
|
||||
object Client {
|
||||
var renderers= emptyList<RenderDecorator>()
|
||||
var renderers = emptyList<RenderDecorator>()
|
||||
var configListeners = emptyList<IConfigChangeListener>()
|
||||
|
||||
val suppressRenderErrors = mutableSetOf<BlockState>()
|
||||
|
||||
@@ -8,139 +8,6 @@ import net.minecraft.util.ResourceLocation
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
import net.minecraftforge.fml.config.ModConfig
|
||||
|
||||
private fun featureEnable() = boolean(true).lang("enabled")
|
||||
|
||||
// Config singleton
|
||||
object Config : DelegatingConfig(BetterFoliageMod.MOD_ID, BetterFoliageMod.MOD_ID) {
|
||||
|
||||
val enabled by boolean(true)
|
||||
val nVidia by boolean(false)
|
||||
|
||||
object leaves : ConfigCategory() {
|
||||
val enabled by featureEnable()
|
||||
val snowEnabled by boolean(true)
|
||||
val hOffset by double(max=0.4, default=0.2).lang("hOffset")
|
||||
val vOffset by double(max=0.4, default=0.1).lang("vOffset")
|
||||
val size by double(min=0.75, max=2.5, default=1.4).lang("size")
|
||||
val dense by boolean(false)
|
||||
val hideInternal by boolean(true)
|
||||
}
|
||||
|
||||
object shortGrass : ConfigCategory(){
|
||||
val grassEnabled by boolean(true)
|
||||
val myceliumEnabled by boolean(true)
|
||||
val snowEnabled by boolean(true)
|
||||
val hOffset by double(max=0.4, default=0.2).lang("hOffset")
|
||||
val heightMin by double(min=0.1, max=2.5, default=0.6).lang("heightMin")
|
||||
val heightMax by double(min=0.1, max=2.5, default=0.8).lang("heightMax")
|
||||
val size by double(min=0.5, max=1.5, default=1.0).lang("size")
|
||||
val population by int(max=64, default=64).lang("population")
|
||||
val useGenerated by boolean(false)
|
||||
val shaderWind by boolean(true).lang("shaderWind")
|
||||
val saturationThreshold by double(default=0.1)
|
||||
}
|
||||
|
||||
object connectedGrass : ConfigCategory(){
|
||||
val enabled by boolean(true)
|
||||
val snowEnabled by boolean(false)
|
||||
}
|
||||
|
||||
object roundLogs : ConfigCategory(){
|
||||
val enabled by featureEnable()
|
||||
val radiusSmall by double(max=0.5, default=0.25)
|
||||
val radiusLarge by double(max=0.5, default=0.44)
|
||||
val dimming by double(default = 0.7)
|
||||
val connectSolids by boolean(false)
|
||||
val lenientConnect by boolean(true)
|
||||
val connectPerpendicular by boolean(true)
|
||||
val connectGrass by boolean(true)
|
||||
val defaultY by boolean(false)
|
||||
val zProtection by double(min = 0.9, default = 0.99)
|
||||
}
|
||||
|
||||
object cactus : ConfigCategory(){
|
||||
val enabled by featureEnable()
|
||||
val size by double(min=0.5, max=1.5, default=0.8).lang("size")
|
||||
val sizeVariation by double(max=0.5, default=0.1)
|
||||
val hOffset by double(max=0.5, default=0.1).lang("hOffset")
|
||||
}
|
||||
|
||||
object lilypad : ConfigCategory(){
|
||||
val enabled by featureEnable()
|
||||
val hOffset by double(max=0.25, default=0.1).lang("hOffset")
|
||||
val flowerChance by int(max=64, default=16, min=0)
|
||||
}
|
||||
|
||||
object reed : ConfigCategory(){
|
||||
val enabled by featureEnable()
|
||||
val hOffset by double(max=0.4, default=0.2).lang("hOffset")
|
||||
val heightMin by double(min=1.5, max=3.5, default=1.7).lang("heightMin")
|
||||
val heightMax by double(min=1.5, max=3.5, default=2.2).lang("heightMax")
|
||||
val population by int(max=64, default=32).lang("population")
|
||||
val minBiomeTemp by double(default=0.4)
|
||||
val minBiomeRainfall by double(default=0.4)
|
||||
// val biomes by biomeList { it.filterTemp(0.4f, null) && it.filterRain(0.4f, null) }
|
||||
val shaderWind by boolean(true).lang("shaderWind")
|
||||
}
|
||||
|
||||
object algae : ConfigCategory(){
|
||||
val enabled by featureEnable()
|
||||
val hOffset by double(max=0.25, default=0.1).lang("hOffset")
|
||||
val size by double(min=0.5, max=1.5, default=1.0).lang("size")
|
||||
val heightMin by double(min=0.1, max=1.5, default=0.5).lang("heightMin")
|
||||
val heightMax by double(min=0.1, max=1.5, default=1.0).lang("heightMax")
|
||||
val population by int(max=64, default=48).lang("population")
|
||||
// val biomes by biomeList { it.filterClass("river", "ocean") }
|
||||
val shaderWind by boolean(true).lang("shaderWind")
|
||||
}
|
||||
|
||||
object coral : ConfigCategory(){
|
||||
val enabled by featureEnable()
|
||||
val shallowWater by boolean(false)
|
||||
val hOffset by double(max=0.4, default=0.2).lang("hOffset")
|
||||
val vOffset by double(max=0.4, default=0.1).lang("vOffset")
|
||||
val size by double(min=0.5, max=1.5, default=0.7).lang("size")
|
||||
val crustSize by double(min=0.5, max=1.5, default=1.4)
|
||||
val chance by int(max=64, default=32)
|
||||
val population by int(max=64, default=48).lang("population")
|
||||
// val biomes by biomeList { it.filterClass("river", "ocean", "beach") }
|
||||
}
|
||||
|
||||
object netherrack : ConfigCategory(){
|
||||
val enabled by featureEnable()
|
||||
val hOffset by double(max=0.4, default=0.2).lang("hOffset")
|
||||
val heightMin by double(min=0.1, max=1.5, default=0.6).lang("heightMin")
|
||||
val heightMax by double(min=0.1, max=1.5, default=0.8).lang("heightMax")
|
||||
val size by double(min=0.5, max=1.5, default=1.0).lang("size")
|
||||
}
|
||||
|
||||
object fallingLeaves : ConfigCategory(){
|
||||
val enabled by featureEnable()
|
||||
val speed by double(min=0.01, max=0.15, default=0.05)
|
||||
val windStrength by double(min=0.1, max=2.0, default=0.5)
|
||||
val stormStrength by double(min=0.1, max=2.0, default=0.8)
|
||||
val size by double(min=0.25, max=1.5, default=0.75).lang("size")
|
||||
val chance by double(min=0.001, max=1.0, default=0.02)
|
||||
val perturb by double(min=0.01, max=1.0, default=0.25)
|
||||
val lifetime by double(min=1.0, max=15.0, default=5.0)
|
||||
val opacityHack by boolean(true)
|
||||
}
|
||||
|
||||
object risingSoul : ConfigCategory(){
|
||||
val enabled by featureEnable()
|
||||
val chance by double(min=0.001, max=1.0, default=0.02)
|
||||
val perturb by double(min=0.01, max=0.25, default=0.05)
|
||||
val headSize by double(min=0.25, max=1.5, default=1.0)
|
||||
val trailSize by double(min=0.25, max=1.5, default=0.75)
|
||||
val opacity by double(min=0.05, max=1.0, default=0.5)
|
||||
val sizeDecay by double(min=0.5, max=1.0, default=0.97)
|
||||
val opacityDecay by double(min=0.5, max=1.0, default=0.97)
|
||||
val lifetime by double(min=1.0, max=15.0, default=4.0)
|
||||
val trailLength by int(min=2, max=128, default=48)
|
||||
val trailDensity by int(min=1, max=16, default=3)
|
||||
}
|
||||
}
|
||||
|
||||
object BlockConfig {
|
||||
private val list = mutableListOf<Any>()
|
||||
|
||||
|
||||
152
src/main/kotlin/mods/betterfoliage/client/config/MainConfig.kt
Normal file
152
src/main/kotlin/mods/betterfoliage/client/config/MainConfig.kt
Normal file
@@ -0,0 +1,152 @@
|
||||
package mods.betterfoliage.client.config
|
||||
|
||||
import mods.betterfoliage.BetterFoliageMod
|
||||
import mods.octarinecore.common.config.DelegatingConfigGroup
|
||||
import mods.octarinecore.common.config.boolean
|
||||
import mods.octarinecore.common.config.double
|
||||
import mods.octarinecore.common.config.integer
|
||||
import mods.octarinecore.common.config.recurring
|
||||
import mods.octarinecore.common.config.subNode
|
||||
|
||||
fun featureEnable(default: Boolean = true) = boolean(default, langKey = recurring)
|
||||
|
||||
val Config get() = BetterFoliageMod.config
|
||||
|
||||
class MainConfig : DelegatingConfigGroup() {
|
||||
val enabled by boolean(true, langKey = { "betterfoliage.global.enabled" })
|
||||
val nVidia by boolean(false)
|
||||
|
||||
val leaves by subNode(::LeavesConfig)
|
||||
val shortGrass by subNode(::ShortGrassConfig)
|
||||
val connectedGrass by subNode(::ConnectedGrassConfig)
|
||||
val roundLogs by subNode(::RoundLogConfig)
|
||||
val cactus by subNode(::CactusConfig)
|
||||
val lilypad by subNode(::LilypadConfig)
|
||||
val reed by subNode(::ReedConfig)
|
||||
val algae by subNode(::AlgaeConfig)
|
||||
val coral by subNode(::CoralConfig)
|
||||
val netherrack by subNode(::NetherrackConfig)
|
||||
val fallingLeaves by subNode(::FallingLeavesConfig)
|
||||
val risingSoul by subNode(::RisingSoulConfig)
|
||||
}
|
||||
|
||||
class LeavesConfig : DelegatingConfigGroup() {
|
||||
val enabled by featureEnable()
|
||||
val snowEnabled by boolean(true)
|
||||
val hOffset by double(max=0.4, default=0.2, langKey = recurring)
|
||||
val vOffset by double(max=0.4, default=0.1, langKey = recurring)
|
||||
val size by double(min=0.75, max=2.5, default=1.4, langKey = recurring)
|
||||
val dense by boolean(false)
|
||||
val hideInternal by boolean(true)
|
||||
}
|
||||
|
||||
class ShortGrassConfig : DelegatingConfigGroup() {
|
||||
val grassEnabled by boolean(true)
|
||||
val myceliumEnabled by boolean(true)
|
||||
val snowEnabled by boolean(true)
|
||||
val hOffset by double(max=0.4, default=0.2, langKey = recurring)
|
||||
val heightMin by double(min=0.1, max=2.5, default=0.6, langKey = recurring)
|
||||
val heightMax by double(min=0.1, max=2.5, default=0.8, langKey = recurring)
|
||||
val size by double(min=0.5, max=1.5, default=1.0, langKey = recurring)
|
||||
val population by integer(max=64, default=64)
|
||||
val useGenerated by boolean(false)
|
||||
val shaderWind by boolean(true, langKey = recurring)
|
||||
val saturationThreshold by double(default=0.1)
|
||||
}
|
||||
|
||||
class ConnectedGrassConfig() : DelegatingConfigGroup() {
|
||||
val enabled by boolean(true)
|
||||
val snowEnabled by boolean(false)
|
||||
}
|
||||
|
||||
class RoundLogConfig() : DelegatingConfigGroup() {
|
||||
val enabled by featureEnable()
|
||||
val radiusSmall by double(max=0.5, default=0.25)
|
||||
val radiusLarge by double(max=0.5, default=0.44)
|
||||
val dimming by double(default = 0.7)
|
||||
val connectSolids by boolean(false)
|
||||
val lenientConnect by boolean(true)
|
||||
val connectPerpendicular by boolean(true)
|
||||
val connectGrass by boolean(true)
|
||||
val defaultY by boolean(false)
|
||||
val zProtection by double(min = 0.9, default = 0.99)
|
||||
}
|
||||
|
||||
class CactusConfig() : DelegatingConfigGroup() {
|
||||
val enabled by featureEnable()
|
||||
val size by double(min=0.5, max=1.5, default=0.8, langKey = recurring)
|
||||
val sizeVariation by double(max=0.5, default=0.1)
|
||||
val hOffset by double(max=0.5, default=0.1, langKey = recurring)
|
||||
}
|
||||
|
||||
class LilypadConfig() : DelegatingConfigGroup() {
|
||||
val enabled by featureEnable()
|
||||
val hOffset by double(max=0.25, default=0.1, langKey = recurring)
|
||||
val flowerChance by integer(max=64, default=16, min=0)
|
||||
}
|
||||
|
||||
class ReedConfig() : DelegatingConfigGroup() {
|
||||
val enabled by featureEnable()
|
||||
val hOffset by double(max=0.4, default=0.2, langKey = recurring)
|
||||
val heightMin by double(min=1.5, max=3.5, default=1.7, langKey = recurring)
|
||||
val heightMax by double(min=1.5, max=3.5, default=2.2, langKey = recurring)
|
||||
val population by integer(max=64, default=32, langKey = recurring)
|
||||
val minBiomeTemp by double(default=0.4)
|
||||
val minBiomeRainfall by double(default=0.4)
|
||||
val shaderWind by boolean(true, langKey = recurring)
|
||||
}
|
||||
|
||||
class AlgaeConfig() : DelegatingConfigGroup() {
|
||||
val enabled by featureEnable()
|
||||
val hOffset by double(max=0.25, default=0.1, langKey = recurring)
|
||||
val size by double(min=0.5, max=1.5, default=1.0, langKey = recurring)
|
||||
val heightMin by double(min=0.1, max=1.5, default=0.5, langKey = recurring)
|
||||
val heightMax by double(min=0.1, max=1.5, default=1.0, langKey = recurring)
|
||||
val population by integer(max=64, default=48, langKey = recurring)
|
||||
val shaderWind by boolean(true, langKey = recurring)
|
||||
}
|
||||
|
||||
class CoralConfig() : DelegatingConfigGroup() {
|
||||
val enabled by featureEnable()
|
||||
val shallowWater by boolean(false)
|
||||
val hOffset by double(max=0.4, default=0.2, langKey = recurring)
|
||||
val vOffset by double(max=0.4, default=0.1, langKey = recurring)
|
||||
val size by double(min=0.5, max=1.5, default=0.7, langKey = recurring)
|
||||
val crustSize by double(min=0.5, max=1.5, default=1.4)
|
||||
val chance by integer(max=64, default=32)
|
||||
val population by integer(max=64, default=48, langKey = recurring)
|
||||
}
|
||||
|
||||
class NetherrackConfig() : DelegatingConfigGroup() {
|
||||
val enabled by featureEnable()
|
||||
val hOffset by double(max=0.4, default=0.2, langKey = recurring)
|
||||
val heightMin by double(min=0.1, max=1.5, default=0.6, langKey = recurring)
|
||||
val heightMax by double(min=0.1, max=1.5, default=0.8, langKey = recurring)
|
||||
val size by double(min=0.5, max=1.5, default=1.0, langKey = recurring)
|
||||
}
|
||||
|
||||
class FallingLeavesConfig() : DelegatingConfigGroup() {
|
||||
val enabled by featureEnable()
|
||||
val speed by double(min=0.01, max=0.15, default=0.05)
|
||||
val windStrength by double(min=0.1, max=2.0, default=0.5)
|
||||
val stormStrength by double(min=0.1, max=2.0, default=0.8)
|
||||
val size by double(min=0.25, max=1.5, default=0.75, langKey = recurring)
|
||||
val chance by double(min=0.001, max=1.0, default=0.02)
|
||||
val perturb by double(min=0.01, max=1.0, default=0.25)
|
||||
val lifetime by double(min=1.0, max=15.0, default=5.0)
|
||||
val opacityHack by boolean(true)
|
||||
}
|
||||
|
||||
class RisingSoulConfig() : DelegatingConfigGroup() {
|
||||
val enabled by featureEnable()
|
||||
val chance by double(min=0.001, max=1.0, default=0.02)
|
||||
val perturb by double(min=0.01, max=0.25, default=0.05)
|
||||
val headSize by double(min=0.25, max=1.5, default=1.0)
|
||||
val trailSize by double(min=0.25, max=1.5, default=0.75)
|
||||
val opacity by double(min=0.05, max=1.0, default=0.5)
|
||||
val sizeDecay by double(min=0.5, max=1.0, default=0.97)
|
||||
val opacityDecay by double(min=0.5, max=1.0, default=0.97)
|
||||
val lifetime by double(min=1.0, max=15.0, default=4.0)
|
||||
val trailLength by integer(min=2, max=128, default=48)
|
||||
val trailDensity by integer(min=1, max=16, default=3)
|
||||
}
|
||||
172
src/main/kotlin/mods/octarinecore/common/config/Delegate.kt
Normal file
172
src/main/kotlin/mods/octarinecore/common/config/Delegate.kt
Normal file
@@ -0,0 +1,172 @@
|
||||
package mods.octarinecore.common.config
|
||||
|
||||
import me.shedaniel.forge.clothconfig2.api.AbstractConfigListEntry
|
||||
import me.shedaniel.forge.clothconfig2.api.ConfigBuilder
|
||||
import me.shedaniel.forge.clothconfig2.api.ConfigEntryBuilder
|
||||
import me.shedaniel.forge.clothconfig2.gui.entries.SubCategoryListEntry
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.client.resources.I18n
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import net.minecraftforge.common.ForgeConfigSpec
|
||||
import java.util.*
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
const val MAX_LINE_LEN = 30
|
||||
|
||||
fun DelegatingConfigGroup.forgeSpecRoot() =
|
||||
ForgeConfigSpec.Builder()
|
||||
.also { createForgeNode(it) }
|
||||
.build()
|
||||
|
||||
fun DelegatingConfigGroup.clothGuiRoot(
|
||||
parentScreen: Screen,
|
||||
prefix: List<String>,
|
||||
background: ResourceLocation,
|
||||
saveAction: ()->Unit
|
||||
) = ConfigBuilder.create()
|
||||
.setParentScreen(parentScreen)
|
||||
.setTitle(I18n.format((prefix + "title").joinToString(".")))
|
||||
.setDefaultBackgroundTexture(background)
|
||||
.setSavingRunnable(saveAction)
|
||||
.also { builder ->
|
||||
createClothNode(prefix).value.forEach { rootCategory ->
|
||||
builder.getOrCreateCategory("main").addEntry(rootCategory)
|
||||
}
|
||||
}
|
||||
.build()
|
||||
|
||||
sealed class DelegatingConfigNode {
|
||||
abstract fun createClothNode(path: List<String>): AbstractConfigListEntry<*>
|
||||
}
|
||||
|
||||
abstract class DelegatingConfigValue<T> : DelegatingConfigNode(), ReadOnlyProperty<DelegatingConfigGroup, T> {
|
||||
lateinit var forgeValue: ForgeConfigSpec.ConfigValue<T>
|
||||
abstract fun createForgeNode(builder: ForgeConfigSpec.Builder, name: String)
|
||||
}
|
||||
|
||||
open class DelegatingConfigGroup : DelegatingConfigNode() {
|
||||
val children = mutableMapOf<String, DelegatingConfigNode>()
|
||||
|
||||
fun createForgeNode(builder: ForgeConfigSpec.Builder) {
|
||||
children.forEach { (name, node) ->
|
||||
when(node) {
|
||||
is DelegatingConfigGroup -> {
|
||||
builder.push(name)
|
||||
node.createForgeNode(builder)
|
||||
builder.pop()
|
||||
}
|
||||
is DelegatingConfigValue<*> -> node.createForgeNode(builder, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun createClothNode(path: List<String>): SubCategoryListEntry {
|
||||
val builder = ConfigEntryBuilder.create()
|
||||
.startSubCategory(path.joinToString(".").translate())
|
||||
.setTooltip(*path.joinToString(".").translateTooltip())
|
||||
.setExpended(false)
|
||||
children.forEach { (name, node) -> builder.add(node.createClothNode(path + name)) }
|
||||
return builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
interface DelegatingConfigGroupFactory<T> {
|
||||
operator fun provideDelegate(parent: DelegatingConfigGroup, property: KProperty<*>): ReadOnlyProperty<DelegatingConfigGroup, T>
|
||||
}
|
||||
|
||||
fun <T: DelegatingConfigGroup> subNode(factory: ()->T) = object : DelegatingConfigGroupFactory<T> {
|
||||
override operator fun provideDelegate(parent: DelegatingConfigGroup, property: KProperty<*>): ReadOnlyProperty<DelegatingConfigGroup, T> {
|
||||
val child = factory()
|
||||
parent.children[property.name] = child
|
||||
return object : ReadOnlyProperty<DelegatingConfigGroup, T> {
|
||||
override fun getValue(thisRef: DelegatingConfigGroup, property: KProperty<*>) = child
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface DelegatingConfigValueFactory<T> {
|
||||
fun createForgeNode(builder: ForgeConfigSpec.Builder, name: String): ForgeConfigSpec.ConfigValue<T>
|
||||
fun createClothNode(prop: CachingConfigProperty<T>, path: List<String>): AbstractConfigListEntry<T>
|
||||
|
||||
operator fun provideDelegate(parent: DelegatingConfigGroup, property: KProperty<*>): ReadOnlyProperty<DelegatingConfigGroup, T> {
|
||||
return object : CachingConfigProperty<T>(parent, property) {
|
||||
override fun createForgeNode(builder: ForgeConfigSpec.Builder, name: String) {
|
||||
forgeValue = this@DelegatingConfigValueFactory.createForgeNode(builder, name)
|
||||
}
|
||||
|
||||
override fun createClothNode(path: List<String>): AbstractConfigListEntry<*> = createClothNode(this, path)
|
||||
|
||||
}.apply { parent.children[property.name] = this }
|
||||
}
|
||||
}
|
||||
|
||||
abstract class CachingConfigProperty<T>(parent: DelegatingConfigGroup, property: KProperty<*>) : DelegatingConfigValue<T>() {
|
||||
var value: T? = null
|
||||
override fun getValue(thisRef: DelegatingConfigGroup, property: KProperty<*>) =
|
||||
value ?: forgeValue.get().apply { value = this }
|
||||
}
|
||||
|
||||
fun String.translate() = I18n.format(this)
|
||||
fun String.translateTooltip(lineLength: Int = MAX_LINE_LEN) = ("$this.tooltip").translate().let { tooltip ->
|
||||
tooltip.splitToSequence(" ").fold(mutableListOf("")) { tooltips, word ->
|
||||
if (tooltips.last().length + word.length < lineLength) {
|
||||
tooltips[tooltips.lastIndex] += "$word "
|
||||
} else {
|
||||
tooltips.add("$word ")
|
||||
}
|
||||
tooltips
|
||||
}.map { it.trim() }.toTypedArray()
|
||||
}
|
||||
|
||||
fun boolean(
|
||||
default: Boolean,
|
||||
langKey: (List<String>)->String = { it.joinToString(".") },
|
||||
valueOverride: (Boolean)->Boolean = { it }
|
||||
) = object : DelegatingConfigValueFactory<Boolean> {
|
||||
override fun createForgeNode(builder: ForgeConfigSpec.Builder, name: String) =
|
||||
builder.define(name, default)
|
||||
|
||||
override fun createClothNode(prop: CachingConfigProperty<Boolean>, path: List<String>) = ConfigEntryBuilder.create()
|
||||
.startBooleanToggle(langKey(path).translate(), prop.forgeValue.get())
|
||||
.setTooltip(langKey(path).let { if (I18n.hasKey("$it.tooltip")) Optional.of(it.translateTooltip()) else Optional.empty() })
|
||||
.setSaveConsumer { prop.forgeValue.set(valueOverride(it)); prop.value = null }
|
||||
.build()
|
||||
}
|
||||
|
||||
fun integer(
|
||||
default: Int = 0, min: Int = 0, max: Int,
|
||||
langKey: (List<String>)->String = { it.joinToString(".") },
|
||||
valueOverride: (Int)->Int = { it }
|
||||
) = object : DelegatingConfigValueFactory<Int> {
|
||||
override fun createForgeNode(builder: ForgeConfigSpec.Builder, name: String) =
|
||||
builder.defineInRange(name, default, min, max)
|
||||
|
||||
override fun createClothNode(prop: CachingConfigProperty<Int>, path: List<String>) = ConfigEntryBuilder.create()
|
||||
.startIntField(langKey(path).translate(), prop.forgeValue.get())
|
||||
.setTooltip(langKey(path).let { if (I18n.hasKey("$it.tooltip")) Optional.of(it.translateTooltip()) else Optional.empty() })
|
||||
.setMin(min).setMax(max)
|
||||
.setSaveConsumer { prop.forgeValue.set(valueOverride(it)); prop.value = null }
|
||||
.build()
|
||||
}
|
||||
|
||||
fun double(
|
||||
default: Double = 0.0, min: Double = 0.0, max: Double = 1.0,
|
||||
langKey: (List<String>)->String = { it.joinToString(".") },
|
||||
valueOverride: (Double)->Double = { it }
|
||||
) = object : DelegatingConfigValueFactory<Double> {
|
||||
override fun createForgeNode(builder: ForgeConfigSpec.Builder, name: String) =
|
||||
builder.defineInRange(name, default, min, max)
|
||||
|
||||
override fun createClothNode(prop: CachingConfigProperty<Double>, path: List<String>) = ConfigEntryBuilder.create()
|
||||
.startDoubleField(langKey(path).translate(), prop.forgeValue.get())
|
||||
.setTooltip(langKey(path).let { if (I18n.hasKey("$it.tooltip")) Optional.of(it.translateTooltip()) else Optional.empty() })
|
||||
.setMin(min).setMax(max)
|
||||
.setSaveConsumer { prop.forgeValue.set(valueOverride(it)); prop.value = null }
|
||||
.build()
|
||||
}
|
||||
|
||||
val recurring = { path: List<String> -> "${path.first()}.${path.last()}" }
|
||||
fun fakeCategory(name: String) = { names: List<String> ->
|
||||
(listOf(names.first(), name) + names.drop(1)).joinToString(".")
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
@file:JvmName("DelegatingConfigKt")
|
||||
|
||||
package mods.octarinecore.common.config
|
||||
|
||||
import mods.octarinecore.metaprog.reflectDelegates
|
||||
import mods.octarinecore.metaprog.reflectNestedObjects
|
||||
import net.minecraftforge.common.ForgeConfigSpec
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
open class DelegatingConfig(val modId: String, val langPrefix: String) {
|
||||
fun build() = ForgeConfigSpec.Builder().apply { ConfigBuildContext(langPrefix, emptyList(), this).addCategory(this@DelegatingConfig) }.build()
|
||||
}
|
||||
|
||||
class ConfigBuildContext(val langPrefix: String, val path: List<String>, val builder: ForgeConfigSpec.Builder) {
|
||||
|
||||
fun addCategory(configObj: Any) {
|
||||
configObj.reflectNestedObjects.forEach { (name, category) ->
|
||||
builder.push(name)
|
||||
descend(name).addCategory(category)
|
||||
builder.pop()
|
||||
}
|
||||
configObj.reflectDelegates(ConfigDelegate::class.java).forEach { (name, delegate) ->
|
||||
descend(name).apply { delegate.addToBuilder(this) }
|
||||
}
|
||||
}
|
||||
|
||||
fun descend(pathName: String) = ConfigBuildContext(langPrefix, path + pathName, builder)
|
||||
}
|
||||
|
||||
open class ConfigCategory(val comment: String? = null) {
|
||||
}
|
||||
|
||||
abstract class ConfigDelegate<T> : ReadOnlyProperty<Any, T> {
|
||||
lateinit var configValue: ForgeConfigSpec.ConfigValue<T>
|
||||
var cachedValue: T? = null
|
||||
|
||||
override fun getValue(thisRef: Any, property: KProperty<*>): T {
|
||||
if (cachedValue == null) cachedValue = configValue.get()
|
||||
return cachedValue!!
|
||||
}
|
||||
|
||||
abstract fun getConfigValue(name: String, builder: ForgeConfigSpec.Builder): ForgeConfigSpec.ConfigValue<T>
|
||||
fun addToBuilder(ctx: ConfigBuildContext) {
|
||||
val langKey = ctx.langPrefix + "." + (langPrefixOverride ?: ctx.path.joinToString("."))
|
||||
ctx.builder.translation(langKey)
|
||||
configValue = getConfigValue(ctx.path.last(), ctx.builder)
|
||||
}
|
||||
|
||||
var langPrefixOverride: String? = null
|
||||
fun lang(prefix: String) = apply { langPrefixOverride = prefix }
|
||||
|
||||
}
|
||||
|
||||
class DelegatingBooleanValue(val defaultValue: Boolean) : ConfigDelegate<Boolean>() {
|
||||
override fun getConfigValue(name: String, builder: ForgeConfigSpec.Builder) = builder.define(name, defaultValue)
|
||||
}
|
||||
|
||||
class DelegatingIntValue(
|
||||
val minValue: Int = 0,
|
||||
val maxValue: Int = 1,
|
||||
val defaultValue: Int = 0
|
||||
) : ConfigDelegate<Int>() {
|
||||
override fun getConfigValue(name: String, builder: ForgeConfigSpec.Builder) = builder.defineInRange(name, defaultValue, minValue, maxValue)
|
||||
}
|
||||
|
||||
class DelegatingLongValue(
|
||||
val minValue: Long = 0,
|
||||
val maxValue: Long = 1,
|
||||
val defaultValue: Long = 0
|
||||
) : ConfigDelegate<Long>() {
|
||||
override fun getConfigValue(name: String, builder: ForgeConfigSpec.Builder) = builder.defineInRange(name, defaultValue, minValue, maxValue)
|
||||
}
|
||||
|
||||
class DelegatingDoubleValue(
|
||||
val minValue: Double = 0.0,
|
||||
val maxValue: Double = 1.0,
|
||||
val defaultValue: Double = 0.0
|
||||
) : ConfigDelegate<Double>() {
|
||||
override fun getConfigValue(name: String, builder: ForgeConfigSpec.Builder) = builder.defineInRange(name, defaultValue, minValue, maxValue)
|
||||
}
|
||||
|
||||
// ============================
|
||||
// Delegate factory methods
|
||||
// ============================
|
||||
fun double(min: Double = 0.0, max: Double = 1.0, default: Double) = DelegatingDoubleValue(min, max, default)
|
||||
fun int(min: Int = 0, max: Int, default: Int) = DelegatingIntValue(min, max, default)
|
||||
fun long(min: Long = 0, max: Long, default: Long) = DelegatingLongValue(min, max, default)
|
||||
fun boolean(default: Boolean) = DelegatingBooleanValue(default)
|
||||
Reference in New Issue
Block a user