Skip to content

feat: Display error frame when specific hardware is not available.#51

Merged
clansty merged 7 commits intoMuNET-OSS:mainfrom
AdemJensen:hardware_check
Sep 15, 2025
Merged

feat: Display error frame when specific hardware is not available.#51
clansty merged 7 commits intoMuNET-OSS:mainfrom
AdemJensen:hardware_check

Conversation

@AdemJensen
Copy link
Copy Markdown
Contributor

@AdemJensen AdemJensen commented Sep 1, 2025

Before

Currently, when any hardware is unavailable, the system only displays a "BAD" status in the list, and the message quickly disappears.

After (with this MR)

This merge request introduces a custom hardware check that halts the startup process if a hardware error is detected.
Users can configure which hardware components should be monitored, ensuring the system does not proceed until the specified devices are available and functioning correctly.

Additionally, the ErrorFrame implementation adopts the built-in startup error window style of the system, closely replicating the way arcade machines display errors during the boot process.

image

Sourcery 总结

引入一个 HardwareAlert 模块和辅助的 ErrorFrame 助手,用于在启动时监控指定的硬件组件,在出现故障时阻止初始化,并显示一个带有自定义代码和消息的样式化错误窗口。

新功能:

  • 添加可配置的硬件检查,在组件缺失或故障时中止启动
  • 在硬件故障时,显示带有自定义代码和消息的详细街机风格错误帧

改进:

  • 在启动补丁管道中注册 ErrorFrame,并与 ErrorMonitor 集成以覆盖错误显示
  • 修补 CameraManager 以动态检测和索引摄像头类型进行监控
Original summary in English

Summary by Sourcery

Introduce a HardwareAlert module and supporting ErrorFrame helper to monitor specified hardware components during startup, block initialization on failures, and present a styled error window with custom codes and messages.

New Features:

  • Add configurable hardware checks that halt startup on missing or failing components
  • Display detailed arcade-style error frames with custom codes and messages on hardware faults

Enhancements:

  • Register ErrorFrame in the startup patch pipeline and integrate with ErrorMonitor to override error display
  • Patch CameraManager to dynamically detect and index camera types for monitoring

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Sep 1, 2025

审阅者指南

此 PR 引入了一个新的 HardwareAlert 模组和一个 ErrorFrame 辅助工具,用于在街机风格的错误窗口中拦截和显示自定义启动错误。HardwareAlert 可通过 YAML 条目完全配置,它通过 Harmony 后缀钩入启动过程,以检测特定的硬件故障(触摸传感器、LED、摄像头),并通过调用 ErrorFrame 停止初始化。ErrorFrame 调度一个 ErrorProcess 并修补内置的 ErrorMonitor 以渲染自定义代码和消息。

硬件错误拦截和错误帧显示的序列图

sequenceDiagram
    participant StartupProcess
    participant HardwareAlert
    participant ErrorFrame
    participant ErrorMonitor
    participant ErrorProcess
    participant GameManager
    StartupProcess->>HardwareAlert: OnUpdate()
    HardwareAlert-->>ErrorFrame: Show(process, errCode, errMsg)
    ErrorFrame->>ErrorFrame: Store custom error info
    ErrorFrame->>ErrorFrame: Show(process)
    ErrorFrame->>ErrorProcess: Add ErrorProcess to manager
    ErrorFrame->>GameManager: Set IsErrorMode = true
    ErrorMonitor->>ErrorFrame: Initialize(errCode, isCustom)
    ErrorFrame-->>ErrorMonitor: Patch to display custom error info
Loading

文件级别变更

变更 详情 文件
引入 ErrorFrame 辅助工具以显示自定义启动错误
  • 实现 Show 重载,用于存储自定义代码、消息和时间戳
  • 调度 ErrorProcess 并释放原始进程以进入错误模式
  • 在 ErrorMonitor.Initialize 上添加 Harmony 后缀以使用自定义值覆盖 UI 字段
