diff --git a/src/client/kotlin/com/bytedice/bde_particles/client/Bde_particlesClient.kt b/src/client/kotlin/com/bytedice/bde_particles/client/Bde_particlesClient.kt index 9f6feb0..beb0108 100644 --- a/src/client/kotlin/com/bytedice/bde_particles/client/Bde_particlesClient.kt +++ b/src/client/kotlin/com/bytedice/bde_particles/client/Bde_particlesClient.kt @@ -2,6 +2,7 @@ package com.bytedice.bde_particles.client import com.bytedice.bde_particles.commands.GiveEmitterTool 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.init import com.bytedice.bde_particles.onRightClick @@ -40,6 +41,7 @@ class Bde_particlesClient : ClientModInitializer { GiveEmitterTool.register(dispatcher, registryAccess) //ManageEmitters .register(dispatcher) KillAllEmitters.register(dispatcher) + SpawnEmitter .register(dispatcher) } UseItemCallback.EVENT.register(UseItemCallback { player: PlayerEntity, world: World, hand: Hand -> diff --git a/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt b/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt index b8473ac..a6c1c0c 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt @@ -2,9 +2,13 @@ package com.bytedice.bde_particles import com.bytedice.bde_particles.commands.GiveEmitterTool 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.items.ParticleEmitterTool 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.awaitAll import kotlinx.coroutines.runBlocking @@ -23,37 +27,35 @@ import net.minecraft.entity.player.PlayerEntity import net.minecraft.item.ItemStack import net.minecraft.nbt.NbtCompound 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.world.ServerWorld +import net.minecraft.text.Style +import net.minecraft.text.Text import net.minecraft.util.ActionResult import net.minecraft.util.Hand import net.minecraft.util.TypedActionResult import net.minecraft.world.GameRules import net.minecraft.world.World import org.joml.Vector2f +import java.awt.Color import java.util.* +import java.util.concurrent.CompletableFuture // TODO: (future additions) // 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. - // not implementing in v1.0. Maybe in v2.0. - -// Emitter groups (multiple emitters for EmitterTool) - -// Private functions/classes +// Copying particle params in-game // TODO: (project) // fix ManageEmitter command // 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 = emptyArray() @@ -90,6 +92,7 @@ class Bde_particles : ModInitializer { GiveEmitterTool.register(dispatcher, registryAccess) //ManageEmitters .register(dispatcher) KillAllEmitters.register(dispatcher) + SpawnEmitter .register(dispatcher) } UseItemCallback.EVENT.register(UseItemCallback { player: PlayerEntity, world: World, hand: Hand -> @@ -117,9 +120,9 @@ class Bde_particles : ModInitializer { fun init() { - addToRegister("DEFAULT", EmitterParams.DEFAULT, 137) - addToRegister("DEBUG", EmitterParams.DEBUG, 137) - addToRegister("STRESS_TEST", EmitterParams.STRESS_TEST, 1532) + addToRegister("DEFAULT", EmitterParams.DEFAULT) + addToRegister("DEBUG", EmitterParams.DEBUG) + addToRegister("STRESS_TEST", EmitterParams.STRESS_TEST) } @@ -177,35 +180,46 @@ fun onRightClick(player: PlayerEntity, world: ServerWorld, hand: Hand) : TypedAc emitterParams, debug ) - ALL_PARTICLE_EMITTERS += emitter + spawnEmitter(emitter) return TypedActionResult(ActionResult.PASS, handItem) } -/* -fun emitterParamsToJson(params: EmitterParams) : Map { // TODO: map to new params - val allParamsJson: MutableList> = 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 { val nbt = NbtCompound() entity.writeNbt(nbt) val tagsNbtList = nbt.getList("Tags", 8) return tagsNbtList?.any { it.asString() == tag } == true +} + + +fun emitterListArg (argName: String) : RequiredArgumentBuilder { + 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) { + 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) { + val feedback = Text.literal("BPS - $text") + .setStyle(Style.EMPTY.withColor(Color(200, 0, 0).rgb)) + + context.source.sendFeedback({ feedback }, false) } \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/commands/ManageConfigArgs.kt b/src/main/kotlin/com/bytedice/bde_particles/commands/ManageConfigArgs.kt deleted file mode 100644 index 7e8fa4f..0000000 --- a/src/main/kotlin/com/bytedice/bde_particles/commands/ManageConfigArgs.kt +++ /dev/null @@ -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, 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, 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - return CommandManager.literal("forceFields") - .then(argAddForceField()) - .then(argRemoveForceField()) - } - fun gravity() : LiteralArgumentBuilder { - 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 { - 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 { - 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 { - 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 { - 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 { - 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) : Pair { - 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 { - 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 { // 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 = 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) : 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) : 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, 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 - ) -} -*/ \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/commands/ManageEmitters.kt b/src/main/kotlin/com/bytedice/bde_particles/commands/ManageEmitters.kt index 3463b88..19611f7 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/commands/ManageEmitters.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/commands/ManageEmitters.kt @@ -1,24 +1,18 @@ 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.positiveFeedback import com.mojang.brigadier.Command import com.mojang.brigadier.CommandDispatcher import com.mojang.brigadier.arguments.StringArgumentType -import com.mojang.brigadier.builder.LiteralArgumentBuilder 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.ServerCommandSource -import net.minecraft.text.MutableText import net.minecraft.text.Style import net.minecraft.text.Text -import net.minecraft.text.TextColor import java.awt.Color -import java.util.concurrent.CompletableFuture // TODO: completely redesign @@ -56,7 +50,7 @@ blockCurve: Pair, LerpCurves>, // ManageEmitters -// +// // create // // @@ -68,7 +62,6 @@ blockCurve: Pair, LerpCurves>, // config // - // // // // output -> update the selected parameter of the selected emitter id to the new value @@ -82,7 +75,6 @@ blockCurve: Pair, LerpCurves>, object ManageEmitters { - val allEmitterIds = idRegister.keys fun register(dispatcher: CommandDispatcher) { val command = CommandManager.literal("ManageEmitters") @@ -90,6 +82,102 @@ object ManageEmitters { dispatcher.register( 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 { + 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 { + 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 { + return emitterList("Emitter ID") + .then( + + ) + }*/ + + // I am not going to torture myself by converting this to a json. + /* + private fun copy() : RequiredArgumentBuilder { + return emitterList("Emitter ID").executes { context -> + val emitterId = StringArgumentType.getString(context, "Emitter ID") + + Command.SINGLE_SUCCESS + } + } + */ +} \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/commands/SpawnEmitter.kt b/src/main/kotlin/com/bytedice/bde_particles/commands/SpawnEmitter.kt index 0cf57ed..2204f50 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/commands/SpawnEmitter.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/commands/SpawnEmitter.kt @@ -1,9 +1,17 @@ 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.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.ServerCommandSource -import net.minecraft.server.command.SummonCommand +import net.minecraft.util.math.Vec3d +import org.joml.Vector2f object SpawnEmitter { @@ -12,6 +20,42 @@ object SpawnEmitter { .requires { source -> source.hasPermissionLevel(2) } 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, 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) + } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleIdRegister.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleIdRegister.kt index c195c87..efa44e1 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleIdRegister.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleIdRegister.kt @@ -5,7 +5,7 @@ val idRegister: MutableMap = mutableMapOf() val forbiddenIds = arrayOf("", "NULL") -fun addToRegister(id: String, params: EmitterParams, cacheLength: Int) : Pair { +fun addToRegister(id: String, params: EmitterParams) : Pair { val newId = replaceForbiddenChars(id.replace(" ", "_")) if (idRegister.containsKey(newId)) { @@ -14,7 +14,7 @@ fun addToRegister(id: String, params: EmitterParams, cacheLength: Int) : Pair