quilt-kotlin-libraries
quilt-kotlin-libraries copied to clipboard
Coroutines functionalities in the context of Minecraft
This thread is all about upcoming coroutine functionalities. Please share your thoughts regarding the following topics.
Topic 1 - Dispatchers.Main
Soon we would have Dispatchers.Main
been implemented as a supplement to other dispatchers. A few questions I'd like to ask before diving into it.
Q1: We need to specify how the dispatcher runs actually, because unlike the official implementations, there's no ready-to-use event loop, but only
tick
,render
forming some kind of "event loop". Maybe QSL lifecycle events could be used.
So I'm looking into kotlinx.coroutine for reference. However only UI related implementations (Android Event Loop, JavaFX, Swing) are found.
Q2: Do we really need main dispatcher on the server side? Usually it is for UI and is confined to only one thread. What is the usage?
Q3: Usually main dispatcher implements
Delay
for time related tasks. While real time is used among other main dispatcher implementations, Minecraft has a special time unit which is tick. Should we consider a tick basedDelay
implementation?
Q1 and Q2 are an interesting consideration. Android, JavaFX, and Swing are all GUI frameworks. In their contexts, thread safety is only needed when drawing onto the view. Minecraft, however, has both rendering and worlds requiring synchronization, with worlds having a server and client running in parallel. Any of them can pass for a Main
context, though my expectation would probably be to find server being referred to as such.
Perhaps it'd be a better idea to add Server
, Client
, and Render
as Dispatchers extensions instead.
As for delays, the question here is behavior on dispatchers that don't implement Delay: the docs don't seem to state it explicitly, but the delay handler in this case is the DefaultDelay. I could only track down the execution so far after that. However, it'll eventually have to come back to the dispatcher and dispatch anyway, so the behavior will likely end up being rounding up to the nearest tick.
I say implementing Delay, warning that it shouldn't be used in logs (can't do deprecation as we don't control the delay(Duration)
and delay(Int)
functions themselves, and pointing towards a separate method that takes ticks would be the cleaner option that tells the users their delays are being rounded to ticks and to specify that upfront.
Perhaps it'd be a better idea to add Server, Client, and Render as Dispatchers extensions instead.
Is there a meaningful difference between server and client?
The both only have a single thread for computation afaik, with client just running an integrated server
Is there a meaningful difference between server and client?
The both only have a single thread for computation afaik, with client just running an integrated server
In this case, one difference is how the dispatcher functions. I'm considering the following implementation: maintain an internal task queue for each main dispatcher, and when certain event happens like XxxTickEvents.START/END, these scheduled tasks get executed. So the difference here is where the tasks run. For example, client may run tasks that are still available outside gameplay like screen rendering.
Perhaps it'd be a better idea to add
Server
,Client
, andRender
as Dispatchers extensions instead.
This is what I mean to do at first place. (Can you explain the reason to seperate Render
and Client
? I didn't find minecraft seperating these two contexts)
I say implementing Delay, warning that it shouldn't be used in logs (can't do deprecation as we don't control the
delay(Duration)
anddelay(Int)
functions themselves, and pointing towards a separate method that takes ticks would be the cleaner option that tells the users their delays are being rounded to ticks and to specify that upfront.
A seperate function for ticks is needed so users don't get confused by the behavior. Normal delay
would most likely round up to the nearest tick if going for my suppose specified in the previous comment.
Can you explain the reason to seperate Render and Client? I didn't find minecraft seperating these two contexts)
My impression was client-side rendering and world ticks still run on separate threads, so they are separate contexts. I might be wrong on that, but if so, running rendering code on a world thread would slow the ticks down, while vice versa would result in concurrent modification.
Bringing this up again, for Q1 something that would make sense would be the ability attach jobs to specific objects with their own lifecycles
so, i.e, you could attach a Job
/coroutine to a player, delay for "ticks" (running the job as part of the player tick?) and if the player disconnects from a server, close their CoroutineScope
so that anything attached gets the ability to clean up automatically when it makes sense
Ive had a few cases now where my Jobs
are doing something in relation to a world, and I need to spend a bunch of time hooking it up to the start and stop events
Generalize this topic in order to welcome other coroutine related ideas.
Bringing this up again, for Q1 something that would make sense would be the ability attach jobs to specific objects with their own lifecycles
so, i.e, you could attach a ...
A CoroutineScope
could be created for an object with the corresponding lifecycle based CoroutineContext
.
Something that occurred to me, is there any we can write this where it wont explode with those various "Minecraft but with more threads" projects?
They are, unfortunately, somewhat popular and I suspect we'll run into issues at some point with them.