AquaMai.Core/Helpers/ErrorFrame.cs
将 ErrorFrame 集成到启动中并配置硬件监控
  • 通过将 ErrorFrame 添加到 CollectWantedPatches 中,在 Startup.Initialize 中注册 ErrorFrame
  • 添加 HardwareAlert 模组,其中包含每个硬件组件的 YAML 可配置开关
  • 修补 CameraManager.CameraInitialize 以映射摄像头索引
  • 修补 StartupProcess.OnUpdate 以检测已配置的硬件故障并使用本地化消息调用 ErrorFrame
  • 添加区域设置解析逻辑和错误消息字典
  • 更新 configSort.yaml 以包含 UX.HardwareAlert
AquaMai.Core/Startup.cs
AquaMai/configSort.yaml
AquaMai.Mods/UX/HardwareAlert.cs

提示和命令

与 Sourcery 交互

  • 触发新审查: 在拉取请求上评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审查评论。
  • 从审查评论生成 GitHub issue: 通过回复 Sourcery 的审查评论,要求它根据评论创建一个 issue。您也可以回复审查评论并带上 @sourcery-ai issue 来创建 issue。
  • 生成拉取请求标题: 随时在拉取请求标题的任意位置写上 @sourcery-ai 即可生成标题。您也可以在拉取请求上评论 @sourcery-ai title 来随时(重新)生成标题。
  • 生成拉取请求摘要: 随时在拉取请求正文的任意位置写上 @sourcery-ai summary 即可在您希望的位置生成 PR 摘要。您也可以在拉取请求上评论 @sourcery-ai summary 来随时(重新)生成摘要。
  • 生成审阅者指南: 在拉取请求上评论 @sourcery-ai guide 来随时(重新)生成审阅者指南。
  • 解决所有 Sourcery 评论: 在拉取请求上评论 @sourcery-ai resolve 来解决所有 Sourcery 评论。如果您已经处理了所有评论并且不想再看到它们,这会很有用。
  • 驳回所有 Sourcery 审查: 在拉取请求上评论 @sourcery-ai dismiss 来驳回所有现有的 Sourcery 审查。如果您想重新开始新的审查,这会特别有用——别忘了评论 @sourcery-ai review 来触发新的审查!

自定义您的体验

访问您的仪表板以:

  • 启用或禁用审查功能,例如 Sourcery 生成的拉取请求摘要、审阅者指南等。
  • 更改审查语言。
  • 添加、删除或编辑自定义审查说明。
  • 调整其他审查设置。

获取帮助

Original review guide in English

Reviewer's Guide

This PR adds a new HardwareAlert mod and an ErrorFrame helper to intercept and display custom startup errors in the arcade-style error window. HardwareAlert is fully configurable via YAML entries, hooks into the startup process with Harmony postfixes to detect specific hardware failures (touch sensors, LEDs, cameras) and halts initialization by invoking ErrorFrame. ErrorFrame schedules an ErrorProcess and patches the built-in ErrorMonitor to render custom codes and messages.

Sequence diagram for hardware error interception and error frame display

sequenceDiagram
    participant StartupProcess
    participant HardwareAlert
    participant ErrorFrame
    participant ErrorMonitor
    participant ErrorProcess
    participant GameManager
    StartupProcess->>HardwareAlert: OnUpdate()
    HardwareAlert-->>ErrorFrame: Show(process, errCode, errMsg)
    ErrorFrame->>ErrorFrame: Store custom error info
    ErrorFrame->>ErrorFrame: Show(process)
    ErrorFrame->>ErrorProcess: Add ErrorProcess to manager
    ErrorFrame->>GameManager: Set IsErrorMode = true
    ErrorMonitor->>ErrorFrame: Initialize(errCode, isCustom)
    ErrorFrame-->>ErrorMonitor: Patch to display custom error info
Loading

File-Level Changes

Change Details Files
Introduce ErrorFrame helper to display custom startup errors
  • Implement Show overloads that store custom code, message, and timestamp
  • Schedule ErrorProcess and release the original process to enter error mode
  • Add Harmony postfix on ErrorMonitor.Initialize to override UI fields with custom values
