## mirai-core

2.12 带来以下主要更新：

- `EventChannel` 到协程 `Flow` 的对接；
- 消息链性能优化；
- 针对开发易用性的优化；
- 对调试插件的更好支持；
- 大量文档更新；
- 以及一些问题修复。

### 不兼容变更

- 弃用 `EmptyMessageChain`，以 `emptyMessageChain()` 函数替换 (#1997)
  > 因为内部结构有变更，见下文。Java
  可以 `MessageUtils.emptyMessageChain()` 替换。

- `MarketFace.contentToString`
  现在在原本会返回空字符串的情况下会返回 `"[商城表情]"` (#2030 by
  @cssxsh)
  > 原本会返回空字符串是因为服务器提供的表情名称可能为空。

- 修复 `FileMessage` 的序列化名称 (#2041 by @cssxsh)
  > 以前错误地使用了 `Image`，现在改为 `FileMessage`
  。以前序列化的 `FileMessage` 可能会无法反序列化。

- `Image.equals` 现在会比较全部属性
  > 而不是只比较 `imageId`。因为现在图片没有一些详细属性时可能无法发送。

- 弃用 `EventDisabled` 属性 (#1911)
  > 它可以关闭事件功能，但这并不是明智的做法。

- 弃用 `GroupEntranceAnnouncementChangeEvent` (#1873)
  > 这个事件在 2.7 增加 `Announcements` 时就已经无效了。

### 新特性

- 优化 `MessageChain` 实现的性能，现在在大量调用 `Message.plus`
  构造消息链也能获得与 `MessageChainBuilder` 相当的性能。(#1997)
  > 只修改了内部实现，API 及行为都没有变化。
- 优化处理合并转发消息的效率
- 新增 `EventChannel.asFlow` 获得事件通道的 `Flow<...>` (#1911)
  > 协程 `Flow` 很适合承载事件广播功能，拥有更高的通用性和扩展性。（mirai
  未使用是因为在
  mirai `EventChannel` 设计之时 `Flow` 还未稳定）
- 新增 Java 友好的 `EventChannel.exceptionHandler()` (#1953)
- 新增 `BotConfiguration.disableAccountSecretes` 关闭 `account.secrets`
  > account.secrets 保存账号的会话信息。
  它可加速登录过程，也可能可以减少出现验证码的次数。如果遇到一段时间后无法接收消息通知等同步问题时可尝试禁用。

### 优化和修复

#### 消息

- 部分的消息类型的 `toString` 将包含更多属性，涉及：
    - `Image`
      > 现在图片没有一些详细属性时可能无法发送，因此属性也与 imageId
      一样重要。更多的信息将帮助调试。
    - `MessageSource`
    - `QuoteReply`
    - `FileMessage`

- `Image.toString` 现在将包含全部属性

- 重写消息协议层与发送消息流程 (#1997)
  > 可扩展，易于测试，为将来支持频道和模块化等做准备。这不会影响现有的功能。
- 为 `ForwardMessage.BuilderNode` 实现 `toString`

#### 事件

- 优化 `EventChannel` 事件异常处理机制 (#1911)
  > 现在广播方不会收到来自监听方的事件，监听方有全部责任处理自己的异常，未处理的异常会通过默认日志输出。
- 优化 `nextEvent` 和 `syncFromEvent`：
    - 完善文档
    - 在遇到异常时正确停止监听器
- 针对异常处理机制完善事件相关文档：`Event`、`EventChannel`、`Listener`
- 增加事件追踪日志，可由 `-Dmirai.event.trace=true` 启用
  > 这将会在遇到异常时输出注册事件监听器时的 stacktrace，以及记录每一个事件的广播。
- 修复官方 macOS 客户端发送给机器人的图片后缀均为 `.mirai` 的问题 (
  #1111)

#### 其他

- 更新开发文档索引
  > 现在在开发介绍文档中能访问 mirai-console 相关文档，在《准备工作》中也能了解启动
  console 的方式。
- 为 `Bot.close` 的自动登出增加超时

## mirai-console

[指令文档]: https://github.com/mamoe/mirai/blob/dev/mirai-console/docs/Commands.md

### 新特性

- 新增 `CommandContext`，支持在指令中获得原消息链 (#2099)
  > 三种内置指令 `RawCommand`、`SimpleCommand` 和 `CompositeCommand` 的
  Kotlin 以及
  Java 版（`J` 前缀）都支持。参考[文档][指令文档]。
  > 能获得原消息链也就能获得 `MessageMetadata` (#1835)。
- 支持在 `JSimpleCommand` 和 `JCompositeCommand`
  修改 `CommandArgumentContext`
  > 参考[文档][指令文档]。
- 增加 `PluginCustomCommandSender` 可供插件实现 `CommandSender` (#1964)
- 新增 `MiraiConsole.shutdown` 来*优雅*地关闭 Console (#1959, #2016)
    - 修复收到 SIGINT Console 不退出的问题 (#2042)
    - 关闭时有一分钟限时，超时后强制结束
  > *优雅*指的是会禁用插件，依次停止各种服务并保存数据。
- 在加载配置和数据文件失败时自动备份原文件 (#2089 by @cssxsh)
- 当插件加载失败时标记其为加载失败而不关闭 Console (#2022 by @Nambers)
  > 当有插件依赖这个失败的插件时，也会禁用相关插件。
  > 实际上该功能可由前端选择是否开启。mirai 官方的终端前端以及 Mirai
  Android 都会启用该功能。
- 相反于加载顺序卸载插件 (#1994)
  > 若 A 依赖 B，现在会先卸载 A 再卸载 B。

### 优化和修复

#### 插件

- 修复插件无法使用更高版本的 Ktor 等 mirai-core 也使用的依赖的问题 (
  #2051)
  > 现在可以使用 Ktor 2.0
- 修复插件在引用了相同的库时，在某些的情况下会产生冲突的问题 (#2054)
- 修复在插件配置的路径中使用子路径出现的异常的问题 (#2088 by @MrXiaoM)

#### 文档

[指令参数智能解析
]: https://github.com/mamoe/mirai/blob/dev/docs/ConsoleTerminal.md#%E6%8C%87%E4%BB%A4%E5%8F%82%E6%95%B0%E6%99%BA%E8%83%BD%E8%A7%A3%E6%9E%90

[ConsoleTerminal]: https://github.com/mamoe/mirai/blob/dev/docs/ConsoleTerminal.md

- 增加关于使用日志的文档 (#2003)
- 现在 `PluginManager.getPluginDescription` 不再需要插件已被加载 (#2052)
  > 这可能帮助实现 `PluginLoader`。
- 重写[指令文档]
  > 增加大量示例、覆盖更多内容、用语更简单。  
  > 增加关于智能参数解析的文档 ([面向用户][ConsoleTerminal]
  和[面向开发者][指令参数智能解析
  ]的都有) (#1952)
- 优化事件文档
  > 警告在插件中使用 `GlobalEventChannel` 的危险性。
- 优化文档细节 (#2078 by @xtyuns, #2067 by @CauchyDOOM, #2095 by
  @Hugozys)

## mirai-console-gradle

### 新特性

[调试文档]: https://github.com/mamoe/mirai/blob/155e4a6ec4cd7ede2ed5bf6d947fbc9d7f4e1aa6/mirai-console/docs/plugin/JVMPlugin.md#%E8%B0%83%E8%AF%95

- 新增任务 `runConsole` 启动模拟 `Mirai Console` 实例 (#2056, #2058)
  > 解决了在 IDEA 直接运行 RunTerminal 时出现 `NoClassDefError`
  等错误的问题 (#2055)。现在在
  IDEA 新生成的项目可以选择 Mirai 文件夹中的 `Run Mirai Console`
  来启动测试。详见 [文档][调试文档]。

### 优化和修复

- 修复 `shadowLink` 打包的依赖在其他依赖也引用时无效的问题 (#2070)
