diff options
| author | 2026-01-18 12:24:29 +0800 | |
|---|---|---|
| committer | 2026-01-18 12:24:29 +0800 | |
| commit | fd00ac6878b2cee9337b9e92d0c990ecdce9a346 (patch) | |
| tree | bb5540f763dc0061877c9d9ac53747d79193eecc /.github | |
| parent | ad36e0ce82770f9b3509ddb1cf96bc3422969806 (diff) | |
| parent | 6d82ab2275130f3bafdb7ec664297eb700321526 (diff) | |
| download | DropOut-fd00ac6878b2cee9337b9e92d0c990ecdce9a346.tar.gz DropOut-fd00ac6878b2cee9337b9e92d0c990ecdce9a346.zip | |
Merge pull request #58 from HsiangNianian/main
Diffstat (limited to '.github')
| -rw-r--r-- | .github/ISSUE_TEMPLATE/bug_report.yml | 211 | ||||
| -rw-r--r-- | .github/ISSUE_TEMPLATE/cn-bug-report.yml | 211 | ||||
| -rw-r--r-- | .github/ISSUE_TEMPLATE/cn-feature-request.yml | 118 | ||||
| -rw-r--r-- | .github/ISSUE_TEMPLATE/cn-question.yml | 87 | ||||
| -rw-r--r-- | .github/ISSUE_TEMPLATE/config.yml | 11 | ||||
| -rw-r--r-- | .github/ISSUE_TEMPLATE/feature_request.yml | 118 | ||||
| -rw-r--r-- | .github/ISSUE_TEMPLATE/question.yml | 87 | ||||
| -rw-r--r-- | .github/PULL_REQUEST_TEMPLATE/cn-pull_request_template.md | 127 | ||||
| -rw-r--r-- | .github/PULL_REQUEST_TEMPLATE/en-pull_request_template.md | 127 | ||||
| -rw-r--r-- | .github/agents/commit.agent.md | 260 | ||||
| -rw-r--r-- | .github/copilot-instructions.md | 289 | ||||
| -rw-r--r-- | .github/instructions/commit.instructions.md | 38 | ||||
| -rw-r--r-- | .github/references/git/conventional-commit.md | 153 | ||||
| -rw-r--r-- | .github/workflows/check.yml | 4 | ||||
| -rw-r--r-- | .github/workflows/issue-checkbox-checker.yml | 104 | ||||
| -rw-r--r-- | .github/workflows/prek.yml | 60 | ||||
| -rw-r--r-- | .github/workflows/stale.yml | 92 | ||||
| -rw-r--r-- | .github/workflows/test.yml | 72 |
18 files changed, 2165 insertions, 4 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..063bbb7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,211 @@ +name: Bug Report +description: Report a bug or issue with DropOut Minecraft Launcher +title: "[Bug]: " +labels: ["bug", "needs-triage"] +assignees: [] + +body: + - type: markdown + attributes: + value: | + Thank you for taking the time to report a bug! Please fill out the form below to help us understand and fix the issue. + + - type: checkboxes + id: prerequisites + attributes: + label: Prerequisites + description: Please confirm you have completed the following before submitting. Issues that check "I have not read carefully" or fail to meet required items may be closed immediately. + options: + - label: I understand that Issues are for reporting and solving problems, not for comments or complaints. I will provide as much information as possible to help resolve the issue. + required: false + - label: I have not read carefully and just clicked through everything, believing this won't affect issue handling. + required: false + - label: I have filled in a short and clear title so that developers can quickly identify the issue when browsing the Issue list, rather than "a suggestion" or "stuck" etc. + required: false + - label: I have searched existing issues to ensure this is not a duplicate + required: false + - label: I am using the latest version of DropOut + required: false + - label: I have read the README and documentation + required: false + + - type: input + id: version + attributes: + label: DropOut Version + description: What version of DropOut are you using? + placeholder: "e.g., 0.1.23" + validations: + required: true + + - type: dropdown + id: os + attributes: + label: Operating System + description: Which operating system are you using? + options: + - Windows 11 + - Windows 10 + - Windows 8,8.1 + - Windows 7 + - macOS (Apple Silicon) + - macOS (Intel) + - Linux (Debian/Ubuntu) + - Linux (Arch) + - Linux (Fedora/RHEL) + - Other Linux + validations: + required: true + + - type: input + id: os-version + attributes: + label: OS Version + description: Specific version of your operating system + placeholder: "e.g., Windows 11 23H2, macOS 14.2, Ubuntu 22.04" + validations: + required: true + + - type: dropdown + id: minecraft-version + attributes: + label: Minecraft Version + description: Which Minecraft version are you trying to launch? + options: + - "1.21.x" + - "1.20.x" + - "1.19.x" + - "1.18.x" + - "1.17.x" + - "1.16.x" + - "1.12.x" + - Other (specify in description) + validations: + required: true + + - type: dropdown + id: mod-loader + attributes: + label: Mod Loader + description: Are you using a mod loader? + options: + - None (Vanilla) + - Fabric + - Forge + - Not applicable + validations: + required: true + + - type: input + id: java-version + attributes: + label: Java Version + description: Which Java version are you using? + placeholder: "e.g., Java 21.0.1, Java 17.0.9, Java 8u381" + validations: + required: true + + - type: dropdown + id: java-source + attributes: + label: Java Source + description: Where did you get Java from? + options: + - Auto-detected by DropOut + - Downloaded via DropOut + - Manually installed (Oracle) + - Manually installed (Sdkman) + - Manually installed (Homebrew) + - Manually installed (Chocolatey) + - Manually installed (Other) + - Unknown + validations: + required: false + + - type: textarea + id: description + attributes: + label: Bug Description + description: A clear and concise description of what the bug is + placeholder: Describe the issue you're experiencing... + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Steps to Reproduce + description: Steps to reproduce the behavior + placeholder: | + 1. Go to '...' + 2. Click on '...' + 3. Scroll down to '...' + 4. See error + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: What did you expect to happen? + placeholder: Describe what you expected to happen... + validations: + required: true + + - type: textarea + id: actual + attributes: + label: Actual Behavior + description: What actually happened? + placeholder: Describe what actually happened... + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Logs and Error Messages + description: | + Please upload log files from the DropOut launcher terminal, then paste the log link here. + + **How to upload logs:** + 1. Open the terminal in DropOut launcher + 2. Use the built-in log upload feature + 3. Copy the generated log link and paste it below + + If automatic upload is unavailable, you can manually retrieve logs from: + - **macOS**: `$HOME/Library/Application Support/com.dropout.launcher/logs` + - **Linux**: `$HOME/.local/share/com.dropout.launcher` + placeholder: | + Paste log link or log content... + validations: + required: false + + - type: textarea + id: screenshots + attributes: + label: Screenshots or Screen Recordings + description: | + If applicable, add screenshots or screen recordings to help explain your problem. + + **Screenshot Requirements:** + - Use native screenshot tools (Windows: `Win+Shift+S`, macOS: `Cmd+Shift+4`, Linux: `gnome-screenshot`/`spectacle`) + - DO NOT use QQ/WeChat/Discord screenshot tools as they may alter resolution and aspect ratio + - Provide unobstructed original images, avoid window borders or overlays + - For game-related issues, capture the actual game window + - Keep the original resolution and DPI + + You can compress large files before uploading. + placeholder: Drag and drop images here or paste image URLs + validations: + required: false + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Add any other context about the problem here + placeholder: Any additional information that might be helpful... + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/cn-bug-report.yml b/.github/ISSUE_TEMPLATE/cn-bug-report.yml new file mode 100644 index 0000000..a128e28 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/cn-bug-report.yml @@ -0,0 +1,211 @@ +name: Bug 反馈(中文) +description: 报告 DropOut Minecraft 启动器的错误或问题 +title: "[Bug]: " +labels: ["bug", "needs-triage"] +assignees: [] + +body: + - type: markdown + attributes: + value: | + 感谢您花时间报告 Bug!请填写以下表单以帮助我们理解和修复问题。 + + - type: checkboxes + id: prerequisites + attributes: + label: 前置确认 + description: 请确认自己完成了下列项目之后再进行勾选,若未完成必选项或勾选了"我未仔细阅读"选项将视为自愿接受被直接关闭 Issue + options: + - label: 我理解 Issue 是用于反馈和解决问题的,而非吐槽评论区,将尽可能提供更多信息帮助问题解决 + required: false + - label: 我未仔细阅读这些内容,只是一键已读所有内容,并相信这不会影响问题的处理 + required: false + - label: 我填写了简短且清晰明确的标题,以便开发者在翻阅 Issue 列表时能快速确定大致问题,而不是"一个建议"、"卡住了"等 + required: false + - label: 我已搜索现有 Issue,确认这不是重复问题 + required: false + - label: 我正在使用最新版本的 DropOut + required: false + - label: 我已阅读 README 和文档 + required: false + + - type: input + id: version + attributes: + label: DropOut 版本 + description: 您正在使用的 DropOut 版本是? + placeholder: "例如:0.1.23" + validations: + required: true + + - type: dropdown + id: os + attributes: + label: 操作系统 + description: 您使用的操作系统是? + options: + - Windows 11 + - Windows 10 + - Windows 8/8.1 + - Windows 7 + - macOS (Apple Silicon) + - macOS (Intel) + - Linux (Debian/Ubuntu) + - Linux (Arch) + - Linux (Fedora/RHEL) + - 其他 Linux + validations: + required: true + + - type: input + id: os-version + attributes: + label: 操作系统版本 + description: 操作系统的具体版本号 + placeholder: "例如:Windows 11 23H2, macOS 14.2, Ubuntu 22.04" + validations: + required: true + + - type: dropdown + id: minecraft-version + attributes: + label: Minecraft 版本 + description: 您尝试启动的 Minecraft 版本是? + options: + - "1.21.x" + - "1.20.x" + - "1.19.x" + - "1.18.x" + - "1.17.x" + - "1.16.x" + - "1.12.x" + - 其他(请在描述中说明) + validations: + required: true + + - type: dropdown + id: mod-loader + attributes: + label: Mod 加载器 + description: 您是否使用了 Mod 加载器? + options: + - 无(原版) + - Fabric + - Forge + - 不适用 + validations: + required: true + + - type: input + id: java-version + attributes: + label: Java 版本 + description: 您使用的 Java 版本是? + placeholder: "例如:Java 21.0.1, Java 17.0.9, Java 8u381" + validations: + required: true + + - type: dropdown + id: java-source + attributes: + label: Java 来源 + description: 您的 Java 来自哪里? + options: + - DropOut 自动检测 + - 通过 DropOut 下载 + - 手动安装 (Oracle) + - 手动安装 (Sdkman) + - 手动安装 (Homebrew) + - 手动安装 (Chocolatey) + - 手动安装 (其他) + - 未知 + validations: + required: false + + - type: textarea + id: description + attributes: + label: 问题描述 + description: 清晰简洁地描述这个 Bug 是什么 + placeholder: 描述您遇到的问题... + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: 复现步骤 + description: 复现该问题的步骤 + placeholder: | + 1. 打开 '...' + 2. 点击 '...' + 3. 滚动到 '...' + 4. 出现错误 + validations: + required: true + + - type: textarea + id: expected + attributes: + label: 预期行为 + description: 您期望发生什么? + placeholder: 描述您期望发生的事情... + validations: + required: true + + - type: textarea + id: actual + attributes: + label: 实际行为 + description: 实际发生了什么? + placeholder: 描述实际发生的事情... + validations: + required: true + + - type: textarea + id: logs + attributes: + label: 日志和错误信息 + description: | + 请从 DropOut 启动器终端上传日志文件,然后在此粘贴日志链接。 + + **如何上传日志:** + 1. 在 DropOut 启动器中打开终端 + 2. 使用内置的日志上传功能 + 3. 复制生成的日志链接并粘贴到下方 + + 如果无法使用自动上传,可以手动从以下位置获取日志: + - **macOS**: `$HOME/Library/Application Support/com.dropout.launcher/logs` + - **Linux**: `$HOME/.local/share/com.dropout.launcher` + placeholder: | + 粘贴日志链接或日志内容... + validations: + required: false + + - type: textarea + id: screenshots + attributes: + label: 截图或录屏 + description: | + 如果适用,请添加截图或录屏以帮助说明您的问题。 + + **截图要求:** + - 使用系统自带截图工具(Windows: `Win+Shift+S`, macOS: `Cmd+Shift+4`, Linux: `gnome-screenshot`/`spectacle`) + - 不要使用 QQ/微信/Discord 截图工具,它们可能改变分辨率和纵横比 + - 提供无遮挡的原始图片,避免窗口边框或覆盖层 + - 对于游戏问题,请捕获实际游戏窗口 + - 保持原始分辨率和 DPI + + 可以在上传前压缩大文件。 + placeholder: 拖放图片到这里或粘贴图片 URL + validations: + required: false + + - type: textarea + id: additional + attributes: + label: 其他信息 + description: 在此添加关于该问题的任何其他信息 + placeholder: 任何可能有帮助的额外信息... + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/cn-feature-request.yml b/.github/ISSUE_TEMPLATE/cn-feature-request.yml new file mode 100644 index 0000000..366a533 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/cn-feature-request.yml @@ -0,0 +1,118 @@ +name: 功能请求(中文) +description: 为 DropOut 提出新功能或改进建议 +title: "[Feature]: " +labels: ["enhancement", "needs-triage"] +assignees: [] + +body: + - type: markdown + attributes: + value: | + 感谢您提出新功能建议!请填写以下表单以帮助我们理解您的需求。 + + - type: checkboxes + id: prerequisites + attributes: + label: 前置确认 + description: 请确认自己完成了下列项目之后再进行勾选,若勾选了"我未仔细阅读"选项将视为自愿接受被直接关闭 Issue + options: + - label: 我理解 Issue 是用于反馈和解决问题的,而非吐槽评论区,将尽可能提供更多信息 + required: false + - label: 我未仔细阅读这些内容,只是一键已读所有内容,并相信这不会影响问题的处理 + required: false + - label: 我已搜索现有 Issue,确认这不是重复的功能请求 + required: false + - label: 我已查看 README 中的 Roadmap + required: false + - label: 这个功能将使多个用户受益,而不仅仅是我自己 + required: false + + - type: dropdown + id: feature-type + attributes: + label: 功能类型 + description: 您请求的是哪种类型的功能? + options: + - UI/UX 改进 + - 游戏管理 + - Mod 加载器支持 + - 账户管理 + - Java 管理 + - 性能优化 + - 新平台支持 + - 文档 + - 其他 + validations: + required: true + + - type: textarea + id: problem + attributes: + label: 问题陈述 + description: 您的功能请求是否与某个问题相关?请描述。 + placeholder: "我总是对...感到困扰" + validations: + required: true + + - type: textarea + id: solution + attributes: + label: 建议的解决方案 + description: 描述您希望看到的解决方案 + placeholder: 清晰简洁地描述您希望发生的事情... + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: 替代方案 + description: 描述您考虑过的任何替代解决方案或功能 + placeholder: 是否有其他方法可以解决这个问题? + validations: + required: false + + - type: textarea + id: examples + attributes: + label: 示例和参考 + description: | + 提供其他启动器或应用程序实现类似功能的示例 + placeholder: | + - MultiMC 通过...实现 + - Prism Launcher 有类似功能... + - 可以像 [示例链接] 这样工作... + validations: + required: false + + - type: dropdown + id: priority + attributes: + label: 优先级 + description: 这个功能对您有多重要? + options: + - 关键(阻碍正常使用) + - 高(显著改善体验) + - 中(锦上添花) + - 低(小便利) + validations: + required: true + + - type: checkboxes + id: contribution + attributes: + label: 贡献意愿 + description: 您是否愿意为这个功能做出贡献? + options: + - label: 我愿意实现这个功能 + - label: 我愿意帮助测试这个功能 + - label: 我可以提供设计草图或规范 + + - type: textarea + id: additional + attributes: + label: 其他信息 + description: 在此添加关于功能请求的任何其他信息、草图或截图 + placeholder: 任何可能有帮助的额外信息... + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/cn-question.yml b/.github/ISSUE_TEMPLATE/cn-question.yml new file mode 100644 index 0000000..b7422e8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/cn-question.yml @@ -0,0 +1,87 @@ +name: 问题咨询(中文) +description: 询问关于使用 DropOut 的问题 +title: "[Question]: " +labels: ["question"] +assignees: [] + +body: + - type: markdown + attributes: + value: | + 有关于使用 DropOut 的问题吗?请填写以下表单。 + + **注意:** 如果是 Bug 报告,请使用 Bug 反馈模板。 + + - type: checkboxes + id: prerequisites + attributes: + label: 前置确认 + description: 请确认自己完成了下列项目之后再进行勾选,若勾选了"我未仔细阅读"选项将视为自愿接受被直接关闭 Issue + options: + - label: 我理解 Issue 是用于提问和获取帮助的,而非吐槽评论区 + required: false + - label: 我未仔细阅读这些内容,只是一键已读所有内容,并相信这不会影响问题的处理 + required: false + - label: 我已搜索现有 Issue,查看是否有人已经回答了我的问题 + required: false + - label: 我已阅读 README 和文档 + required: false + + - type: dropdown + id: category + attributes: + label: 问题类别 + description: 您的问题是关于什么的? + options: + - 安装和设置 + - 账户和认证 + - Minecraft 版本管理 + - Mod 加载器(Fabric/Forge) + - Java 安装和配置 + - 游戏启动问题 + - 设置和配置 + - 从源代码构建 + - 为项目做贡献 + - 其他 + validations: + required: true + + - type: textarea + id: question + attributes: + label: 您的问题 + description: 请详细描述您的问题 + placeholder: 您想了解什么? + validations: + required: true + + - type: input + id: version + attributes: + label: DropOut 版本(如果适用) + description: 您正在使用的 DropOut 版本是? + placeholder: "例如:0.1.23" + validations: + required: false + + - type: dropdown + id: os + attributes: + label: 操作系统(如果适用) + description: 您使用的操作系统是? + options: + - Windows + - macOS + - Linux + - 不适用 + validations: + required: false + + - type: textarea + id: context + attributes: + label: 其他信息 + description: 添加任何其他可能帮助我们回答您问题的上下文、截图或信息 + placeholder: 任何额外的细节... + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..b2dbc20 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Documentation + url: https://dropout.hydroroll.team + about: Read the project documentation and guides + - name: Discussions + url: https://github.com/HsiangNianian/DropOut/discussions + about: Ask questions and discuss ideas with the community + - name: Releases + url: https://github.com/HsiangNianian/DropOut/releases + about: Download the latest version or view changelog diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..38cb216 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,118 @@ +name: Feature Request +description: Suggest a new feature or enhancement for DropOut +title: "[Feature]: " +labels: ["enhancement", "needs-triage"] +assignees: [] + +body: + - type: markdown + attributes: + value: | + Thank you for suggesting a new feature! Please fill out the form below to help us understand your request. + + - type: checkboxes + id: prerequisites + attributes: + label: Prerequisites + description: Please confirm you have completed the following before submitting. Issues that check "I have not read carefully" may be closed immediately. + options: + - label: I understand that Issues are for feedback and problem-solving, not for complaints. I will provide as much information as possible. + required: false + - label: I have not read carefully and just clicked through everything, believing this won't affect issue handling. + required: false + - label: I have searched existing issues to ensure this is not a duplicate + required: false + - label: I have checked the roadmap in the README + required: false + - label: This feature would benefit multiple users, not just myself + required: false + + - type: dropdown + id: feature-type + attributes: + label: Feature Type + description: What type of feature are you requesting? + options: + - UI/UX Enhancement + - Game Management + - Mod Loader Support + - Account Management + - Java Management + - Performance Improvement + - New Platform Support + - Documentation + - Other + validations: + required: true + + - type: textarea + id: problem + attributes: + label: Problem Statement + description: Is your feature request related to a problem? Please describe. + placeholder: "I'm always frustrated when..." + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Proposed Solution + description: Describe the solution you'd like to see + placeholder: A clear and concise description of what you want to happen... + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternative Solutions + description: Describe any alternative solutions or features you've considered + placeholder: Are there other ways to solve this problem? + validations: + required: false + + - type: textarea + id: examples + attributes: + label: Examples and References + description: | + Provide examples from other launchers or applications that implement similar features + placeholder: | + - MultiMC does this by... + - Prism Launcher has a similar feature... + - This could work like [example link]... + validations: + required: false + + - type: dropdown + id: priority + attributes: + label: Priority + description: How important is this feature to you? + options: + - Critical (blocks normal usage) + - High (significantly improves experience) + - Medium (nice to have) + - Low (minor convenience) + validations: + required: true + + - type: checkboxes + id: contribution + attributes: + label: Contribution + description: Would you be willing to contribute to this feature? + options: + - label: I would be willing to implement this feature + - label: I would be willing to help test this feature + - label: I can provide design mockups or specifications + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Add any other context, mockups, or screenshots about the feature request here + placeholder: Any additional information that might be helpful... + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml new file mode 100644 index 0000000..ac170ab --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -0,0 +1,87 @@ +name: Question +description: Ask a question about using DropOut +title: "[Question]: " +labels: ["question"] +assignees: [] + +body: + - type: markdown + attributes: + value: | + Have a question about using DropOut? Please fill out the form below. + + **Note:** For bug reports, please use the Bug Report template instead. + + - type: checkboxes + id: prerequisites + attributes: + label: Prerequisites + description: Please confirm you have completed the following before submitting. Issues that check "I have not read carefully" may be closed immediately. + options: + - label: I understand that Issues are for asking questions and getting help, not for complaints. + required: false + - label: I have not read carefully and just clicked through everything, believing this won't affect issue handling. + required: false + - label: I have searched existing issues to see if my question has been answered + required: false + - label: I have read the README and documentation + required: false + + - type: dropdown + id: category + attributes: + label: Question Category + description: What is your question about? + options: + - Installation and Setup + - Account and Authentication + - Minecraft Version Management + - Mod Loaders (Fabric/Forge) + - Java Installation and Configuration + - Game Launch Issues + - Settings and Configuration + - Building from Source + - Contributing to the Project + - Other + validations: + required: true + + - type: textarea + id: question + attributes: + label: Your Question + description: Please describe your question in detail + placeholder: What would you like to know? + validations: + required: true + + - type: input + id: version + attributes: + label: DropOut Version (if applicable) + description: What version of DropOut are you using? + placeholder: "e.g., 0.1.23" + validations: + required: false + + - type: dropdown + id: os + attributes: + label: Operating System (if applicable) + description: Which operating system are you using? + options: + - Windows + - macOS + - Linux + - Not applicable + validations: + required: false + + - type: textarea + id: context + attributes: + label: Additional Context + description: Add any other context, screenshots, or information that might help us answer your question + placeholder: Any additional details... + validations: + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE/cn-pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/cn-pull_request_template.md new file mode 100644 index 0000000..abcbaa1 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/cn-pull_request_template.md @@ -0,0 +1,127 @@ +# 描述 + +<!-- 简要描述此 PR 的更改内容 --> + +## 更改类型 + +<!-- 用 "x" 标记相关选项 --> + +- [ ] Bug 修复(修复问题的非破坏性更改) +- [ ] 新功能(添加功能的非破坏性更改) +- [ ] 破坏性更改(会导致现有功能无法正常工作的修复或功能) +- [ ] 文档更新 +- [ ] UI/UX 改进 +- [ ] 性能优化 +- [ ] 代码重构(无功能性更改) +- [ ] 配置更改 +- [ ] 测试添加或更新 + +## LLM 生成代码声明 + +<!-- 如果此 PR 包含 LLM 生成的代码,请在此声明 --> + +- [ ] 此 PR 包含 LLM 生成的代码,我**提供**质量担保 +- [ ] 此 PR 包含 LLM 生成的代码,我**不提供**质量担保 +- [ ] 此 PR 不包含 LLM 生成的代码 + +## 相关 Issue + +<!-- 使用 #issue_number 链接相关 issue --> + +关闭 # +相关 # + +## 更改内容 + +<!-- 详细描述更改内容 --> + +### 后端 (Rust) + +- + +### 前端 (Svelte) + +- + +### 配置 + +- + +## 测试 + +<!-- 描述你运行的测试以及如何复现 --> + +### 测试环境 + +- **操作系统**:<!-- 例如:Windows 11、macOS 14、Ubuntu 22.04 --> +- **DropOut 版本**:<!-- 例如:0.1.23 --> +- **测试的 Minecraft 版本**:<!-- 例如:1.21.1 --> +- **Mod 加载器**:<!-- 例如:Fabric 0.16.0、Forge 49.0.3 或 无 --> + +### 测试用例 + +- [ ] 已在 Windows 上测试 +- [ ] 已在 macOS 上测试 +- [ ] 已在 Linux 上测试 +- [ ] 已测试原版 Minecraft +- [ ] 已测试 Fabric +- [ ] 已测试 Forge +- [ ] 已测试游戏启动 +- [ ] 已测试登录流程 +- [ ] 已测试 Java 检测/下载 + +### 测试步骤 + +1. +2. +3. + +## 检查清单 + +<!-- 用 "x" 标记已完成的项目 --> + +### 代码质量 + +- [ ] 我的代码遵循项目的代码风格指南 +- [ ] 我已对自己的代码进行了自审 +- [ ] 我已对难以理解的区域添加了注释 +- [ ] 我的更改没有产生新的警告或错误 + +### 测试验证 + +- [ ] 我已在本地测试了我的更改 +- [ ] 我已添加测试来证明我的修复有效或功能正常工作 +- [ ] 新的和现有的单元测试在本地通过 +- [ ] 我至少在一个目标平台上进行了测试 + +### 文档更新 + +- [ ] 我已相应地更新了文档 +- [ ] 如有需要,我已更新 README +- [ ] 我已在必要处添加/更新代码注释 + +### 依赖项 + +- [ ] 我已检查没有添加不必要的依赖项 +- [ ] 所有新依赖项都已正确记录 +- [ ] `Cargo.lock` 和/或 `pnpm-lock.yaml` 已更新(如果依赖项有变化) + +## 截图 / 视频 + +<!-- 如适用,添加截图或视频来展示更改 --> + +## 附加说明 + +<!-- 在此添加关于此 PR 的其他上下文 --> + +## 破坏性更改说明 + +<!-- 如果这是破坏性更改,请描述用户的迁移路径 --> + +--- + +**维护者专用:** + +- [ ] 代码审查已完成 +- [ ] CI 检查通过 +- [ ] 准备合并 diff --git a/.github/PULL_REQUEST_TEMPLATE/en-pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/en-pull_request_template.md new file mode 100644 index 0000000..79a8148 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/en-pull_request_template.md @@ -0,0 +1,127 @@ +# Description + +<!-- Provide a brief description of the changes in this PR --> + +## Type of Change + +<!-- Mark the relevant option with an "x" --> + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Documentation update +- [ ] UI/UX improvement +- [ ] Performance improvement +- [ ] Code refactoring (no functional changes) +- [ ] Configuration change +- [ ] Test addition or update + +## LLM-Generated Code Disclosure + +<!-- If this PR contains LLM-generated code, please disclose it here --> + +- [ ] This PR contains LLM-generated code, and I **provide** quality assurance +- [ ] This PR contains LLM-generated code, and I **do not provide** quality assurance +- [ ] This PR does not contain LLM-generated code + +## Related Issues + +<!-- Link to related issues using #issue_number --> + +Closes # +Related to # + +## Changes Made + +<!-- Describe the changes in detail --> + +### Backend (Rust) + +- + +### Frontend (Svelte) + +- + +### Configuration + +- + +## Testing + +<!-- Describe the tests you ran and how to reproduce them --> + +### Test Environment + +- **OS**: <!-- e.g., Windows 11, macOS 14, Ubuntu 22.04 --> +- **DropOut Version**: <!-- e.g., 0.1.23 --> +- **Minecraft Version Tested**: <!-- e.g., 1.21.1 --> +- **Mod Loader**: <!-- e.g., Fabric 0.16.0, Forge 49.0.3, or N/A --> + +### Test Cases + +- [ ] Tested on Windows +- [ ] Tested on macOS +- [ ] Tested on Linux +- [ ] Tested with vanilla Minecraft +- [ ] Tested with Fabric +- [ ] Tested with Forge +- [ ] Tested game launch +- [ ] Tested authentication flow +- [ ] Tested Java detection/download + +### Steps to Test + +1. +2. +3. + +## Checklist + +<!-- Mark completed items with an "x" --> + +### Code Quality + +- [ ] My code follows the project's style guidelines +- [ ] I have performed a self-review of my own code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] My changes generate no new warnings or errors + +### Testing Verification + +- [ ] I have tested my changes locally +- [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] New and existing unit tests pass locally with my changes +- [ ] I have tested on at least one target platform + +### Documentation + +- [ ] I have updated the documentation accordingly +- [ ] I have updated the README if needed +- [ ] I have added/updated code comments where necessary + +### Dependencies + +- [ ] I have checked that no unnecessary dependencies were added +- [ ] All new dependencies are properly documented +- [ ] `Cargo.lock` and/or `pnpm-lock.yaml` are updated (if dependencies changed) + +## Screenshots / Videos + +<!-- If applicable, add screenshots or videos to demonstrate the changes --> + +## Additional Notes + +<!-- Add any other context about the PR here --> + +## Breaking Changes + +<!-- If this is a breaking change, describe the migration path for users --> + +--- + +**For Maintainers:** + +- [ ] Code review completed +- [ ] CI checks passing +- [ ] Ready to merge diff --git a/.github/agents/commit.agent.md b/.github/agents/commit.agent.md new file mode 100644 index 0000000..7187402 --- /dev/null +++ b/.github/agents/commit.agent.md @@ -0,0 +1,260 @@ +# Commit Helper Agent + +You are a Git commit message assistant following the Conventional Commits specification. + +## Task + +Generate well-structured commit messages based on staged changes or user descriptions. + +## Commit Format + +``` +<type>[optional scope]: <description> + +[optional body] + +[optional footer(s)] +``` + +## Workflow Rules + +### Language Policy + +1. **Commit message language**: ALWAYS write in **English** unless user explicitly requests another language +2. **Explanation language**: Use the **same language as user's request** +3. **Translation rule**: If commit language ≠ user's language → provide explanation + - User speaks Chinese + English commit → Explain in Chinese + - User speaks English + Chinese commit → Explain in English + - User speaks English + English commit → No extra explanation needed + - User speaks Chinese + Chinese commit → No extra explanation needed + +### Confirmation Policy + +**ALWAYS ask for confirmation before committing** unless user explicitly says: +- "commit directly" +- "commit immediately" +- "just commit it" + +**Standard flow**: +1. Generate commit message +2. Explain what it means (in user's language if different from English) +3. Show the command: `git commit -m "..."` +4. Ask: "Proceed with this commit?" (in user's language) +5. Only execute if user confirms + +### Step 0: Check Current Branch (REQUIRED) + +**Before doing anything**, check the current branch and validate: + +1. Run `git branch --show-current` to get current branch name +2. Run `git status` to see if there are any changes +3. **Validate branch naming**: + - Feature work → Should be on `feat/*` or `feature/*` branch + - Bug fixes → Should be on `fix/*` or `bugfix/*` branch + - Documentation → Should be on `docs/*` branch + - Refactoring → Should be on `refactor/*` branch + - Hotfix → Should be on `hotfix/*` branch + +4. **Branch validation rules**: + - If on `main` or `master` → WARN: "You're on the main branch. Consider creating a feature branch first." + - If branch name doesn't match change type → WARN: "Current branch is `X`, but changes look like `Y` type. Continue or switch branch?" + - If branch name matches change type → Proceed silently + +**Example warnings**: +``` +On main + adding feature: + "You're on main branch. Consider: git checkout -b feat/your-feature-name" + +On feat/ui-update + fixing bug: + "Current branch is feat/ui-update but changes look like a bug fix. + Consider: git checkout -b fix/bug-name or continue on current branch?" + +On docs/readme + adding code: + "Current branch is docs/readme but changes include code modifications. + Consider switching to feat/* or fix/* branch?" +``` + +If user chooses to continue, proceed to generate commit message as normal. + +### Step 1: Analyze Changes + +When user asks for a commit message: + +1. **If changes are staged**: Run `git diff --cached --stat` to see what files changed +2. **If specific files mentioned**: Run `git diff <file>` to understand the changes +3. **If user describes changes**: Use their description directly + +### Step 2: Determine Type + +| Type | When to Use | +|------|-------------| +| `feat` | New feature for the user | +| `fix` | Bug fix | +| `docs` | Documentation only changes | +| `style` | Formatting, missing semicolons, etc. (no code change) | +| `refactor` | Code change that neither fixes a bug nor adds a feature | +| `perf` | Performance improvement | +| `test` | Adding or updating tests | +| `build` | Changes to build system or dependencies | +| `ci` | CI configuration changes | +| `chore` | Other changes that don't modify src or test files | +| `revert` | Reverts a previous commit | + +**Quick Decision Tree**: +``` +Changes involve... +├─ New user-facing feature? → feat +├─ Fix user-reported bug? → fix +├─ Only docs/comments? → docs +├─ Internal refactor? → refactor +├─ Performance improvement? → perf +└─ Breaking API change? → Add ! + BREAKING CHANGE footer +``` + +### Step 3: Determine Scope (Optional) + +Scope should be a noun describing the section of codebase: +- `feat(gui)`: GUI-related feature +- `fix(memory)`: Memory-related fix +- `docs(api)`: API documentation +- `refactor(core)`: Core module refactoring + +### Step 4: Write Description + +- Use imperative mood: "add" not "added" or "adds" +- Don't capitalize first letter +- No period at the end +- Keep under 50 characters + +**Common mistakes**: +- ❌ `Added new feature` → ✅ `add new feature` +- ❌ `Fix bug.` → ✅ `fix authentication issue` +- ❌ Multiple concerns → Split into separate commits + +### Step 5: Add Body (If Needed) + +- Explain WHAT and WHY, not HOW +- Wrap at 72 characters +- Separate from description with blank line + +### Step 6: Add Footer (If Needed) + +**Breaking Changes**: +``` +BREAKING CHANGE: <description> +``` + +**AI-Generated Commits** (REQUIRED for AI assistance): +``` +Reviewed-by: [MODEL_NAME] +``` + +**Issue References**: +``` +Refs #123 +Closes #456 +``` + +## Examples + +### Simple Feature +``` +feat(gui): add transparent window support +``` + +### Bug Fix with Body +``` +fix(memory): resolve index memory leak + +The index was not being properly released when switching +between different memory contexts, causing gradual memory +growth over extended sessions. + +Reviewed-by: [MODEL_NAME] +``` + +### Breaking Change +``` +refactor(core)!: restructure plugin system + +Plugin API now requires explicit registration instead of +auto-discovery. This improves startup time but requires +migration of existing plugins. + +BREAKING CHANGE: Plugin API signature changed from +`register()` to `register(manifest: PluginManifest)` + +Reviewed-by: [MODEL_NAME] +``` + +### Documentation Update +``` +docs: update PRD with new interaction flow + +Reviewed-by: [MODEL_NAME] +``` + +### Multiple Changes (use most significant type) +``` +feat(state): add mood decay system with persistence + +- Implement time-based mood decay algorithm +- Add SQLite persistence for mood state +- Create mood recovery mechanics + +Reviewed-by: [MODEL_NAME] +Refs #42 +``` + +## Commands + +When user says "create commit" or "commit message": + +1. **[REQUIRED]** Check current branch and validate (Step 0) +2. Ask what changes to commit (or analyze staged changes) +3. Generate commit message in **English** (following Conventional Commits format) +4. **If commit language is not user's language**: Explain the commit in user's language +5. **Always ask for confirmation** before executing (unless user said "commit directly" or similar) +6. If confirmed, run: `git commit -m "<message>"` + +**Example 1 (Chinese user, English commit)**: +``` +User: "帮我提交这个功能" +AI: "建议的提交信息: + feat(gui): add transparent window support + + 这个提交添加了透明窗口功能。是否执行此提交?" +User: "是" or "直接提交" or "y" +AI: [executes git commit] +``` + +**Example 2 (English user, Chinese commit)**: +``` +User: "write a Chinese commit for this feature" +AI: "Suggested commit: + feat(gui): 添加透明窗口支持 + + This commit adds transparent window support. Proceed?" +User: "yes" or "commit directly" or "y" +AI: [executes git commit] +``` + +**Example 3 (English user, English commit - no explanation)**: +``` +User: "commit this feature" +AI: "Suggested commit: + feat(gui): add transparent window support + + Proceed with this commit?" +User: "yes" or "commit directly" or "y" +AI: [executes git commit] +``` + +When user says "amend commit": +```bash +git commit --amend -m "<new message>" +``` + +## References + +- Commit spec: <a>.github/references/git/conventional-commit.md</a> diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..6b577d4 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,289 @@ +# DropOut Minecraft Launcher - AI Development Guide + +## Architecture Overview + +**DropOut** is a Tauri v2 desktop application combining: +- **Backend (Rust)**: Game launching, asset management, authentication, mod loader installation +- **Frontend (Svelte 5)**: Reactive UI with Tailwind CSS 4 and particle effects +- **Communication**: Tauri commands (invoke) and events (emit/listen) +- **Pre-commit Hooks**: Python-based tooling for JSON/TOML validation (managed via `pyproject.toml`) + +**Key Data Flow**: Frontend invokes Rust commands → Rust processes/downloads → Rust emits progress events → Frontend updates UI via listeners + +**Version Management**: Uses `_version.py` for single source of truth, synced to `Cargo.toml` (0.1.24) and `tauri.conf.json` + +## Project Structure + +``` +src-tauri/ # Rust backend + src/ + main.rs # Tauri commands, game launch logic, event emissions + core/ # Core modules (auth, downloader, fabric, forge, java, etc.) + mod.rs # Module declarations + auth.rs # Microsoft OAuth + offline auth via Device Code Flow + downloader.rs # Concurrent downloads with progress tracking, resumable downloads + fabric.rs # Fabric loader installation and version management + forge.rs # Forge installer execution and profile generation + java.rs # Java detection, Adoptium download/install, catalog management + config.rs # LauncherConfig (memory, java path, download threads) + game_version.rs # Minecraft version JSON parsing + manifest.rs # Mojang version manifest fetching + maven.rs # Maven artifact URL resolution for mod loaders + rules.rs # OS/feature rule evaluation for libraries + version_merge.rs # Parent version inheritance merging + utils/ + zip.rs # Native library extraction +ui/ # Svelte 5 frontend + src/ + App.svelte # Main app component, enforces dark mode + stores/ # Svelte 5 runes state management ($state, $effect) + auth.svelte.ts # Authentication state with device code polling + game.svelte.ts # Game state (running, logs) + settings.svelte.ts # Settings + Java detection + ui.svelte.ts # UI state (toasts, modals, active view) + components/ # UI components (HomeView, VersionsView, SettingsView, etc.) + lib/ # Reusable components (DownloadMonitor, GameConsole) +``` + +## Critical Development Workflows + +### Development Mode +```bash +cargo tauri dev # Starts frontend dev server (Vite on :5173) + Tauri window +``` +- Frontend uses **Rolldown-based Vite fork** (`npm:rolldown-vite@7.2.5`) with hot reload +- Backend recompiles on Rust file changes +- Console shows both Rust stdout and frontend Vite logs +- **Vite Config**: Uses `usePolling: true` for watch compatibility with Tauri +- **HMR**: WebSocket on `ws://localhost:5173` + +### Pre-commit Checks +- Uses **pre-commit** with Python (configured in `pyproject.toml`) +- Hooks: JSON/TOML/YAML validation, Ruff for Python files +- Run manually: `pre-commit run --all-files` +- **IMPORTANT**: All Python tooling for CI/validation lives here, NOT for app logic + +### Building +```bash +cd ui && pnpm install # Install frontend dependencies (requires pnpm 9, Node 22) +cargo tauri build # Produces platform bundles in src-tauri/target/release/bundle/ +``` + +### Frontend Workflows +```bash +cd ui +pnpm check # Svelte type checking + TypeScript validation +pnpm lint # OxLint for code quality +pnpm format # OxFmt for formatting (--check for CI) +``` + +### Testing +- CI workflow: [`.github/workflows/test.yml`](.github/workflows/test.yml) tests on Ubuntu, Arch (Wayland), Windows, macOS +- Local: `cargo test` (no comprehensive test suite exists yet) +- **Test workflow behavior**: Push/PR = Linux build only, `workflow_dispatch` = full multi-platform builds + +## Project-Specific Patterns & Conventions + +### Tauri Command Pattern +Commands in [`main.rs`](../src-tauri/src/main.rs) follow this structure: +```rust +#[tauri::command] +async fn command_name( + window: Window, + state: State<'_, SomeState>, + param: Type, +) -> Result<ReturnType, String> { + emit_log!(window, "Status message"); // Emits "launcher-log" event + // ... async logic + Ok(result) +} +``` +**Register in `main()`:** +```rust +tauri::Builder::default() + .invoke_handler(tauri::generate_handler![command_name, ...]) +``` + +### Event Communication +**Rust → Frontend (Progress/Logs):** +```rust +// In Rust +window.emit("launcher-log", "Downloading assets...")?; +window.emit("download-progress", progress_struct)?; +``` +```typescript +// In Frontend (Svelte) +import { listen } from "@tauri-apps/api/event"; +const unlisten = await listen("launcher-log", (event) => { + console.log(event.payload); +}); +``` + +**Frontend → Rust (Commands):** +```typescript +import { invoke } from "@tauri-apps/api/core"; +const result = await invoke("start_game", { versionId: "1.20.4" }); +``` + +### State Management (Rust) +Global state via Tauri's managed state: +```rust +pub struct ConfigState { + pub config: Mutex<LauncherConfig>, + pub file_path: PathBuf, +} +// In main: +.manage(ConfigState::new(&app_handle)) +// In commands: +config_state: State<'_, ConfigState> +``` + +### State Management (Svelte 5) +Uses **Svelte 5 runes** (not stores): +```typescript +// stores/auth.svelte.ts +export class AuthState { + currentAccount = $state<Account | null>(null); // Reactive state + isLoginModalOpen = $state(false); + + $effect(() => { // Side effects + // Runs when dependencies change + }); +} +// Export singleton +export const authState = new AuthState(); +``` +**CRITICAL**: Stores are TypeScript classes with `$state` runes, not Svelte 4's `writable()`. Each store file exports a singleton instance. + +**Store Pattern**: +- File: `stores/*.svelte.ts` (note `.svelte.ts` extension) +- Class-based with reactive `$state` properties +- Methods for actions (async operations with `invoke()`) +- Derived values with `get` accessors +- Side effects with `$effect()` (auto-tracks dependencies) + +### Version Inheritance System +Modded versions (Fabric/Forge) use `inheritsFrom` field: +- [`version_merge.rs`](../src-tauri/src/core/version_merge.rs): Merges parent vanilla JSON with mod loader JSON +- [`manifest.rs`](../src-tauri/src/core/manifest.rs): `load_version()` recursively resolves inheritance +- Libraries, assets, arguments are merged from parent + modded version + +### Microsoft Authentication Flow +Uses **Device Code Flow** (no redirect needed): +1. Frontend calls `start_microsoft_login()` → gets device code + URL +2. User visits URL in browser, enters code +3. Frontend polls `complete_microsoft_login()` with device code +4. Rust exchanges code → MS token → Xbox Live → XSTS → Minecraft token +5. Stores MS refresh token for auto-refresh (see [`auth.rs`](../src-tauri/src/core/auth.rs)) + +**Client ID**: Uses ATLauncher's public client ID (`c36a9fb6-4f2a-41ff-90bd-ae7cc92031eb`) + +### Download System +[`downloader.rs`](../src-tauri/src/core/downloader.rs) features: +- **Concurrent downloads** with semaphore (configurable threads) +- **Resumable downloads**: `.part` + `.part.meta` files track progress +- **Multi-segment downloads**: Large files split into segments downloaded in parallel +- **Checksum verification**: SHA1/SHA256 validation +- **Progress events**: Emits `download-progress` with file name, bytes, ETA +- **Queue persistence**: Java downloads saved to `download_queue.json` for resumption + +### Java Management +[`java.rs`](../src-tauri/src/core/java.rs): +- **Auto-detection**: Scans `/usr/lib/jvm`, `/Library/Java`, `JAVA_HOME`, `PATH` +- **Adoptium API**: Fetches available JDK/JRE versions for current OS/arch +- **Catalog caching**: `java_catalog.json` cached for 24 hours +- **Installation**: Downloads, extracts to `app_data_dir/java/<version>` +- **Cancellation**: Global `AtomicBool` flag for download cancellation + +### Error Handling +- Commands return `Result<T, String>` (String for JS-friendly errors) +- Use `.map_err(|e| e.to_string())` to convert errors +- Emit detailed error logs: `emit_log!(window, format!("Error: {}", e))` + +### File Paths +- **Game directory**: `app_handle.path().app_data_dir()` (~/.local/share/com.dropout.launcher on Linux) +- **Versions**: `game_dir/versions/<version_id>/<version_id>.json` +- **Libraries**: `game_dir/libraries/<maven-path>` +- **Assets**: `game_dir/assets/objects/<hash[0..2]>/<hash>` +- **Config**: `game_dir/config.json` +- **Accounts**: `game_dir/accounts.json` + +## Integration Points + +### External APIs +- **Mojang**: `https://piston-meta.mojang.com/mc/game/version_manifest_v2.json` +- **Fabric Meta**: `https://meta.fabricmc.net/v2/` +- **Forge Maven**: `https://maven.minecraftforge.net/` +- **Adoptium**: `https://api.adoptium.net/v3/` +- **GitHub Releases**: `https://api.github.com/repos/HsiangNianian/DropOut/releases` + +### Native Dependencies +- **Linux**: `libwebkit2gtk-4.1-dev`, `libgtk-3-dev` (see [test.yml](../.github/workflows/test.yml)) +- **macOS**: System WebKit via Tauri +- **Windows**: WebView2 runtime (bundled) + +## Common Tasks + +### Adding a New Tauri Command +1. Define function in [`main.rs`](../src-tauri/src/main.rs) with `#[tauri::command]` +2. Add to `.invoke_handler(tauri::generate_handler![..., new_command])` +3. Call from frontend: `invoke("new_command", { args })` + +### Adding a New UI View +1. Create component in `ui/src/components/NewView.svelte` +2. Import in [`App.svelte`](../ui/src/App.svelte) +3. Add navigation in [`Sidebar.svelte`](../ui/src/components/Sidebar.svelte) +4. Update `uiState.activeView` in [`ui.svelte.ts`](../ui/src/stores/ui.svelte.ts) + +### Emitting Progress Events +Use `emit_log!` macro for launcher logs: +```rust +emit_log!(window, format!("Downloading {}", filename)); +``` +For custom events: +```rust +window.emit("custom-event", payload)?; +``` + +### Handling Placeholders in Arguments +Game arguments may contain `${variable}` placeholders. Use the `has_unresolved_placeholder()` helper to skip malformed arguments (see [`main.rs:57-67`](../src-tauri/src/main.rs#L57-L67)). + +## Important Notes + +- **Dark mode enforced**: [`App.svelte`](../ui/src/App.svelte) force-adds `dark` class regardless of system preference +- **Svelte 5 syntax**: Use `$state`, `$derived`, `$effect` (not `writable` stores) +- **No CREATE_NO_WINDOW on non-Windows**: Use `#[cfg(target_os = "windows")]` for Windows-specific code +- **Version IDs**: Fabric uses `fabric-loader-<loader>-<game>`, Forge uses `<game>-forge-<loader>` +- **Mod loader libraries**: Don't have `downloads.artifact`, use Maven resolution via [`maven.rs`](../src-tauri/src/core/maven.rs) +- **Native extraction**: Extract to `versions/<version>/natives/`, exclude META-INF +- **Classpath order**: Libraries → Client JAR (see [`main.rs:437-453`](../src-tauri/src/main.rs#L437-L453)) +- **Version management**: Single source in `_version.py`, synced to Cargo.toml and tauri.conf.json +- **Frontend dependencies**: Must use pnpm 9 + Node 22 (uses Rolldown-based Vite fork) +- **Store files**: Must have `.svelte.ts` extension, not `.ts` + +## Debugging Tips + +- **Rust logs**: Check terminal running `cargo tauri dev` +- **Frontend logs**: Browser devtools (Ctrl+Shift+I in Tauri window) +- **Game logs**: Listen to `game-stdout`/`game-stderr` events +- **Download issues**: Check `download-progress` events, validate SHA1 hashes +- **Auth issues**: MS WAF blocks requests without User-Agent (see [`auth.rs:6-12`](../src-tauri/src/core/auth.rs#L6-L12)) + +## Version Compatibility + +- **Rust**: Edition 2021, requires Tauri v2 dependencies +- **Node.js**: 22+ with pnpm 9+ for frontend (uses Rolldown-based Vite fork `npm:rolldown-vite@7.2.5`) +- **Tauri**: v2.9+ +- **Svelte**: v5.46+ (runes mode) +- **Java**: Supports detection of Java 8-23+, recommends Java 17+ for modern Minecraft +- **Python**: 3.10+ for pre-commit hooks (validation only, not app logic) + +## Commit Conventions + +Follow instructions in [`.github/instructions/commit.instructions.md`](.github/instructions/commit.instructions.md): +- **Format**: `<type>[scope]: <description>` (lowercase, imperative, no period) +- **AI commits**: MUST include `Reviewed-by: [MODEL_NAME]` +- **Common types**: `feat`, `fix`, `docs`, `refactor`, `perf`, `test`, `chore` +- **Language**: Commit messages ALWAYS in English +- **Confirmation**: ALWAYS ask before committing (unless "commit directly" requested) +- See [Conventional Commits spec](.github/references/git/conventional-commit.md) for details diff --git a/.github/instructions/commit.instructions.md b/.github/instructions/commit.instructions.md new file mode 100644 index 0000000..f01f080 --- /dev/null +++ b/.github/instructions/commit.instructions.md @@ -0,0 +1,38 @@ +--- +applyTo: "**" +--- + +# Commit Helper Instructions + +When user requests commit help → Follow <a>.github/agents/commit.agent.md</a> + +## Critical Rules + +1. **Language**: Commit message ALWAYS in **English** (unless user specifies otherwise) +2. **Explanation**: Use **user's request language** ONLY when commit language differs + - Chinese user + English commit → Explain in Chinese + - English user + Chinese commit → Explain in English + - Same language → No extra explanation needed +3. **Confirmation**: ALWAYS ask before committing (unless "commit directly" requested) + +## Quick Reference + +**Format**: `<type>[scope]: <description>` + +**Common types**: `feat` `fix` `docs` `refactor` `perf` `test` `chore` + +**AI commits MUST include**: `Reviewed-by: [MODEL_NAME]` + +**Spec**: <a>.github/references/git/conventional-commit.md</a> + +## Common Mistakes + +| Wrong | Right | +|-------|-------| +| `feat: Added feature` | `feat: add feature` (imperative) | +| `Fix bug.` | `fix: resolve auth issue` (lowercase, no period) | +| `feat: add A, refactor B, update C` | Split into 3 commits | + +## User Triggers + +"create commit", "commit message", "conventional commit" diff --git a/.github/references/git/conventional-commit.md b/.github/references/git/conventional-commit.md new file mode 100644 index 0000000..a9e27bc --- /dev/null +++ b/.github/references/git/conventional-commit.md @@ -0,0 +1,153 @@ +# What is Conventional Commits? + +> A standard for writing commit messages. + +## Table of Contents + +- [What is Conventional Commits?](#what-is-conventional-commits) +- [Examples](#examples) +- [Rules](#rules) +- [Why Should We Use It?](#why-should-we-use-it) +- [Changelog Generation](#changelog-generation) +- [Bump the Version Precisely](#bump-the-version-precisely) +- [How About Squash Merges?](#how-about-squash-merges) + +The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of. This convention dovetails with [SemVer](https://semver.org/), by describing the features, fixes, and breaking changes made in commit messages. + +```text +<type>[optional scope]: <description> + +[optional body] + +[optional footer(s)] +``` + +## Examples + +> Commit message with scope + +```text +feat(SHOPPER-000): introduce OrderMonitor v2 +``` + +> Commit message with breaking change + +```text +refactor!: drop support for Node 6 +``` + +> Commit message with footer and breaking change + +```text +feat: enhance error handling + +BREAKING CHANGE: Modified every error message and added the error key +``` + +> Commit message with multi-paragraph body and multiple footers + +```text +fix(SHOPPER-000): correct minor typos in code + +see the issue for details + +on typos fixed. + +Reviewed-by: Z +Refs #133 +``` + +> Here reviewer should be replaced with the actual name of the reviewer or the **model name card** like "GPT-4o mini" by default. + +## Rules + +The key words **“MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL”** in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). + +- Commits MUST be prefixed with a type, which consists of a noun, feat, fix, etc., followed by the OPTIONAL scope, OPTIONAL !, and REQUIRED terminal colon and space. +- The type feat MUST be used when a commit adds a new feature to your application or library. +- The type fix MUST be used when a commit represents a bug fix for your application. +- A scope MAY be provided after a type. A scope MUST consist of a noun describing a section of the codebase surrounded by parenthesis, e.g., fix(parser): +- A description MUST immediately follow the colon and space after the type/scope prefix. The description is a short summary of the code changes, e.g., fix: array parsing issue when multiple spaces were contained in string. +- A longer commit body MAY be provided after the short description, providing additional contextual information about the code changes. The body MUST begin one blank line after the description. +- A commit body is free-form and MAY consist of any number of newline separated paragraphs. +- One or more footers MAY be provided one blank line after the body. Each footer MUST consist of a word token, followed by either a :<space> or <space># separator, followed by a string value (this is inspired by the git trailer convention). +- A footer’s token MUST use - in place of whitespace characters, e.g., Acked-by (this helps differentiate the footer section from a multi-paragraph body). An exception is made for BREAKING CHANGE, which MAY also be used as a token. +- A footer’s value MAY contain spaces and newlines, and parsing MUST terminate when the next valid footer token/separator pair is observed. +- Breaking changes MUST be indicated in the type/scope prefix of a commit, or as an entry in the footer. +- If included as a footer, a breaking change MUST consist of the uppercase text BREAKING CHANGE, followed by a colon, space, and description, e.g., BREAKING CHANGE: environment variables now take precedence over config files. +If included in the type/scope prefix, breaking changes MUST be indicated by a ! immediately before the :. If ! is used, BREAKING CHANGE: MAY be omitted from the footer section, and the commit description SHALL be used to describe the breaking change. +- Types other than feat and fix MAY be used in your commit messages, e.g., docs: updated ref docs. +- The units of information that make up Conventional Commits MUST NOT be treated as case sensitive by implementors, with the exception of BREAKING CHANGE which MUST be uppercase. +- BREAKING-CHANGE MUST be synonymous with BREAKING CHANGE, when used as a token in a footer. + +## Why Should We Use It? + +- Automatic changelog generation +- The context information that refers to business initiative when it's needed +- Noticeable breaking changes +- Forces us to write better commit messages (no more vague 'fix', 'refactor' commits) +- Bumping version precisely +- Making it easier to contribute to the projects by allowing contributors to explore a more structured commit history + +## Changelog Generation + +### Why Changelog? + +A changelog is a file that contains a curated, chronologically ordered list of notable changes for each version of a project to make it easier for users and contributors. + +For more information, see the [Keep a Changelog](https://keepachangelog.com/) standard. + +### Why Generate Changelogs via Conventional Commits? + +It's hard to maintain changelogs by hand and most of the time it fails. Manual changelog updates lead to: + +- Discrepancy between docs and actual versions +- Missing breaking changes +- Outdated changelogs + +You can automate the process of generating changelogs via GitHub Actions or locally via git hooks, which speeds up the process significantly. + +## Bump the Version Precisely + +### Benefits of Bumping Version Through Conventional Commits + +- We shouldn't depend on one owner who knows every change between releases +- Every contributor should decide the impact of their changes during the development process +- You can auto-bump the version once it's merged to a specific branch (no more forgotten version updates) +- See [Conventional Commits Version Bump](https://github.com/marketplace/actions/conventional-commits-version-bump) GitHub Action +- Speeds up the process +- Prevents human mistakes + +**Major Version Bump** + +```text +refactor!: drop support for Node 6 +``` + +**Minor Version Bump** + +```text +feat(SHOPPER-000): introduce OrderMonitor v2 +``` + +**Patch Version Bump** + +```text +fix(SHOPPER-000): correct minor typos in code +``` + +## How About Squash Merges? + +Why do we need squash merges if we have good commit messages? + +### Pros + +- Every squash commit linked to PR +- Cleaner git history +- Easy roll-back + +### Cons + +- It changes commit history, which can cause conflicts +- It's hard to understand what actually changed +- Sometimes what you commit is not related to the purpose of the PR diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 58fc378..ba8ce54 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -13,6 +13,8 @@ on: jobs: check: + permissions: + contents: read runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -38,6 +40,6 @@ jobs: - run: pnpm lint working-directory: ui - - run: pnpm format --check + - run: pnpm format working-directory: ui diff --git a/.github/workflows/issue-checkbox-checker.yml b/.github/workflows/issue-checkbox-checker.yml new file mode 100644 index 0000000..ce7e011 --- /dev/null +++ b/.github/workflows/issue-checkbox-checker.yml @@ -0,0 +1,104 @@ +name: Issue Checkbox Checker + +on: + issues: + types: [opened, edited] + +permissions: + issues: write + +jobs: + check-checkboxes: + runs-on: ubuntu-latest + steps: + - name: Check for unchecked prerequisites + uses: actions/github-script@v7 + with: + script: | + const issue = context.payload.issue; + if (!issue) return; + + const body = issue.body || ''; + + // Check if "I have not read carefully" checkbox is checked + const notReadPatterns = [ + /- \[[xX]\] I have not read carefully/, + /- \[[xX]\] 我未仔细阅读/ + ]; + + const hasNotReadChecked = notReadPatterns.some(pattern => pattern.test(body)); + + if (hasNotReadChecked) { + const closeMessage = [ + '## Issue Automatically Closed / Issue 已自动关闭', + '', + '**English:**', + 'This issue has been automatically closed because you checked "I have not read carefully."', + '', + 'Please:', + '1. Read the [README](https://github.com/' + context.repo.owner + '/' + context.repo.repo + '/blob/main/README.md) and documentation carefully', + '2. Search for existing issues', + '3. Fill out the issue template completely', + '4. Submit a new issue when ready', + '', + '**中文:**', + '此 Issue 已被自动关闭,因为您勾选了"我未仔细阅读"。', + '', + '请:', + '1. 仔细阅读 [README](https://github.com/' + context.repo.owner + '/' + context.repo.repo + '/blob/main/README.md) 和文档', + '2. 搜索现有 Issue', + '3. 完整填写 Issue 模板', + '4. 准备好后提交新的 Issue', + '', + '---', + '*This is an automated action. If you believe this was done in error, please contact the maintainers.*' + ].join('\n'); + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + body: closeMessage + }); + + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + state: 'closed', + state_reason: 'not_planned' + }); + + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + labels: ['invalid', 'auto-closed'] + }); + + return; + } + + // Count total checkboxes and checked boxes + const totalBoxes = (body.match(/- \[[ xX]\]/g) || []).length; + const checkedBoxes = (body.match(/- \[[xX]\]/g) || []).length; + + // If no boxes are checked in prerequisites, add a reminder + if (totalBoxes > 0 && checkedBoxes === 0) { + const reminderMessage = [ + '## Reminder / 提醒', + '', + '**English:**', + 'Please check the prerequisite boxes in the issue template to confirm you have completed the required steps.', + '', + '**中文:**', + '请勾选 Issue 模板中的前置条件复选框,以确认您已完成必要步骤。' + ].join('\n'); + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + body: reminderMessage + }); + } diff --git a/.github/workflows/prek.yml b/.github/workflows/prek.yml new file mode 100644 index 0000000..8e43763 --- /dev/null +++ b/.github/workflows/prek.yml @@ -0,0 +1,60 @@ +name: Prek Checks + +on: + push: + branches: ["main", "dev"] + workflow_dispatch: + +permissions: + contents: write + +jobs: + prek: + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[skip ci]')" + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Install system dependencies + if: runner.os == 'Linux' + run: | + sudo apt-get update || true + sudo apt-get install -y \ + libwebkit2gtk-4.1-dev \ + build-essential \ + libssl-dev \ + libgtk-3-dev \ + libayatana-appindicator3-dev \ + librsvg2-dev \ + pkg-config + + - name: Run prek + id: prek + uses: j178/prek-action@v1 + continue-on-error: true + + - name: Check for changes + id: check_changes + if: steps.prek.outcome == 'failure' + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "has_changes=true" >> $GITHUB_OUTPUT + else + echo "has_changes=false" >> $GITHUB_OUTPUT + fi + + - name: Commit fixes + if: steps.prek.outcome == 'failure' && steps.check_changes.outputs.has_changes == 'true' + uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "chore: apply prek auto-fixes [skip ci]" + commit_user_name: "hydroroll-bot" + commit_user_email: "bot@hydroroll.team" + skip_dirty_check: true diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000..4005b2c --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,92 @@ +name: 'Close stale issues' + +on: + schedule: + - cron: '0 0 * * *' # Run daily at midnight UTC + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + # Issues + days-before-issue-stale: 90 + days-before-issue-close: 7 + stale-issue-label: 'stale' + exempt-issue-labels: 'pinned,enhancement,documentation' + stale-issue-message: | + ## This issue has been automatically marked as stale + ## 此 Issue 已被自动标记为过期 + + **English:** + This issue has had no activity for 90 days and will be closed in 7 days if no further activity occurs. + + If this issue is still relevant: + - Comment with an update + - Provide additional information + - Confirm you're still experiencing the problem + + **中文:** + 此 Issue 已 90 天无活动,如果继续无活动将在 7 天后关闭。 + + 如果此问题仍然相关: + - 发表评论更新状态 + - 提供额外信息 + - 确认您仍在遇到该问题 + + --- + *This is an automated message. To prevent closure, simply comment on this issue.* + close-issue-message: | + ## This issue has been automatically closed + ## 此 Issue 已被自动关闭 + + **English:** + This issue was automatically closed due to inactivity. If you're still experiencing this problem, please open a new issue with updated information. + + **中文:** + 此 Issue 因无活动而被自动关闭。如果您仍然遇到此问题,请开启一个新的 Issue 并提供最新信息。 + + # Pull Requests + days-before-pr-stale: 60 + days-before-pr-close: 14 + stale-pr-label: 'stale' + exempt-pr-labels: 'pinned,security' + stale-pr-message: | + ## This pull request has been automatically marked as stale + ## 此 PR 已被自动标记为过期 + + **English:** + This pull request has had no activity for 60 days and will be closed in 14 days if no further activity occurs. + + If you're still working on this: + - Push new commits + - Comment with a status update + - Request a review + + **中文:** + 此 PR 已 60 天无活动,如果继续无活动将在 14 天后关闭。 + + 如果您仍在处理此问题: + - 推送新的提交 + - 发表评论更新状态 + - 请求审查 + close-pr-message: | + ## This pull request has been automatically closed + ## 此 PR 已被自动关闭 + + **English:** + This pull request was automatically closed due to inactivity. Feel free to reopen if you resume work on this. + + **中文:** + 此 PR 因无活动而被自动关闭。如果您恢复工作,请随时重新开启。 + + # General settings + operations-per-run: 100 + remove-stale-when-updated: true + ascending: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8ca056e..8bf6d2f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,6 +10,9 @@ on: branches: ["main"] workflow_dispatch: +permissions: + contents: read + env: CARGO_TERM_COLOR: always @@ -42,8 +45,8 @@ jobs: - name: Install Dependencies (Ubuntu) if: runner.os == 'Linux' && !matrix.wayland run: | - sudo apt-get update - sudo apt-get install -y libwebkit2gtk-4.1-dev build-essential curl wget file libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev + sudo apt-get update || true + sudo apt-get install -y libwebkit2gtk-4.1-dev build-essential curl wget file libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev libfuse2 - name: Install Dependencies (Arch Linux) if: matrix.wayland @@ -62,6 +65,27 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable + - name: Install Node.js + if: github.event_name == 'workflow_dispatch' + uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Install pnpm + if: github.event_name == 'workflow_dispatch' + uses: pnpm/action-setup@v2 + with: + version: 9 + + - name: Install Frontend Dependencies + if: github.event_name == 'workflow_dispatch' + working-directory: ./ui + run: pnpm install + + - name: Install Tauri CLI + if: github.event_name == 'workflow_dispatch' + run: cargo install tauri-cli + - name: Rust Cache uses: swatinem/rust-cache@v2 with: @@ -71,6 +95,48 @@ jobs: working-directory: ./src-tauri run: cargo test --verbose - - name: Build (Dev) + - name: Build Rust Only (Push/PR) + if: github.event_name != 'workflow_dispatch' working-directory: ./src-tauri run: cargo build --verbose + + - name: Build App (Debug) + if: github.event_name == 'workflow_dispatch' + run: cargo tauri build --debug + + - name: Get Short SHA + if: github.event_name == 'workflow_dispatch' + id: slug + run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT + + - name: Upload Artifact (Linux) + if: runner.os == 'Linux' && github.event_name == 'workflow_dispatch' + uses: actions/upload-artifact@v4 + with: + name: dropout-linux-${{ matrix.wayland && 'arch' || 'ubuntu' }}-${{ steps.slug.outputs.sha8 }} + path: | + src-tauri/target/debug/bundle/appimage/*.AppImage + src-tauri/target/debug/bundle/deb/*.deb + src-tauri/target/debug/dropout + retention-days: 5 + + - name: Upload Artifact (Windows) + if: runner.os == 'Windows' && github.event_name == 'workflow_dispatch' + uses: actions/upload-artifact@v4 + with: + name: dropout-windows-${{ steps.slug.outputs.sha8 }} + path: | + src-tauri/target/debug/bundle/msi/*.msi + src-tauri/target/debug/bundle/nsis/*.exe + src-tauri/target/debug/dropout.exe + retention-days: 5 + + - name: Upload Artifact (macOS) + if: runner.os == 'macOS' && github.event_name == 'workflow_dispatch' + uses: actions/upload-artifact@v4 + with: + name: dropout-macos-${{ steps.slug.outputs.sha8 }} + path: | + src-tauri/target/debug/bundle/dmg/*.dmg + src-tauri/target/debug/bundle/macos/DropOut.app + retention-days: 5 |