hopefully the last commit before 1.0

This commit is contained in:
2024-11-24 15:37:24 +01:00
parent 4f5a6c1ae9
commit c87b2f7483
11 changed files with 181 additions and 204 deletions
@@ -27,10 +27,6 @@ import net.minecraft.world.World
import java.util.*
// TODO: finish the particle ticking
// TODO: make custom commands to create particles easier (only temporarily saved)
var ALL_PARTICLE_EMITTERS: Array<ParticleEmitter> = emptyArray()
val sessionUuid: UUID = UUID.randomUUID()
@@ -122,8 +118,8 @@ fun onRightClick(player: PlayerEntity, world: ServerWorld, hand: Hand) : TypedAc
fun emitterParamsToJson(params: EmitterParams) : Map<String, Any> {
val allParticleParamsJSON: MutableList<Map<String, Any?>> = mutableListOf()
val particle = params.particle
for (particle in params.particleTypes) {
val particleParamsJSON = mapOf(
"shape" to particle.shape,
"blockCurve" to particle.blockCurve,
@@ -142,7 +138,6 @@ fun emitterParamsToJson(params: EmitterParams) : Map<String, Any> {
)
allParticleParamsJSON.add(particleParamsJSON)
}
val emitterParamsJSON = mapOf(
"maxCount" to params.maxCount,
@@ -224,24 +224,25 @@ fun interpolateCurve(start: Vector3f, end: Vector3f, t: Float, curve: Interpolat
}
fun sdfSphere(point: Vec3d, radius: Double): Double {
val x = point.x
val y = point.y
val z = point.z
fun sdfSphere(pos: Vector3f, radius: Float, objectPos: Vector3f): Float {
val dx = objectPos.x - pos.x
val dy = objectPos.y - pos.y
val dz = objectPos.z - pos.z
val distanceFromCenter = sqrt(x * x + y * y + z * z)
return distanceFromCenter - radius
val distanceFromCenter = sqrt(dx * dx + dy * dy + dz * dz)
return (distanceFromCenter - radius)
}
fun sdfCube(point: Vec3d, size: Vec3d): Double {
val px = point.x
val py = point.y
val pz = point.z
val sx = size.x
val sy = size.y
val sz = size.z
fun sdfCube(pos: Vector3f, size: Vector3f, objectPos: Vector3f): Float {
val px = objectPos.x - pos.x
val py = objectPos.y - pos.y
val pz = objectPos.z - pos.z
val sx = size.x.toDouble()
val sy = size.y.toDouble()
val sz = size.z.toDouble()
val halfSize = Triple(sx / 2, sy / 2, sz / 2)
@@ -256,5 +257,10 @@ fun sdfCube(point: Vec3d, size: Vec3d): Double {
val insideDistance = min(max(dx, max(dy, dz)), 0.0)
return outsideDistance + insideDistance
return (outsideDistance + insideDistance).toFloat()
}
fun normalizeSdf(sdf: Float, radius: Float): Float {
return if (sdf < 0) (sdf + radius) / radius else 0f
}
@@ -24,9 +24,10 @@ import java.util.concurrent.CompletableFuture
val curves = arrayOf("LINEAR", "SQRT", "EXPONENT", "CUBIC", "SINE", "COSINE", "INVERSE", "LOG", "EXP", "BOUNCE")
fun argUpdateEmitterParam(context: CommandContext<ServerCommandSource>, paramName: String, typeValue: Any) : MutableText {
fun updateEmitterParam(context: CommandContext<ServerCommandSource>, paramName: String, typeValue: Any) : MutableText {
val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID")
val success = updateSingleParam(emitterIdVal, -1, paramName, typeValue)
val success = updateSingleEmitterParam(emitterIdVal, paramName, typeValue)
val feedback = if (success) {
Text.literal("BPS - Successfully updated Emitter ID \"$emitterIdVal\": Parameter \"$paramName\", value \"$typeValue\"")
@@ -42,17 +43,18 @@ fun argUpdateEmitterParam(context: CommandContext<ServerCommandSource>, paramNam
}
fun argUpdateParticleParam(context: CommandContext<ServerCommandSource>, particleIndex: Int, paramName: String, typeValue: Any) : MutableText {
fun updateParticleParam(context: CommandContext<ServerCommandSource>, paramName: String, typeValue: Any) : MutableText {
val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID")
val success = updateSingleParam(emitterIdVal, particleIndex, paramName, typeValue)
val particle = getEmitterParams(emitterIdVal)?.particle
val success = updateSingleParticleParam(emitterIdVal, paramName, typeValue)
val feedback = if (success) {
Text.literal("BPS - Successfully updated Emitter ID \"$emitterIdVal\": Index \"$particleIndex\", parameter \"$paramName\", value \"$typeValue\"")
Text.literal("BPS - Successfully updated Particle of Emitter ID \"$emitterIdVal\": parameter \"$paramName\", value \"$typeValue\"")
.setStyle(Style.EMPTY.withColor(Color(0, 200, 0).rgb))
}
else {
Text.literal("BPS - Failed to update Emitter ID \"$emitterIdVal\": Index \"$particleIndex\", parameter \"$paramName\", value \"$typeValue\": Unknown Error\n" +
"Try checking if the emitter, particle index, and parameter exist, and the value is the correct type.")
Text.literal("BPS - Failed to update Emitter ID \"$emitterIdVal\": parameter \"$paramName\", value \"$typeValue\": Unknown Error\n" +
"Try checking if the Emitter ID and parameter exist, and the value is the correct type.")
.setStyle(Style.EMPTY.withColor(Color(200, 0, 0).rgb))
}
@@ -63,11 +65,10 @@ fun argUpdateParticleParam(context: CommandContext<ServerCommandSource>, particl
class ArgConfigEmitterKeys {
fun maxCount() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("maxCount")
.then(
CommandManager.argument("Int", IntegerArgumentType.integer())
.then(CommandManager.argument("Int", IntegerArgumentType.integer())
.executes { context ->
val typeValue = IntegerArgumentType.getInteger(context, "Int")
val feedback = argUpdateEmitterParam(context, "maxCount", typeValue)
val feedback = updateEmitterParam(context, "maxCount", typeValue)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -75,11 +76,10 @@ class ArgConfigEmitterKeys {
}
fun spawnsPerTick() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("spawnsPerTick")
.then(
CommandManager.argument("Int", IntegerArgumentType.integer())
.then(CommandManager.argument("Int", IntegerArgumentType.integer())
.executes { context ->
val typeValue = IntegerArgumentType.getInteger(context, "Int")
val feedback = argUpdateEmitterParam(context, "spawnsPerTick", typeValue)
val feedback = updateEmitterParam(context, "spawnsPerTick", typeValue)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -87,11 +87,10 @@ class ArgConfigEmitterKeys {
}
fun loopDur() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("loopDur")
.then(
CommandManager.argument("Int", IntegerArgumentType.integer())
.then(CommandManager.argument("Int", IntegerArgumentType.integer())
.executes { context ->
val typeValue = IntegerArgumentType.getInteger(context, "Int")
val feedback = argUpdateEmitterParam(context, "loopDur", typeValue)
val feedback = updateEmitterParam(context, "loopDur", typeValue)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -99,11 +98,10 @@ class ArgConfigEmitterKeys {
}
fun loopDelay() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("loopDelay")
.then(
CommandManager.argument("Int", IntegerArgumentType.integer())
.then(CommandManager.argument("Int", IntegerArgumentType.integer())
.executes { context ->
val typeValue = IntegerArgumentType.getInteger(context, "Int")
val feedback = argUpdateEmitterParam(context, "loopDelay", typeValue)
val feedback = updateEmitterParam(context, "loopDelay", typeValue)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -111,11 +109,10 @@ class ArgConfigEmitterKeys {
}
fun loopCount() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("loopCount")
.then(
CommandManager.argument("Int", IntegerArgumentType.integer())
.then(CommandManager.argument("Int", IntegerArgumentType.integer())
.executes { context ->
val typeValue = IntegerArgumentType.getInteger(context, "Int")
val feedback = argUpdateEmitterParam(context, "loopCount", typeValue)
val feedback = updateEmitterParam(context, "loopCount", typeValue)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -130,9 +127,8 @@ class ArgConfigParticleKeys {
.then(CommandManager.literal("circle")
.then(CommandManager.argument("Radius", FloatArgumentType.floatArg())
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val radius = FloatArgumentType.getFloat(context, "Radius")
val feedback = argUpdateParticleParam(context, particleIndex, "shape", SpawningShape.CIRCLE(radius))
val feedback = updateParticleParam(context, "shape", SpawningShape.CIRCLE(radius))
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -142,10 +138,9 @@ class ArgConfigParticleKeys {
.then(CommandManager.argument("Width", FloatArgumentType.floatArg())
.then(CommandManager.argument("Height", FloatArgumentType.floatArg())
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val w = FloatArgumentType.getFloat(context, "Width")
val h = FloatArgumentType.getFloat(context, "Height")
val feedback = argUpdateParticleParam(context, particleIndex, "shape", SpawningShape.RECT(Vector2f(w, h)))
val feedback = updateParticleParam(context, "shape", SpawningShape.RECT(Vector2f(w, h)))
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -157,11 +152,10 @@ class ArgConfigParticleKeys {
.then(CommandManager.argument("Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Z", FloatArgumentType.floatArg())
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val x = FloatArgumentType.getFloat(context, "X")
val y = FloatArgumentType.getFloat(context, "Y")
val z = FloatArgumentType.getFloat(context, "Z")
val feedback = argUpdateParticleParam(context, particleIndex, "shape", SpawningShape.CUBE(Vector3f(x, y, z)))
val feedback = updateParticleParam(context, "shape", SpawningShape.CUBE(Vector3f(x, y, z)))
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -172,9 +166,8 @@ class ArgConfigParticleKeys {
.then(CommandManager.literal("sphere")
.then(CommandManager.argument("Radius", FloatArgumentType.floatArg())
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val radius = FloatArgumentType.getFloat(context, "Radius")
val feedback = argUpdateParticleParam(context, particleIndex, "shape", SpawningShape.SPHERE(radius))
val feedback = updateParticleParam(context, "shape", SpawningShape.SPHERE(radius))
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -185,10 +178,9 @@ class ArgConfigParticleKeys {
return CommandManager.literal("blockCurve")
.then(CommandManager.argument("Array (separate by comma)", StringArgumentType.string())
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val typeValue = StringArgumentType.getString(context, "Array (separate by comma)")
val typeArray = typeValue.split(",").toTypedArray()
val feedback = argUpdateParticleParam(context, particleIndex, "blockCurve", typeArray)
val feedback = updateParticleParam(context, "blockCurve", typeArray)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -203,10 +195,8 @@ class ArgConfigParticleKeys {
.then(CommandManager.argument("Max Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Max Z", FloatArgumentType.floatArg())
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val vectors = x1x2ToPairVector3f(context)
val feedback = argUpdateParticleParam(context, particleIndex, "rotRandom", vectors)
val feedback = updateParticleParam(context, "rotRandom", vectors)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -226,10 +216,8 @@ class ArgConfigParticleKeys {
.then(CommandManager.argument("Max Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Max Z", FloatArgumentType.floatArg())
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val vectors = x1x2ToPairVector3f(context)
val feedback = argUpdateParticleParam(context, particleIndex, "rotVelRandom", vectors)
val feedback = updateParticleParam(context, "rotVelRandom", vectors)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -249,10 +237,8 @@ class ArgConfigParticleKeys {
.then(CommandManager.argument("Max Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Max Z", FloatArgumentType.floatArg())
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val vectors = x1x2ToPairVector3f(context)
val feedback = argUpdateParticleParam(context, particleIndex, "sizeRandom", vectors)
val feedback = updateParticleParam(context, "sizeRandom", vectors)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -267,9 +253,8 @@ class ArgConfigParticleKeys {
return CommandManager.literal("uniformSize")
.then(CommandManager.argument("Bool", BoolArgumentType.bool())
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val uniform = BoolArgumentType.getBool(context, "Bool")
val feedback = argUpdateParticleParam(context, particleIndex, "uniformSize", uniform)
val feedback = updateParticleParam(context, "uniformSize", uniform)
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -284,10 +269,8 @@ class ArgConfigParticleKeys {
.then(CommandManager.argument("Max Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Max Z", FloatArgumentType.floatArg())
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val vectors = x1x2ToPairVector3f(context)
val feedback = argUpdateParticleParam(context, particleIndex, "velRandom", vectors)
val feedback = updateParticleParam(context, "velRandom", vectors)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -299,7 +282,7 @@ class ArgConfigParticleKeys {
)
}
fun forceFields() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("ForceFields")
return CommandManager.literal("forceFields")
.then(argAddForceField())
.then(argRemoveForceField())
}
@@ -309,12 +292,11 @@ class ArgConfigParticleKeys {
.then(CommandManager.argument("Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Z", FloatArgumentType.floatArg())
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val x1 = FloatArgumentType.getFloat(context, "X")
val y1 = FloatArgumentType.getFloat(context, "Y")
val z1 = FloatArgumentType.getFloat(context, "Z")
val feedback = argUpdateParticleParam(context, particleIndex, "gravity", Vector3f(x1, y1, z1))
val feedback = updateParticleParam(context, "gravity", Vector3f(x1, y1, z1))
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -326,9 +308,8 @@ class ArgConfigParticleKeys {
return CommandManager.literal("drag")
.then(CommandManager.argument("Float", FloatArgumentType.floatArg())
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val value = FloatArgumentType.getFloat(context, "Float")
val feedback = argUpdateParticleParam(context, particleIndex, "drag", value)
val feedback = updateParticleParam(context, "drag", value)
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -338,9 +319,8 @@ class ArgConfigParticleKeys {
return CommandManager.literal("minVel")
.then(CommandManager.argument("Float", FloatArgumentType.floatArg())
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val value = FloatArgumentType.getFloat(context, "Float")
val feedback = argUpdateParticleParam(context, particleIndex, "minVel", value)
val feedback = updateParticleParam(context, "minVel", value)
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -351,10 +331,9 @@ class ArgConfigParticleKeys {
.then(CommandManager.argument("min", IntegerArgumentType.integer())
.then(CommandManager.argument("max", IntegerArgumentType.integer())
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val min = IntegerArgumentType.getInteger(context, "min")
val max = IntegerArgumentType.getInteger(context, "max")
val feedback = argUpdateParticleParam(context, particleIndex, "lifeTime", Pair(min, max))
val feedback = updateParticleParam(context, "lifeTime", Pair(min, max))
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
@@ -375,13 +354,11 @@ class ArgConfigParticleKeys {
CompletableFuture.completedFuture(builder.build())
}
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val vectors = x1x2ToPairVector3f(context)
val curveString = StringArgumentType.getString(context, "Curve")
val feedback = argUpdateParticleParam(
val feedback = updateParticleParam(
context,
particleIndex,
"rotVelCurve",
Triple(vectors.first, vectors.second, getCurveByString(curveString)))
@@ -410,13 +387,11 @@ class ArgConfigParticleKeys {
CompletableFuture.completedFuture(builder.build())
}
.executes { context ->
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val vectors = x1x2ToPairVector3f(context)
val curveString = StringArgumentType.getString(context, "Curve")
val feedback = argUpdateParticleParam(
val feedback = updateParticleParam(
context,
particleIndex,
"sizeCurve",
Triple(vectors.first, vectors.second, getCurveByString(curveString)))
@@ -503,10 +478,10 @@ fun argRemoveForceField() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("remove")
.then(CommandManager.argument("Force Field Name", StringArgumentType.string())
.suggests { context, builder ->
val particleId = StringArgumentType.getString(context, "Registered Emitter ID")
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val params = getEmitterParams(particleId)
val forceFields = params!!.particleTypes[particleIndex].forceFields
val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID")
val params = getEmitterParams(emitterIdVal)
val forceFields = params!!.particle.forceFields
forceFields.iterator().forEach {
builder.suggest(it.name)
@@ -516,11 +491,10 @@ fun argRemoveForceField() : LiteralArgumentBuilder<ServerCommandSource> {
}
.executes { context ->
val ffName = StringArgumentType.getString(context, "Force Field Name")
val particleId = StringArgumentType.getString(context, "Registered Emitter ID")
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID")
val params = getEmitterParams(particleId)
val forceFields = params!!.particleTypes[particleIndex].forceFields
val params = getEmitterParams(emitterIdVal)
val forceFields = params!!.particle.forceFields
val newForceFields: MutableList<ForceField> = forceFields.toMutableList()
for (forceField in forceFields) {
@@ -529,9 +503,8 @@ fun argRemoveForceField() : LiteralArgumentBuilder<ServerCommandSource> {
}
}
val feedback = argUpdateParticleParam(
val feedback = updateParticleParam(
context,
particleIndex,
"forceFields",
newForceFields
)
@@ -543,19 +516,20 @@ fun argRemoveForceField() : LiteralArgumentBuilder<ServerCommandSource> {
fun forceFieldAddSphereExec(context: CommandContext<ServerCommandSource>) : Int {
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val radius = FloatArgumentType.getFloat(context, "Radius")
val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID")
val shape = ForceFieldShape.SPHERE(radius)
val radius = FloatArgumentType.getFloat(context, "Radius")
val minForce = FloatArgumentType.getFloat(context, "Min Force")
val maxForce = FloatArgumentType.getFloat(context, "Max Force")
val shape = ForceFieldShape.SPHERE(radius, Pair(minForce, maxForce))
val forceField = forceFieldGenericParams(context, shape)
val currentParams = getEmitterParams(emitterIdVal)
val forceFields = currentParams!!.particleTypes[particleIndex].forceFields
val forceFields = currentParams!!.particle.forceFields
val feedback = argUpdateParticleParam(
val feedback = updateParticleParam(
context,
particleIndex,
"forceFields",
forceFields.toMutableList().add(forceField)
)
@@ -568,7 +542,6 @@ fun forceFieldAddSphereExec(context: CommandContext<ServerCommandSource>) : Int
fun forceFieldAddCubeExec(context: CommandContext<ServerCommandSource>) : Int {
val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index")
val xSize = FloatArgumentType.getFloat(context, "X Size")
val ySize = FloatArgumentType.getFloat(context, "Y Size")
val zSize = FloatArgumentType.getFloat(context, "Z Size")
@@ -581,11 +554,10 @@ fun forceFieldAddCubeExec(context: CommandContext<ServerCommandSource>) : Int {
val forceField = forceFieldGenericParams(context, shape)
val currentParams = getEmitterParams(emitterIdVal)
val forceFields = currentParams!!.particleTypes[particleIndex].forceFields
val forceFields = currentParams!!.particle.forceFields
val feedback = argUpdateParticleParam(
val feedback = updateParticleParam(
context,
particleIndex,
"forceFields",
forceFields.toMutableList().add(forceField)
)
@@ -602,13 +574,10 @@ fun forceFieldGenericParams(context: CommandContext<ServerCommandSource>, shape:
val posX = FloatArgumentType.getFloat(context, "X Pos")
val posY = FloatArgumentType.getFloat(context, "Y Pos")
val posZ = FloatArgumentType.getFloat(context, "Z Pos")
val minForce = FloatArgumentType.getFloat(context, "Min Force")
val maxForce = FloatArgumentType.getFloat(context, "Max Force")
return ForceField(
name.replace(" ", "_"),
Vector3f(posX, posY, posZ),
Pair(minForce, maxForce),
shape
)
}
@@ -36,7 +36,7 @@ import java.util.concurrent.CompletableFuture
// config
// <emitter id>
// <[particle index] / EMITTER>
// <PARTICLE / EMITTER>
// <param key> // HARDCODED KEYS, if EMITTER use emitter params.
// <new param value> // HARDCODED TYPES
// output -> update the selected parameter of the selected emitter id to the new value
@@ -69,7 +69,7 @@ object ManageEmitters {
val allEmitterIds = emitterIdRegister.keys
// TODO: maybe make this a Command.literal() if possible
// TODO: perhaps make this a Command.literal() if possible
val emitterIdSuggestion: RequiredArgumentBuilder<ServerCommandSource, String> = CommandManager.argument("Registered Emitter ID", StringArgumentType.string())
.suggests { _, builder ->
allEmitterIds.forEach { key ->
@@ -212,30 +212,21 @@ fun argCopy() : LiteralArgumentBuilder<ServerCommandSource> {
// config
// <emitter id>
// <[particle index] / EMITTER>
// <PARTICLE / EMITTER>
// <param key> // HARDCODED KEYS, if EMITTER use emitter params.
// <new param value> // HARDCODED TYPES
// output -> update the selected parameter of the selected emitter id to the new value
fun argConfig() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("config")
.then(emitterIdSuggestion
.then(CommandManager.literal("EMITTER")
.then(CommandManager.literal("emitter")
.then(emitterConfigKeys.maxCount())
.then(emitterConfigKeys.spawnsPerTick())
.then(emitterConfigKeys.loopDur())
.then(emitterConfigKeys.loopDelay())
.then(emitterConfigKeys.loopCount())
)
.then(CommandManager.argument("Particle Index", IntegerArgumentType.integer())
.suggests { context, builder ->
val emitterId = StringArgumentType.getString(context, "Registered Emitter ID")
getEmitterParams(emitterId)?.particleTypes?.indices?.forEach {
builder.suggest(it)
}
CompletableFuture.completedFuture(builder.build())
}
.then(CommandManager.literal("particle")
.then(particleConfigKeys.shape())
.then(particleConfigKeys.blockCurve())
.then(particleConfigKeys.rotRandom())
@@ -9,7 +9,7 @@ package com.bytedice.bde_particles.particles
* @param loopDur The duration for which the loop runs, in ticks. A value 0 or below means the loop is infinite, and `loopDelay` and `loopCount` will be ignored.
* @param loopDelay The delay between each loop cycle, in ticks. Negative values are treated as 0, meaning no delay.
* @param loopCount The number of times the loop will repeat. 0 means it will shoot a single burst of particles. A value below 0 means it will repeat indefinitely.
* @param particleTypes An array of `ParticleParams` defining the types of particles to spawn. If empty, no particles will spawn.
* @param particle The particle params of the particle that will spawn.
*/
data class EmitterParams (
var maxCount: Int = 200,
@@ -17,7 +17,7 @@ data class EmitterParams (
var loopDur: Int = 25,
var loopDelay: Int = 0,
var loopCount: Int = 0,
var particleTypes: Array<ParticleParams> = arrayOf(ParticleParams()),
var particle: ParticleParams = ParticleParams(),
)
{
companion object Presets {
@@ -28,7 +28,7 @@ data class EmitterParams (
25,
0,
0,
arrayOf(ParticleParams.DEFAULT)
ParticleParams.FIRE_GEYSER
)
}
}
@@ -4,7 +4,6 @@ import org.joml.Vector3f
data class ForceField (
val name: String = "DEFAULT",
val pos: Vector3f = Vector3f(0.0f, 0.0f, 0.0f),
val force: Pair<Float, Float> = Pair(0.0f, 1.0f),
val pos: Vector3f = Vector3f(0.0f, 5.0f, 0.0f),
val shape: ForceFieldShape = ForceFieldShape.SPHERE()
)
@@ -5,8 +5,7 @@ import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.Vec3d
import org.joml.Vector3f
import org.joml.Vector4f
import kotlin.math.abs
import kotlin.math.round
import kotlin.math.*
class Particle(private val particleParams: ParticleParams) {
@@ -124,13 +123,28 @@ class Particle(private val particleParams: ParticleParams) {
return particleParams.blockCurve[newBlockIdx]
}
/*fun calcVel() {
for (forceField in particleParams.forceFields) {
if (forceField.shape::class == ForceFieldShape.Sphere::class) {
fun sphereSdfVel(forceField: ForceField) : Vector3f {
if (forceField.shape !is ForceFieldShape.SPHERE) { return Vector3f(0.0f, 0.0f, 0.0f) }
val shape = forceField.shape
val sdfVal = sdfSphere(forceField.pos, shape.radius, offset)
val normalizedSdf = normalizeSdf(sdfVal, shape.radius)
val velDir = Vector3f(offset).sub(forceField.pos).normalize()
val velMul = lerp(shape.force.second, shape.force.second, 1 - normalizedSdf)
return velDir.mul(velMul)
}
fun cubeSdfVel(forceField: ForceField) : Vector3f {
if (forceField.shape !is ForceFieldShape.CUBE) { return Vector3f(0.0f, 0.0f, 0.0f) }
val shape = forceField.shape
val sdfVal = sdfCube(forceField.pos, shape.size, offset)
val velDir = if (sdfVal < 0) { shape.forceDir }
else { Vector3f(0.0f, 0.0f, 0.0f) }
return velDir
}
}*/
fun calcRot(timeAliveClamped: Float) : Vector3f {
val newRot = Vector3f(rot)
@@ -174,6 +188,11 @@ class Particle(private val particleParams: ParticleParams) {
offset = newOffset
rot = newRot
for (forceField in particleParams.forceFields) {
if (forceField.shape is ForceFieldShape.SPHERE) { vel.add(sphereSdfVel(forceField)) }
else if (forceField.shape is ForceFieldShape.CUBE) { vel.add(cubeSdfVel(forceField)) }
}
val (quatRot, transformOffset) = calcTransformOffset(newRot, initOffset, newScale)
val combinedOffset = transformOffset.add(newOffset)
@@ -33,18 +33,16 @@ class ParticleEmitter(private val emitterPos: Vec3d, private val emitterWorld: S
private fun addParticle() {
if (loopDelayActive) { return }
for (i in emitterParams.particleTypes.indices) {
repeat(this.emitterParams.spawnsPerTick) {
if (allParticles.size >= emitterParams.maxCount) { return }
val particle = Particle(emitterParams.particleTypes[i])
val particle = Particle(emitterParams.particle)
particle.init(this.emitterPos)
particle.spawn(emitterWorld)
allParticles += particle
}
}
}
private fun count() {
@@ -40,28 +40,25 @@ fun updateEmitterParams(id: String, newParams: EmitterParams) {
}
fun updateSingleParam(id: String, particleIndex: Int, paramName: String, paramValue: Any) : Boolean {
fun updateSingleEmitterParam(id: String, paramName: String, paramValue: Any) : Boolean {
val emitter = getEmitterParams(id) ?: return false
if (particleIndex == -1) {
val updatedValues = updateSingleEmitterParam(emitter, paramName, paramValue)
updateEmitterParams(id, updatedValues.first)
return updatedValues.second
}
else if (emitter.particleTypes.isNotEmpty()) {
val particle = emitter.particleTypes[particleIndex]
}
fun updateSingleParticleParam(emitterId: String, paramName: String, paramValue: Any) : Boolean {
val emitter = getEmitterParams(emitterId) ?: return false
val particle = emitter.particle
val updatedValues = updateSingleParticleParam(particle, paramName, paramValue)
emitter.particleTypes[particleIndex] = updatedValues.first
updateEmitterParams(id, emitter)
emitter.particle = updatedValues.first
updateEmitterParams(emitterId, emitter)
return updatedValues.second
}
else {
return false
}
}
@@ -29,7 +29,7 @@ data class ParticleParams (
var sizeRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(0.5f, 0.5f, 0.5f), Vector3f(1.0f, 1.0f, 1.0f)),
var uniformSize: Boolean = true,
var velRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(-0.1f, 0.4f, -0.1f), Vector3f(0.1f, 0.8f, 0.1f)),
var forceFields: Array<ForceField> = emptyArray(),
var forceFields: Array<ForceField> = arrayOf(ForceField()),
var gravity: Vector3f = Vector3f(0.0f, -0.01f, 0.0f),
var drag: Float = 0.075f,
var minVel: Float = 0.0f,
@@ -11,9 +11,12 @@ sealed class SpawningShape {
}
sealed class ForceFieldShape {
data class SPHERE(val radius: Float = 1.0f) : ForceFieldShape()
data class SPHERE(
val radius: Float = 3.0f,
val force: Pair<Float, Float> = Pair(0.0f, 0.02f),
) : ForceFieldShape()
data class CUBE(
val size: Vector3f = Vector3f(1.0f, 1.0f, 1.0f),
val forceDir: Vector3f = Vector3f(0.0f, 0.0f, 0.0f) // 0.0 on all means from center
val forceDir: Vector3f = Vector3f(0.0f, 0.0f, 0.0f)
) : ForceFieldShape()
}