added force field arg. Testing required for ALL args

This commit is contained in:
2024-12-14 19:17:42 +01:00
parent 5c1b1b07ce
commit 7716ba30f8
8 changed files with 239 additions and 33 deletions
@@ -50,12 +50,7 @@ import java.util.concurrent.CompletableFuture
// Cylinder and cone force field shape.
// Copying particle params in-game
// Custom curve equation command args (parse from strings)
// TODO: (project)
// fix ManageEmitter command
// Better command auto-completion. (and change names of args)
// force field "config" option
// force field "config" option
var ALL_PARTICLE_EMITTERS: Array<ParticleEmitter> = emptyArray()
@@ -22,7 +22,6 @@ import org.joml.Vector2f
import org.joml.Vector3f
import kotlin.reflect.*
import kotlin.reflect.full.memberProperties
import net.minecraft.server.command.GiveCommand
typealias CommandArgumentBuilder = KFunction<ArgumentBuilder<ServerCommandSource, *>>
@@ -72,7 +71,6 @@ fun parseArgNameToAccess(name: String) : KProperty1<EmitterParams, *>? {
return access
}
// TODO: add forceField & implement rest of args
fun parseArgTypeToFunc(type: KType) : CommandArgumentBuilder? {
return when (type.classifier) {
Int::class -> ::intArg
@@ -86,7 +84,8 @@ fun parseArgTypeToFunc(type: KType) : CommandArgumentBuilder? {
ParamClasses.PairFloat::class -> ::pairFloatArg
ParamClasses.TransformWithVel::class -> ::transformWithVelArg
ParamClasses.StringCurve::class -> ::stringCurveArg
ParamClasses.LerpVal::class -> null
ParamClasses.LerpVal::class -> ::lerpValArg
ParamClasses.ForceFieldArray::class -> ::forceFieldArg
else -> null
}
}
@@ -509,5 +508,214 @@ fun stringCurveRemoveArg(context: CommandContext<ServerCommandSource>,
updateParam(id, access, modelCurve)
}
successText(access, "--item at $index", id, context)
}
fun lerpValArg(access: KProperty1<EmitterParams,ParamClasses.PairVec3f>,
configArg: LiteralArgumentBuilder<ServerCommandSource>
) : LiteralArgumentBuilder<ServerCommandSource>
{
return configArg
.then(CommandManager.literal("LerpVec3f")
.then(CommandManager.argument("Min X", FloatArgumentType.floatArg())
.then(CommandManager.argument("Min Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Min Z", FloatArgumentType.floatArg())
.then(CommandManager.argument("Max X", FloatArgumentType.floatArg())
.then(CommandManager.argument("Max Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Max Z", FloatArgumentType.floatArg())
.then(curveListArg("Curve")
.executes { context ->
val id = StringArgumentType.getString(context, "Emitter ID")
val minX = FloatArgumentType.getFloat(context, "Min X")
val minY = FloatArgumentType.getFloat(context, "Min Y")
val minZ = FloatArgumentType.getFloat(context, "Min Z")
val maxX = FloatArgumentType.getFloat(context, "Max X")
val maxY = FloatArgumentType.getFloat(context, "Max Y")
val maxZ = FloatArgumentType.getFloat(context, "Max Z")
val curveName = StringArgumentType.getString(context, "Curve")
val curve = stringToCurve(curveName)
updateParam(id, access, ParamClasses.LerpVal.LerpVec3f(minX, minY, minZ, maxX, maxY, maxZ, curve!!))
successText(access, "LerpVec3f", id, context)
Command.SINGLE_SUCCESS
}
)
)
)
)
)
)
)
)
.then(CommandManager.literal("MultiLerpVec3f")
.then(CommandManager.argument("Min X", FloatArgumentType.floatArg())
.then(CommandManager.argument("Min Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Min Z", FloatArgumentType.floatArg())
.then(CommandManager.argument("Max X", FloatArgumentType.floatArg())
.then(CommandManager.argument("Max Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Max Z", FloatArgumentType.floatArg())
.then(curveListArg("CurveX")
.then(curveListArg("CurveY")
.then(curveListArg("CurveZ")
.executes { context ->
val id = StringArgumentType.getString(context, "Emitter ID")
val minX = FloatArgumentType.getFloat(context, "Min X")
val minY = FloatArgumentType.getFloat(context, "Min Y")
val minZ = FloatArgumentType.getFloat(context, "Min Z")
val maxX = FloatArgumentType.getFloat(context, "Max X")
val maxY = FloatArgumentType.getFloat(context, "Max Y")
val maxZ = FloatArgumentType.getFloat(context, "Max Z")
val curveNameX = StringArgumentType.getString(context, "CurveX")
val curveNameY = StringArgumentType.getString(context, "CurveY")
val curveNameZ = StringArgumentType.getString(context, "CurveZ")
val curveX = stringToCurve(curveNameX)
val curveY = stringToCurve(curveNameY)
val curveZ = stringToCurve(curveNameZ)
updateParam(id, access, ParamClasses.LerpVal.MultiLerpVec3f(minX, minY, minZ, maxX, maxY, maxZ, curveX!!, curveY!!, curveZ!!))
successText(access, "MultiLerpVec3f", id, context)
Command.SINGLE_SUCCESS
}
)
)
)
)
)
)
)
)
)
)
.then(CommandManager.literal("Null")
.executes { context ->
val id = StringArgumentType.getString(context, "Emitter ID")
updateParam(id, access, ParamClasses.LerpVal.Null)
successText(access, "Null", id, context)
Command.SINGLE_SUCCESS
}
)
}
fun forceFieldArg(access: KProperty1<EmitterParams,ParamClasses.ForceFieldArray>,
configArg: LiteralArgumentBuilder<ServerCommandSource>
) : LiteralArgumentBuilder<ServerCommandSource>
{
return configArg
.then(CommandManager.literal("Add")
.then(CommandManager.argument("X", FloatArgumentType.floatArg())
.then(CommandManager.argument("Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Z", FloatArgumentType.floatArg())
.then(CommandManager.literal("Sphere")
.then(CommandManager.argument("Radius", FloatArgumentType.floatArg())
.then(CommandManager.argument("Min Force", FloatArgumentType.floatArg())
.then(CommandManager.argument("Max Force", FloatArgumentType.floatArg())
.executes { context ->
forceFieldAddArg(context, access, "Sphere")
Command.SINGLE_SUCCESS
}
)
)
)
)
.then(CommandManager.literal("Cube")
.then(CommandManager.argument("Size X", FloatArgumentType.floatArg())
.then(CommandManager.argument("Size Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Size Z", FloatArgumentType.floatArg())
.then(CommandManager.argument("Dir X", FloatArgumentType.floatArg())
.then(CommandManager.argument("Dir Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Dir Z", FloatArgumentType.floatArg())
.then(CommandManager.argument("Force", FloatArgumentType.floatArg())
.executes { context ->
forceFieldAddArg(context, access, "Cube")
Command.SINGLE_SUCCESS
}
)
)
)
)
)
)
)
)
)
)
)
)
.then(CommandManager.literal("Remove")
.then(CommandManager.argument("Index", IntegerArgumentType.integer())
.executes { context ->
val index = IntegerArgumentType.getInteger(context, "Index")
forceFieldRemoveArg(context, access, index)
Command.SINGLE_SUCCESS
}
)
.executes { context ->
forceFieldRemoveArg(context, access, -1)
Command.SINGLE_SUCCESS
}
)
}
fun forceFieldAddArg(context: CommandContext<ServerCommandSource>,
access: KProperty1<EmitterParams, ParamClasses.ForceFieldArray>,
shape: String
) {
val id = StringArgumentType.getString(context, "Emitter ID")
val x = FloatArgumentType.getFloat(context, "X")
val y = FloatArgumentType.getFloat(context, "Y")
val z = FloatArgumentType.getFloat(context, "Z")
val forceFields = getEmitterDataById(id)?.forceFields
var forceField: ForceField? = null
if (shape == "Sphere") {
val radius = FloatArgumentType.getFloat(context, "Radius")
val minForce = FloatArgumentType.getFloat(context, "Min Force")
val maxForce = FloatArgumentType.getFloat(context, "Max Force")
forceField = ForceField(
Vector3f(x, y, z),
ForceFieldShape.Sphere(radius, Pair(minForce, maxForce))
)
}
if (forceFields != null && forceField != null) {
forceFields.array.toMutableList().apply { add(forceField) }.toTypedArray()
updateParam(id, access, forceFields)
successText(access, "++ForceField", id, context)
}
else {
negativeFeedback("Failed to update param \"forceFields\"! The Emitter ID is most likely invalid!", context)
}
}
fun forceFieldRemoveArg(context: CommandContext<ServerCommandSource>,
access: KProperty1<EmitterParams, ParamClasses.ForceFieldArray>,
index: Int
) {
val id = StringArgumentType.getString(context, "Emitter ID")
val forceFields = getEmitterDataById(id)?.forceFields
if (index == -1 && forceFields != null) {
forceFields.array.toMutableList().apply { removeLast() }.toTypedArray()
updateParam(id, access, forceFields)
}
else if (forceFields != null) {
forceFields.array.toMutableList().apply { removeAt(index.coerceIn(0, forceFields.array.lastIndex)) }.toTypedArray()
updateParam(id, access, forceFields)
}
successText(access, "--item at $index", id, context)
}
@@ -22,7 +22,7 @@ data class EmitterParams (
var initScale: ParamClasses.PairVec3f,
var transformWithVel: ParamClasses.TransformWithVel,
// velocity
var forceFields: Array<ForceField>,
var forceFields: ParamClasses.ForceFieldArray,
var constVel: Vector3f,
var drag: Float,
var minVel: Float,
@@ -49,11 +49,11 @@ data class EmitterParams (
initCenterVel = ParamClasses.PairFloat(0.4f, 0.5f),
initScale = ParamClasses.PairVec3f.Uniform(0.5f, 1.5f),
transformWithVel = ParamClasses.TransformWithVel.None,
forceFields = emptyArray(),
forceFields = ParamClasses.ForceFieldArray(emptyArray()),
constVel = Vector3f(0.0f, 0.0f, 0.0f),
drag = 0.075f,
minVel = 0.0f,
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
offsetCurve = ParamClasses.LerpVal.Null,
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Sqrt),
scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 2.5f, LerpCurves.Linear),
modelCurve = ParamClasses.StringCurve(
@@ -83,11 +83,11 @@ data class EmitterParams (
initCenterVel = ParamClasses.PairFloat(1.5f, 1.5f),
initScale = ParamClasses.PairVec3f.Uniform(2.0f, 2.0f),
transformWithVel = ParamClasses.TransformWithVel.ScaleAndRot(0.75f),
forceFields = emptyArray(),
forceFields = ParamClasses.ForceFieldArray(emptyArray()),
constVel = Vector3f(0.0f, -0.05f, 0.0f),
drag = 0.075f,
minVel = 0.0f,
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
offsetCurve = ParamClasses.LerpVal.Null,
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Linear),
scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 1.0f, LerpCurves.Linear),
modelCurve = ParamClasses.StringCurve(
@@ -117,15 +117,16 @@ data class EmitterParams (
initCenterVel = ParamClasses.PairFloat(-1.5f, -1.5f),
initScale = ParamClasses.PairVec3f.Uniform(10.0f, 15.0f),
transformWithVel = ParamClasses.TransformWithVel.None,
forceFields = arrayOf(ForceField(
"MUSHROOM_HEAD",
Vector3f(0.0f, 75.0f, 0.0f),
ForceFieldShape.Sphere(15.0f, Pair(0.1f, 0.2f))
)),
forceFields = ParamClasses.ForceFieldArray(
arrayOf(ForceField(
Vector3f(0.0f, 75.0f, 0.0f),
ForceFieldShape.Sphere(15.0f, Pair(0.1f, 0.2f))
))
),
constVel = Vector3f(0.0f, 0.001f, 0.0f),
drag = 0.075f,
minVel = 0.0f,
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
offsetCurve = ParamClasses.LerpVal.Null,
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Linear),
scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 1.5f, LerpCurves.Linear),
modelCurve = ParamClasses.StringCurve(
@@ -3,7 +3,6 @@ package com.bytedice.bde_particles.particles
import org.joml.Vector3f
data class ForceField (
val name: String = "DEFAULT",
val pos: Vector3f = Vector3f(0.0f, 5.0f, 0.0f),
val shape: ForceFieldShape = ForceFieldShape.Sphere()
val pos: Vector3f,
val shape: ForceFieldShape
)
@@ -94,7 +94,7 @@ class ParamClasses {
return com.bytedice.bde_particles.lerp(from, to, curve.function(t))
}
}
data object NoLerpVec3f : LerpVal()
data object Null : LerpVal()
fun lerpToVector3f(t: Float) : Vector3f {
when (this) {
@@ -104,7 +104,7 @@ class ParamClasses {
val x = this.lerp(t)
return Vector3f(x, x, x)
}
is NoLerpVec3f -> return Vector3f(1.0f, 1.0f, 1.0f)
is Null -> return Vector3f(1.0f, 1.0f, 1.0f)
}
}
}
@@ -162,4 +162,7 @@ class ParamClasses {
) {
fun lerp(t: Float) : String { return lerpArray(array as Array<Any>, t, curve) as String }
}
data class ForceFieldArray (
val array: Array<ForceField>
)
}
@@ -157,7 +157,7 @@ class Particle(
pos = newPos
for (forceField in emitterParams.forceFields) {
for (forceField in emitterParams.forceFields.array) {
if (forceField.shape is ForceFieldShape.Sphere) { vel.add(sphereSdfVel(forceField)) }
else if (forceField.shape is ForceFieldShape.Cube) { vel.add(cubeSdfVel(forceField)) }
}
@@ -27,7 +27,7 @@ fun addToRegister(id: String, params: EmitterParams) : Pair<String, Boolean> {
val newModels: MutableList<String> = mutableListOf()
for (model in params.modelCurve.first) {
for (model in params.modelCurve.array) {
val modelModIdRegex = ".*:".toRegex()
if (modelModIdRegex.containsMatchIn(model)) { break }
else {
@@ -35,7 +35,7 @@ fun addToRegister(id: String, params: EmitterParams) : Pair<String, Boolean> {
}
}
params.modelCurve = Pair(newModels.toTypedArray(), params.modelCurve.second)
params.modelCurve = ParamClasses.StringCurve(newModels.toTypedArray(), params.modelCurve.curve)
idRegister[id] = params
println("BPS - Registered Emitter ID \"$newId\".")
@@ -118,12 +118,12 @@ sealed class SpawningShape() {
sealed class ForceFieldShape {
data class Sphere(
val radius: Float = 3.0f,
val force: Pair<Float, Float> = Pair(0.0f, 0.02f),
val radius: Float,
val force: Pair<Float, Float>,
) : ForceFieldShape()
data class Cube(
val size: Vector3f = Vector3f(1.0f, 1.0f, 1.0f),
val dir: Vector3f = Vector3f(0.0f, 1.0f, 0.0f),
val force: Float = 0.02f
val size: Vector3f,
val dir: Vector3f,
val force: Float
) : ForceFieldShape()
}