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.IColumnTextureInfo import mods.betterfoliage.client.render.LogRegistry import mods.betterfoliage.client.render.StaticColumnInfo import mods.betterfoliage.client.texture.StandardLeafSupport import mods.betterfoliage.loader.Refs import mods.octarinecore.client.render.Quad import mods.octarinecore.client.render.ShadingContext import mods.octarinecore.client.render.blockContext import mods.octarinecore.client.resource.* import mods.octarinecore.common.rotate import mods.octarinecore.metaprog.ClassRef import mods.octarinecore.metaprog.MethodRef import mods.octarinecore.metaprog.allAvailable import net.minecraft.block.state.IBlockState 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 import net.minecraft.util.ResourceLocation import net.minecraftforge.client.model.IModel import net.minecraftforge.common.MinecraftForge import net.minecraftforge.fml.common.Loader import net.minecraftforge.fml.relauncher.Side import net.minecraftforge.fml.relauncher.SideOnly import org.apache.logging.log4j.Level import org.apache.logging.log4j.Logger @SideOnly(Side.CLIENT) object IC2Integration { val BlockRubWood = ClassRef("ic2.core.block.BlockRubWood") init { if (Loader.isModLoaded("IC2") && allAvailable(BlockRubWood)) { Client.log(Level.INFO, "IC2 support initialized") LogRegistry.subRegistries.add(IC2LogSupport) } } } @SideOnly(Side.CLIENT) object TechRebornIntegration { val BlockRubberLog = ClassRef("techreborn.blocks.BlockRubberLog") val ITexturedBlock = ClassRef("me.modmuss50.jsonDestroyer.api.ITexturedBlock") val getTextureNameFromState = MethodRef(ITexturedBlock, "getTextureNameFromState", Refs.String, Refs.IBlockState, Refs.EnumFacing) val rubberLogTextureNames = listOf( "techreborn:blocks/rubber_log_top", "techreborn:blocks/rubber_log_top", "techreborn:blocks/rubber_log_side", "techreborn:blocks/rubber_log_sap" ) init { if (Loader.isModLoaded("techreborn") && allAvailable(BlockRubberLog, ITexturedBlock, getTextureNameFromState)) { Client.log(Level.INFO, "TechReborn support initialized") LogRegistry.subRegistries.add(TechRebornLogSupport) // initialize object but don't add to registry TechRebornLeafSupport.toString() } } } @SideOnly(Side.CLIENT) data class RubberLogModelInfo( val axis: EnumFacing.Axis?, val spotDir: EnumFacing?, val textures: List ) // TODO avoid copy-paste pattern with regards to StaticColumnInfo @SideOnly(Side.CLIENT) data class RubberLogColumnInfo(override val axis: EnumFacing.Axis?, val spotDir: EnumFacing, val topTexture: TextureAtlasSprite, val bottomTexture: TextureAtlasSprite, val sideTexture: TextureAtlasSprite, val spotTexture: TextureAtlasSprite): IColumnTextureInfo { override val top = { ctx: ShadingContext, idx: Int, quad: Quad -> OptifineCTM.override(topTexture, blockContext, EnumFacing.UP.rotate(ctx.rotation)) } override val bottom = { ctx: ShadingContext, idx: Int, quad: Quad -> OptifineCTM.override(bottomTexture, blockContext, EnumFacing.DOWN.rotate(ctx.rotation)) } override val side = { ctx: ShadingContext, idx: Int, quad: Quad -> val worldRelativeSide = (if ((idx and 1) == 0) EnumFacing.SOUTH else EnumFacing.EAST).rotate(ctx.rotation) val texture = if (worldRelativeSide == spotDir) spotTexture else sideTexture OptifineCTM.override(texture, blockContext, worldRelativeSide) } } @SideOnly(Side.CLIENT) abstract class RubberLogSupportBase : ModelProcessor, IColumnRegistry { override var variants = mutableMapOf>() override var variantToKey = mutableMapOf() override var variantToValue = mapOf() override val logger = BetterFoliageMod.logDetail init { MinecraftForge.EVENT_BUS.register(this) } override fun processStitch(variant: ModelVariant, key: RubberLogModelInfo, atlas: TextureMap): IColumnTextureInfo? { val topTex = atlas[key.textures[0]] ?: return null val bottomTex = atlas[key.textures[1]] ?: return null val sideTex = atlas[key.textures[2]] ?: return null if (key.spotDir == null) return StaticColumnInfo(key.axis, topTex, bottomTex, listOf(sideTex)) else { val spotTex = atlas[key.textures[3]] ?: return null return RubberLogColumnInfo(key.axis, key.spotDir, topTex, bottomTex, sideTex, spotTex) } } override fun get(state: IBlockState, rand: Int): IColumnTextureInfo? { val variant = getVariant(state, rand) ?: return null return variantToValue[variant] } } @SideOnly(Side.CLIENT) object IC2LogSupport : RubberLogSupportBase() { override fun processModelLoad(state: IBlockState, modelLoc: ModelResourceLocation, model: IModel) { // check for proper block class, existence of ModelBlock, and "state" blockstate property if (!IC2Integration.BlockRubWood.isInstance(state.block)) return val blockLoc = model.modelBlockAndLoc.firstOrNull() ?: return val type = state.properties.entries.find { it.key.getName() == "state" }?.value?.toString() ?: return // logs with no rubber spot if (blockLoc.derivesFrom(ResourceLocation("block/cube_column"))) { val axis = when(type) { "plain_y" -> EnumFacing.Axis.Y "plain_x" -> EnumFacing.Axis.X "plain_z" -> EnumFacing.Axis.Z else -> null } val textureNames = listOf("end", "end", "side").map { blockLoc.first.resolveTextureName(it) } logger.log(Level.DEBUG, "IC2LogSupport: block state ${state.toString()}") logger.log(Level.DEBUG, "IC2LogSupport: axis=$axis, end=${textureNames[0]}, side=${textureNames[2]}") if (textureNames.all { it != "missingno" }) { putKeySingle(state, RubberLogModelInfo(axis, null, textureNames)) } return } // logs with rubber spot val spotDir = when(type) { "dry_north", "wet_north" -> EnumFacing.NORTH "dry_south", "wet_south" -> EnumFacing.SOUTH "dry_west", "wet_west" -> EnumFacing.WEST "dry_east", "wet_east" -> EnumFacing.EAST else -> null } val textureNames = listOf("up", "down", "south", "north").map { blockLoc.first.resolveTextureName(it) } logger.log(Level.DEBUG, "IC2LogSupport: block state ${state.toString()}") logger.log(Level.DEBUG, "IC2LogSupport: spotDir=$spotDir, up=${textureNames[0]}, down=${textureNames[1]}, side=${textureNames[2]}, spot=${textureNames[3]}") if (textureNames.all { it != "missingno" }) { putKeySingle(state, RubberLogModelInfo(EnumFacing.Axis.Y, spotDir, textureNames)) } } } @SideOnly(Side.CLIENT) object TechRebornLogSupport : RubberLogSupportBase() { override fun processModelLoad(state: IBlockState, modelLoc: ModelResourceLocation, model: IModel) { // check for proper block class, existence of ModelBlock if (!TechRebornIntegration.BlockRubberLog.isInstance(state.block)) return val hasSap = state.properties.entries.find { it.key.getName() == "hassap" }?.value as? Boolean ?: return val sapSide = state.properties.entries.find { it.key.getName() == "sapside" }?.value as? EnumFacing ?: return logger.log(Level.DEBUG, "TechRebornLogSupport: block state ${state.toString()}") if (hasSap) { val textureNames = listOf(EnumFacing.UP, EnumFacing.DOWN, sapSide.opposite, sapSide).map { TechRebornIntegration.getTextureNameFromState.invoke(state.block, state, it) as String } logger.log(Level.DEBUG, "TechRebornLogSupport: spotDir=$sapSide, up=${textureNames[0]}, down=${textureNames[1]}, side=${textureNames[2]}, spot=${textureNames[3]}") if (textureNames.all { it != "missingno" }) { putKeySingle(state, RubberLogModelInfo(EnumFacing.Axis.Y, sapSide, textureNames)) } } else { val textureNames = listOf(EnumFacing.UP, EnumFacing.DOWN, sapSide).map { TechRebornIntegration.getTextureNameFromState.invoke(state.block, state, it) as String } logger.log(Level.DEBUG, "TechRebornLogSupport: up=${textureNames[0]}, down=${textureNames[1]}, side=${textureNames[2]}") if (textureNames.all { it != "missingno" }) { putKeySingle(state, RubberLogModelInfo(EnumFacing.Axis.Y, null, textureNames)) } } } } @SideOnly(Side.CLIENT) object TechRebornLeafSupport : ModelProcessor { init { MinecraftForge.EVENT_BUS.register(this) } override var variants = mutableMapOf>() override var variantToKey = mutableMapOf() override var variantToValue = mapOf() override val logger: Logger get() = BetterFoliageMod.logDetail override fun processModelLoad(state: IBlockState, modelLoc: ModelResourceLocation, model: IModel) { if (Config.blocks.leavesClasses.matchesClass(state.block) && TechRebornIntegration.ITexturedBlock.isInstance(state.block)) { val textureName = TechRebornIntegration.getTextureNameFromState.invoke(state.block, state, EnumFacing.UP) as String logger.log(Level.DEBUG, "TechRebornLeafSupport: block state ${state.toString()}") logger.log(Level.DEBUG, "TechRebornLeafSupport: texture=$textureName") // register directly into StandardLeafSupport for the sake of simplicity StandardLeafSupport.putKeySingle(state, listOf(textureName)) } } // no-op override fun processStitch(variant: ModelVariant, key: Nothing, atlas: TextureMap) = null }