Skip to content

Commit

Permalink
Merge pull request #53 from HQService/dev/paper
Browse files Browse the repository at this point in the history
Dev/paper
  • Loading branch information
cccgh5 authored Jun 17, 2024
2 parents 047f158 + ffb1110 commit 10bef91
Show file tree
Hide file tree
Showing 36 changed files with 742 additions and 267 deletions.
9 changes: 7 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ kotlin.code.style=official

projectName=HQFramework
projectGroup=kr.hqservice
projectVersion=1.0.1-SNAPSHOT
projectVersion=1.0.2-SNAPSHOT
projectAuthors=vjh0107, cccgh5
projectUrl=https://github.com/HQService/HQFramework

kotlinVersion=1.7.21
spigotVersion=1.19.2-R0.1-SNAPSHOT
spigotVersion=1.20.1-R0.1-SNAPSHOT
bungeecordVersion=1.19-R0.1-SNAPSHOT
velocityVersion=3.2.0-SNAPSHOT

# https://github.com/PaperMC/Folia
foliaVersion=1.20.1-R0.1-SNAPSHOT

# https://github.com/InsertKoinIO/koin
koinVersion=3.3.3
# https://github.com/JetBrains/Exposed
Expand Down Expand Up @@ -47,3 +50,5 @@ byteBuddyVersion=1.14.4
quartzVersion=2.3.2
# https://github.com/google/gson
gsonVersion=2.10

