shynixn / mccoroutine Goto Github PK
View Code? Open in Web Editor NEWMCCoroutine is a library, which adds extensive support for Kotlin Coroutines for Minecraft Server environments.
License: Other
MCCoroutine is a library, which adds extensive support for Kotlin Coroutines for Minecraft Server environments.
License: Other
Hi, you recently implemented MCCoroutines for Minestom and I'd like to firstly thank you for that.
But there is a little issue on the implementation of server.launch { }
: in Minestom, we usually don't store any MinecraftServer
instance because every method in that class is static. That means that instead of server.launch { }
, we should be able to do MinecraftServer.launch { }
.
Unfortunately, MinecraftServer
is a java class and doesn't have any companion object, so making an extension function for the companion object is impossible. A workaround would be to change fun MinecraftServer.launch
to just fun minecraftServerLaunch
.
For now, I am using this:
private var minecraftServer = MinecraftServer()
fun minecraftServerLaunch(
context: CoroutineContext = minecraftServer.minecraftDispatcher,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job = minecraftServer.launch(context, start, block)
When I use asycnDispatcher it behaves like Dispatchers.Unconfined
in every way, unless it is the main thread. Because of this, I caught a lot of errors, because I thought that he would always switch thread to the asynchronous bukkit, but it continued to execute in the lettuce thread, for example
Dispatch method from com.github.shynixn.mccoroutine.bukkit.dispatcher.AsyncCoroutineDispatcher
override fun isDispatchNeeded(context: CoroutineContext): Boolean {
wakeUpBlockService.ensureWakeup()
return plugin.server.isPrimaryThread
}
This code prints Coroutine has been cancelled.
after a second.
val job = launch { // Plugin.launch
delay(1000.seconds)
}
launch { // Plugin.launch
delay(1.seconds)
job.cancel()
}
However, this code does not.
launch { // Plugin.launch
val job = launch { // CoroutineScope.launch
delay(1000.seconds)
}
delay(1.seconds)
job.cancel()
}
Is this how you are supposed to make a cancellable coroutine?
Consider adding support for Velocity.
https://github.com/PaperMC/Velocity
It is often the case, that we want to measure performance using spigot timings. https://timings.spigotmc.org/
However, coroutines schedules using plugin.launch {}
often yield a name like CancellableContinuationImpl(Single)
which is not helpful if we are using many coroutines spread across larger plugins. It should be possible to use class names in the same way as the standard bukkit scheduler.
Since MCCoroutine uses the normal bukkit scheduler, it seems to struggle with stuff on Folia
Any chance this can get supported?
In my JavPlugin#onDisable method, I would like to save the data of a player to a database. However when I try to do that, I get this error:
java.lang.RuntimeException: Plugin wool-wars attempt to start a new coroutine session while being disabled. Dispatchers such as plugin.minecraftDispatcher and plugin.asyncDispatcher are already disposed at this point and cannot be used!
I think it would be great if the coroutine session was only closed after the onDisable method was called, so we could do things like I described earlier.
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.
Would it be possible to add a suspend method for the registering functional-style listener?
An example of the non suspend method: https://docs.papermc.io/velocity/dev/event-api#registering-a-functional-style-listener
Source code:
I hope I provided enough information for you to work with.
So this is a bit of a strange issue I've encountered; when using a Suspending Listener (A listener registered with registerSuspendingEvents()), multiple Exceptions are thrown when listening to certain events and then are caught somewhere such that they don't appear in the server's log. The only way I was able to catch onto this was by analysing Spark's profiler and seeing that significant CPU time was being taken by jdk.internal.reflect.GeneratedMethodAccessor.invoke()
. After additional testing I was eventually able to get logs which pointed to event listeners. I tracked it to the ChunkLoadEvent and PhysicsEvent.
(For the record, I am listening to these events with a SuspendingListener. I tested with and without the suspend keyword on the event listener functions but still encountered the issue)
From guess work I used a normal Listener interface and the Exceptions were now gone and so was the extra CPU time consumed by them.
The plugin itself is a custom plugin that when loading chunks will scan each chunk and based on certain block and biome predicates replace an above-ground block with a custom vegetation (a custom model that drops unique drops). There is a lot of concurrency involved is the main point.
Spark Profiler - USING Suspending Listener
https://spark.lucko.me/EkXjQTa7Vp
Spark Profiler - USING Normal Listener
https://spark.lucko.me/1UJTdh3uGz
I'm not using this library directly, but am following the patterns you described in your initial README before this became an actual library.
This is my Minecraft dispatcher:
private class MinecraftCoroutineDispatcher : CoroutineDispatcher() {
/** Dispatches the coroutine on the main server thread. */
override fun dispatch(context: CoroutineContext, block: Runnable) {
if (Bukkit.isPrimaryThread()) {
block.run()
} else {
// this directly calls the bukkit scheduler internally, no magic here
BukkitExecutor.schedule(action = block::run)
}
}
}
/** A coroutine dispatcher that is confined to the Minecraft server thread. */
public val Dispatchers.Minecraft: CoroutineContext by lazy { MinecraftCoroutineDispatcher() }
This is all nice and dandy, and harnessing the power of Coroutines is truly a joy!
Unfortunately, there's a deadlock situation that I can't figure out how to fix.
Imagine the following code:
runBlocking(Dispatchers.Minecraft) {
// do something on the MC thread...
withContext(Dispatchers.IO) {
// some file I/O
}
// handle the result on the MC thread
}
This will deadlock when switching context back to Dispatchers.Minecraft
, as the Bukkit thread is blocked (thanks to runBlocking
), which means that the Bukkit scheduler will never get to tick and execute the Runnable
.
Unfortunately, in some cases, writing code like this is the most idiomatic thing to do - in my plugin's onEnable
, I want to wait for the execution of a suspending function that switches between the I/O and Minecraft dispatcher a few times. However, the switching will deadlock if we use runBlocking
for the aforementioned reasons.
Do you know of a solution to this issue? Is there a way to detect whether the primary thread is blocked, allowing us to execute code without fear of concurrency issues?
Thanks in advance!
Hi, this is my first time working with coroutines.
I have a service that accesses the database. The service is called when the player logs in.
I marked the method in the service as suspend, to use it in the Listener I just need to make a launch { service.callMethod(arg)
}?
Do I need to mark the listener method as suspend in this case and register accordingly?
Can you add support for Minestom game server ?
Exceptions are captured and logged into console, requiring a handler to be added to the logger. Allow Sentry to capture these exceptions by adding a configuration value which will not handle these exceptions if set to true.
Hi,
To describe my issue, let's take a look on the following event handler:
@EventHandler(ignoreCancelled = false)
suspend fun onBlockBreak(e: BlockBreakEvent) {
val blockMaterial = e.block.type // Assigning blockMaterial here, as it gets erased after calling a suspending function
withContext(Dispatchers.IO) {
delay(10)
}
if (blockMaterial == Material.STONE) {
e.isDropItems = false // Does not stop items drop
e.isCancelled = true // Does not cancel the event
}
}
After calling a suspending function - withContext(Dispatchers.IO
delay(10)
in this case - the event gets "erased/reset".
My question is: How can I keep the access to the event after calling a suspending function?
It'd be nice if someone could explain me why the event gets erased, too.
Hello,
I'm experiencing the following error:
Caused by: java.lang.ClassNotFoundException: com.github.shynixn.mccoroutine.bukkit.impl.MCCoroutineImpl
I can't also can't find this class in the shaded jar. Even though other classes of this library are available.
Maven pom.xml:
<dependency> <groupId>net.citizensnpcs</groupId> <artifactId>citizens-main</artifactId> <version>2.0.31-SNAPSHOT</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.github.shynixn.mccoroutine</groupId> <artifactId>mccoroutine-bukkit-core</artifactId> <version>2.13.0</version> </dependency>
Maven shade output:
[INFO] Including com.github.shynixn.mccoroutine:mccoroutine-bukkit-api:jar:2.13.0 in the shaded jar. [INFO] Including com.github.shynixn.mccoroutine:mccoroutine-bukkit-core:jar:2.13.0 in the shaded jar.
Am I doing something wrong?
onEnable, onReload, onDisable often does not got used correctly with MCCoroutine, therefore an implementation should be provided
The SuspendingTabCompleter
doesn't have the same level of support as the regular TabCompleter
provided in Paper.
You can return null
to the TabCompleter
to allow it to fall back to the default command executor but the signature for SuspendingTabCompleter.onTabComplete
is:
suspend fun onTabComplete(
sender: CommandSender,
command: Command,
alias: String,
args: Array<out String>
): List<String>
compared to TabCompleter.onTabComplete
@Nullable
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args);
This article is translated by Google
When using mc-coroutine on my paper server
It crashed (plugin activation failed
After viewing the error message
I think a field called pluginParentTimer is causing this problem
This field exists in org.bukkit.plugin.java.JavaPluginLoader
Let's take a look at the implementation of JavaPluginLoader on spigot
public final class JavaPluginLoader implements PluginLoader {
final Server server;
private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")};
private final Map<String, Class<?>> classes = new ConcurrentHashMap<String, Class<?>>();
private final List<PluginClassLoader> loaders = new CopyOnWriteArrayList<PluginClassLoader>();
public static final CustomTimingsHandler pluginParentTimer = new CustomTimingsHandler("** Plugins"); // Spigot
}
on paper
public final class JavaPluginLoader implements PluginLoader {
final Server server;
private static final boolean DISABLE_CLASS_PRIORITIZATION = Boolean.getBoolean("Paper.DisableClassPrioritization"); // Paper
private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")};
private final Map<String, Class<?>> classes = new ConcurrentHashMap<String, Class<?>>();
private final Map<String, java.util.concurrent.locks.ReentrantReadWriteLock> classLoadLock = new java.util.HashMap<String, java.util.concurrent.locks.ReentrantReadWriteLock>(); // Paper
private final Map<String, Integer> classLoadLockCount = new java.util.HashMap<String, Integer>(); // Paper
private final List<PluginClassLoader> loaders = new CopyOnWriteArrayList<PluginClassLoader>();
}
So JavaPluginLoader.pluginParentTimer is only defined on spigot
But JavaPluginLoader.pluginParentTimer is used in line 134 in mccoroutine-bukkit-core/src/main/java/com/github/shynixn/mccoroutine/service/EventServiceImpl.kt
I checked EventServiceImpl in bukkit-core
and theres different between check and if code
am i wrong or is code wrong?
Currently, for Velocity, the class SuspendingSimpleCommand
is present. However, lot of server use Brigadier command system.
So, could you add some extensions to use brigadier command in a coroutine context ?
The documentation about brigadier + Example
Other example of brigadier
Notes:
runBlocking
in onDisable
.How to fix:
plugin.isEnabled
check to isDispatchNeeded
in com.github.shynixn.mccoroutine.bukkit.dispatcher.MinecraftCoroutineDispatcher
and com.github.shynixn.mccoroutine.bukkit.dispatcher.AsyncCoroutineDispatcher
if (!plugin.isEnabled)
check in dispatch
from those filesWelcome, this issue contains all information about the Hacktoberfest event and available tasks on this repository. Please notice that more tasks may be added later this month.
Required Knowledge
Optional Knowledge
Code/Style/Architecture
master
branch when you are done to initiate a reviewing processโ It is highly recommend to create a new issue on this project with the task name for example "Refactor convertChatColors" to avoid duplicate task pull requests. โ
Yes, but only 1 task at a time. After your first pull request has been approved, you can take the second task.
I normally check daily for new activity on this repository.
Just message me below this issue.
~
I am using events to manage my players' prefixes. However, if multiple prefixes are added in the events, ordering is very important.
In my situation, I am adding the player's rank first, then a color after it.
// Lowest priority - rank should be added before other prefixes.
@EventHandler(priority = EventPriority.LOWEST)
suspend fun rankOnPlayerPrefixUpdate(event: PlayerPrefixUpdateEvent) {
delay(500.milliseconds) // Fetch rank from database
event.prefixes.add(Component.text("[Rank] "))
}
// Highest priority - color should be added after other prefixes.
@EventHandler(priority = EventPriority.HIGHEST)
fun rankOnPlayerPrefixUpdate(event: PlayerPrefixUpdateEvent) {
event.prefixes.add(Component.text("[Color] "))
}
// Update player's prefix with an event.
val event = PlayerPrefixUpdateEvent(player, mutableListOf())
server.pluginManager.callSuspendingEvent(event, this).joinAll()
println(event.prefixes) // '[Color] [Rank] '
Even though the rank event is being called first, its prefix is appended last because of the delay. There should be an option in callSuspendingEvent
to wait for each suspending event before continuing to the next one.
Workarounds:
runBlocking
fixes the ordering issue but misuses coroutines.add(0, ...)
to explicitly prepend the prefix works, but is messy and only fixes this specific case.Hey there! I'm a huge fan of your library! I use it in my plugin TicketManager, and it's now an integral part of the plugin! Currently my plugin is written for both Paper and Spigot, but I eventually want to create a Sponge version too. However, I noticed that the library is written for Sponge API-7. Do you have any plans to write an MCCoroutine version for Sponge API-8?
PluginManager.callSuspendingEvent(....)
How can i dispatch without scheduler in primary-thread?
For example
inline fun<reified T: Event> Player.listenAsync(withCancel: Boolean = true): Deferred<T> {
val completableDeferred = CompletableDeferred<T>()
ListeningPlayer.register(T::class.java, this) {
completableDeferred.complete(it)
}
return completableDeferred
}
then if i use await with it
it just run after next tick
I'm testing out coroutines by routing all events to a shared flow. I'm getting the following error on /reload
:
Caused by: java.util.zip.ZipException: ZipFile invalid LOC header (bad signature)
at java.util.zip.ZipFile$ZipFileInputStream.initDataOffset(ZipFile.java:1003) ~[?:?]
at java.util.zip.ZipFile$ZipFileInputStream.read(ZipFile.java:1013) ~[?:?]
at java.util.zip.ZipFile$ZipFileInflaterInputStream.fill(ZipFile.java:468) ~[?:?]
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:159) ~[?:?]
at java.io.FilterInputStream.read(FilterInputStream.java:107) ~[?:?]
at com.google.common.io.ByteStreams.copy(ByteStreams.java:106) ~[spigot-1.16.5.jar:3016-Spigot-73fb609-ea050e6]
at com.google.common.io.ByteStreams.toByteArray(ByteStreams.java:166) ~[spigot-1.16.5.jar:3016-Spigot-73fb609-ea050e6]
at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:135) ~[spigot-1.16.5.jar:3016-Spigot-73fb609-ea050e6]
at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:96) ~[spigot-1.16.5.jar:3016-Spigot-73fb609-ea050e6]
at java.lang.ClassLoader.loadClass(ClassLoader.java:589) ~[?:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:522) ~[?:?]
at kotlinx.coroutines.JobSupport.getChildren(JobSupport.kt:947) ~[?:?]
at kotlinx.coroutines.JobKt__JobKt.cancelChildren(Job.kt:628) ~[?:?]
at kotlinx.coroutines.JobKt.cancelChildren(Unknown Source) ~[?:?]
at kotlinx.coroutines.JobKt__JobKt.cancelChildren$default(Job.kt:627) ~[?:?]
at kotlinx.coroutines.JobKt.cancelChildren$default(Unknown Source) ~[?:?]
at com.github.shynixn.mccoroutine.service.CoroutineSessionImpl.dispose(CoroutineSessionImpl.kt:57) ~[?:?]
at com.github.shynixn.mccoroutine.impl.MCCoroutineImpl.disable(MCCoroutineImpl.kt:32) ~[?:?]
at com.github.shynixn.mccoroutine.listener.PluginListener.onPluginDisable(PluginListener.kt:19) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:315) ~[spigot-1.16.5.jar:3016-Spigot-73fb609-ea050e6]
Perhaps this is related to how the scope is disposed? Or more specifically, usage of Plugin.findClazz
[15:22:46 ERROR]: Exception in thread "main" java.lang.RuntimeException: Exception while trying to handle coroutine exception
[15:22:46 ERROR]: at kotlinx.coroutines.CoroutineExceptionHandlerKt.handlerException(CoroutineExceptionHandler.kt:38)
[15:22:46 ERROR]: at kotlinx.coroutines.CoroutineExceptionHandlerKt.handleCoroutineException(CoroutineExceptionHandler.kt:29)
[15:22:46 ERROR]: at kotlinx.coroutines.StandaloneCoroutine.handleJobException(Builders.common.kt:196)
[15:22:46 ERROR]: at kotlinx.coroutines.JobSupport.finalizeFinishingState(JobSupport.kt:229)
[15:22:46 ERROR]: at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:906)
[15:22:46 ERROR]: at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:863)
[15:22:46 ERROR]: at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:828)
[15:22:46 ERROR]: at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:100)
[15:22:46 ERROR]: at kotlinx.coroutines.intrinsics.CancellableKt.dispatcherFailure(Cancellable.kt:65)
[15:22:46 ERROR]: at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:78)
[15:22:46 ERROR]: at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
[15:22:46 ERROR]: at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
[15:22:46 ERROR]: at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
[15:22:46 ERROR]: at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
[15:22:46 ERROR]: at kotlinx.coroutines.BuildersKt.launch(Unknown Source)
[15:22:46 ERROR]: at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
[15:22:46 ERROR]: at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source)
[15:22:46 ERROR]: at com.github.shynixn.mccoroutine.velocity.impl.MCCoroutineImpl.setupCoroutineSession(MCCoroutineImpl.kt:52)
[15:22:46 ERROR]: at com.github.shynixn.mccoroutine.velocity.SuspendingPluginContainer.initialize(SuspendingPluginContainer.kt:44)
[15:22:46 ERROR]: at com.github.jsh32.astroisles.proxy.MCCoroutineSamplePlugin.<init>(AstroIslesProxy.kt:42)
[15:22:46 ERROR]: at com.github.jsh32.astroisles.proxy.MCCoroutineSamplePlugin$$FastClassByGuice$$1948344.GUICE$TRAMPOLINE(<generated>)
[15:22:46 ERROR]: at com.github.jsh32.astroisles.proxy.MCCoroutineSamplePlugin$$FastClassByGuice$$1948344.apply(<generated>)
[15:22:46 ERROR]: at com.google.inject.internal.DefaultConstructionProxyFactory$FastClassProxy.newInstance(DefaultConstructionProxyFactory.java:82)
[15:22:46 ERROR]: at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:114)
[15:22:46 ERROR]: at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:91)
[15:22:46 ERROR]: at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:300)
[15:22:46 ERROR]: at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
[15:22:46 ERROR]: at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:169)
[15:22:46 ERROR]: at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:45)
[15:22:46 ERROR]: at com.google.inject.internal.InjectorImpl$1.get(InjectorImpl.java:1101)
[15:22:46 ERROR]: at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1139)
[15:22:46 ERROR]: at com.velocitypowered.proxy.plugin.loader.java.JavaPluginLoader.createPlugin(JavaPluginLoader.java:124)
[15:22:46 ERROR]: at com.velocitypowered.proxy.plugin.VelocityPluginManager.loadPlugins(VelocityPluginManager.java:155)
[15:22:46 ERROR]: at com.velocitypowered.proxy.VelocityServer.loadPlugins(VelocityServer.java:345)
[15:22:46 ERROR]: at com.velocitypowered.proxy.VelocityServer.start(VelocityServer.java:227)
[15:22:46 ERROR]: at com.velocitypowered.proxy.Velocity.main(Velocity.java:69)
[15:22:46 ERROR]: Suppressed: java.util.NoSuchElementException: No value present
[15:22:46 ERROR]: at java.base/java.util.Optional.get(Optional.java:143)
[15:22:46 ERROR]: at com.velocitypowered.proxy.scheduler.VelocityScheduler$TaskBuilderImpl.schedule(VelocityScheduler.java:197)
[15:22:46 ERROR]: at com.github.shynixn.mccoroutine.velocity.dispatcher.VelocityCoroutineDispatcher.dispatch(VelocityCoroutineDispatcher.kt:28)
[15:22:46 ERROR]: at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:322)
[15:22:46 ERROR]: at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
[15:22:46 ERROR]: ... 26 more
[15:22:46 ERROR]: Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [com.github.shynixn.mccoroutine.velocity.impl.CoroutineSessionImpl$special$$inlined$CoroutineExceptionHandler$1@74ea46e2, StandaloneCoroutine{Cancelling}@48b4a043, VelocityCoroutineDispatcher@2f5b8250]
[15:22:46 ERROR]: Caused by: java.util.NoSuchElementException: No value present
[15:22:46 ERROR]: at java.base/java.util.Optional.get(Optional.java:143)
[15:22:46 ERROR]: at com.velocitypowered.proxy.scheduler.VelocityScheduler$TaskBuilderImpl.schedule(VelocityScheduler.java:197)
[15:22:46 ERROR]: at com.github.shynixn.mccoroutine.velocity.impl.CoroutineSessionImpl$special$$inlined$CoroutineExceptionHandler$1.handleException(CoroutineExceptionHandler.kt:115)
[15:22:46 ERROR]: at kotlinx.coroutines.CoroutineExceptionHandlerKt.handleCoroutineException(CoroutineExceptionHandler.kt:25)
[15:22:46 ERROR]: ... 34 more
[15:22:46 ERROR]: Can't create plugin mccoroutinesample
com.google.inject.ProvisionException: Unable to provision, see the following errors:
1) [Guice/ErrorInjectingConstructor]: NoSuchElementException: No value present
at MCCoroutineSamplePlugin.<init>(AstroIslesProxy.kt:41)
at VelocityPluginModule.configure(VelocityPluginModule.java:49)
while locating MCCoroutineSamplePlugin
Learn more:
https://github.com/google/guice/wiki/ERROR_INJECTING_CONSTRUCTOR
1 error
======================
Full classname legend:
======================
MCCoroutineSamplePlugin: "com.github.jsh32.astroisles.proxy.MCCoroutineSamplePlugin"
VelocityPluginModule: "com.velocitypowered.proxy.plugin.loader.java.VelocityPluginModule"
========================
End of classname legend:
========================
at com.google.inject.internal.InternalProvisionException.toProvisionException(InternalProvisionException.java:251) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.google.inject.internal.InjectorImpl$1.get(InjectorImpl.java:1104) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1139) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.velocitypowered.proxy.plugin.loader.java.JavaPluginLoader.createPlugin(JavaPluginLoader.java:124) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.velocitypowered.proxy.plugin.VelocityPluginManager.loadPlugins(VelocityPluginManager.java:155) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.velocitypowered.proxy.VelocityServer.loadPlugins(VelocityServer.java:345) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.velocitypowered.proxy.VelocityServer.start(VelocityServer.java:227) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.velocitypowered.proxy.Velocity.main(Velocity.java:69) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
Caused by: java.util.NoSuchElementException: No value present
at java.util.Optional.get(Optional.java:143) ~[?:?]
at com.velocitypowered.proxy.scheduler.VelocityScheduler$TaskBuilderImpl.schedule(VelocityScheduler.java:197) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.github.shynixn.mccoroutine.velocity.dispatcher.VelocityCoroutineDispatcher.dispatch(VelocityCoroutineDispatcher.kt:28) ~[?:?]
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:322) ~[?:?]
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30) ~[?:?]
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25) ~[?:?]
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110) ~[?:?]
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126) ~[?:?]
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56) ~[?:?]
at kotlinx.coroutines.BuildersKt.launch(Unknown Source) ~[?:?]
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47) ~[?:?]
at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source) ~[?:?]
at com.github.shynixn.mccoroutine.velocity.impl.MCCoroutineImpl.setupCoroutineSession(MCCoroutineImpl.kt:52) ~[?:?]
at com.github.shynixn.mccoroutine.velocity.SuspendingPluginContainer.initialize(SuspendingPluginContainer.kt:44) ~[?:?]
at com.github.jsh32.astroisles.proxy.MCCoroutineSamplePlugin.<init>(AstroIslesProxy.kt:42) ~[?:?]
at com.github.jsh32.astroisles.proxy.MCCoroutineSamplePlugin$$FastClassByGuice$$1948344.GUICE$TRAMPOLINE(<generated>) ~[?:?]
at com.github.jsh32.astroisles.proxy.MCCoroutineSamplePlugin$$FastClassByGuice$$1948344.apply(<generated>) ~[?:?]
at com.google.inject.internal.DefaultConstructionProxyFactory$FastClassProxy.newInstance(DefaultConstructionProxyFactory.java:82) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:114) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:91) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:300) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:169) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:45) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
at com.google.inject.internal.InjectorImpl$1.get(InjectorImpl.java:1101) ~[velocity-3.2.0-SNAPSHOT-256.jar:3.2.0-SNAPSHOT (git-40b76c63-b256)]
... 6 more
The issue is caused by suspendingPluginContainer.initialize(this)
I don't see what's done differently with your build gradle, but it seems like sources are not bundled together in through maven. When navigating the code, IntelliJ uses decompiled .class
files rather than actual sources, so users won't be able to navigate through the code.
How does it work with canceling events and still maintain async?
Please, add bungeecord support
MCCoroutineException event may cause an exception in 2.6.0. See #84.
If you encounter it, temporarily use MCCoroutine 2.5.0 until the next version is released.
I ran into an issue where I need to do some work with a function like this:
fun Audience.susMsg(message: Component) = plugin.launch {}
I can't because Velocity plugins don't have any sort of superclasses.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.