mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-10 18:40:15 +08:00
Fix Settings
This commit is contained in:
parent
b00b3d97f0
commit
c13076eea0
@ -24,6 +24,7 @@ import net.mamoe.mirai.utils.MiraiLogger
|
||||
import java.io.File
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.annotation.AnnotationTarget.*
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
|
||||
/**
|
||||
@ -44,6 +45,11 @@ public annotation class ConsoleFrontEndImplementation
|
||||
*/
|
||||
@ConsoleFrontEndImplementation
|
||||
public interface MiraiConsoleImplementation : CoroutineScope {
|
||||
/**
|
||||
* [MiraiConsole] 的 [CoroutineScope.coroutineContext]
|
||||
*/
|
||||
public override val coroutineContext: CoroutineContext
|
||||
|
||||
/**
|
||||
* Console 运行路径
|
||||
*/
|
||||
|
@ -107,7 +107,7 @@ public object BuiltInCommands {
|
||||
private val closingLock = Mutex()
|
||||
|
||||
@Handler
|
||||
public suspend fun CommandSender.handle(): Unit {
|
||||
public suspend fun CommandSender.handle() {
|
||||
closingLock.withLock {
|
||||
sendMessage("Stopping mirai-console")
|
||||
kotlin.runCatching {
|
||||
|
@ -13,6 +13,6 @@ import java.util.*
|
||||
|
||||
internal object MiraiConsoleBuildConstants { // auto-filled on build (task :mirai-console:fillBuildConstants)
|
||||
@JvmStatic
|
||||
val buildDate: Date = Date(1596350800177L) // 2020-08-02 14:46:40
|
||||
const val version: String = "1.0-M1"
|
||||
val buildDate: Date = Date(1597935352287L) // 2020-08-20 22:55:52
|
||||
const val version: String = "1.0-M2-1"
|
||||
}
|
||||
|
@ -24,15 +24,20 @@ import kotlin.reflect.full.*
|
||||
|
||||
internal object CompositeCommandSubCommandAnnotationResolver :
|
||||
AbstractReflectionCommand.SubCommandAnnotationResolver {
|
||||
override fun hasAnnotation(function: KFunction<*>) = function.hasAnnotation<CompositeCommand.SubCommand>()
|
||||
override fun getSubCommandNames(function: KFunction<*>): Array<out String> =
|
||||
override fun hasAnnotation(baseCommand: AbstractReflectionCommand, function: KFunction<*>) =
|
||||
function.hasAnnotation<CompositeCommand.SubCommand>()
|
||||
|
||||
override fun getSubCommandNames(baseCommand: AbstractReflectionCommand, function: KFunction<*>): Array<out String> =
|
||||
function.findAnnotation<CompositeCommand.SubCommand>()!!.value
|
||||
}
|
||||
|
||||
internal object SimpleCommandSubCommandAnnotationResolver :
|
||||
AbstractReflectionCommand.SubCommandAnnotationResolver {
|
||||
override fun hasAnnotation(function: KFunction<*>) = function.hasAnnotation<SimpleCommand.Handler>()
|
||||
override fun getSubCommandNames(function: KFunction<*>): Array<out String> = arrayOf("")
|
||||
override fun hasAnnotation(baseCommand: AbstractReflectionCommand, function: KFunction<*>) =
|
||||
function.hasAnnotation<SimpleCommand.Handler>()
|
||||
|
||||
override fun getSubCommandNames(baseCommand: AbstractReflectionCommand, function: KFunction<*>): Array<out String> =
|
||||
baseCommand.names
|
||||
}
|
||||
|
||||
internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
|
||||
@ -74,12 +79,12 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
interface SubCommandAnnotationResolver {
|
||||
fun hasAnnotation(function: KFunction<*>): Boolean
|
||||
fun getSubCommandNames(function: KFunction<*>): Array<out String>
|
||||
fun hasAnnotation(baseCommand: AbstractReflectionCommand, function: KFunction<*>): Boolean
|
||||
fun getSubCommandNames(baseCommand: AbstractReflectionCommand, function: KFunction<*>): Array<out String>
|
||||
}
|
||||
|
||||
internal val subCommands: Array<SubCommandDescriptor> by lazy {
|
||||
this::class.declaredFunctions.filter { subCommandAnnotationResolver.hasAnnotation(it) }
|
||||
this::class.declaredFunctions.filter { subCommandAnnotationResolver.hasAnnotation(this, it) }
|
||||
.also { subCommandFunctions ->
|
||||
// overloading not yet supported
|
||||
val overloadFunction = subCommandFunctions.groupBy { it.name }.entries.firstOrNull { it.value.size > 1 }
|
||||
@ -278,7 +283,7 @@ internal fun AbstractReflectionCommand.createSubCommand(
|
||||
}
|
||||
|
||||
val commandName =
|
||||
subCommandAnnotationResolver.getSubCommandNames(function)
|
||||
subCommandAnnotationResolver.getSubCommandNames(this, function)
|
||||
.let { namesFromAnnotation ->
|
||||
if (namesFromAnnotation.isNotEmpty()) {
|
||||
namesFromAnnotation
|
||||
|
@ -11,10 +11,7 @@ package net.mamoe.mirai.console.internal.plugin
|
||||
|
||||
import kotlinx.atomicfu.AtomicLong
|
||||
import kotlinx.atomicfu.locks.withLock
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.*
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.plugin.Plugin
|
||||
import net.mamoe.mirai.console.plugin.PluginManager
|
||||
@ -69,6 +66,7 @@ internal abstract class JvmPluginInternal(
|
||||
internal fun internalOnDisable() {
|
||||
firstRun = false
|
||||
this.onDisable()
|
||||
this.cancel(CancellationException("plugin disabled"))
|
||||
}
|
||||
|
||||
internal fun internalOnLoad() {
|
||||
|
@ -12,6 +12,8 @@
|
||||
package net.mamoe.mirai.console.internal.plugin
|
||||
|
||||
import kotlinx.atomicfu.locks.withLock
|
||||
import kotlinx.coroutines.InternalCoroutinesApi
|
||||
import kotlinx.coroutines.Job
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.internal.setting.cast
|
||||
import net.mamoe.mirai.console.plugin.*
|
||||
@ -54,6 +56,12 @@ internal object PluginManagerImpl : PluginManager {
|
||||
_pluginLoaders.remove(loader)
|
||||
}
|
||||
|
||||
init {
|
||||
@OptIn(InternalCoroutinesApi::class)
|
||||
MiraiConsole.coroutineContext[Job]!!.invokeOnCompletion(true) {
|
||||
plugins.forEach(Plugin::disable)
|
||||
}
|
||||
}
|
||||
|
||||
// region LOADING
|
||||
|
||||
|
@ -10,10 +10,7 @@
|
||||
package net.mamoe.mirai.console.internal.setting
|
||||
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.*
|
||||
import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip
|
||||
import net.mamoe.mirai.console.internal.plugin.updateWhen
|
||||
import net.mamoe.mirai.console.plugin.jvm.loadSetting
|
||||
@ -36,7 +33,10 @@ import kotlin.reflect.full.findAnnotation
|
||||
*
|
||||
* @see loadSetting
|
||||
*/
|
||||
internal open class AutoSaveSetting(private val owner: AutoSaveSettingHolder) :
|
||||
internal open class AutoSaveSetting(
|
||||
private val owner: AutoSaveSettingHolder,
|
||||
internal val originSettingClass: KClass<out Setting>
|
||||
) :
|
||||
AbstractSetting() {
|
||||
private lateinit var storage: SettingStorage
|
||||
|
||||
@ -54,7 +54,8 @@ internal open class AutoSaveSetting(private val owner: AutoSaveSettingHolder) :
|
||||
internal var currentFirstStartTime = atomic(0L)
|
||||
|
||||
init {
|
||||
owner.coroutineContext[Job]?.invokeOnCompletion { doSave() }
|
||||
@OptIn(InternalCoroutinesApi::class)
|
||||
owner.coroutineContext[Job]?.invokeOnCompletion(true) { doSave() }
|
||||
}
|
||||
|
||||
private val updaterBlock: suspend CoroutineScope.() -> Unit = {
|
||||
@ -125,10 +126,12 @@ internal class MemorySettingStorageImpl(
|
||||
internal open class MultiFileSettingStorageImpl(
|
||||
public final override val directory: File
|
||||
) : SettingStorage, MultiFileSettingStorage {
|
||||
init {
|
||||
directory.mkdir()
|
||||
}
|
||||
|
||||
public override fun <T : Setting> load(holder: SettingHolder, settingClass: Class<T>): T =
|
||||
with(settingClass.kotlin) {
|
||||
val file = getSettingFile(holder, this)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val instance = objectInstance ?: this.createInstanceOrNull() ?: kotlin.run {
|
||||
require(settingClass == Setting::class.java) {
|
||||
@ -136,15 +139,20 @@ internal open class MultiFileSettingStorageImpl(
|
||||
"or has a constructor which either has no parameters or all parameters of which are optional"
|
||||
}
|
||||
if (holder is AutoSaveSettingHolder) {
|
||||
AutoSaveSetting(holder) as T?
|
||||
AutoSaveSetting(holder, this) as T?
|
||||
} else null
|
||||
} ?: throw IllegalArgumentException(
|
||||
"Cannot create Setting instance. Make sure 'holder' is a AutoSaveSettingHolder, " +
|
||||
"or 'setting' is an object or has a constructor which either has no parameters or all parameters of which are optional"
|
||||
)
|
||||
|
||||
val file = getSettingFile(holder, this)
|
||||
file.createNewFile()
|
||||
check(file.exists() && file.isFile && file.canRead()) { "${file.absolutePath} cannot be read" }
|
||||
Yaml.default.decodeFromString(instance.updaterSerializer, file.readText())
|
||||
val text = file.readText()
|
||||
if (text.isNotBlank()) {
|
||||
Yaml.default.decodeFromString(instance.updaterSerializer, file.readText())
|
||||
}
|
||||
instance
|
||||
}.also { it.setStorage(this) }
|
||||
|
||||
@ -155,6 +163,7 @@ internal open class MultiFileSettingStorageImpl(
|
||||
if (dir.isFile) {
|
||||
error("Target directory ${dir.path} for holder $holder is occupied by a file therefore setting $qualifiedNameOrTip can't be saved.")
|
||||
}
|
||||
dir.mkdir()
|
||||
|
||||
val file = File(directory, name)
|
||||
if (file.isDirectory) {
|
||||
@ -164,8 +173,9 @@ internal open class MultiFileSettingStorageImpl(
|
||||
}
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
public override fun store(holder: SettingHolder, setting: Setting): Unit = with(setting::class) {
|
||||
val file = getSettingFile(holder, this)
|
||||
public override fun store(holder: SettingHolder, setting: Setting) {
|
||||
val file =
|
||||
getSettingFile(holder, if (setting is AutoSaveSetting) setting.originSettingClass else setting::class)
|
||||
|
||||
if (file.exists() && file.isFile && file.canRead()) {
|
||||
file.writeText(Yaml.default.encodeToString(setting.updaterSerializer, Unit))
|
||||
|
@ -178,10 +178,10 @@ public interface AutoSaveSettingHolder : SettingHolder, CoroutineScope {
|
||||
*/
|
||||
@JvmDefault
|
||||
public override fun <T : Setting> newSettingInstance(type: KType): T {
|
||||
val classifier = type.classifier?.cast<KClass<*>>()?.java
|
||||
require(classifier == Setting::class.java) {
|
||||
val classifier = type.classifier?.cast<KClass<Setting>>()
|
||||
require(classifier != null && classifier.java == Setting::class.java) {
|
||||
"Cannot create Setting instance. AutoSaveSettingHolder supports only Setting type."
|
||||
}
|
||||
return AutoSaveSetting(this) as T // T is always Setting
|
||||
return AutoSaveSetting(this, classifier) as T // T is always Setting
|
||||
}
|
||||
}
|
@ -46,7 +46,7 @@ internal fun startupConsoleThread() {
|
||||
}
|
||||
}
|
||||
|
||||
CoroutineScope(dispatch).launch {
|
||||
CoroutineScope(dispatch + SupervisorJob()).launch {
|
||||
val consoleLogger = DefaultLogger("console")
|
||||
while (isActive) {
|
||||
try {
|
||||
|
@ -48,14 +48,13 @@ class MiraiConsoleImplementationPure
|
||||
@JvmOverloads constructor(
|
||||
override val rootDir: File = File("."),
|
||||
override val builtInPluginLoaders: List<PluginLoader<*, *>> = Collections.unmodifiableList(
|
||||
listOf(
|
||||
DeferredPluginLoader { JarPluginLoader })
|
||||
listOf(DeferredPluginLoader { JarPluginLoader })
|
||||
),
|
||||
override val frontEnd: MiraiConsoleFrontEnd = MiraiConsoleFrontEndPure,
|
||||
override val mainLogger: MiraiLogger = frontEnd.loggerFor("main"),
|
||||
override val consoleCommandSender: ConsoleCommandSender = ConsoleCommandSenderImpl,
|
||||
override val settingStorageForJarPluginLoader: SettingStorage = MultiFileSettingStorage(rootDir),
|
||||
override val settingStorageForBuiltIns: SettingStorage = MultiFileSettingStorage(rootDir)
|
||||
override val settingStorageForJarPluginLoader: SettingStorage = MultiFileSettingStorage(File(rootDir, "data")),
|
||||
override val settingStorageForBuiltIns: SettingStorage = MultiFileSettingStorage(File(rootDir, "data"))
|
||||
) : MiraiConsoleImplementation, CoroutineScope by CoroutineScope(SupervisorJob()) {
|
||||
init {
|
||||
rootDir.mkdir()
|
||||
|
Loading…
Reference in New Issue
Block a user