138 lines
5.1 KiB
Kotlin
138 lines
5.1 KiB
Kotlin
package mods.betterfoliage.render
|
|
|
|
import mods.betterfoliage.config.Config
|
|
import mods.betterfoliage.render.old.AbstractEntityFX
|
|
import mods.betterfoliage.render.old.HSB
|
|
import mods.betterfoliage.util.Double3
|
|
import mods.betterfoliage.util.PI2
|
|
import mods.betterfoliage.util.minmax
|
|
import mods.betterfoliage.util.randomD
|
|
import net.minecraft.client.Minecraft
|
|
import net.minecraft.client.renderer.BufferBuilder
|
|
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 java.util.Random
|
|
import kotlin.math.abs
|
|
import kotlin.math.cos
|
|
import kotlin.math.sin
|
|
|
|
const val rotationFactor = PI2.toFloat() / 64.0f
|
|
|
|
class EntityFallingLeavesFX(
|
|
world: World, pos: BlockPos
|
|
) : AbstractEntityFX(
|
|
world, pos.x.toDouble() + 0.5, pos.y.toDouble(), pos.z.toDouble() + 0.5
|
|
) {
|
|
|
|
companion object {
|
|
@JvmStatic val biomeBrightnessMultiplier = 0.5f
|
|
}
|
|
|
|
var particleRot = rand.nextInt(64)
|
|
var rotPositive = true
|
|
val isMirrored = (rand.nextInt() and 1) == 1
|
|
var wasCollided = false
|
|
|
|
init {
|
|
maxAge = MathHelper.floor(randomD(0.6, 1.0) * Config.fallingLeaves.lifetime * 20.0)
|
|
motionY = -Config.fallingLeaves.speed
|
|
|
|
particleScale = Config.fallingLeaves.size.toFloat() * 0.1f
|
|
|
|
val state = world.getBlockState(pos)
|
|
// val leafInfo = LeafRegistry[state, world, pos]
|
|
val blockColor = Minecraft.getInstance().blockColors.getColor(state, world, pos, 0)
|
|
// if (leafInfo != null) {
|
|
// sprite = leafInfo.particleTextures[rand.nextInt(1024)]
|
|
// calculateParticleColor(leafInfo.averageColor, blockColor)
|
|
// } else {
|
|
// sprite = LeafParticleRegistry["default"][rand.nextInt(1024)]
|
|
// setColor(blockColor)
|
|
// }
|
|
}
|
|
|
|
override val isValid: Boolean get() = (sprite != null)
|
|
|
|
override fun update() {
|
|
if (rand.nextFloat() > 0.95f) rotPositive = !rotPositive
|
|
if (age > maxAge - 20) particleAlpha = 0.05f * (maxAge - age)
|
|
|
|
if (onGround || wasCollided) {
|
|
velocity.setTo(0.0, 0.0, 0.0)
|
|
if (!wasCollided) {
|
|
age = age.coerceAtLeast(maxAge - 20)
|
|
wasCollided = true
|
|
}
|
|
} else {
|
|
velocity.setTo(cos[particleRot], 0.0, sin[particleRot]).mul(Config.fallingLeaves.perturb)
|
|
.add(LeafWindTracker.current).add(0.0, -1.0, 0.0).mul(Config.fallingLeaves.speed)
|
|
particleRot = (particleRot + (if (rotPositive) 1 else -1)) and 63
|
|
particleAngle = rotationFactor * particleRot.toFloat()
|
|
}
|
|
}
|
|
|
|
override fun render(worldRenderer: BufferBuilder, partialTickTime: Float) {
|
|
// if (Config.fallingLeaves.opacityHack) GL11.glDepthMask(true)
|
|
// renderParticleQuad(worldRenderer, partialTickTime, rotation = particleRot, isMirrored = isMirrored)
|
|
}
|
|
|
|
fun calculateParticleColor(textureAvgColor: Int, blockColor: Int) {
|
|
val texture = HSB.fromColor(textureAvgColor)
|
|
val block = HSB.fromColor(blockColor)
|
|
|
|
val weightTex = texture.saturation / (texture.saturation + block.saturation)
|
|
val weightBlock = 1.0f - weightTex
|
|
|
|
// avoid circular average for hue for performance reasons
|
|
// one of the color components should dominate anyway
|
|
val particle = HSB(
|
|
weightTex * texture.hue + weightBlock * block.hue,
|
|
weightTex * texture.saturation + weightBlock * block.saturation,
|
|
weightTex * texture.brightness + weightBlock * block.brightness * biomeBrightnessMultiplier
|
|
)
|
|
setColor(particle.asColor)
|
|
}
|
|
}
|
|
|
|
object LeafWindTracker {
|
|
var random = Random()
|
|
val target = Double3.zero
|
|
val current = Double3.zero
|
|
var nextChange: Long = 0
|
|
|
|
init {
|
|
MinecraftForge.EVENT_BUS.register(this)
|
|
}
|
|
|
|
fun changeWind(world: World) {
|
|
nextChange = world.worldInfo.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)
|
|
target.setTo(cos(direction) * speed, 0.0, sin(direction) * speed)
|
|
}
|
|
|
|
@SubscribeEvent
|
|
fun handleWorldTick(event: TickEvent.ClientTickEvent) {
|
|
if (event.phase == TickEvent.Phase.START) Minecraft.getInstance().world?.let { world ->
|
|
// change target wind speed
|
|
if (world.worldInfo.dayTime >= nextChange) changeWind(world)
|
|
|
|
// change current wind speed
|
|
val changeRate = if (world.isRaining) 0.015 else 0.005
|
|
current.add(
|
|
(target.x - current.x).minmax(-changeRate, changeRate),
|
|
0.0,
|
|
(target.z - current.z).minmax(-changeRate, changeRate)
|
|
)
|
|
}
|
|
}
|
|
|
|
@SubscribeEvent
|
|
fun handleWorldLoad(event: WorldEvent.Load) { if (event.world.isRemote) changeWind(event.world.world) }
|
|
} |