re-added config subcommand, this time better than ever!

This commit is contained in:
2024-11-22 18:38:25 +01:00
parent 986477ef40
commit 90fc0decab
14 changed files with 254 additions and 133 deletions
@@ -1,12 +1,9 @@
@file:Suppress("UNCHECKED_CAST")
package com.bytedice.bde_particles
import com.bytedice.bde_particles.commands.GiveEmitterTool
import com.bytedice.bde_particles.commands.ManageEmitters
import com.bytedice.bde_particles.items.ParticleEmitterTool
import com.bytedice.bde_particles.math.raycastFromPlayer
import com.bytedice.bde_particles.particle.*
import com.bytedice.bde_particles.particleIdRegister.*
import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents
@@ -20,7 +17,6 @@ import net.minecraft.util.ActionResult
import net.minecraft.util.Hand
import net.minecraft.util.TypedActionResult
import net.minecraft.world.World
import org.joml.Vector3f
// TODO: finish the particle ticking
@@ -132,53 +128,3 @@ fun emitterParamsToJson(params: EmitterParams) : Map<String, Any> {
return emitterParamsJSON
}
fun jsonToEmitterParams(json: Map<String, Any>): EmitterParams {
val particleTypes = json["particleTypes"] as? List<*>
?: throw IllegalArgumentException("particleTypes must be a list of ParticleParams")
val allParticleTypes: MutableList<ParticleParams> = mutableListOf()
for (particle in particleTypes.iterator()) {
val particleParams = particle as? ParticleParams ?: ParticleParams.DEFAULT
val updatedParticle = ParticleParams(
shape = (particleParams.shape ?: ParticleParams.DEFAULT.shape),
blockCurve = (json["blockCurve"] as? Array<String>) ?: particleParams.blockCurve,
rotRandom = (json["rotRandom"] as? Pair<Vector3f, Vector3f>) ?: particleParams.rotRandom,
rotVelRandom = (json["rotVelRandom"] as? Pair<Vector3f, Vector3f>) ?: particleParams.rotVelRandom,
rotVelCurve = (json["rotVelCurve"] as? Array<Vector3f>) ?: particleParams.rotVelCurve,
sizeRandom = (json["sizeRandom"] as? Pair<Vector3f, Vector3f>) ?: particleParams.sizeRandom,
uniformSize = (json["uniformSize"] as? Boolean) ?: particleParams.uniformSize,
sizeCurve = (json["sizeCurve"] as? Array<Vector3f>) ?: particleParams.sizeCurve,
velRandom = (json["velRandom"] as? Pair<Vector3f, Vector3f>) ?: particleParams.velRandom,
forceFields = (json["forceFields"] as? Array<ForceField>) ?: particleParams.forceFields,
gravity = (json["gravity"] as? Vector3f) ?: particleParams.gravity,
drag = (json["drag"] as? Float) ?: particleParams.drag,
minVel = (json["minVel"] as? Float) ?: particleParams.minVel,
lifeTime = (json["lifeTime"] as? Pair<Int, Int>) ?: particleParams.lifeTime
)
allParticleTypes.add(updatedParticle)
}
val params = EmitterParams(
maxCount = (json["maxCount"] as? Int) ?: EmitterParams.DEFAULT.maxCount,
spawnsPerTick = (json["spawnsPerTick"] as? Int) ?: EmitterParams.DEFAULT.spawnsPerTick,
loopDur = (json["loopDur"] as? Int) ?: EmitterParams.DEFAULT.loopDur,
loopDelay = (json["loopDelay"] as? Int) ?: EmitterParams.DEFAULT.loopDelay,
loopCount = (json["loopCount"] as? Int) ?: EmitterParams.DEFAULT.loopCount,
particleTypes = allParticleTypes.toTypedArray()
)
return params
}
fun stringToMap(input: String): Map<String, String> {
return input.split(",")
.map { it.split("=") }
.associate { it[0].trim() to it[1].trim() }
}
@@ -1,4 +1,4 @@
package com.bytedice.bde_particles.math
package com.bytedice.bde_particles
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.hit.HitResult
@@ -1,7 +1,7 @@
package com.bytedice.bde_particles.commands
import com.bytedice.bde_particles.items.ParticleEmitterTool
import com.bytedice.bde_particles.particle.emitterIdRegister
import com.bytedice.bde_particles.particleIdRegister.emitterIdRegister
import com.mojang.brigadier.Command
import com.mojang.brigadier.CommandDispatcher
import com.mojang.brigadier.arguments.StringArgumentType
@@ -45,7 +45,7 @@ object GiveEmitterTool {
val emitterId = StringArgumentType.getString(context, "Emitter ID")
val feedback = Text.literal("BPS - You like fancy particles. Don't you?\nBPS - gave particle emitter, bound to ID: \"${emitterId}\".")
.setStyle(Style.EMPTY.withColor(TextColor.fromRgb(Color(0, 200, 0).rgb)).withItalic(true))
.setStyle(Style.EMPTY.withColor(TextColor.fromRgb(Color(0, 200, 0).rgb)))
context.source.player?.inventory?.insertStack(ParticleEmitterTool.makeData(item.item, name, emitterId))
context.source.sendFeedback({ feedback }, false)
@@ -1,7 +1,7 @@
package com.bytedice.bde_particles.commands
import com.bytedice.bde_particles.emitterParamsToJson
import com.bytedice.bde_particles.particle.*
import com.bytedice.bde_particles.particleIdRegister.*
import com.mojang.brigadier.Command
import com.mojang.brigadier.CommandDispatcher
import com.mojang.brigadier.arguments.StringArgumentType
@@ -26,26 +26,26 @@ import java.util.concurrent.CompletableFuture
// ManageEmitters
// <create / remove / config / list>
// create
// [emitter id]
// [preset emitter id]
// <emitter id>
// <preset emitter id>
// output -> register new emitter with a preset
// remove
// [emitter id]
// <emitter id>
// output -> removes the particle with that id
// config // TODO
// [emitter id]
// <emitter id>
// <[particle index] / EMITTER>
// [param key] // HARDCODED KEYS, if EMITTER use emitter params.
// [new param value] // HARDCODED TYPES
// <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
// list
// output -> all registered emitters
// copy
// [emitter id]
// <emitter id>
// output -> give player a command block with the particle params (should be paste-able in kotlin)
@@ -59,6 +59,7 @@ object ManageEmitters {
// <create / remove / config / list / copy>
.then(argCreate())
.then(argRemove())
.then(argConfig())
.then(argList())
.then(argCopy())
)
@@ -68,6 +69,7 @@ object ManageEmitters {
val allEmitterIds = emitterIdRegister.keys
// TODO: maybe make this a Command.literal()
val emitterIdSuggestion: RequiredArgumentBuilder<ServerCommandSource, String> = CommandManager.argument("Registered Emitter ID", StringArgumentType.string())
.suggests { _, builder ->
val suggestionsBuilder = SuggestionsBuilder(builder.remaining, 0)
@@ -78,6 +80,7 @@ val emitterIdSuggestion: RequiredArgumentBuilder<ServerCommandSource, String> =
}
// TODO: fix "new emitter id" error
fun argCreate() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("create")
.then(
@@ -105,8 +108,13 @@ fun argCreate() : LiteralArgumentBuilder<ServerCommandSource> {
"BPS - This emitter will be removed on server restart! Use \"/ManageEmitters copy\" to save the data to your clipboard!")
.setStyle(Style.EMPTY.withColor(TextColor.fromRgb(Color(0, 200, 0).rgb)))
}
else if (newEmitterId !in allEmitterIds) {
Text.literal("BPS - Preset Emitter ID \"$emitterPresetVal\" doesn't exist!\n" +
"BPS - Use \"/ManageEmitters list\" to view all Emitter ID's.")
.setStyle(Style.EMPTY.withColor(TextColor.fromRgb(Color(200, 0, 0).rgb)))
}
else {
Text.literal("BPS - Emitter ID \"$newEmitterId\" already exists!\n" +
Text.literal("BPS - Emitter ID \"$newEmitterId\" already exists\n" +
"BPS - Use \"/ManageEmitters list\" to view all Emitter ID's.")
.setStyle(Style.EMPTY.withColor(TextColor.fromRgb(Color(200, 0, 0).rgb)))
}
@@ -200,6 +208,26 @@ fun argCopy() : LiteralArgumentBuilder<ServerCommandSource> {
)
}
// config // TODO
// <emitter id>
// <[particle index] / 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(argConfigEmitter())
)
}
fun argConfigEmitter() : LiteralArgumentBuilder<ServerCommandSource> {
return CommandManager.literal("EMITTER")
.then(ArgConfigEmitterKeys().maxCount())
}
fun makeCommandBlock(emitterData: Map<String, Any>): ItemStack {
val i = ItemStack(Items.COMMAND_BLOCK)
@@ -0,0 +1,47 @@
package com.bytedice.bde_particles.commands
import com.bytedice.bde_particles.particleIdRegister.updateSingleParam
import com.mojang.brigadier.Command
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 java.awt.Color
fun argUpdateEmitterParam(context: CommandContext<ServerCommandSource>, paramName: String, typeValue: Any) : MutableText {
val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID")
val success = updateSingleParam(emitterIdVal, -1, "maxCount", typeValue)
val feedback = if (success) {
Text.literal("BPS - Successfully updated Emitter ID \"$emitterIdVal\" parameter \"$paramName\" to value \"$typeValue\"")
.setStyle(Style.EMPTY.withColor(Color(0, 200, 0).rgb))
}
else {
Text.literal("BPS - Failed to update Emitter ID \"$emitterIdVal\" parameter \"$paramName\" to value \"$typeValue\": Unknown Error")
.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 = argUpdateEmitterParam(context, "maxCount", typeValue)
context.source.sendFeedback({ feedback }, false)
Command.SINGLE_SUCCESS
}
)
}
}
@@ -25,7 +25,7 @@ object ParticleEmitterTool {
val displayName = Text.literal(name)
.setStyle(Style.EMPTY.withColor(TextColor.fromRgb(Color(0, 200, 0).rgb)).withItalic(true))
val loreLines = Text.literal("BPS - Bound to ID \"$emitterId\".")
val loreLines = Text.literal("BPS - Bound to Emitter ID \"$emitterId\".")
.setStyle(Style.EMPTY.withColor(TextColor.fromRgb(Color(0, 200, 0).rgb)).withItalic(true))
val lore = LoreComponent(listOf(loreLines))
@@ -1,34 +0,0 @@
package com.bytedice.bde_particles.particle
val emitterIdRegister: MutableMap<String, EmitterParams> = mutableMapOf()
val forbiddenIds = arrayOf("", "DEFAULT", "NULL")
fun addToEmitterRegister(id: String, params: EmitterParams) : Pair<String, Boolean> {
val newId = id.replace(" ", "_")
if (newId in forbiddenIds && newId != "DEFAULT") {return Pair(newId, false) }
if (emitterIdRegister.containsKey(newId)) {return Pair(newId, false) }
emitterIdRegister[id] = params
return Pair(newId, true)
}
fun removeFromEmitterRegister(id: String) : Boolean {
if (id in forbiddenIds) { return false }
if (!emitterIdRegister.containsKey(id)) { return false }
emitterIdRegister.remove(id)
return true
}
fun getEmitterParams(id: String) : EmitterParams? {
return emitterIdRegister[id]
}
fun updateEmitterParams(id: String, newParams: EmitterParams) {
emitterIdRegister[id] = newParams
}
@@ -1,4 +1,4 @@
package com.bytedice.bde_particles.particle
package com.bytedice.bde_particles.particleIdRegister
/**
* EmitterParams defines the parameters for controlling how particles are emitted,
@@ -12,12 +12,12 @@ package com.bytedice.bde_particles.particle
* @param particleTypes An array of `ParticleParams` defining the types of particles to spawn. If empty, no particles will spawn.
*/
data class EmitterParams (
val maxCount: Int = 200,
val spawnsPerTick: Int = 2,
val loopDur: Int = 25,
val loopDelay: Int = 10,
val loopCount: Int = 3,
val particleTypes: Array<ParticleParams> = arrayOf(ParticleParams()),
var maxCount: Int = 200,
var spawnsPerTick: Int = 2,
var loopDur: Int = 25,
var loopDelay: Int = 10,
var loopCount: Int = 3,
var particleTypes: Array<ParticleParams> = arrayOf(ParticleParams()),
)
{
companion object Presets {
@@ -28,7 +28,7 @@ data class EmitterParams (
25,
0,
0,
arrayOf(ParticleParams.FIRE_GEYSER)
arrayOf(ParticleParams.DEFAULT)
)
}
}
@@ -1,4 +1,4 @@
package com.bytedice.bde_particles.particle
package com.bytedice.bde_particles.particleIdRegister
data class ForceField (
val x: Float = 0.0f,
@@ -1,8 +1,6 @@
package com.bytedice.bde_particles.particle
package com.bytedice.bde_particles.particleIdRegister
import com.bytedice.bde_particles.DisplayEntity
import com.bytedice.bde_particles.DisplayEntityProperties
import com.bytedice.bde_particles.math.*
import com.bytedice.bde_particles.*
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.Vec3d
import org.joml.Vector3f
@@ -1,4 +1,4 @@
package com.bytedice.bde_particles.particle
package com.bytedice.bde_particles.particleIdRegister
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.Vec3d
@@ -0,0 +1,136 @@
@file:Suppress("UNCHECKED_CAST")
package com.bytedice.bde_particles.particleIdRegister
import org.joml.Vector3f
val emitterIdRegister: MutableMap<String, EmitterParams> = mutableMapOf()
val forbiddenIds = arrayOf("", "DEFAULT", "NULL")
fun addToEmitterRegister(id: String, params: EmitterParams) : Pair<String, Boolean> {
val newId = id.replace(" ", "_")
if (newId in forbiddenIds && newId != "DEFAULT") { return Pair(newId, false) }
if (emitterIdRegister.containsKey(newId)) { return Pair(newId, false) }
emitterIdRegister[id] = params
return Pair(newId, true)
}
fun removeFromEmitterRegister(id: String) : Boolean {
if (id in forbiddenIds) { return false }
if (!emitterIdRegister.containsKey(id)) { return false }
emitterIdRegister.remove(id)
return true
}
fun getEmitterParams(id: String) : EmitterParams? {
return emitterIdRegister[id]
}
fun updateEmitterParams(id: String, newParams: EmitterParams) {
emitterIdRegister[id] = newParams
}
fun updateSingleParam(id: String, particleIndex: Int, 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]
val updatedValues = updateSingleParticleParam(particle, paramName, paramValue)
emitter.particleTypes[particleIndex] = updatedValues.first
updateEmitterParams(id, emitter)
return updatedValues.second
}
else {
return false
}
}
fun updateSingleEmitterParam(params: EmitterParams, paramName: String, paramValue: Any) : Pair<EmitterParams, Boolean> {
val value: Any? = when (paramName) {
"maxCount" -> paramValue as Int
"spawnsPerTick" -> paramValue as Int
"loopDur" -> paramValue as Int
"loopDelay" -> paramValue as Int
"loopCount" -> paramValue as Int
else -> null
}
if (value == null) { return Pair(params, false) }
val newParams = params.copy()
when (paramName) {
"maxCount" -> newParams.maxCount = value as Int
"spawnsPerTick" -> newParams.spawnsPerTick = value as Int
"loopDur" -> newParams.loopDur = value as Int
"loopDelay" -> newParams.loopDelay = value as Int
"loopCount" -> newParams.loopCount = value as Int
else -> return Pair(params, false)
}
return Pair(newParams, true)
}
fun updateSingleParticleParam(params: ParticleParams, paramName: String, paramValue: Any) : Pair<ParticleParams, Boolean> {
val value: Any? = when (paramName) {
"shape" -> paramValue as SpawningShape?
"blockCurve" -> paramValue as Array<String>
"rotRandom" -> paramValue as Pair<Vector3f, Vector3f>
"rotVelRandom" -> paramValue as Pair<Vector3f, Vector3f>
"rotVelCurve" -> paramValue as Array<Vector3f>
"sizeRandom" -> paramValue as Pair<Vector3f, Vector3f>
"uniformSize" -> paramValue as Boolean
"sizeCurve" -> paramValue as Array<Vector3f>
"velRandom" -> paramValue as Pair<Vector3f, Vector3f>
"forceFields" -> paramValue as Array<ForceField>
"gravity" -> paramValue as Vector3f
"drag" -> paramValue as Float
"minVel" -> paramValue as Float
"lifeTime" -> paramValue as Pair<Int, Int>
else -> null
}
if (value == null) { return Pair(params, false) }
val newParams = params.copy()
when (paramName) {
"shape" -> newParams.shape = value as SpawningShape?
"blockCurve" -> newParams.blockCurve = value as Array<String>
"rotRandom" -> newParams.rotRandom = value as Pair<Vector3f, Vector3f>
"rotVelRandom" -> newParams.rotVelRandom = value as Pair<Vector3f, Vector3f>
"rotVelCurve" -> newParams.rotVelCurve = value as Array<Vector3f>
"sizeRandom" -> newParams.sizeRandom = value as Pair<Vector3f, Vector3f>
"uniformSize" -> newParams.uniformSize = value as Boolean
"sizeCurve" -> newParams.sizeCurve = value as Array<Vector3f>
"velRandom" -> newParams.velRandom = value as Pair<Vector3f, Vector3f>
"forceFields" -> newParams.forceFields = value as Array<ForceField>
"gravity" -> newParams.gravity = value as Vector3f
"drag" -> newParams.drag = value as Float
"minVel" -> newParams.minVel = value as Float
"lifeTime" -> newParams.lifeTime = value as Pair<Int, Int>
else -> return Pair(params, false)
}
return Pair(newParams, true)
}
@@ -1,4 +1,4 @@
package com.bytedice.bde_particles.particle
package com.bytedice.bde_particles.particleIdRegister
import org.joml.Vector3f
@@ -21,20 +21,20 @@ import org.joml.Vector3f
* @param lifeTime A range for the particle's lifetime in ticks. A value below 1 will result in the particle not spawning.
*/
data class ParticleParams (
val shape: SpawningShape? = SpawningShape.Circle(3.0f),
val blockCurve: Array<String> = arrayOf("minecraft:shroomlight", "minecraft:orange_concrete", "minecraft:orange_stained_glass", "minecraft:gray_stained_glass", "minecraft:light_gray_stained_glass"),
val rotRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(0.0f, 0.0f, 0.0f), Vector3f(360.0f, 360.0f, 360.0f)),
val rotVelRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(-0.2f, -0.2f, -0.2f), Vector3f(0.2f, 0.2f, 0.2f)),
val rotVelCurve: Array<Vector3f> = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.0f, 0.0f, 0.0f)),
val sizeRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(0.5f, 0.5f, 0.5f), Vector3f(1.0f, 1.0f, 1.0f)),
val uniformSize: Boolean = true,
val sizeCurve: Array<Vector3f> = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.5f, 0.5f, 0.5f)),
val velRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(-0.1f, 0.4f, -0.1f), Vector3f(0.1f, 0.8f, 0.1f)),
val forceFields: Array<ForceField> = arrayOf(ForceField()), // emptyArray(),
val gravity: Vector3f = Vector3f(0.0f, -0.01f, 0.0f),
val drag: Float = 0.075f,
val minVel: Float = 0.0f,
val lifeTime: Pair<Int, Int> = Pair(15, 45)
var shape: SpawningShape? = SpawningShape.Circle(3.0f),
var blockCurve: Array<String> = arrayOf("minecraft:shroomlight", "minecraft:orange_concrete", "minecraft:orange_stained_glass", "minecraft:gray_stained_glass", "minecraft:light_gray_stained_glass"),
var rotRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(0.0f, 0.0f, 0.0f), Vector3f(360.0f, 360.0f, 360.0f)),
var rotVelRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(-0.2f, -0.2f, -0.2f), Vector3f(0.2f, 0.2f, 0.2f)),
var rotVelCurve: Array<Vector3f> = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.0f, 0.0f, 0.0f)),
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 sizeCurve: Array<Vector3f> = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.5f, 0.5f, 0.5f)),
var velRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(-0.1f, 0.4f, -0.1f), Vector3f(0.1f, 0.8f, 0.1f)),
var forceFields: Array<ForceField> = arrayOf(ForceField()), // emptyArray(),
var gravity: Vector3f = Vector3f(0.0f, -0.01f, 0.0f),
var drag: Float = 0.075f,
var minVel: Float = 0.0f,
var lifeTime: Pair<Int, Int> = Pair(15, 45)
) {
companion object Presets {
val DEFAULT = ParticleParams()
@@ -1,4 +1,4 @@
package com.bytedice.bde_particles.particle
package com.bytedice.bde_particles.particleIdRegister
import org.joml.Vector2f
import org.joml.Vector3f