Compare commits

11 Commits

Author SHA1 Message Date
5aa33d7c70 Update README: Add fix details for texture rendering adjustments 2026-04-09 03:17:17 +02:00
64146a0f98 Ensure grass rendering respects air block checks and update project Java home in gradle properties. 2026-04-09 03:09:28 +02:00
octarine-noise
47c134049c Merge branch 'Snownee-1.12' into kotlin-1.12
# Conflicts:
#	src/main/resources/assets/betterfoliage/crop_default.cfg
#	src/main/resources/assets/betterfoliage/leaves_blocks_default.cfg
2021-04-26 11:53:34 +02:00
thedarkcolour
b1ad58c089 Fix an NPE with music discs
Fixes an NPE I found while playing around with music discs. Changes the "soundIn" parameter in the playRecord function in IBlockUpdateListener nullable which is safe because the parameter never gets used. This fixes the NPE because somehow taking a music disc out of the jukebox passes null for the playRecord function, which causes a crash when it shouldn't.
2021-04-26 11:34:02 +02:00
Jordan Rey
85e63b9161 "Plants" mod Crop compatibility 2021-04-26 11:33:21 +02:00
Jordan Rey
59ddaa0335 "Plants" mod Log compatibility 2021-04-26 11:33:21 +02:00
Jordan Rey
ae84741622 "Plants" mod Leaves compatibility 2021-04-26 11:33:21 +02:00
octarine-noise
7b739c172f Bump version 2020-01-01 16:12:57 +01:00
octarine-noise
8319d721c7 Update to work with OptiFine_1.12.2_HD_U_F6_pre1 2020-01-01 15:15:44 +01:00
octarine-noise
1b0e93b050 Array bounds check for overlay layer 2020-01-01 15:14:19 +01:00
Snownee
369348f6aa Add Cuisine classes to defaults 2019-01-20 20:30:03 +08:00
16 changed files with 106 additions and 38 deletions

View File

