diff --git a/CHANGELOG.md b/CHANGELOG.md
index fe56aac85..b34647d2d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,10 +2,12 @@
 
 开发版本. 频繁更新, 不保证高稳定性
 
-## `0.13.0` *On the way*
+## `0.13.0` 2020/2/12
 
 ### mirai-core
 1. 修改 BotFactory, 添加 `context` 参数.
+2. currentTimeMillis 减少不必要对象创建
+3. 优化无锁链表性能 (大幅提升 `addAll` 性能)
 
 ### mirai-core-qqanroid
 安卓协议发布, 基于最新 QQ, 版本 `8.2.0`
@@ -14,7 +16,8 @@
 - 消息: 文字消息, 图片消息(含表情消息), 群员 At.
 - 列表: 群列表, 群员列表, 好友列表均已稳定.
 - 群操作: 查看和修改群名, 查看和修改群属性(含全体禁言, 坦白说, 自动批准加入, 匿名聊天, 允许成员拉人), 设置和解除成员禁言, 查看和修改成员名片, 踢出成员.
-- 事件: 接受群消息和好友消息并解析
+- 消息事件: 接受群消息和好友消息并解析
+- 群事件: 群员加入, 群员离开, 禁言和解除禁言, 群属性(含全体禁言, 坦白说, 匿名聊天, 允许成员拉人)改动.
 
 ### mirai-api-http
 HTTP API 已完成, by [@ryoii](https://github.com/ryoii).  
diff --git a/gradle.properties b/gradle.properties
index cce0a8c34..ddf817985 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,7 +1,7 @@
 # style guide
 kotlin.code.style=official
 # config
-mirai_version=0.12.0
+mirai_version=0.13.0
 kotlin.incremental.multiplatform=true
 kotlin.parallel.tasks.in.project=true
 # kotlin
diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
index 78b54628b..9126bc908 100644
--- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
+++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
@@ -47,9 +47,10 @@ import kotlin.time.ExperimentalTime
 internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler() {
     override val bot: QQAndroidBot by bot.unsafeWeakRef()
     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 ->
-        bot.logger.error("Exception in NetworkHandler", throwable)
+        logger.error("Exception in NetworkHandler", throwable)
     }
 
     private lateinit var channel: PlatformSocket
@@ -62,7 +63,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
         channel.connect("113.96.13.208", 8080)
         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()
         mainloop@ while (true) {
             when (response) {
@@ -104,7 +105,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
                 }
 
                 is WtLogin.Login.LoginPacketResponse.Success -> {
-                    bot.logger.info("Login successful")
+                    logger.info("Login successful")
                     break@mainloop
                 }
             }
@@ -118,7 +119,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
     override suspend fun init(): Unit = coroutineScope {
         this@QQAndroidBotNetworkHandler.subscribeAlways<BotOfflineEvent> {
             if (this@QQAndroidBotNetworkHandler.bot == this.bot) {
-                this.bot.logger.error("被挤下线")
+                logger.error("被挤下线")
                 close()
             }
         }
@@ -130,7 +131,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
 
         val friendListJob = launch {
             try {
-                bot.logger.info("开始加载好友信息")
+                logger.info("开始加载好友信息")
                 var currentFriendCount = 0
                 var totalFriendCount: Short
                 while (true) {
@@ -149,21 +150,21 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
                             currentFriendCount++
                         }
                     }
-                    bot.logger.verbose("正在加载好友列表 ${currentFriendCount}/${totalFriendCount}")
+                    logger.verbose("正在加载好友列表 ${currentFriendCount}/${totalFriendCount}")
                     if (currentFriendCount >= totalFriendCount) {
                         break
                     }
                     // delay(200)
                 }
-                bot.logger.info("好友列表加载完成, 共 ${currentFriendCount}个")
+                logger.info("好友列表加载完成, 共 ${currentFriendCount}个")
             } catch (e: Exception) {
-                bot.logger.error("加载好友列表失败|一般这是由于加载过于频繁导致/将以热加载方式加载好友列表")
+                logger.error("加载好友列表失败|一般这是由于加载过于频繁导致/将以热加载方式加载好友列表")
             }
         }
 
         val groupJob = launch {
             try {
-                bot.logger.info("开始加载群组列表与群成员列表")
+                logger.info("开始加载群组列表与群成员列表")
                 val troopListData = FriendList.GetTroopListSimplify(bot.client)
                     .sendAndExpect<FriendList.GetTroopListSimplify.Response>(retry = 2)
 
@@ -196,15 +197,15 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
                                 )
                             )
                         } catch (e: Exception) {
-                            bot.logger.error("群${troopNum.groupCode}的列表拉取失败, 一段时间后将会重试")
-                            bot.logger.error(e)
+                            logger.error("群${troopNum.groupCode}的列表拉取失败, 一段时间后将会重试")
+                            logger.error(e)
                         }
                     }
                 }
