From 46498d25f450d10d863ef3f80a5d6c75d993c725 Mon Sep 17 00:00:00 2001 From: Byte Dice Date: Thu, 26 Dec 2024 16:34:19 +0100 Subject: [PATCH] added emitter debug tools. More testing required before 1.0! --- .../bytedice/bde_particles/Bde_particles.kt | 4 - .../bde_particles/particles/EmitterDebug.kt | 120 +++++++++++++----- .../bde_particles/particles/EmitterParams.kt | 2 +- .../bde_particles/particles/ParamClasses.kt | 12 +- .../bde_particles/particles/Particle.kt | 11 +- .../bde_particles/particles/ParticleDebug.kt | 4 +- .../particles/ParticleEmitter.kt | 29 +++-- 7 files changed, 130 insertions(+), 52 deletions(-) diff --git a/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt b/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt index 82bbef8..fe5b069 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt @@ -53,10 +53,6 @@ import kotlin.reflect.full.declaredMemberProperties // Custom curve equation command args (parse from strings). // Force field "config" option. -// TODO: (now) -// Better particle debug tools. - // Use more BDEs instead of particles, and show more values than origin and velocity. - var ALL_PARTICLE_EMITTERS: Array = emptyArray() var LIVING_PARTICLE_COUNT: Int = 0 diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterDebug.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterDebug.kt index 20db94b..88d03a3 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterDebug.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterDebug.kt @@ -3,6 +3,7 @@ package com.bytedice.bde_particles.particles import com.bytedice.bde_particles.Billboard import com.bytedice.bde_particles.DisplayEntity import com.bytedice.bde_particles.DisplayEntityProperties +import com.bytedice.bde_particles.SESSION_UUID import net.minecraft.server.world.ServerWorld import net.minecraft.util.math.Vec3d import org.joml.Vector2f @@ -14,26 +15,31 @@ class EmitterDebug( eOrigin: Vec3d, spawnPosOffset: Vector3f, shape: SpawningShape, - forceFields: ParamClasses.ForceFieldArray ) { - private val eOrigin = EOrigin(rot, eOrigin) - private val shapeDebug = ShapeDebug(rot, eOrigin, spawnPosOffset, shape) + private val eOriginDebug = EOrigin(rot, eOrigin) + private val shapeDebug = ShapeDebug(eOrigin, spawnPosOffset, shape) + private val forceFieldDebug = ForceFieldDebug() - fun spawn(world: ServerWorld) { - eOrigin.spawn(world) + fun spawn(world: ServerWorld, eOrigin: Vec3d, forceFields: ParamClasses.ForceFieldArray, spawnPosOffset: Vector3f) { + eOriginDebug.spawn(world) shapeDebug.spawn(world) + forceFieldDebug.makeArray(eOrigin, forceFields, spawnPosOffset) + forceFieldDebug.spawn(world) } fun update( rot: Vector2f, eOrigin: Vec3d, - pOrigin: Vector3f, - pVel: Vector3f, - pScale: Vector3f, - spawnPosOffset: Vector3f, - shape: SpawningShape, + spawnPosOffset: Vector3f ) { + eOriginDebug.update(rot, eOrigin) + shapeDebug.update(rot, eOrigin, spawnPosOffset) + } + fun kill() { + eOriginDebug.kill() + shapeDebug.kill() + forceFieldDebug.kill() } } @@ -44,11 +50,10 @@ class EOrigin(rot: Vector2f, eOrigin: Vec3d) { pos = eOrigin, rot = rot, model = "minecraft:red_concrete", - tags = arrayOf("DEBUG", "E_DEBUG", "eOrigin_DEBUG"), + tags = arrayOf("DEBUG", "E_DEBUG", "eOrigin_DEBUG", "BPS_UUID", SESSION_UUID.toString()), brightnessOverride = 15, scale = Vector3f(0.25f, 0.25f, 0.25f) - ) - ) + )) fun spawn(world: ServerWorld) { eOriginDE.spawn(world) @@ -61,36 +66,52 @@ class EOrigin(rot: Vector2f, eOrigin: Vec3d) { eOriginDE.updateProperties(newProperties!!) } + + fun kill() { + eOriginDE.kill() + } } -class ShapeDebug(rot: Vector2f, eOrigin: Vec3d, spawnPosOffset: Vector3f, shape: SpawningShape) { +class ShapeDebug(eOrigin: Vec3d, spawnPosOffset: Vector3f, shape: SpawningShape) { val shapeScale: Vector3f? = when (shape) { - is SpawningShape.Circle -> Vector3f(shape.radius * 1.75f, shape.radius * 1.75f, 0.0f) - is SpawningShape.Sphere -> Vector3f(shape.radius * 1.75f, shape.radius * 1.75f, 0.0f) - is SpawningShape.Rect -> Vector3f(shape.size.x, 0.0f, shape.size.y) - is SpawningShape.Cube -> Vector3f(shape.size.x, shape.size.y, shape.size.z) + is SpawningShape.Circle -> Vector3f(shape.radius * 1.75f * 2, shape.radius * 1.75f * 2, 0.0001f) + is SpawningShape.Sphere -> Vector3f(shape.radius * 1.75f * 2, shape.radius * 1.75f * 2, 0.0001f) + is SpawningShape.Rect -> Vector3f(shape.size.x, 0.0001f, shape.size.y) + is SpawningShape.Cube -> Vector3f(shape.size.x, shape.size.y, shape.size.z) else -> null } - val shapeRot = if (shape is SpawningShape.Circle) { Vector4f(-0.707f, 0.0f, 0.0f, 0.707f) } - else { Vector4f(0.0f, 0.0f, 0.0f, 1.0f) } + val shapeRot = when (shape) { + is SpawningShape.Circle -> Vector4f(-0.707f, 0.0f, 0.0f, 0.707f) + else -> Vector4f(0.0f, 0.0f, 0.0f, 1.0f) + } + private fun determineModel(shape: SpawningShape): String = + when (shape) { + is SpawningShape.Circle, is SpawningShape.Sphere -> "minecraft:sunflower" + else -> "minecraft:yellow_stained_glass" + } + + private fun determineBillboard(shape: SpawningShape): String = + if (shape !is SpawningShape.Sphere) Billboard.FIXED else Billboard.CENTER val shapeDE: DisplayEntity? = if (shape !is SpawningShape.Point) { + val position = eOrigin.add( + spawnPosOffset.x.toDouble(), + spawnPosOffset.y.toDouble(), + spawnPosOffset.z.toDouble() + ) + DisplayEntity(DisplayEntityProperties( - pos = eOrigin.add(spawnPosOffset.x.toDouble(), spawnPosOffset.y.toDouble(), spawnPosOffset.z.toDouble()), - rot = rot, - model = if (shape is SpawningShape.Circle || shape is SpawningShape.Sphere) { "minecraft:sunflower" } - else { "minecraft:yellow_stained_glass" }, - tags = arrayOf("DEBUG", "P_DEBUG", "shape_DEBUG"), + pos = position.add(spawnPosOffset.x.toDouble(), spawnPosOffset.y.toDouble(), spawnPosOffset.z.toDouble()), + model = determineModel(shape), + tags = arrayOf("DEBUG", "P_DEBUG", "shape_DEBUG", "BPS_UUID", SESSION_UUID.toString()), brightnessOverride = 15, - billboard = if (shape !is SpawningShape.Sphere) { Billboard.FIXED } else { Billboard.CENTER }, - translation = spawnPosOffset, + billboard = determineBillboard(shape), leftRotation = shapeRot, - scale = shapeScale!! + scale = shapeScale ?: Vector3f(1f, 1f, 1f) )) - } - else { null } + } else null fun spawn(world: ServerWorld) { shapeDE?.spawn(world) @@ -104,4 +125,43 @@ class ShapeDebug(rot: Vector2f, eOrigin: Vec3d, spawnPosOffset: Vector3f, shape: shapeDE?.updateProperties(newProperties!!) } + + fun kill() { + shapeDE?.kill() + } +} + +class ForceFieldDebug { + var FFDEArray: Array = emptyArray() + + fun makeArray(eOrigin: Vec3d, forceFieldArray: ParamClasses.ForceFieldArray, spawnPosOffset: Vector3f) { + forceFieldArray.array.forEach { + val shapeScale = when (it.shape) { + is ForceFieldShape.Sphere -> Vector3f(1.333f * it.shape.radius * 2, 1.333f * it.shape.radius * 2, 0.0001f) + is ForceFieldShape.Cube -> it.shape.size + } + + val newOffset = Vector3f(spawnPosOffset).add(it.pos) + + val displayEntity = DisplayEntity( + DisplayEntityProperties( + pos = eOrigin.add(newOffset.x.toDouble(), newOffset.y.toDouble(), newOffset.z.toDouble()), + model = if (it.shape is ForceFieldShape.Sphere) { "minecraft:snowball" } else { "minecraft:white_stained_glass" }, + tags = arrayOf("DEBUG", "E_DEBUG", "eOrigin_DEBUG", "BPS_UUID", SESSION_UUID.toString()), + brightnessOverride = 15, + billboard = if (it.shape is ForceFieldShape.Sphere) { Billboard.CENTER } else { Billboard.FIXED }, + scale = shapeScale + )) + + FFDEArray += displayEntity + } + } + + fun spawn(world: ServerWorld) { + FFDEArray.forEach { it.spawn(world) } + } + + fun kill() { + FFDEArray.forEach { it.kill() } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt index 6fbc636..1cd7e21 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt @@ -126,7 +126,7 @@ data class EmitterParams ( ForceFieldShape.Sphere(15.0f, Pair(0.1f, 0.2f)) )) ), - constVel = Vector3f(0.0f, 0.001f, 0.0f), + constVel = Vector3f(0.0f, 0.00001f, 0.0f), drag = 0.075f, minVel = 0.0f, offsetCurve = ParamClasses.LerpValVec3f.Null, diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/ParamClasses.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/ParamClasses.kt index 8442cb7..2e1e243 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/ParamClasses.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/ParamClasses.kt @@ -43,14 +43,22 @@ class ParamClasses { private val min: Int, private val max: Int, ) { - fun randomize() : Int { return randomIntBetween(min, max) } + fun randomize() : Int { + return if (min == max) { max } + else if (min > max) { max } + else { randomIntBetween(min, max) } + } } class PairFloat( private val min: Float, private val max: Float, ) { - fun randomize() : Float { return randomFloatBetween(min, max) } + fun randomize() : Float { + return if (min == max) { max } + else if (min > max) { max } + else { randomFloatBetween(min, max) } + } } sealed class LerpValVec3f { diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/Particle.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/Particle.kt index a175479..58d0bb8 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/Particle.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/Particle.kt @@ -60,8 +60,10 @@ class Particle( fun init() { - val so = emitterParams.spawnPosOffset - entityPos = entityPos.add(so.x.toDouble(), so.y.toDouble(), so.z.toDouble()) + val so = Vector3f(emitterParams.spawnPosOffset) + if (so.x + so.y + so.z != 0.0f) { + entityPos = entityPos.add(so.x.toDouble(), so.y.toDouble(), so.z.toDouble()) + } val shape = emitterParams.shape val newSpawnPos = shape.random(shape) @@ -222,7 +224,10 @@ class Particle( private fun calcPos() : Pair { var vel = Vector3f(vel) - vel = vel.add(emitterParams.constVel) + val constVel = emitterParams.constVel + if (constVel.x + constVel.y + constVel.z != 0.0f) { + vel = vel.add(emitterParams.constVel) + } vel = vel.mul(1.0f - emitterParams.drag) if (abs(vel.x) < emitterParams.minVel) { vel.x = 0.0f } diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleDebug.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleDebug.kt index f334928..45b4ddc 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleDebug.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleDebug.kt @@ -49,7 +49,7 @@ class POrigin(rot: Vector2f, eOrigin: Vec3d, pOrigin: Vector3f) { pos = eOrigin, rot = rot, model = "minecraft:lime_concrete", - tags = arrayOf("DEBUG", "P_DEBUG", "pOrigin_DEBUG"), + tags = arrayOf("DEBUG", "P_DEBUG", "pOrigin_DEBUG", "BPS_UUID", SESSION_UUID.toString()), brightnessOverride = 15, translation = Vector3f(pOrigin), scale = Vector3f(0.15f, 0.15f, 0.15f) @@ -78,7 +78,7 @@ class PVel(rot: Vector2f, eOrigin: Vec3d, pOrigin: Vector3f, pVel: Vector3f, pSc pos = eOrigin, rot = rot, model = "minecraft:red_nether_brick_slab", //"minecraft:red_stained_glass", - tags = arrayOf("DEBUG", "P_DEBUG", "pVel_DEBUG"), + tags = arrayOf("DEBUG", "P_DEBUG", "pVel_DEBUG", "BPS_UUID", SESSION_UUID.toString()), brightnessOverride = 15, translation = Vector3f(pOrigin), scale = Vector3f(0.05f, max(max(pScale.x, pScale.y), pScale.z) + (pVel.x + pVel.y + pVel.z), 0.05f) diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt index b85a4b4..eed4a8b 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt @@ -20,6 +20,7 @@ class ParticleEmitter( private var allParticles: Array = emptyArray() private var timeAlive = 0 + private var timeEmitted = 0 private var timePaused = 0 private var timesLooped = 0 private var isPaused = false @@ -28,13 +29,20 @@ class ParticleEmitter( var isDead = false + private var debugTool = EmitterDebug(rot, pos, params.spawnPosOffset, params.shape) + suspend fun tick() { if (isTicking) { count() } if (isTicking) { addParticle() } - if (!isTicking && allParticles.isEmpty()) { isDead = true } + if (!isTicking && allParticles.isEmpty()) { isDead = true; kill() } processParticlesInBatches(100) + + if (timeAlive == 0 && debug) { debugTool.spawn(world, pos, params.forceFields, params.spawnPosOffset) } + if (debug) { debugTool.update(rot, pos, params.spawnPosOffset) } + + timeAlive += 1 } @@ -87,9 +95,9 @@ class ParticleEmitter( private fun count() { if (params.spawnDuration is ParamClasses.Duration.SingleBurst) { val loopDur = (params.spawnDuration as ParamClasses.Duration.SingleBurst).loopDur - if (timeAlive >= loopDur) { isTicking = false; return } + if (timeEmitted >= loopDur) { isTicking = false; return } - timeAlive += 1 + timeEmitted += 1 } else if (params.spawnDuration is ParamClasses.Duration.MultiBurst) { @@ -97,19 +105,19 @@ class ParticleEmitter( val loopDelay = (params.spawnDuration as ParamClasses.Duration.MultiBurst).loopDelay val loopCount = (params.spawnDuration as ParamClasses.Duration.MultiBurst).loopCount - if (timeAlive >= loopDur && timesLooped + 1 >= loopCount) { isTicking = false; return } + if (timeEmitted >= loopDur && timesLooped + 1 >= loopCount) { isTicking = false; return } if (timePaused >= loopDelay) { isPaused = false timePaused = 0 timesLooped += 1 } - if (timeAlive >= loopDur && loopDelay > 0) { + if (timeEmitted >= loopDur && loopDelay > 0) { isPaused = true - timeAlive = 0 + timeEmitted = 0 } - if (!isPaused) { timeAlive += 1 } + if (!isPaused) { timeEmitted += 1 } else { timePaused += 1 } } @@ -121,12 +129,12 @@ class ParticleEmitter( isPaused = false timePaused = 0 } - if (timeAlive >= loopDur && loopDelay > 0) { + if (timeEmitted >= loopDur && loopDelay > 0) { isPaused = true - timeAlive = 0 + timeEmitted = 0 } - if (!isPaused) { timeAlive += 1 } + if (!isPaused) { timeEmitted += 1 } else { timePaused += 1 } } } @@ -137,6 +145,7 @@ class ParticleEmitter( particle.kill() allParticles = allParticles.toMutableList().apply { remove(particle) }.toTypedArray() } + if (debug) { debugTool.kill() } isTicking = false isDead = true }