Add support for Forestry logs

fixes #82
This commit is contained in:
octarine-noise
2016-09-05 15:13:31 +02:00
parent e00ccd5919
commit 4a4d39b523
18 changed files with 217 additions and 178 deletions

View File

@@ -61,8 +61,9 @@ object Client {
)
val singletons = listOf(
StandardLeafSupport,
StandardGrassSupport,
LeafRegistry,
GrassRegistry,
LogRegistry,
LeafWindTracker,
RisingSoulTextures,
ShadersModIntegration,

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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<List<String>, IColumnTextureResolver>, IColumnRegistry {
override var stateToKey = mutableMapOf<IBlockState, List<String>>()
override var stateToValue = mapOf<IBlockState, IColumnTextureResolver>()
override val logger = BetterFoliageMod.logDetail
init { MinecraftForge.EVENT_BUS.register(this) }
override fun processModelLoad(state: IBlockState, modelLoc: ModelResourceLocation, model: IModel): List<String>? {
// 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<String>, 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]
}

View File

@@ -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<StaticColumnInfo>() {
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<TextureAtlasSprite>, 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)

View File

@@ -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<IColumnTextureResolver>, IColumnRegistry {
init { MinecraftForge.EVENT_BUS.register(this) }
override var stateToKey = mutableMapOf<IBlockState, List<String>>()
override var stateToValue = mapOf<IBlockState, IColumnTextureResolver>()
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<String>, 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
)

View File

@@ -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 {

View File

@@ -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<IColumnRegistry> = mutableListOf(StandardLogSupport)
override fun get(state: IBlockState) = subRegistries.findFirst { it[state] }
}
object StandardLogSupport : TextureListModelProcessor<IColumnTextureResolver>, IColumnRegistry {
init { MinecraftForge.EVENT_BUS.register(this) }
override var stateToKey = mutableMapOf<IBlockState, List<String>>()
override var stateToValue = mapOf<IBlockState, IColumnTextureResolver>()
override val logger = BetterFoliageMod.logDetail
override val logName = "StandardLogSupport"
override val matchClasses: ConfigurableBlockMatcher get() = Config.blocks.logClasses
override val modelTextures: List<ModelTextureList> get() = Config.blocks.logModels.list
override fun processStitch(state: IBlockState, key: List<String>, 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]
}

View File

@@ -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<IGrassRegistry> = 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<ModelTextureList> get() = Config.blocks.grassModels.list
override fun get(state: IBlockState, world: IBlockAccess, pos: BlockPos, face: EnumFacing): GrassInfo? {

View File

@@ -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<ModelTextureList> get() = Config.blocks.leavesModels.list
override val logger: Logger? get() = BetterFoliageMod.logDetail

View File

@@ -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")

View File

@@ -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<IBlockState, ModelResourceLocation>).entries
}
val stateModels = Refs.stateModels.get(event.loader) as Map<ModelResourceLocation, IModel>
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<T> : ModelDataInspector() {
val state2Names = hashMapOf<IBlockState, Iterable<String>>()
val modelMappings = mutableListOf<Pair<(IBlockState, IModel)->Boolean, Iterable<String>>>()
val stateMap = hashMapOf<IBlockState, T>()
fun match(textureNames: Iterable<String>, predicate: (IBlockState, IModel)->Boolean) =
modelMappings.add(predicate to textureNames)
fun matchClassAndModel(blockClass: BlockMatcher, modelLocation: String, textureNames: Iterable<String>) =
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<IBlockState, List<TextureAtlasSprite>>()
val texture2Info = hashMapOf<List<TextureAtlasSprite>, 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<TextureAtlasSprite>, atlas: TextureMap): T
}

View File

@@ -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<T1, T2> {
val logger: Logger?
var stateToKey: MutableMap<IBlockState, T1>
@@ -58,7 +63,7 @@ interface ModelProcessor<T1, T2> {
interface TextureListModelProcessor<T2> : ModelProcessor<List<String>, T2> {
val logName: String
val matchClasses: BlockMatcher
val matchClasses: IBlockMatcher
val modelTextures: List<ModelTextureList>
override fun processModelLoad(state: IBlockState, modelLoc: ModelResourceLocation, model: IModel): List<String>? {

View File

@@ -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)

View File

@@ -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<Class<*>>(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<Class<*>>(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<Cl
data class ModelTextureList(val modelLocation: ResourceLocation, val textureNames: List<String>)
fun modelTextures(vararg args: String) = ModelTextureList(ResourceLocation(args[0]), listOf(*args).drop(1))
class ModelTextureListConfigOption(domain: String, path: String, val minTextures: Int) : StringListConfigOption<ModelTextureList>(domain, path) {
override fun convertValue(line: String): ModelTextureList? {
val elements = line.split(",")

View File

@@ -0,0 +1,3 @@
block/column_side,end,end,side
block/cube_column,end,end,side
block/cube_all,all,all,all

View File

@@ -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