Skip to content

Commit

Permalink
✨ Make ScriptLoader in async
Browse files Browse the repository at this point in the history
✨ Add SuperItemEvent.kt
✨ Add Feature ScheduleTask.kt
  • Loading branch information
way-zer committed Mar 7, 2020
1 parent 9b37f2f commit ef153ad
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 56 deletions.
6 changes: 3 additions & 3 deletions src/main/kotlin/cf/wayzer/SuperItem/Commander.kt
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,11 @@ class Commander : CommandExecutor {
s.sendMessage("§a发现旧实例存在,卸载成功")
}
s.sendMessage("§a开始加载脚本,可能会有所卡顿")
ItemManager.loadFile(file,"")?.let {
ItemManager.loadFile(file,""){
if(it==null)return@loadFile s.sendMessage("§c脚本加载失败,查看后台以了解错误信息")
ItemManager.registerItem(it)
return s.sendMessage("§a脚本加载成功")
s.sendMessage("§a脚本加载成功")
}
return s.sendMessage("§c脚本加载失败,查看后台以了解错误信息")
}

private fun help(s: CommandSender) {
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/cf/wayzer/SuperItem/ConfigManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ object ConfigManager{
}

fun <H : Any> loadForFeature(item: Item, feature: Feature<H>){
if(feature.defaultData is Nothing)return
if(feature.defaultData == null)return
val config = item.config
if(!config.has(feature.name))config.add(feature.name, gson.toJsonTree(feature.defaultData))
feature.data= gson.fromJson(config.get(feature.name),feature.defaultData::class.java)
feature.data= gson.fromJson(config.get(feature.name),feature.defaultData!!::class.java)
map[item]=config
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/cf/wayzer/SuperItem/Feature.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ abstract class Feature<H> where H : Any {
* 绑定的Item
*/
lateinit var item: Item
abstract val defaultData: H
abstract val defaultData: H?
/**
* Feature的配置信息
*/
Expand Down
71 changes: 36 additions & 35 deletions src/main/kotlin/cf/wayzer/SuperItem/ItemManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import cf.wayzer.SuperItem.Main.Companion.main
import cf.wayzer.SuperItem.features.NBT
import cf.wayzer.SuperItem.features.Permission
import cf.wayzer.SuperItem.scripts.ScriptSupporter
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.bukkit.Material
import org.bukkit.event.HandlerList
import org.bukkit.inventory.ItemStack
Expand All @@ -15,8 +17,8 @@ import java.util.logging.Level
object ItemManager {
private val logger = main.logger
private val items = HashMap<String, Item>()
private lateinit var ucl:URLClassLoader
lateinit var rootDir:File
private lateinit var ucl: URLClassLoader
lateinit var rootDir: File

/**
* 从文件夹加载Item
Expand All @@ -29,22 +31,18 @@ object ItemManager {
rootDir.mkdirs()
ucl = URLClassLoader.newInstance(arrayOf(rootDir.toURI().toURL()),
ItemManager::class.java.classLoader)
loadDir(rootDir,"")
loadDir(rootDir, "")
}

private fun loadDir(dir:File,prefix:String){
private fun loadDir(dir: File, prefix: String) {
dir.listFiles()?.forEach { file ->
if(file.isDirectory){
if("lib" != file.name)
loadDir(file,prefix+"."+file.name)
}
else {
try {
val name = file.nameWithoutExtension
val item = loadFile(file,"$prefix.$name".substring(1))
if(item!=null)registerItem0(item)
} catch (e: Exception) {
logger.log(Level.SEVERE, "注册物品失败: ${file.nameWithoutExtension}", e)
if (file.isDirectory) {
if ("lib" != file.name)
loadDir(file, prefix + "." + file.name)
} else {
val name = file.nameWithoutExtension
loadFile(file, "$prefix.$name".substring(1)) {
if (it != null) registerItem0(it)
}
}
}
Expand All @@ -54,23 +52,26 @@ object ItemManager {
* 供插件内部使用
*/
@Throws(Exception::class)
fun loadFile(file: File,className: String):Item?{
var item:Item? = null
if(file.name.endsWith("superitem.kts")){
ScriptSupporter.init(logger)
logger.info("Load Item in async: ${file.name}")
run {
item = ScriptSupporter.load(file)
}
}else if (file.name.endsWith(".class")&&!file.name.contains("$")){
val c = ucl.loadClass(className)
if (c.superclass != Item::class.java) {
logger.warning("非物品Class: ${file.name}")
return null
fun loadFile(file: File, className: String, callBack: (Item?) -> Unit) {
try {
if (file.name.endsWith("superitem.kts")) {
ScriptSupporter.init(logger)
logger.info("Load Item in async: ${file.name}")
GlobalScope.launch {
callBack(ScriptSupporter.load(file))
}
} else if (file.name.endsWith(".class") && !file.name.contains("$")) {
val c = ucl.loadClass(className)
if (c.superclass != Item::class.java) {
logger.warning("非物品Class: ${file.name}")
return callBack(null)
}
return callBack(c.getConstructor().newInstance() as Item)
}
return c.getConstructor().newInstance() as Item
return callBack(null)
} catch (e: Exception) {
logger.log(Level.SEVERE, "注册物品失败: $className", e)
}
return item
}

/**
Expand All @@ -85,8 +86,8 @@ object ItemManager {
* 注册物品,可以从其他插件注册,使用DSL
*/
@Suppress("unused")
fun registerItem(packageName:String,name:String, body: Item.Builder.()->Unit) {
val builder = Item.Builder(packageName,name.toUpperCase())
fun registerItem(packageName: String, name: String, body: Item.Builder.() -> Unit) {
val builder = Item.Builder(packageName, name.toUpperCase())
body(builder)
builder.register()
}
Expand All @@ -108,12 +109,12 @@ object ItemManager {
logger.info("注册物品成功: ${item.name}")
}

fun unregisterItem(item: Item){
items.remove(item.name,item)
fun unregisterItem(item: Item) {
items.remove(item.name, item)
HandlerList.unregisterAll(item)
item.onDisable()
item.features.values.flatten().forEach {
if(it is Feature.OnDisable)
if (it is Feature.OnDisable)
it.onDisable(main)
}
}
Expand Down
39 changes: 39 additions & 0 deletions src/main/kotlin/cf/wayzer/SuperItem/events/SuperItemEvent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package cf.wayzer.SuperItem.events

import cf.wayzer.SuperItem.Main
import org.bukkit.event.Cancellable
import org.bukkit.event.Event
import org.bukkit.event.HandlerList

/**
* Use for script custom event
*/
data class SuperItemEvent(val type:String,private var data:Any) : Event(), Cancellable {
init {
try {
Class.forName(data::class.java.name,false,Main::class.java.classLoader)
}catch (e: Exception){
throw Error("Can only use common Type as data",e)
}
}

@Suppress("UNCHECKED_CAST")
operator fun <T> invoke(): T {
return data as T
}
private var isCancelled = false
override fun getHandlers(): HandlerList {
return handlerList
}

override fun setCancelled(cancel: Boolean) {
isCancelled = cancel
}

override fun isCancelled(): Boolean {
return isCancelled
}
companion object{
val handlerList = HandlerList()
}
}
3 changes: 2 additions & 1 deletion src/main/kotlin/cf/wayzer/SuperItem/features/DataStore.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ interface DataStore<T>{
fun set(o: Metadatable,value: T?)
fun <T> get(o:Metadatable,defaultValue:T):T

class MetaStore<T>(override val defaultData: Nothing) :Feature<Nothing>(),DataStore<T>{
class MetaStore<T>:Feature<Nothing>(),DataStore<T>{
override val defaultData = null
private val key:String
get() = "SIMS_${item.name}"
override fun <T> get(o: Metadatable, defaultValue: T):T {
Expand Down
25 changes: 25 additions & 0 deletions src/main/kotlin/cf/wayzer/SuperItem/features/ScheduleTask.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cf.wayzer.SuperItem.features

import cf.wayzer.SuperItem.Feature
import cf.wayzer.SuperItem.Main
import org.bukkit.scheduler.BukkitRunnable

class ScheduleTask : Feature<Nothing>(),Feature.OnDisable {
private val list = mutableListOf<BukkitRunnable>()
override val defaultData: Nothing? = null
override fun onDisable(main: Main) {
list.forEach { it.cancel() }
}
fun create(autoCancel:Boolean =true,runH: BukkitRunnable.()->Unit):BukkitRunnable{
val runnable = object: BukkitRunnable(){
override fun run(){
cancel()
runH(this)
if(autoCancel&&isCancelled)
list.remove(this)
}
}
if(autoCancel)list.add(runnable)
return runnable
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import kotlin.script.experimental.jvm.updateClasspath
import kotlin.script.experimental.jvm.util.classpathFromClass

object CompilationConfiguration: ScriptCompilationConfiguration({
ide{

}
jvm {
dependenciesFromClassloader(
"kotlin-stdlib",
Expand Down Expand Up @@ -67,7 +70,7 @@ object CompilationConfiguration: ScriptCompilationConfiguration({
dependenciesFromClass(*importClasses.toTypedArray())

if(dependencies.isNotEmpty())
LibraryManager(Paths.get("lib")).apply {
LibraryManager(Paths.get("libs")).apply {
addAliYunMirror()
dependencies.forEach {
require(it)
Expand Down
27 changes: 15 additions & 12 deletions src/main/kotlin/cf/wayzer/SuperItem/scripts/ScriptLoader.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cf.wayzer.SuperItem.scripts

import cf.wayzer.SuperItem.Item
import cf.wayzer.SuperItem.Main
import java.io.File
import java.util.logging.Level
import java.util.logging.Logger
Expand All @@ -20,23 +19,23 @@ import kotlin.script.experimental.jvmhost.createJvmCompilationConfigurationFromT
class ScriptLoader {
lateinit var logger: Logger
private val hostConfiguration by lazy { ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration){
configurationDependencies(JvmDependency(classpathFromClassloader(Main::class.java.classLoader) ?:listOf()))
configurationDependencies(JvmDependency(classpathFromClassloader(ScriptLoader::class.java.classLoader) ?:listOf()))
}}
private val compilationConfiguration by lazy {createJvmCompilationConfigurationFromTemplate<SuperItemScript> (hostConfiguration) }

fun load(file: File):Item?{
suspend fun load(file: File):Item?{
var item:Item?=null
val result = load0(file)
result.onSuccess {
val res = result.valueOrThrow().returnValue
if(res.scriptInstance is Item) {
item = (res.scriptInstance as Item)
result.reports.filterNot { it.severity== ScriptDiagnostic.Severity.DEBUG }.forEachIndexed { index, rep ->
logger.log(Level.WARNING,"##$index##"+rep.message,rep.exception)
logger.log(Level.WARNING,"##$index##"+rep.message+rep.location?.let { "($it)" },rep.exception)
}
return@onSuccess ResultWithDiagnostics.Success(res)
} else {
return@onSuccess ResultWithDiagnostics.Failure(ScriptDiagnostic("非物品Kts: ${file.name}"))
return@onSuccess ResultWithDiagnostics.Failure(ScriptDiagnostic("非物品Kts: ${file.name}: ${res.scriptInstance}"))
}
}.onFailure {
logger.warning("物品Kts加载失败: ")
Expand All @@ -47,12 +46,16 @@ class ScriptLoader {
return item
}

private fun load0(f: File):ResultWithDiagnostics<EvaluationResult>{
return BasicJvmScriptingHost(hostConfiguration).eval(f.toScriptSource(),compilationConfiguration, ScriptEvaluationConfiguration {
jvm {
baseClassLoader(ScriptLoader::class.java.classLoader)
}
constructorArgs(f.name.split(".")[0].toUpperCase())
})
private val host by lazy {BasicJvmScriptingHost(hostConfiguration)}
private suspend fun load0(f: File):ResultWithDiagnostics<EvaluationResult>{
return host.compiler(f.toScriptSource(),compilationConfiguration).onSuccess {script->
host.evaluator(script,ScriptEvaluationConfiguration {
jvm {
baseClassLoader(ScriptLoader::class.java.classLoader)
enableScriptsInstancesSharing()
}
constructorArgs(f.name.split(".")[0].toUpperCase())
})
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ object ScriptSupporter {
inited =true
}

fun load(file: File): Item?{
suspend fun load(file: File): Item?{
if(!inited)throw IllegalStateException("Must init first!!")
return loader.load(file)
}
Expand Down

0 comments on commit ef153ad

Please sign in to comment.