Shynixn / MCCoroutine

MCCoroutine is a library, which adds extensive support for Kotlin Coroutines for Minecraft Server environments.
Other
211 stars 19 forks source link

Add function to delay by Minecraft server ticks #72

Closed ChrisMcLain closed 2 years ago

ChrisMcLain commented 2 years ago

I am using Paper 1.18.2.

I would love an option to do something like this:

doSomething()
delayTicks(5)
doSomething()

I was able to implement this myself like so:

inline val Int.ticks get() = (this * 50).toDuration(DurationUnit.MILLISECONDS)

// Usage
delay(5.ticks)

It appears to work fine for durations longer than one tick, but unfortunately, using 1.tick results in a gap of two server ticks rather than just one. (I measured this by logging world.fullTime before and after the delay.)

I'm guessing this has something to do with the inner workings of the library or coroutines that are beyond my understanding.

I think it would be great if something like this were implemented in MCCoroutine-- with my bug fixed, of course ;)

Alternatively, I would love to hear reasoning on why I should avoid measuring with ticks and should instead measure with seconds, if that is better design-wise here. If that is the case, I would be happy to contribute that information to the documentation.

Shynixn commented 2 years ago

Hello,

I think a delayTicks option is a good idea. I would even prefer the delay(5.ticks) option over a delayTicks(..). Regarding the 2 ticks, the following is happening in the internals of MCCoroutine when you delay for 50 milliseconds:

delay(50Ms) // 1. Kotlin Coroutines waits for 50ms <-- tick 1 is here // 2. MCCoroutine gets a notification to do something // 3. MCCoroutine sends a new task to the Bukkit Scheduler // 4. BukkitScheduler appens the task to its task list // 5. BukkitScheduler picks the task up next tick <-- tick 2 is here

Can you please try to call delay(49ms) to confirm this behaviour? 49ms should result in a one tick gap. Anything below 50ms should always result in a 1 tick delay.