diff --git a/build.gradle b/build.gradle index 78add32..a03ecf3 100644 --- a/build.gradle +++ b/build.gradle @@ -48,6 +48,8 @@ dependencies{ compile "org.jetbrains.kotlin:kotlin-script-util:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-scripting-jvm-host:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" + implementation "org.mapdb:mapdb:3.0.7" compileOnly "org.spigotmc:spigot-api:$mc_version" compileOnly "net.md-5:bungeecord-chat:$bc_version" diff --git a/src/main/kotlin/cf/wayzer/SuperItem/Commander.kt b/src/main/kotlin/cf/wayzer/SuperItem/Commander.kt index 87fe608..8f773c1 100644 --- a/src/main/kotlin/cf/wayzer/SuperItem/Commander.kt +++ b/src/main/kotlin/cf/wayzer/SuperItem/Commander.kt @@ -143,11 +143,23 @@ class Commander : CommandExecutor { s.sendMessage("§c请输入Path") return } - if (!File(ItemManager.rootDir,args[1]).exists()){ - s.sendMessage("§c请输入Path") - return - } - TODO("From path to get item name") + val file = File(ItemManager.rootDir,args[1]) + if (!file.exists()) + return s.sendMessage("§c请输入Path") + if(file.extension!="kts") + return s.sendMessage("§c只有脚本允许重载") + val name = file.name.removeSuffix(".superitem.kts") + ItemManager.getItem(name)?.let{ + s.sendMessage("§a发现旧实例存在,尝试卸载") + ItemManager.unregisterItem(it) + s.sendMessage("§a发现旧实例存在,卸载成功") + } + s.sendMessage("§a开始加载脚本,可能会有所卡顿") + ItemManager.loadFile(file,"")?.let { + ItemManager.registerItem(it) + return s.sendMessage("§a脚本加载成功") + } + return s.sendMessage("§c脚本加载失败,查看后台以了解错误信息") } private fun help(s: CommandSender) { diff --git a/src/main/kotlin/cf/wayzer/SuperItem/Item.kt b/src/main/kotlin/cf/wayzer/SuperItem/Item.kt index 102713c..50ce690 100644 --- a/src/main/kotlin/cf/wayzer/SuperItem/Item.kt +++ b/src/main/kotlin/cf/wayzer/SuperItem/Item.kt @@ -18,22 +18,38 @@ import java.util.logging.Logger */ abstract class Item : Listener { open class Builder(override val packageName: String,override val name:String):Item(){ + private var disableF = fun(){} + private var enableF = fun(){} override fun loadFeatures() {} + override fun onDisable() { + super.onDisable() + disableF() + } - @Suppress("unused") - inline fun listen(ignoreCancelled:Boolean=false, priority: EventPriority = EventPriority.NORMAL, crossinline handle:(T)->Unit){ - Bukkit.getServer().pluginManager.registerEvent(T::class.java,this,priority, { _, event -> if(event is T)handle(event) },pluginMain,ignoreCancelled) + override fun onEnable() { + super.onEnable() + enableF() } fun register(){ ItemManager.registerItem(this) } + + fun bindDisable(h:()->Unit){ disableF = h } + fun bindEnable(h:()->Unit){ enableF = h } } /** * 获取默认物品 */ abstract fun loadFeatures() + open fun onEnable(){ + enabled = true + } + open fun onDisable(){ + enabled = false + } + var enabled = false val features : MutableMap,MutableList>> = mutableMapOf() open val name: String @@ -45,6 +61,17 @@ abstract class Item : Listener { val logger: Logger get() = Logger.getLogger("SI-$packageName-$name") + fun listen(cls:Class,ignoreCancelled:Boolean=false, priority: EventPriority = EventPriority.NORMAL, handle:(T)->Unit){ + Bukkit.getServer().pluginManager.registerEvent(cls,this,priority, { _, event -> + @Suppress("UNCHECKED_CAST") + if(enabled && cls.isInstance(event))handle(event as T) + },pluginMain,ignoreCancelled) + } + + inline fun listen(ignoreCancelled:Boolean=false, priority: EventPriority = EventPriority.NORMAL, noinline handle:(T)->Unit){ + listen(T::class.java,ignoreCancelled, priority, handle) + } + /** * 安全的获取指定类型的feature diff --git a/src/main/kotlin/cf/wayzer/SuperItem/ItemManager.kt b/src/main/kotlin/cf/wayzer/SuperItem/ItemManager.kt index 2e0eae7..b69d768 100644 --- a/src/main/kotlin/cf/wayzer/SuperItem/ItemManager.kt +++ b/src/main/kotlin/cf/wayzer/SuperItem/ItemManager.kt @@ -5,6 +5,7 @@ import cf.wayzer.SuperItem.features.NBT import cf.wayzer.SuperItem.features.Permission import cf.wayzer.SuperItem.scripts.ScriptSupporter import org.bukkit.Material +import org.bukkit.event.HandlerList import org.bukkit.inventory.ItemStack import java.io.File import java.net.URLClassLoader @@ -101,6 +102,7 @@ object ItemManager { main.server.pluginManager.registerEvents(it.listener, main) } } + item.onEnable() items[item.name] = item main.server.pluginManager.registerEvents(item, main) logger.info("注册物品成功: ${item.name}") @@ -108,6 +110,8 @@ object ItemManager { fun unregisterItem(item: Item){ items.remove(item.name,item) + HandlerList.unregisterAll(item) + item.onDisable() item.features.values.flatten().forEach { if(it is Feature.OnDisable) it.onDisable(main) diff --git a/src/main/kotlin/cf/wayzer/SuperItem/Main.kt b/src/main/kotlin/cf/wayzer/SuperItem/Main.kt index 27ac430..0384b9a 100644 --- a/src/main/kotlin/cf/wayzer/SuperItem/Main.kt +++ b/src/main/kotlin/cf/wayzer/SuperItem/Main.kt @@ -1,5 +1,6 @@ package cf.wayzer.SuperItem +import cf.wayzer.SuperItem.features.DataStore import cf.wayzer.libraryManager.Dependency import cf.wayzer.libraryManager.LibraryManager import org.bukkit.plugin.java.JavaPlugin @@ -20,6 +21,8 @@ class Main : JavaPlugin() { } override fun onDisable() { + DataStore.fileDB.close() + DataStore.memoryDB.close() ItemManager.getItems().toList().forEach(ItemManager::unregisterItem) } @@ -37,6 +40,14 @@ class Main : JavaPlugin() { require(Dependency("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion")) require(Dependency("org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion")) require(Dependency("org.jetbrains:annotations:13.0")) + + require(Dependency("org.mapdb:mapdb:3.0.7")) + require(Dependency("org.eclipse.collections:eclipse-collections:10.1.0")) + require(Dependency("org.eclipse.collections:eclipse-collections-api:10.1.0")) + require(Dependency("org.eclipse.collections:eclipse-collections-forkjoin:10.1.0")) + require(Dependency("com.google.guava:guava:28.1-jre")) + require(Dependency("net.jpountz.lz4:lz4:1.3.0")) + require(Dependency("org.mapdb:elsa:3.0.0-M5")) loadToClassLoader(Main::class.java.classLoader) } } diff --git a/src/main/kotlin/cf/wayzer/SuperItem/features/DataStore.kt b/src/main/kotlin/cf/wayzer/SuperItem/features/DataStore.kt index 9bcf972..a93367e 100644 --- a/src/main/kotlin/cf/wayzer/SuperItem/features/DataStore.kt +++ b/src/main/kotlin/cf/wayzer/SuperItem/features/DataStore.kt @@ -4,6 +4,7 @@ import cf.wayzer.SuperItem.Feature import cf.wayzer.SuperItem.Main import org.bukkit.metadata.FixedMetadataValue import org.bukkit.metadata.Metadatable +import org.mapdb.DBMaker interface DataStore{ fun set(o: Metadatable,value: T?) @@ -23,5 +24,10 @@ interface DataStore{ else o.setMetadata(key,FixedMetadataValue(Main.main,value)) } } + companion object{ + val fileDB = DBMaker.fileDB(Main.main.dataFolder.resolve("data.mapdb")) + .fileMmapEnableIfSupported().transactionEnable().closeOnJvmShutdown().make() + val memoryDB = DBMaker.heapDB().make() + } //TODO other Store: SQL and File } diff --git a/src/main/kotlin/cf/wayzer/SuperItem/features/NBT.kt b/src/main/kotlin/cf/wayzer/SuperItem/features/NBT.kt index c15682b..05ecda4 100644 --- a/src/main/kotlin/cf/wayzer/SuperItem/features/NBT.kt +++ b/src/main/kotlin/cf/wayzer/SuperItem/features/NBT.kt @@ -4,7 +4,6 @@ import cf.wayzer.SuperItem.Feature import cf.wayzer.SuperItem.Main import de.tr7zw.changeme.nbtapi.NBTCompound import de.tr7zw.changeme.nbtapi.NBTItem -import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ReflectionMethod import org.bukkit.inventory.ItemStack import java.util.logging.Level @@ -75,8 +74,7 @@ class NBT(override vararg val defaultData: AttributeModifier) : Feature - val annotations = context.collectedData?.get(ScriptCollectedData.foundAnnotations)?.filter { it.annotationClass== ImportClass::class }?: listOf() - val classes = annotations.map { Class.forName((it as ImportClass).name).kotlin} - val diagnostics = classes.map { ScriptDiagnostic("[Info]PluginDependency: ${it.java.name}",ScriptDiagnostic.Severity.INFO) } - ScriptCompilationConfiguration(context.compilationConfiguration) { - jvm { - dependenciesFromClass(*classes.toTypedArray()) + onAnnotations(ImportClass::class,MavenDepends::class,ImportScript::class) {context-> + val annotations = context.collectedData?.get(ScriptCollectedData.foundAnnotations) + val diagnostics = mutableListOf() + val scriptBaseDir = (context.script as? FileBasedScriptSource)?.file?.parentFile + + val importClasses = mutableListOf>() + val dependencies = mutableListOf() + val importScriptSources = mutableListOf() + + annotations?.forEach { + when(it){ + is ImportClass -> { + try { + Class.forName(it.name).kotlin.also {cls-> + importClasses.add(cls) + diagnostics.add(ScriptDiagnostic("[Info]PluginDependency: ${cls.java.name}",ScriptDiagnostic.Severity.INFO)) + } + }catch (e : ClassNotFoundException){ + diagnostics.add(ScriptDiagnostic("Can't find ImportClass: ${it.name}",ScriptDiagnostic.Severity.FATAL)) + } + } + is MavenDepends -> { + Dependency(it.name,it.repo).also {d-> + dependencies.add(d) + ScriptDiagnostic("[Info]MavenDependency: $d",ScriptDiagnostic.Severity.INFO) + } + } + is ImportScript -> { + importScriptSources.add(FileScriptSource(scriptBaseDir?.resolve(it.path) ?: File(it.path))) + ScriptDiagnostic("[Info]ImportScript: ${it.path}",ScriptDiagnostic.Severity.INFO) + } } - }.asSuccess(diagnostics) - } - onAnnotations(MavenDepends::class){ context-> - val annotations = context.collectedData?.get(ScriptCollectedData.foundAnnotations)?.filter { it.annotationClass== MavenDepends::class }?: listOf() - val dependencies = annotations.map {Dependency((it as MavenDepends).name,it.repo)} - val diagnostics = dependencies.map { ScriptDiagnostic("[Info]MavenDependency: $it",ScriptDiagnostic.Severity.INFO) } + } ScriptCompilationConfiguration(context.compilationConfiguration) { + defaultImports.invoke(*importClasses.toTypedArray()) jvm { + dependenciesFromClass(*importClasses.toTypedArray()) + + if(dependencies.isNotEmpty()) LibraryManager(Paths.get("lib")).apply { addAliYunMirror() dependencies.forEach { @@ -50,6 +76,7 @@ object CompilationConfiguration: ScriptCompilationConfiguration({ updateClasspath(loadFiles()) } } + importScripts.append(importScriptSources) }.asSuccess(diagnostics) } } diff --git a/src/main/kotlin/cf/wayzer/SuperItem/scripts/ImportScript.kt b/src/main/kotlin/cf/wayzer/SuperItem/scripts/ImportScript.kt new file mode 100644 index 0000000..0847231 --- /dev/null +++ b/src/main/kotlin/cf/wayzer/SuperItem/scripts/ImportScript.kt @@ -0,0 +1,8 @@ +package cf.wayzer.SuperItem.scripts + +@Target(AnnotationTarget.FILE) +@Retention(AnnotationRetention.SOURCE) +@Repeatable +annotation class ImportScript ( + val path:String +)