-                bot.logger.info("群组列表与群成员加载完成, 共 ${troopListData.groups.size}个")
+                logger.info("群组列表与群成员加载完成, 共 ${troopListData.groups.size}个")
             } catch (e: Exception) {
-                bot.logger.error("加载组信息失败|一般这是由于加载过于频繁导致/将以热加载方式加载群列表")
-                bot.logger.error(e)
+                logger.error("加载组信息失败|一般这是由于加载过于频繁导致/将以热加载方式加载群列表")
+                logger.error(e)
             }
         }
 
@@ -317,7 +318,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
             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 {
             when (this) {
@@ -416,13 +417,13 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
                 bot.tryReinitializeNetworkHandler(e)
                 return
             } catch (e: ReadPacketInternalException) {
-                bot.logger.error("Socket channel read failed: ${e.message}")
+                logger.error("Socket channel read failed: ${e.message}")
                 bot.tryReinitializeNetworkHandler(e)
                 return
             } catch (e: CancellationException) {
                 return
             } catch (e: Throwable) {
-                bot.logger.error("Caught unexpected exceptions", e)
+                logger.error("Caught unexpected exceptions", e)
                 bot.tryReinitializeNetworkHandler(e)
                 return
             }
@@ -438,7 +439,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
      * 发送一个包, 但不期待任何返回.
      */
     suspend fun OutgoingPacket.sendWithoutExpect() {
-        bot.logger.info("Send: ${this.commandName}")
+        logger.info("Send: ${this.commandName}")
         withContext(this@QQAndroidBotNetworkHandler.coroutineContext + CoroutineName("Packet sender")) {
             channel.send(delegate)
         }
@@ -461,7 +462,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
                 withContext(this@QQAndroidBotNetworkHandler.coroutineContext + CoroutineName("Packet sender")) {
                     channel.send(delegate)
                 }
-                bot.logger.info("Send: ${this.commandName}")
+                logger.info("Send: ${this.commandName}")
                 return withTimeoutOrNull(timeoutMillis) {
                     @Suppress("UNCHECKED_CAST")
                     handler.await() as E
@@ -480,7 +481,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
                     withContext(this@QQAndroidBotNetworkHandler.coroutineContext + CoroutineName("Packet sender")) {
                         channel.send(data, 0, length)
                     }
-                    bot.logger.info("Send: ${this.commandName}")
+                    logger.info("Send: ${this.commandName}")
                     return withTimeoutOrNull(timeoutMillis) {
                         @Suppress("UNCHECKED_CAST")
                         handler.await() as E
diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.kt
index 3754f973e..0e9cee6be 100644
--- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.kt
+++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/OnlinePush.kt
@@ -132,9 +132,9 @@ internal class OnlinePush {
                             bot.getGroupByUin(groupUin).let { group ->
                                 val member = group[target] as MemberImpl
                                 this.discardExact(1)
-                                return MemberLeaveEvent.Kick(member, group.members[readUInt().toLong()].also {
-                                    group.members.delegate.remove(it)
-                                })
+                                return MemberLeaveEvent.Kick(member.also {
+                                    group.members.delegate.remove(member)
+                                }, group.members[readUInt().toLong()])
                             }
                         }
                     }
@@ -187,14 +187,18 @@ internal class OnlinePush {
                                             )
                                         }
                                     } else {
-                                        if (target == bot.uin) {
-
-                                        }
-                                        val member = group[target]
-                                        if (time == 0) {
-                                            MemberUnmuteEvent(operator = operator, member = member)
+                                        return if (target == bot.uin) {
+                                            if (time == 0) {
+                                                BotUnmuteEvent(operator)
+                                            } else
+                                                BotMuteEvent(durationSeconds = time, operator = operator)
                                         } 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)
+                                            }
                                         }
                                     }
                                 }
diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt
index 8003cc10e..3793b2ceb 100644
--- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt
+++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt
@@ -40,7 +40,7 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
     @UseExperimental(RawAccountIdUse::class)
     override val uin: Long
         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 {
         instances.addLast(this.weakRef())
diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Subscribable.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Subscribable.kt
index 0a8346cf4..3aff7e809 100644
--- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Subscribable.kt
+++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Subscribable.kt
@@ -79,6 +79,12 @@ suspend fun <E : Event> E.broadcast(): E = apply {
     this@broadcast.broadcastInternal() // inline, no extra cost
 }
 
+/**
+ * 设置为 `true` 以关闭事件.
+ * 所有的 `subscribe` 都能正常添加到监听器列表, 但所有的广播都会直接返回.
+ */
+var EventDisabled = false
+
 /**
  * 可控制是否需要广播这个事件包
  */
diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt
index b33e6c205..b1b2722bb 100644
--- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt
+++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/BotEvents.kt
@@ -129,12 +129,27 @@ data class BotGroupPermissionChangeEvent(
  */
 data class BotMuteEvent(
     val durationSeconds: Int,
-    override val group: Group,
     /**
-     * 操作人. 为 null 则为机器人操作
+     * 操作人.
      */
-    val operator: Member?
-) : GroupEvent, Packet, BotPassiveEvent
+    val operator: Member
+) : 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 加入了一个新群
diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/internal/InternalEventListeners.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/internal/InternalEventListeners.kt
index 366ce9d02..2a9f8f3b7 100644
--- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/internal/InternalEventListeners.kt
+++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/internal/InternalEventListeners.kt
@@ -11,22 +11,17 @@ package net.mamoe.mirai.event.internal
 
 import kotlinx.coroutines.*
 import net.mamoe.mirai.event.Event
+import net.mamoe.mirai.event.EventDisabled
 import net.mamoe.mirai.event.Listener
 import net.mamoe.mirai.event.ListeningStatus
-import net.mamoe.mirai.utils.LockFreeLinkedList
-import net.mamoe.mirai.utils.MiraiDebugAPI
-import net.mamoe.mirai.utils.MiraiLogger
+import net.mamoe.mirai.utils.*
 import net.mamoe.mirai.utils.io.logStacktrace
 import kotlin.coroutines.CoroutineContext
 import kotlin.coroutines.coroutineContext
 import kotlin.jvm.JvmField
 import kotlin.reflect.KClass
 
-/**
- * 设置为 `true` 以关闭事件.
- * 所有的 `subscribe` 都能正常添加到监听器列表, 但所有的广播都会直接返回.
- */
-var EventDisabled = false
+val EventLogger: MiraiLoggerWithSwitch = DefaultLogger("Event").withSwitch(false)
 
 @PublishedApi
 internal fun <L : Listener<E>, E : Event> KClass<out E>.subscribeInternal(listener: L): L {
@@ -108,6 +103,8 @@ internal object EventListenerManager {
 internal suspend inline fun Event.broadcastInternal() {
     if (EventDisabled) return
 
+    EventLogger.info { "Event broadcast: $this" }
+
     callAndRemoveIfRequired(this::class.listeners())
 
     var supertypes = this::class.supertypes
diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
index a37550997..c7d286b97 100644
--- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
+++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
@@ -17,6 +17,7 @@ import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
 import net.mamoe.mirai.Bot
 import net.mamoe.mirai.utils.MiraiInternalAPI
+import net.mamoe.mirai.utils.MiraiLogger
 import net.mamoe.mirai.utils.io.PlatformDatagramChannel
 
 /**
@@ -47,6 +48,11 @@ abstract class BotNetworkHandler : CoroutineScope {
      */
     abstract val supervisor: CompletableJob
 
+    /**
+     * logger
+     */
+    abstract val logger: MiraiLogger
+
     /**
      * 依次尝试登录到可用的服务器. 在任一服务器登录完成后返回.
      * 本函数将挂起直到登录成功.
diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt
index 4cb969396..26a532f7c 100644
--- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt
+++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt
@@ -11,6 +11,7 @@ package net.mamoe.mirai.utils
 
 import kotlinx.io.core.IoBuffer
 import net.mamoe.mirai.Bot
+import net.mamoe.mirai.network.BotNetworkHandler
 import kotlin.coroutines.CoroutineContext
 import kotlin.coroutines.EmptyCoroutineContext
 import kotlin.jvm.JvmStatic
@@ -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})") }
     /**
      * 设备信息覆盖
      */
diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt
index 187b2e266..4e15bb879 100644
--- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt
+++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt
@@ -12,14 +12,12 @@
 package net.mamoe.mirai.utils
 
 import io.ktor.client.HttpClient
-import io.ktor.util.date.GMTDate
-import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.io.core.toByteArray
 
 /**
  * 时间戳
  */
-inline val currentTimeMillis: Long get() = GMTDate().timestamp
+expect val currentTimeMillis: Long
 
 inline val currentTimeSeconds: Long get() = currentTimeMillis / 1000
 
diff --git a/settings.gradle b/settings.gradle
index 548c79dc8..ce530da22 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -21,15 +21,19 @@ pluginManagement {
 
 rootProject.name = 'mirai'
 
-def keyProps = new Properties()
-def keyFile = file("local.properties")
-if (keyFile.exists()) keyFile.withInputStream { keyProps.load(it) }
-if (!keyProps.getProperty("sdk.dir", "").isEmpty()) {
-    include(':mirai-demos:mirai-demo-android')
-    project(':mirai-demos:mirai-demo-android').projectDir = file('mirai-demos/mirai-demo-android')
-} else {
-    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")
+try {
+    def keyProps = new Properties()
+    def keyFile = file("local.properties")
+    if (keyFile.exists()) keyFile.withInputStream { keyProps.load(it) }
+    if (!keyProps.getProperty("sdk.dir", "").isEmpty()) {
+        include(':mirai-demos:mirai-demo-android')
+        project(':mirai-demos:mirai-demo-android').projectDir = file('mirai-demos/mirai-demo-android')
+    } else {
+        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')
@@ -47,10 +51,18 @@ include(':mirai-plugins')
 include(':mirai-plugins:image-sender')
 
 def javaVersion = System.getProperty("java.version")
-if (javaVersion.substring(0, javaVersion.indexOf(".")).toInteger() >= 11) {
-    include(':mirai-debug')
-} else {
-    println("当前使用的 JDK 版本为 ${System.getProperty("java.version")}, 最低需要 JDK 11 才能引入模块 `:mirai-debug`")
+def versionPos = javaVersion.indexOf(".")
+if (versionPos==-1) versionPos = javaVersion.indexOf("-")
+if (versionPos==-1){
+    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')