made some newly added params function correctly

This commit is contained in:
2024-11-30 13:08:35 +01:00
parent be00598efe
commit 8ad6cb9ffb
13 changed files with 130 additions and 65 deletions
+7 -2
View File
@@ -3,8 +3,13 @@
BDE_ParticleSys is a highly customizable **server-side** particle system that uses `Block Display Entities` (BDEs) as particles. It is meant to be used as a library for other mods, but can be used as a standalone mod too. BDE_ParticleSys is a highly customizable **server-side** particle system that uses `Block Display Entities` (BDEs) as particles. It is meant to be used as a library for other mods, but can be used as a standalone mod too.
<!-- change GiveParticleEmitter to GiveEmitterTool --> If BDE_ParticleSys is used as a standalone mod, you will only be able to use it with the custom in-game commands `/GiveEmitterTool`, `/KillAllEmitters`, and `/ManageEmitters`. Any particles made, removed, or changed with those commands are **temporary** and get reverted once the server shuts down, as they are meant for quick testing.
If BDE_ParticleSys is used as a standalone mod, you will only be able to use it with the custom in-game commands `/GiveEmitterTool`, `/KillAllEmitters` and `/ManageEmitters`. Any particles made with those commands are **temporary** and get removed once the server shuts down, as they are meant for quick testing.
### Contents (in-game)
* `/GiveEmitterTool`
* `/KillAllEmitters`
* `/ManageEmitters`
* `GlobalMaxParticles` (GameRule)
# Open-source - Copyright # Open-source - Copyright
@@ -2,7 +2,7 @@ package com.bytedice.bde_particles.client
import com.bytedice.bde_particles.commands.GiveEmitterTool import com.bytedice.bde_particles.commands.GiveEmitterTool
import com.bytedice.bde_particles.commands.KillAllEmitters import com.bytedice.bde_particles.commands.KillAllEmitters
import com.bytedice.bde_particles.commands.ManageEmitters //import com.bytedice.bde_particles.commands.ManageEmitters
import com.bytedice.bde_particles.init import com.bytedice.bde_particles.init
import com.bytedice.bde_particles.onRightClick import com.bytedice.bde_particles.onRightClick
import com.bytedice.bde_particles.tick import com.bytedice.bde_particles.tick
@@ -38,7 +38,7 @@ class Bde_particlesClient : ClientModInitializer {
CommandRegistrationCallback.EVENT.register { dispatcher, registryAccess, _ -> CommandRegistrationCallback.EVENT.register { dispatcher, registryAccess, _ ->
GiveEmitterTool.register(dispatcher, registryAccess) GiveEmitterTool.register(dispatcher, registryAccess)
ManageEmitters .register(dispatcher) //ManageEmitters .register(dispatcher)
KillAllEmitters.register(dispatcher) KillAllEmitters.register(dispatcher)
} }
@@ -2,7 +2,7 @@ package com.bytedice.bde_particles
import com.bytedice.bde_particles.commands.GiveEmitterTool import com.bytedice.bde_particles.commands.GiveEmitterTool
import com.bytedice.bde_particles.commands.KillAllEmitters import com.bytedice.bde_particles.commands.KillAllEmitters
import com.bytedice.bde_particles.commands.ManageEmitters //import com.bytedice.bde_particles.commands.ManageEmitters
import com.bytedice.bde_particles.items.ParticleEmitterTool import com.bytedice.bde_particles.items.ParticleEmitterTool
import com.bytedice.bde_particles.particles.* import com.bytedice.bde_particles.particles.*
import kotlinx.coroutines.async import kotlinx.coroutines.async
@@ -47,23 +47,31 @@ import java.util.*
// Custom curve equation command args (parse from strings) // Custom curve equation command args (parse from strings)
// Cylinder and cone force field shape. // Cylinder and cone force field shape.
// Better particle performance. // Better particle performance.
// Global max particles variable.
// gamerule max particles
// Emitter groups (multiple emitters for EmitterTool) // Emitter groups (multiple emitters for EmitterTool)
// Private functions/classes // Private functions/classes
// Debug tools
// RenderParticleDebug gamerule
// render emitter origin
// render particle origin
// name-tag particle with its data
// render particle velocity direction
var ALL_PARTICLE_EMITTERS: Array<ParticleEmitter> = emptyArray() var ALL_PARTICLE_EMITTERS: Array<ParticleEmitter> = emptyArray()
var LIVING_PARTICLE_COUNT: Int = 0
val SESSION_UUID: UUID = UUID.randomUUID() val SESSION_UUID: UUID = UUID.randomUUID()
val GLOBAL_MAX_PARTICLES = GameRuleRegistry.register(
"GlobalMaxParticles",
GameRules.Category.UPDATES,
GameRuleFactory.createIntRule(3000, 0)
)
class Bde_particles : ModInitializer { class Bde_particles : ModInitializer {
companion object {
val GLOBAL_MAX_PARTICLES: GameRules.Key<GameRules.IntRule> = GameRuleRegistry.register(
"GlobalMaxParticles",
GameRules.Category.UPDATES,
GameRuleFactory.createIntRule(3000, 0)
)
}
override fun onInitialize() { override fun onInitialize() {
if (FabricLoader.getInstance().environmentType != EnvType.SERVER) { if (FabricLoader.getInstance().environmentType != EnvType.SERVER) {
return return
@@ -71,17 +79,13 @@ class Bde_particles : ModInitializer {
println("BPS - Initializing on ${FabricLoader.getInstance().environmentType}") println("BPS - Initializing on ${FabricLoader.getInstance().environmentType}")
ServerLifecycleEvents.SERVER_STARTED.register { _ ->
init()
}
ServerTickEvents.START_SERVER_TICK.register { server -> ServerTickEvents.START_SERVER_TICK.register { server ->
tick(server) tick(server)
} }
CommandRegistrationCallback.EVENT.register { dispatcher, registryAccess, _ -> CommandRegistrationCallback.EVENT.register { dispatcher, registryAccess, _ ->
GiveEmitterTool.register(dispatcher, registryAccess) GiveEmitterTool.register(dispatcher, registryAccess)
ManageEmitters .register(dispatcher) //ManageEmitters .register(dispatcher)
KillAllEmitters.register(dispatcher) KillAllEmitters.register(dispatcher)
} }
@@ -93,6 +97,8 @@ class Bde_particles : ModInitializer {
}) })
ServerLifecycleEvents.SERVER_STARTED.register(ServerLifecycleEvents.ServerStarted { _ -> ServerLifecycleEvents.SERVER_STARTED.register(ServerLifecycleEvents.ServerStarted { _ ->
init()
println("BPS - Progress bar filled :3") println("BPS - Progress bar filled :3")
println( println(
"\n____________ _____ _____ \n" + "\n____________ _____ _____ \n" +
@@ -75,7 +75,7 @@ class DisplayEntity(private var properties: DisplayEntityProperties?) {
fun kill() { fun kill() {
if (entity == null) { println("BPS - Particle Emitter entity is null!"); return } if (entity == null) { println("BPS - Failed to kill BDE. Entity is null!"); return }
entity?.kill() entity?.kill()
} }
} }
@@ -186,7 +186,6 @@ fun sdfSphere(pos: Vector3f, radius: Float, objectPos: Vector3f): Float {
} }
fun sdfCube(pos: Vector3f, size: Vector3f, objectPos: Vector3f): Float { fun sdfCube(pos: Vector3f, size: Vector3f, objectPos: Vector3f): Float {
val px = objectPos.x - pos.x val px = objectPos.x - pos.x
val py = objectPos.y - pos.y val py = objectPos.y - pos.y
@@ -216,3 +215,21 @@ fun sdfCube(pos: Vector3f, size: Vector3f, objectPos: Vector3f): Float {
fun normalizeSdf(sdf: Float, radius: Float): Float { fun normalizeSdf(sdf: Float, radius: Float): Float {
return if (sdf < 0) (sdf + radius) / radius else 0f return if (sdf < 0) (sdf + radius) / radius else 0f
} }
fun velToRot(velocity: Vector3f): Vector3f {
val normalizedVelocity = Vector3f(velocity).normalize()
val yaw = Math.toDegrees(atan2(normalizedVelocity.z.toDouble(), normalizedVelocity.x.toDouble())).toFloat()
val pitch = Math.toDegrees(
atan2(
-normalizedVelocity.y.toDouble(),
sqrt(
normalizedVelocity.x.toDouble().pow(2) + normalizedVelocity.z.toDouble().pow(2)
)
)
).toFloat()
return Vector3f(pitch, yaw, 0f)
}
@@ -16,11 +16,13 @@ object KillAllEmitters {
dispatcher.register( dispatcher.register(
command.executes { context -> command.executes { context ->
var amountEmitters = 0
for (emitter in ALL_PARTICLE_EMITTERS) { for (emitter in ALL_PARTICLE_EMITTERS) {
emitter.kill() emitter.kill()
amountEmitters += 1
} }
val feedback = Text.literal("BPS - Killed all living Emitters.") val feedback = Text.literal("BPS - Killed all living Emitters. [$amountEmitters]")
.setStyle(Style.EMPTY.withColor(Color(0, 200, 0).rgb)) .setStyle(Style.EMPTY.withColor(Color(0, 200, 0).rgb))
context.source.sendFeedback({ feedback }, false) context.source.sendFeedback({ feedback }, false)
@@ -22,7 +22,7 @@ import java.util.concurrent.CompletableFuture
// TODO: completely redesign // TODO: completely redesign
/*
// CLOSE THIS FILE IMMEDIATELY, YOU ARE ENTERING EGYPTIAN (pyramid) AND ITALIAN (spaghetti) TERRITORY // CLOSE THIS FILE IMMEDIATELY, YOU ARE ENTERING EGYPTIAN (pyramid) AND ITALIAN (spaghetti) TERRITORY
val curves = arrayOf("LINEAR", "SQRT", "EXPONENT", "CUBIC", "SINE", "COSINE", "INVERSE", "LOG", "EXP", "BOUNCE") val curves = arrayOf("LINEAR", "SQRT", "EXPONENT", "CUBIC", "SINE", "COSINE", "INVERSE", "LOG", "EXP", "BOUNCE")
@@ -603,3 +603,4 @@ fun forceFieldGenericParams(context: CommandContext<ServerCommandSource>, shape:
shape shape
) )
} }
*/
@@ -1,6 +1,5 @@
package com.bytedice.bde_particles.commands package com.bytedice.bde_particles.commands
import com.bytedice.bde_particles.emitterParamsToJson
import com.bytedice.bde_particles.particles.* import com.bytedice.bde_particles.particles.*
import com.mojang.brigadier.Command import com.mojang.brigadier.Command
import com.mojang.brigadier.CommandDispatcher import com.mojang.brigadier.CommandDispatcher
@@ -81,7 +80,7 @@ blockCurve: Pair<Array<String>, LerpCurves>,
// <emitter id> // <emitter id>
// output -> give player a command block with the particle params (should be paste-able in kotlin) // output -> give player a command block with the particle params (should be paste-able in kotlin)
/*
object ManageEmitters { object ManageEmitters {
fun register(dispatcher: CommandDispatcher<ServerCommandSource>) { fun register(dispatcher: CommandDispatcher<ServerCommandSource>) {
val command = CommandManager.literal("ManageEmitters") val command = CommandManager.literal("ManageEmitters")
@@ -299,3 +298,4 @@ fun makeCommandBlock(emitterData: Map<String, Any>): ItemStack {
return i return i
} }
*/
@@ -14,52 +14,50 @@ data class EmitterParams (
var lifeTime: ParamClasses.PairInt, var lifeTime: ParamClasses.PairInt,
var shape: SpawningShape, var shape: SpawningShape,
// init transforms // init transforms
var offset: ParamClasses.PairVec3f, var offset: ParamClasses.PairVec3f,
var initRot: ParamClasses.PairVec3f, var initRot: ParamClasses.PairVec3f,
var rotVel: ParamClasses.PairVec3f, var rotVel: ParamClasses.PairVec3f,
var rotWithVel: Boolean, var initVel: ParamClasses.PairVec3f,
var initVel: ParamClasses.PairVec3f, var initCenterVel: ParamClasses.PairFloat,
var initCenterVel: ParamClasses.PairFloat, var initScale: ParamClasses.PairVec3f,
var initScale: ParamClasses.PairVec3f, var transformWithVel: ParamClasses.TransformWithVel,
var scaleWithVel: Boolean,
// velocity // velocity
var forceFields: Array<ForceField>, var forceFields: Array<ForceField>,
var constVel: Vector3f, var constVel: Vector3f,
var drag: Float, var drag: Float,
var minVel: Float, var minVel: Float,
// curves // curves
var offsetCurve: ParamClasses.LerpVal, var offsetCurve: ParamClasses.LerpVal,
var rotVelCurve: ParamClasses.LerpVal, var rotVelCurve: ParamClasses.LerpVal,
var scaleCurve: ParamClasses.LerpVal, var scaleCurve: ParamClasses.LerpVal,
var blockCurve: Pair<Array<String>, LerpCurves>, var blockCurve: Pair<Array<String>, LerpCurves>,
) )
{ {
companion object Presets { companion object Presets {
val DEFAULT = EmitterParams( val DEFAULT = EmitterParams(
maxCount = 200, maxCount = 400,
spawnRate = 1, spawnRate = 100,
spawnChance = 1.0f, spawnChance = 1.0f,
spawnDuration = ParamClasses.Duration.SingleBurst(25), spawnDuration = ParamClasses.Duration.SingleBurst(4),
spawnPosOffset = Vector3f(0.0f, 0.0f, 0.0f), spawnPosOffset = Vector3f(0.0f, 0.0f, 0.0f),
lifeTime = ParamClasses.PairInt(25, 40), lifeTime = ParamClasses.PairInt(25, 40),
shape = SpawningShape.Circle(3.0f, false), shape = SpawningShape.Sphere(1.0f, true),
offset = ParamClasses.PairVec3f.Uniform(-0.5f, -0.5f), offset = ParamClasses.PairVec3f.Uniform(-0.5f, -0.5f),
initRot = ParamClasses.PairVec3f.Null, initRot = ParamClasses.PairVec3f.NonUniform(0.0f, 0.0f, 0.0f, 360.0f, 360.0f, 360.0f),
rotVel = ParamClasses.PairVec3f.NonUniform(-0.2f, -0.2f, -0.2f, 0.2f, 0.2f, 0.2f), rotVel = ParamClasses.PairVec3f.NonUniform(-0.2f, -0.2f, -0.2f, 0.2f, 0.2f, 0.2f),
rotWithVel = true,
initVel = ParamClasses.PairVec3f.Null, initVel = ParamClasses.PairVec3f.Null,
initCenterVel = ParamClasses.PairFloat(0.1f, 0.3f), initCenterVel = ParamClasses.PairFloat(0.4f, 0.5f),
initScale = ParamClasses.PairVec3f.Uniform(1.0f, 0.2f), initScale = ParamClasses.PairVec3f.Uniform(1.5f, 1.0f),
scaleWithVel = true, transformWithVel = ParamClasses.TransformWithVel.none,
forceFields = emptyArray(), forceFields = emptyArray(),
constVel = Vector3f(0.0f, -0.01f, 0.0f), constVel = Vector3f(0.0f, 0.0f, 0.0f),
drag = 0.075f, drag = 0.075f,
minVel = 0.0f, minVel = 0.0f,
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f(Vector3f(-0.5f, -0.5f, -0.5f)), offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Sqrt), rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Sqrt),
scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.5f, LerpCurves.Linear), scaleCurve = ParamClasses.LerpVal.LerpUniform(0.0f, 2.0f, LerpCurves.Linear),
blockCurve = Pair( blockCurve = Pair(
arrayOf("minecraft:purple_concrete", "minecraft:purple_stained_glass"), arrayOf("shroomlight", "orange_concrete", "orange_stained_glass", "gray_wool", "gray_stained_glass", "light_gray_stained_glass"),
LerpCurves.Sqrt LerpCurves.Sqrt
), ),
) )
@@ -90,7 +90,7 @@ class ParamClasses {
return com.bytedice.bde_particles.lerp(from, to, t) * curve.function(t) return com.bytedice.bde_particles.lerp(from, to, t) * curve.function(t)
} }
} }
data class NoLerpVec3f(val value: Vector3f) : LerpVal() data object NoLerpVec3f : LerpVal()
fun lerpToVector3f(t: Float) : Vector3f { fun lerpToVector3f(t: Float) : Vector3f {
when (this) { when (this) {
@@ -100,7 +100,7 @@ class ParamClasses {
val x = this.lerp(t) val x = this.lerp(t)
return Vector3f(x, x, x) return Vector3f(x, x, x)
} }
is NoLerpVec3f -> return this.value is NoLerpVec3f -> return Vector3f(1.0f, 1.0f, 1.0f)
} }
} }
} }
@@ -118,4 +118,9 @@ class ParamClasses {
val loopDelay: Int val loopDelay: Int
) : Duration() ) : Duration()
} }
enum class TransformWithVel {
rotOnly,
scaleAndRot,
none
}
} }
@@ -66,7 +66,8 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos:
pos = newSpawnPos pos = newSpawnPos
val dirFromCenter = entityPos.subtract(pos.x.toDouble(), pos.y.toDouble(), pos.z.toDouble()).normalize() val posDouble = Vec3d(pos.x.toDouble(), pos.y.toDouble(), pos.z.toDouble())
val dirFromCenter = posDouble.normalize()
val forceFromCenter = dirFromCenter.multiply(emitterParams.initCenterVel.randomize().toDouble()) val forceFromCenter = dirFromCenter.multiply(emitterParams.initCenterVel.randomize().toDouble())
vel.add(forceFromCenter.x.toFloat(), forceFromCenter.y.toFloat(), forceFromCenter.z.toFloat()) vel.add(forceFromCenter.x.toFloat(), forceFromCenter.y.toFloat(), forceFromCenter.z.toFloat())
@@ -89,7 +90,10 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos:
fun spawn(world: ServerWorld) { fun spawn(world: ServerWorld) {
if (isInit) { blockDisplay.spawn(world) } if (isInit) {
blockDisplay.spawn(world)
LIVING_PARTICLE_COUNT += 1
}
else { error("Particle is not initialized before being spawned. Please use Particle.init() to initialize it.") } else { error("Particle is not initialized before being spawned. Please use Particle.init() to initialize it.") }
} }
@@ -101,7 +105,7 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos:
blockDisplay.updateProperties(newProperties) blockDisplay.updateProperties(newProperties)
if (timeAlive > lifeTime) { isDead = true; blockDisplay.kill() } if (timeAlive > lifeTime) { kill() }
timeAlive += 1 timeAlive += 1
} }
@@ -144,7 +148,7 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos:
val newProperties = DisplayEntityProperties( val newProperties = DisplayEntityProperties(
pos = entityPos, pos = entityPos,
blockType = newBlock, blockType = newBlock,
translation = combinedOffset, translation = combinedOffset.add(newOriginOffset),
leftRotation = quatRot, leftRotation = quatRot,
scale = newScale, scale = newScale,
tags = arrayOf("BPS_Particle", "BPS_UUID", SESSION_UUID.toString()) tags = arrayOf("BPS_Particle", "BPS_UUID", SESSION_UUID.toString())
@@ -183,11 +187,17 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos:
private fun calcRot(t: Float) : Vector3f { private fun calcRot(t: Float) : Vector3f {
val newRot = Vector3f(rot) val newRot = Vector3f(rot)
val newVel = Vector3f(rotVel)
newVel.mul(emitterParams.rotVelCurve.lerpToVector3f(t)) if (emitterParams.transformWithVel == ParamClasses.TransformWithVel.none) {
newRot.add(newVel) val newVel = Vector3f(rotVel)
return newRot
newVel.mul(emitterParams.rotVelCurve.lerpToVector3f(t))
return newRot.add(newVel)
}
else {
val rotWithVel = velToRot(vel)
return newRot.add(rotWithVel)
}
} }
@@ -214,6 +224,10 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos:
fun kill() { fun kill() {
if (!isDead) { blockDisplay.kill() } if (!isDead) {
blockDisplay.kill()
LIVING_PARTICLE_COUNT -= 1
isDead = true
}
} }
} }
@@ -1,5 +1,7 @@
package com.bytedice.bde_particles.particles package com.bytedice.bde_particles.particles
import com.bytedice.bde_particles.Bde_particles
import com.bytedice.bde_particles.LIVING_PARTICLE_COUNT
import com.bytedice.bde_particles.randomFloatBetween import com.bytedice.bde_particles.randomFloatBetween
import net.minecraft.server.world.ServerWorld import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.Vec3d import net.minecraft.util.math.Vec3d
@@ -37,6 +39,9 @@ class ParticleEmitter(private val pos: Vec3d, private val rot: Vector2f, private
repeat(params.spawnRate) { repeat(params.spawnRate) {
if (allParticles.size >= params.maxCount) { return } if (allParticles.size >= params.maxCount) { return }
val maxParticles = world.gameRules.getInt(Bde_particles.GLOBAL_MAX_PARTICLES)
if (LIVING_PARTICLE_COUNT >= maxParticles) { return }
val randomSpawnChance = randomFloatBetween(0.0f, params.spawnChance.coerceIn(0.0f, 1.0f)) val randomSpawnChance = randomFloatBetween(0.0f, params.spawnChance.coerceIn(0.0f, 1.0f))
if (randomSpawnChance > params.spawnChance) { return } if (randomSpawnChance > params.spawnChance) { return }
@@ -13,6 +13,18 @@ fun addToRegister(id: String, params: EmitterParams) : Pair<String, Boolean> {
return Pair(newId, false) return Pair(newId, false)
} }
val newBlocks: MutableList<String> = mutableListOf()
for (block in params.blockCurve.first) {
val blockModIdRegex = ".*:".toRegex()
if (blockModIdRegex.containsMatchIn(block)) { break }
else {
newBlocks.add("minecraft:$block")
}
}
params.blockCurve = Pair(newBlocks.toTypedArray(), params.blockCurve.second)
idRegister[id] = params idRegister[id] = params
println("BPS - Registered Emitter ID \"$newId\".") println("BPS - Registered Emitter ID \"$newId\".")
return Pair(newId, true) return Pair(newId, true)