AdventureTextVersion=4.17.0
2 changes: 1 addition & 1 deletion modules/bukkit-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ dependencies {
apiModule("global", "core")
apiModule("global", "netty")
apiModule("global", "yaml")
api(libs.spigot.api)
api(libs.paper.api)
api(libs.kotlin.reflect)
api(libs.kotlinx.coroutines.core)
api(libs.koin.core)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,13 @@ import kr.hqservice.framework.global.core.HQPlugin
import kr.hqservice.framework.global.core.component.registry.ComponentRegistry
import net.bytebuddy.agent.ByteBuddyAgent
import org.bukkit.plugin.Plugin
import org.bukkit.plugin.PluginDescriptionFile
import org.bukkit.plugin.java.JavaPluginLoader
import org.koin.core.context.startKoin
import org.koin.core.qualifier.named
import org.koin.dsl.binds
import org.koin.dsl.module
import java.io.File

abstract class HQFrameworkBukkitPlugin : HQBukkitPlugin {
constructor() : super()
constructor(loader: JavaPluginLoader, description: PluginDescriptionFile, dataFolder: File, file: File) : super(loader, description, dataFolder, file)
abstract class HQFrameworkBukkitPlugin : HQBukkitPlugin() {
//constructor(loader: JavaPluginLoader, description: PluginDescriptionFile, dataFolder: File, file: File) : super(loader, description, dataFolder, file)

final override fun onPreLoad() {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,43 @@ import kr.hqservice.framework.bukkit.core.coroutine.extension.BukkitMain
import kr.hqservice.framework.bukkit.core.coroutine.extension.childrenAll
import kr.hqservice.framework.bukkit.core.coroutine.extension.coroutineContext
import kr.hqservice.framework.bukkit.core.extension.format
import kr.hqservice.framework.bukkit.core.scheduler.HQScheduler
import kr.hqservice.framework.bukkit.core.scheduler.bukkit.HQBukkitScheduler
import kr.hqservice.framework.bukkit.core.scheduler.folia.HQFoliaGlobalScheduler
import kr.hqservice.framework.bukkit.core.scheduler.folia.HQFoliaRegionScheduler
import kr.hqservice.framework.global.core.HQPlugin
import kr.hqservice.framework.global.core.component.registry.ComponentRegistry
import kr.hqservice.framework.global.core.util.AnsiColor
import kr.hqservice.framework.yaml.config.HQYamlConfiguration
import kr.hqservice.framework.yaml.extension.yaml
import org.bukkit.Location
import org.bukkit.configuration.file.YamlConfiguration
import org.bukkit.plugin.PluginDescriptionFile
import org.bukkit.plugin.java.JavaPlugin
import org.bukkit.plugin.java.JavaPluginLoader
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.koin.core.parameter.parametersOf
import java.io.File
import java.io.InputStream
import java.io.PrintWriter
import java.nio.file.Files
import java.time.LocalDateTime
import java.util.logging.Logger
import kotlin.coroutines.CoroutineContext

abstract class HQBukkitPlugin : JavaPlugin, HQPlugin, KoinComponent, CoroutineScope, ExceptionHandlerRegistry {
constructor() : super()
internal constructor(
abstract class HQBukkitPlugin : JavaPlugin(), HQPlugin, KoinComponent, CoroutineScope, ExceptionHandlerRegistry {
/*internal constructor(
loader: JavaPluginLoader,
description: PluginDescriptionFile,
dataFolder: File,
file: File
) : super(loader, description, dataFolder, file)
) : super(loader, description, dataFolder, file)*/

protected open val bukkitComponentRegistry: BukkitComponentRegistry by inject { parametersOf(this) }
private val config = File(dataFolder, "config.yml").yaml()

// folia
private lateinit var globalScheduler: HQScheduler
private var hasRegionScheduler = false

internal companion object GlobalExceptionHandlerRegistry : ExceptionHandlerRegistry {
private val exceptionHandlers: MutableList<AttachableExceptionHandler> = mutableListOf()

Expand All @@ -61,6 +66,7 @@ abstract class HQBukkitPlugin : JavaPlugin, HQPlugin, KoinComponent, CoroutineSc
*GlobalExceptionHandlerRegistry.exceptionHandlers.toTypedArray(),
*this.exceptionHandlers.toTypedArray()
)

exceptionHandlers.forEach forEach@{ handler ->
when (handler.handle(throwable)) {
HandleResult.HANDLED -> return@handler
Expand Down Expand Up @@ -160,6 +166,15 @@ abstract class HQBukkitPlugin : JavaPlugin, HQPlugin, KoinComponent, CoroutineSc

@OptIn(ExperimentalStdlibApi::class)
final override fun onEnable() {
hasRegionScheduler = try {
Class.forName("io.papermc.paper.threadedregions.RegionizedServer")
globalScheduler = HQFoliaGlobalScheduler(this)
true
} catch (_: Exception) {
globalScheduler = HQBukkitScheduler(this)
false
}

runBlocking(coroutineContext.minusKey(CoroutineDispatcher.Key) + CoroutineName("${this@HQBukkitPlugin.name}EnableCoroutine")) {
val timerJob =
launch(Dispatchers.Default + CoroutineName("${this@HQBukkitPlugin.name}EnableTimerCoroutine")) timer@{
Expand Down Expand Up @@ -240,6 +255,15 @@ abstract class HQBukkitPlugin : JavaPlugin, HQPlugin, KoinComponent, CoroutineSc
return bukkitComponentRegistry
}

fun getScheduler(): HQScheduler {
return globalScheduler
}

fun getScheduler(location: Location): HQScheduler {
return if (hasRegionScheduler) HQFoliaRegionScheduler(this, location)
else globalScheduler
}

private fun loadConfigIfExist() {
val stream = getResource("config.yml") ?: return
val file = File(dataFolder, "config.yml")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,74 @@ package kr.hqservice.framework.bukkit.core.coroutine.dispatcher

import kotlinx.coroutines.*
import kr.hqservice.framework.bukkit.core.coroutine.element.PluginCoroutineContextElement
import kr.hqservice.framework.bukkit.core.scheduler.getScheduler
import org.bukkit.Bukkit
import org.bukkit.Location
import org.bukkit.plugin.IllegalPluginAccessException
import org.bukkit.plugin.Plugin
import org.bukkit.scheduler.BukkitRunnable
import kotlin.coroutines.CoroutineContext

@OptIn(InternalCoroutinesApi::class, ExperimentalCoroutinesApi::class)
class BukkitDispatcher(private val isAsync: Boolean) : MainCoroutineDispatcher(), Delay {
class BukkitDispatcher(private val isAsync: Boolean, private val location: Location?) : MainCoroutineDispatcher(), Delay {
override val immediate: MainCoroutineDispatcher
get() = BukkitMainDispatcherImmediate()

override fun dispatch(context: CoroutineContext, block: Runnable) {
val plugin = getPluginByCoroutineContext(context)
try {
if (isAsync) Bukkit.getScheduler().runTaskAsynchronously(plugin, block)
else Bukkit.getScheduler().runTask(plugin, block)
if (location != null) {
if (isAsync) plugin.getScheduler(location).runTaskAsynchronously { block.run() }
else plugin.getScheduler(location).runTask { block.run() }
}
else {
if (isAsync) plugin.getScheduler().runTaskAsynchronously { block.run() }
else plugin.getScheduler().runTask { block.run() }
}
} catch (_: IllegalPluginAccessException) {}
}

override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
val plugin = getPluginByCoroutineContext(continuation.context)
val runnable = object : BukkitRunnable() {
override fun run() {
with(continuation) {
resumeUndispatched(Unit)
}

val task = if (location != null) {
if (isAsync) {
try {
plugin.getScheduler(location).runTaskLaterAsynchronously(timeMillis / 50) {
with(continuation) {
resumeUndispatched(Unit)
}
}
} catch (_: IllegalPluginAccessException) { null }
} else {
try {
plugin.getScheduler(location).runTaskLater(timeMillis / 50) {
with(continuation) {
resumeUndispatched(Unit)
}
}
} catch (_: IllegalPluginAccessException) { null }
}
}
val task = if (isAsync) {
try {
runnable.runTaskLaterAsynchronously(plugin, timeMillis / 50)
} catch (_: IllegalPluginAccessException) { null }
} else {
try {
runnable.runTaskLater(plugin, timeMillis / 50)
} catch (_: IllegalPluginAccessException) { null }
if (isAsync) {
try {
plugin.getScheduler().runTaskLaterAsynchronously(timeMillis / 50) {
with(continuation) {
resumeUndispatched(Unit)
}
}
} catch (_: IllegalPluginAccessException) { null }
} else {
try {
plugin.getScheduler().runTaskLater(timeMillis / 50) {
with(continuation) {
resumeUndispatched(Unit)
}
}
} catch (_: IllegalPluginAccessException) { null }
}
}

continuation.invokeOnCancellation { task?.cancel() }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,21 @@ package kr.hqservice.framework.bukkit.core.coroutine.extension
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kr.hqservice.framework.bukkit.core.coroutine.dispatcher.BukkitDispatcher
import org.bukkit.Location

private val bukkitMainDispatcher = BukkitDispatcher(false)
private val bukkitAsyncDispatcher = BukkitDispatcher(true)
private val bukkitMainDispatcher = BukkitDispatcher(false, null)
private val bukkitAsyncDispatcher = BukkitDispatcher(true, null)

val Dispatchers.BukkitMain: CoroutineDispatcher
get() = bukkitMainDispatcher

val Dispatchers.BukkitAsync: CoroutineDispatcher
get() = bukkitAsyncDispatcher
get() = bukkitAsyncDispatcher

fun Dispatchers.FoliaRegion(location: Location): CoroutineDispatcher {
return BukkitDispatcher(false, location)
}

fun Dispatchers.FoliaRegionAsync(location: Location): CoroutineDispatcher {
return BukkitDispatcher(true, location)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package kr.hqservice.framework.bukkit.core.listener

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.merge
import kr.hqservice.framework.bukkit.core.HQBukkitPlugin
import org.bukkit.event.Event
import org.bukkit.event.Listener
Expand All @@ -20,25 +21,25 @@ class SuspendEventExecutor(
private val method: KFunction<*>,
private val plugin: HQBukkitPlugin
) : EventExecutor {
@OptIn(ExperimentalStdlibApi::class)
private val suspend = method.isSuspend

override fun execute(empty: Listener, event: Event) {
if (eventClass.isInstance(event)) {
runBlocking {
val dispatcher = coroutineContext[CoroutineDispatcher.Key]!!
CoroutineScope(plugin.coroutineContext.minusKey(CoroutineDispatcher.Key)).launch(dispatcher) {
invokeHandlerMethod(event)
}
}
invokeHandlerMethod(event)
}
}

private suspend fun invokeHandlerMethod(event: Event) {
@OptIn(ExperimentalStdlibApi::class)
private fun invokeHandlerMethod(event: Event) {
try {
if (method.isSuspend) {
method.callSuspend(listenerInstance, event)
} else {
method.call(listenerInstance, event)
}
if (suspend) {
runBlocking {
val dispatcher = coroutineContext[CoroutineDispatcher.Key]!!
CoroutineScope(plugin.coroutineContext.minusKey(CoroutineDispatcher.Key)).launch(dispatcher) {
method.callSuspend(listenerInstance, event)
}
}
} else method.call(listenerInstance, event)
} catch (exception: InvocationTargetException) {
val cause = exception.cause ?: exception
throw cause
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import org.bukkit.event.Event
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.Listener
import org.bukkit.plugin.EventExecutor
import org.bukkit.plugin.RegisteredListener
import kotlin.reflect.KClass
import kotlin.reflect.KFunction
import kotlin.reflect.full.*
import kotlin.reflect.jvm.isAccessible
import kotlin.reflect.jvm.javaMethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package kr.hqservice.framework.bukkit.core.netty
import kr.hqservice.framework.bukkit.core.netty.event.AsyncNettyPacketReceivedEvent
import kr.hqservice.framework.bukkit.core.netty.event.NettyClientDisconnectedEvent
import kr.hqservice.framework.bukkit.core.netty.event.NettyPacketReceivedEvent
import kr.hqservice.framework.bukkit.core.scheduler.getScheduler
import kr.hqservice.framework.netty.HQNettyBootstrap
import kr.hqservice.framework.netty.packet.Direction
import kr.hqservice.framework.netty.packet.message.BroadcastPacket
Expand Down Expand Up @@ -48,9 +49,10 @@ class NettyClientBootstrap(
handlerBoss.setDisconnectionHandler {
if (!plugin.isEnabled) return@setDisconnectionHandler
it.setEnabled(false)
plugin.server.scheduler.runTask(plugin, Runnable {
plugin.getScheduler().runTask {
plugin.server.pluginManager.callEvent(NettyClientDisconnectedEvent(it))
})
}

try {
TimeUnit.SECONDS.sleep(3)
initializing()
Expand All @@ -62,9 +64,9 @@ class NettyClientBootstrap(
handlerBoss.setPacketPreprocessHandler { packet, wrapper ->
if (!plugin.isEnabled) return@setPacketPreprocessHandler
plugin.server.pluginManager.callEvent(AsyncNettyPacketReceivedEvent(wrapper, packet))
plugin.server.scheduler.runTask(plugin, Runnable {
plugin.getScheduler().runTask {
plugin.server.pluginManager.callEvent(NettyPacketReceivedEvent(wrapper, packet))
})
}
}

logger.info("netty-client initialization success!")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package kr.hqservice.framework.bukkit.core.scheduler

interface HQScheduler {
fun runTask(runnable: () -> Unit)

fun runTaskLater(delay: Long, runnable: () -> Unit): HQTask

fun runTaskTimer(delay: Long, period: Long, runnable: () -> Unit): HQTask

fun runTaskAsynchronously(runnable: () -> Unit): HQTask

fun runTaskLaterAsynchronously(delay: Long, runnable: () -> Unit): HQTask

fun runTaskTimerAsynchronously(delay: Long, period: Long, runnable: () -> Unit): HQTask
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package kr.hqservice.framework.bukkit.core.scheduler

interface HQTask {
fun isCancelled(): Boolean

fun cancel()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package kr.hqservice.framework.bukkit.core.scheduler

import kr.hqservice.framework.bukkit.core.HQBukkitPlugin
import kr.hqservice.framework.bukkit.core.scheduler.bukkit.HQBukkitScheduler
import org.bukkit.Location
import org.bukkit.plugin.Plugin

fun Plugin.getScheduler(): HQScheduler {
return if (this is HQBukkitPlugin) getScheduler()
else HQBukkitScheduler(this)
}

fun Plugin.getScheduler(location: Location): HQScheduler {
return if (this is HQBukkitPlugin) getScheduler(location)
else HQBukkitScheduler(this)
}
Loading

0 comments on commit 10bef91

Please sign in to comment.