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 8d94f28..b8473ac 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt @@ -117,9 +117,9 @@ class Bde_particles : ModInitializer { fun init() { - addToRegister("DEFAULT", EmitterParams.DEFAULT) - addToRegister("DEBUG", EmitterParams.DEBUG) - addToRegister("STRESS_TEST", EmitterParams.STRESS_TEST) + addToRegister("DEFAULT", EmitterParams.DEFAULT, 137) + addToRegister("DEBUG", EmitterParams.DEBUG, 137) + addToRegister("STRESS_TEST", EmitterParams.STRESS_TEST, 1532) } @@ -147,9 +147,8 @@ fun tick(server: MinecraftServer) { synchronized(ALL_PARTICLE_EMITTERS) { ALL_PARTICLE_EMITTERS = ALL_PARTICLE_EMITTERS.toMutableList().apply { remove(emitter) }.toTypedArray() } - } else { - emitter.tick() } + else { emitter.tick() } } }.awaitAll() } @@ -160,7 +159,7 @@ fun onRightClick(player: PlayerEntity, world: ServerWorld, hand: Hand) : TypedAc val handItem = player.getStackInHand(hand) val (isEmitterTool, emitterId) = ParticleEmitterTool.getToolDetails(handItem) val hitResult = raycastFromPlayer(player as ServerPlayerEntity, 200.0) - val emitterParams = getParamsById(emitterId) + val emitterParams = getEmitterDataById(emitterId) if ( !isEmitterTool @@ -171,7 +170,13 @@ fun onRightClick(player: PlayerEntity, world: ServerWorld, hand: Hand) : TypedAc } val debug = world.gameRules.getBoolean(Bde_particles.SHOW_PARTICLE_DEBUG) - val emitter = ParticleEmitter(hitResult.pos, Vector2f(0.0f, 0.0f), world, emitterParams, debug) + val emitter = ParticleEmitter( + hitResult.pos, + Vector2f(0.0f, 0.0f), + world, + emitterParams, + debug + ) ALL_PARTICLE_EMITTERS += emitter return TypedActionResult(ActionResult.PASS, handItem) diff --git a/src/main/kotlin/com/bytedice/bde_particles/Math.kt b/src/main/kotlin/com/bytedice/bde_particles/Math.kt index 51a691e..b90c914 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/Math.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/Math.kt @@ -8,6 +8,7 @@ import net.minecraft.world.World import org.joml.Vector2f import org.joml.Vector3f import org.joml.Vector4f +import java.util.SplittableRandom import kotlin.math.* import kotlin.random.Random @@ -79,7 +80,7 @@ fun randomFloatBetween(min: Float, max: Float) : Float { fun randomIntBetween(min: Int, max: Int) : Int { - return Random.nextInt(min, max) + return Random.nextInt(max - min) + min } diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt index 1adcf8a..3a1f98d 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt @@ -104,9 +104,9 @@ data class EmitterParams ( ) val STRESS_TEST = EmitterParams( maxCount = 10000, - spawnRate = 50, + spawnRate = 5000, spawnChance = 1.0f, - spawnDuration = ParamClasses.Duration.SingleBurst(100), + spawnDuration = ParamClasses.Duration.SingleBurst(1), spawnPosOffset = Vector3f(0.0f, 0.0f, 0.0f), lifeTime = ParamClasses.PairInt(75, 100), shape = SpawningShape.Circle(10.0f, true), diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/ParamClasses.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/ParamClasses.kt index bb49633..5f5533d 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/ParamClasses.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/ParamClasses.kt @@ -4,7 +4,6 @@ import com.bytedice.bde_particles.LerpCurves import com.bytedice.bde_particles.randomFloatBetween import com.bytedice.bde_particles.randomIntBetween import org.joml.Vector3f -import kotlin.math.abs import kotlin.math.atan2 import kotlin.math.pow import kotlin.math.sqrt diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt index 858926e..613d3c9 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt @@ -3,6 +3,9 @@ package com.bytedice.bde_particles.particles import com.bytedice.bde_particles.Bde_particles import com.bytedice.bde_particles.LIVING_PARTICLE_COUNT import com.bytedice.bde_particles.randomFloatBetween +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope import net.minecraft.server.world.ServerWorld import net.minecraft.util.math.Vec3d import org.joml.Vector2f @@ -26,15 +29,38 @@ class ParticleEmitter( var isDead = false - fun tick() { + suspend fun tick() { if (isTicking) { count() } if (isTicking) { addParticle() } if (!isTicking && allParticles.isEmpty()) { isDead = true } - for (particle in allParticles) { - if (particle.isDead) { allParticles = allParticles.toMutableList().apply { remove(particle) }.toTypedArray() } - else { particle.tick(world) } + processParticlesInBatches(world, 100) + } + + + private suspend fun processParticlesInBatches( + world: ServerWorld, + batchSize: Int + ) = coroutineScope { + val batches = allParticles.toMutableList().chunked(batchSize) + + val jobs = batches.map { batch -> + async { + val toRemove = mutableListOf() + batch.forEach { particle -> + if (particle.isDead) { + toRemove.add(particle) + } else { + particle.tick(world) + } + } + synchronized(allParticles) { + allParticles = allParticles.toMutableList().apply { removeAll(toRemove) }.toTypedArray() + } + } } + + jobs.awaitAll() } 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 b56fc3c..64b8a64 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) : Pair { +fun addToRegister(id: String, params: EmitterParams, cacheLength: Int) : Pair { val newId = replaceForbiddenChars(id.replace(" ", "_")) if (idRegister.containsKey(newId)) { @@ -40,7 +40,7 @@ fun removeFromRegister(id: String) : Boolean { } -fun getParamsById(id: String) : EmitterParams? { +fun getEmitterDataById(id: String) : EmitterParams? { return idRegister[id] } @@ -51,7 +51,7 @@ fun updateRegistered(id: String, newParams: EmitterParams) { fun updateParam(id: String, paramName: String, paramValue: Any) : Boolean { - val emitter = getParamsById(id) ?: return false + val emitter = getEmitterDataById(id) ?: return false val updatedValues = updateParams(emitter, paramName, paramValue) return updatedValues.second