smoke and lava particles

This commit is contained in:
Bixilon 2021-05-28 23:17:46 +02:00
parent 9af4f479a9
commit d1861a0679
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
12 changed files with 239 additions and 109 deletions

View File

@ -25,6 +25,10 @@ import de.bixilon.minosoft.data.player.Hands
import de.bixilon.minosoft.gui.rendering.input.camera.RaycastHit import de.bixilon.minosoft.gui.rendering.input.camera.RaycastHit
import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.CampfireSmokeParticle import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.CampfireSmokeParticle
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.fire.SmokeParticle
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.lava.LavaParticle
import de.bixilon.minosoft.gui.rendering.util.VecUtil.noise
import de.bixilon.minosoft.gui.rendering.util.VecUtil.verticalPlus
import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.util.KUtil.asResourceLocation import de.bixilon.minosoft.util.KUtil.asResourceLocation
import de.bixilon.minosoft.util.KUtil.chance import de.bixilon.minosoft.util.KUtil.chance
@ -34,8 +38,10 @@ import kotlin.random.Random
open class CampfireBlock(resourceLocation: ResourceLocation, registries: Registries, data: JsonObject) : Block(resourceLocation, registries, data) { open class CampfireBlock(resourceLocation: ResourceLocation, registries: Registries, data: JsonObject) : Block(resourceLocation, registries, data) {
private val campfireCrackleSoundEvent = registries.soundEventRegistry[CAMPFIRE_CRACKLE_SOUND_RESOURCE_LOCATION]!! private val campfireCrackleSoundEvent = registries.soundEventRegistry[CAMPFIRE_CRACKLE_SOUND_RESOURCE_LOCATION]!!
private val cosySmokeParticle = registries.particleTypeRegistry[CampfireSmokeParticle.CosySmokeParticleFactory]!! private val cosySmokeParticle = registries.particleTypeRegistry[CampfireSmokeParticle.CosyFactory]!!
private val signalSmokeParticle = registries.particleTypeRegistry[CampfireSmokeParticle.SignalSmokeParticleFactory]!! private val signalSmokeParticle = registries.particleTypeRegistry[CampfireSmokeParticle.SignalFactory]!!
private val lavaParticle = registries.particleTypeRegistry[LavaParticle]!!
private val smokeParticle = registries.particleTypeRegistry[SmokeParticle]!!
private fun extinguish(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i) { private fun extinguish(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i) {
val particleRenderer = connection.rendering?.renderWindow?.get(ParticleRenderer) ?: return val particleRenderer = connection.rendering?.renderWindow?.get(ParticleRenderer) ?: return
@ -45,24 +51,29 @@ open class CampfireBlock(resourceLocation: ResourceLocation, registries: Registr
} }
fun spawnSmokeParticles(connection: PlayConnection, particleRenderer: ParticleRenderer, blockState: BlockState, blockPosition: Vec3i, extinguished: Boolean) { fun spawnSmokeParticles(connection: PlayConnection, particleRenderer: ParticleRenderer, blockState: BlockState, blockPosition: Vec3i, extinguished: Boolean) {
val horizontal = { 0.5f + Random.nextFloat() / 3.0f * if (Random.nextBoolean()) 1.0f else -1.0f } let {
val position = Vec3( val position = Vec3(blockPosition).verticalPlus(
blockPosition.x + horizontal(), { 0.5f + 3.0f.noise },
blockPosition.y + Random.nextFloat() + Random.nextFloat(), Random.nextFloat() + Random.nextFloat() + 0.5f // ToDo: This +0.5f is a temporary fix for not making the particle stuck in ourself
blockPosition.z + horizontal() )
)
val isSignal = blockState.properties[BlockProperties.CAMPFIRE_SIGNAL_FIRE] == true
val particleType = if (isSignal) { val isSignal = blockState.properties[BlockProperties.CAMPFIRE_SIGNAL_FIRE] == true
signalSmokeParticle
} else { val particleType = if (isSignal) {
cosySmokeParticle signalSmokeParticle
} else {
cosySmokeParticle
}
particleRenderer.add(CampfireSmokeParticle(connection, particleRenderer, position, Vec3(0.0f, 0.07f, 0.0f), particleType.simple(), isSignal))
} }
particleRenderer.add(CampfireSmokeParticle(connection, particleRenderer, position, Vec3(0.0f, 0.07f, 0.0f), particleType.simple(), isSignal))
if (extinguished) { if (extinguished) {
// ToDo: Spawn smoke particles val position = Vec3(blockPosition).verticalPlus(
{ 0.5f + 4.0f.noise },
0.5f
)
particleRenderer.add(SmokeParticle(connection, particleRenderer, position, Vec3(0.0f, 0.005f, 0.0f), smokeParticle.simple()))
} }
} }
@ -74,7 +85,13 @@ open class CampfireBlock(resourceLocation: ResourceLocation, registries: Registr
if (random.chance(10)) { if (random.chance(10)) {
connection.rendering?.audioPlayer?.playSoundEvent(campfireCrackleSoundEvent, blockPosition + Vec3(0.5f), 0.5f + random.nextFloat(), 0.6f + random.nextFloat() * 0.7f) connection.rendering?.audioPlayer?.playSoundEvent(campfireCrackleSoundEvent, blockPosition + Vec3(0.5f), 0.5f + random.nextFloat(), 0.6f + random.nextFloat() * 0.7f)
} }
// ToDo: Spawn Lava particles
if (random.chance(20)) {
val position = Vec3(blockPosition) + Vec3(0.5f)
for (i in 0 until random.nextInt(1) + 1) {
particleRenderer.add(LavaParticle(connection, particleRenderer, position, lavaParticle.simple()))
}
}
} }
override fun onUse(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages { override fun onUse(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack?): BlockUsages {

View File

@ -14,7 +14,7 @@
package de.bixilon.minosoft.gui.rendering.particle package de.bixilon.minosoft.gui.rendering.particle
import de.bixilon.minosoft.gui.rendering.particle.types.norender.ExplosionEmitterParticle import de.bixilon.minosoft.gui.rendering.particle.types.norender.ExplosionEmitterParticle
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.ExplosionLargeParticle import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.ExplosionParticle
import de.bixilon.minosoft.gui.rendering.util.VecUtil.times import de.bixilon.minosoft.gui.rendering.util.VecUtil.times
import de.bixilon.minosoft.modding.event.CallbackEventInvoker import de.bixilon.minosoft.modding.event.CallbackEventInvoker
import de.bixilon.minosoft.modding.event.events.ExplosionEvent import de.bixilon.minosoft.modding.event.events.ExplosionEvent
@ -29,14 +29,14 @@ object DefaultParticleBehavior {
fun register(connection: PlayConnection, particleRenderer: ParticleRenderer) { fun register(connection: PlayConnection, particleRenderer: ParticleRenderer) {
val random = java.util.Random() val random = java.util.Random()
val explosionParticleType = connection.registries.particleTypeRegistry[ExplosionLargeParticle]!! val explosionParticleType = connection.registries.particleTypeRegistry[ExplosionParticle]!!
val explosionEmitterParticleType = connection.registries.particleTypeRegistry[ExplosionEmitterParticle]!! val explosionEmitterParticleType = connection.registries.particleTypeRegistry[ExplosionEmitterParticle]!!
val invokers = listOf( val invokers = listOf(
CallbackEventInvoker.of<ExplosionEvent> { CallbackEventInvoker.of<ExplosionEvent> {
if (it.power >= 2.0f) { if (it.power >= 2.0f) {
particleRenderer.add(ExplosionEmitterParticle(connection, particleRenderer, it.position, explosionEmitterParticleType.simple())) particleRenderer.add(ExplosionEmitterParticle(connection, particleRenderer, it.position, explosionEmitterParticleType.simple()))
} else { } else {
particleRenderer.add(ExplosionLargeParticle(connection, particleRenderer, it.position, explosionParticleType.simple())) particleRenderer.add(ExplosionParticle(connection, particleRenderer, it.position, explosionParticleType.simple()))
} }
}, },
CallbackEventInvoker.of<ParticleSpawnEvent> { CallbackEventInvoker.of<ParticleSpawnEvent> {

View File

@ -17,11 +17,15 @@ import de.bixilon.minosoft.data.mappings.DefaultFactory
import de.bixilon.minosoft.gui.rendering.particle.types.Particle import de.bixilon.minosoft.gui.rendering.particle.types.Particle
import de.bixilon.minosoft.gui.rendering.particle.types.norender.ExplosionEmitterParticle import de.bixilon.minosoft.gui.rendering.particle.types.norender.ExplosionEmitterParticle
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.CampfireSmokeParticle import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.CampfireSmokeParticle
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.ExplosionLargeParticle import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.ExplosionParticle
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.fire.SmokeParticle
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.lava.LavaParticle
object DefaultParticleFactory : DefaultFactory<ParticleFactory<out Particle>>( object DefaultParticleFactory : DefaultFactory<ParticleFactory<out Particle>>(
ExplosionEmitterParticle, ExplosionEmitterParticle,
ExplosionLargeParticle, ExplosionParticle,
CampfireSmokeParticle.CosySmokeParticleFactory, CampfireSmokeParticle.CosyFactory,
CampfireSmokeParticle.SignalSmokeParticleFactory, CampfireSmokeParticle.SignalFactory,
LavaParticle,
SmokeParticle,
) )

View File

@ -25,7 +25,6 @@ import de.bixilon.minosoft.gui.rendering.util.VecUtil.plusAssign
import de.bixilon.minosoft.gui.rendering.util.VecUtil.sqr import de.bixilon.minosoft.gui.rendering.util.VecUtil.sqr
import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.KUtil.millis
import glm_.vec3.Vec3 import glm_.vec3.Vec3
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.sqrt import kotlin.math.sqrt
@ -45,7 +44,9 @@ abstract class Particle(
var dead = false var dead = false
var age: Int = 0 var age: Int = 0
protected set protected set
var maxAge: Int = (4.0f / (random.nextFloat() * 0.9f + 0.1f)).millis val floatAge: Float
get() = age.toFloat()
var maxAge: Int = (4.0f / (random.nextFloat() * 0.9f + 0.1f)).toInt()
// moving // moving
var previousPosition = position var previousPosition = position
@ -62,6 +63,7 @@ abstract class Particle(
var spacing: Vec3 = Vec3.EMPTY var spacing: Vec3 = Vec3.EMPTY
set(value) { set(value) {
if (field == value) { if (field == value) {
return
} }
field = value field = value
@ -113,8 +115,6 @@ abstract class Particle(
} }
previousPosition = Vec3(position) previousPosition = Vec3(position)
velocity.y -= (0.04f * gravityStrength).millis
move(velocity.millis * (deltaTime / 1000.0f)) move(velocity.millis * (deltaTime / 1000.0f))
} }
@ -144,10 +144,8 @@ abstract class Particle(
lastTickTime = currentTime lastTickTime = currentTime
} }
protected fun age(deltaTime: Int) { protected fun age() {
age += deltaTime if (age++ >= maxAge) {
if (age >= maxAge) {
dead = true dead = true
} }
} }
@ -155,11 +153,6 @@ abstract class Particle(
open fun tick(deltaTime: Int) { open fun tick(deltaTime: Int) {
check(!dead) { "Cannot tick dead particle!" } check(!dead) { "Cannot tick dead particle!" }
check(deltaTime >= 0) check(deltaTime >= 0)
age(deltaTime)
if (dead) {
return
}
} }
open fun postTick(deltaTime: Int) { open fun postTick(deltaTime: Int) {
@ -170,6 +163,12 @@ abstract class Particle(
if (!movement) { if (!movement) {
return return
} }
age()
if (dead) {
return
}
velocity.y -= 0.04f * gravityStrength
if (accelerateIfYBlocked && position.y == previousPosition.y) { if (accelerateIfYBlocked && position.y == previousPosition.y) {
velocity.x *= 1.1f velocity.x *= 1.1f
@ -180,7 +179,7 @@ abstract class Particle(
if (onGround) { if (onGround) {
velocity.x *= 0.699999988079071f velocity.x *= 0.699999988079071f
velocity.y *= 0.699999988079071f velocity.z *= 0.699999988079071f
} }
} }

View File

@ -17,7 +17,7 @@ import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.particle.data.ParticleData import de.bixilon.minosoft.data.mappings.particle.data.ParticleData
import de.bixilon.minosoft.gui.rendering.particle.ParticleFactory import de.bixilon.minosoft.gui.rendering.particle.ParticleFactory
import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.ExplosionLargeParticle import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.ExplosionParticle
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus
import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.protocol.network.connection.PlayConnection
@ -25,30 +25,25 @@ import de.bixilon.minosoft.util.KUtil.asResourceLocation
import glm_.vec3.Vec3 import glm_.vec3.Vec3
class ExplosionEmitterParticle(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, data: ParticleData) : NoRenderParticle(connection, particleRenderer, position, Vec3.EMPTY, data) { class ExplosionEmitterParticle(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, data: ParticleData) : NoRenderParticle(connection, particleRenderer, position, Vec3.EMPTY, data) {
private val explosionParticleType = connection.registries.particleTypeRegistry[ExplosionLargeParticle]!! private val explosionParticleType = connection.registries.particleTypeRegistry[ExplosionParticle]!!
init { init {
maxAge = Int.MAX_VALUE maxAge = MAX_AGE
movement = false movement = false
} }
private var ticks = 0
override fun realTick() { override fun realTick() {
super.realTick() super.realTick()
for (i in 0 until 6) { for (i in 0 until 6) {
val position = position + { (random.nextFloat() - random.nextFloat()) * 4.0f } val position = position + { (random.nextFloat() - random.nextFloat()) * 4.0f }
particleRenderer.add(ExplosionLargeParticle(connection, particleRenderer, position, explosionParticleType.simple(), (ticks.toFloat() / MAX_AGE))) particleRenderer.add(ExplosionParticle(connection, particleRenderer, position, explosionParticleType.simple(), floatAge / MAX_AGE))
}
if (ticks == MAX_AGE) {
dead = true
} }
} }
companion object : ParticleFactory<ExplosionEmitterParticle> { companion object : ParticleFactory<ExplosionEmitterParticle> {
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:explosion_emitter".asResourceLocation() override val RESOURCE_LOCATION: ResourceLocation = "minecraft:explosion_emitter".asResourceLocation()
private const val MAX_AGE = 8 private const val MAX_AGE = 9
override fun build(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData): ExplosionEmitterParticle { override fun build(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData): ExplosionEmitterParticle {
return ExplosionEmitterParticle(connection, particleRenderer, position, data) return ExplosionEmitterParticle(connection, particleRenderer, position, data)

View File

@ -20,55 +20,8 @@ import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer
import de.bixilon.minosoft.gui.rendering.particle.types.Particle import de.bixilon.minosoft.gui.rendering.particle.types.Particle
import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import glm_.vec3.Vec3 import glm_.vec3.Vec3
import kotlin.math.abs
abstract class RenderParticle(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData) : Particle(connection, particleRenderer, position, velocity, data) { abstract class RenderParticle(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData) : Particle(connection, particleRenderer, position, velocity, data) {
protected var scale: Float = 0.1f * (random.nextFloat() * 0.5f + 0.5f) * 2.0f protected open var scale: Float = 0.1f * (random.nextFloat() * 0.5f + 0.5f) * 2.0f
protected var color: RGBColor = ChatColors.WHITE protected var color: RGBColor = ChatColors.WHITE
// growing
protected var nextScale: Float = scale
protected var scalePerMillisecond = Float.NEGATIVE_INFINITY
override fun tick(deltaTime: Int) {
super.tick(deltaTime)
if (dead) {
return
}
grow(deltaTime)
}
fun grow(scale: Float, time: Long) {
nextScale = scale
scalePerMillisecond = (scale - this.scale) / time
}
private fun grow(deltaTime: Int) {
if (scalePerMillisecond == Float.NEGATIVE_INFINITY) {
return
}
val deltaScale = nextScale - scale
if (abs(deltaScale) > GROW_LOWER_LIMIT) {
// we need to grow
val scaleAdd = scalePerMillisecond * deltaTime
// checke if the delta gets bigger (aka. we'd grew to much)
val nextScale = scale + scaleAdd
if (abs(this.nextScale - nextScale) > deltaScale) {
// abort scaling and avoid getting called another time
scale = nextScale
scalePerMillisecond = Float.NEGATIVE_INFINITY
return
}
// we can grow
scale = nextScale
}
}
companion object {
const val GROW_LOWER_LIMIT = 0.001f
}
} }

View File

@ -0,0 +1,55 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple
import de.bixilon.minosoft.data.mappings.particle.data.ParticleData
import de.bixilon.minosoft.data.text.RGBColor.Companion.asGray
import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.util.MMath
import glm_.vec3.Vec3
abstract class AscendingParticle(
connection: PlayConnection,
particleRenderer: ParticleRenderer,
position: Vec3,
velocity: Vec3,
velocityMultiplier: Vec3,
scaleMultiplier: Float,
colorMultiplier: Float,
baseAge: Int,
gravityStrength: Float,
physics: Boolean,
data: ParticleData,
) : SimpleTextureParticle(connection, particleRenderer, position, Vec3.EMPTY, data) {
override var scale: Float
get() = super.scale * MMath.clamp(floatAge / maxAge * 32.0f, 0.0f, 1.0f)
set(value) {
super.scale = value
}
init {
friction = 0.96f
this.gravityStrength = gravityStrength
accelerateIfYBlocked = true
this.velocity *= velocityMultiplier
this.velocity += velocity
color = (random.nextFloat() * colorMultiplier).asGray()
super.scale *= 0.75f * scaleMultiplier
super.maxAge = ((baseAge.toFloat() / (random.nextFloat() * 0.8f + 0.2f)).toInt() * scaleMultiplier).toInt().coerceAtLeast(1)
this.physics = physics
}
}

View File

@ -22,7 +22,6 @@ import de.bixilon.minosoft.gui.rendering.util.VecUtil.assign
import de.bixilon.minosoft.gui.rendering.util.VecUtil.millis import de.bixilon.minosoft.gui.rendering.util.VecUtil.millis
import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.util.KUtil.asResourceLocation import de.bixilon.minosoft.util.KUtil.asResourceLocation
import de.bixilon.minosoft.util.KUtil.millis
import glm_.vec3.Vec3 import glm_.vec3.Vec3
class CampfireSmokeParticle(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData, signal: Boolean) : SimpleTextureParticle(connection, particleRenderer, position, Vec3.EMPTY, data) { class CampfireSmokeParticle(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData, signal: Boolean) : SimpleTextureParticle(connection, particleRenderer, position, Vec3.EMPTY, data) {
@ -30,12 +29,12 @@ class CampfireSmokeParticle(connection: PlayConnection, particleRenderer: Partic
init { init {
scale *= 3.0f scale *= 3.0f
spacing = Vec3(0.25f) spacing = Vec3(0.25f)
maxAge = random.nextInt(50).millis maxAge = random.nextInt(50)
if (signal) { if (signal) {
maxAge += 280.millis maxAge += 280
color = color.with(alpha = 0.95f) color = color.with(alpha = 0.95f)
} else { } else {
maxAge += 80.millis maxAge += 80
color = color.with(alpha = 0.90f) color = color.with(alpha = 0.90f)
} }
@ -54,7 +53,7 @@ class CampfireSmokeParticle(connection: PlayConnection, particleRenderer: Partic
velocity.y -= gravityStrength velocity.y -= gravityStrength
velocity.z += horizontal() velocity.z += horizontal()
if (age >= maxAge - 60.millis) { if (age >= maxAge - 60) {
color = color.with(alpha = color.floatAlpha - 0.015f) color = color.with(alpha = color.floatAlpha - 0.015f)
} }
if (color.alpha == 0) { if (color.alpha == 0) {
@ -68,7 +67,7 @@ class CampfireSmokeParticle(connection: PlayConnection, particleRenderer: Partic
} }
object CosySmokeParticleFactory : ParticleFactory<CampfireSmokeParticle> { object CosyFactory : ParticleFactory<CampfireSmokeParticle> {
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:campfire_cosy_smoke".asResourceLocation() override val RESOURCE_LOCATION: ResourceLocation = "minecraft:campfire_cosy_smoke".asResourceLocation()
override fun build(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData): CampfireSmokeParticle { override fun build(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData): CampfireSmokeParticle {
@ -77,7 +76,7 @@ class CampfireSmokeParticle(connection: PlayConnection, particleRenderer: Partic
} }
object SignalSmokeParticleFactory : ParticleFactory<CampfireSmokeParticle> { object SignalFactory : ParticleFactory<CampfireSmokeParticle> {
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:campfire_signal_smoke".asResourceLocation() override val RESOURCE_LOCATION: ResourceLocation = "minecraft:campfire_signal_smoke".asResourceLocation()
override fun build(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData): CampfireSmokeParticle { override fun build(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData): CampfireSmokeParticle {

View File

@ -21,24 +21,23 @@ import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.util.KUtil.asResourceLocation import de.bixilon.minosoft.util.KUtil.asResourceLocation
import de.bixilon.minosoft.util.KUtil.millis
import glm_.vec3.Vec3 import glm_.vec3.Vec3
class ExplosionLargeParticle(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, data: ParticleData, power: Float = 1.0f) : SimpleTextureParticle(connection, particleRenderer, position, Vec3.EMPTY, data) { class ExplosionParticle(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, data: ParticleData, power: Float = 1.0f) : SimpleTextureParticle(connection, particleRenderer, position, Vec3.EMPTY, data) {
init { init {
movement = false movement = false
maxAge = (6 + random.nextInt(4)).millis maxAge = 6 + random.nextInt(4)
val gray = random.nextFloat() * 0.6f + 0.4f val gray = random.nextFloat() * 0.6f + 0.4f
color = gray.asGray() color = gray.asGray()
scale = 2.0f * (power - gray * 0.5f) scale = 2.0f * (power - gray * 0.5f)
} }
companion object : ParticleFactory<ExplosionLargeParticle> { companion object : ParticleFactory<ExplosionParticle> {
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:explosion".asResourceLocation() override val RESOURCE_LOCATION: ResourceLocation = "minecraft:explosion".asResourceLocation()
override fun build(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData): ExplosionLargeParticle { override fun build(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData): ExplosionParticle {
return ExplosionLargeParticle(connection, particleRenderer, position, data, velocity.x) return ExplosionParticle(connection, particleRenderer, position, data, velocity.x)
} }
} }
} }

View File

@ -0,0 +1,35 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.fire
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.particle.data.ParticleData
import de.bixilon.minosoft.gui.rendering.particle.ParticleFactory
import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.AscendingParticle
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.util.KUtil.asResourceLocation
import glm_.vec3.Vec3
class SmokeParticle(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData, scaleMultiplier: Float = 1.0f) : AscendingParticle(connection, particleRenderer, position, velocity, Vec3(0.1f), scaleMultiplier, 0.3f, 8, -0.1f, true, data) {
companion object : ParticleFactory<SmokeParticle> {
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:smoke".asResourceLocation()
override fun build(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData): SmokeParticle {
return SmokeParticle(connection, particleRenderer, position, velocity, data)
}
}
}

View File

@ -0,0 +1,62 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.lava
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.particle.data.ParticleData
import de.bixilon.minosoft.gui.rendering.particle.ParticleFactory
import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.SimpleTextureParticle
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.fire.SmokeParticle
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import de.bixilon.minosoft.gui.rendering.util.VecUtil.sqr
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.util.KUtil.asResourceLocation
import glm_.vec3.Vec3
class LavaParticle(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, data: ParticleData) : SimpleTextureParticle(connection, particleRenderer, position, Vec3.EMPTY, data) {
private val smokeParticleType = connection.registries.particleTypeRegistry[SmokeParticle]!!
override var scale: Float
get() = super.scale * (1.0f - (floatAge / maxAge).sqr)
set(value) {
super.scale = value
}
init {
gravityStrength = 0.75f
friction = 0.999f
velocity.x *= 0.800000011920929f
velocity.y = random.nextFloat() * 0.4f + 0.05f
velocity.z *= 0.800000011920929f
scale *= random.nextFloat() * 2.0f + 0.2f
maxAge = (16.0f / (random.nextFloat() * 0.8f + 0.2f)).toInt()
}
override fun realTick() {
super.realTick()
if (random.nextFloat() > (floatAge / maxAge)) {
particleRenderer.add(SmokeParticle(connection, particleRenderer, Vec3(position), Vec3(velocity), smokeParticleType.simple()))
}
}
companion object : ParticleFactory<LavaParticle> {
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:lava".asResourceLocation()
override fun build(connection: PlayConnection, particleRenderer: ParticleRenderer, position: Vec3, velocity: Vec3, data: ParticleData): LavaParticle {
return LavaParticle(connection, particleRenderer, position, data)
}
}
}

View File

@ -35,6 +35,7 @@ import glm_.vec2.Vec2
import glm_.vec2.Vec2i import glm_.vec2.Vec2i
import glm_.vec3.Vec3 import glm_.vec3.Vec3
import glm_.vec3.Vec3i import glm_.vec3.Vec3i
import kotlin.random.Random
object VecUtil { object VecUtil {
val Vec3.Companion.EMPTY: Vec3 val Vec3.Companion.EMPTY: Vec3
@ -351,4 +352,15 @@ object VecUtil {
Axes.Z -> this.z Axes.Z -> this.z
} }
} }
fun Vec3.Companion.vertical(xz: () -> Float, y: Float): Vec3 {
return Vec3(xz(), y, xz())
}
fun Vec3.verticalPlus(xz: () -> Float, y: Float): Vec3 {
return Vec3(this.x + xz(), this.y + y, this.z + xz())
}
val Float.noise: Float
get() = Random.nextFloat() / this * if (Random.nextBoolean()) 1.0f else -1.0f
} }