Giter Site home page Giter Site logo

shynixn / mccoroutine Goto Github PK

View Code? Open in Web Editor NEW
176.0 7.0 16.0 24.37 MB

MCCoroutine is a library, which adds extensive support for Kotlin Coroutines for Minecraft Server environments.

License: Other

Kotlin 98.46% Java 1.54%
minecraft spigot sponge bukkit kotlin library functions server async await

mccoroutine's Introduction

Shynixn's github stats

mccoroutine's People

Contributors

geeyoueye avatar shynixn avatar spliterash avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

mccoroutine's Issues

Using MinecraftServer in Minestom

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)

AsyncDispatcher behaves like Dispatchers.Unconfined

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
    }

Q: Is "Coroutine has been cancelled." an error message? How should one avoid it?

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?

Add meaningful Spigot Timings

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.

Folia Support

Since MCCoroutine uses the normal bukkit scheduler, it seems to struggle with stuff on Folia
Any chance this can get supported?

Close the coroutine session after JavaPlugin#onDisable has been called

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.

Add function to delay by Minecraft server ticks

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.

Registering a suspend functional-style listener Velocity

Using a suspending Listener throws invisible exceptions

Issue

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.

Background of the Plugin

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.

Steps to Reproduce

  • Register any event handler (not 100% sure if its with any event, by try maybe with a chunk load event) with a SuspendingListener
  • Start the server and start a profiler using Spark. With /spark profiler --combine-all
  • Trigger the event multiple times and then use /spark profiler --stop to view the error.

Evidence

Spark Profiler - USING Suspending Listener
https://spark.lucko.me/EkXjQTa7Vp
Screen Shot 2023-05-11 at 12 59 41 pm

Spark Profiler - USING Normal Listener
https://spark.lucko.me/1UJTdh3uGz
Screen Shot 2023-05-11 at 1 00 46 pm

Deadlock when using `runBlocking(Dispatchers.Minecraft)`

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!

Help with coroutines

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?

Allow Sentry to capture exceptions

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.

[Question] Changing an event status after calling a suspending function

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.

com.github.shynixn.mccoroutine.bukkit.impl.MCCoroutineImpl not included in shaded jar

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?

Add SuspendingJavaPlugin

onEnable, onReload, onDisable often does not got used correctly with MCCoroutine, therefore an implementation should be provided

SuspendingTabCompleter missing default support

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);

Can only work on spigot

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

Deadlock when joining a job switching context to minecraft scope while plugin is disabled

Notes:

  • Only occurs when you try to join a job using runBlocking in onDisable.
  • Looking for hacktoberfest contributors.

How to fix:

  • Add a plugin.isEnabled check to isDispatchNeeded in com.github.shynixn.mccoroutine.bukkit.dispatcher.MinecraftCoroutineDispatcher and com.github.shynixn.mccoroutine.bukkit.dispatcher.AsyncCoroutineDispatcher
  • Remove if (!plugin.isEnabled) check in dispatch from those files

Hacktoberfest 2021

Hacktoberfest 2021

Welcome, 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.

Guidlines

Required Knowledge

  • Java/Kotlin

Optional Knowledge

  • Common knowledge about the Bukkit API

Code/Style/Architecture

  • Please use the existing layout of the project and avoid creating packages.
  • Keep consistency over the whole project.

Getting started

  • Look for a task below which you would like to do
  • Create a new issue with the task name
  • Fork and clone the repository to your local pc
  • Use the contributing description on the README to setup required dependencies in order to build the project.
  • Work on it :)
  • Submit a pull request to the master branch when you are done to initiate a reviewing process

Tasks

โ— 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. โ—

FAQ

Can I take more than 1 task?

Yes, but only 1 task at a time. After your first pull request has been approved, you can take the second task.

How long does it take to get feedback on a pull request?

I normally check daily for new activity on this repository.

I am not able to setup the project environment?

Just message me below this issue.

Open Tasks

  • The documentation only contains samples for the bukkit API. However, it would be nice to also have samples for the sponge API. In this task you should perform the following steps:

Completed Tasks

~

Option to call suspending events consecutively

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.
  • Using add(0, ...) to explicitly prepend the prefix works, but is messy and only fixes this specific case.

Sponge API-8?

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?

Dispatching in primary-thread

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

Potential error on reload

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

MCCoroutine for velocity does not work in velocity 3.2.x

[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)

Bundle sources with maven release

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.

Canceling

How does it work with canceling events and still maintain async?

How can I plugin.launch{} on Velocity?

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.