Initial commit
This commit is contained in:
1 parent
57a6538f85
commit
4de4f7bf53
19 files changed
+984
-17
No files matched your search
@@ -0,0 +1,42 @@
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
@@ -0,0 +1,112 @@
|
||||
plugins {
|
||||
id("java")
|
||||
kotlin("jvm")
|
||||
id("com.github.johnrengelman.shadow") version "7.1.2"
|
||||
id("maven-publish")
|
||||
id("signing")
|
||||
}
|
||||
|
||||
group = "me.redtea"
|
||||
val globalArtifactId = "kotlinbukkitkit-architecture"
|
||||
val globalName = "kotlinbukkitkit-architecture"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
name = "spigotmc-repo"
|
||||
url = uri("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT")
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(8)
|
||||
}
|
||||
|
||||
kotlin {
|
||||
sourceSets.main {
|
||||
kotlin.srcDir("build/generated/ksp/main/kotlin")
|
||||
}
|
||||
sourceSets.test {
|
||||
kotlin.srcDir("build/generated/ksp/test/kotlin")
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
withJavadocJar()
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("maven") {
|
||||
artifactId = globalArtifactId
|
||||
groupId = "io.github.iredtea"
|
||||
version = version
|
||||
from(components["java"])
|
||||
versionMapping {
|
||||
usage("java-api") {
|
||||
fromResolutionOf("runtimeClasspath")
|
||||
}
|
||||
usage("java-runtime") {
|
||||
fromResolutionResult()
|
||||
}
|
||||
}
|
||||
pom {
|
||||
artifactId = globalArtifactId
|
||||
groupId = "io.github.iredtea"
|
||||
version = version
|
||||
name.set(globalArtifactId)
|
||||
description.set(globalArtifactId)
|
||||
url.set("https://github.com/iRedTea/CarcadeX")
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name.set("GNU General Public License v3.0")
|
||||
url.set("https://www.gnu.org/licenses/gpl-3.0.en.html")
|
||||
}
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id.set("itzRedTea")
|
||||
name.set("Red Tea")
|
||||
email.set("red__tea@outlook.com")
|
||||
}
|
||||
}
|
||||
scm {
|
||||
connection.set("scm:https://github.com/CarcadeX/$globalName.git")
|
||||
developerConnection.set("git@github.com:CarcadeX/$globalName.git")
|
||||
url.set("https://github.com/iRedTea/CarcadeX")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
val releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
|
||||
val snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
|
||||
url = uri(if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl)
|
||||
credentials {
|
||||
username = "itzRedTea"
|
||||
password = project.findProperty("password").toString()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
signing {
|
||||
useGpgCmd()
|
||||
sign(publishing.publications.getByName("maven"))
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.architecture
|
||||
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
|
||||
AUTHOR: https://github.com/DevSrSouza
|
||||
|
||||
Thanks DevSrSouza for KotlinBukkitAPI
|
||||
*/
|
||||
package me.redtea.kotlinbukkitkit.architecture
|
||||
|
||||
import me.redtea.kotlinbukkitkit.architecture.lifecycle.Lifecycle
|
||||
import me.redtea.kotlinbukkitkit.architecture.lifecycle.LifecycleEvent
|
||||
import me.redtea.kotlinbukkitkit.architecture.lifecycle.LifecycleListener
|
||||
import me.redtea.kotlinbukkitkit.architecture.lifecycle.PluginLifecycleListener
|
||||
import org.bukkit.plugin.java.JavaPlugin
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
|
||||
|
||||
// remove all this APIs and create a `lifecycle aware` implementation.
|
||||
// This will be possible to integrate the lifecycle mechanism of KBAPI in non Bukkit plugins
|
||||
// for example in Nova Addon
|
||||
// more close to what LifecycleOwner is in the Android API
|
||||
// this could be accomplished using delegate implementation
|
||||
|
||||
public abstract class KotlinPlugin : JavaPlugin() {
|
||||
|
||||
public open fun onPluginLoad() {}
|
||||
public open fun onPluginEnable() {}
|
||||
public open fun onPluginDisable() {}
|
||||
public open fun onConfigReload() {}
|
||||
|
||||
/**
|
||||
* Register the lifecycle listener returned by the [block] lambda with the given [priority].
|
||||
*
|
||||
* **Priority Order**: High priority loads first and disable lastly
|
||||
*/
|
||||
public inline fun <P : KotlinPlugin, T : LifecycleListener<P>> lifecycle(
|
||||
priority: Int = 1,
|
||||
block: () -> T,
|
||||
): T = block().also {
|
||||
registerKotlinPluginLifecycle(priority, it as LifecycleListener<KotlinPlugin>)
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a lifecycle listener with the given [priority].
|
||||
*
|
||||
* **Priority Order**: High priority loads first and disable lastly
|
||||
*/
|
||||
public fun registerKotlinPluginLifecycle(
|
||||
priority: Int = 1,
|
||||
listener: PluginLifecycleListener,
|
||||
) {
|
||||
_lifecycleListeners.put(
|
||||
Lifecycle(
|
||||
priority,
|
||||
listener,
|
||||
),
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
// implementation stuff, ignore...
|
||||
|
||||
private val _lifecycleListeners = ConcurrentHashMap<Lifecycle, Boolean>()
|
||||
public val lifecycleListeners: Set<Lifecycle> = _lifecycleListeners.keys
|
||||
|
||||
private fun lifecycleLoadOrder() = _lifecycleListeners.keys.sortedBy { it.priority }.asReversed()
|
||||
private fun lifecycleDisableOrder() = _lifecycleListeners.keys.sortedBy { it.priority }
|
||||
|
||||
final override fun onLoad() {
|
||||
onPluginLoad()
|
||||
|
||||
for (lifecycle in lifecycleLoadOrder())
|
||||
lifecycle.listener(LifecycleEvent.LOAD)
|
||||
}
|
||||
|
||||
final override fun onEnable() {
|
||||
onPluginEnable()
|
||||
|
||||
for (lifecycle in lifecycleLoadOrder())
|
||||
lifecycle.listener(LifecycleEvent.ENABLE)
|
||||
}
|
||||
|
||||
final override fun onDisable() {
|
||||
onPluginDisable()
|
||||
|
||||
// reversing lifecycles for execute first the low priority ones
|
||||
val reversedLifecyle = lifecycleDisableOrder()
|
||||
|
||||
for (lifecycle in reversedLifecyle)
|
||||
lifecycle.listener(LifecycleEvent.DISABLE)
|
||||
}
|
||||
|
||||
final override fun reloadConfig() {
|
||||
super.reloadConfig()
|
||||
|
||||
someConfigReloaded(all = true)
|
||||
}
|
||||
|
||||
public fun someConfigReloaded(all: Boolean = false) {
|
||||
onConfigReload()
|
||||
|
||||
for (lifecycle in lifecycleListeners)
|
||||
lifecycle.listener(
|
||||
if (all) {
|
||||
LifecycleEvent.ALL_CONFIG_RELOAD
|
||||
} else LifecycleEvent.CONFIG_RELOAD,
|
||||
)
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.architecture
|
||||
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
|
||||
AUTHOR: https://github.com/DevSrSouza
|
||||
|
||||
Thanks DevSrSouza for KotlinBukkitAPI
|
||||
*/
|
||||
package me.redtea.kotlinbukkitkit.architecture
|
||||
|
||||
import me.redtea.kotlinbukkitkit.architecture.extensions.WithPlugin
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.HandlerList
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.server.PluginDisableEvent
|
||||
import org.bukkit.plugin.Plugin
|
||||
import java.util.WeakHashMap
|
||||
|
||||
/**
|
||||
* A holder for all instance of a class [T] that is bound a specific plugin.
|
||||
* It unregister when the plugin is disable.
|
||||
*/
|
||||
public abstract class PluginDisableAwareController<T : PluginDisableAware> {
|
||||
|
||||
public abstract val factory: (plugin: Plugin) -> T
|
||||
|
||||
private val instances: WeakHashMap<Plugin, T> = WeakHashMap()
|
||||
private val listeners: WeakHashMap<Plugin, Listener> = WeakHashMap()
|
||||
|
||||
public fun get(plugin: Plugin): T {
|
||||
return instances.getOrPut(plugin) {
|
||||
listeners.put(
|
||||
plugin,
|
||||
DisableListener(plugin, ::disable).apply {
|
||||
Bukkit.getServer().pluginManager.registerEvents(this, plugin)
|
||||
},
|
||||
)
|
||||
factory(plugin)
|
||||
}
|
||||
}
|
||||
|
||||
public fun ensureInitialized(plugin: Plugin) {
|
||||
get(plugin)
|
||||
}
|
||||
|
||||
private fun disable(plugin: Plugin) {
|
||||
instances.remove(plugin)?.onDisable()
|
||||
listeners.remove(plugin)?.also(HandlerList::unregisterAll)
|
||||
}
|
||||
}
|
||||
|
||||
public interface PluginDisableAware : WithPlugin<Plugin> {
|
||||
public fun onDisable()
|
||||
}
|
||||
|
||||
private class DisableListener(
|
||||
val plugin: Plugin,
|
||||
val onDisable: (Plugin) -> Unit,
|
||||
) : Listener {
|
||||
@EventHandler
|
||||
public fun pluginDisableEvent(event: PluginDisableEvent) {
|
||||
if (event.plugin.name == plugin.name) {
|
||||
onDisable(plugin)
|
||||
}
|
||||
}
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.architecture
|
||||
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
|
||||
AUTHOR: https://github.com/DevSrSouza
|
||||
|
||||
Thanks DevSrSouza for KotlinBukkitAPI.
|
||||
*/
|
||||
package me.redtea.kotlinbukkitkit.architecture.extensions
|
||||
|
||||
import me.redtea.kotlinbukkitkit.architecture.KotlinPlugin
|
||||
import org.bukkit.plugin.Plugin
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
* Delegate that returns the plugin dependency if the plugin is installed in the server
|
||||
* otherwise, returns null
|
||||
*/
|
||||
public inline fun <reified T : Plugin> KotlinPlugin.softDepend(
|
||||
pluginName: String,
|
||||
): SoftDependencyDelegate<T> = softDepend(T::class, pluginName)
|
||||
|
||||
public fun <T : Plugin> KotlinPlugin.softDepend(
|
||||
type: KClass<T>,
|
||||
pluginName: String,
|
||||
): SoftDependencyDelegate<T> =
|
||||
SoftDependencyDelegate(
|
||||
pluginName,
|
||||
type,
|
||||
)
|
||||
|
||||
/**
|
||||
* Delegate that returns the plugin dependency, disable the plugin if the plugin
|
||||
* is not available.
|
||||
*/
|
||||
public inline fun <reified T : Plugin> KotlinPlugin.depend(
|
||||
pluginName: String,
|
||||
): DependencyDelegate<T> = depend(T::class, pluginName)
|
||||
|
||||
public fun <T : Plugin> KotlinPlugin.depend(
|
||||
type: KClass<T>,
|
||||
pluginName: String,
|
||||
): DependencyDelegate<T> =
|
||||
DependencyDelegate(pluginName, type)
|
||||
|
||||
public class DependencyDelegate<T : Plugin>(
|
||||
public val pluginName: String,
|
||||
public val type: KClass<T>,
|
||||
) : ReadOnlyProperty<KotlinPlugin, T> {
|
||||
|
||||
private var isDisabled: Boolean = false
|
||||
private var cache: T? = null
|
||||
|
||||
override fun getValue(
|
||||
thisRef: KotlinPlugin,
|
||||
property: KProperty<*>,
|
||||
): T {
|
||||
if (cache == null) {
|
||||
val plugin = thisRef.server.pluginManager.getPlugin(pluginName)
|
||||
|
||||
if (plugin != null) {
|
||||
if (type.isInstance(plugin)) {
|
||||
cache = plugin as T
|
||||
} else {
|
||||
thisRef.server.pluginManager.disablePlugin(thisRef)
|
||||
error(
|
||||
"Invalid plugin dependency with the name $pluginName: " +
|
||||
"The plugin do not match main class with ${type.qualifiedName}.",
|
||||
)
|
||||
}
|
||||
} else {
|
||||
thisRef.server.pluginManager.disablePlugin(thisRef)
|
||||
error("Missing plugin dependency: $pluginName")
|
||||
}
|
||||
}
|
||||
|
||||
return cache!!
|
||||
}
|
||||
}
|
||||
|
||||
public class SoftDependencyDelegate<T : Plugin>(
|
||||
public val pluginName: String,
|
||||
public val type: KClass<T>,
|
||||
) : ReadOnlyProperty<KotlinPlugin, T?> {
|
||||
|
||||
private var alreadySearch: Boolean = false
|
||||
private var cache: T? = null
|
||||
|
||||
override fun getValue(
|
||||
thisRef: KotlinPlugin,
|
||||
property: KProperty<*>,
|
||||
): T? {
|
||||
if (!alreadySearch) {
|
||||
val plugin = thisRef.server.pluginManager.getPlugin(pluginName) ?: return null
|
||||
|
||||
alreadySearch = true
|
||||
|
||||
if (type.isInstance(plugin)) {
|
||||
cache = plugin as T
|
||||
} else {
|
||||
thisRef.server.pluginManager.disablePlugin(thisRef)
|
||||
error(
|
||||
"Invalid plugin dependency with the name $pluginName: " +
|
||||
"The plugin do not match main class with ${type.qualifiedName}.",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return cache
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.architecture
|
||||
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
|
||||
AUTHOR: https://github.com/DevSrSouza
|
||||
|
||||
Thanks DevSrSouza for KotlinBukkitAPI
|
||||
*/
|
||||
package me.redtea.kotlinbukkitkit.architecture.extensions
|
||||
|
||||
import org.bukkit.plugin.Plugin
|
||||
|
||||
// TODO: make it a experimental API that will be replaced with Context Receivers in the future
|
||||
public interface WithPlugin<T : Plugin> { public val plugin: T }
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.architecture
|
||||
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
|
||||
AUTHOR: https://github.com/DevSrSouza
|
||||
|
||||
Thanks DevSrSouza for KotlinBukkitAPI
|
||||
*/
|
||||
package me.redtea.kotlinbukkitkit.architecture.lifecycle
|
||||
|
||||
/**
|
||||
* Holds a lifecycle listener class and its priority
|
||||
*/
|
||||
public data class Lifecycle(
|
||||
val priority: Int,
|
||||
val listener: PluginLifecycleListener,
|
||||
) : Comparable<Lifecycle> {
|
||||
|
||||
override fun compareTo(
|
||||
other: Lifecycle,
|
||||
): Int = other.priority.compareTo(priority)
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.architecture
|
||||
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
|
||||
AUTHOR: https://github.com/DevSrSouza
|
||||
|
||||
Thanks DevSrSouza for KotlinBukkitAPI
|
||||
*/
|
||||
package me.redtea.kotlinbukkitkit.architecture.lifecycle
|
||||
|
||||
import me.redtea.kotlinbukkitkit.architecture.KotlinPlugin
|
||||
import me.redtea.kotlinbukkitkit.architecture.extensions.WithPlugin
|
||||
|
||||
/**
|
||||
* Class that listen to Lifecycle from a [KotlinPlugin]
|
||||
*/
|
||||
public interface LifecycleListener<T : KotlinPlugin> : PluginLifecycleListener, WithPlugin<T> {
|
||||
|
||||
override fun invoke(event: LifecycleEvent) {
|
||||
when (event) {
|
||||
LifecycleEvent.LOAD -> onPluginLoad()
|
||||
LifecycleEvent.ENABLE -> onPluginEnable()
|
||||
LifecycleEvent.DISABLE -> onPluginDisable()
|
||||
LifecycleEvent.CONFIG_RELOAD -> onConfigReload()
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the Plugin loads (before the World)
|
||||
*/
|
||||
public fun onPluginLoad() {}
|
||||
|
||||
/**
|
||||
* Called when the Plugin enables and is ready to register events, commands and etc...
|
||||
*/
|
||||
public fun onPluginEnable() {}
|
||||
|
||||
/**
|
||||
* Called when the Plugin disable like: Server Stop,
|
||||
* Reload Server or Plugins such Plugman disable the plugin.
|
||||
*/
|
||||
public fun onPluginDisable() {}
|
||||
|
||||
/**
|
||||
* Called when some part of your code calls [KotlinPlugin.reloadConfig]
|
||||
*/
|
||||
public fun onConfigReload() {}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.architecture
|
||||
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
|
||||
AUTHOR: https://github.com/DevSrSouza
|
||||
|
||||
Thanks DevSrSouza for KotlinBukkitAPI
|
||||
*/
|
||||
package me.redtea.kotlinbukkitkit.architecture.lifecycle
|
||||
|
||||
public enum class LifecycleEvent { LOAD, ENABLE, DISABLE, CONFIG_RELOAD, ALL_CONFIG_RELOAD }
|
||||
|
||||
public typealias PluginLifecycleListener = (LifecycleEvent) -> Unit
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.architecture
|
||||
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
|
||||
AUTHOR: https://github.com/DevSrSouza
|
||||
|
||||
Thanks DevSrSouza for KotlinBukkitAPI
|
||||
*/
|
||||
package me.redtea.kotlinbukkitkit.architecture.lifecycle
|
||||
|
||||
import me.redtea.kotlinbukkitkit.architecture.KotlinPlugin
|
||||
|
||||
public inline fun <reified T : PluginLifecycleListener> KotlinPlugin.getOrInsertGenericLifecycle(
|
||||
priority: Int,
|
||||
factory: () -> T,
|
||||
): T {
|
||||
return lifecycleListeners
|
||||
.map { it.listener }
|
||||
.filterIsInstance<T>()
|
||||
.firstOrNull()
|
||||
?: factory().also { registerKotlinPluginLifecycle(priority, it) }
|
||||
}
|
||||
Reference in new issue
Block a user