AquaMai.Core/Helpers/ErrorFrame.cs
Integrate ErrorFrame into startup and configure hardware monitoring
  • Register ErrorFrame in Startup.Initialize by adding it to CollectWantedPatches
  • Add HardwareAlert mod with YAML-configurable toggles for each hardware component
  • Patch CameraManager.CameraInitialize to map camera indices
  • Patch StartupProcess.OnUpdate to detect configured hardware failures and call ErrorFrame with localized messages
  • Add locale resolution logic and error message dictionaries
  • Update configSort.yaml to include UX.HardwareAlert
AquaMai.Core/Startup.cs
AquaMai/configSort.yaml
AquaMai.Mods/UX/HardwareAlert.cs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你好 - 我已审阅了你的更改 - 以下是一些反馈:

  • OnPostUpdate 中的硬件检查逻辑是重复的;考虑重构为数据驱动结构,将每个配置条目映射到其错误代码/消息,以减少样板代码。
  • 验证 CameraTypeList 和 _cameraIndex 的集合初始化器是否为有效的 C# 语法(例如,使用 new List { ... } 和 new SortedDictionary<,>()),因为当前的字面量可能无法编译。
  • 检查 CodeReader_1P 和 CodeReader_2P 的错误代码分配(都使用 3101),以确保如果需要,它们是不同的,或者更新注释以反映共享代码。
给 AI 代理的提示
请处理此代码审查中的注释:
## 总体注释
- OnPostUpdate 中的硬件检查逻辑是重复的;考虑重构为数据驱动结构,将每个配置条目映射到其错误代码/消息,以减少样板代码。
- 验证 CameraTypeList 和 _cameraIndex 的集合初始化器是否为有效的 C# 语法(例如,使用 new List<string> { ... } 和 new SortedDictionary<,>()),因为当前的字面量可能无法编译。
- 检查 CodeReader_1P 和 CodeReader_2P 的错误代码分配(都使用 3101),以确保如果需要,它们是不同的,或者更新注释以反映共享代码。

## 单独注释

### 注释 1
<location> `AquaMai.Mods/UX/HardwareAlert.cs:111` </location>
<code_context>
+        // get current startup state
+        var tv = Traverse.Create(__instance);
+        // var state = tv.Field("_state").GetValue<byte>();
+        var statusSubMsg = tv.Field("_statusSubMsg").GetValue<string[]>();
+        
+        // Do another version check, since the AMDaemon error code gets disappeared sometimes...
</code_context>

<issue_to_address>
如果 statusSubMsg 为 null 或元素数量少于预期,则存在潜在风险。

在访问 statusSubMsg 的项目之前,添加检查以确保 statusSubMsg 不为 null 且至少包含四个元素,以防止运行时异常。
</issue_to_address>

### 注释 2
<location> `AquaMai.Mods/UX/HardwareAlert.cs:140` </location>
<code_context>
+            if (PlayerCamera && !CameraManager.IsAvailableCameras[_cameraIndex[CameraTypeEnumInner.Photo]])
</code_context>

<issue_to_address>
如果 _cameraIndex 不包含预期的键,可能会发生 KeyNotFoundException。

如果 _cameraIndex 缺少 CameraTypeEnumInner 值,这将抛出异常。在访问之前使用 TryGetValue 或检查键是否存在。
</issue_to_address>

### 注释 3
<location> `AquaMai.Core/Helpers/ErrorFrame.cs:48` </location>
<code_context>
+            return;
+        }
+        MelonLogger.Msg($"Displaying error frame with custom code {_customErrCode}: {_customErrMsg}");
+        tv.Field("ErrorID").GetValue<TextMeshProUGUI>().text = _customErrCode.ToString().PadLeft(4, '0');
+        tv.Field("ErrorMessage").GetValue<TextMeshProUGUI>().text = _customErrMsg;
+        tv.Field("ErrorDate").GetValue<TextMeshProUGUI>().text = _customErrDate.ToString();
+    }
+    
</code_context>

