Skip to content

Commit

Permalink
Merge pull request #15 from Shynixn/development
Browse files Browse the repository at this point in the history
Merge changes to master. --release
  • Loading branch information
Shynixn authored Nov 21, 2020
2 parents edb5fe8 + af9b7a8 commit face8eb
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 128 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ Include the dependency to MCCoroutine
<dependency>
<groupId>com.github.shynixn.mccoroutine</groupId>
<artifactId>mccoroutine-bukkit-api</artifactId>
<version>0.0.4</version>
<version>0.0.5</version>
<scope>provided</scope>
</dependency>
```
**Gradle**

```xml
dependencies {
compileOnly("com.github.shynixn.mccoroutine:mccoroutine-bukkit-api:0.0.4")
compileOnly("com.github.shynixn.mccoroutine:mccoroutine-bukkit-api:0.0.5")
}
```

Expand Down Expand Up @@ -198,12 +198,12 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlin.coroutines.CoroutineContext

fun launch(f: suspend CoroutineScope.() -> Unit) {
JavaPlugin.getPlugin(YourPluginClass::class.java).launch(f)
fun launch(f: suspend CoroutineScope.() -> Unit): Job {
return JavaPlugin.getPlugin(YourPluginClass::class.java).launch(f)
}

fun launchAsync(f: suspend CoroutineScope.() -> Unit) {
JavaPlugin.getPlugin(YourPluginClass::class.java).launchAsync(f)
fun launchAsync(f: suspend CoroutineScope.() -> Unit): Job {
return JavaPlugin.getPlugin(YourPluginClass::class.java).launchAsync(f)
}

val Dispatchers.minecraft: CoroutineContext
Expand Down Expand Up @@ -486,7 +486,7 @@ class PlaceHolderApiConnector(private val cache : UserDataCache) {
<dependency>
<groupId>com.github.shynixn.mccoroutine</groupId>
<artifactId>mccoroutine-bukkit-core</artifactId>
<version>0.0.4</version>
<version>0.0.5</version>
<scope>compile</scope>
</dependency>
<dependency>
Expand All @@ -512,7 +512,7 @@ class PlaceHolderApiConnector(private val cache : UserDataCache) {

```xml
dependencies {
implementation("com.github.shynixn.mccoroutine:mccoroutine-bukkit-core:0.0.4")
implementation("com.github.shynixn.mccoroutine:mccoroutine-bukkit-core:0.0.5")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.x.x")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.x.x")
implementation("org.jetbrains.kotlin:kotlin-reflect:1.x.x")
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ allprojects {

subprojects {
group 'com.github.shynixn.mccoroutine'
version '0.0.4'
version '0.0.5'

sourceCompatibility = 1.8

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.github.shynixn.mccoroutine

import com.github.shynixn.mccoroutine.contract.MCCoroutine
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import org.bukkit.command.PluginCommand
import org.bukkit.event.Listener
import org.bukkit.plugin.Plugin
Expand Down Expand Up @@ -68,9 +69,10 @@ val Plugin.scope: CoroutineScope
* for example that event cancelling or modifying return values is still possible.
* @param dispatcher Coroutine context. The default context is minecraft dispatcher.
* @param f callback function inside a coroutine scope.
* @return Cancelable coroutine job.
*/
fun Plugin.launch(dispatcher: CoroutineContext, f: suspend CoroutineScope.() -> Unit) {
mcCoroutine.getCoroutineSession(this).launch(dispatcher, f)
fun Plugin.launch(dispatcher: CoroutineContext, f: suspend CoroutineScope.() -> Unit): Job {
return mcCoroutine.getCoroutineSession(this).launch(dispatcher, f)
}

/**
Expand All @@ -79,9 +81,10 @@ fun Plugin.launch(dispatcher: CoroutineContext, f: suspend CoroutineScope.() ->
* calling this function Bukkit.isPrimaryThread() is true. This means
* for example that event cancelling or modifying return values is still possible.
* @param f callback function inside a coroutine scope.
* @return Cancelable coroutine job.
*/
fun Plugin.launch(f: suspend CoroutineScope.() -> Unit) {
mcCoroutine.getCoroutineSession(this).launch(minecraftDispatcher, f)
fun Plugin.launch(f: suspend CoroutineScope.() -> Unit): Job {
return mcCoroutine.getCoroutineSession(this).launch(minecraftDispatcher, f)
}

/**
Expand All @@ -90,9 +93,10 @@ fun Plugin.launch(f: suspend CoroutineScope.() -> Unit) {
* calling this function Bukkit.isPrimaryThread() is false. This means
* for example that event cancelling or modifying return values is still possible.
* @param f callback function inside a coroutine scope.
* @return Cancelable coroutine job.
*/
fun Plugin.launchAsync(f: suspend CoroutineScope.() -> Unit) {
mcCoroutine.getCoroutineSession(this).launch(this.asyncDispatcher, f)
fun Plugin.launchAsync(f: suspend CoroutineScope.() -> Unit): Job {
return mcCoroutine.getCoroutineSession(this).launch(this.asyncDispatcher, f)
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.shynixn.mccoroutine.contract

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlin.coroutines.CoroutineContext

interface CoroutineSession {
Expand Down Expand Up @@ -31,8 +32,9 @@ interface CoroutineSession {

/**
* Launches the given function on the plugin coroutine scope.
* @return Cancelable coroutine job.
*/
fun launch(dispatcher: CoroutineContext, f: suspend CoroutineScope.() -> Unit)
fun launch(dispatcher: CoroutineContext, f: suspend CoroutineScope.() -> Unit) : Job

/**
* Disposes the session.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,17 @@ internal class CoroutineSessionImpl(private val plugin: Plugin) : CoroutineSessi
/**
* Launches the given function on the plugin coroutine scope.
*/
override fun launch(dispatcher: CoroutineContext, f: suspend CoroutineScope.() -> Unit) {
override fun launch(dispatcher: CoroutineContext, f: suspend CoroutineScope.() -> Unit) : Job {
if (disposed) {
return
return Job()
}

if (dispatcher == Dispatchers.Unconfined) {
// If the dispatcher is unconfined. Always schedule immediately.
launchInternal(dispatcher, CoroutineStart.UNDISPATCHED, f)
return
return launchInternal(dispatcher, CoroutineStart.UNDISPATCHED, f)
}

launchInternal(dispatcher, CoroutineStart.DEFAULT, f)
return launchInternal(dispatcher, CoroutineStart.DEFAULT, f)
}

/**
Expand All @@ -81,9 +80,9 @@ internal class CoroutineSessionImpl(private val plugin: Plugin) : CoroutineSessi
dispatcher: CoroutineContext,
coroutineStart: CoroutineStart,
f: suspend CoroutineScope.() -> Unit
) {
) : Job {
// Launch a new coroutine on the current thread thread on the plugin scope.
scope.launch(dispatcher, coroutineStart) {
return scope.launch(dispatcher, coroutineStart) {
try {
// The user may or may not launch multiple sub suspension operations. If
// one of those fails, only this scope should fail instead of the plugin scope.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,17 @@ package com.github.shynixn.mccoroutine.service
import com.github.shynixn.mccoroutine.contract.CoroutineSession
import com.github.shynixn.mccoroutine.contract.EventService
import com.github.shynixn.mccoroutine.extension.invokeSuspend
import com.github.shynixn.mccoroutine.launch
import com.github.shynixn.mccoroutine.minecraftDispatcher
import kotlinx.coroutines.Dispatchers
import org.bukkit.Warning
import org.bukkit.event.*
import org.bukkit.plugin.*
import org.bukkit.plugin.java.JavaPluginLoader
import java.lang.Deprecated
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
import java.util.*
import java.util.logging.Level
import kotlin.Any
import kotlin.Exception
import kotlin.IllegalArgumentException
import kotlin.Int
import kotlin.String
import kotlin.Throwable
import kotlin.collections.HashMap
import kotlin.collections.HashSet

internal class EventServiceImpl(private val plugin: Plugin, private val coroutineSession: CoroutineSession) :
EventService {
Expand All @@ -37,119 +28,96 @@ internal class EventServiceImpl(private val plugin: Plugin, private val coroutin
method.isAccessible = true

for (entry in registeredListeners.entries) {
val clazz = entry.key as Class<*>
val clazz = entry.key
val handlerList = method.invoke(plugin.server.pluginManager, clazz) as HandlerList
handlerList.registerAll(entry.value as MutableCollection<RegisteredListener>)
}
}

/**
* Ugly coroutine listener hacking.
* Creates a listener according to the spigot implementation.
*/
private fun createCoroutineListener(listener: Listener, plugin: Plugin): HashMap<*, *> {
val ret: HashMap<Class<*>, Set<RegisteredListener?>> = HashMap()
private fun createCoroutineListener(
listener: Listener,
plugin: Plugin
): Map<Class<*>, MutableSet<RegisteredListener>> {
val eventMethods = HashSet<Method>()

val methods: HashSet<*>
try {
val publicMethods = listener.javaClass.methods
val privateMethods = listener.javaClass.declaredMethods
methods = HashSet<Any?>(publicMethods.size + privateMethods.size, 1.0f)
var var11 = publicMethods
var var10 = publicMethods.size
var method: Method?
var var9: Int
var9 = 0
while (var9 < var10) {
method = var11[var9]
methods.add(method)
++var9
// Adds public methods of the current class and inherited classes
eventMethods.addAll(listener.javaClass.methods)
// Adds all methods of the current class
eventMethods.addAll(listener.javaClass.declaredMethods)
} catch (e: NoClassDefFoundError) {
plugin.logger.severe("Plugin " + plugin.description.fullName + " has failed to register events for " + listener.javaClass + " because " + e.message + " does not exist.")
return emptyMap()
}

val result = mutableMapOf<Class<*>, MutableSet<RegisteredListener>>()

for (method in eventMethods) {
val annotation = method.getAnnotation(EventHandler::class.java)

if (annotation == null || method.isBridge || method.isSynthetic) {
continue
}
var11 = privateMethods
var10 = privateMethods.size
var9 = 0
while (var9 < var10) {
method = var11[var9]
methods.add(method)
++var9

val eventClass = method.parameterTypes[0].asSubclass(Event::class.java)
method.isAccessible = true

if (!result.containsKey(eventClass)) {
result[eventClass] = HashSet()
}
} catch (var15: NoClassDefFoundError) {
plugin.logger.severe("Plugin " + plugin.description.fullName + " has failed to register events for " + listener.javaClass + " because " + var15.message + " does not exist.")
return ret
}

val var17: Iterator<*> = methods.iterator()

while (true) {
while (true) {
var method: Method
var eh: EventHandler?
do {
do {
do {
if (!var17.hasNext()) {
return ret
}
method = var17.next() as Method
eh = method.getAnnotation(EventHandler::class.java)
} while (eh == null)
} while (method.isBridge)
} while (method.isSynthetic)

var checkClass: Class<*> = method.getParameterTypes()[0]
val eventClass = checkClass.asSubclass(Event::class.java)
method.isAccessible = true

var eventSet: MutableSet<RegisteredListener?>? = ret[eventClass] as MutableSet<RegisteredListener?>?

if (eventSet == null) {
eventSet = HashSet<RegisteredListener?>()
ret[eventClass] = eventSet
}
var clazz: Class<*> = eventClass

var clazz: Class<*> = eventClass

while (Event::class.java.isAssignableFrom(clazz)) {
if (clazz.getAnnotation(Deprecated::class.java) != null) {
val warning = clazz.getAnnotation(Warning::class.java)
val warningState: Warning.WarningState = plugin.server.getWarningState()
if (warningState.printFor(warning)) {
plugin.logger.log(
Level.WARNING,
String.format(
"\"%s\" has registered a listener for %s on method \"%s\", but the event is Deprecated. \"%s\"; please notify the authors %s.",
plugin.description.fullName,
clazz.name,
method.toGenericString(),
if (warning != null && warning.reason.length != 0) warning.reason else "Server performance will be affected",
Arrays.toString(plugin.description.authors.toTypedArray())
),
if (warningState == Warning.WarningState.ON) AuthorNagException(null as String?) else null
)
}
break
}
while (Event::class.java.isAssignableFrom(clazz)) {
if (clazz.getAnnotation(Deprecated::class.java) == null) {
clazz = clazz.superclass
continue
}

val warning = clazz.getAnnotation(Warning::class.java)
val warningState = plugin.server.warningState

if (!warningState.printFor(warning)) {
break
}

val executor = createEventExecutor(plugin, eventClass, method)
eventSet!!.add(
RegisteredListener(
listener,
executor,
eh!!.priority,
plugin,
eh!!.ignoreCancelled
)
plugin.logger.log(
Level.WARNING,
""""%s" has registered a listener for %s on method "%s", but the event is Deprecated. "%s"; please notify the authors %s.""".format(
plugin.description.fullName,
clazz.name,
method.toGenericString(),
if (warning?.reason?.isNotEmpty() == true) warning.reason else "Server performance will be affected",
plugin.description.authors.toTypedArray().contentToString()
),
if (warningState == Warning.WarningState.ON) {
AuthorNagException(null as String?)
} else null
)
}

val executor = createEventExecutor(eventClass, method)
result[eventClass]!!.add(
RegisteredListener(
listener,
executor,
annotation.priority,
plugin,
annotation.ignoreCancelled
)
)
}

return result
}

/**
* Creates a single event executor.
*/
private fun createEventExecutor(
plugin: Plugin,
eventClass: Class<*>,
method: Method
): EventExecutor {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ package helper
import com.github.shynixn.mccoroutine.contract.CommandService
import com.github.shynixn.mccoroutine.contract.CoroutineSession
import com.github.shynixn.mccoroutine.contract.EventService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.*
import org.mockito.Mockito
import kotlin.coroutines.CoroutineContext

Expand Down Expand Up @@ -48,8 +45,8 @@ class MockedCoroutineSession : CoroutineSession {
/**
* Launches the given function on the plugin coroutine scope.
*/
override fun launch(dispatcher: CoroutineContext, f: suspend kotlinx.coroutines.CoroutineScope.() -> Unit) {
GlobalScope.launch(dispatcher) {
override fun launch(dispatcher: CoroutineContext, f: suspend kotlinx.coroutines.CoroutineScope.() -> Unit) : Job {
return GlobalScope.launch(dispatcher) {
f.invoke(this)
}
}
Expand Down
Loading

0 comments on commit face8eb

Please sign in to comment.