11package cc.modlabs.kpaper.extensions
22
3+ import cc.modlabs.kpaper.visuals.effect.ParticleData
34import dev.fruxz.ascend.extension.time.inWholeMinecraftTicks
45import org.bukkit.Color
56import org.bukkit.Location
@@ -14,6 +15,10 @@ import org.bukkit.potion.PotionEffect
1415import org.bukkit.potion.PotionEffectType
1516import kotlin.time.Duration
1617import kotlin.time.Duration.Companion.seconds
18+ import com.destroystokyo.paper.ParticleBuilder
19+ import kotlinx.coroutines.GlobalScope
20+ import kotlinx.coroutines.delay
21+ import kotlinx.coroutines.launch
1722
1823
1924/* *
@@ -222,16 +227,53 @@ fun buildMelody(builder: MelodyBuilder.() -> Unit): Melody {
222227}
223228
224229// Melody and Beat classes
225- class Melody (private val beats : List <Beat >) {
226- fun play (player : Player ) {
227- beats.forEach { it.play(player) }
230+ class Melody (
231+ private var ticksPerBeat : Long = 10 ,
232+ private var ticksPerSound : Long = 0 ,
233+ var repetitions : Int = 0 ,
234+ private val beats : List <Beat >
235+ ) {
236+ var delayPerBeat: Duration
237+ get() = ticksPerBeat.takeIf { it > 0 }?.minecraftTicks ? : Duration .ZERO
238+ set(value) {
239+ ticksPerBeat = value.inWholeMinecraftTicks
240+ }
241+
242+ var delayPerSound: Duration
243+ get() = ticksPerSound.takeIf { it > 0 }?.minecraftTicks ? : Duration .ZERO
244+ set(value) {
245+ ticksPerSound = value.inWholeMinecraftTicks
246+ }
247+
248+ fun play (player : Player ) = GlobalScope .launch {
249+ repeat(1 + repetitions) {
250+ beats.forEach {
251+ it.play(player)
252+ delay(delayPerSound)
253+ }
254+ delay(delayPerBeat)
255+ }
256+ }
257+
258+ fun play (location : Location ) = GlobalScope .launch {
259+ repeat(1 + repetitions) {
260+ beats.forEach {
261+ it.play(location)
262+ delay(delayPerSound)
263+ }
264+ delay(delayPerBeat)
265+ }
228266 }
229267}
230268
231269class Beat (private val sounds : List <SoundEffect >) {
232270 fun play (player : Player ) {
233271 sounds.forEach { it.play(player) }
234272 }
273+
274+ fun play (location : Location ) {
275+ sounds.forEach { it.play(location) }
276+ }
235277}
236278
237279data class SoundEffect (
@@ -244,16 +286,40 @@ data class SoundEffect(
244286 fun play (player : Player ) {
245287 player.playSound(player.location, sound, volume, pitch)
246288 }
289+
290+ fun play (location : Location ) {
291+ location.world.playSound(location, sound, volume, pitch)
292+ }
247293}
248294
249295class MelodyBuilder {
250296 private val beats = mutableListOf<Beat >()
297+ private var repetitions = 0
298+ private var delayPerBeat: Duration = Duration .ZERO
299+ private var delayPerSound: Duration = Duration .ZERO
251300
252301 fun beat (vararg sounds : SoundEffect ) {
253302 beats.add(Beat (sounds.toList()))
254303 }
255304
256- fun build (): Melody = Melody (beats)
305+ fun repeat (times : Int ) {
306+ repetitions = times
307+ }
308+
309+ fun delayPerBeat (duration : Duration ) {
310+ delayPerBeat = duration
311+ }
312+
313+ fun delayPerSound (duration : Duration ) {
314+ delayPerSound = duration
315+ }
316+
317+ fun build (): Melody = Melody (
318+ ticksPerBeat = delayPerBeat.inWholeMinecraftTicks,
319+ ticksPerSound = delayPerSound.inWholeMinecraftTicks,
320+ repetitions = repetitions,
321+ beats = beats.toList()
322+ )
257323}
258324
259325// Utility function to create SoundEffect
@@ -275,4 +341,66 @@ fun PotionEffect(type: PotionEffectType, duration: Duration = 10.seconds, amplif
275341 PotionEffect (type, duration.inWholeMinecraftTicks.toInt(), amplifier, ambient, particles, icon)
276342
277343fun buildPotionEffect (type : PotionEffectType , duration : Duration = 10.seconds, amplifier : Int = 0, ambient : Boolean = true, particles : Boolean = true, icon : Boolean = true, builder : PotionEffect .() -> Unit ) =
278- PotionEffect (type, duration, amplifier, ambient, particles, icon).apply (builder)
344+ PotionEffect (type, duration, amplifier, ambient, particles, icon).apply (builder)
345+
346+
347+ @Throws(IllegalStateException ::class )
348+ fun ParticleBuilder.playParticleEffect (reach : Double = .0) {
349+ val location = location()
350+ val internalReceivers = receivers()?.toList() ? : location?.world?.players
351+
352+ if (location != null ) {
353+ internalReceivers!!
354+
355+ if (reach > 0 ) {
356+ val participants = location.getNearbyPlayers(reach).filter { internalReceivers.contains(it) }
357+ val computedParticleBuilder = receivers(participants)
358+
359+ computedParticleBuilder.spawn()
360+
361+ } else
362+ spawn()
363+
364+ } else
365+ throw IllegalStateException (" 'location'[bukkit.Location] of ParticleBuilder cannot be null!" )
366+ }
367+
368+ @Throws(IllegalStateException ::class )
369+ fun ParticleBuilder.playParticleEffect (reach : Number = .0) =
370+ playParticleEffect(reach.toDouble())
371+
372+ fun ParticleBuilder.playParticleEffect () =
373+ playParticleEffect(.0 )
374+
375+ fun ParticleBuilder.offset (offset : Number ) = offset(offset.toDouble(), offset.toDouble(), offset.toDouble())
376+
377+ fun ParticleBuilder.offset (offsetX : Number , offsetZ : Number ) = offset(offsetX.toDouble(), .0 , offsetZ.toDouble())
378+
379+ fun ParticleBuilder.location (loc : Location ) = location(loc)
380+
381+ fun particleOf (particle : Particle ): ParticleData = ParticleData (particle)
382+
383+ fun buildParticle (particle : Particle , builder : ParticleData .() -> Unit ) =
384+ ParticleData (particle).apply (builder)
385+
386+ fun ParticleBuilder.copy (
387+ particle : Particle = particle(),
388+ receivers : List <Player >? = receivers(),
389+ source : Player ? = source(),
390+ location : Location ? = location(),
391+ count : Int = count(),
392+ offsetX : Double = offsetX(),
393+ offsetY : Double = offsetY(),
394+ offsetZ : Double = offsetZ(),
395+ extra : Double = extra(),
396+ data : Any? = data(),
397+ force : Boolean = force(),
398+ ) = ParticleBuilder (particle)
399+ .receivers(receivers)
400+ .source(source)
401+ .count(count)
402+ .offset(offsetX, offsetY, offsetZ)
403+ .extra(extra)
404+ .data(data)
405+ .force(force)
406+ .let { if (location != null ) it.location(location) else it }
0 commit comments