<issue_to_address>
ErrorDate 格式可能与用户预期不一致。

在将 _customErrDate 转换为字符串时,指定格式字符串或使用不变区域性,以确保日期/时间显示一致。
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
        tv.Field("ErrorDate").GetValue<TextMeshProUGUI>().text = _customErrDate.ToString();
=======
        tv.Field("ErrorDate").GetValue<TextMeshProUGUI>().text = _customErrDate.ToString("yyyy-MM-dd HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
>>>>>>> REPLACE

</suggested_fix>

### 注释 4
<location> `AquaMai.Mods/UX/HardwareAlert.cs:93` </location>
<code_context>
+    
+    [HarmonyPostfix]
+    [HarmonyPatch(typeof(StartupProcess), "OnUpdate")]
+    public static void OnPostUpdate(StartupProcess __instance)
+    {
+        if (AMDaemon.Error.Number > 0)
</code_context>

<issue_to_address>
考虑将重复的硬件检查块重构为使用描述符对象的数据驱动循环。

这是将所有重复的 `if (…) ErrorFrame.Show(…) return;` 块折叠成单个数据驱动循环的一种方法。您可以保留所有标志、代码和消息,但将它们打包成一个小的“条目”类型,然后只需迭代。

```csharp
// 1) Define a small descriptor for each check
private class HardwareCheck
{
  public Func<bool> IsEnabled;
  public Func<StartupProcess, string[], bool> Triggers;
  public int ErrorCode;
  public IReadOnlyDictionary<string,string> Messages;
}

// 2) Build your list of checks once
private static readonly HardwareCheck[] _checks = new[]
{
  // AMDaemon error fallback for 1P touch
  new HardwareCheck {
    IsEnabled = () => TouchSensor_1P,
    Triggers  = (proc,msg) =>
      AMDaemon.Error.Number > 0 &&
      (AMDaemon.Error.Number == 3300 || AMDaemon.Error.Number == 3301),
    ErrorCode = 3300,
    Messages  = FaultTouchSensor1P
  },
  // statusSubMsg sensor checks
  new HardwareCheck {
    IsEnabled = () => TouchSensor_1P,
    Triggers  = (proc,msg) => msg[0] == ConstParameter.TestString_Bad,
    ErrorCode = 3300,
    Messages  = FaultTouchSensor1P
  },
  // ... repeat for TouchSensor_2P, LED_1P, LED_2P
};

// Camera‐based checks (after CameraManager.IsReady)
private static readonly HardwareCheck[] _cameraChecks = new[]
{
  new HardwareCheck {
    IsEnabled = () => PlayerCamera,
    Triggers  = (proc,msg) =>
      !CameraManager.IsAvailableCameras[_cameraIndex[CameraTypeEnumInner.Photo]],
    ErrorCode = 3102,
    Messages  = FaultPlayerCamera
  },
  // ... QR1P, QR2P, Chime
};
```

然后,您的整个 `OnPostUpdate` 简化为:

```csharp
[HarmonyPostfix]
[HarmonyPatch(typeof(StartupProcess), "OnUpdate")]
public static void OnPostUpdate(StartupProcess __instance)
{
  var tv = Traverse.Create(__instance);
  var statusSubMsg = tv.Field("_statusSubMsg").GetValue<string[]>();

  // Try all raw‐sensor & statusSubMsg entries
  foreach (var chk in _checks)
    if (chk.IsEnabled() && chk.Triggers(__instance, statusSubMsg))
    {
      ErrorFrame.Show(__instance, chk.ErrorCode, chk.Messages[GetLocale()]);
      return;
    }

  // Then camera checks
  if (CameraManager.IsReady)
    foreach (var chk in _cameraChecks)
      if (chk.IsEnabled() && chk.Triggers(__instance, statusSubMsg))
      {
        ErrorFrame.Show(__instance, chk.ErrorCode, chk.Messages[GetLocale()]);
        return;
      }
}
```

优点:
- 所有“样板” `if (…) { Show; return }` 都位于单个循环中。
- 添加新的传感器或相机只是数组中的另一个条目。
- 消除了大型单一方法、重度嵌套以及字符串到枚举的转换。
</issue_to_address>

Sourcery 对开源免费 - 如果您喜欢我们的评论,请考虑分享它们 ✨
帮助我更有用!请点击每个评论上的 👍 或 👎,我将使用反馈来改进您的评论。
Original comment in English

Hey there - I've reviewed your changes - here's some feedback:

  • The hardware check logic in OnPostUpdate is repetitive; consider refactoring into a data-driven structure mapping each config entry to its error code/message to reduce boilerplate.
  • Verify the collection initializers for CameraTypeList and _cameraIndex are valid C# syntax (e.g., use new List { ... } and new SortedDictionary<,>()), as the current literals might not compile.
  • Review the error code assignments for CodeReader_1P and CodeReader_2P (both using 3101) to ensure they are distinct if intended or update comments to reflect the shared code.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The hardware check logic in OnPostUpdate is repetitive; consider refactoring into a data-driven structure mapping each config entry to its error code/message to reduce boilerplate.
- Verify the collection initializers for CameraTypeList and _cameraIndex are valid C# syntax (e.g., use new List<string> { ... } and new SortedDictionary<,>()), as the current literals might not compile.
- Review the error code assignments for CodeReader_1P and CodeReader_2P (both using 3101) to ensure they are distinct if intended or update comments to reflect the shared code.

## Individual Comments

### Comment 1
<location> `AquaMai.Mods/UX/HardwareAlert.cs:111` </location>
<code_context>
+        // get current startup state
+        var tv = Traverse.Create(__instance);
+        // var state = tv.Field("_state").GetValue<byte>();
+        var statusSubMsg = tv.Field("_statusSubMsg").GetValue<string[]>();
+        
+        // Do another version check, since the AMDaemon error code gets disappeared sometimes...
</code_context>

<issue_to_address>
Potential risk if statusSubMsg is null or has fewer than expected elements.

Add a check to ensure statusSubMsg is not null and contains at least four elements before accessing its items to prevent runtime exceptions.
</issue_to_address>

### Comment 2
<location> `AquaMai.Mods/UX/HardwareAlert.cs:140` </location>
<code_context>
+            if (PlayerCamera && !CameraManager.IsAvailableCameras[_cameraIndex[CameraTypeEnumInner.Photo]])
</code_context>

<issue_to_address>
Possible KeyNotFoundException if _cameraIndex does not contain expected keys.

If _cameraIndex lacks a CameraTypeEnumInner value, this will throw. Use TryGetValue or check for key existence before accessing.
</issue_to_address>

### Comment 3
<location> `AquaMai.Core/Helpers/ErrorFrame.cs:48` </location>
<code_context>
+            return;
+        }
+        MelonLogger.Msg($"Displaying error frame with custom code {_customErrCode}: {_customErrMsg}");
+        tv.Field("ErrorID").GetValue<TextMeshProUGUI>().text = _customErrCode.ToString().PadLeft(4, '0');
+        tv.Field("ErrorMessage").GetValue<TextMeshProUGUI>().text = _customErrMsg;
+        tv.Field("ErrorDate").GetValue<TextMeshProUGUI>().text = _customErrDate.ToString();
+    }
+    
</code_context>

