Port to 1.16.5
Kottle -> KotlinForForge
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
package mods.betterfoliage.render.block.vanilla
|
||||
|
||||
import mods.betterfoliage.BetterFoliageMod
|
||||
import mods.betterfoliage.BetterFoliage
|
||||
import mods.betterfoliage.BetterFoliageMod
|
||||
import mods.betterfoliage.config.Config
|
||||
import mods.betterfoliage.config.DIRT_BLOCKS
|
||||
import mods.betterfoliage.config.SALTWATER_BIOMES
|
||||
import mods.betterfoliage.config.isSnow
|
||||
import mods.betterfoliage.integration.ShadersModIntegration
|
||||
import mods.betterfoliage.model.HalfBakedSpecialWrapper
|
||||
import mods.betterfoliage.model.HalfBakedWrapperKey
|
||||
@@ -15,7 +16,6 @@ import mods.betterfoliage.model.tuftModelSet
|
||||
import mods.betterfoliage.model.tuftShapeSet
|
||||
import mods.betterfoliage.render.lighting.LightingPreferredFace
|
||||
import mods.betterfoliage.render.pipeline.RenderCtxBase
|
||||
import mods.betterfoliage.render.pipeline.RenderCtxVanilla
|
||||
import mods.betterfoliage.resource.discovery.AbstractModelDiscovery
|
||||
import mods.betterfoliage.resource.discovery.BakeWrapperManager
|
||||
import mods.betterfoliage.resource.discovery.ModelBakingContext
|
||||
@@ -27,20 +27,18 @@ import mods.betterfoliage.util.LazyInvalidatable
|
||||
import mods.betterfoliage.util.get
|
||||
import mods.betterfoliage.util.offset
|
||||
import mods.betterfoliage.util.randomI
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.RenderTypeLookup
|
||||
import net.minecraft.client.renderer.model.BlockModel
|
||||
import net.minecraft.util.Direction.UP
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import net.minecraft.world.biome.Biome
|
||||
|
||||
object StandardDirtDiscovery : AbstractModelDiscovery() {
|
||||
fun canRenderInLayer(layer: RenderType) = when {
|
||||
!Config.enabled -> layer == RenderType.getSolid()
|
||||
!Config.connectedGrass.enabled && !Config.algae.enabled && !Config.reed.enabled -> layer == RenderType.getSolid()
|
||||
else -> layer == RenderType.getCutoutMipped()
|
||||
!Config.enabled -> layer == RenderType.solid()
|
||||
!Config.connectedGrass.enabled && !Config.algae.enabled && !Config.reed.enabled -> layer == RenderType.solid()
|
||||
else -> layer == RenderType.cutoutMipped()
|
||||
}
|
||||
|
||||
override fun processModel(ctx: ModelDiscoveryContext) {
|
||||
@@ -67,9 +65,12 @@ class StandardDirtModel(
|
||||
|
||||
val stateUp = ctx.state(UP)
|
||||
val state2Up = ctx.state(Int3(0, 2, 0))
|
||||
val isConnectedGrass = Config.connectedGrass.enabled && stateUp in BetterFoliage.blockTypes.grass
|
||||
val isConnectedGrass = Config.connectedGrass.enabled &&
|
||||
stateUp in BetterFoliage.blockTypes.grass &&
|
||||
(Config.connectedGrass.snowEnabled || !state2Up.isSnow)
|
||||
|
||||
if (isConnectedGrass) {
|
||||
(ctx.blockModelShapes.getModel(stateUp) as? SpecialRenderModel)?.let { grassModel ->
|
||||
(ctx.blockModelShapes.getBlockModel(stateUp) as? SpecialRenderModel)?.let { grassModel ->
|
||||
ctx.renderMasquerade(UP.offset) {
|
||||
grassModel.render(ctx, true)
|
||||
}
|
||||
@@ -81,9 +82,9 @@ class StandardDirtModel(
|
||||
super.render(ctx, false)
|
||||
|
||||
val isWater = stateUp.material == Material.WATER
|
||||
val isDeepWater = isWater && ctx.offset(Int3(2 to UP)).state.material == Material.WATER
|
||||
val isShallowWater = isWater && ctx.offset(Int3(2 to UP)).state.isAir
|
||||
val isSaltWater = isWater && ctx.biome?.category in SALTWATER_BIOMES
|
||||
val isDeepWater = isWater && state2Up.material == Material.WATER
|
||||
val isShallowWater = isWater && state2Up.isAir
|
||||
val isSaltWater = isWater && ctx.biome?.biomeCategory in SALTWATER_BIOMES
|
||||
|
||||
if (Config.algae.enabled(ctx.random) && isDeepWater) {
|
||||
ctx.vertexLighter = vanillaTuftLighting
|
||||
|
||||
@@ -31,7 +31,7 @@ object StandardMyceliumDiscovery : AbstractModelDiscovery() {
|
||||
override fun processModel(ctx: ModelDiscoveryContext) {
|
||||
if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in MYCELIUM_BLOCKS) {
|
||||
ctx.addReplacement(StandardMyceliumKey)
|
||||
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.getCutout())
|
||||
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.cutout())
|
||||
}
|
||||
super.processModel(ctx)
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ import net.minecraft.util.ResourceLocation
|
||||
|
||||
object StandardNetherrackDiscovery : AbstractModelDiscovery() {
|
||||
fun canRenderInLayer(layer: RenderType) = when {
|
||||
!Config.enabled -> layer == RenderType.getSolid()
|
||||
!Config.netherrack.enabled -> layer == RenderType.getSolid()
|
||||
else -> layer == RenderType.getCutoutMipped()
|
||||
!Config.enabled -> layer == RenderType.solid()
|
||||
!Config.netherrack.enabled -> layer == RenderType.solid()
|
||||
else -> layer == RenderType.cutoutMipped()
|
||||
}
|
||||
|
||||
override fun processModel(ctx: ModelDiscoveryContext) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package mods.betterfoliage.render.block.vanilla
|
||||
|
||||
import mods.betterfoliage.BetterFoliage
|
||||
import mods.betterfoliage.config.ACCEPTED_ROUND_LOG_MATERIALS
|
||||
import mods.betterfoliage.config.BlockConfig
|
||||
import mods.betterfoliage.config.Config
|
||||
import mods.betterfoliage.resource.discovery.ModelTextureList
|
||||
import mods.betterfoliage.model.HalfBakedWrapperKey
|
||||
import mods.betterfoliage.model.SpecialRenderModel
|
||||
import mods.betterfoliage.render.column.ColumnBlockKey
|
||||
@@ -16,11 +16,12 @@ import mods.betterfoliage.resource.discovery.ConfigurableModelDiscovery
|
||||
import mods.betterfoliage.resource.discovery.ModelBakingContext
|
||||
import mods.betterfoliage.resource.discovery.ModelBakingKey
|
||||
import mods.betterfoliage.resource.discovery.ModelDiscoveryContext
|
||||
import mods.betterfoliage.resource.discovery.ModelTextureList
|
||||
import mods.betterfoliage.util.Atlas
|
||||
import mods.betterfoliage.util.LazyMapInvalidatable
|
||||
import mods.betterfoliage.util.tryDefault
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.LogBlock
|
||||
import net.minecraft.block.RotatedPillarBlock
|
||||
import net.minecraft.util.Direction.Axis
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import org.apache.logging.log4j.Level.INFO
|
||||
@@ -43,13 +44,15 @@ object StandardRoundLogDiscovery : ConfigurableModelDiscovery() {
|
||||
|
||||
override fun processModel(ctx: ModelDiscoveryContext, textureMatch: List<ResourceLocation>) {
|
||||
val axis = getAxis(ctx.blockState)
|
||||
detailLogger.log(INFO, " axis $axis")
|
||||
ctx.addReplacement(StandardRoundLogKey(axis, textureMatch[0], textureMatch[1]))
|
||||
|
||||
detailLogger.log(INFO, " axis $axis, material ${ctx.blockState.material}")
|
||||
if (!Config.roundLogs.plantsOnly || ctx.blockState.material in ACCEPTED_ROUND_LOG_MATERIALS)
|
||||
ctx.addReplacement(StandardRoundLogKey(axis, textureMatch[0], textureMatch[1]))
|
||||
}
|
||||
|
||||
fun getAxis(state: BlockState): Axis? {
|
||||
val axis = tryDefault(null) { state.get(LogBlock.AXIS).toString() } ?:
|
||||
state.values.entries.find { it.key.getName().toLowerCase() == "axis" }?.value?.toString()
|
||||
val axis = tryDefault(null) { state.getValue(RotatedPillarBlock.AXIS).toString() } ?:
|
||||
state.values.entries.find { it.key.name.toLowerCase() == "axis" }?.value?.toString()
|
||||
return when (axis) {
|
||||
"x" -> Axis.X
|
||||
"y" -> Axis.Y
|
||||
|
||||
@@ -43,7 +43,7 @@ object StandardSandDiscovery : AbstractModelDiscovery() {
|
||||
if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in SAND_BLOCKS) {
|
||||
BetterFoliage.blockTypes.dirt.add(ctx.blockState)
|
||||
ctx.addReplacement(StandardSandKey)
|
||||
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.getCutoutMipped())
|
||||
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.cutoutMipped())
|
||||
}
|
||||
super.processModel(ctx)
|
||||
}
|
||||
@@ -61,7 +61,7 @@ class StandardSandModel(
|
||||
override fun render(ctx: RenderCtxBase, noDecorations: Boolean) {
|
||||
super.render(ctx, noDecorations)
|
||||
if (noDecorations || !Config.enabled || !Config.coral.enabled(ctx.random)) return
|
||||
if (ctx.biome?.category !in SALTWATER_BIOMES) return
|
||||
if (ctx.biome?.biomeCategory !in SALTWATER_BIOMES) return
|
||||
|
||||
allDirections.filter { ctx.random.nextInt(64) < Config.coral.chance }.forEach { face ->
|
||||
val isWater = ctx.state(face).material == Material.WATER
|
||||
|
||||
@@ -23,7 +23,7 @@ import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.Direction.Axis
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
|
||||
/** Index of SOUTH-EAST quadrant. */
|
||||
const val SE = 0
|
||||
@@ -83,13 +83,13 @@ abstract class ColumnRenderLayer : ChunkOverlayLayer<ColumnLayerData> {
|
||||
|
||||
val allNeighborOffsets = (-1..1).flatMap { offsetX -> (-1..1).flatMap { offsetY -> (-1..1).map { offsetZ -> Int3(offsetX, offsetY, offsetZ) }}}
|
||||
|
||||
override fun onBlockUpdate(world: ILightReader, pos: BlockPos) {
|
||||
override fun onBlockUpdate(world: IBlockDisplayReader, pos: BlockPos) {
|
||||
allNeighborOffsets.forEach { offset -> ChunkOverlayManager.clear(world.dimType, this, pos + offset) }
|
||||
}
|
||||
|
||||
override fun calculate(ctx: BlockCtx): ColumnLayerData {
|
||||
// TODO detect round logs
|
||||
if (allDirections.all { dir -> ctx.offset(dir).let { it.isNormalCube } }) return ColumnLayerData.SkipRender
|
||||
if (allDirections.all { dir -> ctx.offset(dir).let { it.isFullBlock } }) return ColumnLayerData.SkipRender
|
||||
val columnTextures = getColumnKey(ctx.state) ?: return ColumnLayerData.ResolveError
|
||||
|
||||
// if log axis is not defined and "Default to vertical" config option is not set, render normally
|
||||
@@ -185,7 +185,7 @@ abstract class ColumnRenderLayer : ChunkOverlayLayer<ColumnLayerData> {
|
||||
val offsetRot = offset.rotate(rotation)
|
||||
val key = getColumnKey(state(offsetRot))
|
||||
return if (key == null) {
|
||||
if (offset(offsetRot).isNormalCube) SOLID else NONSOLID
|
||||
if (offset(offsetRot).isFullBlock) SOLID else NONSOLID
|
||||
} else {
|
||||
(key.axis ?: if (Config.roundLogs.defaultY) Axis.Y else null)?.let {
|
||||
if (it == axis) PARALLEL else PERPENDICULAR
|
||||
|
||||
@@ -5,7 +5,7 @@ import net.minecraft.block.BlockState
|
||||
import net.minecraft.client.renderer.BlockModelRenderer
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
|
||||
data class LightingData(
|
||||
@JvmField var packedLight: Int = 0,
|
||||
@@ -29,7 +29,7 @@ data class LightingData(
|
||||
* Not thread-safe, always use a [ThreadLocal] instance
|
||||
*/
|
||||
class VanillaAoCalculator {
|
||||
lateinit var world: ILightReader
|
||||
lateinit var world: IBlockDisplayReader
|
||||
|
||||
/** [blockPos] is used to get block-related information (i.e. tint, opacity, etc.)
|
||||
* [lightPos] is used to get light-related information
|
||||
@@ -37,7 +37,7 @@ class VanillaAoCalculator {
|
||||
lateinit var blockPos: BlockPos
|
||||
lateinit var lightPos: BlockPos
|
||||
|
||||
private val probe = LightProbe(BlockModelRenderer.CACHE_COMBINED_LIGHT.get())
|
||||
private val probe = LightProbe(BlockModelRenderer.CACHE.get())
|
||||
|
||||
val isValid = BooleanArray(6)
|
||||
val aoData = Array(24) { LightingData() }
|
||||
@@ -70,13 +70,13 @@ class VanillaAoCalculator {
|
||||
|
||||
// Bit 0 of the bitset in vanilla calculations
|
||||
// true if the block model is planar with the block boundary
|
||||
val isFullBlock = forceFull ?: world.getBlockState(blockPos).isCollisionShapeOpaque(world, blockPos)
|
||||
val isFullBlock = forceFull ?: world.getBlockState(blockPos).isCollisionShapeFullBlock(world, blockPos)
|
||||
|
||||
val lightOrigin = if (isFullBlock) lightPos.offset(lightFace) else lightPos
|
||||
val lightOrigin = if (isFullBlock) lightPos.relative(lightFace) else lightPos
|
||||
|
||||
// AO calculation for the face center
|
||||
probe.position { setPos(lightOrigin) }.writeTo(centerAo)
|
||||
if (!isFullBlock && !probe.position { move(lightFace) }.state.isOpaqueCube(world, probe.pos)) {
|
||||
probe.position { set(lightOrigin) }.writeTo(centerAo)
|
||||
if (!isFullBlock && !probe.position { move(lightFace) }.state.isSolidRender(world, probe.pos)) {
|
||||
// if the neighboring block in the lightface direction is
|
||||
// transparent (non-opaque), use its packed light instead of our own
|
||||
// (if our block is a full block, we are already using this value)
|
||||
@@ -86,7 +86,7 @@ class VanillaAoCalculator {
|
||||
// AO calculation for the 4 sides
|
||||
sideHelper.sides.forEachIndexed { sideIdx, sideDir ->
|
||||
// record light data in the block 1 step to the side
|
||||
probe.position { setPos(lightOrigin).move(sideDir) }.writeTo(sideAo[sideIdx])
|
||||
probe.position { set(lightOrigin).move(sideDir) }.writeTo(sideAo[sideIdx])
|
||||
// side is considered occluded if the block 1 step to that side and
|
||||
// 1 step forward (in the lightface direction) is not fully transparent
|
||||
isOccluded[sideIdx] = probe.position { move(lightFace) }.isNonTransparent
|
||||
@@ -103,7 +103,7 @@ class VanillaAoCalculator {
|
||||
else {
|
||||
// lookup actual packed light from the cornering block in the world
|
||||
probe.position {
|
||||
setPos(lightOrigin)
|
||||
set(lightOrigin)
|
||||
.move(sideHelper.sides[sideIndices.first])
|
||||
.move(sideHelper.sides[sideIndices.second])
|
||||
}.writeTo(cornerAo[cornerIdx])
|
||||
@@ -129,9 +129,9 @@ class VanillaAoCalculator {
|
||||
lateinit var state: BlockState
|
||||
val pos = BlockPos.Mutable()
|
||||
|
||||
val packedLight: Int get() = cache.getPackedLight(state, world, pos)
|
||||
val colorMultiplier: Float get() = cache.getBrightness(state, world, pos)
|
||||
val isNonTransparent: Boolean get() = state.getOpacity(world, pos) > 0
|
||||
val packedLight: Int get() = cache.getLightColor(state, world, pos)
|
||||
val colorMultiplier: Float get() = cache.getShadeBrightness(state, world, pos)
|
||||
val isNonTransparent: Boolean get() = state.getLightBlock(world, pos) > 0
|
||||
|
||||
fun writeTo(data: LightingData) {
|
||||
data.packedLight = packedLight
|
||||
|
||||
@@ -69,7 +69,7 @@ object VanillaFullBlockLighting : VanillaVertexLighter() {
|
||||
lighting.calc.fillLightData(face, true)
|
||||
lighting.updateWithCornerAo(quad) { nearestCornerOnFace(it, face) }
|
||||
lighting.updateBlockTint(quad.baked.tintIndex)
|
||||
if (quad.baked.shouldApplyDiffuseLighting()) lighting.applyDiffuseLighting(face)
|
||||
if (quad.baked.isShade) lighting.applyDiffuseLighting(face)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ import mods.betterfoliage.util.Double3
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.particle.SpriteTexturedParticle
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo
|
||||
import net.minecraft.client.renderer.Vector3f
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite
|
||||
import net.minecraft.client.world.ClientWorld
|
||||
import net.minecraft.util.math.MathHelper
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.util.math.vector.Vector3f
|
||||
|
||||
abstract class AbstractParticle(world: World, x: Double, y: Double, z: Double) : SpriteTexturedParticle(world, x, y, z) {
|
||||
abstract class AbstractParticle(world: ClientWorld, x: Double, y: Double, z: Double) : SpriteTexturedParticle(world, x, y, z) {
|
||||
|
||||
companion object {
|
||||
// @JvmStatic val sin = Array(64) { idx -> Math.sin(PI2 / 64.0 * idx) }
|
||||
@@ -24,12 +24,12 @@ abstract class AbstractParticle(world: World, x: Double, y: Double, z: Double) :
|
||||
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
currentPos.setTo(posX, posY, posZ)
|
||||
prevPos.setTo(prevPosX, prevPosY, prevPosZ)
|
||||
velocity.setTo(motionX, motionY, motionZ)
|
||||
currentPos.setTo(x, y, z)
|
||||
prevPos.setTo(xo, yo, zo)
|
||||
velocity.setTo(xd, yd, zd)
|
||||
update()
|
||||
posX = currentPos.x; posY = currentPos.y; posZ = currentPos.z;
|
||||
motionX = velocity.x; motionY = velocity.y; motionZ = velocity.z;
|
||||
x = currentPos.x; y = currentPos.y; z = currentPos.z;
|
||||
xd = velocity.x; yd = velocity.y; zd = velocity.z;
|
||||
}
|
||||
|
||||
/** Update particle on world tick. */
|
||||
@@ -39,10 +39,10 @@ abstract class AbstractParticle(world: World, x: Double, y: Double, z: Double) :
|
||||
abstract val isValid: Boolean
|
||||
|
||||
/** Add the particle to the effect renderer if it is valid. */
|
||||
fun addIfValid() { if (isValid) Minecraft.getInstance().particles.addEffect(this) }
|
||||
fun addIfValid() { if (isValid) Minecraft.getInstance().particleEngine.add(this) }
|
||||
|
||||
override fun renderParticle(vertexBuilder: IVertexBuilder, camera: ActiveRenderInfo, tickDelta: Float) {
|
||||
super.renderParticle(vertexBuilder, camera, tickDelta)
|
||||
override fun render(vertexBuilder: IVertexBuilder, camera: ActiveRenderInfo, tickDelta: Float) {
|
||||
super.render(vertexBuilder, camera, tickDelta)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,39 +63,39 @@ abstract class AbstractParticle(world: World, x: Double, y: Double, z: Double) :
|
||||
tickDelta: Float,
|
||||
currentPos: Double3 = this.currentPos,
|
||||
prevPos: Double3 = this.prevPos,
|
||||
size: Double = particleScale.toDouble(),
|
||||
currentAngle: Float = this.particleAngle,
|
||||
prevAngle: Float = this.prevParticleAngle,
|
||||
size: Double = quadSize.toDouble(),
|
||||
currentAngle: Float = this.roll,
|
||||
prevAngle: Float = this.oRoll,
|
||||
sprite: TextureAtlasSprite = this.sprite,
|
||||
alpha: Float = this.particleAlpha) {
|
||||
alpha: Float = this.alpha) {
|
||||
|
||||
val center = Double3.lerp(tickDelta.toDouble(), prevPos, currentPos)
|
||||
val angle = MathHelper.lerp(tickDelta, prevAngle, currentAngle)
|
||||
val rotation = camera.rotation.copy().apply { multiply(Vector3f.ZP.rotation(angle)) }
|
||||
val lightmapCoord = getBrightnessForRender(tickDelta)
|
||||
val rotation = camera.rotation().copy().apply { mul(Vector3f.ZP.rotation(angle)) }
|
||||
val lightmapCoord = getLightColor(tickDelta)
|
||||
|
||||
val coords = arrayOf(
|
||||
Double3(-1.0, -1.0, 0.0),
|
||||
Double3(-1.0, 1.0, 0.0),
|
||||
Double3(1.0, 1.0, 0.0),
|
||||
Double3(1.0, -1.0, 0.0)
|
||||
).map { it.rotate(rotation).mul(size).add(center).sub(camera.projectedView.x, camera.projectedView.y, camera.projectedView.z) }
|
||||
).map { it.rotate(rotation).mul(size).add(center).sub(camera.position.x, camera.position.y, camera.position.z) }
|
||||
|
||||
fun renderVertex(vertex: Double3, u: Float, v: Float) = vertexConsumer
|
||||
.pos(vertex.x, vertex.y, vertex.z).tex(u, v)
|
||||
.color(particleRed, particleGreen, particleBlue, alpha).lightmap(lightmapCoord)
|
||||
.vertex(vertex.x, vertex.y, vertex.z).uv(u, v)
|
||||
.color(rCol, gCol, bCol, alpha).uv2(lightmapCoord)
|
||||
.endVertex()
|
||||
|
||||
renderVertex(coords[0], sprite.maxU, sprite.maxV)
|
||||
renderVertex(coords[1], sprite.maxU, sprite.minV)
|
||||
renderVertex(coords[2], sprite.minU, sprite.minV)
|
||||
renderVertex(coords[3], sprite.minU, sprite.maxV)
|
||||
renderVertex(coords[0], sprite.u1, sprite.v1)
|
||||
renderVertex(coords[1], sprite.u1, sprite.v0)
|
||||
renderVertex(coords[2], sprite.u0, sprite.v0)
|
||||
renderVertex(coords[3], sprite.u0, sprite.v1)
|
||||
}
|
||||
|
||||
fun setColor(color: Int) {
|
||||
particleBlue = (color and 255) / 256.0f
|
||||
particleGreen = ((color shr 8) and 255) / 256.0f
|
||||
particleRed = ((color shr 16) and 255) / 256.0f
|
||||
bCol = (color and 255) / 256.0f
|
||||
gCol = ((color shr 8) and 255) / 256.0f
|
||||
rCol = ((color shr 16) and 255) / 256.0f
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,22 +8,22 @@ import mods.betterfoliage.util.randomB
|
||||
import mods.betterfoliage.util.randomD
|
||||
import mods.betterfoliage.util.randomF
|
||||
import mods.betterfoliage.util.randomI
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.particle.IParticleRenderType
|
||||
import net.minecraft.client.world.ClientWorld
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.MathHelper
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
import net.minecraftforge.event.TickEvent
|
||||
import net.minecraftforge.event.world.WorldEvent
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
import net.minecraftforge.fml.LogicalSide
|
||||
import java.util.Random
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
class FallingLeafParticle(
|
||||
world: World, pos: BlockPos, leaf: LeafParticleKey, blockColor: Int, random: Random
|
||||
world: ClientWorld, pos: BlockPos, leaf: LeafParticleKey, blockColor: Int, random: Random
|
||||
) : AbstractParticle(
|
||||
world, pos.x.toDouble() + 0.5, pos.y.toDouble(), pos.z.toDouble() + 0.5
|
||||
) {
|
||||
@@ -37,13 +37,13 @@ class FallingLeafParticle(
|
||||
var wasCollided = false
|
||||
|
||||
init {
|
||||
particleAngle = random.randomF(max = PI2)
|
||||
prevParticleAngle = particleAngle - rotationSpeed
|
||||
roll = random.randomF(max = PI2)
|
||||
oRoll = roll - rotationSpeed
|
||||
|
||||
maxAge = MathHelper.floor(randomD(0.6, 1.0) * Config.fallingLeaves.lifetime * 20.0)
|
||||
motionY = -Config.fallingLeaves.speed
|
||||
lifetime = MathHelper.floor(randomD(0.6, 1.0) * Config.fallingLeaves.lifetime * 20.0)
|
||||
yd = -Config.fallingLeaves.speed
|
||||
|
||||
particleScale = Config.fallingLeaves.size.toFloat() * 0.1f
|
||||
quadSize = Config.fallingLeaves.size.toFloat() * 0.1f
|
||||
setColor(leaf.overrideColor?.asInt ?: blockColor)
|
||||
sprite = LeafParticleRegistry[leaf.leafType][randomI(max = 1024)]
|
||||
}
|
||||
@@ -52,21 +52,21 @@ class FallingLeafParticle(
|
||||
|
||||
|
||||
override fun update() {
|
||||
if (rand.nextFloat() > 0.95f) rotationSpeed *= -1.0f
|
||||
if (age > maxAge - 20) particleAlpha = 0.05f * (maxAge - age)
|
||||
if (random.nextFloat() > 0.95f) rotationSpeed *= -1.0f
|
||||
if (age > lifetime - 20) alpha = 0.05f * (lifetime - age)
|
||||
|
||||
if (onGround || wasCollided) {
|
||||
velocity.setTo(0.0, 0.0, 0.0)
|
||||
if (!wasCollided) {
|
||||
age = age.coerceAtLeast(maxAge - 20)
|
||||
age = age.coerceAtLeast(lifetime - 20)
|
||||
wasCollided = true
|
||||
}
|
||||
} else {
|
||||
val cosRotation = cos(particleAngle).toDouble(); val sinRotation = sin(particleAngle).toDouble()
|
||||
val cosRotation = cos(roll).toDouble(); val sinRotation = sin(roll).toDouble()
|
||||
velocity.setTo(cosRotation, 0.0, sinRotation).mul(Config.fallingLeaves.perturb)
|
||||
.add(LeafWindTracker.current).add(0.0, -1.0, 0.0).mul(Config.fallingLeaves.speed)
|
||||
prevParticleAngle = particleAngle
|
||||
particleAngle += rotationSpeed
|
||||
oRoll = roll
|
||||
roll += rotationSpeed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ object LeafWindTracker {
|
||||
}
|
||||
|
||||
fun changeWind(world: World) {
|
||||
nextChange = world.worldInfo.gameTime + 120 + random.nextInt(80)
|
||||
nextChange = world.gameTime + 120 + random.nextInt(80)
|
||||
val direction = PI2 * random.nextDouble()
|
||||
val speed = abs(random.nextGaussian()) * Config.fallingLeaves.windStrength +
|
||||
(if (!world.isRaining) 0.0 else abs(random.nextGaussian()) * Config.fallingLeaves.stormStrength)
|
||||
@@ -92,10 +92,10 @@ object LeafWindTracker {
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun handleWorldTick(event: TickEvent.ClientTickEvent) {
|
||||
if (event.phase == TickEvent.Phase.START) Minecraft.getInstance().world?.let { world ->
|
||||
fun handleWorldTick(event: TickEvent.WorldTickEvent) {
|
||||
if (event.phase == TickEvent.Phase.START && event.side == LogicalSide.CLIENT) event.world.let { world ->
|
||||
// change target wind speed
|
||||
if (world.worldInfo.dayTime >= nextChange) changeWind(world)
|
||||
if (world.dayTime >= nextChange) changeWind(world)
|
||||
|
||||
// change current wind speed
|
||||
val changeRate = if (world.isRaining) 0.015 else 0.005
|
||||
@@ -107,6 +107,6 @@ object LeafWindTracker {
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun handleWorldLoad(event: WorldEvent.Load) { if (event.world.isRemote) changeWind(event.world.world) }
|
||||
// @SubscribeEvent
|
||||
// fun handleWorldLoad(event: WorldEvent.Load) { if (event.world.isClientSide) changeWind(event.world) }
|
||||
}
|
||||
@@ -41,7 +41,7 @@ object LeafParticleRegistry : HasLogger(), VeryEarlyReloadListener {
|
||||
|
||||
@SubscribeEvent
|
||||
fun handlePreStitch(event: TextureStitchEvent.Pre) {
|
||||
if (event.map.textureLocation == Atlas.PARTICLES.resourceId) {
|
||||
if (event.map.location() == Atlas.PARTICLES.resourceId) {
|
||||
allTypes.forEach { leafType ->
|
||||
val locations = (0 until 16).map { idx ->
|
||||
ResourceLocation(BetterFoliageMod.MOD_ID, "particle/falling_leaf_${leafType}_$idx")
|
||||
@@ -55,7 +55,7 @@ object LeafParticleRegistry : HasLogger(), VeryEarlyReloadListener {
|
||||
|
||||
@SubscribeEvent
|
||||
fun handlePostStitch(event: TextureStitchEvent.Post) {
|
||||
if (event.map.textureLocation == Atlas.PARTICLES.resourceId) {
|
||||
if (event.map.location() == Atlas.PARTICLES.resourceId) {
|
||||
(typeMappings.mappings.map { it.type } + "default").distinct().forEach { leafType ->
|
||||
val sprites = (0 until 16).map { idx ->
|
||||
ResourceLocation(BetterFoliageMod.MOD_ID, "particle/falling_leaf_${leafType}_$idx")
|
||||
|
||||
@@ -13,6 +13,7 @@ import mods.betterfoliage.util.randomD
|
||||
import mods.betterfoliage.util.randomI
|
||||
import net.minecraft.client.particle.IParticleRenderType
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo
|
||||
import net.minecraft.client.world.ClientWorld
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.MathHelper
|
||||
@@ -23,7 +24,7 @@ import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
class RisingSoulParticle(
|
||||
world: World, pos: BlockPos
|
||||
world: ClientWorld, pos: BlockPos
|
||||
) : AbstractParticle(
|
||||
world, pos.x.toDouble() + 0.5, pos.y.toDouble() + 1.0, pos.z.toDouble() + 0.5
|
||||
) {
|
||||
@@ -32,10 +33,10 @@ class RisingSoulParticle(
|
||||
val initialPhase = randomD(max = PI2)
|
||||
|
||||
init {
|
||||
motionY = 0.1
|
||||
particleGravity = 0.0f
|
||||
yd = 0.1
|
||||
gravity = 0.0f
|
||||
sprite = headIcons[randomI(max = 1024)]
|
||||
maxAge = MathHelper.floor((0.6 + 0.4 * randomD()) * Config.risingSoul.lifetime * 20.0)
|
||||
lifetime = MathHelper.floor((0.6 + 0.4 * randomD()) * Config.risingSoul.lifetime * 20.0)
|
||||
}
|
||||
|
||||
override val isValid: Boolean get() = true
|
||||
@@ -49,12 +50,12 @@ class RisingSoulParticle(
|
||||
particleTrail.addFirst(currentPos.copy())
|
||||
while (particleTrail.size > Config.risingSoul.trailLength) particleTrail.removeLast()
|
||||
|
||||
if (!Config.enabled) setExpired()
|
||||
if (!Config.enabled) remove()
|
||||
}
|
||||
|
||||
override fun renderParticle(vertexBuilder: IVertexBuilder, camera: ActiveRenderInfo, tickDelta: Float) {
|
||||
override fun render(vertexBuilder: IVertexBuilder, camera: ActiveRenderInfo, tickDelta: Float) {
|
||||
var alpha = Config.risingSoul.opacity.toFloat()
|
||||
if (age > maxAge - 40) alpha *= (maxAge - age) / 40.0f
|
||||
if (age > lifetime - 40) alpha *= (lifetime - age) / 40.0f
|
||||
|
||||
renderParticleQuad(
|
||||
vertexBuilder, camera, tickDelta,
|
||||
|
||||
@@ -3,18 +3,18 @@ package mods.betterfoliage.render.pipeline
|
||||
import com.mojang.blaze3d.matrix.MatrixStack
|
||||
import mods.betterfoliage.chunk.BasicBlockCtx
|
||||
import mods.betterfoliage.chunk.BlockCtx
|
||||
import mods.betterfoliage.model.HalfBakedQuad
|
||||
import mods.betterfoliage.model.SpecialRenderModel
|
||||
import mods.betterfoliage.render.lighting.VanillaFullBlockLighting
|
||||
import mods.betterfoliage.render.lighting.VanillaQuadLighting
|
||||
import mods.betterfoliage.render.lighting.VanillaVertexLighter
|
||||
import mods.betterfoliage.model.HalfBakedQuad
|
||||
import mods.betterfoliage.util.Int3
|
||||
import mods.betterfoliage.util.plus
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
import net.minecraftforge.client.model.data.IModelData
|
||||
import java.util.Random
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.util.Random
|
||||
* push-based partial rendering pipeline for [SpecialRenderModel] instances.
|
||||
*/
|
||||
abstract class RenderCtxBase(
|
||||
world: ILightReader,
|
||||
world: IBlockDisplayReader,
|
||||
pos: BlockPos,
|
||||
val matrixStack: MatrixStack,
|
||||
var checkSides: Boolean,
|
||||
@@ -36,14 +36,14 @@ abstract class RenderCtxBase(
|
||||
abstract fun renderQuad(quad: HalfBakedQuad)
|
||||
|
||||
var hasRendered = false
|
||||
val blockModelShapes = Minecraft.getInstance().blockRendererDispatcher.blockModelShapes
|
||||
val blockModelShapes = Minecraft.getInstance().blockRenderer.blockModelShaper
|
||||
var vertexLighter: VanillaVertexLighter = VanillaFullBlockLighting
|
||||
protected val lightingData = RenderCtxBase.lightingData.get().apply {
|
||||
calc.reset(this@RenderCtxBase)
|
||||
blockColors = Minecraft.getInstance().blockColors
|
||||
}
|
||||
|
||||
inline fun Direction?.shouldRender() = this == null || !checkSides || Block.shouldSideBeRendered(state, world, pos, this)
|
||||
inline fun Direction?.shouldRender() = this == null || !checkSides || Block.shouldRenderFace(state, world, pos, this)
|
||||
|
||||
fun renderQuads(quads: Iterable<HalfBakedQuad>) {
|
||||
quads.forEach { quad ->
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
package mods.betterfoliage.render.pipeline
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack
|
||||
import mods.betterfoliage.model.HalfBakedQuad
|
||||
import mods.betterfoliage.model.SpecialRenderModel
|
||||
import mods.betterfoliage.render.lighting.ForgeVertexLighter
|
||||
import mods.betterfoliage.render.lighting.ForgeVertexLighterAccess
|
||||
import mods.betterfoliage.model.HalfBakedQuad
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.client.renderer.LightTexture
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
import net.minecraftforge.client.model.data.IModelData
|
||||
import net.minecraftforge.client.model.pipeline.VertexLighterFlat
|
||||
import java.util.Random
|
||||
|
||||
class RenderCtxForge(
|
||||
world: ILightReader,
|
||||
world: IBlockDisplayReader,
|
||||
pos: BlockPos,
|
||||
val lighter: VertexLighterFlat,
|
||||
matrixStack: MatrixStack,
|
||||
@@ -33,8 +33,8 @@ class RenderCtxForge(
|
||||
var vIdx = 0
|
||||
override fun updateVertexLightmap(normal: FloatArray, lightmap: FloatArray, x: Float, y: Float, z: Float) {
|
||||
lightingData.packedLight[vIdx].let { packedLight ->
|
||||
lightmap[0] = LightTexture.getLightBlock(packedLight) / 0xF.toFloat()
|
||||
lightmap[1] = LightTexture.getLightSky(packedLight) / 0xF.toFloat()
|
||||
lightmap[0] = LightTexture.block(packedLight) / 0xF.toFloat()
|
||||
lightmap[1] = LightTexture.sky(packedLight) / 0xF.toFloat()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class RenderCtxForge(
|
||||
@JvmStatic
|
||||
fun render(
|
||||
lighter: VertexLighterFlat,
|
||||
world: ILightReader,
|
||||
world: IBlockDisplayReader,
|
||||
model: SpecialRenderModel,
|
||||
state: BlockState,
|
||||
pos: BlockPos,
|
||||
|
||||
@@ -2,18 +2,18 @@ package mods.betterfoliage.render.pipeline
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack
|
||||
import com.mojang.blaze3d.vertex.IVertexBuilder
|
||||
import mods.betterfoliage.model.SpecialRenderModel
|
||||
import mods.betterfoliage.model.HalfBakedQuad
|
||||
import mods.betterfoliage.model.SpecialRenderModel
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.client.renderer.BlockModelRenderer
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
import net.minecraftforge.client.model.data.IModelData
|
||||
import java.util.Random
|
||||
|
||||
class RenderCtxVanilla(
|
||||
val renderer: BlockModelRenderer,
|
||||
world: ILightReader,
|
||||
world: IBlockDisplayReader,
|
||||
pos: BlockPos,
|
||||
val buffer: IVertexBuilder,
|
||||
val combinedOverlay: Int,
|
||||
@@ -27,8 +27,8 @@ class RenderCtxVanilla(
|
||||
|
||||
override fun renderQuad(quad: HalfBakedQuad) {
|
||||
vertexLighter.updateLightmapAndColor(quad, lightingData)
|
||||
buffer.addQuad(
|
||||
matrixStack.last, quad.baked,
|
||||
buffer.putBulkData(
|
||||
matrixStack.last(), quad.baked,
|
||||
lightingData.colorMultiplier,
|
||||
lightingData.tint[0], lightingData.tint[1], lightingData.tint[2],
|
||||
lightingData.packedLight, combinedOverlay, true
|
||||
@@ -39,7 +39,7 @@ class RenderCtxVanilla(
|
||||
@JvmStatic
|
||||
fun render(
|
||||
renderer: BlockModelRenderer,
|
||||
world: ILightReader,
|
||||
world: IBlockDisplayReader,
|
||||
model: SpecialRenderModel,
|
||||
state: BlockState,
|
||||
pos: BlockPos,
|
||||
|
||||
Reference in New Issue
Block a user