holy shit i can spawn invisible particles

This commit is contained in:
2024-11-14 21:13:17 +01:00
parent cbcff4e157
commit 9c0bd44f14
8 changed files with 170 additions and 25 deletions
@@ -2,8 +2,8 @@ package com.bytedice.bde_particles
import com.bytedice.bde_particles.commands.GiveParticleEmitter import com.bytedice.bde_particles.commands.GiveParticleEmitter
import com.bytedice.bde_particles.items.getToolDetails import com.bytedice.bde_particles.items.getToolDetails
import com.bytedice.bde_particles.particle.Particle import com.bytedice.bde_particles.math.raycastFromPlayer
import com.bytedice.bde_particles.particle.returnParticleFunction import com.bytedice.bde_particles.particle.*
import net.fabricmc.api.ModInitializer import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents
@@ -12,10 +12,13 @@ import net.fabricmc.fabric.api.event.player.UseItemCallback
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.server.MinecraftServer import net.minecraft.server.MinecraftServer
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.server.world.ServerWorld
import net.minecraft.text.Text 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.World
// const val ALL_PARTICLE_EMITTERS: Array<> // ParticleEmitter // const val ALL_PARTICLE_EMITTERS: Array<> // ParticleEmitter
@@ -31,6 +34,8 @@ val cfg = Config()
class Bde_particles : ModInitializer { class Bde_particles : ModInitializer {
override fun onInitialize() { override fun onInitialize() {
init()
ServerTickEvents.START_SERVER_TICK.register { _ -> ServerTickEvents.START_SERVER_TICK.register { _ ->
tick() tick()
} }
@@ -39,8 +44,8 @@ class Bde_particles : ModInitializer {
GiveParticleEmitter.register(dispatcher, registryAccess) GiveParticleEmitter.register(dispatcher, registryAccess)
} }
UseItemCallback.EVENT.register(UseItemCallback { player: PlayerEntity, _, hand: Hand -> UseItemCallback.EVENT.register(UseItemCallback { player: PlayerEntity, world: World, hand: Hand ->
onRightClick(player, hand) onRightClick(player, world as ServerWorld, hand)
}) })
ServerLifecycleEvents.SERVER_STARTED.register(ServerLifecycleEvents.ServerStarted { server: MinecraftServer -> ServerLifecycleEvents.SERVER_STARTED.register(ServerLifecycleEvents.ServerStarted { server: MinecraftServer ->
@@ -52,19 +57,32 @@ class Bde_particles : ModInitializer {
} }
fun init() {
addToParticleRegister("DEBUG", ParticleEmitterParams())
}
fun tick() { fun tick() {
} }
fun onRightClick(player: PlayerEntity, hand: Hand) : TypedActionResult<ItemStack> { fun onRightClick(player: PlayerEntity, world: ServerWorld, hand: Hand) : TypedActionResult<ItemStack> {
val handItem = player.getStackInHand(hand) val handItem = player.getStackInHand(hand)
val (isEmitterTool, particleId) = getToolDetails(handItem) val (isEmitterTool, particleId) = getToolDetails(handItem)
val hitResult = raycastFromPlayer(player as ServerPlayerEntity, 50.0)
val emitterParams = getParticleEmitterParams(particleId)
if (isEmitterTool) { if (
val particleFunction = returnParticleFunction(particleId) !isEmitterTool
if (particleFunction != null) { /* spawn particle with params */ } || emitterParams == null
|| hitResult == null
) {
return TypedActionResult(ActionResult.PASS, handItem)
} }
val emitter = ParticleEmitter(hitResult.pos, world, emitterParams)
emitter.tick()
return TypedActionResult(ActionResult.PASS, handItem) return TypedActionResult(ActionResult.PASS, handItem)
} }
@@ -42,7 +42,11 @@ fun getToolDetails(item: ItemStack) : Pair<Boolean, String> {
val isParticleEmitterTool = customData?.nbt?.getByte("BPS_particleTool") == 1.toByte() val isParticleEmitterTool = customData?.nbt?.getByte("BPS_particleTool") == 1.toByte()
val particleId = customData?.nbt?.getString("BPS_particleId") val particleId = customData?.nbt?.getString("BPS_particleId")
if (particleId == null) { return Pair(isParticleEmitterTool, "") } return if (particleId == null) {
Pair(isParticleEmitterTool, "")
}
else { return Pair(isParticleEmitterTool, particleId) } else {
Pair(isParticleEmitterTool, particleId)
}
} }
@@ -5,6 +5,13 @@ import net.minecraft.util.hit.HitResult
import net.minecraft.util.math.Vec3d import net.minecraft.util.math.Vec3d
import net.minecraft.world.RaycastContext import net.minecraft.world.RaycastContext
import net.minecraft.world.World import net.minecraft.world.World
import org.joml.Vector3f
import org.joml.Vector4f
import kotlin.math.asin
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.sin
import kotlin.random.Random
fun raycastFromPlayer(player: ServerPlayerEntity, maxDistance: Double): HitResult? { fun raycastFromPlayer(player: ServerPlayerEntity, maxDistance: Double): HitResult? {
@@ -29,3 +36,57 @@ fun raycastFromPlayer(player: ServerPlayerEntity, maxDistance: Double): HitResul
null null
} }
} }
fun randomFloatBetween(min: Float, max: Float) : Float {
return Random.nextFloat() * (max - min) + min
}
fun eulerToQuat(euler: Vector3f): Vector4f {
val roll = euler.x
val pitch = euler.y
val yaw = euler.z
val cy = cos(yaw * 0.5)
val sy = sin(yaw * 0.5)
val cp = cos(pitch * 0.5)
val sp = sin(pitch * 0.5)
val cr = cos(roll * 0.5)
val sr = sin(roll * 0.5)
val w = cr * cp * cy + sr * sp * sy
val x = sr * cp * cy - cr * sp * sy
val y = cr * sp * cy + sr * cp * sy
val z = cr * cp * sy - sr * sp * cy
return Vector4f(x.toFloat(), y.toFloat(), z.toFloat(), w.toFloat())
}
fun quatToEuler(quat: Vector4f): Vector3f {
val x = quat.x
val y = quat.y
val z = quat.z
val w = quat.w
// Roll (X-axis rotation)
val sinr_cosp = 2 * (w * x + y * z)
val cosr_cosp = 1 - 2 * (x * x + y * y)
val roll = atan2(sinr_cosp, cosr_cosp)
// Pitch (Y-axis rotation)
val sinp = 2 * (w * y - z * x)
val pitch = if (kotlin.math.abs(sinp) >= 1) {
// Use 90 degrees if out of range
kotlin.math.sign(sinp) * (Math.PI.toFloat() / 2)
} else {
asin(sinp)
}
// Yaw (Z-axis rotation)
val siny_cosp = 2 * (w * z + x * y)
val cosy_cosp = 1 - 2 * (y * y + z * z)
val yaw = atan2(siny_cosp, cosy_cosp)
return Vector3f(roll, pitch, yaw)
}
@@ -1,15 +1,51 @@
package com.bytedice.bde_particles.particle package com.bytedice.bde_particles.particle
import com.bytedice.bde_particles.DisplayEntity
import com.bytedice.bde_particles.DisplayEntityProperties
import com.bytedice.bde_particles.math.eulerToQuat
import com.bytedice.bde_particles.math.randomFloatBetween
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.Vec3d import net.minecraft.util.math.Vec3d
import org.joml.Vector3f import org.joml.Vector3f
import org.joml.Vector4f
class Particle(particleParams: ParticleParams) { class Particle(particleParams: ParticleParams) {
fun init() { val rot = Vector3f(
randomFloatBetween(particleParams.rotRandom.first.x, particleParams.rotRandom.second.x),
randomFloatBetween(particleParams.rotRandom.first.y, particleParams.rotRandom.second.x),
randomFloatBetween(particleParams.rotRandom.first.z, particleParams.rotRandom.second.z)
)
val rotVel = Vector3f(
randomFloatBetween(particleParams.rotVelRandom.first.x, particleParams.rotVelRandom.second.x),
randomFloatBetween(particleParams.rotVelRandom.first.y, particleParams.rotVelRandom.second.x),
randomFloatBetween(particleParams.rotVelRandom.first.z, particleParams.rotVelRandom.second.z)
)
val size = Vector3f(
randomFloatBetween(particleParams.sizeRandom.first.x, particleParams.sizeRandom.second.x),
randomFloatBetween(particleParams.sizeRandom.first.y, particleParams.sizeRandom.second.x),
randomFloatBetween(particleParams.sizeRandom.first.z, particleParams.sizeRandom.second.z)
)
var blockDisplay: DisplayEntity? = null
val params = particleParams
fun init(pos: Vec3d) {
val properties = DisplayEntityProperties(
pos = pos,
blockType = this.params.blockCurve[0],
leftRotation = eulerToQuat(rot),
scale = size
)
blockDisplay = DisplayEntity(properties)
} }
fun registerEmitter(id: String, params: ParticleEmitterParams) {
addToParticleRegister(id, params) fun spawn(world: ServerWorld) {
blockDisplay?.spawn(world)
}
fun tick() {
} }
} }
@@ -0,0 +1,21 @@
package com.bytedice.bde_particles.particle
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.Vec3d
class ParticleEmitter(emitterPos: Vec3d, emitterWorld: ServerWorld, emitterParams: ParticleEmitterParams) {
val world = emitterWorld
val pos = emitterPos
val params = emitterParams
val allParticles: Array<Particle> = emptyArray()
val timeAlive = 0
fun tick() {
repeat(this.params.spawnsPerTick) {
val particle = Particle(ParticleParams())
particle.init(this.pos)
particle.spawn(world)
}
}
}
@@ -1,12 +1,11 @@
package com.bytedice.bde_particles.particle package com.bytedice.bde_particles.particle
class ParticleEmitterParams { data class ParticleEmitterParams (
data class init ( val maxCount: Int = 100,
val maxCount: Int = 20, val spawnsPerTick: Int = 1,
val spawnDur: Int = 20,
val particleTypes: Array<Particle> = emptyArray(), val particleTypes: Array<Particle> = emptyArray(),
val loop: Boolean = false, val loop: Boolean = false,
val loopDur: Int = 1,
val loopDelay: Int = 10, val loopDelay: Int = 10,
val loopCount: Int = 2, val loopCount: Int = 2,
) )
}
@@ -6,7 +6,8 @@ import org.joml.Vector3f
data class ParticleParams ( data class ParticleParams (
//val shape: Shape, // add later, start with single point //val shape: Shape, // add later, start with single point
val blockCurve: Array<String> = arrayOf("minecraft:black_concrete", "minecraft:green_concrete"), val blockCurve: Array<String> = arrayOf("minecraft:black_concrete", "minecraft:green_concrete"),
val rotVelRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(0.0f, 0.0f, 0.0f), Vector3f(360.0f, 360.0f, 360.0f)), 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(1.0f, 1.0f, 1.0f), Vector3f(5.0f, 5.0f, 5.0f)),
val rotVelCurve: Array<Vector3f> = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.0f, 0.0f, 0.0f)), 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 sizeRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(0.5f, 0.5f, 0.5f), Vector3f(1.0f, 1.0f, 1.0f)),
val sizeCurve: Array<Vector3f> = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.0f, 0.0f, 0.0f)), val sizeCurve: Array<Vector3f> = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.0f, 0.0f, 0.0f)),
@@ -14,3 +14,8 @@ fun returnParticleFunction(id: String) : ParticleEmitterParams? {
fun addToParticleRegister(id: String, params: ParticleEmitterParams) { fun addToParticleRegister(id: String, params: ParticleEmitterParams) {
particleIdRegister[id] = params particleIdRegister[id] = params
} }
fun getParticleEmitterParams(id: String) : ParticleEmitterParams? {
return particleIdRegister[id]
}