@@ -2,3 +2,6 @@ BetterFoliage
=============
Minecraft mod that alters the appearance of leaves & grass
fixed by @CatmanGames for StateMC<br>
(don't render certain textures when there is a block from another mod above)

View File

@@ -1,7 +1,7 @@
group = com.github.octarine-noise
jarName = BetterFoliage-MC1.12
version = 2.3.0
version = 2.3.1
mc_version = 1.12.2
forge_version = 14.23.5.2847
@@ -9,3 +9,5 @@ mcp_mappings = stable_39
kotlin_version = 1.3.40
forgelin_version = 1.8.4
org.gradle.java.home=C:\\Users\\catma\\.jdks\\corretto-1.8.0_482

View File

@@ -92,14 +92,16 @@ object ChunkOverlayManager : IBlockUpdateListener {
}
class ChunkOverlayData(layers: List<ChunkOverlayLayer<*>>) {
val BlockPos.isValid: Boolean get() = y in validYRange
val rawData = layers.associateWith { emptyOverlay() }
fun <T> get(layer: ChunkOverlayLayer<T>, pos: BlockPos): T? = rawData[layer]?.get(pos.x and 15)?.get(pos.z and 15)?.get(pos.y) as T?
fun <T> set(layer: ChunkOverlayLayer<T>, pos: BlockPos, data: T) = rawData[layer]?.get(pos.x and 15)?.get(pos.z and 15)?.set(pos.y, data)
fun <T> clear(layer: ChunkOverlayLayer<T>, pos: BlockPos) = rawData[layer]?.get(pos.x and 15)?.get(pos.z and 15)?.set(pos.y, UNCALCULATED)
fun <T> get(layer: ChunkOverlayLayer<T>, pos: BlockPos): T? = if (pos.isValid) rawData[layer]?.get(pos.x and 15)?.get(pos.z and 15)?.get(pos.y) as T? else null
fun <T> set(layer: ChunkOverlayLayer<T>, pos: BlockPos, data: T) = if (pos.isValid) rawData[layer]?.get(pos.x and 15)?.get(pos.z and 15)?.set(pos.y, data) else null
fun <T> clear(layer: ChunkOverlayLayer<T>, pos: BlockPos) = if (pos.isValid) rawData[layer]?.get(pos.x and 15)?.get(pos.z and 15)?.set(pos.y, UNCALCULATED) else null
companion object {
val UNCALCULATED = object {}
fun emptyOverlay() = Array(16) { Array(16) { Array<Any?>(256) { UNCALCULATED }}}
val validYRange = 0 until 256
}
}
@@ -116,7 +118,7 @@ interface IBlockUpdateListener : IWorldEventListener {
override fun notifyLightSet(pos: BlockPos) {}
override fun spawnParticle(particleID: Int, ignoreRange: Boolean, xCoord: Double, yCoord: Double, zCoord: Double, xSpeed: Double, ySpeed: Double, zSpeed: Double, vararg parameters: Int) {}
override fun spawnParticle(id: Int, ignoreRange: Boolean, minimiseParticleLevel: Boolean, x: Double, y: Double, z: Double, xSpeed: Double, ySpeed: Double, zSpeed: Double, vararg parameters: Int) {}
override fun playRecord(soundIn: SoundEvent, pos: BlockPos) {}
override fun playRecord(soundIn: SoundEvent?, pos: BlockPos) {}
override fun sendBlockBreakProgress(breakerId: Int, pos: BlockPos, progress: Int) {}
override fun markBlockRangeForRenderUpdate(x1: Int, y1: Int, z1: Int, x2: Int, y2: Int, z2: Int) {}
}

View File

@@ -2,6 +2,7 @@ package mods.betterfoliage.client.config
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.gui.BiomeListConfigEntry
import mods.betterfoliage.client.integration.ShadersModIntegration
import mods.octarinecore.common.config.*
import net.minecraft.client.Minecraft
import net.minecraft.world.biome.Biome
@@ -32,6 +33,11 @@ object Config : DelegatingConfig(BetterFoliageMod.MOD_ID, BetterFoliageMod.DOMAI
var enabled by boolean(true)
var nVidia by boolean(GL11.glGetString(GL11.GL_VENDOR).toLowerCase().contains("nvidia"))
object shaders {
val leavesId by long(min = 1, max = 65535, default = ShadersModIntegration.leavesDefaultBlockId.toInt())
val grassId by long(min = 1, max = 65535, default = ShadersModIntegration.grassDefaultBlockId.toInt())
}
object blocks {
val leavesClasses = ConfigurableBlockMatcher(BetterFoliageMod.DOMAIN, "leaves_blocks_default.cfg")
val leavesModels = ModelTextureListConfigOption(BetterFoliageMod.DOMAIN, "leaves_models_default.cfg", 1)

View File

@@ -38,7 +38,7 @@ object OptifineCustomColors {
fun getBlockColor(ctx: BlockContext): Int {
val ofColor = if (isColorAvailable && Minecraft.getMinecraft().gameSettings.reflectField<Boolean>("ofCustomColors") == true) {
renderEnv.reset(ctx.world!!, ctx.blockState(Int3.zero), ctx.pos)
renderEnv.reset(ctx.blockState(Int3.zero), ctx.pos)
Refs.getColorMultiplier.invokeStatic(fakeQuad, ctx.blockState(Int3.zero), ctx.world!!, ctx.pos, renderEnv.wrapped) as? Int
} else null
return if (ofColor == null || ofColor == -1) ctx.blockData(Int3.zero).color else ofColor
@@ -48,13 +48,13 @@ object OptifineCustomColors {
@SideOnly(Side.CLIENT)
class OptifineRenderEnv {
val wrapped: Any = Refs.RenderEnv.element!!.getDeclaredConstructor(
Refs.IBlockAccess.element, Refs.IBlockState.element, Refs.BlockPos.element
Refs.IBlockState.element, Refs.BlockPos.element
).let {
it.isAccessible = true
it.newInstance(null, null, null)
it.newInstance(null, null)
}
fun reset(blockAccess: IBlockAccess, state: IBlockState, pos: BlockPos) {
Refs.RenderEnv_reset.invoke(wrapped, blockAccess, state, pos)
fun reset(state: IBlockState, pos: BlockPos) {
Refs.RenderEnv_reset.invoke(wrapped, state, pos)
}
}

View File

@@ -9,6 +9,8 @@ import net.minecraft.block.BlockTallGrass
import net.minecraft.block.state.IBlockState
import net.minecraft.client.renderer.BufferBuilder
import net.minecraft.init.Blocks
import net.minecraft.util.EnumBlockRenderType
import net.minecraft.util.EnumBlockRenderType.MODEL
import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly
import org.apache.logging.log4j.Level.INFO
@@ -19,23 +21,32 @@ import org.apache.logging.log4j.Level.INFO
@SideOnly(Side.CLIENT)
object ShadersModIntegration {
@JvmStatic var isAvailable = allAvailable(Refs.sVertexBuilder, Refs.pushEntity_state, Refs.pushEntity_num, Refs.popEntity)
@JvmStatic val tallGrassEntityData = entityDataFor(Blocks.TALLGRASS.defaultState.withProperty(BlockTallGrass.TYPE, BlockTallGrass.EnumType.GRASS))
@JvmStatic val leavesEntityData = entityDataFor(Blocks.LEAVES.defaultState)
@JvmStatic val isAvailable = allAvailable(Refs.sVertexBuilder, Refs.pushEntity_state, Refs.pushEntity_num, Refs.popEntity)
fun entityDataFor(blockState: IBlockState) =
(Block.REGISTRY.getIDForObject(blockState.block).toLong() and 65535) or
((blockState.renderType.ordinal.toLong() and 65535) shl 16) or
(blockState.block.getMetaFromState(blockState).toLong() shl 32)
val grassDefaultBlockId = blockIdFor(Blocks.TALLGRASS.defaultState.withProperty(BlockTallGrass.TYPE, BlockTallGrass.EnumType.GRASS))
val leavesDefaultBlockId = blockIdFor(Blocks.LEAVES.defaultState)
fun blockIdFor(blockState: IBlockState) = Block.REGISTRY.getIDForObject(blockState.block).toLong() and 65535
// fun entityDataFor(blockState: IBlockState) =
// (Block.REGISTRY.getIDForObject(blockState.block).toLong() and 65535) //or
// ((blockState.renderType.ordinal.toLong() and 65535) shl 16) or
// (blockState.block.getMetaFromState(blockState).toLong() shl 32)
fun logEntityData(name: String, blockState: IBlockState) {
val blockId = Block.REGISTRY.getIDForObject(blockState.block).toLong() and 65535
val meta = blockState.renderType.ordinal.toLong() and 65535
val renderType = blockState.renderType.ordinal.toLong() and 65535
Client.log(INFO, "ShadersMod integration for $name")
Client.log(INFO, " blockState=$blockState")
Client.log(INFO, " blockId=$blockId, meta=$meta, type=$renderType")
}
/**
* Called from transformed ShadersMod code.
* @see mods.betterfoliage.loader.BetterFoliageTransformer
*/
@JvmStatic fun getBlockIdOverride(original: Long, blockState: IBlockState): Long {
if (Config.blocks.leavesClasses.matchesClass(blockState.block)) return leavesEntityData
if (Config.blocks.crops.matchesClass(blockState.block)) return tallGrassEntityData
if (Config.blocks.leavesClasses.matchesClass(blockState.block)) return Config.shaders.leavesId
if (Config.blocks.crops.matchesClass(blockState.block)) return Config.shaders.grassId
return original
}
@@ -44,10 +55,11 @@ object ShadersModIntegration {
}
/** Quads rendered inside this block will use the given block entity data in shader programs. */
inline fun renderAs(blockEntityData: Long, renderer: BufferBuilder, enabled: Boolean = true, func: ()->Unit) {
inline fun renderAs(blockId: Long, renderType: EnumBlockRenderType, renderer: BufferBuilder, enabled: Boolean = true, func: ()->Unit) {
val blockData = blockId or (renderType.ordinal shl 16).toLong()
if ((isAvailable && enabled)) {
val vertexBuilder = Refs.sVertexBuilder.get(renderer)!!
Refs.pushEntity_num.invoke(vertexBuilder, blockEntityData)
Refs.pushEntity_num.invoke(vertexBuilder, blockId)
func()
Refs.popEntity.invoke(vertexBuilder)
} else {
@@ -56,14 +68,14 @@ object ShadersModIntegration {
}
/** Quads rendered inside this block will use the given block entity data in shader programs. */
inline fun renderAs(state: IBlockState, renderer: BufferBuilder, enabled: Boolean = true, func: ()->Unit) =
renderAs(entityDataFor(state), renderer, enabled, func)
inline fun renderAs(state: IBlockState, renderType: EnumBlockRenderType, renderer: BufferBuilder, enabled: Boolean = true, func: ()->Unit) =
renderAs(blockIdFor(state), renderType, renderer, enabled, func)
/** Quads rendered inside this block will behave as tallgrass blocks in shader programs. */
inline fun grass(renderer: BufferBuilder, enabled: Boolean = true, func: ()->Unit) =
renderAs(tallGrassEntityData, renderer, enabled, func)
renderAs(Config.shaders.grassId, MODEL, renderer, enabled, func)
/** Quads rendered inside this block will behave as leaf blocks in shader programs. */
inline fun leaves(renderer: BufferBuilder, enabled: Boolean = true, func: ()->Unit) =
renderAs(leavesEntityData, renderer, enabled, func)
renderAs(Config.shaders.leavesId, MODEL, renderer, enabled, func)
}

View File

@@ -12,6 +12,8 @@ import mods.octarinecore.random
import net.minecraft.client.renderer.BlockRendererDispatcher
import net.minecraft.client.renderer.BufferBuilder
import net.minecraft.util.BlockRenderLayer
import net.minecraft.util.EnumBlockRenderType
import net.minecraft.util.EnumBlockRenderType.MODEL
import net.minecraft.util.EnumFacing.Axis
import net.minecraft.util.EnumFacing.UP
import net.minecraftforge.fml.relauncher.Side
@@ -78,7 +80,7 @@ class RenderGrass : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) {
val isHidden = forgeDirs.map { ctx.blockState(it.offset).isOpaqueCube }
// render full grass block
ShadersModIntegration.renderAs(ctx.blockState(Int3.zero), renderer) {
ShadersModIntegration.renderAs(ctx.blockState(Int3.zero), MODEL, renderer) {
modelRenderer.render(
renderer,
fullCube,
@@ -100,6 +102,10 @@ class RenderGrass : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) {
}
if (!Config.shortGrass.grassEnabled) return true
val stateAbove = ctx.blockState(up1)
if (!stateAbove.block.isAir(stateAbove, ctx.world!!, ctx.pos.up())) return true
if (isSnowed && !Config.shortGrass.snowEnabled) return true
if (ctx.blockState(up1).isOpaqueCube) return true
if (Config.shortGrass.population < 64 && noise[ctx.pos] >= Config.shortGrass.population) return true

View File

@@ -17,6 +17,8 @@ import net.minecraft.client.renderer.BlockRendererDispatcher
import net.minecraft.client.renderer.BufferBuilder
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.util.BlockRenderLayer
import net.minecraft.util.EnumBlockRenderType
import net.minecraft.util.EnumBlockRenderType.MODEL
import net.minecraft.util.EnumFacing.*
import net.minecraft.util.math.BlockPos
import net.minecraft.world.IBlockAccess
@@ -117,7 +119,7 @@ abstract class AbstractRenderColumn(modId: String) : AbstractBlockRenderingHandl
modelRenderer.updateShading(Int3.zero, allFaces)
val baseRotation = rotationFromUp[((roundLog.column.axis ?: Axis.Y) to AxisDirection.POSITIVE).face.ordinal]
renderAs(ctx.blockState(Int3.zero), renderer) {
renderAs(ctx.blockState(Int3.zero), MODEL, renderer) {
quadrantRotations.forEachIndexed { idx, quadrantRotation ->
// set rotation for the current quadrant
val rotation = baseRotation + quadrantRotation

View File

@@ -101,7 +101,7 @@ class BetterFoliageTransformer : Transformer() {
}
if (isOptifinePresent) {
find(varinsn(ISTORE, 23))?.insertAfter {
log.info("[BetterFoliageLoader] Applying RenderChunk block layer override")
log.info("[BetterFoliageLoader] Applying RenderChunk block layer override (Optifine)")
varinsn(ALOAD, 19)
varinsn(ALOAD, 18)
varinsn(ALOAD, 22)
@@ -110,7 +110,7 @@ class BetterFoliageTransformer : Transformer() {
}
} else {
find(invokeRef(Refs.canRenderInLayer))?.replace {
log.info("[BetterFoliageLoader] Applying RenderChunk block layer override")
log.info("[BetterFoliageLoader] Applying RenderChunk block layer override (non-Optifine)")
invokeStatic(Refs.canRenderBlockInLayer)
}
}

View File

@@ -98,7 +98,7 @@ object Refs {
// Optifine
val RenderEnv = ClassRef("net.optifine.render.RenderEnv")
val RenderEnv_reset = MethodRef(RenderEnv, "reset", ClassRef.void, IBlockAccess, IBlockState, BlockPos)
val RenderEnv_reset = MethodRef(RenderEnv, "reset", ClassRef.void, IBlockState, BlockPos)
val quadSprite = FieldRef(BufferBuilder, "quadSprite", TextureAtlasSprite)
// Optifine: custom colors

View File

@@ -47,11 +47,10 @@ class AoData() {
}
class AoFaceData(val face: EnumFacing) {
val ao = Refs.AmbientOcclusionFace.element!!.let {
if (allAvailable(Refs.OptifineClassTransformer)) it.getDeclaredConstructor().newInstance()
else it.getDeclaredConstructor(Refs.BlockModelRenderer.element!!)
val ao = Refs.AmbientOcclusionFace.element!!.getDeclaredConstructor(Refs.BlockModelRenderer.element!!)
.newInstance(BlockModelRenderer(Minecraft.getMinecraft().blockColors))
} as BlockModelRenderer.AmbientOcclusionFace
as BlockModelRenderer.AmbientOcclusionFace
val top = faceCorners[face.ordinal].topLeft.first
val left = faceCorners[face.ordinal].topLeft.second

View File

@@ -228,6 +228,15 @@ class ConfigPropertyInt(val min: Int, val max: Int, val default: Int) :
override fun Property.write(value: Int) = property!!.set(value)
}
/** [Long]-typed property delegate. Still uses [Int] internally */
class ConfigPropertyLong(val min: Int, val max: Int, val default: Int) :
ConfigPropertyDelegate<Long>() {
override fun resolve(target: Configuration, category: String, name: String) =
target.get(category, name, default, null).apply { setMinValue(min); setMaxValue(max) }
override fun Property.read() = property!!.long
override fun Property.write(value: Long) = property!!.set(value)
}
/** [Boolean]-typed property delegate. */
class ConfigPropertyBoolean(val default: Boolean) :
ConfigPropertyDelegate<Boolean>() {
@@ -252,5 +261,6 @@ class ConfigPropertyIntList(val defaults: ()->Array<Int>) :
fun double(min: Double = 0.0, max: Double = 1.0, default: Double) = ConfigPropertyDouble(min, max, default)
fun float(min: Double = 0.0, max: Double = 1.0, default: Double) = ConfigPropertyFloat(min, max, default)
fun int(min: Int = 0, max: Int, default: Int) = ConfigPropertyInt(min, max, default)
fun long(min: Int = 0, max: Int, default: Int) = ConfigPropertyLong(min, max, default)
fun intList(defaults: ()->Array<Int>) = ConfigPropertyIntList(defaults)
fun boolean(default: Boolean) = ConfigPropertyBoolean(default)

View File

@@ -34,3 +34,10 @@ com.pam.harvestcraft.BlockPamCrop
com.pam.harvestcraft.BlockPamDesertGarden
com.pam.harvestcraft.BlockPamNormalGarden
com.pam.harvestcraft.BlockPamWaterGarden
// Plants
shadows.plants2.block.BlockEnumCrop
// Cuisine
snownee.cuisine.blocks.BlockCuisineCrops
-snownee.cuisine.blocks.BlockDoubleCrops

View File

@@ -108,6 +108,13 @@ betterfoliage.blocks.netherrackBlacklist.arrayEntry=%d entries
betterfoliage.blocks.netherrackWhitelist.tooltip=Blocks recognized as Netherrack. Has an impact on Netherrack Vines
betterfoliage.blocks.netherrackBlacklist.tooltip=Blocks never accepted Netherrack. Has an impact on Netherrack Vines
betterfoliage.shaders=Shader configuration
betterfoliage.shaders.tooltip=Configure integration with shaders
betterfoliage.shaders.leavesId=Leaves ID
betterfoliage.shaders.leavesId.tooltip=Block ID reported to shader programs for all kinds of leaves. If your shader uses a §6block.properties§e file, you'll probably need to change this to match the shader's mappings.
betterfoliage.shaders.grassId=Grass ID
betterfoliage.shaders.grassId.tooltip=Block ID reported to shader programs for all grasses and crops. If your shader uses a §6block.properties§e file, you'll probably need to change this to match the shader's mappings.
betterfoliage.leaves=Extra Leaves
betterfoliage.leaves.tooltip=Extra round leaves on leaf blocks
betterfoliage.leaves.dense=Dense mode

View File

@@ -6,3 +6,11 @@ biomesoplenty.common.block.BlockBOPLeaves
// Aether II
com.gildedgames.aether.common.blocks.natural.BlockAetherLeaves
// Plants
shadows.plants2.block.BlockEnumLeaves
shadows.plants2.block.BlockEnumNetherLeaves
// Cuisine
snownee.cuisine.blocks.BlockModLeaves
snownee.cuisine.blocks.BlockShearedLeaves

View File

@@ -33,3 +33,7 @@ techreborn.blocks.BlockRubberLog
// Better With Mods
betterwithmods.blocks.BlockStump
// Plants
shadows.plants2.block.BlockEnumLog
shadows.plants2.block.BlockEnumNetherLog