diff --git a/src/main/kotlin/mods/betterfoliage/client/Client.kt b/src/main/kotlin/mods/betterfoliage/client/Client.kt index 4c454ea..add03c2 100644 --- a/src/main/kotlin/mods/betterfoliage/client/Client.kt +++ b/src/main/kotlin/mods/betterfoliage/client/Client.kt @@ -61,8 +61,9 @@ object Client { ) val singletons = listOf( - StandardLeafSupport, - StandardGrassSupport, + LeafRegistry, + GrassRegistry, + LogRegistry, LeafWindTracker, RisingSoulTextures, ShadersModIntegration, diff --git a/src/main/kotlin/mods/betterfoliage/client/Hooks.kt b/src/main/kotlin/mods/betterfoliage/client/Hooks.kt index 727f50b..0ad951e 100644 --- a/src/main/kotlin/mods/betterfoliage/client/Hooks.kt +++ b/src/main/kotlin/mods/betterfoliage/client/Hooks.kt @@ -31,22 +31,22 @@ import net.minecraftforge.fml.relauncher.Side import net.minecraftforge.fml.relauncher.SideOnly fun doesSideBlockRenderingOverride(original: Boolean, blockAccess: IBlockAccess, pos: BlockPos, side: EnumFacing): Boolean { - return original && !(Config.enabled && Config.roundLogs.enabled && Config.blocks.logs.matchesClass(blockAccess.getBlockState(pos).block)); + return original && !(Config.enabled && Config.roundLogs.enabled && Config.blocks.logClasses.matchesClass(blockAccess.getBlockState(pos).block)); } fun isOpaqueCubeOverride(original: Boolean, state: IBlockState): Boolean { // caution: blocks are initialized and the method called during startup if (!BetterFoliageMod.isAfterPostInit) return original - return original && !(Config.enabled && Config.roundLogs.enabled && Config.blocks.logs.matchesClass(state.block)) + return original && !(Config.enabled && Config.roundLogs.enabled && Config.blocks.logClasses.matchesClass(state.block)) } fun getAmbientOcclusionLightValueOverride(original: Float, state: IBlockState): Float { - if (Config.enabled && Config.roundLogs.enabled && Config.blocks.logs.matchesClass(state.block)) return Config.roundLogs.dimming; + if (Config.enabled && Config.roundLogs.enabled && Config.blocks.logClasses.matchesClass(state.block)) return Config.roundLogs.dimming; return original; } fun getUseNeighborBrightnessOverride(original: Boolean, state: IBlockState): Boolean { - return original || (Config.enabled && Config.roundLogs.enabled && Config.blocks.logs.matchesClass(state.block)); + return original || (Config.enabled && Config.roundLogs.enabled && Config.blocks.logClasses.matchesClass(state.block)); } fun onRandomDisplayTick(world: World, state: IBlockState, pos: BlockPos) { diff --git a/src/main/kotlin/mods/betterfoliage/client/config/Config.kt b/src/main/kotlin/mods/betterfoliage/client/config/Config.kt index df8fd5a..187faf2 100644 --- a/src/main/kotlin/mods/betterfoliage/client/config/Config.kt +++ b/src/main/kotlin/mods/betterfoliage/client/config/Config.kt @@ -31,16 +31,17 @@ object Config : DelegatingConfig(BetterFoliageMod.MOD_ID, BetterFoliageMod.DOMAI var enabled by boolean(true) object blocks { - val leavesClasses = BlockMatcher(BetterFoliageMod.DOMAIN, "LeavesBlocksDefault.cfg") + val leavesClasses = ConfigurableBlockMatcher(BetterFoliageMod.DOMAIN, "LeavesBlocksDefault.cfg") val leavesModels = ModelTextureListConfigOption(BetterFoliageMod.DOMAIN, "LeavesModelsDefault.cfg", 1) - val grassClasses = BlockMatcher(BetterFoliageMod.DOMAIN, "GrassBlocksDefault.cfg") + val grassClasses = ConfigurableBlockMatcher(BetterFoliageMod.DOMAIN, "GrassBlocksDefault.cfg") val grassModels = ModelTextureListConfigOption(BetterFoliageMod.DOMAIN, "GrassModelsDefault.cfg", 1) - val dirt = BlockMatcher(BetterFoliageMod.DOMAIN, "DirtDefault.cfg") - val crops = BlockMatcher(BetterFoliageMod.DOMAIN, "CropDefault.cfg") - val logs = BlockMatcher(BetterFoliageMod.DOMAIN, "LogDefault.cfg") - val sand = BlockMatcher(BetterFoliageMod.DOMAIN, "SandDefault.cfg") - val lilypad = BlockMatcher(BetterFoliageMod.DOMAIN, "LilypadDefault.cfg") - val cactus = BlockMatcher(BetterFoliageMod.DOMAIN, "CactusDefault.cfg") + val dirt = ConfigurableBlockMatcher(BetterFoliageMod.DOMAIN, "DirtDefault.cfg") + val crops = ConfigurableBlockMatcher(BetterFoliageMod.DOMAIN, "CropDefault.cfg") + val logClasses = ConfigurableBlockMatcher(BetterFoliageMod.DOMAIN, "LogBlocksDefault.cfg") + val logModels = ModelTextureListConfigOption(BetterFoliageMod.DOMAIN, "LogModelsDefault.cfg", 3) + val sand = ConfigurableBlockMatcher(BetterFoliageMod.DOMAIN, "SandDefault.cfg") + val lilypad = ConfigurableBlockMatcher(BetterFoliageMod.DOMAIN, "LilypadDefault.cfg") + val cactus = ConfigurableBlockMatcher(BetterFoliageMod.DOMAIN, "CactusDefault.cfg") } object leaves { diff --git a/src/main/kotlin/mods/betterfoliage/client/integration/ForestryIntegration.kt b/src/main/kotlin/mods/betterfoliage/client/integration/ForestryIntegration.kt index d63d153..74d329f 100644 --- a/src/main/kotlin/mods/betterfoliage/client/integration/ForestryIntegration.kt +++ b/src/main/kotlin/mods/betterfoliage/client/integration/ForestryIntegration.kt @@ -1,11 +1,18 @@ package mods.betterfoliage.client.integration +import mods.betterfoliage.BetterFoliageMod import mods.betterfoliage.client.Client +import mods.betterfoliage.client.config.Config +import mods.betterfoliage.client.render.IColumnRegistry +import mods.betterfoliage.client.render.IColumnTextureResolver +import mods.betterfoliage.client.render.LogRegistry +import mods.betterfoliage.client.render.StaticColumnInfo import mods.betterfoliage.client.texture.ILeafRegistry import mods.betterfoliage.client.texture.LeafInfo import mods.betterfoliage.client.texture.LeafRegistry import mods.betterfoliage.client.texture.StandardLeafSupport import mods.betterfoliage.loader.Refs +import mods.octarinecore.client.resource.ModelProcessor import mods.octarinecore.client.resource.get import mods.octarinecore.metaprog.ClassRef import mods.octarinecore.metaprog.FieldRef @@ -13,6 +20,7 @@ import mods.octarinecore.metaprog.MethodRef import mods.octarinecore.metaprog.allAvailable import net.minecraft.block.state.IBlockState import net.minecraft.client.Minecraft +import net.minecraft.client.renderer.block.model.ModelResourceLocation import net.minecraft.client.renderer.texture.TextureAtlasSprite import net.minecraft.client.renderer.texture.TextureMap import net.minecraft.util.EnumFacing @@ -20,6 +28,7 @@ import net.minecraft.util.ResourceLocation import net.minecraft.util.math.BlockPos import net.minecraft.world.IBlockAccess import net.minecraftforge.client.event.TextureStitchEvent +import net.minecraftforge.client.model.IModel import net.minecraftforge.common.MinecraftForge import net.minecraftforge.fml.common.Loader import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -39,10 +48,16 @@ object ForestryIntegration { val TileLeaves = ClassRef("forestry.arboriculture.tiles.TileLeaves") val TiLgetLeaveSprite = MethodRef(TileLeaves, "getLeaveSprite", Refs.ResourceLocation, ClassRef.boolean) + val PropertyWoodType = ClassRef("forestry.arboriculture.blocks.property.PropertyWoodType") + val IWoodType = ClassRef("forestry.api.arboriculture.IWoodType") + val barkTex = MethodRef(IWoodType, "getBarkTexture", Refs.String) + val heartTex = MethodRef(IWoodType, "getHeartTexture", Refs.String) + init { - if (Loader.isModLoaded("forestry") && allAvailable(TextureLeaves, TileLeaves)) { + if (Loader.isModLoaded("forestry") && allAvailable(TextureLeaves, TileLeaves, PropertyWoodType, IWoodType)) { Client.log(Level.INFO, "Forestry support initialized") LeafRegistry.subRegistries.add(ForestryLeavesSupport) + LogRegistry.subRegistries.add(ForestryLogSupport) } } } @@ -89,4 +104,42 @@ object ForestryLeavesSupport : ILeafRegistry { val textureLoc = ForestryIntegration.TiLgetLeaveSprite.invoke(tile, Minecraft.isFancyGraphicsEnabled()) ?: return null return textureToValue[textureLoc] } +} + +object ForestryLogSupport : ModelProcessor, IColumnTextureResolver>, IColumnRegistry { + + override var stateToKey = mutableMapOf>() + override var stateToValue = mapOf() + + override val logger = BetterFoliageMod.logDetail + + init { MinecraftForge.EVENT_BUS.register(this) } + + override fun processModelLoad(state: IBlockState, modelLoc: ModelResourceLocation, model: IModel): List? { + // respect class list to avoid triggering on fences, stairs, etc. + if (!Config.blocks.logClasses.matchesClass(state.block)) return null + + // find wood type property + val woodType = state.properties.entries.find { + ForestryIntegration.PropertyWoodType.isInstance(it.key) && ForestryIntegration.IWoodType.isInstance(it.value) + } ?: return null + + logger.log(Level.DEBUG, "ForestryLogSupport: block state ${state.toString()}") + logger.log(Level.DEBUG, "ForestryLogSupport: variant ${woodType.value.toString()}") + + // get texture names for wood type + val bark = ForestryIntegration.barkTex.invoke(woodType.value) as String? + val heart = ForestryIntegration.heartTex.invoke(woodType.value) as String? + + logger.log(Level.DEBUG, "ForestryLogSupport: textures [heart=$heart, bark=$bark]") + return if (bark != null && heart != null) listOf(heart, bark) else null + } + + override fun processStitch(state: IBlockState, key: List, atlas: TextureMap): IColumnTextureResolver? { + val heart = atlas[key[0]] ?: return null + val bark = atlas[key[1]] ?: return null + return StaticColumnInfo(heart, heart, bark) + } + + override fun get(state: IBlockState) = stateToValue[state] } \ No newline at end of file diff --git a/src/main/kotlin/mods/betterfoliage/client/render/AbstractRenderColumn.kt b/src/main/kotlin/mods/betterfoliage/client/render/AbstractRenderColumn.kt index 9fb2928..362b051 100644 --- a/src/main/kotlin/mods/betterfoliage/client/render/AbstractRenderColumn.kt +++ b/src/main/kotlin/mods/betterfoliage/client/render/AbstractRenderColumn.kt @@ -5,27 +5,28 @@ import mods.betterfoliage.client.integration.ShadersModIntegration import mods.betterfoliage.client.render.AbstractRenderColumn.BlockType.* import mods.betterfoliage.client.render.AbstractRenderColumn.QuadrantType.* import mods.octarinecore.client.render.* -import mods.octarinecore.client.resource.BlockTextureInspector import mods.octarinecore.common.* -import mods.octarinecore.common.config.BlockMatcher import net.minecraft.block.state.IBlockState import net.minecraft.client.renderer.BlockRendererDispatcher import net.minecraft.client.renderer.VertexBuffer import net.minecraft.client.renderer.texture.TextureAtlasSprite -import net.minecraft.client.renderer.texture.TextureMap import net.minecraft.util.BlockRenderLayer import net.minecraft.util.EnumFacing import net.minecraft.util.EnumFacing.* -interface ColumnTextureResolver { +interface IColumnTextureResolver { val top: (ShadingContext, Int, Quad)->TextureAtlasSprite? val bottom: (ShadingContext, Int, Quad)->TextureAtlasSprite? val side: (ShadingContext, Int, Quad)->TextureAtlasSprite? } +interface IColumnRegistry { + operator fun get(state: IBlockState): IColumnTextureResolver? +} + data class StaticColumnInfo(val topTexture: TextureAtlasSprite, val bottomTexture: TextureAtlasSprite, - val sideTexture: TextureAtlasSprite) : ColumnTextureResolver { + val sideTexture: TextureAtlasSprite) : IColumnTextureResolver { override val top = { ctx: ShadingContext, idx: Int, quad: Quad -> OptifineCTM.override(topTexture, blockContext, UP.rotate(ctx.rotation)) } @@ -37,16 +38,6 @@ data class StaticColumnInfo(val topTexture: TextureAtlasSprite, } } -open class ColumnTextures(val matcher: BlockMatcher) : BlockTextureInspector() { - init { - matchClassAndModel(matcher, "block/column_side", listOf("end", "end", "side")) - matchClassAndModel(matcher, "block/cube_column", listOf("end", "end", "side")) - matchClassAndModel(matcher, "block/cube_all", listOf("all", "all", "all")) - } - override fun processTextures(state: IBlockState, textures: List, atlas: TextureMap) = - StaticColumnInfo(textures[0], textures[1], textures[2]) -} - /** Index of SOUTH-EAST quadrant. */ const val SE = 0 /** Index of NORTH-EAST quadrant. */ @@ -135,13 +126,13 @@ abstract class AbstractRenderColumn(modId: String) : AbstractBlockRenderingHandl abstract val axisFunc: (IBlockState)->EnumFacing.Axis? abstract val blockPredicate: (IBlockState)->Boolean - abstract fun resolver(ctx: BlockContext): ColumnTextureResolver? + abstract val registry: IColumnRegistry @Suppress("NON_EXHAUSTIVE_WHEN") override fun render(ctx: BlockContext, dispatcher: BlockRendererDispatcher, renderer: VertexBuffer, layer: BlockRenderLayer): Boolean { if (ctx.isSurroundedBy(surroundPredicate) ) return false - val columnTextures = resolver(ctx) ?: return false + val columnTextures = registry[ctx.blockState(Int3.zero)] ?: return false // get AO data modelRenderer.updateShading(Int3.zero, allFaces) diff --git a/src/main/kotlin/mods/betterfoliage/client/render/RenderCactus.kt b/src/main/kotlin/mods/betterfoliage/client/render/RenderCactus.kt index f20174b..3fbf34d 100644 --- a/src/main/kotlin/mods/betterfoliage/client/render/RenderCactus.kt +++ b/src/main/kotlin/mods/betterfoliage/client/render/RenderCactus.kt @@ -4,12 +4,22 @@ import mods.betterfoliage.BetterFoliageMod import mods.betterfoliage.client.Client import mods.betterfoliage.client.config.Config import mods.octarinecore.client.render.* +import mods.octarinecore.client.resource.TextureListModelProcessor +import mods.octarinecore.client.resource.get import mods.octarinecore.common.Int3 import mods.octarinecore.common.Rotation +import mods.octarinecore.common.config.ConfigurableBlockMatcher +import mods.octarinecore.common.config.ModelTextureList +import mods.octarinecore.common.config.SimpleBlockMatcher +import mods.octarinecore.common.config.modelTextures +import net.minecraft.block.BlockCactus +import net.minecraft.block.state.IBlockState import net.minecraft.client.renderer.BlockRendererDispatcher import net.minecraft.client.renderer.VertexBuffer +import net.minecraft.client.renderer.texture.TextureMap import net.minecraft.util.BlockRenderLayer import net.minecraft.util.EnumFacing.* +import net.minecraftforge.common.MinecraftForge import org.apache.logging.log4j.Level class RenderCactus : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) { @@ -19,10 +29,29 @@ class RenderCactus : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) { val iconCross = iconStatic(BetterFoliageMod.LEGACY_DOMAIN, "blocks/better_cactus") val iconArm = iconSet(BetterFoliageMod.LEGACY_DOMAIN, "blocks/better_cactus_arm_%d") - val iconBase = object : ColumnTextures(Config.blocks.cactus) { - init { - matchClassAndModel(matcher, "block/cactus", listOf("top", "bottom", "side")) + + val cactusTextures: IColumnRegistry = object : TextureListModelProcessor, IColumnRegistry { + + init { MinecraftForge.EVENT_BUS.register(this) } + + override var stateToKey = mutableMapOf>() + override var stateToValue = mapOf() + + override val logger = BetterFoliageMod.logDetail + override val logName = "CactusTextures" + override val matchClasses = SimpleBlockMatcher(BlockCactus::class.java) + override val modelTextures = listOf( + modelTextures("block/cactus", "top", "bottom", "side") + ) + + override fun processStitch(state: IBlockState, key: List, atlas: TextureMap): IColumnTextureResolver? { + val topTex = atlas[key[0]] + val bottomTex = atlas[key[1]] + val sideTex = atlas[key[2]] + return if (topTex != null && bottomTex != null && sideTex != null) StaticColumnInfo(topTex, bottomTex, sideTex) else null } + + override fun get(state: IBlockState) = stateToValue[state] } val modelStem = model { @@ -65,14 +94,14 @@ class RenderCactus : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) { override fun render(ctx: BlockContext, dispatcher: BlockRendererDispatcher, renderer: VertexBuffer, layer: BlockRenderLayer): Boolean { // get AO data modelRenderer.updateShading(Int3.zero, allFaces) - val icons = iconBase[ctx.blockState(Int3.zero)] ?: return renderWorldBlockBase(ctx, dispatcher, renderer, null) + val icons = cactusTextures[ctx.blockState(Int3.zero)] ?: return renderWorldBlockBase(ctx, dispatcher, renderer, null) modelRenderer.render( renderer, modelStem.model, Rotation.identity, icon = { ctx, qi, q -> when(qi) { - 0 -> icons.bottomTexture; 1 -> icons.topTexture; else -> icons.sideTexture + 0 -> icons.bottom(ctx, qi, q); 1 -> icons.top(ctx, qi, q); else -> icons.side(ctx, qi, q) } }, postProcess = noPost ) diff --git a/src/main/kotlin/mods/betterfoliage/client/render/RenderConnectedGrassLog.kt b/src/main/kotlin/mods/betterfoliage/client/render/RenderConnectedGrassLog.kt index cc7b3e0..6816323 100644 --- a/src/main/kotlin/mods/betterfoliage/client/render/RenderConnectedGrassLog.kt +++ b/src/main/kotlin/mods/betterfoliage/client/render/RenderConnectedGrassLog.kt @@ -19,7 +19,7 @@ class RenderConnectedGrassLog : AbstractBlockRenderingHandler(BetterFoliageMod.M override fun isEligible(ctx: BlockContext) = Config.enabled && Config.roundLogs.enabled && Config.roundLogs.connectGrass && Config.blocks.dirt.matchesClass(ctx.block) && - Config.blocks.logs.matchesClass(ctx.block(up1)) + Config.blocks.logClasses.matchesClass(ctx.block(up1)) override fun render(ctx: BlockContext, dispatcher: BlockRendererDispatcher, renderer: VertexBuffer, layer: BlockRenderLayer): Boolean { val grassDir = grassCheckDirs.find { diff --git a/src/main/kotlin/mods/betterfoliage/client/render/RenderLog.kt b/src/main/kotlin/mods/betterfoliage/client/render/RenderLog.kt index fd4f64b..9de5aac 100644 --- a/src/main/kotlin/mods/betterfoliage/client/render/RenderLog.kt +++ b/src/main/kotlin/mods/betterfoliage/client/render/RenderLog.kt @@ -2,12 +2,24 @@ package mods.betterfoliage.client.render import mods.betterfoliage.BetterFoliageMod import mods.betterfoliage.client.config.Config +import mods.betterfoliage.client.texture.GrassRegistry +import mods.betterfoliage.client.texture.IGrassRegistry +import mods.betterfoliage.client.texture.StandardGrassSupport import mods.octarinecore.client.render.BlockContext +import mods.octarinecore.client.resource.TextureListModelProcessor +import mods.octarinecore.client.resource.get import mods.octarinecore.common.Int3 +import mods.octarinecore.common.config.ConfigurableBlockMatcher +import mods.octarinecore.common.config.ModelTextureList +import mods.octarinecore.findFirst import mods.octarinecore.tryDefault import net.minecraft.block.BlockLog import net.minecraft.block.state.IBlockState +import net.minecraft.client.renderer.texture.TextureAtlasSprite +import net.minecraft.client.renderer.texture.TextureMap import net.minecraft.util.EnumFacing.Axis +import net.minecraftforge.common.MinecraftForge +import org.apache.logging.log4j.Logger class RenderLog : AbstractRenderColumn(BetterFoliageMod.MOD_ID) { @@ -16,7 +28,7 @@ class RenderLog : AbstractRenderColumn(BetterFoliageMod.MOD_ID) { override fun isEligible(ctx: BlockContext) = Config.enabled && Config.roundLogs.enabled && ctx.cameraDistance < Config.roundLogs.distance && - Config.blocks.logs.matchesClass(ctx.block) + Config.blocks.logClasses.matchesClass(ctx.block) override var axisFunc = { state: IBlockState -> val axis = tryDefault(null) { state.getValue(BlockLog.LOG_AXIS).toString() } ?: @@ -29,18 +41,10 @@ class RenderLog : AbstractRenderColumn(BetterFoliageMod.MOD_ID) { } } - val columnTextures = object : ColumnTextures(Config.blocks.logs) { - init { - matchClassAndModel(matcher, "plantmegapack:block/_cube_column", listOf("end", "end", "side")) - matchClassAndModel(matcher, "plantmegapack:block/_column_side", listOf("end", "end", "side")) - matchClassAndModel(matcher, "cookingplus:block/palmlog", listOf("top", "top", "texture")) - } - } + override val registry: IColumnRegistry get() = LogRegistry - override fun resolver(ctx: BlockContext): ColumnTextureResolver? = columnTextures[ctx.blockState(Int3.zero)] - - override val blockPredicate = { state: IBlockState -> Config.blocks.logs.matchesClass(state.block) } - override val surroundPredicate = { state: IBlockState -> state.isOpaqueCube && !Config.blocks.logs.matchesClass(state.block) } + override val blockPredicate = { state: IBlockState -> Config.blocks.logClasses.matchesClass(state.block) } + override val surroundPredicate = { state: IBlockState -> state.isOpaqueCube && !Config.blocks.logClasses.matchesClass(state.block) } override val connectPerpendicular: Boolean get() = Config.roundLogs.connectPerpendicular override val connectSolids: Boolean get() = Config.roundLogs.connectSolids @@ -48,4 +52,31 @@ class RenderLog : AbstractRenderColumn(BetterFoliageMod.MOD_ID) { override val radiusLarge: Double get() = Config.roundLogs.radiusLarge override val radiusSmall: Double get() = Config.roundLogs.radiusSmall +} + +object LogRegistry : IColumnRegistry { + val subRegistries: MutableList = mutableListOf(StandardLogSupport) + override fun get(state: IBlockState) = subRegistries.findFirst { it[state] } +} + +object StandardLogSupport : TextureListModelProcessor, IColumnRegistry { + + init { MinecraftForge.EVENT_BUS.register(this) } + + override var stateToKey = mutableMapOf>() + override var stateToValue = mapOf() + + override val logger = BetterFoliageMod.logDetail + override val logName = "StandardLogSupport" + override val matchClasses: ConfigurableBlockMatcher get() = Config.blocks.logClasses + override val modelTextures: List get() = Config.blocks.logModels.list + + override fun processStitch(state: IBlockState, key: List, atlas: TextureMap): IColumnTextureResolver? { + val topTex = atlas[key[0]] + val bottomTex = atlas[key[1]] + val sideTex = atlas[key[2]] + return if (topTex != null && bottomTex != null && sideTex != null) StaticColumnInfo(topTex, bottomTex, sideTex) else null + } + + override fun get(state: IBlockState) = stateToValue[state] } \ No newline at end of file diff --git a/src/main/kotlin/mods/betterfoliage/client/texture/GrassRegistry.kt b/src/main/kotlin/mods/betterfoliage/client/texture/GrassRegistry.kt index 0211fc6..bdd52f4 100644 --- a/src/main/kotlin/mods/betterfoliage/client/texture/GrassRegistry.kt +++ b/src/main/kotlin/mods/betterfoliage/client/texture/GrassRegistry.kt @@ -10,7 +10,7 @@ import mods.octarinecore.client.resource.TextureMediatedRegistry import mods.octarinecore.client.resource.averageColor import mods.octarinecore.client.resource.get import mods.octarinecore.common.Int3 -import mods.octarinecore.common.config.BlockMatcher +import mods.octarinecore.common.config.ConfigurableBlockMatcher import mods.octarinecore.common.config.ModelTextureList import mods.octarinecore.findFirst import net.minecraft.block.state.IBlockState @@ -47,7 +47,7 @@ interface IGrassRegistry { /** Collects and manages rendering-related information for grass blocks. */ @SideOnly(Side.CLIENT) object GrassRegistry : IGrassRegistry { - val subRegistries = mutableListOf(StandardGrassSupport) + val subRegistries: MutableList = mutableListOf(StandardGrassSupport) override fun get(state: IBlockState, world: IBlockAccess, pos: BlockPos, face: EnumFacing) = subRegistries.findFirst { it.get(state, world, pos, face) } @@ -70,7 +70,7 @@ object StandardGrassSupport : override val logger = BetterFoliageMod.logDetail override val logName = "StandardGrassSupport" - override val matchClasses: BlockMatcher get() = Config.blocks.grassClasses + override val matchClasses: ConfigurableBlockMatcher get() = Config.blocks.grassClasses override val modelTextures: List get() = Config.blocks.grassModels.list override fun get(state: IBlockState, world: IBlockAccess, pos: BlockPos, face: EnumFacing): GrassInfo? { diff --git a/src/main/kotlin/mods/betterfoliage/client/texture/LeafRegistry.kt b/src/main/kotlin/mods/betterfoliage/client/texture/LeafRegistry.kt index 55e10fe..adb394c 100644 --- a/src/main/kotlin/mods/betterfoliage/client/texture/LeafRegistry.kt +++ b/src/main/kotlin/mods/betterfoliage/client/texture/LeafRegistry.kt @@ -7,7 +7,7 @@ import mods.betterfoliage.client.integration.OptifineCTM import mods.octarinecore.client.render.BlockContext import mods.octarinecore.client.resource.* import mods.octarinecore.common.Int3 -import mods.octarinecore.common.config.BlockMatcher +import mods.octarinecore.common.config.ConfigurableBlockMatcher import mods.octarinecore.common.config.ModelTextureList import mods.octarinecore.findFirst import net.minecraft.block.state.IBlockState @@ -96,7 +96,7 @@ object StandardLeafSupport : init { MinecraftForge.EVENT_BUS.register(this) } override val logName = "StandardLeafSupport" - override val matchClasses: BlockMatcher get() = Config.blocks.leavesClasses + override val matchClasses: ConfigurableBlockMatcher get() = Config.blocks.leavesClasses override val modelTextures: List get() = Config.blocks.leavesModels.list override val logger: Logger? get() = BetterFoliageMod.logDetail diff --git a/src/main/kotlin/mods/betterfoliage/loader/Refs.kt b/src/main/kotlin/mods/betterfoliage/loader/Refs.kt index f49227b..8398e0e 100644 --- a/src/main/kotlin/mods/betterfoliage/loader/Refs.kt +++ b/src/main/kotlin/mods/betterfoliage/loader/Refs.kt @@ -10,6 +10,7 @@ object Refs { val mcVersion = FMLInjectionData.data()[4].toString() // Java + val String = ClassRef("java.lang.String") val Map = ClassRef("java.util.Map") val List = ClassRef("java.util.List") val Random = ClassRef("java.util.Random") diff --git a/src/main/kotlin/mods/octarinecore/client/resource/ModelDataInspector.kt b/src/main/kotlin/mods/octarinecore/client/resource/ModelDataInspector.kt deleted file mode 100644 index 2763ce8..0000000 --- a/src/main/kotlin/mods/octarinecore/client/resource/ModelDataInspector.kt +++ /dev/null @@ -1,97 +0,0 @@ -package mods.octarinecore.client.resource - -import mods.betterfoliage.loader.Refs -import mods.octarinecore.common.config.BlockMatcher -import net.minecraft.block.Block -import net.minecraft.block.state.IBlockState -import net.minecraft.client.renderer.block.model.ModelResourceLocation -import net.minecraft.client.renderer.block.statemap.DefaultStateMapper -import net.minecraft.client.renderer.block.statemap.IStateMapper -import net.minecraft.client.renderer.texture.TextureAtlasSprite -import net.minecraft.client.renderer.texture.TextureMap -import net.minecraft.util.ResourceLocation -import net.minecraftforge.client.event.TextureStitchEvent -import net.minecraftforge.client.model.IModel -import net.minecraftforge.client.model.ModelLoader -import net.minecraftforge.common.MinecraftForge -import net.minecraftforge.fml.common.eventhandler.Event -import net.minecraftforge.fml.common.eventhandler.EventPriority -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent - -class LoadModelDataEvent(val loader: ModelLoader) : Event() - -abstract class ModelDataInspector { - - abstract fun onAfterModelLoad() - abstract fun processModelDefinition(state: IBlockState, location: ModelResourceLocation, model: IModel) - abstract fun onStitch(atlas: TextureMap) - - init { MinecraftForge.EVENT_BUS.register(this) } - - @Suppress("UNCHECKED_CAST") - @SubscribeEvent - fun handleLoadModelData(event: LoadModelDataEvent) { - val stateMappings = Block.REGISTRY.flatMap { block -> - val mapper = event.loader.blockModelShapes.blockStateMapper.blockStateMap[block] as? IStateMapper ?: DefaultStateMapper() - (mapper.putStateModelLocations(block as Block) as Map).entries - } - val stateModels = Refs.stateModels.get(event.loader) as Map - - onAfterModelLoad() - - stateMappings.forEach { mapping -> - if (mapping.key.block != null) - stateModels[mapping.value]?.let { processModelDefinition(mapping.key, mapping.value, it) } - } - } - - @SubscribeEvent(priority = EventPriority.LOW) - fun handleTextureReload(event: TextureStitchEvent.Pre) { onStitch(event.map) } -} - -abstract class BlockTextureInspector : ModelDataInspector() { - - val state2Names = hashMapOf>() - val modelMappings = mutableListOfBoolean, Iterable>>() - val stateMap = hashMapOf() - - fun match(textureNames: Iterable, predicate: (IBlockState, IModel)->Boolean) = - modelMappings.add(predicate to textureNames) - fun matchClassAndModel(blockClass: BlockMatcher, modelLocation: String, textureNames: Iterable) = - match(textureNames) { state, model -> blockClass.matchesClass(state.block) && model.derivesFromModel(modelLocation) } - - operator fun get(state: IBlockState) = stateMap[state] - - override fun onAfterModelLoad() { - stateMap.clear() - } - - override fun processModelDefinition(state: IBlockState, modelDefLoc: ModelResourceLocation, model: IModel) { - modelMappings.forEach { mapping -> - if (mapping.first(state, model)) { - model.modelBlockAndLoc?.first?.let { modelBlock -> - val textures = mapping.second.map { modelBlock.resolveTextureName(it) } - if (textures.all { it != null && it != "missingno" }) { - state2Names.put(state, textures) - } - } - } - } - } - - override fun onStitch(atlas: TextureMap) { - val state2Texture = hashMapOf>() - val texture2Info = hashMapOf, T>() - state2Names.forEach { state, textureNames -> - val textures = textureNames.map { atlas.getTextureExtry(ResourceLocation(it).toString()) } - if (textures.all { it != null }) { - state2Texture.put(state, textures) - if (textures !in texture2Info) texture2Info.put(textures, processTextures(state, textures, atlas)) - } - } - state2Texture.forEach { state, texture -> stateMap.put(state, texture2Info[texture]!!) } - state2Names.clear() - } - - abstract fun processTextures(state: IBlockState, textures: List, atlas: TextureMap): T -} \ No newline at end of file diff --git a/src/main/kotlin/mods/octarinecore/client/resource/ModelProcessor.kt b/src/main/kotlin/mods/octarinecore/client/resource/ModelProcessor.kt index d85787d..dfb700c 100644 --- a/src/main/kotlin/mods/octarinecore/client/resource/ModelProcessor.kt +++ b/src/main/kotlin/mods/octarinecore/client/resource/ModelProcessor.kt @@ -2,7 +2,8 @@ package mods.octarinecore.client.resource import com.google.common.base.Joiner import mods.betterfoliage.loader.Refs -import mods.octarinecore.common.config.BlockMatcher +import mods.octarinecore.common.config.ConfigurableBlockMatcher +import mods.octarinecore.common.config.IBlockMatcher import mods.octarinecore.common.config.ModelTextureList import mods.octarinecore.filterValuesNotNull import net.minecraft.block.Block @@ -14,11 +15,15 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite import net.minecraft.client.renderer.texture.TextureMap import net.minecraftforge.client.event.TextureStitchEvent import net.minecraftforge.client.model.IModel +import net.minecraftforge.client.model.ModelLoader +import net.minecraftforge.fml.common.eventhandler.Event import net.minecraftforge.fml.common.eventhandler.EventPriority import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import org.apache.logging.log4j.Level import org.apache.logging.log4j.Logger +class LoadModelDataEvent(val loader: ModelLoader) : Event() + interface ModelProcessor { val logger: Logger? var stateToKey: MutableMap @@ -58,7 +63,7 @@ interface ModelProcessor { interface TextureListModelProcessor : ModelProcessor, T2> { val logName: String - val matchClasses: BlockMatcher + val matchClasses: IBlockMatcher val modelTextures: List override fun processModelLoad(state: IBlockState, modelLoc: ModelResourceLocation, model: IModel): List? { diff --git a/src/main/kotlin/mods/octarinecore/client/resource/Utils.kt b/src/main/kotlin/mods/octarinecore/client/resource/Utils.kt index 512c769..1a7b6ca 100644 --- a/src/main/kotlin/mods/octarinecore/client/resource/Utils.kt +++ b/src/main/kotlin/mods/octarinecore/client/resource/Utils.kt @@ -35,7 +35,7 @@ operator fun IResourceManager.get(domain: String, path: String): IResource? = ge operator fun IResourceManager.get(location: ResourceLocation): IResource? = tryDefault(null) { getResource(location) } /** Index operator to get a texture sprite. */ -operator fun TextureMap.get(name: String): TextureAtlasSprite? = getTextureExtry(name) +operator fun TextureMap.get(name: String): TextureAtlasSprite? = getTextureExtry(ResourceLocation(name).toString()) /** Load an image resource. */ fun IResource.loadImage() = ImageIO.read(this.inputStream) diff --git a/src/main/kotlin/mods/octarinecore/common/config/Matchers.kt b/src/main/kotlin/mods/octarinecore/common/config/Matchers.kt index eea8f64..6859bde 100644 --- a/src/main/kotlin/mods/octarinecore/common/config/Matchers.kt +++ b/src/main/kotlin/mods/octarinecore/common/config/Matchers.kt @@ -4,17 +4,32 @@ import mods.octarinecore.metaprog.getJavaClass import net.minecraft.block.Block import net.minecraft.util.ResourceLocation -class BlockMatcher(domain: String, path: String) : BlackWhiteListConfigOption>(domain, path) { +interface IBlockMatcher { + fun matchesClass(block: Block): Boolean + fun matchingClass(block: Block): Class<*>? +} + +class SimpleBlockMatcher(vararg val classes: Class<*>) : IBlockMatcher { + override fun matchesClass(block: Block) = matchingClass(block) != null + + override fun matchingClass(block: Block): Class<*>? { + val blockClass = block.javaClass + classes.forEach { if (it.isAssignableFrom(blockClass)) return it } + return null + } +} + +class ConfigurableBlockMatcher(domain: String, path: String) : IBlockMatcher, BlackWhiteListConfigOption>(domain, path) { override fun convertValue(line: String) = getJavaClass(line) - fun matchesClass(block: Block): Boolean { + override fun matchesClass(block: Block): Boolean { val blockClass = block.javaClass blackList.forEach { if (it.isAssignableFrom(blockClass)) return false } whiteList.forEach { if (it.isAssignableFrom(blockClass)) return true } return false } - fun matchingClass(block: Block): Class<*>? { + override fun matchingClass(block: Block): Class<*>? { val blockClass = block.javaClass blackList.forEach { if (it.isAssignableFrom(blockClass)) return null } whiteList.forEach { if (it.isAssignableFrom(blockClass)) return it } @@ -24,6 +39,8 @@ class BlockMatcher(domain: String, path: String) : BlackWhiteListConfigOption) +fun modelTextures(vararg args: String) = ModelTextureList(ResourceLocation(args[0]), listOf(*args).drop(1)) + class ModelTextureListConfigOption(domain: String, path: String, val minTextures: Int) : StringListConfigOption(domain, path) { override fun convertValue(line: String): ModelTextureList? { val elements = line.split(",") diff --git a/src/main/resources/assets/betterfoliage/LogDefault.cfg b/src/main/resources/assets/betterfoliage/LogBlocksDefault.cfg similarity index 100% rename from src/main/resources/assets/betterfoliage/LogDefault.cfg rename to src/main/resources/assets/betterfoliage/LogBlocksDefault.cfg diff --git a/src/main/resources/assets/betterfoliage/LogModelsDefault.cfg b/src/main/resources/assets/betterfoliage/LogModelsDefault.cfg new file mode 100644 index 0000000..24ebdb4 --- /dev/null +++ b/src/main/resources/assets/betterfoliage/LogModelsDefault.cfg @@ -0,0 +1,3 @@ +block/column_side,end,end,side +block/cube_column,end,end,side +block/cube_all,all,all,all \ No newline at end of file diff --git a/src/main/resources/assets/betterfoliage/lang/en_US.lang b/src/main/resources/assets/betterfoliage/lang/en_US.lang index 6dc6ba0..cbbded9 100644 --- a/src/main/resources/assets/betterfoliage/lang/en_US.lang +++ b/src/main/resources/assets/betterfoliage/lang/en_US.lang @@ -29,6 +29,8 @@ betterfoliage.blocks.dirtWhitelist=Dirt Whitelist betterfoliage.blocks.dirtBlacklist=Dirt Blacklist betterfoliage.blocks.dirtWhitelist.arrayEntry=%d entries betterfoliage.blocks.dirtBlacklist.arrayEntry=%d entries +betterfoliage.blocks.dirtWhitelist.tooltip=Blocks recognized as Dirt. Has an impact on Reeds, Algae, Connected Grass +betterfoliage.blocks.dirtBlacklist.tooltip=Blocks never accepted as Dirt. Has an impact on Reeds, Algae, Connected Grass betterfoliage.blocks.grassClassesWhitelist=Grass Whitelist betterfoliage.blocks.grassClassesBlacklist=Grass Blacklist @@ -36,6 +38,9 @@ betterfoliage.blocks.grassClassesWhitelist.arrayEntry=%d entries betterfoliage.blocks.grassClassesBlacklist.arrayEntry=%d entries betterfoliage.blocks.grassModels=Grass Models betterfoliage.blocks.grassModels.arrayEntry=%d entries +betterfoliage.blocks.grassWhitelist.tooltip=Blocks recognized as Grass. Has an impact on Short Grass, Connected Grass +betterfoliage.blocks.grassBlacklist.tooltip=Blocks never accepted as Grass. Has an impact on Short Grass, Connected Grass +betterfoliage.blocks.grassModels.tooltip=Models and textures recognized for grass blocks betterfoliage.blocks.leavesClassesWhitelist=Leaves Whitelist betterfoliage.blocks.leavesClassesBlacklist=Leaves Blacklist @@ -43,50 +48,49 @@ betterfoliage.blocks.leavesClassesWhitelist.arrayEntry=%d entries betterfoliage.blocks.leavesClassesBlacklist.arrayEntry=%d entries betterfoliage.blocks.leavesModels=Leaves Models betterfoliage.blocks.leavesModels.arrayEntry=%d entries +betterfoliage.blocks.leavesClassesWhitelist.tooltip=Blocks recognized as Leaves. Has an impact on Extra Leaves, Falling Leaves. Leaves will render with leaves block ID in shader programs +betterfoliage.blocks.leavesClassesBlacklist.tooltip=Blocks never accepted as Leaves. Has an impact on Extra Leaves, Falling Leaves. Leaves will render with leaves block ID in shader programs +betterfoliage.blocks.leavesModels.tooltip=Models and textures recognized for leaves blocks betterfoliage.blocks.cropsWhitelist=Crop Whitelist betterfoliage.blocks.cropsBlacklist=Crop Blacklist betterfoliage.blocks.cropsWhitelist.arrayEntry=%d entries betterfoliage.blocks.cropsBlacklist.arrayEntry=%d entries +betterfoliage.blocks.cropsWhitelist.tooltip=Blocks recognized as crops. Crops will render with tallgrass block ID in shader programs +betterfoliage.blocks.cropsBlacklist.tooltip=Blocks never accepted as crops. Crops will render with tallgrass block ID in shader programs -betterfoliage.blocks.logsWhitelist=Wood Log Whitelist -betterfoliage.blocks.logsBlacklist=Wood Log Blacklist -betterfoliage.blocks.logsWhitelist.arrayEntry=%d entries -betterfoliage.blocks.logsBlacklist.arrayEntry=%d entries +betterfoliage.blocks.logClassesWhitelist=Wood Log Whitelist +betterfoliage.blocks.logClassesBlacklist=Wood Log Blacklist +betterfoliage.blocks.logClassesWhitelist.arrayEntry=%d entries +betterfoliage.blocks.logClassesBlacklist.arrayEntry=%d entries +betterfoliage.blocks.logModels=Wood Log Models +betterfoliage.blocks.logModels.arrayEntry=%d entries +betterfoliage.blocks.logClassesWhitelist.tooltip=Blocks recognized as wooden logs. Has an impact on Rounded Logs +betterfoliage.blocks.logClassesBlacklist.tooltip=Blocks never accepted as wooden logs. Has an impact on Rounded Logs +betterfoliage.blocks.logModels.tooltip=Models and textures recognized for wood log blocks betterfoliage.blocks.sandWhitelist=Sand Whitelist betterfoliage.blocks.sandBlacklist=Sand Blacklist betterfoliage.blocks.sandWhitelist.arrayEntry=%d entries betterfoliage.blocks.sandBlacklist.arrayEntry=%d entries +betterfoliage.blocks.sandWhitelist.tooltip=Blocks recognized as Sand. Has an impact on Coral +betterfoliage.blocks.sandBlacklist.tooltip=Blocks never accepted Sand. Has an impact on Coral betterfoliage.blocks.lilypadWhitelist=Lilypad Whitelist betterfoliage.blocks.lilypadBlacklist=Lilypad Blacklist betterfoliage.blocks.lilypadWhitelist.arrayEntry=%d entries betterfoliage.blocks.lilypadBlacklist.arrayEntry=%d entries +betterfoliage.blocks.lilypadWhitelist.tooltip=Blocks recognized as Lilypad. Has an impact on Better Lilypad +betterfoliage.blocks.lilypadBlacklist.tooltip=Blocks never accepted Lilypad. Has an impact on Better Lilypad betterfoliage.blocks.cactusWhitelist=Cactus Whitelist betterfoliage.blocks.cactusBlacklist=Cactus Blacklist betterfoliage.blocks.cactusWhitelist.arrayEntry=%d entries betterfoliage.blocks.cactusBlacklist.arrayEntry=%d entries - - -betterfoliage.blocks.dirtWhitelist.tooltip=Blocks recognized as Dirt. Has an impact on Reeds, Algae, Connected Grass -betterfoliage.blocks.dirtBlacklist.tooltip=Blocks never accepted as Dirt. Has an impact on Reeds, Algae, Connected Grass -betterfoliage.blocks.grassWhitelist.tooltip=Blocks recognized as Grass. Has an impact on Short Grass, Connected Grass -betterfoliage.blocks.grassBlacklist.tooltip=Blocks never accepted as Grass. Has an impact on Short Grass, Connected Grass -betterfoliage.blocks.leavesWhitelist.tooltip=Blocks recognized as Leaves. Has an impact on Extra Leaves, Falling Leaves. Leaves will render with leaves block ID in shader programs -betterfoliage.blocks.leavesBlacklist.tooltip=Blocks never accepted as Leaves. Has an impact on Extra Leaves, Falling Leaves. Leaves will render with leaves block ID in shader programs -betterfoliage.blocks.cropsWhitelist.tooltip=Blocks recognized as crops. Crops will render with tallgrass block ID in shader programs -betterfoliage.blocks.cropsBlacklist.tooltip=Blocks never accepted as crops. Crops will render with tallgrass block ID in shader programs -betterfoliage.blocks.logsWhitelist.tooltip=Blocks recognized as wooden logs. Has an impact on Rounded Logs -betterfoliage.blocks.logsBlacklist.tooltip=Blocks never accepted as wooden logs. Has an impact on Rounded Logs -betterfoliage.blocks.sandWhitelist.tooltip=Blocks recognized as Sand. Has an impact on Coral -betterfoliage.blocks.sandBlacklist.tooltip=Blocks never accepted Sand. Has an impact on Coral -betterfoliage.blocks.lilypadWhitelist.tooltip=Blocks recognized as Lilypad. Has an impact on Better Lilypad -betterfoliage.blocks.lilypadBlacklist.tooltip=Blocks never accepted Lilypad. Has an impact on Better Lilypad betterfoliage.blocks.cactusWhitelist.tooltip=Blocks recognized as Cactus. Has an impact on Better Cactus betterfoliage.blocks.cactusBlacklist.tooltip=Blocks never accepted Cactus. Has an impact on Better Cactus + betterfoliage.leaves=Extra Leaves betterfoliage.leaves.tooltip=Extra round leaves on leaf blocks betterfoliage.leaves.dense=Dense mode