remade ManageEmitters command (except config). Added SpawnEmitter command.

This commit is contained in:
2024-12-07 14:31:34 +01:00
parent ad9ef87874
commit 0b17f8688c
6 changed files with 199 additions and 657 deletions
@@ -2,6 +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.SpawnEmitter
//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
@@ -40,6 +41,7 @@ class Bde_particlesClient : ClientModInitializer {
GiveEmitterTool.register(dispatcher, registryAccess) GiveEmitterTool.register(dispatcher, registryAccess)
//ManageEmitters .register(dispatcher) //ManageEmitters .register(dispatcher)
KillAllEmitters.register(dispatcher) KillAllEmitters.register(dispatcher)
SpawnEmitter .register(dispatcher)
} }
UseItemCallback.EVENT.register(UseItemCallback { player: PlayerEntity, world: World, hand: Hand -> UseItemCallback.EVENT.register(UseItemCallback { player: PlayerEntity, world: World, hand: Hand ->
@@ -2,9 +2,13 @@ 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.SpawnEmitter
//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 com.mojang.brigadier.arguments.StringArgumentType
import com.mojang.brigadier.builder.RequiredArgumentBuilder
import com.mojang.brigadier.context.CommandContext
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@@ -23,37 +27,35 @@ import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtCompound
import net.minecraft.server.MinecraftServer import net.minecraft.server.MinecraftServer
import net.minecraft.server.command.CommandManager
import net.minecraft.server.command.ServerCommandSource
import net.minecraft.server.network.ServerPlayerEntity import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.server.world.ServerWorld import net.minecraft.server.world.ServerWorld
import net.minecraft.text.Style
import net.minecraft.text.Text
import net.minecraft.util.ActionResult import net.minecraft.util.ActionResult
import net.minecraft.util.Hand import net.minecraft.util.Hand
import net.minecraft.util.TypedActionResult import net.minecraft.util.TypedActionResult
import net.minecraft.world.GameRules import net.minecraft.world.GameRules
import net.minecraft.world.World import net.minecraft.world.World
import org.joml.Vector2f import org.joml.Vector2f
import java.awt.Color
import java.util.* import java.util.*
import java.util.concurrent.CompletableFuture
// TODO: (future additions) // TODO: (future additions)
// Allowing the use of regular Minecraft particles instead of just BDEs. // Allowing the use of regular Minecraft particles instead of just BDEs.
// not implementing in v1.0. Maybe in v2.0.
// Better command auto-completion. (and change names of args)
// force field "config" option
// Custom curve equation command args (parse from strings)
// Cylinder and cone force field shape. // Cylinder and cone force field shape.
// not implementing in v1.0. Maybe in v2.0. // Copying particle params in-game
// Emitter groups (multiple emitters for EmitterTool)
// Private functions/classes
// TODO: (project) // TODO: (project)
// fix ManageEmitter command // fix ManageEmitter command
// add SpawnEmitter command for spawning emitters via commands // add SpawnEmitter command for spawning emitters via commands
// Custom curve equation command args (parse from strings)
// Better command auto-completion. (and change names of args)
// force field "config" option
var ALL_PARTICLE_EMITTERS: Array<ParticleEmitter> = emptyArray() var ALL_PARTICLE_EMITTERS: Array<ParticleEmitter> = emptyArray()
@@ -90,6 +92,7 @@ class Bde_particles : ModInitializer {
GiveEmitterTool.register(dispatcher, registryAccess) GiveEmitterTool.register(dispatcher, registryAccess)
//ManageEmitters .register(dispatcher) //ManageEmitters .register(dispatcher)
KillAllEmitters.register(dispatcher) KillAllEmitters.register(dispatcher)
SpawnEmitter .register(dispatcher)
} }
UseItemCallback.EVENT.register(UseItemCallback { player: PlayerEntity, world: World, hand: Hand -> UseItemCallback.EVENT.register(UseItemCallback { player: PlayerEntity, world: World, hand: Hand ->
@@ -117,9 +120,9 @@ class Bde_particles : ModInitializer {
fun init() { fun init() {
addToRegister("DEFAULT", EmitterParams.DEFAULT, 137) addToRegister("DEFAULT", EmitterParams.DEFAULT)
addToRegister("DEBUG", EmitterParams.DEBUG, 137) addToRegister("DEBUG", EmitterParams.DEBUG)
addToRegister("STRESS_TEST", EmitterParams.STRESS_TEST, 1532) addToRegister("STRESS_TEST", EmitterParams.STRESS_TEST)
} }
@@ -177,31 +180,12 @@ fun onRightClick(player: PlayerEntity, world: ServerWorld, hand: Hand) : TypedAc
emitterParams, emitterParams,
debug debug
) )
ALL_PARTICLE_EMITTERS += emitter spawnEmitter(emitter)
return TypedActionResult(ActionResult.PASS, handItem) return TypedActionResult(ActionResult.PASS, handItem)
} }
/*
fun emitterParamsToJson(params: EmitterParams) : Map<String, Any> { // TODO: map to new params
val allParamsJson: MutableList<Map<String, Any?>> = mutableListOf()
val paramsJson = mapOf(
"shape" to params.shape
)
allParamsJson.add(paramsJson)
val emitterParamsJSON = mapOf(
"maxCount" to params.maxCount,
)
return emitterParamsJSON
}
*/
fun displayEntityContainsTag(entity: ItemDisplayEntity, tag: String) : Boolean { fun displayEntityContainsTag(entity: ItemDisplayEntity, tag: String) : Boolean {
val nbt = NbtCompound() val nbt = NbtCompound()
entity.writeNbt(nbt) entity.writeNbt(nbt)
@@ -209,3 +193,33 @@ fun displayEntityContainsTag(entity: ItemDisplayEntity, tag: String) : Boolean {
return tagsNbtList?.any { it.asString() == tag } == true return tagsNbtList?.any { it.asString() == tag } == true
} }
fun emitterListArg (argName: String) : RequiredArgumentBuilder<ServerCommandSource, String> {
return CommandManager.argument(argName, StringArgumentType.string())
.suggests { _, builder ->
idRegister.keys.forEach { key ->
builder.suggest(key)
}
CompletableFuture.completedFuture(builder.build())
}
}
fun spawnEmitter(emitter: ParticleEmitter) {
ALL_PARTICLE_EMITTERS += emitter
}
fun positiveFeedback(text: String, context: CommandContext<ServerCommandSource>) {
val feedback = Text.literal("BPS - $text")
.setStyle(Style.EMPTY.withColor(Color(0, 200, 0).rgb))
context.source.sendFeedback({ feedback }, false)
}
fun negativeFeedback(text: String, context: CommandContext<ServerCommandSource>) {
val feedback = Text.literal("BPS - $text")
.setStyle(Style.EMPTY.withColor(Color(200, 0, 0).rgb))
context.source.sendFeedback({ feedback }, false)
}
@@ -1,606 +0,0 @@
package com.bytedice.bde_particles.commands
import com.bytedice.bde_particles.LerpCurves
import com.bytedice.bde_particles.particles.*
import com.mojang.brigadier.Command
import com.mojang.brigadier.arguments.BoolArgumentType
import com.mojang.brigadier.arguments.FloatArgumentType
import com.mojang.brigadier.arguments.IntegerArgumentType
import com.mojang.brigadier.arguments.StringArgumentType
import com.mojang.brigadier.builder.LiteralArgumentBuilder
import com.mojang.brigadier.context.CommandContext
import net.minecraft.server.command.CommandManager
import net.minecraft.server.command.ServerCommandSource
import net.minecraft.text.MutableText
import net.minecraft.text.Style
import net.minecraft.text.Text
import org.joml.Vector2f
import org.joml.Vector3f
import java.awt.Color
import java.util.concurrent.CompletableFuture
// TODO: completely redesign
/*
// 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")
fun updateEmitterParam(context: CommandContext<ServerCommandSource>, paramName: String, typeValue: Any) : MutableText {
val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID")
val success = updateSingleEmitterParam(emitterIdVal, paramName, typeValue)
val feedback = if (success) {
Text.literal("BPS - Successfully updated 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\": Parameter \"$paramName\", value \"$typeValue\": Unknown Error\n" +
"Try checking if the emitter and parameter exist, and the value is the correct type.")
.setStyle(Style.EMPTY.withColor(Color(200, 0, 0).rgb))
}
return feedback
}
fun updateParticleParam(context: CommandContext<ServerCommandSource>, paramName: String, typeValue: Any) : MutableText {
val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID")
val success = updateSingleParticleParam(emitterIdVal, paramName, typeValue)
val feedback = if (success) {
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\": 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))
}
return feedback
}
class ArgConfigEmitterKeys {
fun maxCount() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("maxCount")
.then(CommandManager.argument("Int", IntegerArgumentType.integer())
.executes { context ->
val typeValue = IntegerArgumentType.getInteger(context, "Int")
val feedback = updateEmitterParam(context, "maxCount", typeValue)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
}
fun spawnsPerTick() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("spawnsPerTick")
.then(CommandManager.argument("Int", IntegerArgumentType.integer())
.executes { context ->
val typeValue = IntegerArgumentType.getInteger(context, "Int")
val feedback = updateEmitterParam(context, "spawnsPerTick", typeValue)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
}
fun loopDur() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("loopDur")
.then(CommandManager.argument("Int", IntegerArgumentType.integer())
.executes { context ->
val typeValue = IntegerArgumentType.getInteger(context, "Int")
val feedback = updateEmitterParam(context, "loopDur", typeValue)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
}
fun loopDelay() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("loopDelay")
.then(CommandManager.argument("Int", IntegerArgumentType.integer())
.executes { context ->
val typeValue = IntegerArgumentType.getInteger(context, "Int")
val feedback = updateEmitterParam(context, "loopDelay", typeValue)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
}
fun loopCount() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("loopCount")
.then(CommandManager.argument("Int", IntegerArgumentType.integer())
.executes { context ->
val typeValue = IntegerArgumentType.getInteger(context, "Int")
val feedback = updateEmitterParam(context, "loopCount", typeValue)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
}
}
class ArgConfigParticleKeys {
fun shape() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("shape")
.then(CommandManager.literal("circle")
.then(CommandManager.argument("Radius", FloatArgumentType.floatArg())
.executes { context ->
val radius = FloatArgumentType.getFloat(context, "Radius")
val feedback = updateParticleParam(context, "shape", SpawningShape.Circle(radius))
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
)
)
.then(CommandManager.literal("rect")
.then(CommandManager.argument("Width", FloatArgumentType.floatArg())
.then(CommandManager.argument("Height", FloatArgumentType.floatArg())
.executes { context ->
val w = FloatArgumentType.getFloat(context, "Width")
val h = FloatArgumentType.getFloat(context, "Height")
val feedback = updateParticleParam(context, "shape", SpawningShape.Rect(Vector2f(w, h)))
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
)
)
)
.then(CommandManager.literal("cube")
.then(CommandManager.argument("X", FloatArgumentType.floatArg())
.then(CommandManager.argument("Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Z", FloatArgumentType.floatArg())
.executes { context ->
val x = FloatArgumentType.getFloat(context, "X")
val y = FloatArgumentType.getFloat(context, "Y")
val z = FloatArgumentType.getFloat(context, "Z")
val feedback = updateParticleParam(context, "shape", SpawningShape.Cube(Vector3f(x, y, z)))
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
)
)
)
)
.then(CommandManager.literal("sphere")
.then(CommandManager.argument("Radius", FloatArgumentType.floatArg())
.executes { context ->
val radius = FloatArgumentType.getFloat(context, "Radius")
val feedback = updateParticleParam(context, "shape", SpawningShape.Sphere(radius))
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
)
)
.then(CommandManager.literal("point")
.executes { context ->
val feedback = updateParticleParam(context, "shape", SpawningShape.Point)
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
)
}
fun blockCurve() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("blockCurve")
.then(CommandManager.argument("Array (separate by comma)", StringArgumentType.string())
.executes { context ->
val typeValue = StringArgumentType.getString(context, "Array (separate by comma)")
val typeArray = typeValue.split(",").toTypedArray()
val feedback = updateParticleParam(context, "blockCurve", typeArray)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
}
fun rotRandom() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("rotRandom")
.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())
.executes { context ->
val vectors = x1x2ToPairVector3f(context)
val feedback = updateParticleParam(context, "rotRandom", vectors)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
)
)
)
)
)
}
fun rotVelRandom() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("rotVelRandom")
.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())
.executes { context ->
val vectors = x1x2ToPairVector3f(context)
val feedback = updateParticleParam(context, "rotVelRandom", vectors)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
)
)
)
)
)
}
fun sizeRandom() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("sizeRandom")
.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())
.executes { context ->
val vectors = x1x2ToPairVector3f(context)
val feedback = updateParticleParam(context, "sizeRandom", vectors)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
)
)
)
)
)
}
fun uniformSize() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("uniformSize")
.then(CommandManager.argument("Bool", BoolArgumentType.bool())
.executes { context ->
val uniform = BoolArgumentType.getBool(context, "Bool")
val feedback = updateParticleParam(context, "uniformSize", uniform)
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
)
}
fun velRandom() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("velRandom")
.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())
.executes { context ->
val vectors = x1x2ToPairVector3f(context)
val feedback = updateParticleParam(context, "velRandom", vectors)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
)
)
)
)
)
}
fun forceFields() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("forceFields")
.then(argAddForceField())
.then(argRemoveForceField())
}
fun gravity() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("gravity")
.then(CommandManager.argument("X", FloatArgumentType.floatArg())
.then(CommandManager.argument("Y", FloatArgumentType.floatArg())
.then(CommandManager.argument("Z", FloatArgumentType.floatArg())
.executes { context ->
val x1 = FloatArgumentType.getFloat(context, "X")
val y1 = FloatArgumentType.getFloat(context, "Y")
val z1 = FloatArgumentType.getFloat(context, "Z")
val feedback = updateParticleParam(context, "gravity", Vector3f(x1, y1, z1))
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
)
)
}
fun drag() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("drag")
.then(CommandManager.argument("Float", FloatArgumentType.floatArg())
.executes { context ->
val value = FloatArgumentType.getFloat(context, "Float")
val feedback = updateParticleParam(context, "drag", value)
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
)
}
fun minVel() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("minVel")
.then(CommandManager.argument("Float", FloatArgumentType.floatArg())
.executes { context ->
val value = FloatArgumentType.getFloat(context, "Float")
val feedback = updateParticleParam(context, "minVel", value)
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
)
}
fun lifeTime() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("lifeTime")
.then(CommandManager.argument("min", IntegerArgumentType.integer())
.then(CommandManager.argument("max", IntegerArgumentType.integer())
.executes { context ->
val min = IntegerArgumentType.getInteger(context, "min")
val max = IntegerArgumentType.getInteger(context, "max")
val feedback = updateParticleParam(context, "lifeTime", Pair(min, max))
context.source.sendFeedback( { feedback }, false)
Command.SINGLE_SUCCESS
}
)
)
}
fun rotVelCurve() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("rotVelCurve")
.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(CommandManager.argument("Curve", StringArgumentType.string())
.suggests { _, builder ->
curves.forEach { builder.suggest(it) }
CompletableFuture.completedFuture(builder.build())
}
.executes { context ->
val vectors = x1x2ToPairVector3f(context)
val curveString = StringArgumentType.getString(context, "Curve")
val feedback = updateParticleParam(
context,
"rotVelCurve",
Triple(vectors.first, vectors.second, getCurveByString(curveString)))
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
)
)
)
)
)
)
}
fun sizeCurve() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("sizeCurve")
.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(CommandManager.argument("Curve", StringArgumentType.string())
.suggests { _, builder ->
curves.forEach { builder.suggest(it) }
CompletableFuture.completedFuture(builder.build())
}
.executes { context ->
val vectors = x1x2ToPairVector3f(context)
val curveString = StringArgumentType.getString(context, "Curve")
val feedback = updateParticleParam(
context,
"sizeCurve",
Triple(vectors.first, vectors.second, getCurveByString(curveString)))
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
)
)
)
)
)
)
}
}
fun getCurveByString(str: String) : LerpCurves {
return when (str) {
"LINEAR" -> LerpCurves.Linear
"SQRT" -> LerpCurves.Sqrt
"EXPONENT" -> LerpCurves.Exponent
"CUBIC" -> LerpCurves.Cubic
"SINE" -> LerpCurves.Sine
"COSINE" -> LerpCurves.Cosine
"INVERSE" -> LerpCurves.Inverse
"LOG" -> LerpCurves.Log
"EXP" -> LerpCurves.Exp
"BOUNCE" -> LerpCurves.Bounce
else -> LerpCurves.Linear
}
}
fun x1x2ToPairVector3f(context: CommandContext<ServerCommandSource>) : Pair<Vector3f, Vector3f> {
val x1 = FloatArgumentType.getFloat(context, "Min X")
val y1 = FloatArgumentType.getFloat(context, "Min Y")
val z1 = FloatArgumentType.getFloat(context, "Min Z")
val x2 = FloatArgumentType.getFloat(context, "Max X")
val y2 = FloatArgumentType.getFloat(context, "Max Y")
val z2 = FloatArgumentType.getFloat(context, "Max Z")
return Pair(Vector3f(x1, y1, z1), Vector3f(x2, y2, z2))
}
fun argAddForceField() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("add")
.then(CommandManager.argument("Name", StringArgumentType.string())
.then(CommandManager.argument("X Pos", FloatArgumentType.floatArg())
.then(CommandManager.argument("Y Pos", FloatArgumentType.floatArg())
.then(CommandManager.argument("Z Pos", 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 -> forceFieldAddSphereExec(context) }
)
)
)
)
.then(CommandManager.literal("cube")
.then(CommandManager.argument("X Size", FloatArgumentType.floatArg())
.then(CommandManager.argument("Y Size", FloatArgumentType.floatArg())
.then(CommandManager.argument("Z Size", FloatArgumentType.floatArg())
.then(CommandManager.argument("X Force", FloatArgumentType.floatArg())
.then(CommandManager.argument("Y Force", FloatArgumentType.floatArg())
.then(CommandManager.argument("Z Force", FloatArgumentType.floatArg())
.executes { context -> forceFieldAddCubeExec(context) }
)
)
)
)
)
)
)
)
)
)
)
}
fun argRemoveForceField() : LiteralArgumentBuilder<ServerCommandSource> { // TODO fix this error somehow
return CommandManager.literal("remove")
.then(CommandManager.argument("Force Field Name", StringArgumentType.string())
.suggests { context, builder ->
val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID")
val params = getEmitterParams(emitterIdVal)
val forceFields = params!!.particle.forceFields
for (forceField in forceFields) {
builder.suggest(forceField.name)
}
CompletableFuture.completedFuture(builder.build())
}
.executes { context ->
val ffName = StringArgumentType.getString(context, "Force Field Name")
val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID")
val params = getEmitterParams(emitterIdVal)
val forceFields = params!!.particle.forceFields
val newForceFields: MutableList<ForceField> = forceFields.toMutableList()
if (forceFields.isEmpty()) {
val feedback = Text.literal("BPS - There are no force fields for Emitter ID \"$emitterIdVal\".")
.setStyle(Style.EMPTY.withColor(Color(200, 0, 0).rgb))
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
else {
for (forceField in forceFields) {
if (forceField.name == ffName) {
newForceFields.apply { remove(forceField) }
}
}
val feedback = updateParticleParam(
context,
"forceFields",
newForceFields.toTypedArray()
)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
}
)
}
fun forceFieldAddSphereExec(context: CommandContext<ServerCommandSource>) : Int {
val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID")
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!!.particle.forceFields
val addedArray = forceFields.toMutableList().apply { add(forceField) }.toTypedArray()
val feedback = updateParticleParam(
context,
"forceFields",
addedArray
)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
return Command.SINGLE_SUCCESS
}
fun forceFieldAddCubeExec(context: CommandContext<ServerCommandSource>) : Int {
val xSize = FloatArgumentType.getFloat(context, "X Size")
val ySize = FloatArgumentType.getFloat(context, "Y Size")
val zSize = FloatArgumentType.getFloat(context, "Z Size")
val xForce = FloatArgumentType.getFloat(context, "X Force")
val yForce = FloatArgumentType.getFloat(context, "Y Force")
val zForce = FloatArgumentType.getFloat(context, "Z Force")
val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID")
val shape = ForceFieldShape.Cube(Vector3f(xSize, ySize, zSize), Vector3f(xForce, yForce, zForce))
val forceField = forceFieldGenericParams(context, shape)
val currentParams = getEmitterParams(emitterIdVal)
val forceFields = currentParams!!.particle.forceFields
val addedArray = forceFields.toMutableList().apply { add(forceField) }.toTypedArray()
val feedback = updateParticleParam(
context,
"forceFields",
addedArray
)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
return Command.SINGLE_SUCCESS
}
fun forceFieldGenericParams(context: CommandContext<ServerCommandSource>, shape: ForceFieldShape) : ForceField {
val name = StringArgumentType.getString(context, "Name")
val posX = FloatArgumentType.getFloat(context, "X Pos")
val posY = FloatArgumentType.getFloat(context, "Y Pos")
val posZ = FloatArgumentType.getFloat(context, "Z Pos")
return ForceField(
name.replace(" ", "_"),
Vector3f(posX, posY, posZ),
shape
)
}
*/
@@ -1,24 +1,18 @@
package com.bytedice.bde_particles.commands package com.bytedice.bde_particles.commands
import com.bytedice.bde_particles.emitterListArg
import com.bytedice.bde_particles.negativeFeedback
import com.bytedice.bde_particles.particles.* import com.bytedice.bde_particles.particles.*
import com.bytedice.bde_particles.positiveFeedback
import com.mojang.brigadier.Command import com.mojang.brigadier.Command
import com.mojang.brigadier.CommandDispatcher import com.mojang.brigadier.CommandDispatcher
import com.mojang.brigadier.arguments.StringArgumentType import com.mojang.brigadier.arguments.StringArgumentType
import com.mojang.brigadier.builder.LiteralArgumentBuilder
import com.mojang.brigadier.builder.RequiredArgumentBuilder import com.mojang.brigadier.builder.RequiredArgumentBuilder
import net.minecraft.component.DataComponentTypes
import net.minecraft.component.type.NbtComponent
import net.minecraft.item.ItemStack
import net.minecraft.item.Items
import net.minecraft.nbt.NbtCompound
import net.minecraft.server.command.CommandManager import net.minecraft.server.command.CommandManager
import net.minecraft.server.command.ServerCommandSource import net.minecraft.server.command.ServerCommandSource
import net.minecraft.text.MutableText
import net.minecraft.text.Style import net.minecraft.text.Style
import net.minecraft.text.Text import net.minecraft.text.Text
import net.minecraft.text.TextColor
import java.awt.Color import java.awt.Color
import java.util.concurrent.CompletableFuture
// TODO: completely redesign // TODO: completely redesign
@@ -56,7 +50,7 @@ blockCurve: Pair<Array<String>, LerpCurves>,
// ManageEmitters // ManageEmitters
// <create / remove / config / list> // <create / remove / config / list / copy>
// create // create
// <emitter id> // <emitter id>
// <preset emitter id> // <preset emitter id>
@@ -68,7 +62,6 @@ blockCurve: Pair<Array<String>, LerpCurves>,
// config // config
// <emitter id> // <emitter id>
// <PARTICLE / EMITTER>
// <param key> // <param key>
// <new param value> // <new param value>
// output -> update the selected parameter of the selected emitter id to the new value // output -> update the selected parameter of the selected emitter id to the new value
@@ -82,7 +75,6 @@ blockCurve: Pair<Array<String>, LerpCurves>,
object ManageEmitters { object ManageEmitters {
val allEmitterIds = idRegister.keys
fun register(dispatcher: CommandDispatcher<ServerCommandSource>) { fun register(dispatcher: CommandDispatcher<ServerCommandSource>) {
val command = CommandManager.literal("ManageEmitters") val command = CommandManager.literal("ManageEmitters")
@@ -90,6 +82,102 @@ object ManageEmitters {
dispatcher.register( dispatcher.register(
command command
.then(CommandManager.literal("create").then(create()))
.then(CommandManager.literal("remove").then(remove()))
.then(CommandManager.literal("config"))
.then(CommandManager.literal("list")
.executes { context ->
val emitterIdList = idRegister.keys.sorted().joinToString(" ")
val feedback = Text.literal("List of all registered Emitter IDs $emitterIdList")
.setStyle(Style.EMPTY.withColor(Color(0, 200, 0).rgb))
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
//.then(CommandManager.literal("copy"))
) )
} }
private fun create() : RequiredArgumentBuilder<ServerCommandSource, String> {
return CommandManager.argument("New Emitter ID", StringArgumentType.string())
.then(emitterListArg("Preset Emitter ID")
.executes { context ->
val newEmitterId = StringArgumentType.getString(context, "New Emitter ID")
val presetEmitterId = StringArgumentType.getString(context, "Preset Emitter ID")
val params = getEmitterDataById(presetEmitterId)
val usedDefault = params == null
val result = addToRegister(
newEmitterId,
if (usedDefault) { EmitterParams.DEFAULT } else { params!! },
)
if (usedDefault && result.second) {
positiveFeedback(
"Successfully added new Emitter with ID \"${result.first}\" to register.\n(DEFAULT params were used as a preset because the specified Preset Emitter ID wasn't valid.)",
context
)
}
else if (!usedDefault && result.second) {
positiveFeedback(
"Successfully added new Emitter with ID \"${result.first}\" and Preset Emitter ID \"$presetEmitterId\" to register.",
context
)
}
else {
negativeFeedback(
"Failed to add new Emitter with ID \"${result.first}\" to register.\nThe provided Emitter ID is either reserved for system use or already in use.",
context
)
}
Command.SINGLE_SUCCESS
}
)
}
private fun remove() : RequiredArgumentBuilder<ServerCommandSource, String> {
return emitterListArg("Emitter ID")
.executes { context ->
val emitterId = StringArgumentType.getString(context, "Emitter ID")
val result = removeFromRegister(emitterId)
if (result) {
positiveFeedback(
"Successfully removed Emitter ID \"$emitterId\" from register.",
context
)
}
else {
negativeFeedback(
"Failed to remove Emitter ID \"$emitterId\" from register.\nThe provided Emitter ID is either reserved for system use or already in use.",
context
)
}
Command.SINGLE_SUCCESS
}
}
/*private fun config() : RequiredArgumentBuilder<ServerCommandSource, String> {
return emitterList("Emitter ID")
.then(
)
}*/
// I am not going to torture myself by converting this to a json.
/*
private fun copy() : RequiredArgumentBuilder<ServerCommandSource, String> {
return emitterList("Emitter ID").executes { context ->
val emitterId = StringArgumentType.getString(context, "Emitter ID")
Command.SINGLE_SUCCESS
}
}
*/
} }
@@ -1,9 +1,17 @@
package com.bytedice.bde_particles.commands package com.bytedice.bde_particles.commands
import com.bytedice.bde_particles.*
import com.bytedice.bde_particles.particles.ParticleEmitter
import com.bytedice.bde_particles.particles.getEmitterDataById
import com.mojang.brigadier.Command
import com.mojang.brigadier.CommandDispatcher import com.mojang.brigadier.CommandDispatcher
import com.mojang.brigadier.arguments.StringArgumentType
import com.mojang.brigadier.context.CommandContext
import net.minecraft.command.argument.Vec3ArgumentType
import net.minecraft.server.command.CommandManager import net.minecraft.server.command.CommandManager
import net.minecraft.server.command.ServerCommandSource import net.minecraft.server.command.ServerCommandSource
import net.minecraft.server.command.SummonCommand import net.minecraft.util.math.Vec3d
import org.joml.Vector2f
object SpawnEmitter { object SpawnEmitter {
@@ -12,6 +20,42 @@ object SpawnEmitter {
.requires { source -> source.hasPermissionLevel(2) } .requires { source -> source.hasPermissionLevel(2) }
dispatcher.register( dispatcher.register(
command.then(emitterListArg("Emitter ID")
.executes { context ->
execute(context, context.source.position)
Command.SINGLE_SUCCESS
}
.then(CommandManager.argument("Pos", Vec3ArgumentType.vec3())
.executes { context ->
val pos = Vec3ArgumentType.getVec3(context, "Pos")
execute(context, pos)
Command.SINGLE_SUCCESS
}
)
)
) )
} }
private fun execute(context: CommandContext<ServerCommandSource>, pos: Vec3d) {
val emitterId = StringArgumentType.getString(context, "Emitter ID")
val emitterParams = getEmitterDataById(emitterId)
val world = context.source.world
if (emitterParams != null) {
val emitter = ParticleEmitter(
pos,
Vector2f(0.0f, 0.0f),
world,
emitterParams,
world.gameRules.getBoolean(Bde_particles.SHOW_PARTICLE_DEBUG)
)
spawnEmitter(emitter)
positiveFeedback("Successfully spawned Emitter ID \"$emitterId\"", context)
}
else {
negativeFeedback("Failed to spawn Emitter ID \"$emitterId\". Emitter ID doesn't exist!", context)
}
}
} }
@@ -5,7 +5,7 @@ val idRegister: MutableMap<String, EmitterParams> = mutableMapOf()
val forbiddenIds = arrayOf("", "NULL") val forbiddenIds = arrayOf("", "NULL")
fun addToRegister(id: String, params: EmitterParams, cacheLength: Int) : Pair<String, Boolean> { fun addToRegister(id: String, params: EmitterParams) : Pair<String, Boolean> {
val newId = replaceForbiddenChars(id.replace(" ", "_")) val newId = replaceForbiddenChars(id.replace(" ", "_"))
if (idRegister.containsKey(newId)) { if (idRegister.containsKey(newId)) {
@@ -14,7 +14,7 @@ fun addToRegister(id: String, params: EmitterParams, cacheLength: Int) : Pair<St
} }
if (newId in forbiddenIds) { if (newId in forbiddenIds) {
println("BPS - Failed to register Emitter ID \"$newId\" as it's been reserved!") println("BPS - Failed to register Emitter ID \"$newId\" as it's been reserved for system use!")
return Pair(newId, false) return Pair(newId, false)
} }