<issue_to_address>
ErrorDate formatting may be inconsistent with user expectations.

Specify a format string or use invariant culture when converting _customErrDate to a string to ensure consistent date/time display.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
        tv.Field("ErrorDate").GetValue<TextMeshProUGUI>().text = _customErrDate.ToString();
=======
        tv.Field("ErrorDate").GetValue<TextMeshProUGUI>().text = _customErrDate.ToString("yyyy-MM-dd HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
>>>>>>> REPLACE

</suggested_fix>

### Comment 4
<location> `AquaMai.Mods/UX/HardwareAlert.cs:93` </location>
<code_context>
+    
+    [HarmonyPostfix]
+    [HarmonyPatch(typeof(StartupProcess), "OnUpdate")]
+    public static void OnPostUpdate(StartupProcess __instance)
+    {
+        if (AMDaemon.Error.Number > 0)
</code_context>

<issue_to_address>
Consider refactoring the repeated hardware check blocks into a data-driven loop using descriptor objects for each check.

Here’s one way to collapse all of those repeated `if (…) ErrorFrame.Show(…) return;` blocks into a single data‐driven loop.  You keep all your flags, codes and messages, but package them into a small “entry” type and then just iterate.

```csharp
// 1) Define a small descriptor for each check
private class HardwareCheck
{
  public Func<bool> IsEnabled;
  public Func<StartupProcess, string[], bool> Triggers;
  public int ErrorCode;
  public IReadOnlyDictionary<string,string> Messages;
}

// 2) Build your list of checks once
private static readonly HardwareCheck[] _checks = new[]
{
  // AMDaemon error fallback for 1P touch
  new HardwareCheck {
    IsEnabled = () => TouchSensor_1P,
    Triggers  = (proc,msg) =>
      AMDaemon.Error.Number > 0 &&
      (AMDaemon.Error.Number == 3300 || AMDaemon.Error.Number == 3301),
    ErrorCode = 3300,
    Messages  = FaultTouchSensor1P
  },
  // statusSubMsg sensor checks
  new HardwareCheck {
    IsEnabled = () => TouchSensor_1P,
    Triggers  = (proc,msg) => msg[0] == ConstParameter.TestString_Bad,
    ErrorCode = 3300,
    Messages  = FaultTouchSensor1P
  },
  // ... repeat for TouchSensor_2P, LED_1P, LED_2P
};

// Camera‐based checks (after CameraManager.IsReady)
private static readonly HardwareCheck[] _cameraChecks = new[]
{
  new HardwareCheck {
    IsEnabled = () => PlayerCamera,
    Triggers  = (proc,msg) =>
      !CameraManager.IsAvailableCameras[_cameraIndex[CameraTypeEnumInner.Photo]],
    ErrorCode = 3102,
    Messages  = FaultPlayerCamera
  },
  // ... QR1P, QR2P, Chime
};
```

Then your entire `OnPostUpdate` collapses to:

```csharp
[HarmonyPostfix]
[HarmonyPatch(typeof(StartupProcess), "OnUpdate")]
public static void OnPostUpdate(StartupProcess __instance)
{
  var tv = Traverse.Create(__instance);
  var statusSubMsg = tv.Field("_statusSubMsg").GetValue<string[]>();

  // Try all raw‐sensor & statusSubMsg entries
  foreach (var chk in _checks)
    if (chk.IsEnabled() && chk.Triggers(__instance, statusSubMsg))
    {
      ErrorFrame.Show(__instance, chk.ErrorCode, chk.Messages[GetLocale()]);
      return;
    }

  // Then camera checks
  if (CameraManager.IsReady)
    foreach (var chk in _cameraChecks)
      if (chk.IsEnabled() && chk.Triggers(__instance, statusSubMsg))
      {
        ErrorFrame.Show(__instance, chk.ErrorCode, chk.Messages[GetLocale()]);
        return;
      }
}
```

Benefits:
- All your “boilerplate” `if (…) { Show; return }` lives in a single loop.
- Adding a new sensor or camera is just another entry in the array.
- Removes the large monolithic method, heavy nesting, and string‐to‐enum plumbing.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

CollectWantedPatches(wantedPatches, typeof(KeyListener));
CollectWantedPatches(wantedPatches, typeof(Shim));
CollectWantedPatches(wantedPatches, typeof(NetPacketHook));
CollectWantedPatches(wantedPatches, typeof(ErrorFrame));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是不是应该在启用之后才 patch 这个,这个也没有被别的地方调用过

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个是调用的它hdd里内置的error frame,感觉是个比较通用的功能,是不是放在这里当通用组件会好一些?这样比如后面要实现CPU温度监控之类的功能,也可以用这个frame还原街机的效果

@clansty clansty merged commit eef8a67 into MuNET-OSS:main Sep 15, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants