Commit aca459f6 authored by jiahua.liu's avatar jiahua.liu

Merge remote-tracking branch 'origin/master'

parents 55e70bd3 8fcdad65
...@@ -2,10 +2,12 @@ ...@@ -2,10 +2,12 @@
开发版本. 频繁更新, 不保证高稳定性 开发版本. 频繁更新, 不保证高稳定性
## `0.13.0` *On the way* ## `0.13.0` 2020/2/12
### mirai-core ### mirai-core
1. 修改 BotFactory, 添加 `context` 参数. 1. 修改 BotFactory, 添加 `context` 参数.
2. currentTimeMillis 减少不必要对象创建
3. 优化无锁链表性能 (大幅提升 `addAll` 性能)
### mirai-core-qqanroid ### mirai-core-qqanroid
安卓协议发布, 基于最新 QQ, 版本 `8.2.0` 安卓协议发布, 基于最新 QQ, 版本 `8.2.0`
...@@ -14,7 +16,8 @@ ...@@ -14,7 +16,8 @@
- 消息: 文字消息, 图片消息(含表情消息), 群员 At. - 消息: 文字消息, 图片消息(含表情消息), 群员 At.
- 列表: 群列表, 群员列表, 好友列表均已稳定. - 列表: 群列表, 群员列表, 好友列表均已稳定.
- 群操作: 查看和修改群名, 查看和修改群属性(含全体禁言, 坦白说, 自动批准加入, 匿名聊天, 允许成员拉人), 设置和解除成员禁言, 查看和修改成员名片, 踢出成员. - 群操作: 查看和修改群名, 查看和修改群属性(含全体禁言, 坦白说, 自动批准加入, 匿名聊天, 允许成员拉人), 设置和解除成员禁言, 查看和修改成员名片, 踢出成员.
- 事件: 接受群消息和好友消息并解析 - 消息事件: 接受群消息和好友消息并解析
- 群事件: 群员加入, 群员离开, 禁言和解除禁言, 群属性(含全体禁言, 坦白说, 匿名聊天, 允许成员拉人)改动.
### mirai-api-http ### mirai-api-http
HTTP API 已完成, by [@ryoii](https://github.com/ryoii). HTTP API 已完成, by [@ryoii](https://github.com/ryoii).
......
# style guide # style guide
kotlin.code.style=official kotlin.code.style=official
# config # config
mirai_version=0.12.0 mirai_version=0.13.0
kotlin.incremental.multiplatform=true kotlin.incremental.multiplatform=true
kotlin.parallel.tasks.in.project=true kotlin.parallel.tasks.in.project=true
# kotlin # kotlin
......
...@@ -47,9 +47,10 @@ import kotlin.time.ExperimentalTime ...@@ -47,9 +47,10 @@ import kotlin.time.ExperimentalTime
internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler() { internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler() {
override val bot: QQAndroidBot by bot.unsafeWeakRef() override val bot: QQAndroidBot by bot.unsafeWeakRef()
override val supervisor: CompletableJob = SupervisorJob(bot.coroutineContext[Job]) override val supervisor: CompletableJob = SupervisorJob(bot.coroutineContext[Job])
override val logger: MiraiLogger get() = bot.configuration.networkLoggerSupplier(this)
override val coroutineContext: CoroutineContext = bot.coroutineContext + CoroutineExceptionHandler { _, throwable -> override val coroutineContext: CoroutineContext = bot.coroutineContext + CoroutineExceptionHandler { _, throwable ->
bot.logger.error("Exception in NetworkHandler", throwable) logger.error("Exception in NetworkHandler", throwable)
} }
private lateinit var channel: PlatformSocket private lateinit var channel: PlatformSocket
...@@ -62,7 +63,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -62,7 +63,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
channel.connect("113.96.13.208", 8080) channel.connect("113.96.13.208", 8080)
this.launch(CoroutineName("Incoming Packet Receiver")) { processReceive() } this.launch(CoroutineName("Incoming Packet Receiver")) { processReceive() }
// bot.logger.info("Trying login") // logger.info("Trying login")
var response: WtLogin.Login.LoginPacketResponse = WtLogin.Login.SubCommand9(bot.client).sendAndExpect() var response: WtLogin.Login.LoginPacketResponse = WtLogin.Login.SubCommand9(bot.client).sendAndExpect()
mainloop@ while (true) { mainloop@ while (true) {
when (response) { when (response) {
...@@ -104,7 +105,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -104,7 +105,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
} }
is WtLogin.Login.LoginPacketResponse.Success -> { is WtLogin.Login.LoginPacketResponse.Success -> {
bot.logger.info("Login successful") logger.info("Login successful")
break@mainloop break@mainloop
} }
} }
...@@ -118,7 +119,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -118,7 +119,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
override suspend fun init(): Unit = coroutineScope { override suspend fun init(): Unit = coroutineScope {
this@QQAndroidBotNetworkHandler.subscribeAlways<BotOfflineEvent> { this@QQAndroidBotNetworkHandler.subscribeAlways<BotOfflineEvent> {
if (this@QQAndroidBotNetworkHandler.bot == this.bot) { if (this@QQAndroidBotNetworkHandler.bot == this.bot) {
this.bot.logger.error("被挤下线") logger.error("被挤下线")
close() close()
} }
} }
...@@ -130,7 +131,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -130,7 +131,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
val friendListJob = launch { val friendListJob = launch {
try { try {
bot.logger.info("开始加载好友信息") logger.info("开始加载好友信息")
var currentFriendCount = 0 var currentFriendCount = 0
var totalFriendCount: Short var totalFriendCount: Short
while (true) { while (true) {
...@@ -149,21 +150,21 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -149,21 +150,21 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
currentFriendCount++ currentFriendCount++
} }
} }
bot.logger.verbose("正在加载好友列表 ${currentFriendCount}/${totalFriendCount}") logger.verbose("正在加载好友列表 ${currentFriendCount}/${totalFriendCount}")
if (currentFriendCount >= totalFriendCount) { if (currentFriendCount >= totalFriendCount) {
break break
} }
// delay(200) // delay(200)
} }
bot.logger.info("好友列表加载完成, 共 ${currentFriendCount}个") logger.info("好友列表加载完成, 共 ${currentFriendCount}个")
} catch (e: Exception) { } catch (e: Exception) {
bot.logger.error("加载好友列表失败|一般这是由于加载过于频繁导致/将以热加载方式加载好友列表") logger.error("加载好友列表失败|一般这是由于加载过于频繁导致/将以热加载方式加载好友列表")
} }
} }
val groupJob = launch { val groupJob = launch {
try { try {
bot.logger.info("开始加载群组列表与群成员列表") logger.info("开始加载群组列表与群成员列表")
val troopListData = FriendList.GetTroopListSimplify(bot.client) val troopListData = FriendList.GetTroopListSimplify(bot.client)
.sendAndExpect<FriendList.GetTroopListSimplify.Response>(retry = 2) .sendAndExpect<FriendList.GetTroopListSimplify.Response>(retry = 2)
...@@ -196,15 +197,15 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -196,15 +197,15 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
) )
) )
} catch (e: Exception) { } catch (e: Exception) {
bot.logger.error("群${troopNum.groupCode}的列表拉取失败, 一段时间后将会重试") logger.error("群${troopNum.groupCode}的列表拉取失败, 一段时间后将会重试")
bot.logger.error(e) logger.error(e)
} }
} }
} }
bot.logger.info("群组列表与群成员加载完成, 共 ${troopListData.groups.size}个") logger.info("群组列表与群成员加载完成, 共 ${troopListData.groups.size}个")
} catch (e: Exception) { } catch (e: Exception) {
bot.logger.error("加载组信息失败|一般这是由于加载过于频繁导致/将以热加载方式加载群列表") logger.error("加载组信息失败|一般这是由于加载过于频繁导致/将以热加载方式加载群列表")
bot.logger.error(e) logger.error(e)
} }
} }
...@@ -317,7 +318,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -317,7 +318,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
if (packet is CancellableEvent && packet.isCancelled) return if (packet is CancellableEvent && packet.isCancelled) return
} }
bot.logger.info("Received: ${packet.toString().replace("\n", """\n""").replace("\r", "")}") logger.info("Received: ${packet.toString().replace("\n", """\n""").replace("\r", "")}")
packetFactory?.run { packetFactory?.run {
when (this) { when (this) {
...@@ -416,13 +417,13 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -416,13 +417,13 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
bot.tryReinitializeNetworkHandler(e) bot.tryReinitializeNetworkHandler(e)
return return
} catch (e: ReadPacketInternalException) { } catch (e: ReadPacketInternalException) {
bot.logger.error("Socket channel read failed: ${e.message}") logger.error("Socket channel read failed: ${e.message}")
bot.tryReinitializeNetworkHandler(e) bot.tryReinitializeNetworkHandler(e)
return return
} catch (e: CancellationException) { } catch (e: CancellationException) {
return return
} catch (e: Throwable) { } catch (e: Throwable) {
bot.logger.error("Caught unexpected exceptions", e) logger.error("Caught unexpected exceptions", e)
bot.tryReinitializeNetworkHandler(e) bot.tryReinitializeNetworkHandler(e)
return return
} }
...@@ -438,7 +439,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -438,7 +439,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
* 发送一个包, 但不期待任何返回. * 发送一个包, 但不期待任何返回.
*/ */
suspend fun OutgoingPacket.sendWithoutExpect() { suspend fun OutgoingPacket.sendWithoutExpect() {
bot.logger.info("Send: ${this.commandName}") logger.info("Send: ${this.commandName}")
withContext(this@QQAndroidBotNetworkHandler.coroutineContext + CoroutineName("Packet sender")) { withContext(this@QQAndroidBotNetworkHandler.coroutineContext + CoroutineName("Packet sender")) {
channel.send(delegate) channel.send(delegate)
} }
...@@ -461,7 +462,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -461,7 +462,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
withContext(this@QQAndroidBotNetworkHandler.coroutineContext + CoroutineName("Packet sender")) { withContext(this@QQAndroidBotNetworkHandler.coroutineContext + CoroutineName("Packet sender")) {
channel.send(delegate) channel.send(delegate)
} }
bot.logger.info("Send: ${this.commandName}") logger.info("Send: ${this.commandName}")
return withTimeoutOrNull(timeoutMillis) { return withTimeoutOrNull(timeoutMillis) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
handler.await() as E handler.await() as E
...@@ -480,7 +481,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -480,7 +481,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
withContext(this@QQAndroidBotNetworkHandler.coroutineContext + CoroutineName("Packet sender")) { withContext(this@QQAndroidBotNetworkHandler.coroutineContext + CoroutineName("Packet sender")) {
channel.send(data, 0, length) channel.send(data, 0, length)
} }
bot.logger.info("Send: ${this.commandName}") logger.info("Send: ${this.commandName}")
return withTimeoutOrNull(timeoutMillis) { return withTimeoutOrNull(timeoutMillis) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
handler.await() as E handler.await() as E
......
...@@ -132,9 +132,9 @@ internal class OnlinePush { ...@@ -132,9 +132,9 @@ internal class OnlinePush {
bot.getGroupByUin(groupUin).let { group -> bot.getGroupByUin(groupUin).let { group ->
val member = group[target] as MemberImpl val member = group[target] as MemberImpl
this.discardExact(1) this.discardExact(1)
return MemberLeaveEvent.Kick(member, group.members[readUInt().toLong()].also { return MemberLeaveEvent.Kick(member.also {
group.members.delegate.remove(it) group.members.delegate.remove(member)
}) }, group.members[readUInt().toLong()])
} }
} }
} }
...@@ -187,14 +187,18 @@ internal class OnlinePush { ...@@ -187,14 +187,18 @@ internal class OnlinePush {
) )
} }
} else { } else {
if (target == bot.uin) { return if (target == bot.uin) {
if (time == 0) {
} BotUnmuteEvent(operator)
val member = group[target] } else
if (time == 0) { BotMuteEvent(durationSeconds = time, operator = operator)
MemberUnmuteEvent(operator = operator, member = member)
} else { } else {
MemberMuteEvent(operator = operator, member = member, durationSeconds = time) val member = group[target]
if (time == 0) {
MemberUnmuteEvent(operator = operator, member = member)
} else {
MemberMuteEvent(operator = operator, member = member, durationSeconds = time)
}
} }
} }
} }
......
...@@ -40,7 +40,7 @@ abstract class BotImpl<N : BotNetworkHandler> constructor( ...@@ -40,7 +40,7 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
@UseExperimental(RawAccountIdUse::class) @UseExperimental(RawAccountIdUse::class)
override val uin: Long override val uin: Long
get() = account.id get() = account.id
final override val logger: MiraiLogger by lazy { configuration.logger ?: DefaultLogger("Bot($uin)").also { configuration.logger = it } } final override val logger: MiraiLogger by lazy { configuration.botLoggerSupplier(this) }
init { init {
instances.addLast(this.weakRef()) instances.addLast(this.weakRef())
......
...@@ -79,6 +79,12 @@ suspend fun <E : Event> E.broadcast(): E = apply { ...@@ -79,6 +79,12 @@ suspend fun <E : Event> E.broadcast(): E = apply {
this@broadcast.broadcastInternal() // inline, no extra cost this@broadcast.broadcastInternal() // inline, no extra cost
} }
/**
* 设置为 `true` 以关闭事件.
* 所有的 `subscribe` 都能正常添加到监听器列表, 但所有的广播都会直接返回.
*/
var EventDisabled = false
/** /**
* 可控制是否需要广播这个事件包 * 可控制是否需要广播这个事件包
*/ */
......
...@@ -129,12 +129,27 @@ data class BotGroupPermissionChangeEvent( ...@@ -129,12 +129,27 @@ data class BotGroupPermissionChangeEvent(
*/ */
data class BotMuteEvent( data class BotMuteEvent(
val durationSeconds: Int, val durationSeconds: Int,
override val group: Group,
/** /**
* 操作人. 为 null 则为机器人操作 * 操作人.
*/ */
val operator: Member? val operator: Member
) : GroupEvent, Packet, BotPassiveEvent ) : GroupEvent, Packet, BotPassiveEvent {
override val group: Group
get() = operator.group
}
/**
* Bot 被取消禁言
*/
data class BotUnmuteEvent(
/**
* 操作人.
*/
val operator: Member
) : GroupEvent, Packet, BotPassiveEvent {
override val group: Group
get() = operator.group
}
/** /**
* Bot 加入了一个新群 * Bot 加入了一个新群
......
...@@ -11,22 +11,17 @@ package net.mamoe.mirai.event.internal ...@@ -11,22 +11,17 @@ package net.mamoe.mirai.event.internal
import kotlinx.coroutines.* import kotlinx.coroutines.*
import net.mamoe.mirai.event.Event import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.EventDisabled
import net.mamoe.mirai.event.Listener import net.mamoe.mirai.event.Listener
import net.mamoe.mirai.event.ListeningStatus import net.mamoe.mirai.event.ListeningStatus
import net.mamoe.mirai.utils.LockFreeLinkedList import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.MiraiDebugAPI
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.io.logStacktrace import net.mamoe.mirai.utils.io.logStacktrace
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.coroutineContext import kotlin.coroutines.coroutineContext
import kotlin.jvm.JvmField import kotlin.jvm.JvmField
import kotlin.reflect.KClass import kotlin.reflect.KClass
/** val EventLogger: MiraiLoggerWithSwitch = DefaultLogger("Event").withSwitch(false)
* 设置为 `true` 以关闭事件.
* 所有的 `subscribe` 都能正常添加到监听器列表, 但所有的广播都会直接返回.
*/
var EventDisabled = false
@PublishedApi @PublishedApi
internal fun <L : Listener<E>, E : Event> KClass<out E>.subscribeInternal(listener: L): L { internal fun <L : Listener<E>, E : Event> KClass<out E>.subscribeInternal(listener: L): L {
...@@ -108,6 +103,8 @@ internal object EventListenerManager { ...@@ -108,6 +103,8 @@ internal object EventListenerManager {
internal suspend inline fun Event.broadcastInternal() { internal suspend inline fun Event.broadcastInternal() {
if (EventDisabled) return if (EventDisabled) return
EventLogger.info { "Event broadcast: $this" }
callAndRemoveIfRequired(this::class.listeners()) callAndRemoveIfRequired(this::class.listeners())
var supertypes = this::class.supertypes var supertypes = this::class.supertypes
......
...@@ -17,6 +17,7 @@ import kotlinx.coroutines.CoroutineScope ...@@ -17,6 +17,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.io.PlatformDatagramChannel import net.mamoe.mirai.utils.io.PlatformDatagramChannel
/** /**
...@@ -47,6 +48,11 @@ abstract class BotNetworkHandler : CoroutineScope { ...@@ -47,6 +48,11 @@ abstract class BotNetworkHandler : CoroutineScope {
*/ */
abstract val supervisor: CompletableJob abstract val supervisor: CompletableJob
/**
* logger
*/
abstract val logger: MiraiLogger
/** /**
* 依次尝试登录到可用的服务器. 在任一服务器登录完成后返回. * 依次尝试登录到可用的服务器. 在任一服务器登录完成后返回.
* 本函数将挂起直到登录成功. * 本函数将挂起直到登录成功.
......
...@@ -11,6 +11,7 @@ package net.mamoe.mirai.utils ...@@ -11,6 +11,7 @@ package net.mamoe.mirai.utils
import kotlinx.io.core.IoBuffer import kotlinx.io.core.IoBuffer
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.network.BotNetworkHandler
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.EmptyCoroutineContext
import kotlin.jvm.JvmStatic import kotlin.jvm.JvmStatic
...@@ -38,7 +39,11 @@ class BotConfiguration { ...@@ -38,7 +39,11 @@ class BotConfiguration {
/** /**
* 日志记录器 * 日志记录器
*/ */
var logger: MiraiLogger? = null var botLoggerSupplier: ((Bot) -> MiraiLogger) = { DefaultLogger("Bot(${it.uin})") }
/**
* 网络层日志构造器
*/
var networkLoggerSupplier: ((BotNetworkHandler) -> MiraiLogger) = { DefaultLogger("Network(${it.bot.uin})") }
/** /**
* 设备信息覆盖 * 设备信息覆盖
*/ */
......
...@@ -12,14 +12,12 @@ ...@@ -12,14 +12,12 @@
package net.mamoe.mirai.utils package net.mamoe.mirai.utils
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.util.date.GMTDate
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.io.core.toByteArray import kotlinx.io.core.toByteArray
/** /**
* 时间戳 * 时间戳
*/ */
inline val currentTimeMillis: Long get() = GMTDate().timestamp expect val currentTimeMillis: Long
inline val currentTimeSeconds: Long get() = currentTimeMillis / 1000 inline val currentTimeSeconds: Long get() = currentTimeMillis / 1000
......
...@@ -21,15 +21,19 @@ pluginManagement { ...@@ -21,15 +21,19 @@ pluginManagement {
rootProject.name = 'mirai' rootProject.name = 'mirai'
def keyProps = new Properties() try {
def keyFile = file("local.properties") def keyProps = new Properties()
if (keyFile.exists()) keyFile.withInputStream { keyProps.load(it) } def keyFile = file("local.properties")
if (!keyProps.getProperty("sdk.dir", "").isEmpty()) { if (keyFile.exists()) keyFile.withInputStream { keyProps.load(it) }
include(':mirai-demos:mirai-demo-android') if (!keyProps.getProperty("sdk.dir", "").isEmpty()) {
project(':mirai-demos:mirai-demo-android').projectDir = file('mirai-demos/mirai-demo-android') include(':mirai-demos:mirai-demo-android')
} else { project(':mirai-demos:mirai-demo-android').projectDir = file('mirai-demos/mirai-demo-android')
println("Android SDK 可能未安装. \n将不会加载模块 `mirai-demo-android`, 但这并不影响其他 demo 的加载 ") } else {
println("Android SDK might not be installed. \nModule `mirai-demo-android` will not be included, but other demos will not be influenced") println("Android SDK 可能未安装. \n将不会加载模块 `mirai-demo-android`, 但这并不影响其他 demo 的加载 ")
println("Android SDK might not be installed. \nModule `mirai-demo-android` will not be included, but other demos will not be influenced")
}
} catch (Exception e) {
e.printStackTrace()
} }
include(':mirai-core') include(':mirai-core')
...@@ -47,10 +51,18 @@ include(':mirai-plugins') ...@@ -47,10 +51,18 @@ include(':mirai-plugins')
include(':mirai-plugins:image-sender') include(':mirai-plugins:image-sender')
def javaVersion = System.getProperty("java.version") def javaVersion = System.getProperty("java.version")
if (javaVersion.substring(0, javaVersion.indexOf(".")).toInteger() >= 11) { def versionPos = javaVersion.indexOf(".")
include(':mirai-debug') if (versionPos==-1) versionPos = javaVersion.indexOf("-")
} else { if (versionPos==-1){
println("当前使用的 JDK 版本为 ${System.getProperty("java.version")}, 最低需要 JDK 11 才能引入模块 `:mirai-debug`") println("jdk version unknown")
}else{
def javaVersionNum = javaVersion.substring(0, versionPos).toInteger()
if (javaVersionNum >= 11) {
println("jdk版本为 "+ javaVersionNum)
include(':mirai-debug')
} else {
println("当前使用的 JDK 版本为 ${System.getProperty("java.version")}, 最低需要 JDK 11 才能引入模块 `:mirai-debug`")
}
} }
project(':mirai-demos:mirai-demo-1').projectDir = file('mirai-demos/mirai-demo-1') project(':mirai-demos:mirai-demo-1').projectDir = file('mirai-demos/mirai-demo-1')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment